The online racing simulator
I have 3 problems in my insim, and i hope someone helps ;)
Hello
I have found some problems in my insim, using InSim.NET. I actually don't know if these are simple problems, but i don't know how to fix them
Anyway .. those problems are:
1) Sometimes whenever someone spectates/pits, the methods which are supposed to take place for that users happen for another. What i mean is, when (for example) i pit, someone else loses his trip bonus, and sometimes i lose my trip bonus. I've checked the code but didn't find anything that would do that!!

2) In the CompCar, and after getting the MCI updates, the Node stays Zero and doesn't change while the other values like Speed, Coords, Direction, ... get new values whenever the MCI packet is updated. Why does the Node stays Zero??

3) Sometimes i get a bug in the Send method from the InSim class, which is ThrowIfNotConnected().
Is the solution for it using an event Insim.Disconnected?

Thank you so much Smile
oh and btw .. i'm using C#
-
(MariusMM) DELETED by MariusMM : History
2) There are no nodes in open configurations, hence the node number stays at zero.

3) I think the problem is pretty self-explanatory. Send() throws an exception when you try to send a packet without being connected to InSim. You have to decide how to handle this.

1) My guess would be that you are mixing up PLID and UCID somewhere but there is no way to tell what's happening when we cannot see the code.

0) Please... Use the term "InSim" correctly. What you have in not an InSim. InSim is an interface, not some general name for programs that use it... For some reason it annoys me to no end having to read this nonsense over and over....
Thanks for the reply

1) I have one list, and it holds 2 bytes (UCID and PLID) and i have two methods to get the index of a player in the list for each one:

int GetIDbyUCID(int UCID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].UniqueID == UCID) return i;
}
return 0;
}

int GetIDbyPLID(int PLID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].PlayerID == PLID) return i;
}
return 0;
}

and this is where the index is being searched for:

var Conn = Connections[GetIDbyPLID(PLL.PLID)];
----------------------------------------------
var Conn = Connections[GetIDbyPLID(PLP.PLID)];

2) yeah, i'm using AS2X .. maybe that's why

3) ok thnx, just making sure about that :P
Quote from Zazcoisa :Thanks for the reply

1) I have one list, and it holds 2 bytes (UCID and PLID) and i have two methods to get the index of a player in the list for each one:

int GetIDbyUCID(int UCID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].UniqueID == UCID) return i;
}
return 0;
}

int GetIDbyPLID(int PLID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].PlayerID == PLID) return i;
}
return 0;
}

and this is where the index is being searched for:

var Conn = Connections[GetIDbyPLID(PLL.PLID)];
----------------------------------------------
var Conn = Connections[GetIDbyPLID(PLP.PLID)];


This is, unfortunately, an incorrect design.

There can be multiple PLIDs per one UCID and PLIDs can jump between UCIDs - read the excerpt from InSim.txt MariusMM quoted. A possible (but not the best) solution to the problem is this:



Dictionary<byte, List<byte>> UCID_to_PLIDs_List;
Dictionary<byte, byte> PLID_to_UCID_List;

byte GetUCIDforPLID(const byte PLID) {
if (!PLID_to_UCID_List.ContainsKey(PLID)) /
// Throw an exception because this PLID is not known
}

return PLID_to_UCID_List[PLID];
}

List<byte> GetPLIDsOfUCID(const byte UCID) {
if (!UCID_to_PLIDs_List.ContainsKey(UCID)) {
// Throw an exception because this UCID is not known
}

return new List<byte>(UCID_to_PLIDs_List[UCID]);
}


Thank you, but i have the connections list as a List<clsConnection>:
List<clsConnection> Connections = new List<clsConnection>();

and it contains:
public byte UniqueID;
public byte PlayerID;

so your way isn't like mine.
Could you please do it in that way?
Should i change
public byte PlayerID;

to something like this
public List<byte> PlayerID;

?

Or should i create two different lists, each contains one of the IDs? (one for UCID and the other for PLID)
Quote from Zazcoisa :Thank you, but i have the connections list as a List<clsConnection>:
List<clsConnection> Connections = new List<clsConnection>();

and it contains:
public byte UniqueID;
public byte PlayerID;


Is this something you just copied from somebody else's code, because this is a rather poor design. If you change the type of Connections to Dictionary<byte, byte> and use PLID as a key, you can remove the whole PLID lookup loop and do just "byte UCID = Connections[PLID]" to get the UCID. You will still need the UCID lookup loop which should return a list of all PLIDs behind one UCID instead of just the first entry in the list. It could then look like this


List<byte> GetPLIDsByUCID(const byte UCID) {
List<byte> PLIDs = new List<byte>();

foreach (KeyValuePair<byte, byte> e in Connections) {
if (e.Value == UCID) {
PLIDs.Add(e.Key);
}
}

return PLIDs;
}

Ok thank you and sorry for the late response.
I'll change the code from List<clsConnection> to Dictionary<byte, clsConnection>.
I've already started it and found a code for Spark Cruise, so i took a look at his codes, and saw that he uses dictionaries too.
So, i've made two dictionaries:
Dictionary<byte, User> Users = new Dictionary<byte, User>();
Dictionary<byte, IS_NPL> Players = new Dictionary<byte, IS_NPL>();

Let me finish it then i'll see if the problem is fixed or not. Smile
Wow .. that was fast O.O
I'm facing a problem with the TOC packet.

I have this list:
Dictionary<byte, IS_NPL> Players = new Dictionary<byte, IS_NPL>();

and when the NPL packet is received, it gets added to the list:
Players[NPL.PLID] = NPL;

Now .. when a player takes over a car, the PLID should be transferred to the new player. I can remove the whole record of that NPL (Players.Remove(old.PLID)) but I can't add a new NPL packet and change the NPL.CName or NPL.PLID because all the bits in the packet are set as readonly.

