public void Connect(string ip, int port)
        {
            serverIp   = ip;
            serverPort = port;

            EventBasedNetListener listener = new EventBasedNetListener();

            listener.PeerConnectedEvent    += OnPeerConnected;
            listener.PeerDisconnectedEvent += OnPeerDisconnected;
            listener.NetworkReceiveEvent   += OnNetworkReceive;

            client = new NetManager(listener)
            {
                AutoRecycle = true,
            };

            PacketProcessor = new NetPacketProcessor();
            LiteNetLibUtils.RegisterAllPacketNestedTypes(PacketProcessor);
            LiteNetLibUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor);

            client.Start();
            client.Connect(ip, port, "nebula");

            SimulatedWorld.Initialize();

            LocalPlayer.IsMasterClient = false;
            LocalPlayer.SetNetworkProvider(this);
        }
예제 #2
0
        public void Connect(string ip, int port)
        {
            serverIp   = ip;
            serverPort = port;

            clientSocket            = new WebSocket($"ws://{ip}:{port}/socket");
            clientSocket.OnOpen    += ClientSocket_OnOpen;
            clientSocket.OnClose   += ClientSocket_OnClose;
            clientSocket.OnMessage += ClientSocket_OnMessage;

            PacketProcessor = new NetPacketProcessor();
#if DEBUG
            PacketProcessor.SimulateLatency = true;
#endif

            PacketUtils.RegisterAllPacketNestedTypes(PacketProcessor);
            PacketUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor);

            clientSocket.Connect();

            SimulatedWorld.Initialize();

            LocalPlayer.IsMasterClient = false;
            LocalPlayer.SetNetworkProvider(this);
        }
예제 #3
0
 public static void OnPlanetDataSet_Postfix()
 {
     if (Multiplayer.IsActive && Multiplayer.Session.IsInLobby)
     {
         GameMain.history.universeObserveLevel = SimulatedWorld.GetUniverseObserveLevel();
     }
 }
예제 #4
0
        public override void ProcessPacket(NewDroneOrderPacket packet, NebulaConnection conn)
        {
            // Host does not need to know about flying drones of other players if he is not on the same planet
            if (IsHost)
            {
                if (GameMain.mainPlayer.planetId != packet.PlanetId)
                {
                    return;
                }

                Player player = playerManager.GetPlayer(conn);
                if (player != null)
                {
                    if (packet.Stage == 1 || packet.Stage == 2)
                    {
                        DroneManager.AddPlayerDronePlan(player.Id, packet.EntityId);
                    }
                    else if (packet.Stage == 3)
                    {
                        DroneManager.RemovePlayerDronePlan(player.Id, packet.EntityId);
                    }
                }
            }

            SimulatedWorld.UpdateRemotePlayerDrone(packet);
        }
예제 #5
0
 public static void FixedUpdate_Postfix(int ___frame)
 {
     if (___frame >= 11 && SimulatedWorld.Initialized)
     {
         SimulatedWorld.OnGameLoadCompleted();
     }
 }
예제 #6
0
        public void ProcessPacket(StationUI packet, NebulaConnection conn)
        {
            Player player = playerManager.GetPlayer(conn);

            // if a user adds/removes a ship, drone or warper or changes max power input broadcast to everyone.
            if ((packet.settingIndex == StationUI.UIsettings.MaxChargePower || packet.settingIndex == StationUI.UIsettings.setDroneCount || packet.settingIndex == StationUI.UIsettings.setShipCount || packet.settingIndex == StationUI.UIsettings.setWarperCount) && player != null && StationUIManager.UpdateCooldown == 0)
            {
                playerManager.SendPacketToAllPlayers(packet);
            }
            else if (StationUIManager.UpdateCooldown == 0 || !packet.isStorageUI)
            {
                List <NebulaConnection> subscribers = StationUIManager.GetSubscribers(packet.stationGId);
                for (int i = 0; i < subscribers.Count; i++)
                {
                    if (subscribers[i] != null)
                    {
                        if (subscribers[i] == conn)
                        {
                            /*
                             * as we block the normal method for the client he must run it once he receives this packet.
                             * but only the one issued the request should do it, we indicate this here
                             */
                            packet.shouldMimick = true;
                        }
                        subscribers[i].SendPacket(packet);
                    }
                }
            }
            // always update values for host
            SimulatedWorld.OnStationUIChange(packet);
        }
예제 #7
0
 public static void OnClose_Postfix(UIStarmap __instance)
 {
     if (SimulatedWorld.Initialized)
     {
         SimulatedWorld.ClearPlayerNameTagsOnStarmap();
     }
 }
