I think this would allow me to deal with AI-driven avatars as well, but my question is, where do I put that logic, as tnetserver does not seem to simulate a world?Run AI logic on the channel host's client. This includes spawning things that you only want spawned once.
Do I run a unity client in a VM with some kind of account with special permissions on tnet?
How does the lobby work?The server's lobby keeps a list of available server instances. You open a server instance and connect to the lobby server simultaneously.
Can it redirect to another IP?The lobby can contain multiple server 'buttons' that allow you to connect to the server of your choice.
Can the lobby server instruct the client whom to connect to next already, or do I have to write additional classes for tnet server to deal with routing?AFAIK you will have to keep track of whatever metrics determine which server is next to allow players, and then you would have to send a function to the clients that tells them which IP to connect to when they're ready to connect. (assuming you don't have a server buttons lobby).
To keep with the idea of server authority, I'll be writing the input scripts separately from the scripts actually pulling the strings inside the spawned avatar, syncing input frequently -- but what is the best practice to sync the avatar's state? Do I sync the character controller somehow? The animator? The 'shadow spine' should be enough for player controlled characters in first person along with syncing some animation booleans of which state they're in (such as reloading a weapon); but there's also a dead state where the player is a disembodied camera that can wander for a while before respawning, leaving the avatar behind as a ragdoll. At a high level, what are the tnet functions I'd be doing for handling player characters like this?Go through all of the source code of the included tutorials. Multiple times if you have to. Everything you need to know for these questions is available in the examples.
What about entering a vehicle? What's the best practice to reparent a player avatar as a child of the vehicle? With unet this proved extremely hard because initially I had it set up so players and vehicles both had networkidentities.Add TNObject script to any objects you want to play with over the network. Remote function calls and remote creation calls will probably be enough to get this done.
I haven't yet started the conversion over to TNET3 so I'm trying to figure out the recommended way to do things before diving in and wasting a whole bunch of time spinning my wheels.Connect to a LAN server. Connect to a remove server. Create a server instance with a PC. Now that you know how to do those... Each server instance can contain any number of channels. Channels can be created within the instance on the fly. In order to create a new channel, the client must already be connected to a server instance. Each channel has a host (TNManager.isHosting) and that's how you decide who runs AI. Go through the examples 100x so you completely understand RFCs and RCCs in this system. They are amazingly simple once you understand them.
The channel system seems like it will work pretty well for my large terrain, splitting areas of concern up and allowing the use of multiple scenes in unity (since punching a hole in a terrain's so hard, I made a crummy model of an railway entrance with a barred gate, jiggling the lock will trigger the scene+channel change, I imagine) but I'm not exactly understanding a good strategy towards growing even bigger. As players do their thing, resources will spawn, things will be crafted, and lots and lots of data has to be stored.Two questions to ask yourself: "Do I want the data stored locally on their PC or the server?" and "Why not try looking into datanodes?"
Run AI logic on the channel host's client. This includes spawning things that you only want spawned once.Where's this go? in tnetserver's codebase or the unity client? That would imply I'd need to run a VM with a headless unity client running the AI code.
if(TNManager.isHosting) // AI logic
The server's lobby keeps a list of available server instances. You open a server instance and connect to the lobby server simultaneously.Great, so it already can act as a classic master-server and route a player inbound to another server.
/// <summary> /// Start a local game server and connect to a remote lobby server. /// </summary> static public bool Start (int tcpPort, int udpPort, string fileName, Type type, IPEndPoint remoteLobby, bool openPort = true)
To make a list available to clients, you will have to build a lobby UI that keeps track of the available server instances. Based on this post, you may as well buy the Starlink package. It has everything you need to get a lobby up and running relatively quickly. I purchased it and it's working out well for me.
The lobby can contain multiple server 'buttons' that allow you to connect to the server of your choice.
AFAIK you will have to keep track of whatever metrics determine which server is next to allow players, and then you would have to send a function to the clients that tells them which IP to connect to when they're ready to connect. (assuming you don't have a server buttons lobby).
Go through all of the source code of the included tutorials. Multiple times if you have to. Everything you need to know for these questions is available in the examples.Yes, I've read large chunks of the source. You're incorrect that everything is in the examples; such as demonstration logic for transferring a mechanim player avatar to a vehicle.
Add TNObject script to any objects you want to play with over the network. Remote function calls and remote creation calls will probably be enough to get this done.
Connect to a LAN server. Connect to a remove server. Create a server instance with a PC.
Now that you know how to do those... Each server instance can contain any number of channels. Channels can be created within the instance on the fly. In order to create a new channel, the client must already be connected to a server instance. Each channel has a host (TNManager.isHosting) and that's how you decide who runs AI.
Go through the examples 100x so you completely understand RFCs and RCCs in this system. They are amazingly simple once you understand them.It's an MMO; players can't be trusted. I'll allow players to build content locally and submit to a preview grid for inspection (so they're not making OP guns, ETC) but one of the biggest reasons I bought tnet was the datanode export to file and upload to dedicated server. The workflow I build around that isn't going to be terribly complex.
Two questions to ask yourself: "Do I want the data stored locally on their PC or the server?" and "Why not try looking into datanodes?"
This post really looks like you're getting baked out of your mind, coming up with a thousand ideas at once, and then praying that there's a solution out there that will take care of all this shit at once. You need to write a design document and stick to it. This is insanity.
Where's this go? in tnetserver's codebase or the unity client? That would imply I'd need to run a VM with a headless unity client running the AI code.In your game code. In TNet, the server merely echoes packets to their intended destination. Clients run everything. So in short, code your game like you normally would if it was single player. When you need to sync something, don't just call function A -- instead, send the function call through TNet. For example instead of this:
Does it retain a connection to the lobby server during gameplay? I didn't notice anything like that in the autojoin example.That's up to you. You can, it's just a matter of keeping the game object with the lobby script attached around.
I've already gotten the standalone server running on an ARM system on a chip, as I've already had lots of experience in C# as part of the TShock server team for Terraria. The issue I'm having is that it's unclear where I should be extending; additional methods and packets available in tnetserver, or getting the server to store datanodes in a more cluster-friendly way.Don't touch the TNServer unless you absolutely have to. Everything should remain on your game side.
Non-player AI has to be serverside.No, the server is just there to echo packets. It knows nothing about your game or the game's logic. There's also no point in running AI in an area if there's no one there. Let players run the AI for you. As Bill mentioned, you can use TNManager.isHosting, or better still tno.isMine. For example, if before you had this:
No clients, no host, everything goes idle and 'the world pauses' until another client comes along to 'be a tnet host'.That is correct. If you really want there to be something going on with no one around, build a headless Linux client with Unity and have it connect to your game (and join appropriate channels). Remember: server will echo the packets for you. Clients will run the code. If you want an authoritative client of your own, a separate headless build is the way to go. It's still going to be a client, so the server remains untouched. To other players it will seem that the AI is server-side, when in fact it would be a separate client, controlled by you. As a nice advantage of this, is you can migrate your headless client from one point to another without shutting down the server just by launching the headless client it in point B, then shutting down point A.
It's an MMO; players can't be trusted.If you need that kind of trust, either go with the dedicated headless client approach I just suggested, or add verification to the server side (have the server process packets, not just forward them). This will complicate the server side greatly, but it's pretty simple to do. Just open up the TNGameServer and look for the ProcessForwardPacket() / ProcessChannelPacket() functions.
large terrainThis is easy to do in TNet 3. TNet 3 supports multiple channels that you can join/leave at will as you traverse your world. All channel data can remain persistent, and objects can travel from one channel to another. Simply subdivide your huge world into smaller logical chunks, with each chunk having a channel ID. I recommend simply basing them on the world position personally, but it's up to you. As players traverse the world, have them join appropriate channels around them. When they create world objects (for example dropping a piece of equipment), create them in the closest channel to wherever they are. This will make them appear to all others nearby, and will vanish when those players get out of range.