Adaptive Cards in deferrals

Originally published at: https://cookbook.fivem.net/2019/06/29/adaptive-cards-in-deferrals/

We’ll be writing some more documentation on this soon, but the latest server version (combined with the canary client at this time – no prod yet!) supports presenting Adaptive Cards to clients during deferrals. Here’s a quick code sample: AddEventHandler(‘playerConnecting’, function(name, skr, d) d.defer() Wait(50) – badly serialized JSON in a string, from the Adaptive…

17 Likes

Have some docs already?

I’ve been playing with this but experienced a lot of intermittent end of file errors yet my JSON files were valid to the examples provided by the Microsoft side that was in the post.

The “badly serialized” json needs to be explained more so documents would be grand right now as valid JSON causes a lot of errors.

When will it be in prod?

2 Likes

Currently is but documention is thin.

Possible in JavaScript?

Edit :

const card  = '{"type":"AdaptiveCard","body":[{"type":"TextBlock","size":"ExtraLarge","weight":"Bolder","text":"Server password?!"},{"type":"TextBlock","text":"That\'s right, motherfucker! You have to enter a goddamn PASSWORD to connect to this server...","wrap":true},{"type":"Input.Text","id":"password","title":"","placeholder":"better enter one now"},{"type":"Image","url":"http://images.amcnetworks.com/ifccenter.com/wp-content/uploads/2019/04/pulpfic_1280.jpg","altText":""},{"type":"ActionSet","actions":[{"type":"Action.Submit","title":"Sure..."},{"type":"Action.ShowCard","title":"YOU WISH!!!!!!","card":{"type":"AdaptiveCard","body":[{"type":"Image","url":"https://i.imgur.com/YjMR0E6.jpg","altText":""}],"$schema":"http://adaptivecards.io/schemas/adaptive-card.json"}}]}],"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","version":"1.0"}';
const card2 = '{"type":"AdaptiveCard","body":[{"type":"Container","items":[{"type":"TextBlock","size":"Medium","weight":"Bolder","text":"Publish Adaptive Card schema"},{"type":"ColumnSet","columns":[{"type":"Column","items":[{"type":"Image","style":"Person","url":"https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg","size":"Small"}],"width":"auto"},{"type":"Column","items":[{"type":"TextBlock","weight":"Bolder","text":"Matt Hidinger","wrap":true},{"type":"TextBlock","spacing":"None","text":"Created {{DATE(2017-02-14T06:08:39Z,SHORT)}}","isSubtle":true,"wrap":true}],"width":"stretch"}]}]},{"type":"Container","items":[{"type":"TextBlock","text":"Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation.","wrap":true},{"type":"FactSet","facts":[{"title":"Board:","value":"Adaptive Card"},{"title":"List:","value":"Backlog"},{"title":"Assigned to:","value":"Matt Hidinger"},{"title":"Due date:","value":"Not set"}]}]}],"actions":[{"type":"Action.ShowCard","title":"Set due date","card":{"type":"AdaptiveCard","body":[{"type":"Input.Date","id":"dueDate"},{"type":"Input.Text","id":"comment","placeholder":"Add a comment","isMultiline":true}],"actions":[{"type":"Action.Submit","title":"OK","url":"http://adaptivecards.io"}],"$schema":"http://adaptivecards.io/schemas/adaptive-card.json"}},{"type":"Action.Submit","title":"View","url":"http://adaptivecards.io"}],"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","version":"1.0"}';

AddEventHandler('playerConnecting', function (playerName, setKickReason, deferrals) {

    deferrals.defer();
    setTimeout(function () {
        deferrals.presentCard(card, function (data, rawData) {
            deferrals.presentCard(card2, function (_, rawData2) {
                deferrals.done('you suck actually for entering the password: ' + data.password + ' and data like ' + rawData2);
            });
        });
    }, 50);

});

still in canary or switched to prod?

I was playing with it in .NET but honestly its not much different as its only the method and content. I had weird EoF errors when sending the JSON file over the net which couldn’t be repeated constantly to see if the error was the sending of the data.

Maybe if its listed as a client file it works better but I didn’t want to try that.

In prod

2 Likes

Is there a way to remove the gray border around the card?

2 Likes

I think you need to use the convar set on the background image for that to work as intended. I am not 100% sure though, however I think I saw someone who had it like that.

(And no image on the actual card itself)

Hello, does anyone know what’s the latest supported version of Adaptive Cards in Fivem deferrals?

1.0 if I’m not mistaken.

1 Like

I was able to successfully make this screen :slight_smile:

Love this system

The only thing I don’t like are that markdown doesn’t work (in the Adaptive Cards designer it works) and that transparency doesn’t work on action icons, but it’s easily fixable by just adding a background of the same color of the buttons to these icons.

Could you share your code my guy?
Just a skeleton version?

Sorry, can’t share my own code; it took me a lot to do it and it’s almost 1000 lines of C#, but I’ll give you a few tips.

  • Use this tool to design adaptive cards.
  • Copy and paste your cards into .json files inside your resource folder
  • Use LoadResourceFile() to load the json content
  • Use deferrals.presentCard(jsonContent, callback) to present the card
  • In the callback, you can chain more cards by just calling deferrals.presentCard again; make sure to await Delay() (C#) or Citizen.Wait() (Lua) before calling another card otherwise the whole server will crash.
8 Likes

how do i start it what do i put in my cfg

You don’t put anything in your config.

This is a feature of coding a resource for a server, used within playerConnecting event listener.
https://docs.fivem.net/docs/scripting-reference/events/list/playerConnecting/#presentcardcard-object--string-cb-data-object-rawdata-string--void-void

2 Likes

how did you even get it to work in c#. Im running a basic card and its not even showing that to me.

 var json = "{\"actionsOrientation\":\"horizontal\",\"verticalContentAlignment\":\"Center\",\"type\":\"AdaptiveCard\",\"backgroundImage\":{\"horizontalAlignment\":\"Center\",\"url\":\"\",\"verticalAlignment\":\"Center\"},\"version\":\"1.3\",\"actions\":[{\"type\":\"Action.Submit\",\"title\":\"Absenden\"}],\"$schema\":\"http://adaptivecards.io/schemas/adaptive-card.json\",\"body\":[{\"type\":\"Image\",\"url\":\"\"},{\"spacing\":\"Medium\",\"height\":\"stretch\",\"type\":\"ActionSet\",\"actions\":[{\"title\":\"Zum Regelwerk\",\"type\":\"Action.OpenUrl\",\"url\":\"https://egopvp.com/regelnfivem\"}]},{\"type\":\"Container\",\"items\":[{\"type\":\"ActionSet\",\"actions\":[{\"title\":\"Discord\",\"type\":\"Action.OpenUrl\",\"url\":\"https://egopvp.com/discord\"},{\"title\":\"TS\",\"type\":\"Action.OpenUrl\",\"url\":\"https://egopvp.com/discord\"},{\"title\":\"SaltyChat Tutorial\",\"type\":\"Action.OpenUrl\",\"url\":\"https://egopvp.com/egovoice\"}]}]},{\"spacing\":\"Large\",\"items\":[{\"spacing\":\"Large\",\"label\":\" \",\"type\":\"Input.Text\",\"errorMessage\":\"Du musst \"**Akzeptiere**\" Schreiben!\",\"isRequired\":true,\"placeholder\":\"Schreibe \"Akzeptiere\"\",\"id\":\"password\",\"regex\":\"Du musst \"**Akzeptiere**\" Schreiben!\"}],\"type\":\"Container\"}]}";
            deferrals.presentCard(json, new Action<dynamic, string>((data, rawData) =>
            {

            }));
1 Like

Make sure you are waiting some time between calls
await Delay(1)