Skip to content

feat(server/state): add train getters for already synced fields - #4093

Open
Github-Samuel wants to merge 1 commit into
citizenfx:masterfrom
Github-Samuel:feat/server-train-getters
Open

feat(server/state): add train getters for already synced fields#4093
Github-Samuel wants to merge 1 commit into
citizenfx:masterfrom
Github-Samuel:feat/server-train-getters

Conversation

@Github-Samuel

Copy link
Copy Markdown

Goal of this PR

Read back a few more train fields server-side. The server already parses them out of the train sync node, there just aren't natives for them yet.

How is this PR achieving the goal

CTrainGameStateDataNode fills in more of CTrainGameStateDataNodeData than the current getters expose. These six are all serialized unconditionally:

s.SerializeSigned(32, 1000.0f, data.distanceFromEngine);

s.Serialize(8, data.trainConfigIndex);
...
s.Serialize(data.isMissionTrain);
s.Serialize(data.direction);
s.Serialize(data.hasPassengerCarriages);
s.Serialize(data.renderDerailed);

s.Serialize(data.forceDoorsOpen);

so this adds:

native field
GET_TRAIN_CONFIG_INDEX trainConfigIndex
GET_TRAIN_DISTANCE_FROM_ENGINE distanceFromEngine
IS_MISSION_TRAIN isMissionTrain
DOES_TRAIN_HAVE_PASSENGER_CARRIAGES hasPassengerCarriages
IS_TRAIN_RENDERED_DERAILED renderDerailed
DOES_TRAIN_FORCE_DOORS_OPEN forceDoorsOpen

Each one is the same shape as the getters already there, e.g. GET_TRAIN_STATE:

fx::ScriptEngine::RegisterNativeHandler("IS_MISSION_TRAIN", makeEntityFunction([](fx::ScriptContext& context, const fx::sync::SyncEntityPtr& entity)
{
	auto train = entity->syncTree->GetTrainState();

	return train ? train->isMissionTrain : false;
}));

I left the build gated fields out on purpose. carriageSpeed and isTrackDirectionForwards are only serialized under IsWinterUpdate25(), and allowRemovalByPopulation / highPrecisionBlending only under Is2372(), so a getter for those would read an uninitialised member on older builds unless it carried the same gate. stopAtStations is in the same boat and is already handled by DOES_TRAIN_STOP_AT_STATIONS.

DOES_TRAIN_FORCE_DOORS_OPEN reads the per train synced flag, which isn't quite the same thing as the client side SET_TRAINS_FORCE_DOORS_OPEN that sets it globally, so I noted that in its page.

This PR applies to the following area(s)

FXServer, OneSync, Natives

Successfully tested on

Game builds: n/a for the gated fields since none are used; the six added are build independent

Platforms: Windows, Linux

Checklist

  • Code compiles and has been tested successfully.
  • Code explains itself well and/or is documented.
  • My commit message explains what the changes do and what they are for.
  • No extra compilation warnings are added by these changes.

I could not do a full server build locally so I left the first box unchecked. What I did check is that each field is actually written by the parser and not behind a build gate, and that none of the six names collide with an existing native in ext/native-decls or the natives stash.

CTrainGameStateDataNode parses more than the existing train natives read
back. Add getters for the fields that are serialized unconditionally, so
they don't depend on a game build:

- GET_TRAIN_CONFIG_INDEX
- GET_TRAIN_DISTANCE_FROM_ENGINE
- IS_MISSION_TRAIN
- DOES_TRAIN_HAVE_PASSENGER_CARRIAGES
- IS_TRAIN_RENDERED_DERAILED
- DOES_TRAIN_FORCE_DOORS_OPEN

The fields behind Is2372/IsWinterUpdate25 are left alone.

Signed-off-by: Samuel Nicol <99494967+Github-Samuel@users.noreply.github.com>
@github-actions github-actions Bot added the invalid Requires changes before it's considered valid and can be (re)triaged label Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Requires changes before it's considered valid and can be (re)triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant