Alef/JIP – User

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - " (={2,})([^ = ])(.*)([^ = ])(={2,}) * " to " $1 $2$3$4 $5 ")
 
(27 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==General==
Work in progress
 
== General ==
The server is already running a mission. At least has the mission.sqm processed.
The server is already running a mission. At least has the mission.sqm processed.
Instanced of object/vehicles are in the server address space.
Instanced of object/vehicles are in the server address space.
Line 6: Line 8:


mission.sqm can't be processed like the server does, because of the randomness of units/vehicles. What if server creates and object and the client not, or if the position is different? This should be an easy remember thing.
mission.sqm can't be processed like the server does, because of the randomness of units/vehicles. What if server creates and object and the client not, or if the position is different? This should be an easy remember thing.
However,OFPEC says mission.sqm/init fields are executed too.


Client get data from server. Sickboy's page explains that.
Client get data from server. Sickboy's MP page explains that.


==JIP test==
== JIP test ==
===source===
=== source ===
<pre>
<pre>
#define SPON_THIS_FILE init.sqf
#include "SPON\Core\core.inc.sqf"
#include "SPON\Core\macros\macros.inc.sqf"
["DEBUG_CLIENT",9999,true] call compile preprocessFileLineNumbers "SPON\Core\initCore.sqf";
// JIP test only. Put "p" as variable name in mission.sqm for JIP player.
// JIP test only. Put "p" as variable name in mission.sqm for JIP player.
#define TEST( xx ) if ( xx ) then { _s=_s+ #xx +" ;" };
#define TEST( xx ) if (xx) then { s=#xx } else { s="not "+#xx };
#define PRINT( xx ) _s=_s+ #xx + " = " + xx +" ;" ;
#define PRINT( xx ) s=#xx+" = "+(xx);
_s="init.sqf\n";
#define PRINTF( xx ) s=#xx+" = "+format["%1",(xx)];
for [{ _x=0 },{ _x<2 },{ _x=_x+1 }] do {
c=0;
    // _u=player; // not needed
waitUntil
    // isNull
{
    // this happens in JIP if no sleep are performed before.
     TEST( isNull p )
     TEST( isNull p )
    SPON_TRACE_1( s, c );
     TEST( isNull player )
     TEST( isNull player )
     _s=_s+"\n";
     SPON_TRACE_1( s, c );
    // locality
     TEST( local p )
     TEST( local p )
    SPON_TRACE_1( s, c );
     TEST( local player )
     TEST( local player )
     _s=_s+"\n";
     SPON_TRACE_1( s, c );
    // isPlayer
     TEST( isPlayer p )
     TEST( isPlayer p )
    SPON_TRACE_1( s, c );
     TEST( isPlayer player )
     TEST( isPlayer player )
     _s=_s+"\n";
     SPON_TRACE_1( s, c );
    // name
     PRINT( name p )
     PRINT( name p )
    SPON_TRACE_1( s, c );
     PRINT( name player )
     PRINT( name player )
     // 20090415 name: "No vehicle", add an additional check for vehicle
     SPON_TRACE_1( s, c );
     PRINT( vehicle p )
    PRINTF( vehicle p )
     PRINT( vehicle player )
    SPON_TRACE_1( s, c );
     // alive
    PRINTF( vehicle player )
     PRINT( alive p )
    SPON_TRACE_1( s, c );
     PRINT( alive player )
     PRINTF( alive p )
     _s=_s+"\nsleep 0.001;\n";
     SPON_TRACE_1( s, c );
     sleep 0.001;
    PRINTF( alive player )
     SPON_TRACE_1( s, c );
// what about getVariable ?
     PRINT( p getVariable "undefined" );
    SPON_TRACE_1( s, c );
     PRINT( player getVariable "undefined" );
    SPON_TRACE_1( s, c );
     c=c+1;
     name player != "Error: No vehicle";
};
};
hint _s;
localize _s;
</pre>
</pre>


===output (edited)===
=== output (edited) ===
hosting game<pre>
{| border="1" cellpadding="2" cellspacing="0"
local p ; local _u ; local player ;
|colspan="13"|hosting game (p != player)
isPlayer _u ; isPlayer player ;
|-
name p = Roberto Duarte ; name _u = alef ; name player = alef ;
|rowspan="2"|time
sleep 0.001;
|colspan="2"|<center>isNull</center>
local p ; local _u ; local player ;
|colspan="2"|<center>local</center>
isPlayer _u ; isPlayer player ;
|colspan="2"|<center>isPlayer</center>
name p = Roberto Duarte ; name _u = alef ; name player = alef ;
|colspan="2"|<center>name</center>
</pre>
|colspan="2"|<center>vehicle</center>
|colspan="2"|<center>alive</center>
|-
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|-
|any
|false
|false
|true
|true
|false
|true
|Roberto Duarte
|alef
|TODO
|TODO
|TODO
|TODO
|-
|colspan="13"|JIP
|-
|rowspan="2"|time
|colspan="2"|<center>isNull</center>
|colspan="2"|<center>local</center>
|colspan="2"|<center>isPlayer</center>
|colspan="2"|<center>name</center>
|colspan="2"|<center>vehicle</center>
|colspan="2"|<center>alive</center>
|-
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|-
|0
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|TODO
|TODO
|TODO
|TODO
|-
|0.001
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|TODO
|TODO
|TODO
|TODO
|-
|colspan="13"|JIP, changed to sleep 1 second
|-
|rowspan="2"|time
|colspan="2"|<center>isNull</center>
|colspan="2"|<center>local</center>
|colspan="2"|<center>isPlayer</center>
|colspan="2"|<center>name</center>
|colspan="2"|<center>vehicle</center>
|colspan="2"|<center>alive</center>
|-
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|-
|0
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|TODO
|TODO
|TODO
|TODO
|-
|1
|false
|false
|true
|true
|true
|true
|alef (2)
|alef (2)
|TODO
|TODO
|TODO
|TODO
|-
|colspan="13"|JIP, monitored with SPON Core, waitUntil name player != "no veh"
|-
|rowspan="2"|time
|colspan="2"|<center>isNull</center>
|colspan="2"|<center>local</center>
|colspan="2"|<center>isPlayer</center>
|colspan="2"|<center>name</center>
|colspan="2"|<center>vehicle</center>
|colspan="2"|<center>alive</center>
|-
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|p
|player
|-
|0
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|p
|<NULL-object>
|true
|false
|-
|c=1
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|p
|<NULL-object>
|true
|false
|-
|c=2
|false
|true
|false
|false
|false
|false
|Roberto Duarte
|Error: No vehicle
|p
|<NULL-object>
|true
|false
|-
|c=3
|false
|false
|true
|true
|true
|true
|alef (2)
|alef (2)
|p
|p
|true
|true
|}


JIP<pre>
=== comments ===
isNull _u ; isNull player ;
So what's happened?
name p = Roberto Duarte ; name _u = Error: No vehicle ; name player = Error: No vehicle ;
sleep 0.001;
isNull _u ; isNull player ;
name p = Roberto Duarte ; name _u = Error: No vehicle ; name player = Error: No vehicle ;
</pre>


JIP, changed to sleep 1 second<pre>
ok, as we enter, player is null. so just waitUntil{!(isNull player)}, like XEH does.
isNull _u ; isNull player ;
name p = Roberto Duarte ; name _u = Error: No vehicle ; name player = Error: No vehicle ;
sleep 1;
local p ; local _u ; local player ;
isPlayer p ; isPlayer _u ; isPlayer player ;
name p = alef (2) ; name _u = alef (2) ; name player = alef (2) ;
</pre>


===comments===
* name p = Roberto Duarte
_u and player are the same thing.
* name player = Error: No vehicle
* remove _u
 
So what's happened?


* isNull _u ; isNull player ;<br>
name of unit p is the random created. No [[setIdentity]] in the mission: it would work looking in description.ext/CfgIdentities.<br>
ok, as we enter, player is null. so just waitUntil{!(isNull player)}, like XEH does.
"name player" says there is no vehicle for it, because player is still null.


* name p = Roberto Duarte ; name _u = Error: No vehicle ; name player = Error: No vehicle ;<br>
* local p ; local player ;
name of unit p is the random created one (no [[setIdentity]] in the mission).<br>
* isPlayer p ; isPlayer player ;
setIdentity would work looking in description.ext/CfgIdentities.<br>
* name p = alef (2) ; name player = alef (2) ;
name player says there is no vehicle for it, because player is still null.<br>
Maybe arma waits assigning a vehicle until [[Description.ext]] has been parsed.


* local p ; local _u ; local player ;
Now the name of unit p has been assigned to the player's name. p is player, I suppose is just a check on the player pointer.
* isPlayer p ; isPlayer _u ; isPlayer ;
XEH relevant code for JIP:<pre>
* name p = alef (2) ; name _u = alef (2) ; name player = alef (2) ;
waitUntil{!(isNull player)}
waitUntil{local player}</pre>


Now the name of unit p has been assigned to the player's name.
XEH does a waitUntil{local player} after checking for null. It could be possible that under heavy load (ACE bug #778), name is not assigned while player being local.


Call stack in ace tracking:<pre>
==== Call stack in ace tracking for bug #778 ====
<pre>
XEH: PostInit.sqf, time == 0
XEH: PostInit.sqf, time == 0
XEH:  isNull player
XEH:  isNull player
Line 104: Line 311:
time > 0
time > 0
XEH:  waited for !isNull (group player)
XEH:  waited for !isNull (group player)
XEH: ... { [] call _x } forEach _PostInits;
XEH: ... { [] call _x } forEach _PostInits; -> XEH_PostInit_Once.sqf: register fUpdateUnits
 
XEH: { _x call SLX_XEH_init } forEach SLX_XEH_OBJECTS; // Run InitPosts
SLX_XEH_init=XEH\Init.sqf
config.cpp:h\Eventhandlers.hpp:
config.cpp:h\Eventhandlers.hpp:
Extended_InitPost_EventHandlers::CAManBase::ace_sys_tracking::
Extended_InitPost_EventHandlers::CAManBase::ace_sys_tracking::
init = "(_this select 0) call ace_sys_tracking_initMan";
init = "(_this select 0) call ace_sys_tracking_initMan";
onRespawn = 1;
onRespawn = 1;
XEH_PreInit_Once.sqf:ace_sys_tracking_initMan = { ace_sys_tracking_units += [_this]; ...}
s/initMan.sqf: spawn s/loopGroup.sqf
s/initMan.sqf: spawn s/loopGroup.sqf
s/loopGroup.sqf:  
s/loopGroup.sqf:     first time and every 10 or more seconds (very roughly)
first time and every 10 or more seconds (very roughly)
s/loopGroup.sqf:35:  call { call ace_sys_tracking_fUpdateUnits }
s/loopGroup.sqf:35:  call { call ace_sys_tracking_fUpdateUnits }
s/fUpdateUnits.sqf: [_units]
s/fUpdateUnits.sqf:  alive _x &&  "<null>" == _x getVariable "ace_sys_tracking_player"
s/fUpdateUnits.sqf:  _x setVariable ["ace_sys_tracking_name", name _x]
</pre>
</pre>

Latest revision as of 19:30, 31 January 2021

Work in progress

General

The server is already running a mission. At least has the mission.sqm processed. Instanced of object/vehicles are in the server address space.

Now, the JIP needs to download from the server the status and keep it updated.

mission.sqm can't be processed like the server does, because of the randomness of units/vehicles. What if server creates and object and the client not, or if the position is different? This should be an easy remember thing. However,OFPEC says mission.sqm/init fields are executed too.

Client get data from server. Sickboy's MP page explains that.

JIP test

source

#define SPON_THIS_FILE init.sqf
#include "SPON\Core\core.inc.sqf"
#include "SPON\Core\macros\macros.inc.sqf"

["DEBUG_CLIENT",9999,true] call compile preprocessFileLineNumbers "SPON\Core\initCore.sqf";
// JIP test only. Put "p" as variable name in mission.sqm for JIP player.
#define  TEST( xx ) if (xx) then { s=#xx } else { s="not "+#xx };
#define PRINT( xx ) s=#xx+" = "+(xx);
#define PRINTF( xx ) s=#xx+" = "+format["%1",(xx)];
c=0;
waitUntil
{
    TEST( isNull p )
    SPON_TRACE_1( s, c );
    TEST( isNull player )
    SPON_TRACE_1( s, c );
    TEST( local p )
    SPON_TRACE_1( s, c );
    TEST( local player )
    SPON_TRACE_1( s, c );
    TEST( isPlayer p )
    SPON_TRACE_1( s, c );
    TEST( isPlayer player )
    SPON_TRACE_1( s, c );
    PRINT( name p )
    SPON_TRACE_1( s, c );
    PRINT( name player )
    SPON_TRACE_1( s, c );
    PRINTF( vehicle p )
    SPON_TRACE_1( s, c );
    PRINTF( vehicle player )
    SPON_TRACE_1( s, c );
    PRINTF( alive p )
    SPON_TRACE_1( s, c );
    PRINTF( alive player )
    SPON_TRACE_1( s, c );
// what about getVariable ?
    PRINT( p getVariable "undefined" );
    SPON_TRACE_1( s, c );
    PRINT( player getVariable "undefined" );
    SPON_TRACE_1( s, c );
    c=c+1;
    name player != "Error: No vehicle";
};

output (edited)

hosting game (p != player)
time
isNull
local
isPlayer
name
vehicle
alive
p player p player p player p player p player p player
any false false true true false true Roberto Duarte alef TODO TODO TODO TODO
JIP
time
isNull
local
isPlayer
name
vehicle
alive
p player p player p player p player p player p player
0 false true false false false false Roberto Duarte Error: No vehicle TODO TODO TODO TODO
0.001 false true false false false false Roberto Duarte Error: No vehicle TODO TODO TODO TODO
JIP, changed to sleep 1 second
time
isNull
local
isPlayer
name
vehicle
alive
p player p player p player p player p player p player
0 false true false false false false Roberto Duarte Error: No vehicle TODO TODO TODO TODO
1 false false true true true true alef (2) alef (2) TODO TODO TODO TODO
JIP, monitored with SPON Core, waitUntil name player != "no veh"
time
isNull
local
isPlayer
name
vehicle
alive
p player p player p player p player p player p player
0 false true false false false false Roberto Duarte Error: No vehicle p <NULL-object> true false
c=1 false true false false false false Roberto Duarte Error: No vehicle p <NULL-object> true false
c=2 false true false false false false Roberto Duarte Error: No vehicle p <NULL-object> true false
c=3 false false true true true true alef (2) alef (2) p p true true

comments

So what's happened?

ok, as we enter, player is null. so just waitUntil{!(isNull player)}, like XEH does.

  • name p = Roberto Duarte
  • name player = Error: No vehicle

name of unit p is the random created. No setIdentity in the mission: it would work looking in description.ext/CfgIdentities.
"name player" says there is no vehicle for it, because player is still null.

  • local p ; local player ;
  • isPlayer p ; isPlayer player ;
  • name p = alef (2) ; name player = alef (2) ;

Now the name of unit p has been assigned to the player's name. p is player, I suppose is just a check on the player pointer.

XEH relevant code for JIP:

waitUntil{!(isNull player)}
waitUntil{local player}


Call stack in ace tracking for bug #778

XEH: PostInit.sqf, time == 0
XEH:  isNull player
XEH:   waited for !(isNull player)
XEH:   waited for local player
time > 0
XEH:   waited for !isNull (group player)
XEH: ... { [] call _x } forEach _PostInits; -> XEH_PostInit_Once.sqf: register fUpdateUnits
XEH: { _x call SLX_XEH_init } forEach SLX_XEH_OBJECTS; // Run InitPosts
SLX_XEH_init=XEH\Init.sqf
config.cpp:h\Eventhandlers.hpp:
 Extended_InitPost_EventHandlers::CAManBase::ace_sys_tracking::
		init = "(_this select 0) call ace_sys_tracking_initMan";
		onRespawn = 1;
XEH_PreInit_Once.sqf:ace_sys_tracking_initMan = { ace_sys_tracking_units += [_this]; ...}
s/initMan.sqf: spawn s/loopGroup.sqf
s/loopGroup.sqf:      first time and every 10 or more seconds (very roughly)
s/loopGroup.sqf:35:   call { call ace_sys_tracking_fUpdateUnits }
s/fUpdateUnits.sqf: [_units] 
s/fUpdateUnits.sqf:  alive _x &&  "<null>" == _x getVariable "ace_sys_tracking_player"
s/fUpdateUnits.sqf:   _x setVariable ["ace_sys_tracking_name", name _x]