The online racing simulator
IS_JRR Packets
So eehhh we have this new [currently beta] packet. I try to implement this;

/modules/prism_packets.php;

<?php 
define
('ISP_JRR',    58);   // 58 - instruction     : reply to a join request (allow / disallow)
$ISP = array(ISP_NONE => 'ISP_NONE'ISP_ISI => 'ISP_ISI'ISP_VER => 'ISP_VER'ISP_TINY => 'ISP_TINY'ISP_SMALL => 'ISP_SMALL'ISP_STA => 'ISP_STA'ISP_SCH => 'ISP_SCH'ISP_SFP => 'ISP_SFP'ISP_SCC => 'ISP_SCC'ISP_CPP => 'ISP_CPP'ISP_ISM => 'ISP_ISM'ISP_MSO => 'ISP_MSO'ISP_III => 'ISP_III'ISP_MST => 'ISP_MST'ISP_MTC => 'ISP_MTC'ISP_MOD => 'ISP_MOD'ISP_VTN => 'ISP_VTN'ISP_RST => 'ISP_RST'ISP_NCN => 'ISP_NCN'ISP_MTC => 'ISP_MTC'ISP_CNL => 'ISP_CNL'ISP_CPR => 'ISP_CPR'ISP_NPL => 'ISP_NPL'ISP_PLP => 'ISP_PLP'ISP_PLL => 'ISP_PLL'ISP_LAP => 'ISP_LAP'ISP_SPX => 'ISP_SPX'ISP_PIT => 'ISP_PIT'ISP_PSF => 'ISP_PSF'ISP_PLA => 'ISP_PLA'ISP_CCH => 'ISP_CCH'ISP_PEN => 'ISP_PEN'ISP_TOC => 'ISP_TOC'ISP_FLG => 'ISP_FLG'ISP_PFL => 'ISP_PFL'ISP_FIN => 'ISP_FIN'ISP_RES => 'ISP_RES'ISP_REO => 'ISP_REO'ISP_NLP => 'ISP_NLP'ISP_MCI => 'ISP_MCI'ISP_MSX => 'ISP_MSX'ISP_MSL => 'ISP_MSL'ISP_CRS => 'ISP_CRS'ISP_BFN => 'ISP_BFN'ISP_AXI => 'ISP_AXI'ISP_AXO => 'ISP_AXO'ISP_BTN => 'ISP_BTN'ISP_BTC => 'ISP_BTC'ISP_BTT => 'ISP_BTT'ISP_RIP => 'ISP_RIP'ISP_SSH => 'ISP_SSH'ISP_CON => 'ISP_CON'ISP_OBH => 'ISP_OBH'ISP_HLV => 'ISP_HLV'ISP_PLC => 'ISP_PLC'ISP_AXM => 'ISP_AXM'ISP_ACR => 'ISP_ACR'ISP_HCP => 'ISP_HCP'ISP_NCI => 'ISP_NCI'ISP_JRR => 'ISP_JRR');
?>


<?php 
class IS_JRR extends Struct // Join Request Reply - send one of these back to LFS in response to a join request
{
    const 
PACK 'CCxCCCxxC';
    const 
UNPACK 'CSize/CType/CReqI/CPLID/CUCID/CJRRAction/xSp2/xSp3/CStartPos';

    protected 
$Size 16;       # 16
    
protected $Type ISP_JRR;  # ISP_JRR
    
public $ReqI;               # 0
    
public $PLID;               # ZERO when this is a reply to a join request - SET to move a car

    
public $UCID;               # set when this is a reply to a join request - ignored when moving a car
    
public $JRRAction;          # 1 - allow / 0 - reject (should send message to user)
    
protected $Sp2;
    protected 
$Sp3;

    public 
$StartPos;           # 0 : use default start point / Flags = 0x80 : set start point
}; function IS_JRR() { return new IS_JRR; }

// Values for JRRAction byte

