The online racing simulator
[Dev Discussion] UCID and PLID handling
(7 posts, started )
#1 - Krayy
[Dev Discussion] UCID and PLID handling
Currently the InfoPlayer object in Lapper that stores information about a Player is a monolithic object and includes data for bothe the connection and the player on the racetrack. This is why when you have AIs on the track tat you get spammed with race messages as these messages are using a PLID that maps to the InfoPlayer object with the AI owners UCID instead of an individual PLID based object.

This is also proving to be a bit of an issue when trying to implement some of the new InSim functions and also when doing a car takeover.

What I would propose is to create a new InfoConnection object that contains UCID specific information and then when the player joins a race, it instances a new InfoPlayer object that is then associated with the InfoConnection object. This would only really entail splitting the current InfoPlayer object into 2 to split off the Connection specific vars and then adding handlers to do things like create InfoPlayer objects when player joins a race, receive PLID based InSim packets and other bits.

Does anyone have any arguments or opinions on doing or not doing this? My opinion is that it would make Lapper a lot more versatile, particularly if we could use AIs as race participants and treat them as unique Players with no interference with the spawners connection.
You absolutely should do this. InSim, and the LFS engine handles Clients and Players are two separate but connected objects where one is the parent of the other. Where Client would be the parent object, the Player is handled as it's child object. I've handled this as an array of Player objects within the Client object, but in your case you would want to use the struct within a struct approach. By that I mean the same way that MCI can contain multiple CompCar packets, your Client struct should be able to contain 4 Player Structs. Using a pointer jump table, this make it EXCEPTIONALLY easy, and outstandingly quick to lookup information about both a client and a player.

I do recommend still having a separate struct for the players that you can fill with pointers to client object's player. In so far as Players[PLID] would bring you directly to the player object within one of the client object player ids. Again, this makes for a very fast lookup. Just make sure you clean and clear the pointer on disconnect.
It's not like I have in idea what I'm really talking about here, but couldn't this kind of things be done with blinding elegance using pointer arithmetics? I suppose C# doesn't allow for this kind of fanciness though, so I'd go with two hashmaps (C# calls those dictionaries, right?)

Something like

class CUCID_Info {
... some UCID specific stuff...
Dictionary<byte, CPLID_Info> plrs; //Players at this connection
}

class CPLID_Info {
...some PLID specific stuff...
CUCID_Info parent;
}

and as a global storage

Dictionary<byte, CUCID_Info> connections; //All currently active connections
Dictionary<byte, CPLID_Info> players; //All currently connected players

Any CPLID_Info object would be pointed at by both the players dictionary and the CUCID_Info object. This would (IMHO) allow for very fast and easy hopping between UCID and PLID info without any need to iterate through arrays and insane PLID<->UCID matching logic. The price for that would be a bit higher memory consumption, but who cares about that today?

(Feel free to point out how full of shit I've just been...)
C# doesn't have pointers, what the hell? But yeah, you've pretty much made the point I wanted to make with code.
Hello,

Good idea. I have started to do that but i stopped and i forgot why :-(. You can use a hastable to do that in easy way.

Gai-Luron
#6 - Krayy
Probably the easiest way to do this in the current code base would be to replace the UCID variable (currently an integer) in the InfoiPlayer oject with an object of class InfoConnection.

I have most of the code written now, but it does touch about 70% of the other source files as they need to be changed dependng on if they reference a UCID or PLID variable.

Gai, I have a lot of changed code in my Lapper version, so how can we handle merging the code bases if mine is quite a bit moved from 6.0.1.2?

By that I mean I have done a bit of cleanup as well as additions like the new packet types, a new handler for REOrder packets, and I started on reworking how Lapper does its configuration to simplify deployments (lots of config info in the database, not in .ini files)
Quote from Dygear :C# doesn't have pointers, what the hell? But yeah, you've pretty much made the point I wanted to make with code.

C# actually has full featured pointers if you use it in unsafe context, but that's not what is needed here.
The point of my idea was that C# collections contain pointers to objects, not some shallow or deep copies of them. That would allow for an CPLID_Info object to be pointed at by both "players" dictionary and a CUCID_Info object, which, in turn, would allow for going back and froth from UCID to PLID with (IMHO) quite an elegance.

To demonstrate what I mean, output of this code

<?php 
namespace ConsoleApplication1
{
    class 
MyObject
    
{
        private 
string s;

        public 
MyObject(string s)
        {
            
this.s;
        }

        public 
void SetString(string s)
        {
            
this.s;
        }

        public 
override string ToString()
        {
            return 
s;
        }
    }
    class 
Program
    
{
        static 
void Main(string[] args)
        {
            List<
MyObjectmyList = new List<MyObject>();
            List<
MyObjectmyList2 = new List<MyObject>();

            
MyObject s1 = new MyObject("abc");
            
MyObject s2 = new MyObject("def");
            
MyObject s3 = new MyObject("ghi");

            
myList.Add(s1);
            
myList.Add(s2);
            
myList.Add(s3);
            
myList2.Add(s1);
            
myList2.Add(s2);
            
myList2.Add(s3);

            
s2.SetString("xxx");
            
myList[0].SetString("yyy");

            foreach (
MyObject s in myList)
                
Console.WriteLine(s.ToString());

            foreach (
MyObject s in myList2)
                
Console.WriteLine(s.ToString());

            
Console.ReadKey();
        }
    }
}
?>

is

yyy
xxx
ghi
yyy
xxx
ghi

Sorry for the OT as Krayy seem to have figured out a solution, I just thought someone might find this approach useful some day...

[Dev Discussion] UCID and PLID handling
(7 posts, started )
FGED GREDG RDFGDR GSFDG