engima 328 Posted March 27, 2013 (edited) ASCOM Framework 1.0by Engima of Östgöta Ops(Download at Armaholic) Description The Arma Script Communication (ASCOM) Framework is a framework that greatly simplifies SQF script communication between machines in a multiplayer mission. The ASCOM framework makes it possible to “call a function on another machine†in the same way that you call a function on the local machine. You can also return values to the caller in a usual manner, even when the caller is on another machine. These calls can be made in a script on any machine on the network. It is efficient, robust and does not require much bandwidth or CPU. Within the ASCOM framework, these functions are called “Network Functionsâ€. A network function is actually just like any other function. The ASCOM framework (which comes with an editor) then generates code that handles communication between machines on the network, which enables you to execute your functions on machines of your choice at each call. Examples Assume you have a function named "ShowMessage" that shows a message on its client. With the ASCOM Framework you can run that function on all clients with the following call: [“Mission completed!â€] call ShowMessageClients; As an another example, assume you have an MP mission, and when a JIP player connects its client needs to get the current tasks and their status from the server. In the init.sqf for the client you can make the following call to execute the function GetCurrentTaskStates on the server and have it return the task states across the network: _taskStateList = call GetCurrentTaskStatesServer; As a third example, assume that you want the server to set state "SUCCEEDED" on the task "FreeHostage" on all machines: ["FreeHostage", "SUCCEEDED"] call SetTaskStateAll; Installation No installation. Simply execute the file "ASCOM Editor.exe". Other Works for Arma 2 and Arma 3. Media This video shows an older version of the editor. One function name has been changed, but principles are the same. Content Package contains: The ASCOM Editor (.NET 4.0 executable). The ASCOM Manual (.PDF) Demo mission for Arma 3. Demo mission for Arma 2. Requirements .NET framework 4.0. Edited March 29, 2013 by Engima Share this post Link to post Share on other sites
Guest Posted March 27, 2013 Thank you very much for sending us the release :cool: Release frontpaged on the Armaholic homepage. ASCOM Framework [ALPHA] v1.00.NET Framework 4 Share this post Link to post Share on other sites
Axek/Axyl 2 Posted March 27, 2013 (edited) So it's essentially a code template wizard that makes client to client/server/combination easier? Interesting idea. Edited March 29, 2013 by Axek Share this post Link to post Share on other sites
engima 328 Posted March 28, 2013 (edited) That's essentially correct. But it supports more combinations than that: client/server to client/clients/server/all/some. The idea is to hide the complicated code for the networking, and provide a super simple programming interface. Edited March 28, 2013 by Engima Share this post Link to post Share on other sites
zuff 10 Posted March 28, 2013 This is exactly the tool I was looking for! Thank you so much for developing this and saving me a ton of headaches! Share this post Link to post Share on other sites
engima 328 Posted March 29, 2013 This is exactly the tool I was looking for!Thank you so much for developing this and saving me a ton of headaches! Glad you like it! Good luck! Share this post Link to post Share on other sites
Kettlewell 1 Posted March 29, 2013 Got used to this, it's unbelievably good and useful so thank you, I'll be using this on ever mission with saving myself hours of headaches. Share this post Link to post Share on other sites
zuff 10 Posted April 7, 2013 Quick question, I'm trying to make a task for a JIP player and I'm having problems getting ASCOM to call that player only. init.sqf: if (!isServer) then { if (isNull player) then { [] spawn { waitUntil {!(isNull player)}; [player, missionType, taskNum] call fnc_CreateNewTaskClient; }; }; }; The function, CreatNewTask, using FHQ Tasktracker to create a task using info from the variables "missionType" and "taskNum" I'm getting an error, though, on the "player" part. I'm trying to only call this code for the JIP. Any clue on what I can do to solve this? Share this post Link to post Share on other sites
clydefrog 3 Posted April 7, 2013 (edited) Quick question, I'm trying to make a task for a JIP player and I'm having problems getting ASCOM to call that player only.init.sqf: if (!isServer) then { if (isNull player) then { [] spawn { waitUntil {!(isNull player)}; [player, missionType, taskNum] call fnc_CreateNewTaskClient; }; }; }; The function, CreatNewTask, using FHQ Tasktracker to create a task using info from the variables "missionType" and "taskNum" I'm getting an error, though, on the "player" part. I'm trying to only call this code for the JIP. Any clue on what I can do to solve this? I know this isn't really helpful but I'd just wait until the people who make FHQ Task Tracker fix it themselves and release an updated version. Edited April 7, 2013 by clydefrog Share this post Link to post Share on other sites
engima 328 Posted April 7, 2013 (edited) Quick question, I'm trying to make a task for a JIP player and I'm having problems getting ASCOM to call that player only.init.sqf: if (!isServer) then { if (isNull player) then { [] spawn { waitUntil {!(isNull player)}; [player, missionType, taskNum] call fnc_CreateNewTaskClient; }; }; }; The function, CreatNewTask, using FHQ Tasktracker to create a task using info from the variables "missionType" and "taskNum" I'm getting an error, though, on the "player" part. I'm trying to only call this code for the JIP. Any clue on what I can do to solve this? Use the players vehicleVarName instead of the user object: [vehicleVarName player, missionType, taskNum] call fnc_CreateNewTaskClient; This call will execute the function fnc_CreateNewTask on the machine that the player is local to. In your case that seems to be the current machine, which makes me wonder why you don't call fnc_CreateNewTask directly instead? Another idea is to have the client ask server for the tasks on initialization. That's how I do it in the demo mission. Edited April 7, 2013 by Engima Share this post Link to post Share on other sites
zuff 10 Posted April 7, 2013 (edited) Use the players vehicleVarName instead of the user object: [vehicleVarName player, missionType, taskNum] call fnc_CreateNewTaskClient; This call will execute the function fnc_CreateNewTask on the machine that the player is local to. In your case that seems to be the current machine, which makes me wonder why you don't call fnc_CreateNewTask directly instead? Another idea is to have the client ask server for the tasks on initialization. That's how I do it in the demo mission. I tried the [vehicleVarName player, missionType, taskNum] call lampCreateNewTaskClient; and it didn't work. I didn't get any errors, though i'm sure there were serverside, and it was probably because the variable "missionType and taskNum were nil. Well here's how my mission is setup: From init.sqf I call a missionControl.sqf missionControl.sqf picks a random marker, task type (kill, rescue, steal, etc), and task objective (car, helicopter, infantry, hostage, etc) then makes an array called "missionType" with [marker, objective type, and task object] and the current task number (which I use to check to end the mission after so many tasks are completed) which is then pulled into a create task function: missionControl.sqf: markList = ["agia","airfield","airstation","campmax","camptemp","girna","kamino","killfarm","lzconnor"]; //Available Markers to choose from taskList = ["Assault", "Rescue", "Destroy", "Steal","Kill"]; //Available Task Types to choose from taskAssaultObjList = ["Infantry", "Infantry and Vehicles"]; //Available Assault Objects etc... (more objlist would be here for each taskType) tasksToComplete = 15; // How many tasks the mission will run till end if (isNil "taskNum") then { taskNum = 0; }; while {taskNum <= tasksToComplete} do { [b]missionType = [markList, taskList, taskAssaultObjList, taskRescueObjList, taskDestroyObjList, taskStealObjList, taskKillObjList] call lampCreateMissionTypeServer;[/b] taskNum = (taskNum + 1); [b][missionType, taskNum] call lampCreateNewTaskServer;[/b] [missionType] call lampCreateUnitsServer; // This creates the units based on the missionType variable, sets them to group "vehGroup" _prevTask = missionType select 1; if (_prevTask == "Assault") then { if (!isNil "vehGroup") then { waitUntil {{alive _x} count units vehGroup == 0}; }; if (!isNil "newGroup") then { waitUntil {{alive _x} count units newGroup == 0}; }; missionSuccess = true; }; waitUntil {!isNil "missionSuccess"}; [taskNum, missionType, missionSuccess] call lampCompleteTaskServer; if (taskNum >= tasksToComplete) then { call lampEndMissionAll; }; }; And here is my functions script for the CreateTask: // Executed on the server lampCreateNewTask = { private ["_missionType", "_taskNum"]; _missionType = _this select 0; _taskNum = _this select 1; // Code goes here! private ["_markerNum", "_taskType", "_taskObject"]; _markerNum = _missionType select 0; _taskType = _missionType select 1; _taskObject = _missionType select 2; [ [ format ["%1%2", _taskType, _taskNum], //task name format ["Mission %1, %2 %3", _taskNum, _taskType, _taskObject], //task long desc e.g. "Mission 2, Assault Infantry" format ["%1 %2", _taskType, _taskObject], //task short desc format ["%1 %2", _taskType, _taskObject], //Marker Text getMarkerPos _markerNum, //task waypoint "assigned" //task state ] ] call FHQ_TT_addTasks; }; This works as intended, but not for JIP. I looked through your demo mission but all of the objectives/tasks were already planned out, so checks are able to be run to see if they are completed or not, for my mission its a bit more complex since the tasks are randomized. I need a way to pull the variable missionType and markerNum into the init.sqf and have it available to create the same task JIP that's currently assigned to the already playing players. I tried the [vehicleVarName player, missionType, taskNum] call lampCreateNewTaskClient; and it didn't work. I didn't get any errors, though i'm sure t, but it was probably because the variable "missionType and taskNum were nil. Sorry if I'm overwhelming you with my messy code, but I'm not sure how to go about this. Thanks for your help. Edited April 7, 2013 by zuff Share this post Link to post Share on other sites
engima 328 Posted April 9, 2013 I cannot se the call to lampCreateNewTaskClient anywhere in your code. Anyway, by the comment "Executed on the server" right above your lampCreateTask function my guess is that you have simply not selected the option in the editor that tells the framework to generate the necessary code for executing a function on a given client. Can it be so? Also, if you simply want to "set a variable value" on clients or the server, you better use the publicVariable command. Then the current variable value is set from start on JIPs. Share this post Link to post Share on other sites
sickboy 13 Posted April 9, 2013 (edited) Interesting. The package seems to be very well prepared; documentation (manual and inline), and an application to assist the user. Few remarks so far: Cool to have the possibility of a return value. I haven't looked close enough to the locking system, but at least in my experience waitUntil { (drn_GetTimeAndWeatherResponseValue select 1) == _callID }; _response = drn_GetTimeAndWeatherResponseValue select 2; or similar situations could lead to data being out of date depending on load / scheduling. better use: _val = []; waitUntil { _val = drn_GetTimeAndWeatherResponseValue; _val select 1 == _callId }; _response = _val select 2; You're using multiple publicvariables. Basically 1 or more per command. For JIP players this means that you sync the last value of each of these publicvariables to every JIP player, this is probably not intended, you could combine them to a single PVEH. An option to execute code where target object is local could be useful Why use spawns in the PVEH code, instead of handle directly / call? spawns only add to script load and lag and should have no execution order guarantee What about synchronization of tasks to JIP players, for the sample mission? Edited April 9, 2013 by Sickboy Share this post Link to post Share on other sites
zuff 10 Posted April 9, 2013 I cannot se the call to lampCreateNewTaskClient anywhere in your code.Anyway, by the comment "Executed on the server" right above your lampCreateTask function my guess is that you have simply not selected the option in the editor that tells the framework to generate the necessary code for executing a function on a given client. Can it be so? Also, if you simply want to "set a variable value" on clients or the server, you better use the publicVariable command. Then the current variable value is set from start on JIPs. That's because I removed it after it didn't work. FHQ Tasktracker is suppose to run on the server and it broadcast to all players. I'm not entirely sure how it works but from what I understand is that it sends out the task to all playable units. In the current state I have it now, everyone is receiving task even though it's ran on the server. It's just JIP that lose the task. I'll see what I can do about the public variable, I've had bad luck with them in the past. Say I publicvariable something on the server, will a JIP client get that value? Share this post Link to post Share on other sites
engima 328 Posted April 10, 2013 Yes, a JIP client will have the last publicVariabled value from start. Just make sure that you don't reset it in the init.sqf. Be careful to use only values that can be publicVariabled: http://community.bistudio.com/wiki/publicVariable ---------- Post added at 13:33 ---------- Previous post was at 12:50 ---------- Thanks for your feedback, Sickboy! I'll look into your suggestions! Since it seems to work quite good right now I wanted to release it, but there are of course optimizations and things to improve. You're using multiple publicvariables. Basically 1 or more per command. For JIP players this means that you sync the last value of each of these publicvariables to every JIP player, this is probably not intended, you could combine them to a single PVEH. Actually it is intended, and I'm aware of the cost to synchronize these values for JIP players. I have tried to spread the load on the PVEHs. Maybe I underestimate the Arma script engine here, I don't know, but at the same time I would guess that the initial synchronization of variables when JIP connects is quite superable. An option to execute code where target object is local could be useful This is actually how the function that executes on a given client works. You can use the vehicle variable name for any object, it must not be a player unit object. Why use spawns in the PVEH code, instead of handle directly / call? spawns only add to script load and lag and should have no execution order guarantee I've had problems with waitUntil command in PVEHs, and I think that's why I did like this. This was a long time ago, so I will look into it again. What about synchronization of tasks to JIP players, for the sample mission? What do you mean? Is it not working? Share this post Link to post Share on other sites