The online racing simulator
php InSim application demo/POC
(12 posts, started )
php InSim application demo/POC
Here is a bare and dirty concept demo that connects, maintains connection and logs the events, and surprise! CALLS USER FUNCTIONS FOR PACKETS! (something similar to LuaLFS)

This is an early working demo, so don't expect too much from it.

how to run it
Modify config.inc.php (and php_insim_base.php for admin password) and run
> php.exe -q php_insim_base.php

You need a dedicated host to run (config and .bat attached).

Why I do this? So far, I want to make a PHP app for myself. To make it, I need a base application. I hope this can be a base for others and there will be other contributors. Though I like the concept of LuaLFS and it looks very tempting, still I don't want to spread myself into many languages. (Having to work in VBA at my work and at the same time to code something in PHP for hobby, is such a pain...)

P.S. lurLFSd is a nice thing, yet I can't (rely on|wait for) this project.
Attached images
it works!.png
Attached files
php InSim base.zip - 37.8 KB - 172 views
So, here is a simple working demo of the app that maintains a connection and calls back user functions when receiving packets.

You have to name your callback function like CBF_ISP_NCN (callback function for new connection packet) and set standard arguments.

Here the first time I faced the limitations of PHP. It's tempting, but I can't do like in JavaScript:

<?php 
define
("ISP_ISI"1);
...
userfunc[ISP_ISI] = function($param1$param2) {
// code 
};
?>

Anyway, I already have a dirty workaround for this.

Of course, to make a more functional and stable app, I need 1) error handling in the functions to prevent wrong calls from a user 2) connection/LFS failure handling 3) keeping state info in memory so that all of it were available to user functions instantly.

Anyway, I wanted to output a working thing AFAP, and here it is.

Though, I doubt if this thing, with such a complex callback mechanism, can handle 32 cars with 10 MCI packets per second... (40 packets to be exact)
Updated.

1. Added a simple scheduler of the packets to be sent (better to say delayed delivery). Some debugging work needed on this, because sometimes I get one packet twice. I'm out of ideas what's the reason (adding and removing var_dump's and print's in some unknown way made it work properly or not)
2. Added a callback mechanism for text commands.
3. Commented most of the code.

The demo script says "hello" to each visitor (after random number of seconds). If you type "!say" command, it will reply to you.

[edit] Reuploaded the file (serious bugs, corrupted structures).
Each plugin should be it's own file, and there really should be a plugin directory.
Something like this code would make writing plugins for InSim so much easier.


