• Content count

  • Joined

  • Last visited

  • Medals

Community Reputation

13 Good


About Muzzleflash


  • Interests
    Little of everything
  1. Jigsor, as fn_Quiksilver says, I would overwrite the entry in the JIP queue, in my examples the JIP-string ensures that there is at most one entry in the JIP-queue. So even if gameplay has lasted many hours, and the remote execution was done multiple times for the participants, any joining player would only get a single call from the JIP-queue to that function. Yes, pierremgi, that is my understanding. All of the init*.sqf scripts run after the JIP queue has been processed, and even then they are scheduled. The only accessible code that runs before is object initialization lines, and preInit functions (and "regular" functions being defined) from CfgFunctions. So, it seems there is no way to ensure function loading before processing of isPersistent calls without using CfgFunctions. Perhaps the least intrusive way to do it, would be to define a single preInit function in CfgFunction that gets run early and ensures everything is loaded. Maybe I will make a wrapper around publicVariable with similar API, which basically performs the publicVariable/waitUntil method discussed here, but also includes the concept of a JIP-queue, which I find useful. Alright, thank for your answers and participation guys.
  2. Yes I only want to do the latter, and not the former to avoid "red chains" and general waste of bandwidth. But my main worry is that from the Initialization Order it appears that initPlayerLocal.sqf is run after the persistant call is made.
  3. Suppose the game is running. On some machine, does not have to be the server, I use remoteExecCall to synchronize something among all current machines, let's say by using "MyFunction". I also use the JIP/isPersistent flags to ensure all future machines that JIP also gets synchronized. Now, machine X JIPs afterwards. X begins executing the initialization order you linked, which means running scripts, etc, and "Persistent functions are called" (the JIP queue), which I believe refers to the function calls made using the JIP/isPersistent flags to remoteExecCall. At some point X will process the earlier call to "MyFunction" (before X joined), but that means X must have "MyFunction" ready to be executed (already loaded). I am guessing if I put it in CfgFunction it will be ready. And everything will work fine. But if I don't put it in CfgFunctions I need some other way to ensure "MyFunction" is loaded on X before the game process the function call.
  4. Yes you can do it like that, and then guard it on the JIP client, with: waitUntil {!isNil "frequency"}; before you use 'frequency' . And what works fine for such simple synchronization, but gets more complicated in more complex synchronization scenarios. But that means avoiding the new commands which can handle both simple and complex synchronization scenarios in one line. I am not asking for a workaround, I know how to do it 'old school'. I want to use the new commands. I am asking is there a way to ensure a function is defined before the game handles the isPersistent calls from remoteExec and remoteExecCall. It seems the init*.sqf scripts cannot guarantee that because they run in a scheduled environment.
  5. Thanks. Can you give me a link or tell where those remarks are? I actually just found this which says they are ordered when using remoteExecCall (actually it is a bit ambiguous on what exactly is sequentially run - could be only the local runs) It doesn't have to be 0. The point is not the particular values. I mean the point is not to duplicate code in both initPlayerLocal.sqf and the original call to remoteExec , when the very functionality is available and builtin. But regardless, say I do the call in initPlayerLocal.sqf, I still need the client that I am remoteExec on to have the function defined. I am asking is there a way to do that without using CfgFunctions?
  6. When the JIP-player joins the client will eventually run init.sqf and the server will eventually run initPlayerServer.sqf. Even if there execution was ordered somehow among the machines, both are still scheduled which means either may be interrupted. So if somewhere during the run of init.sqf on the client "MyFunction" is defined, and somewhere during the run of initPlayerServer.sqf, the server calls remoteExec with no JIP, I don't see how I am guaranteed that the client finishes init.sqf before the server begins remoteExec of "MyFunction"? And, even then I still have to duplicate all my call to remoteExec in initPlayerServer.sqf? Here is an example: During game play the server does something like this: ["Yankee", 432.21] remoteExecCall ["MF_ConfigureRadio", 0, "RadioSettings"]; My intention is that then a client JIPs, the code should run automatically for the JIP. That however, requires that MF_ConfigureRadio is defined when Arma decides to run the JIP-calls to remoteExec and remoteExecCall.
  7. Thanks for the answer. That code runs on the server in a scheduled environment, and only checks that the function is defined locally on the server: so you still need some way to ensure "MyFunction" is defined on the client (for _player) before you run it? And manually doing this seems to defeat the whole purpose of JIP IDs for remoteExec(Call), no?
  8. I have two questions about remote execution using remoteExec and remoteExecCall. 1. Are the invocations ordered with respect to the same sender. For example, if the server performs remoteExecCall A followed by remoteExecCall B, will A run on receivers before B? 2. When are the JIP invocations performed, and are those also ordered - if so - then how? If I define custom function "MyFunction" and during the game do [myArg1, ...] remoteExecCall ["MyFunction", 0, "MyJipId"]; at what point will "MyFunction" have to be defined (unless of course RE waits for the function to be defined which I doubt)? How can I ensure that it is defined when the remote execution framework runs the JIP calls. Do I have any choice other than putting it in CfgFunctions? Thanks
  9. I'm wondering if others have noticed this issue. When people control Ravens, there are bright (especially at night in NVG) spheres on the ground at the locations circled by the Ravens. Everyone, except the operator of a given Raven, can see the spheres. This is a bright telltale that someone is operating a Raven in the air above. I found this old post where it seems the spheres were introduced as invisible object for optimisation. But it seems they are only invisible to the operators.
  10. I've created a JSON parser for reading JSON files into sqf. Example of loading json file and into script: mydata.json { "name": "John Doe", "age": 34, "active": true, "qualifications": ["rifleman","grenadier"], "position": { "rank": "Private", "squad": "Bravo" } } your script, e.g. (init.sqf) //Load library [] call compile preProcessFile "json.sqf"; //Be sure to run in non-scheduled mode, otherwise the engine will halt parsing before completion. [] spawn { //Load data from json file _rawJson = loadFile "mydata.json"; _json = _rawJson call MF_Json_Parse; //Extract data from JSON structure _qualifications = [_json, "qualifications"] call MF_Json_Get; _rank = [_json, "position.rank"]; waitUntil {!isNull player}; //Update player attributes player setVariable ["MY_TAG_Qualifications", _qualifications, true]; player setRank (toUpper _rank); }; Performance is about 250 lines per second. It can handle files up to 10,000 lines, however, they will take extremely long to parse, and it is not intended for such huge amount of data. (It is still SQF). More information is available in the top of the script listed below. The script itself: /*** JSON Parser by Muzzleflash v0.987 --- To parse json _json = "JSON_STRING" call MF_Json_Parse _json now contains the JSON structure in SQF as described below. If some error occurs during parsing _json would be set to a string instead, so you to check for errors you should check whether the return is of type string. --- To ease use, MF_Json_Get can be used to read keys separated by period (.) It currently does not handle indexing into arrays --- Example Usage: FILE: mydata.json: { "name": "John Doe", "age": 34, "active": true, "qualifications": ["rifleman","grenadier"], "position": { "rank": "Private", "squad": "Bravo" } } Script: //Load library [] call compile preProcessFile "json.sqf"; _json = (loadFile "mydata.json") call MF_Json_Parse; //Find rank _rank = [_json, "position.rank"] call MF_Json_Get; --- How JSON data is mapped to SQF JSON objects map to: ["object", [[key_1, val_1], [key_2, val_2] ...]] JSON arrays map to: ["array", [val_1, val_2, val_3, ...]] JSON null maps to objNull The other JSON types maps to what you would expect, eg.: false, true, 123.456, "and strings" The above example would map to: ["object", [ ["name", "John Doe"], ["age", 34], ["active", true], ["qualifications", ["array", ["rifleman", "grenadier"]]], ["position", ["object", [ ["rank", "Private"], ["squad", "Bravo"] ]] ] ]] --- The only unsupported feature is \uXXXX inside strings. --- Performance notes Scheduled environment. (Do not parse in non-scheduled environment since the parsing is aborted halway by the engine) The second number in parantheses is the amount of time spent on lexing out of the total time taken. 254 lines (8577 chars) takes 0.81 (0.78) seconds 1010 lines (34693 chars) takes 3.29 (3.06) seconds 10082 lines (349246 chars) takes 34.19 (31.94) seconds On my budget non-server machine with 500 AI all engaged in battle simultaneous, the time to parse doubled. So expected performance is around 5000-10000 characters or 150-300 lines per second. ***/ //------ Getters MF_Json_Get = { private ["_node","_pathParts","_path","_node","_index"]; _node = _this select 0; _pathParts = (_this select 1) call MF_Json_PathParts; //For each part of the path { _part = _x; //Only objects have keys if (_node select 0 != "object") exitWith { _node = objNull; }; //Find index of key _index = -1; { if (_x select 0 == _part) exitWith { _index = _forEachIndex; }; } forEach (_node select 1); if (_index == -1) exitWith { _node = objNull; }; //Select child with the key matching the part _node = ((_node select 1) select _index) select 1; } forEach _pathParts; //Did client mean to extract array? if (typeName _node == typeName [] and {_node select 0 == "array"}) then { _node = _node select 1; }; _node }; MF_Json_PathParts = { private ["_path","_parts","_dot","_start"]; _path = toArray _this; _parts = []; _dot = toArray "." select 0; _start = 0; for "_i" from 0 to (count _path - 1) do { if (_path select _i == _dot) then { _parts set [count _parts, [_path, _start, _i - 1] call MF_Json_Lex_Extract]; _start = _i + 1; }; }; //Extract last part _parts set [count _parts, [_path, _start, count _path - 1] call MF_Json_Lex_Extract]; _parts }; //------ Parser MF_Json_Parse = { private ["_tokens","_parseState","_result"]; _tokens = _this call MF_Json_Lex; //Error? if (typeName _tokens == typeName "string") exitWith {_tokens}; _parseState = [_tokens, 0, ""]; _result = _parseState call MF_Json_Parse_Top; if (_parseState select 2 != "") exitWith {_parseState select 2}; _result }; MF_Json_SetError = { private ["_parseState", "_formatArgs"]; _parseState = _this select 0; _formatArgs = []; for "_i" from 1 to (count _this - 1) do { _formatArgs set [_i - 1, _this select _i]; }; _parseState set [2, format _formatArgs]; }; #define PARSE_TOKEN_TYPE (((_parseState select 0) select (_parseState select 1)) select 0) #define PARSE_TOKEN_VALUE (((_parseState select 0) select (_parseState select 1)) select 1) #define PARSE_HAS_ERROR (_parseState select 2 != "") #define PARSE_EXIT_IF_ERROR if PARSE_HAS_ERROR exitWith {_result}; #define PARSE_SET_ERROR(ERROR) [_parseState, "%1 at %2", ERROR, PARSE_TOKEN_VALUE] call MF_Json_SetError #define PARSE_SKIP if ((_parseState select 1) >= (count (_parseState select 0))) exitWith {[_parseState, "Expected more input after %1", ((_parseState select 0) select ((_parseState select 1) - 1))] call MF_Json_SetError;}; _parseState set [1, (_parseState select 1) + 1] #define PARSE_IGNORE(TOKEN) if (PARSE_TOKEN_TYPE != TOKEN) exitWith {[_parseState, "Expected token %1 near %2", TOKEN, PARSE_TOKEN_VALUE] call MF_Json_SetError;}; PARSE_SKIP #define PARSE_READ_VAL_INTO(VAR) VAR = PARSE_TOKEN_VALUE; PARSE_SKIP #define PARSE_COMPARE_CURRENT(VAL) (typeName PARSE_TOKEN_TYPE == typeName VAL and {PARSE_TOKEN_TYPE == VAL}) //JSON top level can only be object or array MF_Json_Parse_Top = { private ["_parseState"]; _parseState = _this; if (PARSE_TOKEN_TYPE == "lbrace") exitWith { _parseState call MF_Json_Parse_Object; }; if (PARSE_TOKEN_TYPE == "lbracket") exitWith { _parseState call MF_Json_Parse_Array; }; PARSE_SET_ERROR("Expected { or ["); }; MF_Json_Parse_Object = { private ["_parseState","_result","_kvArray","_key","_val"]; _parseState = _this; _kvArray = []; _result = ["object", _kvArray]; PARSE_IGNORE("lbrace"); if (PARSE_TOKEN_TYPE == "rbrace") exitWith { PARSE_SKIP; _result }; while {true} do { if (PARSE_TOKEN_TYPE != "string") exitWith { PARSE_SET_ERROR("String expected"); }; PARSE_READ_VAL_INTO(_key); PARSE_IGNORE("colon"); _val = _parseState call MF_Json_Parse_Value; PARSE_EXIT_IF_ERROR; _kvArray set [count _kvArray, [_key, _val]]; if (PARSE_TOKEN_TYPE == "rbrace") exitWith { PARSE_SKIP; _result }; if (PARSE_TOKEN_TYPE != "comma") exitWith { //Thanks for a buggy preprocessor , => comma PARSE_SET_ERROR("Expected comma or }"); }; PARSE_SKIP; }; _result }; MF_JSON_Parse_Array = { private ["_parseState","_array","_result","_val"]; _parseState = _this; _array = []; _result = ["array", _array]; PARSE_IGNORE("lbracket"); if (PARSE_TOKEN_TYPE == "rbracket") exitWith { PARSE_SKIP; _result }; while {true} do { _val = _parseState call MF_Json_Parse_Value; PARSE_EXIT_IF_ERROR; _array set [count _array, _val]; if (PARSE_TOKEN_TYPE == "rbracket") exitWith { PARSE_SKIP; _result }; if (PARSE_TOKEN_TYPE != "comma") exitWith { PARSE_SET_ERROR("Expected comma or ]"); }; PARSE_SKIP }; _result }; MF_Json_Parse_Value = { private ["_parseState","_result"]; _parseState = _this; if (PARSE_TOKEN_TYPE == "lbrace") exitWith { _parseState call MF_Json_Parse_Object }; if (PARSE_TOKEN_TYPE == "lbracket") exitWith { _parseState call MF_Json_Parse_Array }; if (PARSE_TOKEN_TYPE in ["string","number","bool","null"]) exitWith { PARSE_READ_VAL_INTO(_result); _result }; PARSE_SET_ERROR("Did not expect the value"); }; //----------------- Lexer MF_Json_Lex = { private ["_codePoints","_state","_startI","_currentI","_codePoint","_tokens","_error","_nextState","_action","_token"]; _codePoints = toArray _this; //EOF -- set does not work when the index is very large, even though still perfectly representable integer _codePoints set [count _codePoints, -1]; _state = 0; _startI = 0; _currentI = 0; _codePoint = _codePoints select _currentI; _tokens = []; _error = ""; scopeName "main"; while {true} do { //Skip blanks if (_state == 0 and (_codePoint in MF_Json_Blanks)) then { _currentI = _currentI + 1; _startI = _currentI; _codePoint = _codePoints select _currentI; } else { //Find next state _nextState = MF_Json_Lex_AcceptUnicodeTable select _state; //In table range? if (_codePoint >= 0 and _codePoint < 128) then { _nextState = (MF_Json_Lex_Table select _state) select _codePoint; }; //Token complete or bad input? if (_nextState == -1) then { //EOF? (Moved inside here for performance; yes it matters!) if (_state == 0 and _codePoint == -1) then { breakTo "main"; }; _action = MF_Json_Lex_AcceptingStates select _state; if (typeName _action == typeName -1) then { _error = format ["Lexer: Did not expect '%1' at this time", toString [_codePoint]]; breakTo "main"; }; //Extract token _token = [_codePoints, _startI, _currentI - 1] call _action; _tokens set [count _tokens, _token]; _nextState = 0; _startI = _currentI; } else { _currentI = _currentI + 1; _codePoint = _codePoints select _currentI; }; _state = _nextState; }; }; if (_error != "") exitWith {_error}; _tokens }; MF_Json_Lex_Extract = { private ["_codePoints","_fromI","_toI","_result"]; _codePoints = _this select 0; _fromI = _this select 1; _toI = _this select 2; _result = []; _result resize (_toI - _fromI + 1); for "_i" from _fromI to (_toI) do { _result set [_i - _fromI, _codePoints select _i]; }; toString _result }; MF_Json_Blanks = [32, 9, 10, 13]; //Lexer functions MF_Json_Lex_Func_Number = { ["number", parseNumber (_this call MF_Json_Lex_Extract)] }; MF_Json_Lex_Func_String = { //TODO: Handle unicode hexadecimal code points //Strip quotes ["string", [_this select 0, (_this select 1) + 1, (_this select 2) - 1] call MF_Json_Lex_Extract] }; MF_Json_Lex_Func_True = { ["bool", true] }; MF_Json_Lex_Func_False = { ["bool", false] }; MF_Json_Lex_Func_Null = { ["null", objNull] }; MF_Json_Lex_Func_Colon = { ["colon", ":"] }; MF_Json_Lex_Func_Comma = { ["comma", ","] }; MF_Json_Lex_Func_L_Brace = { ["lbrace", "{"] }; MF_Json_Lex_Func_L_Bracket = { ["lbracket", "["] }; MF_Json_Lex_Func_R_Brace = { ["rbrace", "}"] }; MF_Json_Lex_Func_R_Bracket = { ["rbracket", "]"] }; //-------- TABLES MF_Json_Lex_Table = [ //START, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,29,9,-1,-1,7,8,8,8,8,8,8,8,8,8,30,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,25,-1,26,-1,-1,-1,-1,-1,-1,-1,-1,18,-1,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,22,-1,-1,-1,-1,-1,-1,27,-1,28,-1,-1], //STRING_1, [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], //STRING_2, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,1,-1,1,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //STRING_3, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,4,4,4,4,4,4,4,4,4,-1,-1,-1,-1,-1,-1,-1,4,4,4,4,4,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,4,4,4,4,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //STRING_4, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5,5,5,5,5,5,5,5,5,5,-1,-1,-1,-1,-1,-1,-1,5,5,5,5,5,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5,5,5,5,5,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //STRING_5, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,6,6,6,6,6,6,6,6,6,6,-1,-1,-1,-1,-1,-1,-1,6,6,6,6,6,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,6,6,6,6,6,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //STRING_6, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_1, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_2, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,-1,8,8,8,8,8,8,8,8,8,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_3, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,8,8,8,8,8,8,8,8,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_4, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,11,11,11,11,11,11,11,11,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_5, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,11,11,11,11,11,11,11,11,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_6, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,13,-1,13,-1,-1,14,14,14,14,14,14,14,14,14,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_7, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,14,14,14,14,14,14,14,14,14,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NUMBER_8, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,14,14,14,14,14,14,14,14,14,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NULL_1, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,16,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NULL_2, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,17,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NULL_3, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //FALSE_1, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,19,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //FALSE_2, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,20,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //FALSE_3, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //FALSE_4, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,33,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //TRUE_1, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //TRUE_2, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,24,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //TRUE_3, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,34,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_LBRACKET, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_RBRACKET, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_LBRACE, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_RBRACE, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_COMMA, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //ACCEPT_COLON, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //STRING_ACCEPT, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //NULL_ACCEPT, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //FALSE_ACCEPT, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], //TRUE_ACCEPT, [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] ]; MF_Json_Lex_AcceptUnicodeTable = [ -1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ]; MF_Json_Lex_AcceptingStates = [ -1,-1,-1,-1,-1,-1,-1,MF_Json_Lex_Func_Number,MF_Json_Lex_Func_Number,-1,-1,MF_Json_Lex_Func_Number,-1,-1,MF_Json_Lex_Func_Number,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,MF_Json_Lex_Func_L_Bracket,MF_Json_Lex_Func_R_Bracket,MF_Json_Lex_Func_L_Brace,MF_Json_Lex_Func_R_Brace,MF_Json_Lex_Func_Comma,MF_Json_Lex_Func_Colon,MF_Json_Lex_Func_String,MF_Json_Lex_Func_Null,MF_Json_Lex_Func_False,MF_Json_Lex_Func_True ];
  11. No it does not imply that. You can store the number (2 ^ 128)-1 in an unsigned integer of 128 bit. However, floating point numbers have a different internal representation that works differently. You can represent (2 ^ 128)-1 (and no more!) using only single-precision float (4 bytes), however, you are not guaranteed the less significant numbers are accurate. Likewise you can store 0.000000000053143453132231 in a floating point number, again no guarantee that it is exactly the number you guaranteed. Basically a 'normal' int and float each only take 4 bytes, giving 32 bits, giving 2^32 different possibilities. Integers can represent, well integers, accurately as long as they are withing the range +(2^31 - 1) to -(2^31) for signed integers. Floats can represent much larger or smaller numbers, but can only accurately represent least significant numbers. A 4 byte float should give you between 6 to 9 significant (decimal) digits. My guess is that the engine either: - Stores all numbers as C floats. This causes no issue normally since most numbers are are less than 9 digits long. - Converts between C floats and C integers automatically.
  12. Groups don't contain vehicles. Groups contain people. Vehicles are in the group of whichever units are in it. (Guessing driver or commander decides). I'm guessing this is the reasons you get the null: - There aren't any units in the heli belonging to the group and an empty vehicle does not belong to any group.
  13. Yes this is possible if you add gear from a script. You can use this to decide what to add: if (isClass(configFile >> "CfgPatches" >> "ace_main")) then { //ACE is running //Add ace gear. } else { //ACE is not running! //Add vanilla gear }; However, since there is no addon dependency people without ACE can join the server, but they will probably get classname errors and ACE weapons will be invisible from their perspective.
  14. No, you should change it to something else. HORDE would be fine. Remember to change it everywhere (also the 2 defines at the top). Only think it is unsafe if the "actual" code to be run is not thread safe: From the globalEvent call: any publicVariabled data are guaranteed to arrive separate, so if you do 2 global events at the same time, then they will still arrive in some order. From the localEvent: when the handler for addPublicVariableHandler runs it runs to completion before any other publicVariabled events are processed. Since localEvent also calls each handler there is no issue with the event "framework". If you own code is affected by race conditions then it will still be affected by if you used two variables. The only place I can see where you might have this problem is if you addEventHandler while a events are already being processed. However that can be fixed by copying the handler array when processing: TAG_LocalEvent = { private ["_event","_args","_eventHandlers"]; _event = _this select 0; _args = if (count _this > 1) then {_this select 1} else {[]}; _eventHandlers = [color="#009000"]+[/color]TAG_EventHandlers getVariable [_event, []]; { //Handler may have been removed. if (!isNil "_x") then { _args call _x; }; } forEach _eventHandlers; };
  15. You should run the file on mission init (preferable: call compile preProcessFile "events.sqf"; ) You call it like this: ["MyEvent", ["My", "Arguments", "Here"]] call Tag_GlobalEvent; //Global event means it will run everywhere (machines) there you have added an event handler with that name. See below. Listeners are added like this: ["MyEvent", { //You get there parameters here: private ["_me", "_arguments", "_here"]; _me = _this select 0; _arguments = _this select 1; _here = _this select 2; //Do weird greeting hint format ["%1 are %2 %3", _here, _me, _arguments]; }] call TAG_AddEventHandler; Can't remember which environment addPublicVariableEventHandler runs in, so if you plan to do sleeping or long running loops in your event 'handler code' you may want to spawn it, to prevent it from blocking other event handlers for the same event, eg.: ["MyEvent", { //Don't block (sleep) other events _this spawn { //Code here that might sleep or take long. Still have all parameters since they are passed in. }; }] call TAG_AddEventHandler; I modified the code above. No reason to change this. It still get all the parameters here from the AddEventHandler shown first. I consider it good style to keep, the "real code" separate from the "message passing" code, be it CBA-style events, publicVariable, RE framework or whatever. During your init or similar you add the event handler for all machines (or those that need): ["Horde_SpaRemPar", { //You sleep in the called code, so it gets spawned. //All the parameters are in _this.. Eg. _this = [_pl, _pos, _type] (horde_fnc_spawn_particle_effect) _this spawn horde_fnc_spawn_remote_particles; }] call TAG_AddEventHandler; So you avoid sending all the code each time. With some minor modifications horde_fnc_spawn_particle_effect and horde_fnc_spawn_remote_particles could be exactly the same you could call GlobalEvent from the fired event handler directly.