Hello programmers.
Mod support is coming soon and there are a couple of changes in InSim (updated InSim.txt attached)
Size byte
Most notably, the size byte is now size divided by four. So the value '1' means the packet is size 4 bytes, etc. This does no harm as packet sizes were always a multiple of 4, and now we can have much bigger packets, up to 1020 in size.
I have made use of these bigger packets in a couple of places:
// IS_AXM maximum objects increased to 60 (was 30) - see AXM_MAX_OBJECTS
// IS_MCI maximum cars increased to 16 (was 8) - see MCI_MAX_CARS
(Layout editor now now allows 60 objects to be moved at once)
- The new INSIM_VERSION is 9 (this uses the new size bytes)
- You can still connect using InSim 8 and LFS will use the old size bytes in that case
So that change, while simple in concept, may or may not be quite quick for you to implement, depending on how your InSim program is structured.
Skin ID for MOD vehicles in the CName fields:
You may notice the Skin ID of a mod has 6 characters. So how will this fit into a 3-byte CName? Well, the Skin ID is actually a 6 digit hexadecimal number (a 4 byte integer with zero in the high byte). So if a CName doesn't match any of the official cars, it must be a mod's Skin ID.
Some more logic relating to Skin ID:
If ALL THREE bytes of CName are ASCII A-Z, a-z, 0-9 then it must be an official car. The characters represent a plain text string. Mods are not issued with Skin ID where all three characters are ASCII A-Z, a-z, 0-9.
If not an official car, you can interpret the 4 bytes as an unsigned integer, which when displayed in hexadecimal, will be the mod's skin ID.
A note on byte order:
An official skin prefix has the form ABC0 (0 being the NULL terminator)
If this was reinterpreted as a Skin ID, A would be the low byte, B the middle byte and C the high byte of the 3 byte integer.
Here is a little C code that may explain things more clearly if you like C.
CODE:
Mod support is coming soon and there are a couple of changes in InSim (updated InSim.txt attached)
Size byte
Most notably, the size byte is now size divided by four. So the value '1' means the packet is size 4 bytes, etc. This does no harm as packet sizes were always a multiple of 4, and now we can have much bigger packets, up to 1020 in size.
I have made use of these bigger packets in a couple of places:
// IS_AXM maximum objects increased to 60 (was 30) - see AXM_MAX_OBJECTS
// IS_MCI maximum cars increased to 16 (was 8) - see MCI_MAX_CARS
(Layout editor now now allows 60 objects to be moved at once)
- The new INSIM_VERSION is 9 (this uses the new size bytes)
- You can still connect using InSim 8 and LFS will use the old size bytes in that case
So that change, while simple in concept, may or may not be quite quick for you to implement, depending on how your InSim program is structured.
Skin ID for MOD vehicles in the CName fields:
You may notice the Skin ID of a mod has 6 characters. So how will this fit into a 3-byte CName? Well, the Skin ID is actually a 6 digit hexadecimal number (a 4 byte integer with zero in the high byte). So if a CName doesn't match any of the official cars, it must be a mod's Skin ID.
Some more logic relating to Skin ID:
If ALL THREE bytes of CName are ASCII A-Z, a-z, 0-9 then it must be an official car. The characters represent a plain text string. Mods are not issued with Skin ID where all three characters are ASCII A-Z, a-z, 0-9.
If not an official car, you can interpret the 4 bytes as an unsigned integer, which when displayed in hexadecimal, will be the mod's skin ID.
A note on byte order:
An official skin prefix has the form ABC0 (0 being the NULL terminator)
If this was reinterpreted as a Skin ID, A would be the low byte, B the middle byte and C the high byte of the 3 byte integer.
Here is a little C code that may explain things more clearly if you like C.
CODE:
// FROM HEADER FILE
typedef const char *ccs;
inline int is_ascii_char(char c) // checks if character c is 0-9 / A-Z / a-z
{
if (c >= '0' && c <= '9') return 1;
if (c >= 'A' && c <= 'Z') return 1;
if (c >= 'a' && c <= 'z') return 1;
return 0;
}
int id_is_valid (unsigned int id);
int is_official_prefix (ccs prefix);
ccs expand_prefix (ccs prefix);
ccs contract_prefix (ccs prefix);
// FROM C FILE
char expanded_prefix [8];
char contracted_prefix [4];
int id_is_valid(unsigned id) // return 1 if the supplied id is valid as a mod's skin ID
{
if ((id & 0xff)==0 || // 1st char is zero
(id & 0xff00)==0 || // 2nd char is zero
(id & 0xff0000)==0 || // 3rd char is zero
id & 0xff000000) // 4th char is non-zero
{
return 0; // invalid
}
if (is_ascii_char(id & 0xff) &&
is_ascii_char((id & 0xff00) >> 8) &&
is_ascii_char((id & 0xff0000) >> 16))
{
return 0; // all 3 characters are 0-9 / A-Z / a-z -> reserve this id for official cars!
}
return 1; // ok
}
int is_official_prefix(ccs prefix)
{
return is_ascii_char(prefix[0]) && is_ascii_char(prefix[1]) && is_ascii_char(prefix[2]) && prefix[3]==0;
}
ccs expand_prefix(ccs prefix) // fill a static buffer "char expanded_prefix[8]" and return a pointer to it
{
memset(expanded_prefix, 0, 8);
if (prefix && prefix[3]==0) // valid prefix supplied
{
if (is_official_prefix(prefix))
{
*(unsigned *)expanded_prefix = *(unsigned *)prefix; // official car - direct copy
}
else // mod
{
sprintf(expanded_prefix, "%06X", *(unsigned *)prefix); // regard the prefix as an unsigned integer and expand it as a 6-digit hexadecimal string
}
}
return expanded_prefix;
}
ccs contract_prefix(ccs prefix) // fill a static buffer "char contracted_prefix[4]" and return a pointer to it
{
if (is_official_prefix(prefix)) // official car - direct copy
{
*(unsigned *)contracted_prefix = *(unsigned *)prefix;
}
else // mod - convert the 6-digit hexadecimal string into an unsigned integer
{
unsigned id;
if (sscanf(prefix, "%X", &id) && id_is_valid(id))
{
*(unsigned *)contracted_prefix = id;
}
else // not valid
{
*(unsigned *)contracted_prefix = 0;
}
}
return contracted_prefix;
}