define('JRR_REJECT',            0);     // 0 - reject (should send message to user)
define('JRR_SPAWN',             1);     // 1 - allow
define('JRR_2',                 2);     // 2 
define('JRR_3',                 3);     // 3 
define('JRR_RESET',             4);     // 4 - reset car with repair
define('JRR_RESET_NO_REPAIR',   5);     // 5 - reset car without repair
define('JRR_6',                 6);     // 6
define('JRR_7',                 7);     // 7
$JRR = array(JRR_REJECT => 'JRR_REJECT'JRR_SPAWN => 'JRR_SPAWN'JRR_2 => 'JRR_2'JRR_3 => 'JRR_3'JRR_RESET => 'JRR_RESET'JRR_RESET_NO_REPAIR => 'JRR_RESET_NO_REPAIR'JRR_6 => 'JRR_6'JRR_7 => 'JRR_7');
?>

plugins/test.php;

<?php 
        
if ($NPL->NumP == 0// join request, we need to do something else 
        
{
            echo 
"hey a join request -.-";
            
IS_JRR()->PLID(0)->UCID($NPL->UCID)->JRRAction(0)->StartPos(0)->Send($hostID);
        }
?>

I think these changes should be sufficient to let PRISM send a JRR. But after loooonnggg investigation it doesn't. Why? I don't know. It's packing, it's doing writeUDP if I var_dump the packet;

/modules/prism_hosts.php


<?php 
                
case ISP_JRR:
                    
var_dump($packetClass);
                    
console("> ${TYPEs[$packetClass->Type]} Packet to {$hostId}.");
?>

I get this;

hey a join request -.-object(IS_JRR)#37 (9) {
["Size":protected]=>
int(16)
["Type":protected]=>
&int(58)
["ReqI"]=>
NULL
["PLID"]=>
int(0)
["UCID"]=>
int(2)
["JRRAction"]=>
int(0)
["Sp2":protected]=>
NULL
["Sp3":protected]=>
NULL
["StartPos"]=>
int(0)
}
> IS_JRR Packet to test.

Looks all good to me. But... When I tcpdump activity on the InSim port I never see this packet actually being send to LFS.. Why? I have no clue.

Assistance is of course welcome Wink

// edit it actually sends something.. But it seems to contain only one byte...
I don't know how this thing works at all, but can you run it in a debugger, so you could put a breakpoint on the line where it says "echo hey a join request" and then step through, line by line, in the debugger, to see where it breaks down and why it doesn't send?
Well I just edited my text.. It actually -does- send something ... But it's nonsense. Eehhhmm strange, this should be not much different then all the other packets. I try to figure out where it goes wrong.
Also, the StartPos is an eight byte structure, not an int. I don't know if that affects anything.
No idea what any of your code means but

const PACK = 'CCxCCCxxC';
const UNPACK = 'CSize/CType/CReqI/CPLID/CUCID/CJRRAction/xSp2/xSp3/CStartPos';

Should CCxCCCxxC be CCCCCCxxC or CReqI be xReqI?
Quote from Scawen :Also, the StartPos is an eight byte structure, not an int. I don't know if that affects anything.

Yes it does.. I already was wondering why I only got 9 bytes of a packet... Facepalm..

Quote from sinanju :Should CCxCCCxxC be CCCCCCxxC or CReqI be xReqI?

Hmm no that bit is fine... ReqI can either be C or x .. Because x gets automatically converted to a nulled C ... That happens in a different part of the code.. But thanks for replying Smile
Right.. Hmm .. I fill the packet with null data like this;


<?php 
class ObjectInfo extends Struct // Info about a single object - explained in the layout file format
{
    const 
PACK 'sscCCC';
    const 
UNPACK 'sX/sY/CZbyte/CFlags/CIndex/CHeading';

    public 
$X;
    public 
$Y;
    public 
$Zbyte;
    public 
$Flags;
    public 
$Index;
    public 
$Heading;
};

