TSO-SE Discussion Thread

25 is a really unusual number... I've been lead to believe that the real value is 20/21 specifically by this function in onlinejobsglobals:
upload_2015-8-4_0-21-21.png
...though from videos of the restaurant show the clock driven by this going a little fast? I'm not sure. What I'm asking is, where did you find the value for this tick rate, and is it definite?

It seems that the client should receive player actions from another packet, and that the server should send these packets before sending the kServerTickConfirmationMsg to the client for the tick when those actions are scheduled to occur.

It turns out that, if you set the simulate_until value to a really high value (many game hours in the future), to catch up to the current time, the game does not simulate as fast as it can, but instead, it gradually increases the speed of the simulation and then gradually decreases the speed when it begins approaching the current time.

As for whether or not the game buffers the kServerTickConfirmationMsg packets it receives and only responds to them after a certain scheduled time in the future (e.g. an 0.5 second latency would protect against dropouts up to 0.5 seconds long), I'm not sure yet.
Actions may not be scheduled to perform on fine tuned ticks, they may just be queued up and then sent in bulk between the server tick packets and then simply be buffered into a queue in the order they were sent then recieved over the tcp stream (eg. run 5 ticks, queue interaction # onto callee object # from caller object #). FreeSO works slightly different from this by instead sending command lists with every tick... but it's the same idea deep down.

The gradual change in simulation speed is interesting, and is probably just there so that the illusion isn't shattered by the state suddenly jumping forward to where it's meant to be. You'll notice that our setup is incredibly stuttery on connections that are less than perfect right now.. This is because we're only buffering 2 ticks maximum at all times and just jumping forward to the latest if >2x the buffer size is queued. In future this is probably going to dynamically adjust by each client to tailor to connection quality, and something like a gradual change would probably help it not look terrible too.

I don't think it deliberately buffers ticks after you recieve them - it probably just adds them to a queue immediately and tries to run through it, maybe slowing down as it gets closer to the end.
 
I don't feel like typing up a long post, so, here are our notes:

Code:
prealpha -> naitrial

Member functions:
cTSOSimulator::cTSOSimulator: TSOSimulatorClientD_base+0x1cce5 -> TSOSimulatorClientD_base+0x6c9a4
cTSOSimulator::SetSpeed: TSOSimulatorClientD_base+0x1d722 -> TSOSimulatorClientD_base+0x6d387
cTSOSimulator::AssembleAndSendChecksum: TSOSimulatorClientD_base+0x1de93 -> TSOSimulatorClientD_base+0x6dbbf
cTSOSimulator::AssembleAndSendChecksync: TSOSimulatorClientD_base+0x1df41 -> TSOSimulatorClientD_base+0x6dc1c
cTSOSimulator::ScheduleLocalEvent: TSOSimulatorClientD_base+0x1e10a -> ?
cTSOSimulator::LocalPause: TSOSimulatorClientD_base+0x1e26b -> TSOSimulatorClientD_base+0x6de4c
cTSOSimulator::LocalUnpause: TSOSimulatorClientD_base+0x1e35a -> TSOSimulatorClientD_base+0x6debb
cTSOSimulator::ClientIdle: cTSOSimulatorClient_base+0x1ecfc -> TSOSimulatorClientD_base+0x6ec79
cTSOSimulator::HandleEvent: TSOSimulatorClientD_base+0x1f192 -> ?

Member variables:
cTSOSimulator::sim_speed: +0x68 -> ?
cTSOSimulator::tick_number: +0xcc -> 0xd4
cTSOSimulator::is_paused: +0xf4 -> 0x100
cTSOSimulator::simulate_until: +0xfc -> 0x108

Do a regex search for "DWORD PTR \[.*\+0x108\]," in TSOSimulatorClientD.dll,
and the result is:
10067963:   89 83 08 01 00 00     mov  DWORD PTR [ebx+0x108],eax
1006ca7b:   89 9e 08 01 00 00     mov  DWORD PTR [esi+0x108],ebx <- being set to 0
1006f33a:   89 86 08 01 00 00     mov  DWORD PTR [esi+0x108],eax
1009c07c:   89 8e 08 01 00 00     mov  DWORD PTR [esi+0x108],ecx

That leaves us with 10067963, 1006f33a, and 1009c07c as potentially the code we
want to reach to increment the simulate_until variable.

Of these three, 1006f33a is perhaps the most interesting (at least in my
opinion) because it appears to retrieve its value from an object that accepts
IID=0x65297976 (kGZIID_cIGZMessage2Standard). The function starts at 0x1006f2ea
and is called by this code:

1006e62a:   ff 50 10     call  DWORD PTR [eax+0x10]
1006e62d:   6a 01     push  0x1
1006e62f:   2d 03 3d 7c 2c     sub  eax,0x2c7c3d03
1006e634:   5b     pop  ebx
1006e635:   0f 84 28 01 00 00     je  0x1006e763
1006e63b:   83 e8 09     sub  eax,0x9
1006e63e:   0f 84 b4 00 00 00     je  0x1006e6f8
1006e644:   2d 86 fa dc 11     sub  eax,0x11dcfa86
1006e649:   0f 84 90 00 00 00     je  0x1006e6df
1006e64f:   83 e8 0c     sub  eax,0xc
1006e652:   74 19     je  0x1006e66d
1006e654:   2d 03 ec 15 2d     sub  eax,0x2d15ec03
1006e659:   0f 85 b5 01 00 00     jne  0x1006e814
1006e65f:   57     push  edi
1006e660:   8d 4e dc     lea  ecx,[esi-0x24]
1006e663:   e8 82 0c 00 00     call  0x1006f2ea

0x2c7c3d03 = 0x2C7C3D03 -> ?
0x2c7c3d03+0x9 = 0x2C7C3D0C -> ?
0x2c7c3d03+0x9+0x11dcfa86 = 0x3E593792 -> ?
0x2c7c3d03+0x9+0x11dcfa86+0xc = 0x3E59379E -> ?
0x2c7c3d03+0x9+0x11dcfa86+0xc+0x2d15ec03 = 0x6B6F23A1 -> kServerTickConfirmationMsg (!!!!!)

This is very interesting because the debugging string in naitrial
"TicksPerServerConfirmation" (at TSOSimulatorClientD_base+0x6e311) tells us that
a "server confirmation" provides a number of ticks to the client.

By placing a breakpoint on the ClientIdle function, you can see that when the house is first loaded, both current_tick and simulate_until are set to 0.

If you send a kServerTickConfirmationMsg cTSONetMessageStandard, it turns out that 0x1006e663 is reached, and subsequently, 0x1006f33a is reached with eax corresponding to the value of the "String ID" field (gosh, we need to rename that). Since there are 5 real world seconds per game minute and 25 SimAntics ticks per real world second, I set this value to 0xaf for 175 ticks or 7 real world seconds, and sure enough, the game time changed from 12:01 to 12:02.

So kServerTickConfirmationMsg updates the value of simulate_until. But is this seriously all we need to do: send the packet several times per second and the simulation works? What about the server "confirming" that the client is in sync etc.? How does the client receive actions from other players? And what do we need to do to ensure that the simulation is smooth for the player?

It seems that, to ensure that the client is still in sync with the server, the client will periodically call cTSOSimulator::AssembleAndSendChecksum and cTSOSimulator::AssembleAndSendChecksync, at least when the server asks the client to do so; but so far this hasn't happened yet.

It seems that the client should receive player actions from another packet, and that the server should send these packets before sending the kServerTickConfirmationMsg to the client for the tick when those actions are scheduled to occur.

It turns out that, if you set the simulate_until value to a really high value (many game hours in the future), to catch up to the current time, the game does not simulate as fast as it can, but instead, it gradually increases the speed of the simulation and then gradually decreases the speed when it begins approaching the current time.

As for whether or not the game buffers the kServerTickConfirmationMsg packets it receives and only responds to them after a certain scheduled time in the future (e.g. an 0.5 second latency would protect against dropouts up to 0.5 seconds long), I'm not sure yet.

Here is the packet:
http://niotso.org/files/kservertickconfirmationmsg.dat

and a screenshot:
kservertickconfirmationmsg_2015-08-03.png
I seriously doubt the server would spam the client with a packet so many times and have it try to respond with another packet on top of that.
 
You haven't been using the "sim_speed 25" cheat for Pre-Alpha NoNetwork mode, have you? :p http://forum.afr0games.com/index.php?threads/pre-alpha-hype-thread.246/page-2

In Pre-Alpha, the sim_speed cheat defaults at 21. In Pre-Alpha -NoNetwork mode, before running the sim_speed cheat, I verified that my patch is increasing simulate_until by 21 per second: I paused inside the hook code, wrote down the initial value of the simulate_until variable and noted the current time, pressed F9, and pressed F2 to break inside the hook code again after exactly 1 minute (using time.gov). The result was: It started at 0x5e60 and ended at 0x634a. 634a-5e60 = 4EA ticks or 1258 ticks in one minute or 20.967 ticks in one second. So it is increasing simulate_until by 21 per second. However, the sprite animations, the character animations, and the time at the bottom of the screen all run too slowly until you run "sim_speed 25", at which point simulate_until increases by 25 per second.

In Play Test RP -NoNetwork mode, the situation was the same, but you need to modify TSOServiceClientD.dll in order to change the sim_speed variable, since you do not have access to cheats.

So it seems like simulate_until should increase by 25 per second.

However, in naitrial online mode, sending kServerTickConfirmationMsg with simulate_until=7*60*5*25= 52500= 0xCD14 causes the game to simulate from 12:01am to 8:14am (shown in the above screenshot), and simulate_until=7*60*5*21= 44100= 0xac44 causes the game to simulate from 12:01am to 6:56am, which is much closer to the target of 7:01am. I have also confirmed that, inside ClientIdle, dword [esi+0x108] is exactly the value that I specified in the packet: 0xac44.

So it seems that there is something different in -NoNetwork mode, or in Pre-Alpha or Play Test RP, or a combination thereof, where sim_speed needs to be changed from the "normal value" of 21 to 25 to run at the correct speed; but in naitrial online mode, the value should be 21.
 
You haven't been using the "sim_speed 25" cheat for Pre-Alpha NoNetwork mode, have you? :p http://forum.afr0games.com/index.php?threads/pre-alpha-hype-thread.246/page-2

In Pre-Alpha, the sim_speed cheat defaults at 21. In Pre-Alpha -NoNetwork mode, before running the sim_speed cheat, I verified that my patch is increasing simulate_until by 21 per second: I paused inside the hook code, wrote down the initial value of the simulate_until variable and noted the current time, pressed F9, and pressed F2 to break inside the hook code again after exactly 1 minute (using time.gov). The result was: It started at 0x5e60 and ended at 0x634a. 634a-5e60 = 4EA ticks or 1258 ticks in one minute or 20.967 ticks in one second. So it is increasing simulate_until by 21 per second. However, the sprite animations, the character animations, and the time at the bottom of the screen all run too slowly until you run "sim_speed 25", at which point simulate_until increases by 25 per second.

In Play Test RP -NoNetwork mode, the situation was the same, but you need to modify TSOServiceClientD.dll in order to change the sim_speed variable, since you do not have access to cheats.

So it seems like simulate_until should increase by 25 per second.

However, in naitrial online mode, sending kServerTickConfirmationMsg with simulate_until=7*60*5*25= 52500= 0xCD14 causes the game to simulate from 12:01am to 8:14am (shown in the above screenshot), and simulate_until=7*60*5*21= 44100= 0xac44 causes the game to simulate from 12:01am to 6:56am, which is much closer to the target of 7:01am. I have also confirmed that, inside ClientIdle, dword [esi+0x108] is exactly the value that I specified in the packet: 0xac44.

So it seems that there is something different in -NoNetwork mode, or in Pre-Alpha or Play Test RP, or a combination thereof, where sim_speed needs to be changed from the "normal value" of 21 to 25 to run at the correct speed; but in naitrial online mode, the value should be 21.
So 21 is definitely the correct speed online? Seems a little unusual that this would work differently in -nonetwork, but I suppose the mode technically isn't meant to function in most versions of the game anyways.
 
So 21 is definitely the correct speed online? Seems a little unusual that this would work differently in -nonetwork, but I suppose the mode technically isn't meant to function in most versions of the game anyways.
It could have been to speed things up so that the devs could test things quicker but I really don't see how it would...
 
The updater uses the Marimba Castanet protocol.

Our server just says "Yep, you are running the latest version" unconditionally (regardless of which version of TSO you have and whether all your files are corrupt) so that the client proceeds to the game. From the server, we literally just send 11 bytes to the client: ca fe be ef 00 00 00 00 00 00 03.

We did this extremely quickly thanks to the fact that there's still a Marimba Castanet transmitter running to date (http://trans.marimba.com/) and due to the fact that the Marimba Castanet protocol hasn't changed since 1997. You can try it out yourself: Back up your TSOPatch folder, and modify Buddy/Buddy.ini and TempBuddy/Buddy.ini and set PatchZero=http://trans.marimba.com/channelstore in both files and run the updater; the updater will ask you to download 20.9 MB to sync with Marimba's Channel Store repository. If you apply the update, the updater replaces itself with the Channel Store (although the TempBuddy folder isn't changed, for some reason). Then when you re-run the updater, it will say it's up-to-date, and using Wireshark, you'll see that the packet the transmitter sends to the client in the up-to-date case is those 11 bytes.

We only figured out enough of the protocol to tell the client that it's up to date. We don't know how to distribute updates yet. But we found some helpful documents explaining the protocol (or the technology) somewhat:
System and method for updating devices using limited amounts of random access memory
Java Beyond the Browser: The Channel Metaphor
Official Marimba Guide to Castanet

Interestingly, my uni has a hard copy of "Official Marimba Guide to Castanet" including the CD-ROM (which includes a trial version of the Castanet Transmitter server) in the library:

marimba_castanet_ut.png


When I get back to school on Monday, I'll grab it and upload it. (Personally I'm not that interested in distributing updates through the patcher, but maybe somebody else is.)
 
Good work, whos Laura Lemay?? Whats next for NIOTSO?

We're still figuring out how to create an object, although we're able to delete an object from the lot. (I'm not sure if we've talked about this already?)
Fatbag will provide screenshots once we get around to writing this part up lol. :p
 
We're still figuring out how to create an object, although we're able to delete an object from the lot. (I'm not sure if we've talked about this already?)
Fatbag will provide screenshots once we get around to writing this part up lol. :p
So bad this is still taking some time, is one of the most importants features to allow people do play testing with NIOTSO.
 
Back
Top