Simple plugins can be constructed with almost no knowledge of the underlying network architecture, but the most complex the multiplayer functionality you want, the more you’ll have to understand.
Plugins and Instances
ViRSE hosts any number of plugins (”Worlds”), and any number of instances of each plugin can exist concurrently. You can think of instances as “parallel realities” of your plugin, two users in different instances of the same plugin will see the same virtual environment but not each other, and any changes made to the state of the world will remain confined to each instance. This is used for grouping users together. For example, your plugin might provide a virtual laboratory, with different workgroups divided into different instances. If all users leave an instance, that instance ceases to exist.
Network architecture
In multiplayer environments, many machines, “clients”, are sharing the same virtual world. Each user is allowed to interact with the world and change its state simultaneously, this presents a problem. Were multiple users to interact with the same thing at once, each user would see different results on their machine. For example, if two users are on different floors of a building in the virtual environment, one summons the elevator to the tenth floor, and one summons the elevator to the ground floor, where does the elevator go? This problem necessitates the existence of a “single source of truth” for the state of the world.
There are a number of network designs to facilitate multiplayer interactive environments, all of which have pros and cons. Many AAA games hold the “true” state of the world on a server in the cloud, with all clients connecting to this server as equals. ViRSE uses an alternative system, in which one client, known as the “host” holds the true state of the world, and all other clients (the “non-hosts”) simply run a prediction of what they think the true version of the world is.
ViRSE does utilize a cloud server, but this is merely for relaying messages between the host and non-hosts. It is important to note that non-hosts never communicate to each other directly, it is always through the host, via the relay server. If the host leaves the instance, a new user will become the host.
Users connected to the same instance
Changing the state of the world
The state of the world is being constantly broadcast from the host to each non-host. If the host user changes the world state (e.g by activating an activatable, or by picking up a grabbable and moving it somewhere), this new world state is transmitted to each non-host. If, however, a *non-*host wishes to change the state of the world, a transmission is first sent to the host so that the world state can be updated on the host's machine, whereupon it can then be propagated back out to each non-host.
For example, we have a world consisting of three clients, A (host), B and C (non-hosts). Client B activates an activatable, sending a message via the relay server to client A. Client A’s world state changes, and this is now transmitted back to Clients B and C.
<aside> 🤓 When is data transmitted?
Updates to the world state are transmitted to the relay server at the beginning of each physics cycle (which is where Unity’s FixedUpdate MonoBehaviour function is invoked). This means changing the world state multiple times between FixedUpdates will have no effect, only the world state at the time of the start of each physics cycle will be transmitted. The exception to this rule applies to InstantMessageHandlers, which transmit data instantly rather than waiting for the next physics cycle.
</aside>