<?php 
php
$plugin
->register('pluginName'1.0'Author');
$plugin->event('pluginName''client_connected''ISP_NCN');
$plugin->event('pluginName''client_pits''ISP_PLA');
class 
pluginName {
    public 
client_connected() {
        
ISP_MST("Client {$PName} has connected - Welcome!");
    }
    public 
client_pits() {
        
$PName get_client_name($PLID);
        
$Laps get_client_lap($PLID);
        if (
$Work == 0# PITLANE_EXIT
            
$Work 'left pit lane';
        if (
$Work == 1# PITLANE_ENTER
            
$Work 'entered pit lane';
        if (
$Work == 2# PITLANE_NO_PURPOSE
            
$Work 'entered for no purpose';
        if (
$Work == 3# PITLANE_DT
            
$Work 'entered for drive-through';
        if (
$Work == 4# PITLANE_SG
            
$Work 'entered for stop-go';
        
ISP_MST("{$PName} {$Work} on lap ${Laps}.");
    }
}
?>

-
(detail) DELETED by detail : double
Quote from Dygear :Each plugin should be it's own file, and there really should be a plugin directory.
Something like this code would make writing plugins for InSim so much easier.

Ok, I'll think about it.

Actually, right now you can already write a bit easier than in your example. The constants are already defined, you don't need to write bare numbers.

<?php 
    $Laps 
get_client_lap($PLID);

// I'd define an array to avoid copying many if's. Just more compact code.
$WorkString = array(PITLANE_EXIT => 'left pit lane',
        
PITLANE_ENTER =>'entered pit lane',
        
PITLANE_NO_PURPOSE => 'entered for no purpose',
        
PITLANE_DT => 'entered for drive-through',
        
PITLANE_SG => 'entered for stop-go');
        
ISP_MST("{$PName} {$WorkString[$Work]} on lap ${Laps}.");
    }
}
?>

Ok, here is a dirty version of plugins system. Thanks to Dygear for the idea. The previous version didn't work actually, because correcting one mistake, I've made another. This time I've tested the app and all the functions, didn't see anything going wrong and didn't change anything then

Delete the previous version, because this one doesn't need anything from there.

So, see the plugins folder for details. One of the plugins co-works with another one. Unfortunately, calling functions from other plugins coudn't be shorter. But now it is possible to have several plugins handling the same packet and interoperating with each other. Dygear's get_client_name($PLID) function and the "database" beyond it can be made with a plugin.

I've avoided making a function like "register_plugin" to minimize and simplify the code. Plugins system uses the same naming convention.

Some settings should be moved from the main scripts into config. This version is less optimized, because it unpacks any packet when receives it. Actually, it's better to decode only if there is a handler for the packet. Need to work on this, but it's late night already, have to work tomorrow.
Quote from detail :Dygear's get_client_name($PLID) function and the "database" beyond it can be made with a plugin.

Ok, then I'll make an amx base, for this.

At this time, I would recomend a plugins.ini file that you can turn on and off plugins (comment them out to take them out of loading, and items that are first on the list are the first to load. Return handlers like, PLUGIN_CONTINUE, and PLUGIN_HANDLED would also be a good idea.
What do you mean by these handlers?

Right now it works the following way: $conn is a Connection class object. $conn->plugin is an array of plugins, for example $conn->plugin["Speaker"] is a Speaker class object. In each plugin object there is a reference to $conn and to $conn->plugin to shorten the queries to them.
BTW, I'm working on the live "database". I thought of referencing the players/connections lists in the classes, like

<?php 
$name 
$this->player[$PLID]["SName"];
$uname $this->connection[$UCID]["UName"];
?>

and cross-referencing them with each other, like

<?php 
$connUsername 
$this->livedbPlayer[$PLID]["Connection"]["UName"];
?>

["Connection"] element is a reference to $this->livedbConnection.

Though, this way looks ugly and requires more code than get_player_name(), suggested by Dygear. I think, I'll stick to references, because right now a standalone function needs to know the objects or to use a general naming convention.
Ok, take the database into account some more. One where the UID or the PLID of the player is the index (what ever one is used more in the packets) from there you can save UName, PName, ULID, PLID, and anything else like penalties, position (X, Y, Z, Place in Race, & Split Currently In), et cetera.


int get_user_ulid(int $plid);
int get_user_plid(int $ulid);
int get_user_lap(int $ulid);
int get_user_split(int $ulid);
int get_user_place(int $ulid);
int get_user_penalty(int $ulid);
int get_user_flags(int $ulid);
array(int x, int y, int z) get_user_position(int $ulid);
string[24] get_user_pname(int $ulid);
string[24] get_user_uname(int $ulid);

That's really all I can think of right now.
Another version, now with Livedb plugin, a "database", which is actually a set of arrays that copy data from some packets. Tested just to function in general. As I've seen, it writes data that seems ok. To test it more, I've added outputting of the whole db into db.log file.

So, Dygear speaks of a special addition that may allow writing text in more readable or more human style than me. I, on the contrary, implemented the simplest interface, just a copy of InSim structures and names, and the values are InSim constants. Consequently you need to know InSim well to navigate well in this db. It's not about my style or minimalizm. I just want to make it work as quicker as possible and leave making a comfortable interface for later. The good point is that knowledge of my db is compatible with InSim, and by learning to work with one thing you learn the other one.

P.S. In the version published yesterday, I've found and fixed an error: unpackStructure didn't work as was supposed with complex multi-level arrays.
Small update: fixed the button function in Sender plugin.

php InSim application demo/POC
(12 posts, started )
FGED GREDG RDFGDR GSFDG