The online racing simulator
Searching in All forums
(303 results)
Bokujishin
S3 licensed
I must say I didn't think of the possibility to just forward the data to a web client, and I guess you may want to avoid too much data processing there. In my live gaps implementation (not delta), I keep track of the last updated node for each car, and only update a node's timestamp when the node from the IS_MCI packet is different from the last updated one. For gaps between cars, and a decently smooth map animation, 250ms between packets is a decent interval, you can interpolate map positions from there using heading and speed (which is effectively a 2D version of the velocity vector you proposed), and I don't think there's much point in updating gaps in the standings more often than once or twice per second anyway.

If you want some telemetry data for all cars, running IS_MCI at 100Hz (with timestamps and pitch and roll included, instead of just heading) should be good enough (the additional angles would help showing cars rolling over too, if that's needed). You can also prune data from the stream of IS_MCI packets to only keep new nodes (as explained above).

For delta itself, my implementation uses OutSim (because it relies on the indexed distance, which I can recreate approximately from the PTH file (this requires creating an accurate PTH file for custom layouts), and delta only applies to the local car anyway, unless you want to display the delta for every car e.g. during qualifying), and I just compare the reference lap and current lap distances at the current timestamp offset by lap start timestamp, so we don't need nodes here. This assumes that you're driving close to your best time, though, since it can get pretty inaccurate otherwise, being distance-based.
Bokujishin
S3 licensed
I like the general idea of what you're proposing here, but I think there are some bits that can be removed for optimization:

The Cars struct doesn't really need UCID or Info (as long as that Info byte only contains the AI flag, at least), since those can easily be retrieved from the PLID.

Similarly in IS_GPS, Info, PLID, and SubT (what is it supposed to represent?) can be removed, which saves us 4 bytes with the spare Sp0. Although to be honest, I think this could also be achieved with an upgrade IS_MCI (or rather CompCar, which should include pitch and yaw in addition to heading).

Overall, I think your proposed IS_GPS, CarInfo, and Cars structs overlap a bit too much, and similar info could be retrieved by adding pitch and yaw to CompCar, as well as timestamps to IS_MCI. The tracking of timestamps at each node could probably be left to InSim developers (I did that myself, I know KingOfIce did too - not sure how exactly, but likely the same principle), but we would really need to be able to load custom PTH files via InSim for this to work in custom layouts.

And another hurdle is the lack of a signal for race start, which, while it helps prevent perfect starts via InSim, also prevents proper time tracking (even in hotlap mode, where we don't know when the finish line is crossed for the first time). Having a packet sent a few seconds after race start, and including the timestamp of the start, could be pretty nice for this.
Bokujishin
S3 licensed
I certainly hope that turning the headlights off during the night will disable the "physical" lights, not just the textures, otherwise things will look very weird. Your first question is interesting though, as it wouldn't be so surprising that lights are "optimized out" during day time; however, I think that would be a mistake in some situations, e.g. going through a tunnel/underpass (KY3, South City) or just into the shadows of buildings in South City in some lighting conditions. There are also more tunnel-like driveable areas in the updated Kyoto and South City.

Another concern I have regarding headlights is how far they can illuminate: I believe AI turns on the high/full beam at night, and well, that doesn't really look like high beam lights to me, but rather low beam. Regulations may vary for each country, but high beams should typically illuminate at least around 100m, while low beams are around 30m (at least that's what regulations say in France). In the videos, it looks like the lights barely reach 30m, let alone 100, which might make racing even more difficult than it should already be at night.

And on a related note: mods - I assume all vehicles will have either one or two "physical" lights, but will we be able to set their position (and orientation) manually? I imagine beam asymmetry is not too much of a concern and doesn't really need to be accounted for.

EDIT: To be fair, even from real life aerial views at the likes of Spa 24h or Nurburgring 24h, the visible illuminated spot on the road in front of the car doesn't reach that far either, but still a bit more than what we can see here. However, in the attached screenshot, the yellow car at the front doesn't appear to be illuminated by the white car's lights at all, when they look like they should be around 25m apart.
Last edited by Bokujishin, .
Bokujishin
S3 licensed
Quote from Scawen :I guess we'll find out in public testing. Smile

Graphics and physics are both more demanding than in the old version but they are split over two CPU cores instead of just one.

Yes we will... ready to test and report Big grin

Also good to see (at least from what I can see in the 2 videos) that AI seem to have a smoother transition into the pitlane. In the current public version, in some configurations, AI can swerve pretty heavily to get into the pitlane, or when exiting, they will brake and turn (e.g. BL1 into chicane). Or maybe it's just the updated tracks that have their blend lines reworked?

On the multithreading front, I was wondering: you say graphics and physics are split over 2 cores, but aren't you using more threads now for various things? Is the out-of-pit stutter mitigation only about spreading the loading over several frames, but not several threads? I was also wondering about splitting car physics over a few (physical) cores, say 16 cars per core or something.

But in any case, I just hope you (and Eric) are now closing in on the finishing touches leading to the test patch, so we can both enjoy it and hopefully have some useful feedback for you.
Bokujishin
S3 licensed
Hi there, here are a few punctuation issues (missing spaces) I found using regexes:

Question marks:
French.txt:3a_exitprog Quitter LFS?
French.txt:3a_endonlin Finir le jeu en ligne?
French.txt:3a_levonlin Quitter le jeu en ligne?
French.txt:3h_kickplyr Expulser le joueur %s^8? (%s^8)
French.txt:3a_deletset Supprimer le setup?
French.txt:3a_deletcol Supprimer les couleurs?
French.txt:3g_deletrep Supprimer le replay?
French.txt:3a_exitnosv Quitter sans sauvegarder?
French.txt:3a_delchnlq Supprimer le canal?
French.txt:3a_clrall_q Effacer tous les objets de la configuration?
French.txt:3g_delete_l Supprimer la disposition?
French.txt:3g_lockques Verrouiller Live for Speed?
French.txt:3a_overwrex Remplacer le fichier existant?
French.txt:3g_deleteex Supprimer le fichier existant?

Exclamation marks:
French.txt:3g_not_time Vous n'avez pas fini dans les temps!
French.txt:3b_wlcmxinr Bienvenue! Il y a %d pilotes dans le salon
help_French.txt:^3Bienvenue sur Live for Speed!^8

I looked for "?", "!", ":", and ";", so those should be all occurrences (there are some for ":", but they're not used as punctuation, so those are fine as is).
Improve ease of finding info in InSim documentation
Bokujishin
S3 licensed
Anyone who has read through the InSim.txt doc, either to make an InSim library or create an InSim app from scratch, knows that parts of the documentation are a bit difficult to parse, because there are many mentions of "see below", but how far below we need to look is not always obvious.

Using a regex search, I found 50 occurrences of "see below", and I believe 14 of them could use some rewording, or directly reference the corresponding enums. The rest are ok as the corresponding info is almost always directly following the "see below" mention.
  • struct IS_SFP: "Other states must be set by using keypresses or messages (see below) → this one should reference TEXT MESSAGES AND KEY PRESSES
  • struct IS_RST: "race flags (must pit, can reset, etc - see below) → biggest offender, you have to scroll 700 lines to find the corresponding info; this should reference the HOSTF_ enum
  • struct IS_CNL: leave reason → should mention LEAVR_ enum
  • struct IS_LAP, IS_SPX, and IS_PIT: penalty → should mention PENALTY_ enum
  • struct IS_PLA: Fact → should mention PITLANE_ enum
  • struct IS_CCH: Camera → should mention VIEW_ enum
  • struct IS_PEN: OldPen, NewPen, and Reason → should mention PENALTY_ and PENR_ enums
  • struct IS_PFL: Flags → should mention PIF_ enum
  • struct IS_FIN and IS_RES: Confirm, Flags → should mention CONF_ and PIF_ enums
  • struct IS_UCO: UCOAction → no description, should add "see below" and/or mention UCO_ enum
  • BUTTONS: "You can also make buttons visible in all screens - see below" → this should probably mention the Inst byte or reference INST_ALWAYS_ON, as the relevant info is buried in the middle of everything else (buttons are a complex subject with dense documentation).
More of a nitpick, but ALLOWED CARS also has 2 occurrences with SMALL_ALC reading "cars (see below)", with the IS_PLC struct in-between; the car list itself could use a "// Cars" title or something.

And a bonus one, may be intended: CAR LIGHTS uses the Switches word everywhere, like CAR SWITCHES - I was just wondering if it should be Lights instead, or if Switches was intended?
Bokujishin
S3 licensed
Had another read here after some conversation on Discord, and noticed I forgot to link to Scawen's mention of going for 16-byte objects one day: https://www.lfs.net/forum/post/2028120#post2028120

The additional data space could then be used for added precision for pitch for some concrete objects, maybe allow more colors for some objects, could also help store more variants of the letter signs (maybe even some symbols?), etc.
Bokujishin
S3 licensed
How open would you be to opening the development/maintenance of those "auxiliary" tools to the community? I'm not volunteering, but I'm sure some people would be interested. This would probably be best handled by giving access to a select few trusted people, and only disclosing relevant parts of the codebase.

While I'm honestly not certain about the Relay (but I do know it has a different handling of packet size Big grin), the REST API seems to be quite popular: I was told that's what is used to authenticate people on the LFS Discord server, and it's also very handy for fetching data about existing mods.

On the mods side, there are even a few things that I, and most likely the rest of the community (cruise server InSim devs in particular), would like to see:
  • the ability to fetch multiple mods per request: currently, we can get the mod list in a single request, but only a single mod with full details, which means we have to perform thousands of requests to update data for all mods; including the full details in the whole list, or fetching multiple skinIDs would help both ends.
  • there seem to be missing fields: for instance, we cannot get the Approved status of a mod from the API.
If Victor is not interested in maintaining those anymore, and to avoid distracting you even more from your own tasks, maybe it would be a good option to let some of us help in those areas?

Just for reference, I made a REST API demo for Godot InSim, fetching the mod list and then details about a select few mods - cruise server InSim devs are actually feeding entire vehicle databases from those requests.
Last edited by Bokujishin, .
Bokujishin
S3 licensed
Getting people to read is probably the biggest challenge in dev, or any business, really. Or not even in business: take any live stream of a race; even if the laps are displayed on the screen, you can be sure someone in the chat will ask how long the race is.

The main thing you can be sure people will read is API documentation, when they need to implement the API Big grin and even then, some parts may be skipped over, willingly or not...

But surely, if the test patch/next update has a flashing button for the unlock code, I expect people will notice it more easily.
Bokujishin
S3 licensed
Quote from cargame.nl :The original answer was longer and gave both 58 and 59 as its a matter of interpretation. 20 characters, 15, 10, even 5 is ridiculously long for the purpose which is a temporarily handshake, not even a password. But keep focusing on the things which do not matter at all in a discussion, this "community" will get "somewhere" 🫠

I don't know why you felt the need to mention my answer as "focusing on the things which do not matter": you provided a number of combinations (generated by AI, but that doesn't matter in the end), which was wrong, I just pointed that out...

Your follow-up with the updated version does give the right answer, okay (but we didn't really need the whole reasoning, 58^20 was ok from the beginning, the "result" the AI gave was just wrong), now back to the "things that matter": 20 characters is way too long, I guess? This is a code you're supposed to copy-paste anyway, how can it be a problem? Should Scawen make a system that generates 10 characters or less, so people who copy the code by hand have an easier time? Is it a sensible thing to do when inputting the unlock code is something you're supposed to do once and forget about it? People who need to regularly get a new code probably should either get the email on their PC to copy-paste, or share their phone's clipboard via wifi or any other means.
Bokujishin
S3 licensed
Yeah, first of all, why 59? 2*26 letters + 10 digits is 62, remove O, 0, I and l and you get 58.
Then the result itself is wrong: 59^20 is 2.612 403 355 × 10^35, while the AI basically said 7.573 809 985 × 10^33 for some reason...
and 58^20 = 1.855 922 647 × 10^35
Bokujishin
S3 licensed
Random guess here, but if we assume you made a mistake when copying the code manually, and it also didn't work with Ctrl+C, could you maybe have selected the space before the code?

If that's the case, I would suggest the unlock code email display the code on its own line, rather than after a colon and a space (although double-clicking should select the code without the surrounding spaces).
Bokujishin
S3 licensed
There's a pinned thread for this already: https://www.lfs.net/forum/thread/111761-Officially-licensed-vehicle-mods

The Ferat Vampire is missing from that list, though.
Bokujishin
S3 licensed
Just for reference, as a real example, here's a diagram for the Monza circuit (from 2019):
https://www.reddit.com/media?url=https%3A%2F%2Fi.redd.it%2Ftcn3vcy35nk31.jpg

You can spot those LED panels in the F1 pole lap video from last year:
https://www.youtube.com/watch?v=pr1kXumP3dk

From a very rough measurement, there's about 500m between panels 14 and 15 just before T11; on the other hand, panels 11 and 12 are only separated by about 150-180m.

This video also helps to spot the panels (2022):


Also, the LED panels don't actually stay on, they are either off or blinking (or displaying one of the other symbols/messages), every flag blinks at 2Hz, including the double yellows, which is the only flag using the diagonal/triangle shape.
Bokujishin
S3 licensed
Quote from Scawen :Does anyone have any good information about how frequently the LED boards should be placed around the track?

This is from the FIM rather than the FIA, but the wording is similar to what I've seen in a few videos on this matter. In section 9.2, the general idea is that LED panels delimit each marshalling sector (with one panel at the start of each sector), the maximum distance between panels is 250m, and each sector should have line of sight to the previous and next sectors.

For some more details about the panels themselves, I found this FIA document, with Appendix 2 showing the standard messages in addition to the flags (but solid colors and "double-yellows" should be enough, with the standard flashing frequency being 2Hz rather than 1Hz as I suggested before).

Edit: Oh and to keep up with my usual "let's ask for one more thing" habit: if/when you do add the ability to control the LED panels, having them available as layout objects would be great (they're much more visible than standard lights, especially since relatively small light sources are a common problem in games, where they're barely or not visible at all despite being extremely bright, because of their sub-pixel size or when they cover few pixels, like tail lights and stop lights do already, since I doubt the graphics update will solve this despite the reworked emissive materials).
Last edited by Bokujishin, .
IS_BTN rendering order is inconsistent, and the state of LFS text encoding
Bokujishin
S3 licensed
We all know that text encoding in LFS is a bit peculiar, as it relies on the very old CP1252 code pages system from the 90s. Scawen himself is aware of this, and has said a few times (even back then in ~2005) that Unicode would probably be the way to go to support more languages. Now in 2025, LFS is still using code pages, and has even expanded their use to support more languages, such as Chinese, Japanese, and Korean, among others. I believe this happened because it was the easiest way to add support for those languages at the time; while Unicode should be the better solution, implementing it may require an enormous amount of work, and there are definitely other priorities right now.

Still, those code pages bring a few issues with them:
  • Limited language support, as only the available code pages are supported, and I doubt there even exist enough code pages to support most languages.
  • Limited character support: I don't think supporting emoji is a goal here, but there are still many unsupported Unicode characters (basically anything not in the code pages).
  • InSim libraries have to implement a UTF-8 to LFS (and LFS to UTF-8) conversion, as the entire world uses Unicode today ("As of July 2025, UTF-8 is used by 98.7% of surveyed web sites.").
  • For LFS itself, while they still work, they do represent a huge technical debt, where using UTF-8 should make things easier, but changing code pages to UTF-8 is becoming more and more difficult and time consuming.
From reading some older forum posts, I gathered that LFS implements its own font system, because at the time, it was difficult to find free fonts that supported enough characters - this should be a non-issue today, with fonts such as the Noto family supporting a vast amount of characters (possibly through the many Noto fonts dedicated to specific languages), and the general availability of free or even open-source fonts.

-----

Anyway, this is not another "please add Unicode support" thread (although I do want to see Unicode support Big grin), I just made this thread as a recap of sorts of the current situation, and to add an interesting issue I found just yesterday while experimenting with InSim buttons to try and draw road signs.

Take a speed limit sign for example (Europe style): the sign is circular, with a white background, a red border, and black text stating the speed limit. We should be able to draw such a sign using 3 IS_BTN packets. LFS even supports the characters we want to use for that: ● for the background, ○ for the border, and digits for the text (for better control over border thickness, and due to general quality of large text rendering, I ended up using ● for the border as well, resizing the button appropriately). My understanding of InSim button z-order, through earlier testing, has been that buttons with a lower clickID are rendered first, and therefore buttons with a higher clickID appear on top. This is generally true... but not always!

Trying to render my speed limit sign, the text is nowhere to be seen, but if I add more text so it spills out of the sign, I can see it being rendered behind the sign, despite having a higher clickID (in the above example, the text reads "505050"). It would appear that characters from different code pages do not follow the clickID z-order, which becomes a headache when dealing with buttons. (for the record, in the above example, the border button has ID 0, the background button has ID 1, and the text button has ID 2)

Even better, this also applies to characters in a single button: in the following example, I created 2 buttons, same position, same size, with texts "^0●a" and "^7b", and here's what the result looks like:

We only have 2 buttons here, but the "b" character appears both in front and behind characters from the other button, simply because they're from different code pages!

It would be nice to get more info about the rendering logic, or whether this can be fixed for consistency, as it unfortunately makes it impossible to draw those signs, or any other kind of button combination that would rely on characters from different code pages (in this example, ● is converted to a Japanese code page character as [94, 74, 129, 156]).
Bokujishin
S3 licensed
Quote from Scawen :I think they should be individually or globally controllable by setting a specific colour or two flashing colours via InSim and using an ID number in some InSim packet.

I guess a global usage would be good, to set all with one packet (e.g, red flag?) but individual would be useful too (blue, yellow flags?).

I'm guessing at this point that monochrome colour for the whole board is enough as it would be much easier to implement than any patterns/

I think this could work with an identifier specific to lights/LED boards, 241 or something, with identifier 255 used to control all of them, and 0 to some value to control individual ones - which controls which one can be subject to some debate, as it could be numbers along the layout (but that could depend on the layout itself), or fixed numbers that we would need to list manually to get the proper lights/boards for our current layout.

As for the monochrome vs 2-color boards, I suppose the current way those are made corresponds to a single light bulb, and as such they're monochrome - switching to 2 separate textures/emissive textures (don't know what you're using, both currently and in your dev version) separated diagonally would work akin to 2 light bulbs and could be very nice to have, but probably not the priority.

I would even say that, in my opinion, being able to set lights to a flashing state would be more important, but I'll let others give their opinions about that.

Quote from kristofferandersen :I'm thinking this is related to network latency, as i haven't ran into this issue at all with my timers/states. As you already said, it'll immidiately revert due to the new packet arriving.

If that's network latency, I would expect InSim buttons (sent just after the corresponding IS_OCO packets) to also have some kind of issue, but they're mostly perfect there, so it's very likely there's something specific to lights or IS_OCO packets.

I would make a small video clip showing the issue, but I won't have access to my actual PC for a few days, so I'll try to do that later this week. I'll also take this opportunity to check whether layout lights have the same issue.
Custom penatly times and the ability to send IS_PEN packets
Bokujishin
S3 licensed
Penalties are currently limited to drive-through, 10s stop-and-go, 30s, and 45s. I think it would be desirable to be able to set lower time penalties, typically 5s and 10s, and allow them to stack.
It would also be nice if the duration of the stop and go could be adjusted, although I think this is less of a priority.

Additionally, having the ability to send IS_PEN packets would be really useful: right now, the only way to apply penalties is through the /p_dt, /p_sg, /p_30, and /p_45 commands; if instead we could send IS_PEN packets, we could not only choose the penalty type (and duration if custom times are added), but also set a penalty reason ("given by admin" being the only reason given for the /p_* commands), so we could have penalties given for speeding, and explicitly stating it as such.

Some other packets are already including the current penalty for a driver, such as IS_LAP, IS_SPX, IS_PIT; IS_RES also includes the penalty, which could then be the total penalty time obtained throughout the race. Sending IS_PEN packets could also be used to reapply penalties to a driver pitting or losing connection and rejoining.

On the technical side of things, ReqI could be used in IS_PEN to either set a penalty, or request a driver's current penalty (or maybe add a SMALL_PEN for that purpose). When a penalty is applied, InSim would send a reply IS_PEN just like it does already for penalties applied by the game.

OldPen would likely be zero, while NewPen would be the penalty to apply, and the Reason could also be set.
If NewPen can only have a limited amount of predefined values, I would suggest adding PENALTY_TIME, so we could set the penalty time in the current spare Sp3 byte. Maybe also PENALTY_REMOVE_TIME to remove a time penalty, as we would want to be able to handle that too, and have time penalties and DT/SG penalties at the same time.

Confirmation flags could add a new, generic CONF_PENALTY or CONF_PENALTY_TIME value, instead of (or in addition to) the current 30 and 45 seconds.

As a side note, time penalties are already implemented in some capacity, as hitting an object on an autocross layout adds a 2-second penalty, although autocross is a bit of a special case.
IS_OCO additions for improved lights control
Bokujishin
S3 licensed
To my knowledge, there are currently 2 issues with IS_OCO packets and lights in general:
  • Response timing to IS_OCO packets is erratic at best (sometimes the lights switch almost immediately, sometimes you have to wait much longer, to the point that flashing lights (changing state every 0.5s) may keep the commanded light on or off for more than a full second (likely because it does change state at some point, but immediately reverts because of the new packet)).
  • We don't have enough working and controllable lights (pit entry/exit, track-side lights (or LED panels for Blackwood).
The first issue forces InSim developers to use "backup lights" for custom starts (which isn't too bad in itself, as having GUI/HUD lights is generally a good idea), because the real lights typically change state late and are not reliable for reaction time (I won't get into 5-red-lights style start lights here, although having those on all tracks would be good as well). The issue is easily noticeable when sending a message right after sending the IS_OCO packet.

The second issue, which hopefully is planned to be addressed in the future (the lights are there after all, so we could have them accessible to InSim with index values other than 240, or identifier values for index 240) would really help to make the track more alive (having green lights/LED panels during a safety car period feels wrong, after all, and being able to use the blue lights at pit exit (or a layout object with a blue light) would also help).

Now for the proposed changes:
  • If possible, having lights react more quickly to IS_OCO packets would be appreciated, as I don't really understand why they wouldn't be updated as soon as the packets are received. By the way, the issue is only visible with host InSim apps, in local apps, the changes are immediate.
  • Whether the above can be addressed or not, it would be nice to be able to set lights to a flashing state, so we don't have to repeatedly send on/off IS_OCO packets (a period of 1s (0.5s between state changes)) should work for most scenarios.
  • Valid index values are currently 149 (with 150 and 151 already reserved for new layout objects) and 240; just like layout objects have 64 identifier values, having some of those for track-side lights seems like a good option for controlling them.
As an additional note to that last point, maybe more lights could be added on official tracks; I checked around Westhill, the National configuration has 2 of those, and International has 4. I don't know how those lights are supposed to be placed in real life, but there is no light at all between the point both configurations converge and the main lights at the finish line, I feel there should be at the very least one.
Bokujishin
S3 licensed
As a quick module development introduction, here are some guidelines, virtual methods for module management, InSim callbacks, and what I consider to be best practices.

Modules are Godot scenes based on a MarginContainer, with a script inheriting GISModule. The only thing a module is required to do is provide a name for itself, in the _initialize_module() virtual method, which must return a String. After that, modules are free to do whatever they want within the possibilities offered by Godot: logic only, 2D graphics, or even 3D graphics.

While Godot InSim provides signals to connect to, GIS Hub connects itself to those signals, and provides callback functions instead, that you need to implement. For instance, you don't manually connect to the isp_mso_received signal, but directly implement the _on_isp_mso_received() callback.

GIS Hub provides wrapper functions for all Godot InSim helper methods that send packets (send_message(), add_button(), etc.); helper methods that are only used to get data or otherwise don't result in sending packets have no wrapper, and should instead be accessed via the hub_insim variable available to all modules.

Virtual methods for modules include the following:
  • _initialize_config(): Assign a custom module config class to your module.
  • _initialize_module(): Assign a name to your module, and optionally perform initialization before adding the module to the scene.
  • _ready_module(): Perform scene initialization, called when the module is first enabled.
  • _load_config(): Define steps for loading module configuration (such as updating the module's GUI).
  • _save_config(): Define steps for saving module configuration (such as updating values from the GUI). Call save_config() (no underscore) when you want to update the saved configuration.
  • _on_insim_connected(): Called when InSim connects to LFS.
  • _on_insim_disconnected(): Called when InSim disconnects from LFS.
  • _on_module_enabled(): Called when the module is enabled. If InSim is connected, _on_insim_connected() will also be called.
  • _on_module_disabled(): Called when the module is disabled. If InSim is connected, _on_insim_disconnected() will also be called.
  • _on_module_sent_custom_data(): Called when a subscribed module sends custom data, that you can then handle here.
The following is a very basic module example, which sends a message upon InSim connecting (or enabling the module if InSim is already connected), and logs incoming messages to the screen, using a RichTextLabel:

class_name MyFirstModule
extends GISModule

@onready var rich_text_label: RichTextLabel = %RichTextLabel

func _initialize_module() -> String:
return "My First Module"

func _on_insim_connected() -> void:
send_message("Hello GIS Hub!")

func _on_isp_mso_received(packet: InSimMSOPacket) -> void:
rich_text_label.append_text(
LFSText.convert_colors(packet.msg, LFSText.ColorType.BBCODE) + "\n"
)

Now for some "best practices", I would recommend the following:
  • Naming: Name your module class "ModuleMyCustomModule", and your module config "ModuleMyCustomModuleConfig", to avoid naming conflicts. You can return whatever you want in _initialize_module(), but should likely stick to "My Custom Module".
  • Typing: I strongly recommend that you use typed GDScript as much as possible, as this helps both with code autocompletion and catching errors. The GIS Hub project considers untyped variables as errors, and also errors on most "unsafe" GDScript warnings.
  • Code order: You should ideally follow the official GDScript style guide as a general rule. For GISModule virtual methods, I suggest the following order: _initialize_config(), _initialize_module(), _ready_module(), remaining virtual methods (grouped by theme, such as _load_config() and _save_config(), or ordered alphabetically). After that, GISModule callbacks (so all _on_isp_xxx_received() methods) and remaining overridden methods, then public methods, then private methods.
  • GIS Hub vs Godot InSim: Modules can access the hub_insim variable, which is the InSim instance handled by GIS Hub. You should only use it when you actually have to, and use methods provided by GIS Hub when possible. Feel free to report missing wrapper methods in GIS Hub if you find yourself using hub_insim too much or when you don't expect it. However, you can and should use other features provided by Godot InSim, such as LFSText for text handling, GISTime and GISUnit for converting data, etc.
  • Module integration in the hub: Handle all InSim packets you need to provide a smooth integration in the hub; if your module displays an InSim button GUI to currently driving players, you want to make sure those buttons are removed when the player spectates or pits, or when the module is disabled, for instance. Keep your module's internal state as clean as possible, and provide options for InSim button placement. You should also make sure your code is not likely to crash the entire app, so you need to handle situations where you may try to access data from null objects, etc.
And finally, on the distribution and security side, I would recommend providing the source code on a public repository (GitHub, GitLab, etc.), and if possible distribute PCK files generated via CI, to ensure they are consistent with the source code. I will strive to do the same for GIS Hub itself and all modules I create.
Last edited by Bokujishin, .
GIS Hub
Bokujishin
S3 licensed
The GIS Hub (or Godot InSim Hub) is, as its name implies, a hub application for Godot InSim. Its main goal is to provide a common interface for multiple Godot InSim apps to interface with LFS via a single InSim connection - which means you can have as many "apps" running as you want, sharing the same InSim connection, instead of being limited to the 8 connections LFS supports.

This allows the hub app to be the only "heavy" part, as a single Godot executable (and its ~80MB) is necessary here; all Godot InSim apps can instead be distributed as "modules", as small .pck files, and run directly in GIS Hub.




GIS Hub provides the following features:
  • Manage a single InSim connection to use with any number of modules (practical limit is 50)
  • Manage modules (discover on startup, hot enable/disable), with active modules arranged as tabs in the GUI
  • Save and load module configuration, including InSim settings and enabled modules, and give access to a per-module data folder
  • Route packets from LFS to all modules and the other way around
  • Mirror Godot InSim functions for sending packets, managing InSim buttons, etc. at the module level (wrapper functions)
  • Callback functions for all InSim packets, ISP_TINY/ISP_SMALL packet subtypes, and Relay packets
  • Inter-module communication with the ability for a module to send arbitrary data, and subscribe to other modules to handle data they send
  • Graphical interface for included modules (InSim settings and module manager, log module, etc.), and all modules can provide their own GUI
For instance, the GIS Hub tab is itself a module, although it doesn't do much on the InSim side. The Log module, however, provides a visual display of all packet traffic, and includes the name of the module when a packet is sent (or defaults to "InSim" if Godot InSim sent the packet automatically).
These 2 modules are considered "core": they are included in the GIS Hub app, and cannot be disabled. You can however disable logging through the Log module's options.

All other modules, including those distributed with GIS Hub, can be enabled or disabled at any time. Adding a module is as simple as dropping a .pck file in the "modules" folder next to the GIS Hub executable.
Modules can write config and data in their dedicated folder, located in the "user://modules" directory, which corresponds to:
  • Windows: "%APPDATA%\Godot\app_userdata\GIS Hub\modules\<module name>"
  • Linux: "~/.local/share/godot/app_userdata/GIS Hub/modules/<module name>"
As an example, the Teleporter module allows configuring the position of its InSim button interface, and saves it to its data folder (and will read it when enabled, of course). It also reads saved teleport destinations in txt files in the "spawn" subfolder, which means you can easily modify destinations without exiting the app, and even update the destinations for the current track by simply disabling and re-enabling the module (as destinations are updated when the track changes or the module is enabled).


Downloads and documentation:
GIS Hub is not released yet, but will likely be soon after Godot InSim 3.0, which I plan to release shortly after Godot 4.5 is available. You can still download it from the GitLab repository and use it or create modules. Do keep in mind that it may still be unstable at this time, and requires a beta version of Godot 4.5 to work with the latest version of Godot InSim.

A documentation website for module developers is in the works; the public API is also documented inside the Godot editor, and you can read the source code of both core and other modules for reference.


Provided modules:
GIS Hub: [Core] This module provides the main interface for InSim settings and module management.

Log: [Core] This module displays all InSim packet traffic, including timestamps, packet direction (and the sender module if relevant), and a human-readable version of the packet contents (which may omit some data, depending on the packet type). It also creates a log file with the full data for all packets, and allows loading such files back into its GUI for easier reading.
Log options include color management for log files (none, ANSI, BBCode), whether to log files to screen and/or file, and whether to include NLP/MCI packets.

Teleporter: This module provides the "teleport" command to display a simple InSim button GUI allowing to choose a teleport destination. Such destinations can be included in a "track.txt" file according to the format in the provided examples, and files should be named according to the track they are intended for (e.g. "BL1.txt", "SO4R.txt"), or only the first 2 letters for open configs (e.g. "WE.txt" instead of "WE1X.txt").
The "teleport" command can be typed either as "/i teleport" or using the InSim connection's prefix ("!teleport", "@teleport", or any other prefix character).

Messager: This module provides a simple text entry GUI allowing you to type messages directly in UTF8, without having to go through the multiple LFS character pages. You can also easily change text color on the fly without having to retype text, and you can also mention someone using the list of connected players, just like you would in the game.
Do note that LFS has poor support for UTF8, despite the addition of code pages for multiple languages, so many characters are not supported and will produce garbage.
Additional planned features include saving shortcuts to custom messages and message history. Providing a virtual keyboard to show characters from some code pages, as you can see in LFS, is very unlikely to happen.
Last edited by Bokujishin, . Reason : Updated GitLab link
Add an InSim packet for vehicle dimensions and wheel positions
Bokujishin
S3 licensed
As far as I know, there are currently 2 ways to retrieve information about a vehicle's dimensions:
  • Pressing O in the garage to generate the corresponding CAR_info.bin file
  • For mods, directly reading the mod file (which requires decoding it)
However, the first point only gives us contact patch position (which is good), and the second one is clearly not intended to begin with, and doesn't work with official vehicles.

Since the origin of a vehicle varies from vehicle to vehicle, it would be really useful if a new packet could be added to retrieve this data, which could be cached after being computed (if needed) when a player/AI leaves the pits, so it can be retrieved easily.

Assuming the vehicle origin is what the IS_MCI packet gives us, I propose the following format:
struct IS_DIM // vehicle DIMensions
{
byte Size; // 76
byte Type; // ISP_DIM
byte ReqI; // 0
byte PLID; // player's unique ID
float Length; // total length in metres
float Width; // total width in metres
float Height; // total height in metres
Vec/tor Offset; // offset from vehicle origin to box centre, local space (ints or floats in metres)
Vec/tor Wheels[4] // Offset to each contact patch center, local space (ints or floats in metres)
}

Total length/width/height represents the dimensions of the vehicle's bounding box, which could be based either on LOD1 or LOD3 (LOD3 makes sense on the physics side, but may be a bit rough, especially for some mods that have a bad LOD3).
Offset is measured from the vehicle origin to the center of the bounding box.

This packet would help generalize access to vehicle dimensions and wheel positions, without having to manually create a CAR_info.bin file (which assumes knowing what vehicles will be in the race/session), and can also help with the new AI control packets, as it gives us a way to measure distance to other vehicles, as well as determine where our own vehicle's wheels are.

Wheel damage would be either ignored entirely, or the wheel positions could be updated shortly after a car takes damage.

This packet could be requested by sending a corresponding SMALL_DIM packet with the PLID.
Last edited by Bokujishin, .
Bokujishin
S3 licensed
While I believe using the starter shouldn't be difficult to add, clutch is probably more of an issue, as we need to consider why the AI cooked it in the first place; in my experience, this mainly happens if they get stuck for some time, e.g. after a crash or spin, and they struggle to move again (or try to go forward, then reverse, multiple times, especially with some cars).

I think there's a bigger underlying problem here: AI is at its best when it's driving along its line, and is not really good at doing anything off line (at least now it's able to go 2-wide into corners), and also does very little to avoid obstacles on its path at low speeds (if you don't move from the front of the grid at race start, chances are you will have a train of AI cars "stuck" behind you). Its starting behavior is also quite clearly flawed as it is likely based on a timer of some sort to determine when to abort driving away and try to reverse instead, thereby putting stress on the clutch.

Also, I believe Scawen said he wouldn't really touch the AI code again until the new tyre physics are done, which makes sense when trying to get them to drive close to the limit, but not as much sense from a purely behavioral perspective; ultimately, we don't know how AI decision making and navigational behavior is done, we can only guess some parts (such as the racing line likely being followed by a PID controller, with a separate line for the pitlane, given the sometimes rough transition between the 2).
Bokujishin
S3 licensed
Some news about GIS Hub development: as it is based on Godot InSim, I am planning to release version 1.0 soon after Godot Insim 3.0, which itself has to wait until Godot 4.5 is out. In the meantime, I've been adding more core features, and the hub can now do the following:
  • Manage a single InSim connection to use with any number of modules
  • Manage modules (discover on startup, hot enable/disable), with active modules arranged as tabs in the GUI
  • Save and load module configuration, including InSim settings and enabled modules, and give access to a per-module data folder
  • Route packets from LFS to all modules and the other way around
  • Mirror Godot InSim functions for sending packets, managing InSim buttons, etc. at the module level (wrapper functions)
  • Callback functions for all packets and ISP_TINY/ISP_SMALL packet subtypes
  • Inter-module communication with the ability for a module to send arbitrary data, and subscribe to other modules to handle data they send
  • Graphical interface for included modules (InSim settings and module manager, log module, etc.), and all modules can provide their own GUI
GIS Hub users just need to download the modules they want to use (in .pck format), put them in the modules folder, launch GIS Hub and enable the modules.

Module developers have access to all Godot InSim features, with a few changes to adapt to modules, and have access to a number of virtual functions to implement module configuration or behavior on specific events.
Developers can clone the GIS Hub repository or download the source code, open it in Godot, and develop in their own module subfolder. Module export is as easy as modifying or duplicating the provided export template, selecting only resources in your module folder, and hitting the Export PCK button.

A big advantage of using GIS Hub modules instead of standalone Godot InSim apps is the export file size: by exporting only the .pck file, your app will typically be a few kB to a few MB at most, instead of a baseline of ~80 MB because of the Godot executable.

I'm also currently working on a dedicated website (similar to the one for Godot InSim), with documentation and guides for module development, including what I view as best practices. Another useful source of documentation is the source code of core modules and other optional modules included with GIS Hub.
Bokujishin
S3 licensed
A big thank you to Flame CZE for his help with the interior textures: he brought the dashboard to life (and adjusted the vents too), and textured the center panel (carbon part with the switches); I took this opportunity to get going with some more textures (reusing the dashboard texture for the seat, steering wheel, and foam blocks), and added labels/logos to various parts of the dashboard (AC controls, the blue knob thingy (radiator cooler), wheel and center panel button labels.



See attached screenshots for a before/after comparison.
Last edited by Bokujishin, .
FGED GREDG RDFGDR GSFDG