Operating system: Windows 10 Artifact version: 4086 IP address: localhost Resources: spawnmanager, vMenu, sessionmanager and the reproduction resource
Incident
Summary: When using OneSync, train carriages can become visibility detached if the player varies their distance around the train in a certain way Expected behavior: Trains should stay together as one on the track Actual behavior: Trains carriages become visibility detached or separated by a large distance. Though all carriages still move as one. Steps to reproduce: Download the attached resource, and load up a server with 2 clients. Position them around (X: 2414 Y: 1095 Z: 79) and then run the /train command on one player. The players positions will automatically be adjusted a couple times to show the issue Server/Client? Client Files for repro (if any):Reproduction.zip (1.4 KB) Error screenshot (if any): None .dmp files/report IDs: None
@nta Mentioning & bumping as it appears this report got buried. This is a set of working reproduction steps for trains breaking. Tested on latest artifacts.
After seeing dbub comment about this post in the recent community pulse discussion, I can confirm this bug is still present as of today, latest artifact being 6302.
I just wanted to do some investigation myself with the very little knowledge I have.
This repro seems to be working on 2612, 2699 and 2802 (didnt test with any version prior to this), testing done with OneSync Infinity.
The method seems to be related to ownership change breaking the link between the engine and the carriage.
Printing the carriage engine with GetTrainCarriageEngine server side does reveal something of importance, it seems like during the ownership change, the data is lost on all carriage (except the engine that returns itself), all carriage now returns 0.
Printing the owner of every carriage seems to be working fine on the server side, all wagons are changing ownership in a single frame all at once.
Printing the carriage index doesn’t reveal anything weird, all wagons exist with correct carriage index during the repro.
When leaving the repro going to the very end, when the train is exiting the scope of the player, the engine is deleted first, leaving all the carriage going without any engine during a few seconds.
That’s all I noted, it seems like this bug will be kinda hard to debug as is everything related to owership weirdness.
Also, doesn’t seems to be a priority at the moment as they are clearly not main gameplay, just wanted to add all this information somewhere at least
Right, I recall the intended fix actually being something like ‘parse the train attachment data and make sure the entire chain only gets migrated and created as a whole’, though I also believe there was something about ‘try to check what game code does here’.
At the time I don’t think this repro had been seen though so testing it was an issue, as is the other thing with cloning changes namely regression testing.
After this fix, and its followups, I noticed that ReassignEntityInner may sometimes be called twice on the same (link-)entity. While fairly innocuous, it puts LastOwner into an incorrect state.
In the train migration logic, there are now some paths in which entity->clientMutex may not be locked; leading to races with the Get* and Get*Unsafe weak references.
I suspected the previous migration fixes may have lead to deadlocking (no time to verify), so I’ll throw out this question for rubber-ducking:
Is the current ReassignEntity logic all-or-nothing, i.e., if the client owns the engine it is guaranteed to also own all its links? Or is this not a (hard) requirement?
This fix unfortunately did not work for us in regards to AI driven trains. We have a very simple script that uses poly zones to tell where to spawn the trains and the one near Sandy Shores specifically always glitches out around multiple players with onesync infinity.
Perhaps you guys may have some suggestions here to improve this old client sided code, if it is indeed dated:
local function Lerp(a, b, x)
return a + ((b - a) * x)
end
function isWithinUrbanZone(train) --checks if train is in an urban zone
local coord = GetEntityCoords(train)
local isInZone, activeZone = false, nil
for _, zone in pairs(Config.Zones) do
if zone.Zone:isPointInside(coord) == true then
isInZone, activeZone = true, zone
end
end
return isInZone, activeZone
end
-- Enable tracks and train/tram spawning with fixed frequency
SwitchTrainTrack(0, true)
SwitchTrainTrack(3, true)
SetTrainTrackSpawnFrequency(0, 120000)
SetTrainTrackSpawnFrequency(3, 160000)
SetRandomTrains(true)
local stopTrain = false
CreateThread(function()
local freightHash = GetHashKey("freight")
local Speed = 20
while true do
local vehiclePool = GetGamePool("CVehicle")
for _, vehicle in pairs(vehiclePool) do
local isTrain = GetVehicleClass(vehicle) == 21
if isTrain and GetEntityModel(vehicle) == freightHash then
local isInZone, activeZone = isWithinUrbanZone(vehicle)
local desiredSpeed = isInZone and activeZone.Speed or Config.RuralSpeed
if stopTrain then desiredSpeed = 0.0 end
Speed = Lerp(Speed, desiredSpeed, 0.0125)
SetTrainSpeed(vehicle, Speed)
end
end
Wait(100)
end
end)