class 
IS_JRR extends Struct // Join Request Reply - send one of these back to LFS in response to a join request
{
    const 
PACK 'CCxCCCxxxxxxxxxx';
    const 
UNPACK 'CSize/CType/CReqI/CPLID/CUCID/CJRRAction/xSp2/xSp3';

    protected 
$Size 16;       # 16
    
protected $Type ISP_JRR;  # ISP_JRR
    
public $ReqI;               # 0
    
public $PLID;               # ZERO when this is a reply to a join request - SET to move a car

    
public $UCID;               # set when this is a reply to a join request - ignored when moving a car
    
public $JRRAction;          # 1 - allow / 0 - reject (should send message to user)
    
protected $Sp2;
    protected 
$Sp3;

    
/*
    public $StartPos = array(); # 0 : use default start point / Flags = 0x80 : set start point

    public function pack()
    {
        $StartPos = '';

        foreach ($this->StartPos as $ObjectInfo) {
            $StartPos .= $ObjectInfo->pack();
        }

        return parent::pack() . $StartPos;
    }
    */
    
protected $Sp4;
    protected 
$Sp5;
    protected 
$Sp6;
    protected 
$Sp7;
    protected 
$Sp8;
    protected 
$Sp9;
    protected 
$Sp10;
    protected 
$Sp11;
}; function 
IS_JRR() { return new IS_JRR; }
?>

I actually finally get the "The host did not allow you to join" or I can join without a message (Depending on JRRAction being 0 or 1) ... But start positions and reset positions etc I cannot get that to work because something goes wrong with StartPos. I stole the code from AXM packet and modified it a bit but without luck. Maybe the code from AXM never worked, no idea if anyone ever tried it. Probably I do something wrong, no clue.. Hopefully one of the American boys (Dygear/T3charmy) or anyone else reading this can give a comment on it when they wake up.

The thing is that ObjectInfo is added manually to the end of the pack with it's own structure. (Which is already defined for AXM).

The problem is that it always ends up with a fatal error; Call to a member function pack() on integer // which refers to the line with $ObjectInfo->pack();
I suppose you could write out the elements of the ObjectInfo structure, as elements of the main packet instead of using an actual sub-structure within the packet, though I don't know if that makes it less convenient.
Yes, I did the same for CPP a while ago.. Had issues with Vec so I structed it outside the packet ( https://www.lfs.net/forum/thread/88472-IS-CPP-Packets ) ... Had the same idea for this, this afternoon;


<?php 
        
if ($NPL->NumP == 0// join request, we need to do something else 
        
{
            
$StartPos pack("sscCCC", -4555, -789491280128);

            
$JRR = new IS_JRR;
            
$JRR->PLID(0)->UCID($NPL->UCID)->JRRAction(1)->StartPos($StartPos)->Send($hostID);
        }
?>

I am allowed or disallowed but if I am allowed I get spawned in pits. Thats why I asked in the other topic what values are valid. By the looks of it something goes wrong with packing .. I need to take a good look what happens @AXM when I place an object. But I moved country in the meantime, was in the car and then my head just continues thinking. And I am actually on a visit at the moment.. Real life... Annoying Tongue
New day... Fresh mind. Success!

Done it the slobby way as usual but I don't care. It works for me Smile ... If people still can follow me or want to follow this...

modules/prism_packets.php;

<?php 
    
public function pack()
    {
        
$return '';
        
$packFormat $this->parsePackFormat();
        
$propertyNumber = -1;

        foreach (
$this as $property => $value) {
            
$pkFnkFormat $packFormat[++$propertyNumber];

            if (
$pkFnkFormat == '#') {
                break; 
# skip symbol for manual packing detected, do no pack processing here.
            
}
            if (
$pkFnkFormat == 'x') {
                
$return .= pack('C'0); # null & 0 are the same thing in Binary (00000000) and Hex (x00), so null == 0.
            
} elseif (is_array($pkFnkFormat)) {
                list(
$type$elements) = $pkFnkFormat;

                if ((
$j count($value)) > $elements) {
                    
$j $elements;
                }

                for (
$i 0$i $elements; ++$i) {
                if(isset(
$value[$i])){
                    
$return .= pack($type$value[$i]);
                } else {
                    
$return .= pack("x");
                    }
                }
            } else {
                
$return .= pack($pkFnkFormat$value);
            }
        }

        return 
$return;
    }
?>


<?php 
class IS_JRR extends Struct // Join Request Reply - send one of these back to LFS in response to a join request
{
    const 
PACK 'CCxCCCxx#';
    const 
UNPACK 'CSize/CType/CReqI/CPLID/CUCID/CJRRAction/xSp2/xSp3';

    protected 
$Size 16;       # 16
    
protected $Type ISP_JRR;  # ISP_JRR
    
public $ReqI;               # 0
    
public $PLID;               # ZERO when this is a reply to a join request - SET to move a car

    
public $UCID;               # set when this is a reply to a join request - ignored when moving a car
    
public $JRRAction;          # 1 - allow / 0 - reject (should send message to user)
    
protected $Sp2;
    protected 
$Sp3;

    public 
$StartPos = array(); # 0 : use default start point / Flags = 0x80 : set start point

    
public function pack()
    {
        
$StartPosPack pack("sscCCC"$this->StartPos["X"], $this->StartPos["Y"], $this->StartPos["Z"], $this->StartPos["Flags"], $this->StartPos["Index"], $this->StartPos["Heading"]);

        return 
parent::pack() . $StartPosPack;
    }
}; function 
IS_JRR() { return new IS_JRR; }

// Values for JRRAction byte

define('JRR_REJECT',            0);     // 0 - reject (should send message to user)
define('JRR_SPAWN',             1);     // 1 - allow
define('JRR_2',                 2);     // 2 
define('JRR_3',                 3);     // 3 
define('JRR_RESET',             4);     // 4 - reset car with repair
define('JRR_RESET_NO_REPAIR',   5);     // 5 - reset car without repair
define('JRR_6',                 6);     // 6
define('JRR_7',                 7);     // 7
$JRR = array(JRR_REJECT => 'JRR_REJECT'JRR_SPAWN => 'JRR_SPAWN'JRR_2 => 'JRR_2'JRR_3 => 'JRR_3'JRR_RESET => 'JRR_RESET'JRR_RESET_NO_REPAIR => 'JRR_RESET_NO_REPAIR'JRR_6 => 'JRR_6'JRR_7 => 'JRR_7');
?>

anyplugin.php;

<?php 
        
if ($NPL->NumP == 0// join request, we need to do something else 
        
{
            
$ObjectInfo = array("X" => -4452"Y" => -1024"Z" => 48"Flags" => 128"Index" => 0"Heading" => 128);
            
IS_JRR()->PLID(0)->UCID($NPL->UCID)->JRRAction(1)->StartPos($ObjectInfo)->Send($hostID);
        }
?>

@cargame, I'll have a look at cleanly/properly implementing it within the next day or so (If you don't hear anything from me by Tuesday mid-day then I probably got side-tracked).

Edit: Do we have the struct from insim.txt I could look at? what LFS version has this packet?

Edit 2: Found it: https://www.lfs.net/forum/post/1902352#post1902352
Hi! Excellent... I wanted to play around with this packet so feedback about it can/could be given. Take your time but don't get side-tracked ^^
These two commits should bring you up to date with the current version of InSim.

Updated packets to 0.6K12 and INSIM_VERSION 7.
Added $JRR array for the JRRAction enum.

And it follows the standard set out by the other packets. No idea if it works, so please check it out.

I find it odd that the IS_BFN packet morphology changed from 'CSize/CType/CReqI/CSubT/CUCID/CClickID/CInst/CSp3' too 'CSize/CType/CReqI/CSubT/CUCID/CClickID/CClickMax/CInst'.

Inst was moved too the last byte, and ClickMax was moved to it's position. I would think there is going to be some BC breaks on that right? Or is it because Inst is exposed but not used that it doesn't matter.
Thanks Dygear but I am already a step further by changing MSO/III/ACR packets to var packets.. For unpacking (packing seems not to be needed), so I can't test this because this would break those packets again :/

Although I did it the sloppy way again, or PHP MacGyver way. Which means that it works, in my own logic Razz

edit: Hhmm I can just ExamDiff this into my version of course. But I skipped the JRR section because I think it doesn't work. Or at least I don't know how to correctly send a packet in your setup. It seems the packing for ObjectInfo is missing.
Quote from cargame.nl :Thanks Dygear but I am already a step further by changing MSO/III/ACR packets to var packets

Get a Github account and commit the code. No reason why we can't share.

Quote from cargame.nl :I skipped the JRR section because I think it doesn't work. Or at least I don't know how to correctly send a packet in your setup. It seems the packing for ObjectInfo is missing.

Haha! You're right! I didn't include the pack function! Woops!
Quote from Dygear :No reason why we can't share.

Hhmm I think my version is not the best approach but I have a GitHub account, however no idea "how to join" PRISM
#18 - PoVo
My solution to packing IS_JRR:

<?php 
class IS_JRR extends Struct // Join Request Reply - send one of these back to LFS in response to a join request
{
    const 
PACK 'CCxCCCxx';
    const 
UNPACK 'CSize/CType/CReqI/CPLID/CUCID/CJRRAction/xSp2/xSp3';
    
    protected 
$Size 16;       # 16
    
protected $Type ISP_JRR;  # ISP_JRR
    
public $ReqI;               # 0
    
public $PLID;            # ZERO when this is a reply to a join request - SET to move a car

    
public $UCID;               # set when this is a reply to a join request - ignored when moving a car
    
public $JRRAction;          # 1 - allow / 0 - reject (should send message to user)
    
public $Sp2;
    public 
$Sp3;

    public 
$StartPos// 0 : use default start point / Flags = 0x80 : set start point
    
    
public function pack() {
        if (
$this->StartPos == null)
            
$this->StartPos = new ObjectInfo();
        return 
parent::pack() . $this->StartPos->pack();
    }
}; function 
IS_JRR() { return new IS_JRR; }
?>

I also had to modify the pack() method in the Struct class similar to cargame.nl:

<?php 
public function pack()
{
    
$return '';
    
$packFormat $this->parsePackFormat();
    
$propertyNumber = -1;

    foreach (
$this as $property => $value) {
        if (!isset(
$packFormat[++$propertyNumber])) break;

        
$pkFnkFormat $packFormat[$propertyNumber];

        if (
$pkFnkFormat == 'x') {
            
$return .= pack('C'0); # null & 0 are the same thing in Binary (00000000) and Hex (x00), so null == 0.
        
} elseif (is_array($pkFnkFormat)) {
            list(
$type$elements) = $pkFnkFormat;

            for (
$i 0$i $elements; ++$i) {
                if(isset(
$value[$i])){
                    
var_dump($value$type$elements$i$value[$i]);
                    
$return .= pack($type$value[$i]);
                } else {
                    
$return .= pack("x");
                }
            }
        } else {
            
$return .= pack($pkFnkFormat$value);
        }
    }

    return 
$return;
}
?>

The line "if (!isset($packFormat[++$propertyNumber])) break;" is needed because PRISM will try to pack the StartObject property even though there is no pack format specified in PACK for it and ends up complaining about a non-existent index.

For me this seems the cleanest solution thus far but I'm wondering if someone can write it any cleaner?

Dygear included the unpack() method in his latest commit. I don't think it's required because LFS doesn't send any IS_JRR packets. IS_JRR is only used for join request responses so it will only be packed.
Quote from PoVo :I also had to modify the pack() method in the Struct class similar to cargame.nl:

The line "if (!isset($packFormat[++$propertyNumber])) break;" is needed because PRISM will try to pack the StartObject property even though there is no pack format specified in PACK for it and ends up complaining about a non-existent index.

For me this seems the cleanest solution thus far but I'm wondering if someone can write it any cleaner?

You shouldn't modify the class function that work's everywhere's for one special case. What you should do, is overwrite that function in the special case only. That way, the special case code is only called when it's needed.

Quote from PoVo :Dygear included the unpack() method in his latest commit. I don't think it's required because LFS doesn't send any IS_JRR packets. IS_JRR is only used for join request responses so it will only be packed.

That's because I'm an idiot and didn't read what the packet was for, I just implemented the packet as far as the structure goes.
#22 - PoVo
Quote from Dygear :You shouldn't modify the class function that work's everywhere's for one special case. What you should do, is overwrite that function in the special case only. That way, the special case code is only called when it's needed.

Haha, that would make a lot of sense!

I kinda forgot the packet class is extending the Struct class Smile
#24 - PoVo
I have made a pull request for all the latest InSim changes required for patch 0.6M.

Currently using this changeset on the RC servers. Works good Smile
..
1

FGED GREDG RDFGDR GSFDG