I would like to achieve the following:
- Start the game in Client&Server mode.
- Portals are created for all current Lobby games
- When the player goes through one of the lobby portals the player should be connected to that remote server
The main issue seems to be the network driver, as when I try to connect to the new server I receive the following error message:
InvalidOperationException: Connection to server already initiated, only one connection allowed at a time.
I did the following for now:
- Destroy existing client & server worlds
- Assign new
NetworkStreamReceiveSystem.DriverConstructor
with obtained relay information - Create a fresh client world or client & server (for the host) using that constructor
The problem is that doesn’t seem to work properly. After the exception the connection is not properly established.
Code
var world = World.All[0];
for (int i = World.All.Count - 1; i >= 0; i--) {
var previousWorld = World.All[i];
if (previousWorld.IsClient() || previousWorld.IsServer()) {
previousWorld.Dispose();
}
}
var relayStuff = SystemAPI.GetSingleton < EnableRelayServer > ();
var relayClientData = world.GetExistingSystemManaged < ConnectingPlayer > ().RelayClientData;
var relayServerData = world.GetExistingSystemManaged < HostServer > ().RelayServerData;
var joinCode = world.GetExistingSystemManaged < HostServer > ().JoinCode;
var createLobbyEntity = EntityManager.CreateEntity();
EntityManager.AddComponentData(createLobbyEntity, new CreateLobbyRequest() {
joinCode = joinCode,
lobbyName = $ "CubeTest_{Random.Range(0, 10_000)}",
maxPlayers = 4
});
var oldConstructor = NetworkStreamReceiveSystem.DriverConstructor;
NetworkStreamReceiveSystem.DriverConstructor = new RelayDriverConstructor(relayServerData, relayClientData);
var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
SceneSystem.LoadSceneAsync(server.Unmanaged, relayStuff.sceneReference);
var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
SceneSystem.LoadSceneAsync(client.Unmanaged, relayStuff.sceneReference);
NetworkStreamReceiveSystem.DriverConstructor = oldConstructor;
if (World.DefaultGameObjectInjectionWorld == null)
World.DefaultGameObjectInjectionWorld = server;
ref
var joinCodeComponent = ref SystemAPI.GetSingletonRW < JoinCode > ().ValueRW;
joinCodeComponent.value = joinCode;
var networkStreamEntity = server.EntityManager.CreateEntity(ComponentType.ReadWrite < NetworkStreamRequestListen > ());
server.EntityManager.SetName(networkStreamEntity, "NetworkStreamRequestListen");
server.EntityManager.SetComponentData(networkStreamEntity,
new NetworkStreamRequestListen {
Endpoint = NetworkEndpoint.AnyIpv4
});
networkStreamEntity
= client.EntityManager.CreateEntity(ComponentType.ReadWrite < NetworkStreamRequestConnect > ());
client.EntityManager.SetName(networkStreamEntity, "NetworkStreamRequestConnect");
// For IPC this will not work and give an error in the transport layer. For this sample we force the client to connect through the relay service.
// For a locally hosted server, the client would need to connect to NetworkEndpoint.AnyIpv4, and the relayClientData.Endpoint in all other cases.
client.EntityManager.SetComponentData(networkStreamEntity,
new NetworkStreamRequestConnect {
Endpoint = relayClientData.Endpoint
});
I found the DriverMigrationSystem, but when using it (storing and loading the worlds) nothing actually seemed to work.
Is there currently a possibility to start with a Client&Server world, and then connect to a remote server with the relay system?