예제 #8
0
        public void StartServer(int port, bool loadSaveFile = false)
        {
            PlayerManager = new PlayerManager();
            if (loadSaveFile)
            {
                SaveManager.LoadServerData();
            }
            SaveManager.SaveOnExit = true;
            PacketProcessor        = new NetPacketProcessor();
            StatisticsManager      = new StatisticsManager();

#if DEBUG
            PacketProcessor.SimulateLatency = true;
#endif

            PacketUtils.RegisterAllPacketNestedTypes(PacketProcessor);
            PacketUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor);

            socketServer = new WebSocketServer(port);
            socketServer.AddWebSocketService("/socket", () => new WebSocketService(PlayerManager, PacketProcessor));

            socketServer.Start();

            SimulatedWorld.Initialize();

            LocalPlayer.SetNetworkProvider(this);
            LocalPlayer.IsMasterClient = true;

            // TODO: Load saved player info here
            LocalPlayer.SetPlayerData(new PlayerData(PlayerManager.GetNextAvailablePlayerId(), GameMain.localPlanet?.id ?? -1, new Float3(1.0f, 0.6846404f, 0.243137181f)));
        }
예제 #9
0
 public static void OnDraw_Postfix()
 {
     if (SimulatedWorld.Initialized)
     {
         SimulatedWorld.OnDronesDraw();
     }
 }
예제 #10
0
        public void ProcessPacket(StationUI packet, NebulaConnection conn)
        {
            Player player = playerManager.GetPlayer(conn);

            // if a user adds/removes a ship, drone or warper broadcast to everyone.
            if ((packet.settingIndex == 0 || packet.settingIndex == 8 || packet.settingIndex == 9 || packet.settingIndex == 10) && player != null && StationUIManager.UpdateCooldown == 0)
            {
                playerManager.SendPacketToAllPlayers(packet);
            }
            else if (StationUIManager.UpdateCooldown == 0 || !packet.isStorageUI)
            {
                List <NebulaConnection> subscribers = StationUIManager.GetSubscribers(packet.stationGId);
                for (int i = 0; i < subscribers.Count; i++)
                {
                    if (subscribers[i] != null)
                    {
                        if (subscribers[i] == conn)
                        {
                            packet.shouldMimick = true;
                        }
                        Debug.Log("sending packet to subscriber");
                        subscribers[i].SendPacket(packet);
                    }
                }
            }
            SimulatedWorld.OnStationUIChange(packet);
        }
예제 #11
0
        public override void ProcessPacket(PlayerMovement packet, NebulaConnection conn)
        {
            bool valid = true;

            if (IsHost)
            {
                Player player = playerManager.GetPlayer(conn);
                if (player != null)
                {
                    player.Data.LocalPlanetId       = packet.LocalPlanetId;
                    player.Data.UPosition           = packet.UPosition;
                    player.Data.Rotation            = packet.Rotation;
                    player.Data.BodyRotation        = packet.BodyRotation;
                    player.Data.LocalPlanetPosition = packet.LocalPlanetPosition;

                    playerManager.SendPacketToOtherPlayers(packet, player);
                }
                else
                {
                    valid = false;
                }
            }

            if (valid)
            {
                SimulatedWorld.UpdateRemotePlayerPosition(packet);
            }
        }
예제 #12
0
        public void ProcessPacket(SyncComplete packet, NebulaConnection conn)
        {
            Player player = playerManager.GetSyncingPlayer(conn);

            if (player == null)
            {
                Log.Warn("Received a SyncComplete packet, but no player is joining.");
                return;
            }

            // Should these be locked together?

            int syncingCount;

            using (playerManager.GetSyncingPlayers(out var syncingPlayers))
            {
                bool removed = syncingPlayers.Remove(player.Connection);
                syncingCount = syncingPlayers.Count;
            }

            using (playerManager.GetConnectedPlayers(out var connectedPlayers))
            {
                connectedPlayers.Add(player.Connection, player);
            }

            // Since the player is now connected, we can safely spawn his player model
            SimulatedWorld.SpawnRemotePlayerModel(player.Data);

            if (syncingCount == 0)
            {
                var inGamePlayersDatas = playerManager.GetAllPlayerDataIncludingHost();
                playerManager.SendPacketToAllPlayers(new SyncComplete(inGamePlayersDatas));
                SimulatedWorld.OnAllPlayersSyncCompleted();
            }
        }