Also I tried to request a new NPL for the new player, with this code:
Insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = ConnNew.UniqueID });

but i get this error: "Collection was modified; enumeration operation may not execute.".

Sorry for all that, but it's a thing that must to be done
Thanks Smile
Saving the IS_NPL packet (or any other InSim packet) is even more wrong that the previous solution. InSim packets are meant only to deliver information to or from LFS. You are not supposed to store them for later use. The right thing to do is to copy the information you need from the packet to your own data structures and throw the packet away.

Why can't you try out what I suggested and keep a "conversion maps" for UCIDs and PLIDs? That should be reasonably easy to manage and use.
I think that what I'm doing is the same thing and that it won't matter much, right?
There are obviously multiple solutions to this problem, some of them are better, some other are worse. Worse solutions will be more error-prone and you'll have to write more plumbing code to keep things working. I would've probably done something like this. It's probably not the best solution possible because I came up with it in like 5 minutes. It's just supposed to show that UCID and PLID handling is quite easy if you design the application neatly.



using LFS_Connection = System.Collections.Generic.List<byte>;

class LFS_Player {
byte PLID;
byte UCID;
bool inPits;

class GameData; // Something specific to your game

LFS_Player(byte PLID, byte UCID) {
this.PLID = PLID;
this.UCID = UCID;
}

void takenOver(const byte UCID) {
this.UCID = UCID;
}

void enteredPits() {
inPits = true;
}

void leftPits() {
inPits = false;
}

...
}

Dictionary<byte, LFS_Player> activePlayers;
Dictionary<byte, LFS_Connection> activeConnections;

void on_IS_NCN(ncn) {
if (activeConnections.ContainsKey(ncn.UCID)) {
// This connection is already registered, this should not happen. Throw an error
}

activeConnections[ncn.UCID] = new LFS_Connection();
}

void on_IS_NPL(npl) {
// If the PLID is already registered, player left pits
if (activePlayers.ContainsKey(npl.PLID)) {
activePlayers[npl.PLID].leftPits();
return;
}

// Register new player within the players' list
AddNewPlayer(npl.PLID, npl.UCID);

// Add PLID of the new player to the list of PLIDs belonging to the respective UCID
if (!activeConnections.ContainsKey(npl.UCID)) {
// UCID of this player is not registered. Throw an error as this cannot happen
}
activeConnections[npl.UCID].Add(npl.PLID);
}

void on_IS_PLL(pll) {
if (!activePlayers.ContainsKey(pll.PLID)) {
// Throw an error, this cannot happed
}
const byte UCID = activePlayers[pll.PLID].UCID;
RemovePlayer(pll.PLID);
RemovePLIDfromConnection(pll.PLID, UCID);
}

void on_IS_TOC(toc) {
RemovePLIDfromConnection(toc.PLID, toc.OldUCID);

if (!activePlayers.ContainsKey(toc.PLID)) {
// This should never happen, throw an error
}
activePlayers[toc.PLID].TakenOver(toc.NewUCID);

if (!activeConnections.ContainsKey(toc.NewUCID)) {
// This should never happen, throw an error
}
activeConnections[toc.NewUCID].Add(toc.PLID);
}

void on_IS_CNL(cnl) {
if (!activeConnections.ContainsKey(cnl.UCID)) {
// This should never happen, throw an error
}
const LFS_Connection c = activeConnections[cnl.UCID];

// Make sure that we do not have any players stored for this connections
foreach (byte PLID in c) {
if (activePlayers.ContainsKey(PLID)) {
// Throw a warning, all players for this connection should have been removed already
RemovePlayer(PLID);
}
}

activeConnections.Remove(cnl.UCID);
}

void AddNewPlayer(const byte PLID, const byte UCID) {
if (activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}
activePlayers[PLID] = new LFS_Player(PLID, UCID);

...
}

void RemovePlayer(byte PLID) {
if (!activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}

...

activePlayers.Remove(PLID);
}

void RemovePLIDfromConnection(byte PLID, byte UCID) {
if (!activeConnections.ContainsKey(UCID)) {
// This UCID should be registered, throw an error
}

activeConnections[UCID].Remove(PLID);
}


I've changed the code to use the Dictionary, and i'll test it
If anything goes wrong, i'll write about it here

Thank you MadCatx Wink
*WE ARE WORKING WITH SAME PROGRAM*

Hello

I have a problem with my InSim, viz it confuses users. For example, the bonus is moving for a person who is in spectators, some user use !showoff command and insim is showing other user stats, when hes connecting insim says other user name "*playername* connected" etc. It does not take someone else's stats. In database it looks like always, nothing changed for both users, not copying stats to other.

Its like one user take other specific user (not random one) and uses his ID?

*Edit: This one user who "take other user acc" is not updated in database, like not online on server right now, there is time from last "working" connect.*

Where may be problem and which part of code You want to see?
Quote from heawy :*WE ARE WORKING WITH SAME PROGRAM*

Hello

I have a problem with my InSim, viz it confuses users. For example, the bonus is moving for a person who is in spectators, some user use !showoff command and insim is showing other user stats, when hes connecting insim says other user name "*playername* connected" etc. It does not take someone else's stats. In database it looks like always, nothing changed for both users, not copying stats to other.

Its like one user take other specific user (not random one) and uses his ID?

*Edit: This one user who "take other user acc" is not updated in database, like not online on server right now, there is time from last "working" connect.*

Where may be problem and which part of code You want to see?

I'm pretty sure that the discussion above already explains what could be wrong and provides some suggestions how to fix it.

FGED GREDG RDFGDR GSFDG