WolfkillArcadia 758 Report post Posted June 5, 2016 (edited) Please note: This document is incomplete and can contain errors. We are expanding on it so please bear with us. Network messages are send and receive commands built into Exile. These commands allow Exile to transfer data across the network to either the server or client. These functions use remoteExec but they are more secure and harder to hack. Starting in Exile version 0.9.6, these commands were opened up for coders and server owners to use without overriding an Exile function only on the client side, meaning that the server can send a network message to the client but not the other way around. Until the functionality is added to the server side, a coder can add this functionality via an override. This wiki will cover both ways of how network messages work, from the client and server side, but the functionality is almost the same. CfgNetworkMessages This class is what controls how a network message is defined. The files ExileClient_system_network_dispatchIncomingMessage.sqf and a customExileServer_system_network_dispatchIncomingMessage.sqf will look in the mission config file (IE. config.cpp or description.ext) for the class CfgNetworkMessages and will check the module and parameters against what is being sent. But fist, let's look at what an example network message class looks like. For these examples, we will be using a default Exile network message. // Declare the class, the message name is purchaseVehicleRequest class purchaseVehicleRequest { // Declare the module, this is part of the file name module = "system_trading"; // Declare the parameters, these are the typeNames of the fields in the package parameters[] = {"STRING","STRING"}; }; class purchaseVehicleResponse { module = "system_trading"; parameters[] = {"SCALAR","STRING","STRING"}; }; It's a bit of information so let's dissect the message purchaseVehicleRequest. class purchaseVehicleRequest {}; The declaration of the function. This name will be the ending part of the function name. This name must match the requesting function name or an error be be logged to the RPT and the message will be disregarded. A good practice with naming classes to end the class with the word "Request" if this message is expecting a "Response" back. In this case, it's good to name the responding network message to end with "Response". module = "system_trading"; The "category" of the function. This is a good way of organizing code, allowing for easier flow. This module is used as part of the function call. parameters[] = {"STRING","STRING"}; The typeNames of our data we are passing through the command. These MUST match the data being passed or an error will be logged to the RPT and the message will be disregarded. "STRING" is not the only typeName that can be used, below are examples of others: "SCALAR" // 1337 "BOOL" // true/false "ARRAY" // [1,2,3,4,5] For a list of every Network Message used by Exile, check the spoiler. Spoiler class CfgNetworkMessages { /////////////////////////////////////////////////////////////////////////// // Start session /////////////////////////////////////////////////////////////////////////// class startSessionRequest { module = "system_session"; parameters[] = { "STRING" // Net ID of player object }; }; class startSessionResponse { module = "system_session"; parameters[] = { "STRING" // Session ID }; }; /////////////////////////////////////////////////////////////////////////// // Update session /////////////////////////////////////////////////////////////////////////// class updateSessionRequest { module = "system_session"; parameters[] = { "STRING" // Net ID of player object }; }; /////////////////////////////////////////////////////////////////////////// // Switch Move /////////////////////////////////////////////////////////////////////////// class switchMoveRequest { module = "object_player"; parameters[] = { "STRING", // Player Net ID "STRING" // Move }; }; /////////////////////////////////////////////////////////////////////////// // Update stats /////////////////////////////////////////////////////////////////////////// class updateStatsRequest { module = "object_player"; parameters[] = { "STRING", // Money "STRING", // Score "SCALAR", // Kills "SCALAR" // Deaths }; }; /////////////////////////////////////////////////////////////////////////// // Show frag /////////////////////////////////////////////////////////////////////////// class showFragRequest { module = "gui"; parameters[] = { "ARRAY" }; }; /////////////////////////////////////////////////////////////////////////// // Has player /////////////////////////////////////////////////////////////////////////// class hasPlayerRequest { module = "object_player"; parameters[] = {}; }; class hasPlayerResponse { module = "object_player"; parameters[] = { "BOOL" }; }; /////////////////////////////////////////////////////////////////////////// // Create player /////////////////////////////////////////////////////////////////////////// class createPlayerRequest { module = "object_player"; parameters[] = { "STRING" // Marker name of spawn location }; }; class createPlayerResponse { module = "object_player"; parameters[] = { "OBJECT", // player object "STRING", // parachute "STRING", // Money "STRING", // Score "SCALAR", // Kills "SCALAR", // Deaths "SCALAR", // Hunger "SCALAR", // Thirst "SCALAR", // Alcohol "SCALAR", // Protection Duration "STRING", // Clan Name "SCALAR" // Spawn Type }; }; /////////////////////////////////////////////////////////////////////////// // Load player /////////////////////////////////////////////////////////////////////////// class loadPlayerRequest { module = "object_player"; parameters[] = {}; }; class loadPlayerResponse { module = "object_player"; parameters[] = { "STRING", // Net ID of player object "STRING", // Money "STRING", // Score "SCALAR", // Kills "SCALAR", // Deaths "SCALAR", // Hunger "SCALAR", // Thirst "SCALAR", // Alcohol "STRING", // Clan Name "SCALAR", // Temperature "SCALAR" // Wetness }; }; /////////////////////////////////////////////////////////////////////////// // updatePlayerIncapacitatedRequest /////////////////////////////////////////////////////////////////////////// class updatePlayerIncapacitatedRequest { module = "object_player"; parameters[] = { "BOOL" // Yes/No }; }; /////////////////////////////////////////////////////////////////////////// // Save player /////////////////////////////////////////////////////////////////////////// class savePlayerRequest { module = "object_player"; parameters[] = { "SCALAR", // Hunger "SCALAR", // Thirst "SCALAR", // Alcohol "SCALAR", // Temperature "SCALAR" // Wetness }; }; /////////////////////////////////////////////////////////////////////////// // Set player money /////////////////////////////////////////////////////////////////////////// class setPlayerMoneyRequest { module = "object_player"; parameters[] = { "SCLAR" // $$$ }; }; /////////////////////////////////////////////////////////////////////////// // Chop tree /////////////////////////////////////////////////////////////////////////// class chopTreeRequest { module = "object_tree"; parameters[] = { "STRING" // Net ID of tree object }; }; // No response required /////////////////////////////////////////////////////////////////////////// // Chop bush /////////////////////////////////////////////////////////////////////////// class chopBushRequest { module = "object_bush"; parameters[] = { "STRING" // Net ID of tree object }; }; // No response required /////////////////////////////////////////////////////////////////////////// // System chat /////////////////////////////////////////////////////////////////////////// class systemChatRequest { module = "gui"; parameters[] = { "STRING" // message }; }; // No response required /////////////////////////////////////////////////////////////////////////// // Advanced hint /////////////////////////////////////////////////////////////////////////// class advancedHintRequest { module = "gui"; parameters[] = { "STRING" // hint name }; }; /////////////////////////////////////////////////////////////////////////// // Standard hint /////////////////////////////////////////////////////////////////////////// class standardHintRequest { module = "gui"; parameters[] = { "STRING" // hint name }; }; /////////////////////////////////////////////////////////////////////////// // Notification Request! /////////////////////////////////////////////////////////////////////////// class notificationRequest { module = "gui_notification"; parameters[] = { "STRING", // NAME "ARRAY" // Params }; }; /////////////////////////////////////////////////////////////////////////// // Dynamic text /////////////////////////////////////////////////////////////////////////// class dynamicTextRequest { module = "gui"; parameters[] = { "STRING", "SCALAR", "SCALAR", "STRING" }; }; /////////////////////////////////////////////////////////////////////////// // FailLoad -- Server plz delete my character /////////////////////////////////////////////////////////////////////////// class resetPlayerRequest { module = "object_player"; parameters[] = {}; }; /////////////////////////////////////////////////////////////////////////// // buildConstructionRequest /////////////////////////////////////////////////////////////////////////// class buildConstructionRequest { module = "object_construction"; parameters[] = { "STRING", // What object "ARRAY" // Object Position }; }; /////////////////////////////////////////////////////////////////////////// // Pay Territory Protection Money Request /////////////////////////////////////////////////////////////////////////// class payTerritoryProtectionMoneyRequest { module = "system_territory"; parameters[] = { "STRING", // Net-ID of flag object "SCALAR" // Mode (Pop Tabs / Respect) }; }; /////////////////////////////////////////////////////////////////////////// // Pay Territory Protection Money Response /////////////////////////////////////////////////////////////////////////// class payTerritoryProtectionMoneyResponse { module = "system_territory"; parameters[] = { "STRING", // New Pop Tab Amount "STRING" // New Respect Amount }; }; /////////////////////////////////////////////////////////////////////////// // buildTerritoryRequest /////////////////////////////////////////////////////////////////////////// class buildTerritoryRequest { module = "object_construction"; parameters[] = { "STRING", // What object "ARRAY", // Object Position "STRING", // Flag name "STRING" // Teritory Name }; }; /////////////////////////////////////////////////////////////////////////// // constructionResponse /////////////////////////////////////////////////////////////////////////// class constructionResponse { module = "object_construction"; parameters[] = { "STRING" // New object Net ID }; }; /////////////////////////////////////////////////////////////////////////// // swapConstructionRequest /////////////////////////////////////////////////////////////////////////// class swapConstructionRequest { module = "object_construction"; parameters[] = { "STRING", // NetID of an object "STRING", // New Class name of an object "ARRAY" // Object info }; }; /////////////////////////////////////////////////////////////////////////// // deconstructConstructionRequest /////////////////////////////////////////////////////////////////////////// class deconstructConstructionRequest { module = "object_construction"; parameters[] = { "STRING" // NetID to delete }; }; /////////////////////////////////////////////////////////////////////////// // moveConstructionRequest /////////////////////////////////////////////////////////////////////////// class moveConstructionRequest { module = "object_construction"; parameters[] = { "STRING" }; }; /////////////////////////////////////////////////////////////////////////// // constructionMoveResponse /////////////////////////////////////////////////////////////////////////// class constructionMoveResponse { module = "object_construction"; parameters[] = { "BOOL", "STRING" }; }; /////////////////////////////////////////////////////////////////////////// // upgradeConstructionRequest /////////////////////////////////////////////////////////////////////////// class upgradeConstructionRequest { module = "object_construction"; parameters[] = { "OBJECT" // Upgrade Object }; }; /////////////////////////////////////////////////////////////////////////// // upgradeConstructionResponse /////////////////////////////////////////////////////////////////////////// class upgradeConstructionResponse { module = "object_construction"; parameters[] = { "OBJECT" }; }; /////////////////////////////////////////////////////////////////////////// // flipVehRequest /////////////////////////////////////////////////////////////////////////// class flipVehRequest { module = "object_vehicle"; parameters[] = { "STRING" // NetID to Flip }; }; /////////////////////////////////////////////////////////////////////////// // pushVehicleRequest /////////////////////////////////////////////////////////////////////////// class pushVehicleRequest { module = "object_vehicle"; parameters[] = { "STRING", // NetID to Push "SCALAR", // Direction "SCALAR", // Magnitude "STRING" // Caller }; }; /////////////////////////////////////////////////////////////////////////// // rotateVehicleRequest /////////////////////////////////////////////////////////////////////////// class rotateVehicleRequest { module = "object_vehicle"; parameters[] = { "STRING", // Vehicle Net ID "SCALAR" // Rotation }; }; ////////////////////////////////////////////////////////////////////////// // lockVehicleRequest /////////////////////////////////////////////////////////////////////////// class lockVehicleRequest { module = "object_vehicle"; parameters[] = { "STRING", // Vehicle Net ID "BOOL" // MODE }; }; ////////////////////////////////////////////////////////////////////////// // lockResponse /////////////////////////////////////////////////////////////////////////// class lockResponse { module = "object_vehicle"; parameters[] = { "STRING", // Message "BOOL", // Mode "STRING", // Vehicle Net ID "STRING", // Pincode "SCALAR" // Is locked now LOCK_UNKNOWN etc. }; }; /////////////////////////////////////////////////////////////////////////// // Spawn Loot Request /////////////////////////////////////////////////////////////////////////// class spawnLootRequest { module = "system_lootManager"; parameters[] = { "ARRAY" // Array of building Net IDs }; }; /////////////////////////////////////////////////////////////////////////// // Toggle Flood Lights /////////////////////////////////////////////////////////////////////////// class toggleFloodLightRequest { module = "object_floodLight"; parameters[] = { "STRING", // NetID of flood light "SCALAR" // damage of light bulb hit point }; }; /////////////////////////////////////////////////////////////////////////// // connectionTest /////////////////////////////////////////////////////////////////////////// class connectionTest { module = "object_player"; parameters[] = { "BOOL" }; }; /////////////////////////////////////////////////////////////////////////// // Purchase Vehicle /////////////////////////////////////////////////////////////////////////// class purchaseVehicleRequest { module = "system_trading"; parameters[] = { "STRING", // Vehicle class name "STRING" // PIN }; }; class purchaseVehicleResponse { module = "system_trading"; parameters[] = { "SCALAR", // Response Code, see preprocessor "STRING", // NetID of new vehicle "STRING" // New $$$ of player }; }; /////////////////////////////////////////////////////////////////////////// // Vehicle Save Request /////////////////////////////////////////////////////////////////////////// class vehicleSaveRequest { module = "system_vehicleSaveQueue"; parameters[] = { "STRING" // NetID of an object }; }; /////////////////////////////////////////////////////////////////////////// // Purchase Vehicle Skin /////////////////////////////////////////////////////////////////////////// class purchaseVehicleSkinRequest { module = "system_trading"; parameters[] = { "STRING", // NetID of original vehicle "ARRAY" // new skin name }; }; class purchaseVehicleSkinResponse { module = "system_trading"; parameters[] = { "SCALAR", // Response Code, see preprocessor "STRING" // New $$$ of player }; }; /////////////////////////////////////////////////////////////////////////// // End Bambi State Request /////////////////////////////////////////////////////////////////////////// class endBambiStateRequest { module = "object_player"; parameters[] = {}; }; /////////////////////////////////////////////////////////////////////////// // Purchase Item /////////////////////////////////////////////////////////////////////////// class purchaseItemRequest { module = "system_trading"; parameters[] = { "STRING", // Item Class Name "SCALAR", // Quantity "SCALAR", // Container type "STRING" // NetID of vehicle if container type is "vehicle" }; }; class purchaseItemResponse { module = "system_trading"; parameters[] = { "SCALAR", // Response Code, see preprocessor "STRING", // New $$$ of player "STRING", // Item Class Name "SCALAR", // Quantity "SCALAR", // Container type "STRING" // NetID of vehicle if container type is "vehicle" }; }; /////////////////////////////////////////////////////////////////////////// // Sell Item /////////////////////////////////////////////////////////////////////////// class sellItemRequest { module = "system_trading"; parameters[] = { "STRING", // Item Class Name "SCALAR", // Quantity "SCALAR", // Container type "STRING" // NetID of vehicle if container type is "vehicle" }; }; class sellItemResponse { module = "system_trading"; parameters[] = { "SCALAR", // Response Code, see preprocessor "STRING", // New $$$ of player "STRING", // Item Class Name "SCALAR", // Quantity "SCALAR", // Container type "STRING", // NetID of vehicle if container type is "vehicle" "STRING" // Current respect }; }; /////////////////////////////////////////////////////////////////////////// // Lock Toggle /////////////////////////////////////////////////////////////////////////// class hotwireLockRequest { module = "object_lock"; parameters[] = { "STRING" // Object Net-ID }; }; class lockToggle { module = "object_lock"; parameters[] = { "STRING", // Object netID "STRING", // pincode "BOOL" // state }; }; class setPin { module = "object_lock"; parameters[] = { "STRING", // Object netID "STRING", // pincode "STRING" // newPincode }; }; class setPinResponse { module = "object_lock"; parameters[] = { "ARRAY", "STRING", "STRING" }; }; class packRequest { module = "object_container"; parameters[] = { "STRING", // Object netID "STRING" // pincode }; }; class setFuelRequest { module = "object_vehicle"; parameters[] = { "STRING", // Veh ID "SCALAR" // Fuel }; }; /////////////////////////////////////////////////////////////////////////// // Register Clan /////////////////////////////////////////////////////////////////////////// class registerClanRequest { module = "system_clan"; parameters[] = { "STRING" // Clan Name }; }; class registerClanResponse { module = "system_clan"; parameters[] = { "SCALAR", // Response Code "STRING", // Clan Name "STRING" // Current Pop Tabs }; }; /////////////////////////////////////////////////////////////////////////// // Invite to Party /////////////////////////////////////////////////////////////////////////// class inviteToPartyRequest { module = "system_party"; parameters[] = { "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Join a party /////////////////////////////////////////////////////////////////////////// class joinPartyRequest { module = "system_party"; parameters[] = { "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Kick From Party /////////////////////////////////////////////////////////////////////////// class kickFromPartyRequest { module = "system_party"; parameters[] = { "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Announce Territory Request /////////////////////////////////////////////////////////////////////////// class announceTerritoryRequest { module = "system_territory"; parameters[] = { "STRING" // Territory Flag Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Add to Territory Request /////////////////////////////////////////////////////////////////////////// class addToTerritoryRequest { module = "system_territory"; parameters[] = { "STRING", // Territory Flag Net ID "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Remove from Territory Request /////////////////////////////////////////////////////////////////////////// class removeFromTerritoryRequest { module = "system_territory"; parameters[] = { "STRING", // Territory Flag Net ID "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // ModerationRequest Territory /////////////////////////////////////////////////////////////////////////// class moderationTerritoryRequest { module = "system_territory"; parameters[] = { "STRING", // Territory Flag Net ID "STRING", // Player Net ID "BOOL" // Mode }; }; /////////////////////////////////////////////////////////////////////////// // Send Money Request /////////////////////////////////////////////////////////////////////////// class sendMoneyRequest { module = "system_trading"; parameters[] = { "STRING", // Pop Tab Amount "STRING" // Player Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Money Sent Request /////////////////////////////////////////////////////////////////////////// class moneySentRequest { module = "system_trading"; parameters[] = { "STRING", // Our new pop tab amount "STRING" // Name of the guy who received the money }; }; /////////////////////////////////////////////////////////////////////////// // Money Received Request /////////////////////////////////////////////////////////////////////////// class moneyReceivedRequest { module = "system_trading"; parameters[] = { "STRING", // Our new pop tab amount "STRING" // Name of they guy who sent the money }; }; /////////////////////////////////////////////////////////////////////////// // Purchase Territory /////////////////////////////////////////////////////////////////////////// class purchaseTerritory { module = "system_territory"; parameters[] = {}; }; /////////////////////////////////////////////////////////////////////////// // Purchase Territory Response /////////////////////////////////////////////////////////////////////////// class purchaseTerritoryResponse { module = "system_territory"; parameters[] = { "SCALAR" // Resonse CODE }; }; /////////////////////////////////////////////////////////////////////////// // Dialog Open Dialog /////////////////////////////////////////////////////////////////////////// class requestTerritoryUpgradeDialog { module = "system_territory"; parameters[] = { "OBJECT" ///FLAG OBJECT }; }; /////////////////////////////////////////////////////////////////////////// // addLockRequest /////////////////////////////////////////////////////////////////////////// class addLockRequest { module = "object_construction"; parameters[] = { "OBJECT", /// Door object "STRING" /// PinCode }; }; /////////////////////////////////////////////////////////////////////////// // addLockResponse /////////////////////////////////////////////////////////////////////////// class addLockResponse { module = "object_construction"; parameters[] = { "STRING" //PINCODE }; }; /////////////////////////////////////////////////////////////////////////// // Dialog Open Dialog response << dont ask /////////////////////////////////////////////////////////////////////////// class territoryUpgradeDialogResponse { module = "gui_upgradeTerritoryDialog"; parameters[] = { "SCALAR" /// territory level }; }; /////////////////////////////////////////////////////////////////////////// // territoryUpgradeRequest /////////////////////////////////////////////////////////////////////////// class territoryUpgradeRequest { module = "system_territory"; parameters[] = { "OBJECT" ///FLAG OBJECT }; }; class territoryUpgradeResponse { module = "system_territory"; parameters[] = { "STRING", // Net-ID of flag object "SCALAR", // New level of territory "SCALAR", // New radius of territory "STRING" // New respect of player }; }; /////////////////////////////////////////////////////////////////////////// // deleteGroupPlz /////////////////////////////////////////////////////////////////////////// class deleteGroupPlz { module = "system"; parameters[] = { "GROUP" // group to delete }; }; /////////////////////////////////////////////////////////////////////////// // Waste Dump /////////////////////////////////////////////////////////////////////////// class wasteDumpRequest { module = "system_trading"; parameters[] = { "STRING", // Net ID of Vehicle "SCALAR" // Mode }; }; class wasteDumpResponse { module = "system_trading"; parameters[] = { "SCALAR", // Response Code "STRING", // Current Pop Tabs "STRING" // Current Respect }; }; /////////////////////////////////////////////////////////////////////////// // Take All /////////////////////////////////////////////////////////////////////////// class beginTakeAllRequest { module = "object_player"; parameters[] = { "STRING" // Net ID of container }; }; class beginTakeAllResponse { module = "object_player"; parameters[] = { "STRING" // Net ID of container }; }; class endTakeAllRequest { module = "object_player"; parameters[] = { "STRING" // Net ID of container }; }; /////////////////////////////////////////////////////////////////////////// // Scan Code Lock /////////////////////////////////////////////////////////////////////////// class scanCodeLockRequest { module = "object_lock"; parameters[] = { "STRING" // Net ID of Vehicle }; }; class scanCodeLockResponse { module = "object_lock"; parameters[] = { "STRING" // Response Code }; }; /////////////////////////////////////////////////////////////////////////// // Enable simulation /////////////////////////////////////////////////////////////////////////// class enableSimulationRequest { module = "system_simulationMonitor"; parameters[] = { "STRING" // Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Box mounting /////////////////////////////////////////////////////////////////////////// class attachSupplyBoxRequest { module = "object_supplyBox"; parameters[] = { "STRING" // Net ID }; }; class detachSupplyBoxRequest { module = "object_supplyBox"; parameters[] = { "STRING" // Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Supply Box installing /////////////////////////////////////////////////////////////////////////// class installSupplyBoxRequest { module = "object_supplyBox"; parameters[] = { "STRING" // Net ID }; }; /////////////////////////////////////////////////////////////////////////// // Bondage! /////////////////////////////////////////////////////////////////////////// class handcuffRequest // Client -> Server and Server -> Victim { module = "object_handcuffs"; parameters[] = { "STRING" // Net ID of victim/hostage taker }; }; class handcuffResponse // Server tells player that he has handcuffed someone { module = "object_handcuffs"; parameters[] = { "STRING" // Respect }; }; class freeRequest // Client wants to free another player { module = "object_handcuffs"; parameters[] = { "STRING" // Net ID }; }; class freeResponse // Client -> Server and Server -> Victim { module = "object_handcuffs"; parameters[] = { "STRING" // Respect }; }; class breakFreeRequest // Client -> Server { module = "object_handcuffs"; parameters[] = {}; }; class breakFreeResponse // Server -> Client { module = "object_handcuffs"; parameters[] = { "STRING" // Respect }; }; /////////////////////////////////////////////////////////////////////////// // Party Marker Things /////////////////////////////////////////////////////////////////////////// class updateMyPartyMarkerRequest // Client -> Server { module = "system_party"; parameters[] = { "BOOL", "ARRAY" // Position }; }; class updatePartyMarkerRequest // Server -> Client { module = "system_party"; parameters[] = { "STRING", // Net ID of player "BOOL", // Update/Remove "ARRAY" // Position }; }; /////////////////////////////////////////////////////////////////////////// // Reset Vehicle Lock /////////////////////////////////////////////////////////////////////////// class resetCodeRequest { module = "object_vehicle"; parameters[] = { "STRING", // Object netID "STRING", // pincode "STRING" // newPincode }; }; class resetCodeResponse { module = "object_vehicle"; parameters[] = { "ARRAY", "STRING", "STRING" }; }; /////////////////////////////////////////////////////////////////////////// // Re-Key Vehicle /////////////////////////////////////////////////////////////////////////// class rekeyVehicleRequest { module = "object_vehicle"; parameters[] = { "STRING", // Object netID "STRING" // newPincode }; }; class rekeyVehicleDialogRequest { module = "object_vehicle"; parameters[] = { "STRING", // Object netID "SCALAR" // Rekey Cost }; }; class rekeyVehicleDialogResponse { module = "gui_vehicleRekeyDialog"; parameters[] = { "STRING", // Response Code "STRING", // Vehicle ID "SCALAR" // Player Money }; }; class resetCodeDialogRequest { module = "object_vehicle"; parameters[] = { "STRING" // Object netID }; }; class resetCodeDialogResponse { module = "gui_vehicleRekeyDialog"; parameters[] = { "STRING", // Response Code "STRING" // Vehicle ID }; }; }; How these are used in ExileServer_system_network_dispatchIncomingMessage / ExileClient_system_network_dispatchIncomingMessage will be explained below. SENDING FROM CLIENT TO SERVER These examples will be using the network messages defined above. Let's say a player went to the trader and purchased a vehicle. Traders are handled on the client but in order for a vehicle to be saved to the database, the server needs to process it, but how do we let the server know that a client ran a client side script to purchase a vehicle? We send a network message. Below is an example of the purchaseVehicleRequest network message used above. // Taken from ExileClient_gui_vehicleTraderDialog_event_onPurchaseButtonClick.sqf [ "purchaseVehicleRequest", // This is the class that is defined in CfgNetworkMessages // Package START [ _vehicleClass, // This is the classname of the vehicle purchased _pin // This is the pin set by the player when purchased ] // Package END ] call ExileClient_system_network_send; // Exile function to call to send a message to the server. // Same above command just in one line ["purchaseVehicleRequest", [_vehicleClass,_pin]] call ExileClient_system_network_send; NOTE: The example will be using a variables named _vehicleClass and _pin. These variables will change based on what vehicle class is chosen and what pin is entered. For ease of understanding, this topic will use the variable names instead of what the data could be. Both of these are passed as STRINGS. ExileClient_system_network_send.sqf ExileClient_system_network_send will take this information, attach the player's sessionID, which is unique to the player's client, and remoteExec to the server. ExileServer_system_network_dispatchIncomingMessage will receive this message on the server side. ExileServer_system_network_dispatchIncomingMessage.sqf ExileServer_system_network_dispatchIncomingMessage will take in this package and perform multiple error checks and security checks to make sure the data is correct. Checks include: Payload is defined. IE, [_sessionID, "purchaseVehicleRequest", [_vehicleClass,_pin]] _sessionID is the player's sessionID that was attached in ExileClient_system_network_send. Payload is an array. Payload includes exactly three fields. Keep in mind that _sessionID was attached, so the payload is now three fields long. Requesting sessionID matches and exists Message name matches the class defined in CfgNetworkMessages. IE, "purchaseVehicleRequest" Requested package parameters count matches the one defined in CfgNetworkMessages. IE, [_vehicleClass,_pin] The count of this array is 2, and the count of parameters for this message is 2 typeName's of the package matches CfgNetworkMessages. IE. [_vehicleClass,_pin] The type names of the information being passed is ["STRING","STRING"] Once it's checked all of those, dispatchIncomingMessage will try to compile a function call using this information. This is where the class name and module comes in to play. In raw terms, this is what it's doing. ExileServer_<ModuleName>_network_<FunctionName> Using the purchaseVehicleRequest, the final function call will be ExileServer_system_trading_network_purchaseVehicleRequest dispatchIncomingMessage will then call the function with the following parameters: [_sessionID,[_vehicleClass,_pin]] This concludes how a message is sent from the client to the server, next is the other way around. SENDING FROM SERVER TO CLIENT Since ExileServer_system_trading_network_purchaseVehicleRequest was called, let's examine what the file is doing with the data. ExileServer_system_trading_network_purchaseVehicleRequest _sessionID = _this select 0; _parameters = _this select 1; _vehicleClass = _parameters select 0; _pinCode = _parameters select 1; This is how to extract the data sent via a network message. On the server side, the player's sessionID will ALWAYS be the first part of the payload (_this select 0) and the "package" will be the second (_this select 1). From the "package" the data sent can be extracted, in this case [_vehicleClass,_pin]. The "package" will always be an array. The way this data is sent to this file looks like this: [_sessionID,[_vehicleClass, _pinCode]]. All messages sent to the server will follow this design, so the way the data extracted is exactly the same across the board. This topic won't go into detail how this file works, but in the end it will be sending back the following: [ _sessionID, // SessionID of the requesting player "purchaseVehicleResponse", // Name of the class defined in CfgNetworkMessages // Package START [ 0, netId _vehicleObject, str _playerMoney ] // Package END ] call ExileServer_system_network_send_to; Since the command is getting ran on the server, ExileServer_system_network_send_to needs a destination to send the data to. This is why the command has the _sessionID attached to it. _sessionID is the SessionID that was tied to the player that sent the initial request. The rest of this command is the same as on the client, "purchaseVehicleResponse" is the destination, and the package containing the information sending back to the client. ExileServer_system_network_send_to This file processing the request just like the client side, but instead of attaching the sessionID to the message, it strips it from it. ExileClient_system_network_dispatchIncomingMessage Back to the client side, ExileClient_system_network_dispatchIncomingMessage receives the message. It preforms the similar checks like the server side one does. Once the checks are done, compiles the function call and sends our package to it. The final package sent to the file, which in the example isExileClient_system_trading_network_purchaseVehicleResponse, will be [0,netId _vehicleObject,str _playerMoney]. ExileClient_system_trading_network_purchaseVehicleResponse This is the final file that will receive the information. As stated above, the package is [0,netId _vehicleObject,str _playerMoney] so the file only has a few variables to extract from the data. _responseCode = _this select 0; _vehicleNetID = _this select 1; _newPlayerMoneyString = _this select 2; That's it! Editor Notes: You can send a network message to any client from the server so long as the server has their player object or the players sessionID. Exile sends all of the money amounts across the network as strings. When that string reaches it's destination, it's converted back to a number using the command parseNumber Edited June 5, 2016 by WolfkillArcadia 14 Share this post Link to post Share on other sites
wernerz 11 Report post Posted June 5, 2016 Thanks Wolf. This is fragging AWESOME. Share this post Link to post Share on other sites
happydayz 490 Report post Posted June 5, 2016 Also to note: Say you want to send a command to a client, but the request didnt originate from that client? How do you get that players SessionID??? Use this: _sessionID = _player getVariable ["ExileSessionID",""]; 2 Share this post Link to post Share on other sites
Mezo 1264 Report post Posted July 8, 2016 Note: You can also send network messages to the client player object instead of their session ID. 1 Share this post Link to post Share on other sites
Apoc 102 Report post Posted July 13, 2016 Say I want to create a new network message type: Do I just add a line in the description.ext to add to the base class as defined in the client mod's config.cpp? class CfgNetworkMessages { include "mynewchildclasses.hpp" }; Sorry for the lack of formatting, my mobile client does not handle this site well. Share this post Link to post Share on other sites
WolfkillArcadia 758 Report post Posted July 13, 2016 Exile will read CfgNetworkMessages defined in the missionConfigFile (description.ext) first before the ones from the client mod config, but these aren't technically extended off of the base class. In a sense you are defining this class in another scope. Since Exile is looking in the missionConfigFile first, you can overwrite default Exile NetworkMessages. I probably should update this document now that Exile 1.0 is out.... 2 Share this post Link to post Share on other sites
ynpMOOSE 122 Report post Posted July 28, 2016 This was highly educational. I just re-wrote a couple of small scripts that now have a much simpler implementation. Looking forward to the v1.0 update. Thanks! Moose Share this post Link to post Share on other sites
StokesMagee 871 Report post Posted August 8, 2016 don't forget about "OBJECT" Share this post Link to post Share on other sites
Mezo 1264 Report post Posted August 8, 2016 9 minutes ago, StokesMagee said: don't forget about "OBJECT" On 08/07/2016 at 1:18 AM, Taylor Swift said: Note: You can also send network messages to the client player object instead of their session ID. Share this post Link to post Share on other sites
StokesMagee 871 Report post Posted August 8, 2016 7 minutes ago, Taylor Swift said: "STRING" is not the only typeName that can be used, below are examples of others: "SCALAR" // 1337 "BOOL" // true/false "ARRAY" // [1,2,3,4,5] Share this post Link to post Share on other sites