Author Topic: Ghost RFC  (Read 5982 times)

ldw-bas

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 32
    • View Profile
Ghost RFC
« on: April 18, 2014, 08:46:46 AM »
Hi!

I have ran into an issue with TNet. In my game I have 2 network level, one lobby and the actual game. When playing the game you go back and forth from lobby to the game level. Everytime, except for the first time, I load the game level I recieve ghost RFCs. Position updates for position I have not been in that game yet. After some debugging it looks like these are position update from just before quiting the level the previous time. When I run this on my remote VPS (with pretty low latency, around 16-50 ping) this happens everytime.

To make this issue clearer I will write down a sequence of actions that I think are happening that cause this issue.

Server sends load lobbylevel
Server clears saved RFCs
Client1 send RFC
Client1 receives load lobbylevel
Client2 receives load lobbylevel
Server receives RFC
Server distributes RFC
Client2 receives RFC
Client2 store RFC in delayed calls
[just lobby level code going on]
[switch level to game level]
All clients load game level
Client2 creates object with game uid as original ghostRFC sender
Client2 executes the delayed call from the previous level leading to unexpected behaviour

I hope the explanation is clear, otherwise I would gladly clearify the issue. I can work around this issue for now but I think this is something that should be handled by TNet and not by external code.


ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Ghost RFC
« Reply #1 on: April 18, 2014, 05:29:35 PM »
If switching levels by yourself, you can't just Application.LoadLevel yourself away. You need to TNManager.LeaveChannel(), then wait for OnNetworkChannelLeave to arrive. That's when you Application.LoadLevel. Not before.

If switching levels while connected, always go through TNManager.LoadLevel -- and only on one player (the host).

ldw-bas

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 32
    • View Profile
Re: Ghost RFC
« Reply #2 on: April 19, 2014, 09:04:14 AM »
This is then I use TNManager.LoadLevel on the host. With server I really mean the TNServer.exe not the host.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Ghost RFC
« Reply #3 on: April 19, 2014, 11:26:01 PM »
Ok then I don't understand how the server can send load lobby level, or why it clears saved RFCs. LoadLevel can only be sent by players, and no one can clear RFCs -- not the server, not the player. When the channel is abandoned (last player leaves), and assuming it hasn't been marked as persistent, only then do RFCs disappear -- and only because the channel disappears as well. If the channel is persistent, then RFCs stay behind, and are brought back to life when some player re-joins.

ldw-bas

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 32
    • View Profile
Re: Ghost RFC
« Reply #4 on: April 21, 2014, 06:41:01 AM »
OK I think I see the misunderstanding now. I think I wasn't clear about two things, the first is the level is loaded by the player, but this message is than of course distributed by the server once it receives this message from the host. So my explanation of the steps should be preceded by:

Quote
Host loads lobby level with TNManager.LoadLevel
Server sends load lobbylevel
Server clears saved RFCs
Client1 send RFC
Client1 receives load lobbylevel
Client2 receives load lobbylevel
Server receives RFC
Server distributes RFC
Client2 receives RFC
Client2 store RFC in delayed calls
[just lobby level code going on]
[switch level to game level]
All clients load game level
Client2 creates object with game uid as original ghostRFC sender
Client2 executes the delayed call from the previous level leading to unexpected behaviour

The second is that I talked about clearing RFCs, this is because I looked at the code and this is only for the saved RFCs. Nevertheless the issue would also occur when the RFC is not saved.

I will try to re describe the issue in the way I think it's occuring. It is occurring with level switches. When some of the clients have loaded the new level and some haven't. If a client with the old level sends an RFC for a TNObject in this old level and this message is received by a client that has loaded the new level, then the there is no TNObject with this the same uid, so the RFC is stored in the delayed calls. Then when a TNObject with the same uid is created the call is loaded. This is what I called the "GhostRFC" since some arbitrary call is executed on a new object.

In my case this happens very often, because of the level switching in the same channel and when a level is loaded the chances that a TNObject gets assigned the same uid is pretty large.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Ghost RFC
« Reply #5 on: April 22, 2014, 05:19:47 AM »
Hmm... interesting. I'm guessing your RFCs are sent pretty frequently then.

My suggestion... don't load the level immediately. Instead send an RFC that would effectively "pause" everyone's RFCs (prevent those frequent RFCs from going out). Then once everyone is paused, do TNManager.LoadLevel.

ldw-bas

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 2
  • Posts: 32
    • View Profile
Re: Ghost RFC
« Reply #6 on: April 23, 2014, 04:02:28 AM »
Ok so you suggest working around this issue. I had come up with a solution like this myself, but although in my case it was happening frequently it could also happen less frequent, causing for very hard to track bugs.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Ghost RFC
« Reply #7 on: April 23, 2014, 07:59:12 AM »
Doing it on the server side would mean basically pausing everything while the level is loading until all clients reported that they've finished loading the level. This can cause other issues, like one client taking a very long time to load, thus everyone else just "chilling" there, not sure what's going on. Keeping track of this on the client side makes more sense as you have more control over what's going on, and can still do things like chat in the background while the game is effectively paused.