예제 #13
0
        public void StartServer(int port)
        {
            EventBasedNetListener listener = new EventBasedNetListener();

            listener.ConnectionRequestEvent += OnConnectionRequest;
            listener.PeerConnectedEvent     += OnPeerConnected;
            listener.PeerDisconnectedEvent  += OnPeerDisconnected;
            listener.NetworkReceiveEvent    += OnNetworkReceive;

            server = new NetManager(listener)
            {
                AutoRecycle = true,
#if DEBUG
                SimulateLatency      = true,
                SimulatePacketLoss   = true,
                SimulationMinLatency = 50,
                SimulationMaxLatency = 100,
#endif
            };

            PlayerManager   = new PlayerManager();
            PacketProcessor = new NetPacketProcessor();
            LiteNetLibUtils.RegisterAllPacketNestedTypes(PacketProcessor);
            LiteNetLibUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor);

            server.Start(port);

            SimulatedWorld.Initialize();

            LocalPlayer.SetNetworkProvider(this);
            LocalPlayer.IsMasterClient = true;

            // TODO: Load saved player info here
            LocalPlayer.SetPlayerData(new PlayerData(PlayerManager.GetNextAvailablePlayerId(), new Float3(1.0f, 0.6846404f, 0.243137181f)));
        }
예제 #14
0
 public void ProcessPacket(ILSShipData packet, NebulaConnection conn)
 {
     using (FactoryManager.EventFromServer.On())
     {
         SimulatedWorld.OnILSShipUpdate(packet);
     }
 }
예제 #15
0
        private void ConnectInternal()
        {
            LocalPlayer.TryLoadGalacticScale2();

            clientSocket            = new WebSocket(socketAddress);
            clientSocket.OnOpen    += ClientSocket_OnOpen;
            clientSocket.OnClose   += ClientSocket_OnClose;
            clientSocket.OnMessage += ClientSocket_OnMessage;

            PacketProcessor = new NetPacketProcessor();
#if DEBUG
            PacketProcessor.SimulateLatency = true;
#endif

            PacketUtils.RegisterAllPacketNestedTypes(PacketProcessor);
            PacketUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor);

            clientSocket.Connect();

            SimulatedWorld.Initialize();

            LocalPlayer.IsMasterClient = false;
            LocalPlayer.SetNetworkProvider(this);

            if (Config.Options.RememberLastIP)
            {
                // We've successfully connected, set connection as last ip, cutting out "ws://" and "/socket"
                Config.Options.LastIP = socketAddress.Substring(5, socketAddress.Length - 12);
                Config.SaveOptions();
            }
        }
예제 #16
0
 public static void OnLateUpdate_Postfix(UIStarmap __instance)
 {
     if (SimulatedWorld.Initialized)
     {
         SimulatedWorld.RenderPlayerNameTagsOnStarmap(__instance);
     }
 }
예제 #17
0
 public static void GameTick_Postfix(long time, float dt)
 {
     if (SimulatedWorld.Initialized)
     {
         SimulatedWorld.OnDronesGameTick(time, dt);
     }
 }
예제 #18
0
        public override void ProcessPacket(TrashSystemNewTrashCreatedPacket packet, NebulaConnection conn)
        {
            bool valid = true;

            if (IsHost)
            {
                Player player = playerManager.GetPlayer(conn);
                if (player != null)
                {
                    playerManager.SendPacketToOtherPlayers(packet, player);
                }
                else
                {
                    valid = false;
                }
            }

            if (valid)
            {
                int myId = SimulatedWorld.GenerateTrashOnPlayer(packet);

                //Check if myID is same as the ID from the host
                if (myId != packet.TrashId)
                {
                    TrashManager.SwitchTrashWithIds(myId, packet.TrashId);
                }
            }
        }
