Author Topic: Making a simple ready room  (Read 3698 times)

Kimos

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Making a simple ready room
« on: May 23, 2014, 06:24:00 PM »
This is my first time using TNet and overall I like how much it simplifies many of the networking details. However, I have been bumping into a few design decisions on TNet that has made my design process more difficult than it needs to be.

I'm trying to create a very simple RTS styled ready room. The important details for this are:
1) As players join they are assigned a player number in order. IE the first player (likely host) is Player 1. The second player is Player 2 and so on. If a player leaves, the next player to join takes over that vacancy.
2) All players in the same channel must "see" the exact same player number assignments. (IE we must all agree that Bob is Player 1, Sue is Player 2, etc.)
3)In the ready room, each player can make arbitrary choices such as choosing a color and choosing a faction.
4) The player numbers assigned in 1 and the data choices in 3 must be preserved through scene loads.

I have determined the following design details about TNet that relate to this:
1) RFC calls only save the most recent invocation for each object. This means I can't have all this data on a single instance of a single object (unless I want to go crazy with copy paste on RFC calls). I must have one player object for each player number I wish to assign (otherwise player number pairings and player choices are lost when "old" RFC calls are dumped)
2) If I wish to use DontDestroyOnLoad on an object with the TNObject script, I can't create that object using TNManager.Create. If I do, all kinds of strange things happen.
3) When the Host player creates the game, I am not getting an OnPlayerJoined event to fire for the host player.

Because of this (especially the part about the host not triggering OnPlayerJoined events), I'm not sure what the cleanest design for this would be. I know the player objects must be in the scene (instead of created). However I do not know the best way to detect when players join / leave. I also do not know how to handle ownership for the static objects. Dynamically created objects were nice because I could create them as players joined and they were auto destroyed when the players left.

What is the cleanest design you would recommend for this? Are there other major TNet design details that I may run into regarding this?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Making a simple ready room
« Reply #1 on: May 23, 2014, 06:30:24 PM »
1. RFCs remember the last value you sent (assuming you sent them via Saved). If you want to store multiple values, send an array instead of a single value.

2. TNManager.Create instantiates objects with their lifetime managed by TNet. When the scene is destroyed, so is the object. If you want DontDestroyOnLoad, don't use TNManager.Create. Have a static object in the scene with TNObject attached, and a fixed ID specified. (read: it should already be there, a part of the scene itself). Also, don't send anything saved via this TNObject as its lifetime is undetermined if you use DontDestroyOnLoad and switch scenes.

3. Correct. The player that joins a channel gets OnNetworkJoinChannel. When another player joins the channel the player is in, the existing players get OnNetworkPlayerJoin.

Kimos

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Re: Making a simple ready room
« Reply #2 on: May 27, 2014, 04:29:29 PM »
Ideally saved RFCs would be used to track each player's choice so that players joining the channel after the choice are updated with the details. These choices need to be preserved across a scene load, meaning DontDestroyOnLoad most likely is required. However, you can't use DontDestroyOnLoad on objects that are created with TNManager.Create(). This means the data would have to be on static objects, but static objects can't have saved RFC calls.  Making the whole idea a catch 22.

Clearly I must be overlooking something because this usage (preserving player decisions across scene loads and informing players that join in the future about those decisions) should be trivial. How would you recommend doing this?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Making a simple ready room
« Reply #3 on: May 28, 2014, 07:59:38 AM »
If you need to store data on the server across different channels, save it as a file. Think player profile saved on the server. RFCs are meant to exist only while the channel exists. In a future version of TNet I'll add regions you can subscribe to (think being able to be in several channels at once).

Kimos

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Re: Making a simple ready room
« Reply #4 on: May 29, 2014, 03:06:53 PM »
Do scene loads cause the players to join a new channel? I'm only worried about preserving data across scene loads and keeping a history for players that join the channel later. Keeping this data in a file seems like overkill, it is only relevant for that game session. In other words, I want it wiped when the channel closes.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Making a simple ready room
« Reply #5 on: May 30, 2014, 03:42:25 PM »
Scene loads cause players to join a new channel? Not sure what you mean. TNManager.LoadLevel will cause you to switch a scene while staying in the same channel. TNManager.JoinChannel will cause you to join a new channel, and potentially load a new scene.

Kimos

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Re: Making a simple ready room
« Reply #6 on: June 03, 2014, 03:57:23 PM »
2 replies back you said something about saving data across multiple channels. That is where I thought maybe scene loads cause you to join a different channel. I am not interested in preserving data across channels, I am interested in preserving data across scene loads AND having that data sent to players that join the channel later. Is there a way for objects marked with DontDestroyOnLoad to use saved RFCs?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Making a simple ready room
« Reply #7 on: June 04, 2014, 02:24:44 AM »
Currently the version of TNet I'm developing as a result of my work on Windward automatically synchronizes Player.data, and I also save this data on the server using save/load file requests. So currently when the player first connects to the server, he requests his profile to be loaded and sets the player's data to this profile object. This profile is sent to other players when the player joins the channel (and it's available for anyone via TNManager.GetPlayer(id).data). Would this address your needs?

Kimos

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Re: Making a simple ready room
« Reply #8 on: June 10, 2014, 02:48:37 PM »
It might. I do recall seeing the player.data field. Is that synchronizing now, or is that a future update?

I constructed the example in my OP because I thought it might be easiest to relate to while helping me come to a solution. My real issue is that I have a ready room where each player picks an image file from their phone, the file is synchronized across all players in the ready room, and then a new scene is loaded for gameplay where each player's image file is used. I don't want to rebroadcast the image file upon entry into the gameplay scene because that would consume additional bandwidth and time. To get around this I ended up combining the gameplay and ready room into one scene. But I am still interested in a "correct" way to do something like this in case I end up expanding the game to the point that it is too unwieldy to have them in the same scene.

On the topic of synchronizing image files: Am I correct in thinking I just convert it to a byte array, send it, then convert it back to my image format? Is there something built into TNet to detect when the entire byte array has been received?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Making a simple ready room
« Reply #9 on: June 11, 2014, 06:13:02 AM »
Player.data is not sync'd in the current version of TNet. I added support for its data to be sync'd in the current Pro version, so it will be available in a future update.

By the sounds of things, the persistent player.data is indeed what you need. You can set the data once (to this image's data if you like), and it will remain there, and will be automatically sent to all newly joined players.