Ragora's Place

A place where things happen.

User Tools

Site Tools



This shows you the differences between two versions of the page.

Link to this comparison view

blog:tribes_2_ghastly_ghosts [2022/02/02 03:30]
blog:tribes_2_ghastly_ghosts [2022/02/02 03:30] (current)
Line 1: Line 1:
 +====== Tribes 2: Ghastly Ghosts ======
 +About a week ago I discovered a ghosting bug in the Tribes 2 engine. What's especially peculiar is that I discovered a networking bug in a listen
 +server of all things. It takes the following form:
 +{{ :blog:ghosting.png?500 |}}
 +The above screenshot was taken in a Meltdown 3 listen game server. After a couple of seconds, everything snaps back into reality:
 +{{ :blog:skycutter.png?500 |}}
 +===== Background =====
 +Before I get into the bug itself, I should explain how Torque Game Engine synchronizes game simulations across the network. To start off with, all
 +interested parties (including the server) run at a tickrate of 32 milliseconds. This means that the game will update the game world in increments of
 +32 milliseconds each. So, 3 ticks = 3 ticks * 32ms = 96ms. On the server side this is precisely true because that's where the local simulation 
 +resides -- no latency is accounted for. However, when operating with clients across the internet, network transmission latency has to be accounted 
 +for in some way. 
 +The game deals with latency using a client-side simulation to fill in the time it takes for the game server to throw another frame at you which yields
 +a more natural looking simulation according to game rules, but it is prone to desynchronization from what the game server wants you to see at any
 +given point in time. The game has several scripting language exposed values that help control this (with their default values):
 +   * $Item::maxWarpTicks = 3
 +   * $Item::minWarpTicks = 0.5
 +   * $Item::maxLatencyTicks = 0
 +   * $Player::minWarpTicks = 0.5
 +   * $Player::maxPredictionTicks = 30
 +   * $Player::maxWarpTicks = 3
 +   * $Player::maxLatencyTicks = 0
 +Fractional ticks are possible depending on the implementation, so the 0.5 values above represent 16ms instead of the usual 32ms. In my explanation,
 +we'll focus primarily on $Player::maxPredictionTicks which holds the most precedence in the game simulation. In essence, $Player::maxPredictionTicks
 +is used to express how many ticks the game will simulate for between receiving frames from the game server. In this case, it defaults to 30 which is
 +960ms, almost a full second of simulation. So it takes up to about a humanly visible second for the whole game simulation to freeze if the server
 +crashes or if ping time is so bad that it exceeds this time.
 +Cool, so what does this have to do with the screenshot above? Or even the title for that matter? An optimized synchronization technique called 
 +ghosting. The client-side representation of a given game object is called the "ghost", which is what's updated from server frames and simulated
 +against using that recent data. However, the game has to deal with dialup connections and slow desktop processors (Pentium 3, Pentium 2). To help alleviate network stress and memory/CPU stress for clients, the game restricts the scope of ghosts to what's relevant to a given player. This means
 +that objects far away enough out of visible distance flat-out does not exist on the client. The game server also performs ghosting based on indoor
 +and outdoor presence -- when indoors, many outdoor ghosts vanish from the client's simulation.
 +Now what do ghosts have to do with the screenshot? The second "vehicle" you see floating off to the side there is a couple of images that are supposed
 +to be mounted to my vehicle. Think of images as holographic representations of an object that you can put on vehicles and players. These images are
 +often used to make new looking objects and weapons without requiring genuine client-side content. Tribes 2 has an inherent bug with keeping these 
 +images attached to ghosts in some circumstances.
 +==== The Bug ====
 +Not only does Tribes 2 have trouble keeping images mounted correctly, it has a problem with keeping actual objects mounted to the vehicle which
 +are not corrected indefinitely and do not seem correctable aside from modder intervention unmounting and remounting the object. This is noticeable
 +in Meltdown 3 (when the fix isn't applied) where a small cloaked sentry turret can sometimes be found floating around the map which doesn'
 +seem to fully exist -- because it doesn't. This turret is a weighting object mounted to the vehicle to help simulate weighting and it isn't supposed
 +to be visible. When you see it detached, its still connected to a vehicle in reality.
 +This bug is very easily reproduced by placing a vehicle outdoors and going indoors on foot. Once inside (you have to be pretty far indoors), use
 +the script to mount yourself back into the vehicle and move as quickly as possible. If done correctly, the images will lag behind briefly and any
 +mounted objects may "detach" visibly. 
 +==== Fixes ====
 +As mentioned above, a fairly simple fix which is likely the most commonly used is to occasionally unmount and remount objects occasionally to fix the
 +perpetually unmounted objects after the fact. However, there is no reliable way of timing this as its bound to the server side ghosting systems which
 +means that this is only a partial bandaid, not a full fix.
 +The scripting engine exposes a function called %object.setScopeAlways, which would seem to be exactly what we need (always ghost the object to everyone) but it apparently simply expedites the problem and actually makes it worse in most cases:
 +{{ :blog:broken_ghost.png?500 |}}
 +The vehicle is also inaudible, which is really odd. Everything goes back to normal once I mount the vehicle, *and* the chassis weight object is
 +The scripting engine also exposes a function called %object.scopeToClient(%client), which serves the same function as setScopeAlways except that it targets an individual client. This function seems to work well enough on a single client basis, though I have managed to crash the engine once with 
 +it and I have not been able to reproduce it since. Perhaps a WINE bug, hopefully not. And hopefully that function can be looped to scope the object
 +to more than one person to properly resolve both the image bug and the object detachment bug.
 +{{tag>gaming tribes blog}}
blog/tribes_2_ghastly_ghosts.txt · Last modified: 2022/02/02 03:30 (external edit)