예제 #19
0
        public override void ProcessPacket(StationUI packet, NebulaConnection conn)
        {
            if (IsHost)
            {
                // if a user adds/removes a ship, drone or warper or changes max power input broadcast to everyone.
                if (StationUIManager.UpdateCooldown == 0 &&
                    (packet.SettingIndex == StationUI.EUISettings.MaxChargePower ||
                     packet.SettingIndex == StationUI.EUISettings.SetDroneCount ||
                     packet.SettingIndex == StationUI.EUISettings.SetShipCount ||
                     packet.SettingIndex == StationUI.EUISettings.SetWarperCount)
                    )
                {
                    // this is the SendPacketToAllPlayers() logic but we need to set the mimic flag here.
                    using (playerManager.GetConnectedPlayers(out var connectedPlayers))
                    {
                        foreach (var kvp in connectedPlayers)
                        {
                            Player p = kvp.Value;
                            packet.ShouldMimic = p.Connection == conn;
                            p.SendPacket(packet);
                        }
                    }
                }
                else if (packet.SettingIndex == StationUI.EUISettings.AddOrRemoveItemFromStorageResponse)
                {
                    // if someone adds or removes items by hand broadcast to every player on that planet
                    Player player = playerManager.GetPlayer(conn);
                    if (player != null)
                    {
                        playerManager.SendPacketToPlanet(packet, player.Data.LocalPlanetId);
                    }
                }
                else if (StationUIManager.UpdateCooldown == 0 || !packet.IsStorageUI)
                {
                    List <NebulaConnection> subscribers = StationUIManager.GetSubscribers(packet.PlanetId, packet.StationId, packet.StationGId);

                    for (int i = 0; i < subscribers.Count; i++)
                    {
                        if (subscribers[i] != null)
                        {
                            /*
                             * as we block the normal method for the client he must run it once he receives this packet.
                             * but only the one issued the request should do it, we indicate this here
                             */
                            packet.ShouldMimic = subscribers[i] == conn;
                            subscribers[i].SendPacket(packet);
                        }
                    }
                }
                // always update values for host, but he does not need to rely on the mimic flag (infact its bad for him)
                packet.ShouldMimic = false;
                SimulatedWorld.OnStationUIChange(packet);
            }

            if (IsClient)
            {
                SimulatedWorld.OnStationUIChange(packet);
            }
        }
예제 #20
0
        private void ClientSocket_OnClose(object sender, CloseEventArgs e)
        {
            IsConnected      = false;
            serverConnection = null;

            UnityDispatchQueue.RunOnMainThread(() =>
            {
                // If the client is Quitting by himself, we don't have to inform him of his disconnection.
                if (e.Code == (ushort)DisconnectionReason.ClientRequestedDisconnect)
                {
                    return;
                }

                if (e.Code == (ushort)DisconnectionReason.ModVersionMismatch)
                {
                    string[] versions = e.Reason.Split(';');
                    InGamePopup.ShowWarning(
                        "Mod Version Mismatch",
                        $"Your Nebula Multiplayer Mod is not the same as the Host version.\nYou:{versions[0]} - Remote:{versions[1]}",
                        "OK",
                        OnDisconnectPopupCloseBeforeGameLoad);
                    return;
                }

                if (e.Code == (ushort)DisconnectionReason.GameVersionMismatch)
                {
                    string[] versions = e.Reason.Split(';');
                    InGamePopup.ShowWarning(
                        "Game Version Mismatch",
                        $"Your version of the game is not the same as the one used by the Host.\nYou:{versions[0]} - Remote:{versions[1]}",
                        "OK",
                        OnDisconnectPopupCloseBeforeGameLoad);
                    return;
                }

                if (SimulatedWorld.IsGameLoaded)
                {
                    InGamePopup.ShowWarning(
                        "Connection Lost",
                        $"You have been disconnected from the server.\n{e.Reason}",
                        "Quit",
                        () => LocalPlayer.LeaveGame());
                }
                else
                {
                    InGamePopup.ShowWarning(
                        "Server Unavailable",
                        $"Could not reach the server, please try again later.",
                        "OK",
                        () =>
                    {
                        LocalPlayer.IsMasterClient = false;
                        SimulatedWorld.Clear();
                        DestroySession();
                        OnDisconnectPopupCloseBeforeGameLoad();
                    });
                }
            });
        }
예제 #21
0
        public void ProcessPacket(VegeMined packet, NebulaConnection conn)
        {
            Player player = playerManager.GetPlayer(conn);

            playerManager.SendPacketToOtherPlayers(packet, player);

            SimulatedWorld.MineVegetable(packet);
        }
예제 #22
0
        public void ProcessPacket(HandshakeRequest packet, NebulaConnection conn)
        {
            Player player;

            if (!playerManager.PendingPlayers.TryGetValue(conn, out player))
            {
                conn.Disconnect(DisconnectionReason.InvalidData);
                Log.Warn("WARNING: Player tried to handshake without being in the pending list");
                return;
            }

            playerManager.PendingPlayers.Remove(conn);

            if (packet.ModVersion != Config.ModVersion.ToString())
            {
                conn.Disconnect(DisconnectionReason.ModVersionMismatch);
                return;
            }

            if (packet.GameVersionSig != GameConfig.gameVersion.sig)
            {
                conn.Disconnect(DisconnectionReason.GameVersionMismatch);
                return;
            }

            SimulatedWorld.OnPlayerJoining();

            //TODO: some validation of client cert / generating auth challenge for the client
            // Load old data of the client
            string clientCertHash = CryptoUtils.Hash(packet.ClientCert);

            if (playerManager.SavedPlayerData.ContainsKey(clientCertHash))
            {
                player.LoadUserData(playerManager.SavedPlayerData[clientCertHash]);
            }
            else
            {
                playerManager.SavedPlayerData.Add(clientCertHash, player.Data);
            }

            // Make sure that each player that is currently in the game receives that a new player as join so they can create its RemotePlayerCharacter
            PlayerData pdata = player.Data.CreateCopyWithoutMechaData(); // Remove inventory from mecha data

            foreach (Player activePlayer in playerManager.GetConnectedPlayers())
            {
                activePlayer.SendPacket(new PlayerJoining(pdata));
            }

            // Add the new player to the list
            playerManager.SyncingPlayers.Add(conn, player);

            //Add current tech bonuses to the connecting player based on the Host's mecha
            player.Data.Mecha.TechBonuses = new PlayerTechBonuses(GameMain.mainPlayer.mecha);

            var gameDesc = GameMain.data.gameDesc;

            player.SendPacket(new HandshakeResponse(gameDesc.galaxyAlgo, gameDesc.galaxySeed, gameDesc.starCount, gameDesc.resourceMultiplier, player.Data));
        }
예제 #23
0
        public static void Update_Prefix()
        {
            if (!SimulatedWorld.Initialized || !SimulatedWorld.IsGameLoaded)
            {
                return;
            }

            SimulatedWorld.RenderPlayerNameTagsInGame();
        }
예제 #24
0
        public void ProcessPacket(TrashSystemNewTrashCreatedPacket packet, NebulaConnection conn)
        {
            int myId = SimulatedWorld.GenerateTrashOnPlayer(packet);

            //Check if myID is same as the ID from the host
            if (myId != packet.TrashId)
            {
                TrashManager.SwitchTrashWithIds(myId, packet.TrashId);
            }
        }
예제 #25
0
 public void ProcessPacket(VegeMinedPacket packet, NebulaConnection conn)
 {
     if (GameMain.galaxy.PlanetById(packet.PlanetId)?.factory != null && GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.vegePool != null)
     {
         using (PlanetManager.EventFromServer.On())
         {
             SimulatedWorld.OnVegetationMined(packet);
         }
     }
 }
        public void ProcessPacket(GameStateUpdate packet, NebulaConnection conn)
        {
            GameState state = packet.State;
            // We offset the tick received to account for the current player ping
            long tickOffsetSinceSent = (long)System.Math.Round((conn.Ping / 2.0) / (GameMain.tickDeltaTime * 1000));

            state.gameTick += tickOffsetSinceSent;

            SimulatedWorld.UpdateGameState(state);
        }
예제 #27
0
 public static void FixedUpdate_Postfix(int ___frame)
 {
     if (___frame >= 11 && SimulatedWorld.Initialized)
     {
         SimulatedWorld.OnGameLoadCompleted();
         if (!LocalPlayer.IsMasterClient)
         {
             MultiplayerClientSession.Instance.DisplayPingIndicator();
         }
     }
 }
예제 #28
0
        public void ProcessPacket(PlayerAnimationUpdate packet, NebulaConnection conn)
        {
            Player player = playerManager.GetPlayer(conn);

            if (player != null)
            {
                packet.PlayerId = player.Id;
                playerManager.SendPacketToOtherPlayers(packet, player);

                SimulatedWorld.UpdateRemotePlayerAnimation(packet);
            }
        }
예제 #29
0
        public void PlayerDisconnected(NebulaConnection conn)
        {
            if (connectedPlayers.TryGetValue(conn, out Player player))
            {
                SendPacketToOtherPlayers(new PlayerDisconnected(player.Id), player);
                connectedPlayers.Remove(conn);
                availablePlayerIds.Enqueue(player.Id);
                SimulatedWorld.DestroyRemotePlayerModel(player.Id);
            }

            // TODO: Should probably also handle playing that disconnect during "pending" or "syncing" steps.
        }
예제 #30
0
        public void ProcessPacket(GameStateUpdate packet, NebulaConnection conn)
        {
            GameState state = packet.State;

            // We offset the tick received to account for the time it took to receive the packet
            long timeOffset          = TimeUtils.CurrentUnixTimestampMilliseconds() - packet.State.timestamp;
            long tickOffsetSinceSent = (long)System.Math.Round(timeOffset / (GameMain.tickDeltaTime * 1000));

            state.gameTick += tickOffsetSinceSent;

            SimulatedWorld.UpdateGameState(state);
        }