예제 #1
0
        /// <summary>
        /// Send object sync.
        /// </summary>
        /// <param name="objectID">The Object ID of the object.</param>
        /// <param name="setOwner">Set owner of the object.</param>
        public void SendObjectSync(int objectID, Vector3 pos, Quaternion rot, ObjectSyncManager.SyncTypes syncType, float[] syncedVariables, ObjectSyncManager.Flags flags)
        {
            if (NetManager.Instance.IsHost)
            {
                SendObjectSyncHost(objectID, pos, rot, syncType, syncedVariables, flags);
                return;
            }

            Network.Messages.ObjectSyncMessage msg = new Network.Messages.ObjectSyncMessage();
            msg.objectID = objectID;
            msg.SyncType = (int)syncType;
            if (syncedVariables != null)
            {
                msg.SyncedVariables = syncedVariables;
            }

            switch (flags)
            {
            case ObjectSyncManager.Flags.Full:
                msg.Position = Utils.GameVec3ToNet(pos);
                msg.Rotation = Utils.GameQuatToNet(rot);
                break;

            case ObjectSyncManager.Flags.RotationOnly:
                msg.Rotation = Utils.GameQuatToNet(rot);
                break;

            case ObjectSyncManager.Flags.PositionOnly:
                msg.Position = Utils.GameVec3ToNet(pos);
                break;
            }

            NetManager.Instance.BroadcastMessage(msg, Steamworks.EP2PSend.k_EP2PSendReliable);
        }
예제 #2
0
 /// <summary>
 /// Sends a sync update of the object.
 /// </summary>
 public void SendObjectSync(ObjectSyncManager.SyncTypes type, bool sendVariables, bool syncWasRequested)
 {
     if (sendVariables)
     {
         NetLocalPlayer.Instance.SendObjectSync(ObjectID, syncedObject.ObjectTransform().position, syncedObject.ObjectTransform().rotation, type, syncedObject.ReturnSyncedVariables(true));
     }
     else
     {
         NetLocalPlayer.Instance.SendObjectSync(ObjectID, syncedObject.ObjectTransform().position, syncedObject.ObjectTransform().rotation, type, null);
     }
 }
예제 #3
0
 /// <summary>
 /// Send object sync.
 /// </summary>
 /// <param name="objectID">The Object ID of the object.</param>
 /// <param name="setOwner">Set owner of the object.</param>
 public void SendObjectSync(int objectID, Vector3 pos, Quaternion rot, ObjectSyncManager.SyncTypes syncType, float[] syncedVariables)
 {
     Messages.ObjectSyncMessage msg = new Messages.ObjectSyncMessage();
     msg.objectID = objectID;
     msg.position = Utils.GameVec3ToNet(pos);
     msg.rotation = Utils.GameQuatToNet(rot);
     msg.SyncType = (int)syncType;
     if (syncedVariables != null)
     {
         msg.SyncedVariables = syncedVariables;
     }
     netManager.BroadcastMessage(msg, Steamworks.EP2PSend.k_EP2PSendReliable);
 }
예제 #4
0
        /// <summary>
        /// Sends a sync update of the object.
        /// </summary>
        public void SendObjectSync(ObjectSyncManager.SyncTypes type, bool sendVariables, bool syncWasRequested)
        {
            if (ObjectType == ObjectSyncManager.ObjectTypes.Weather)
            {
                SendObjectSync(ObjectID, syncedObject.ObjectTransform().localPosition, syncedObject.ObjectTransform().localRotation, type, syncedObject.ReturnSyncedVariables(true), syncedObject.flags());
            }

            if (sendVariables)
            {
                SendObjectSync(ObjectID, syncedObject.ObjectTransform().position, syncedObject.ObjectTransform().rotation, type, syncedObject.ReturnSyncedVariables(true), syncedObject.flags());
            }
            else
            {
                SendObjectSync(ObjectID, syncedObject.ObjectTransform().position, syncedObject.ObjectTransform().rotation, type, null, syncedObject.flags());
            }
        }
예제 #5
0
        /// <summary>
        /// Send object sync as the host.
        /// </summary>
        public void SendObjectSyncHost(int objectID, Vector3 pos, Quaternion rot, ObjectSyncManager.SyncTypes syncType, float[] syncedVariables, ObjectSyncManager.Flags flags)
        {
            Network.Messages.ObjectSyncMessage msg = new Network.Messages.ObjectSyncMessage();

            msg.objectID = objectID;
            msg.SyncType = (int)syncType;
            if (syncedVariables != null)
            {
                msg.SyncedVariables = syncedVariables;
            }

            switch (flags)
            {
            case ObjectSyncManager.Flags.Full:
                msg.Position = Utils.GameVec3ToNet(pos);
                msg.Rotation = Utils.GameQuatToNet(rot);
                break;

            case ObjectSyncManager.Flags.RotationOnly:
                msg.Rotation = Utils.GameQuatToNet(rot);
                break;

            case ObjectSyncManager.Flags.PositionOnly:
                msg.Position = Utils.GameVec3ToNet(pos);
                break;
            }

            if (syncType != ObjectSyncManager.SyncTypes.PeriodicSync && syncType != ObjectSyncManager.SyncTypes.GenericSync)
            {
                Network.Messages.ObjectSyncMessage msgBroadcast = new Network.Messages.ObjectSyncMessage();
                // Set owner as host.
                if (syncType == ObjectSyncManager.SyncTypes.SetOwner)
                {
                    if (Owner == null)
                    {
                        Owner                 = NetManager.Instance.GetLocalPlayer();
                        SyncEnabled           = true;
                        msgBroadcast.SyncType = (int)ObjectSyncManager.SyncTypes.SetOwner;
                    }
                }
                // Remove owner as host.
                else if (syncType == ObjectSyncManager.SyncTypes.RemoveOwner)
                {
                    Owner = null;
                    OwnerRemoved();
                    msgBroadcast.SyncType = (int)ObjectSyncManager.SyncTypes.RemoveOwner;
                }
                // Force take sync control as host.
                else if (syncType == ObjectSyncManager.SyncTypes.ForceSetOwner)
                {
                    SyncEnabled           = true;
                    msgBroadcast.SyncType = (int)ObjectSyncManager.SyncTypes.ForceSetOwner;
                }

                // Send updated ownership info to other clients.
                msgBroadcast.objectID      = msg.objectID;
                msgBroadcast.OwnerPlayerID = NetManager.Instance.GetPlayerIDBySteamID(Steamworks.SteamUser.GetSteamID());
                NetManager.Instance.BroadcastMessage(msgBroadcast, Steamworks.EP2PSend.k_EP2PSendReliable);
            }
            else
            {
                NetManager.Instance.BroadcastMessage(msg, Steamworks.EP2PSend.k_EP2PSendReliable);
            }
        }
예제 #6
0
        /// <summary>
        /// Register world related network message handlers.
        /// </summary>
        /// <param name="netMessageHandler">The network message handler to register
        /// messages to.</param>
        void RegisterNetworkMessagesHandlers(NetMessageHandler netMessageHandler)
        {
            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender,
                 Messages.PickupableSetPositionMessage msg) => {
                Client.Assert(ObjectSyncManager.Instance.ObjectIDs.ContainsKey(msg.id),
                              $"Tried to move pickupable that is not spawned {msg.id}.");
                GameObject gameObject =
                    ObjectSyncManager.Instance.ObjectIDs[msg.id].gameObject;
                gameObject.transform.position = Utils.NetVec3ToGame(msg.position);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.PickupableActivateMessage msg) => {
                GameObject gameObject = null;
                if (ObjectSyncManager.Instance.ObjectIDs.ContainsKey(msg.id))
                {
                    gameObject = ObjectSyncManager.Instance.ObjectIDs[msg.id].gameObject;
                }
                Client.Assert(gameObject != null,
                              "Tried to activate pickupable but its not spawned!");

                if (msg.activate)
                {
                    gameObject.SetActive(true);
                }
                else
                {
                    if (gameObject != null)
                    {
                        gameObject.SetActive(false);
                    }
                }
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.PickupableSpawnMessage msg) => {
                SpawnPickupable(msg);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.PickupableDestroyMessage msg) => {
                if (!ObjectSyncManager.Instance.ObjectIDs.ContainsKey(msg.id))
                {
                    return;
                }

                GameObject go;
                try {
                    go = ObjectSyncManager.Instance.ObjectIDs[msg.id].gameObject;
                } catch {
                    Logger.Error(
                        "Failed to remove object: OSC found but can't get GameObject.");
                    return;
                }

                GameObject.Destroy(
                    ObjectSyncManager.Instance.ObjectIDs[msg.id].gameObject);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender,
                 Messages.WorldPeriodicalUpdateMessage msg) => {
                // Game reports 'next hour' - we want to have transition so correct it.
                GameWorld.Instance.WorldTime = (float)msg.sunClock - 2.0f;
                GameWorld.Instance.WorldDay  = (int)msg.worldDay;
                GameWeatherManager.Instance.SetWeather(msg.currentWeather);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.PlayerSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Log(
                        $"Received synchronization packet from {sender} but there is not player registered using this id.");
                    return;
                }

                player.HandleSynchronize(msg);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.AnimSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Log(
                        $"Received animation synchronization packet from {sender} but there is not player registered using this id.");
                    return;
                }

                player.HandleAnimSynchronize(msg);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.OpenDoorsMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Log(
                        $"Received OpenDoorsMessage however there is no matching player {sender}! (open: {msg.open}");
                    return;
                }

                GameDoor doors = GameDoorsManager.Instance.FindGameDoors(
                    Utils.NetVec3ToGame(msg.position));
                if (doors == null)
                {
                    Logger.Log(
                        $"Player tried to open door, however, the door could not be found!");
                    return;
                }
                doors.Open(msg.open);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.FullWorldSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);

                // This one should never happen - if happens there is something done
                // miserably wrong.
                Client.Assert(player != null,
                              $"There is no player matching given steam id {sender}.");

                // Handle full world state synchronization.

                HandleFullWorldSync(msg);

                // Spawn host character.

                player.Spawn();

                // Set player state.

                player.Teleport(Utils.NetVec3ToGame(msg.spawnPosition),
                                Utils.NetQuatToGame(msg.spawnRotation));

                if (msg.pickedUpObject != NetPickupable.INVALID_ID)
                {
                    player.PickupObject(msg.pickedUpObject);
                }

                // World is loaded! Notify network manager about that.

                netManager.OnNetworkWorldLoaded();
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.AskForWorldStateMessage msg) => {
                var msgF = new Messages.FullWorldSyncMessage();
                WriteFullWorldSync(msgF);
                netManager.BroadcastMessage(
                    msgF, Steamworks.EP2PSend.k_EP2PSendReliable);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.VehicleEnterMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error(
                        $"Steam user of id {sender} send message however there is no active player matching this id.");
                    return;
                }

                ObjectSyncComponent vehicle =
                    ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                if (vehicle == null)
                {
                    Logger.Error("Player " + player.SteamId +
                                 " tried to enter vehicle with Object ID " + msg.objectID +
                                 " but there is no vehicle with such id.");
                    return;
                }

                player.EnterVehicle(vehicle, msg.passenger);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.VehicleLeaveMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error(
                        $"Steam user of id {sender} send message however there is no active player matching this id.");
                    return;
                }
                player.LeaveVehicle();
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.VehicleStateMessage msg) => {
                float startTime = -1;

                ObjectSyncComponent vehicle =
                    ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                if (vehicle == null)
                {
                    Logger.Log("Remote player tried to set state of vehicle " +
                               msg.objectID + " but there is no vehicle with such id.");
                    return;
                }

                if (msg.HasStartTime)
                {
                    startTime = msg.StartTime;
                }

                PlayerVehicle subType = vehicle.GetObjectSubtype() as PlayerVehicle;
                subType.SetEngineState((PlayerVehicle.EngineStates)msg.state,
                                       (PlayerVehicle.DashboardStates)msg.dashstate, startTime);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.VehicleSwitchMessage msg) => {
                float newValueFloat = -1;

                PlayerVehicle vehicle =
                    ObjectSyncManager.Instance.ObjectIDs[msg.objectID].GetObjectSubtype()
                    as PlayerVehicle;
                if (vehicle == null)
                {
                    Logger.Log("Remote player tried to change a switch in vehicle " +
                               msg.objectID + " but there is no vehicle with such id.");
                    return;
                }

                if (msg.HasSwitchValueFloat)
                {
                    newValueFloat = msg.SwitchValueFloat;
                }

                vehicle.SetVehicleSwitch((PlayerVehicle.SwitchIDs)msg.switchID,
                                         msg.switchValue, newValueFloat);
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.LightSwitchMessage msg) => {
                LightSwitch light = Game.LightSwitchManager.Instance.FindLightSwitch(
                    Utils.NetVec3ToGame(msg.pos));
                light.TurnOn(msg.toggle);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.ObjectSyncMessage msg) => {
                ObjectSyncComponent osc;
                ObjectSyncManager.SyncTypes type = (ObjectSyncManager.SyncTypes)msg.SyncType;
                try {
                    osc = ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                } catch {
                    Logger.Log(
                        $"Specified object is not yet added to the ObjectID's Dictionary! (Object ID: {msg.objectID})");
                    return;
                }
                if (osc != null)
                {
                    // Set owner.
                    if (type == ObjectSyncManager.SyncTypes.SetOwner)
                    {
                        if (osc.Owner == ObjectSyncManager.NO_OWNER ||
                            osc.Owner == sender.m_SteamID)
                        {
                            osc.OwnerSetToRemote(sender.m_SteamID);
                            netManager.GetLocalPlayer().SendObjectSyncResponse(osc.ObjectID, true);
                        }
                        else
                        {
                            Logger.Debug(
                                $"Set owner request rejected for object: {osc.transform.name} (Owner: {osc.Owner} Sender: {sender.m_SteamID})");
                        }
                    }
                    // Remove owner.
                    else if (type == ObjectSyncManager.SyncTypes.RemoveOwner)
                    {
                        if (osc.Owner == sender.m_SteamID)
                        {
                            osc.OwnerRemoved();
                        }
                    }
                    // Force set owner.
                    else if (type == ObjectSyncManager.SyncTypes.ForceSetOwner)
                    {
                        osc.Owner = sender.m_SteamID;
                        netManager.GetLocalPlayer().SendObjectSyncResponse(osc.ObjectID, true);
                        osc.SyncTakenByForce();
                        osc.SyncEnabled = false;
                    }

                    // Set object's position and variables
                    if (osc.Owner == sender.m_SteamID ||
                        type == ObjectSyncManager.SyncTypes.PeriodicSync)
                    {
                        if (msg.HasSyncedVariables == true)
                        {
                            osc.HandleSyncedVariables(msg.SyncedVariables);
                        }
                        osc.SetPositionAndRotation(Utils.NetVec3ToGame(msg.position),
                                                   Utils.NetQuatToGame(msg.rotation));
                    }
                }
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.ObjectSyncResponseMessage msg) => {
                ObjectSyncComponent osc =
                    ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                if (msg.accepted)
                {
                    osc.SyncEnabled = true;
                    osc.Owner       = Steamworks.SteamUser.GetSteamID().m_SteamID;
                }
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender,
                                                  Messages.ObjectSyncRequestMessage
                                                  msg) => {
                try {
                    ObjectSyncComponent osc =
                        ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                    osc.SendObjectSync(ObjectSyncManager.SyncTypes.GenericSync, true, true);
                } catch {
                    Logger.Error(
                        $"Remote client tried to request object sync of an unknown object, Object ID: {msg.objectID}");
                }
            });

            netMessageHandler.BindMessageHandler(
                (Steamworks.CSteamID sender, Messages.EventHookSyncMessage msg) => {
                if (msg.request)
                {
                    EventHook.SendSync(msg.fsmID);
                }
                else
                {
                    if (msg.HasFsmEventName)
                    {
                        EventHook.HandleEventSync(
                            msg.fsmID, msg.fsmEventID, msg.FsmEventName);
                    }
                    else
                    {
                        EventHook.HandleEventSync(msg.fsmID, msg.fsmEventID);
                    }
                }
            });
        }
예제 #7
0
        /// <summary>
        /// Register world related network message handlers.
        /// </summary>
        /// <param name="netMessageHandler">The network message handler to register messages to.</param>
        void RegisterNetworkMessagesHandlers(NetMessageHandler netMessageHandler)
        {
            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.PickupableSetPositionMessage msg) => {
                Client.Assert(ObjectSyncManager.GetObjectByID(msg.id), $"Tried to move pickupable that is not spawned {msg.id}.");
                GameObject gameObject         = ObjectSyncManager.GetObjectByID(msg.id);
                gameObject.transform.position = Utils.NetVec3ToGame(msg.position);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.PickupableActivateMessage msg) => {
                GameObject gameObject = null;
                if (ObjectSyncManager.GetObjectByID(msg.id))
                {
                    gameObject = ObjectSyncManager.GetObjectByID(msg.id);
                }
                Client.Assert(gameObject != null, "Tried to activate a pickupable but it's not spawned! Does any connected client or you have other mods beside MSC:MP installed? Try uninstalling them!");

                if (msg.activate)
                {
                    gameObject.SetActive(true);
                }
                else
                {
                    if (gameObject != null)
                    {
                        gameObject.SetActive(false);
                    }
                }
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.PickupableSpawnMessage msg) => {
                SpawnPickupable(msg);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.PickupableDestroyMessage msg) => {
                if (!ObjectSyncManager.GetSyncComponentByID(msg.id))
                {
                    return;
                }

                ObjectSyncComponent osc = ObjectSyncManager.GetSyncComponentByID(msg.id);

                GameObject.Destroy(ObjectSyncManager.GetObjectByID(msg.id));
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.WorldPeriodicalUpdateMessage msg) => {
                // Game reports 'next hour' - we want to have transition so correct it.
                GameWorld.Instance.WorldTime = (float)msg.sunClock - 2.0f;
                GameWorld.Instance.WorldDay  = (int)msg.worldDay;
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.PlayerSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error($"Received synchronization packet from {sender} but there is not player registered using this id.");
                    return;
                }

                player.HandleSynchronize(msg);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.AnimSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error($"Received animation synchronization packet from {sender} but there is not player registered using this id.");
                    return;
                }

                player.HandleAnimSynchronize(msg);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.OpenDoorsMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error($"Received OpenDoorsMessage however there is no matching player {sender}! (open: {msg.open}");
                    return;
                }

                GameDoor doors = GameDoorsManager.Instance.FindGameDoors(Utils.NetVec3ToGame(msg.position));
                if (doors == null)
                {
                    Logger.Error($"Player tried to open door, however, the door could not be found!");
                    return;
                }
                doors.Open(msg.open);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.FullWorldSyncMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);

                // This one should never happen - if happens there is something done miserably wrong.
                Client.Assert(player != null, $"There is no player matching given steam id {sender}.");

                // Handle full world state synchronization.

                HandleFullWorldSync(msg);

                // Spawn host character.

                player.Spawn();

                // Set player state.

                player.Teleport(Utils.NetVec3ToGame(msg.spawnPosition), Utils.NetQuatToGame(msg.spawnRotation));

                if (msg.pickedUpObject != NetPickupable.INVALID_ID)
                {
                    player.PickupObject(msg.pickedUpObject);
                }

                // World is loaded! Notify network manager about that.

                netManager.OnNetworkWorldLoaded();
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.AskForWorldStateMessage msg) => {
                var msgF = new Messages.FullWorldSyncMessage();
                WriteFullWorldSync(msgF);
                netManager.SendMessage(netManager.GetPlayer(sender), msgF, Steamworks.EP2PSend.k_EP2PSendReliable);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.VehicleEnterMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error($"Steam user of id {sender} send message however there is no active player matching this id.");
                    return;
                }

                ObjectSyncComponent vehicle = ObjectSyncManager.Instance.ObjectIDs[msg.objectID];
                if (vehicle == null)
                {
                    Logger.Error("Player " + player.SteamId + " tried to enter vehicle with Object ID " + msg.objectID + " but there is no vehicle with such id.");
                    return;
                }

                player.EnterVehicle(vehicle, msg.passenger);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.VehicleLeaveMessage msg) => {
                NetPlayer player = netManager.GetPlayer(sender);
                if (player == null)
                {
                    Logger.Error($"Steam user of id {sender} send message however there is no active player matching this id.");
                    return;
                }
                player.LeaveVehicle();
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.VehicleSwitchMessage msg) => {
                float newValueFloat = -1;

                PlayerVehicle vehicle = ObjectSyncManager.Instance.ObjectIDs[msg.objectID].GetObjectSubtype() as PlayerVehicle;
                if (vehicle == null)
                {
                    Logger.Debug("Remote player tried to change a switch in vehicle " + msg.objectID + " but there is no vehicle with such id.");
                    return;
                }

                if (msg.HasSwitchValueFloat)
                {
                    newValueFloat = msg.SwitchValueFloat;
                }

                vehicle.SetVehicleSwitch((PlayerVehicle.SwitchIDs)msg.switchID, msg.switchValue, newValueFloat);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.LightSwitchMessage msg) => {
                LightSwitch light = LightSwitchManager.Instance.FindLightSwitch(Utils.NetVec3ToGame(msg.pos));
                light.TurnOn(msg.toggle);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.ObjectSyncMessage msg) => {
                ObjectSyncComponent osc;
                ObjectSyncManager.SyncTypes type = (ObjectSyncManager.SyncTypes)msg.SyncType;
                if (ObjectSyncManager.GetObjectByID(msg.objectID))
                {
                    osc = ObjectSyncManager.GetSyncComponentByID(msg.objectID);
                }
                else
                {
                    Logger.Error($"Specified object is not yet added to the ObjectID's Dictionary! (Object ID: {msg.objectID})");
                    return;
                }

                // This *should* never happen, but apparently it's possible.
                Client.Assert(osc != null, $"Object Sync Component wasn't found for object with ID {msg.objectID}, however, the object had a dictionary entry!");

                // Host controls who owns an object.
                if (NetManager.Instance.IsHost)
                {
                    // Set owner on host.
                    if (type == ObjectSyncManager.SyncTypes.SetOwner)
                    {
                        ObjectSyncManager.SetOwnerHandler(msg, osc, sender);
                    }
                    // Remove owner on host.
                    if (type == ObjectSyncManager.SyncTypes.RemoveOwner)
                    {
                        if (osc.Owner == netManager.GetLocalPlayer())
                        {
                            ObjectSyncManager.RemoveOwnerHandler(msg, osc, sender);
                        }
                    }
                    // Sync taken by force on host.
                    if (type == ObjectSyncManager.SyncTypes.ForceSetOwner)
                    {
                        ObjectSyncManager.SyncTakenByForceHandler(msg, osc, sender);
                    }
                }

                // Set ownership info on clients.
                else
                {
                    NetPlayer player = netManager.GetPlayerByPlayerID(msg.OwnerPlayerID);
                    // Check if player exists.
                    if (player == null)
                    {
                        return;
                    }
                    // Set owner.
                    if (type == ObjectSyncManager.SyncTypes.SetOwner)
                    {
                        if (osc.Owner != netManager.GetLocalPlayer())
                        {
                            osc.OwnerSetToRemote(player);
                        }
                        osc.Owner = player;
                    }
                    // Remove owner.
                    else if (type == ObjectSyncManager.SyncTypes.RemoveOwner)
                    {
                        if (osc.Owner != netManager.GetLocalPlayer())
                        {
                            osc.OwnerRemoved();
                        }
                        osc.Owner = null;
                    }
                    // Force set owner.
                    else if (type == ObjectSyncManager.SyncTypes.ForceSetOwner)
                    {
                        if (osc.Owner != netManager.GetLocalPlayer())
                        {
                            osc.SyncTakenByForce();
                            osc.SyncEnabled = false;
                        }
                        osc.Owner = player;
                        if (osc.Owner == netManager.GetLocalPlayer())
                        {
                            osc.SyncEnabled = true;
                        }
                    }
                }

                // Set object's position and variables.
                if ((osc.Owner == netManager.GetPlayer(sender)) || type == ObjectSyncManager.SyncTypes.PeriodicSync)
                {
                    // Send synced variables, or variables only sync in some cases.
                    if (msg.HasSyncedVariables)
                    {
                        osc.HandleSyncedVariables(msg.SyncedVariables);
                    }

                    // Full sync.
                    if (msg.HasPosition && msg.HasRotation)
                    {
                        osc.SetPositionAndRotation(Utils.NetVec3ToGame(msg.Position), Utils.NetQuatToGame(msg.Rotation));
                    }
                    // Position only sync.
                    else if (msg.HasPosition)
                    {
                        Quaternion zero = new Quaternion(0, 0, 0, 0);
                        osc.SetPositionAndRotation(Utils.NetVec3ToGame(msg.Position), zero);
                    }
                    // Rotation only sync.
                    else if (msg.HasRotation)
                    {
                        osc.SetPositionAndRotation(Vector3.zero, Utils.NetQuatToGame(msg.Rotation));
                    }
                }
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.ObjectSyncResponseMessage msg) => {
                ObjectSyncComponent osc = ObjectSyncManager.GetSyncComponentByID(msg.objectID);
                if (msg.accepted)
                {
                    osc.SyncEnabled = true;
                    osc.Owner       = NetManager.Instance.GetLocalPlayer();
                }
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.ObjectSyncRequestMessage msg) => {
                Client.Assert(ObjectSyncManager.GetObjectByID(msg.objectID), $"Remote client tried to request object sync of an unknown object, remote ObjectID was: {msg.objectID}");

                ObjectSyncComponent osc = ObjectSyncManager.GetSyncComponentByID(msg.objectID);
                osc.SendObjectSync(ObjectSyncManager.SyncTypes.GenericSync, true, true);
            });

            netMessageHandler.BindMessageHandler((Steamworks.CSteamID sender, Messages.EventHookSyncMessage msg) => {
                if (msg.request)
                {
                    EventHook.SendSync(msg.fsmID);
                    return;
                }

                if (msg.HasFsmEventName)
                {
                    EventHook.HandleEventSync(msg.fsmID, msg.fsmEventID, msg.FsmEventName);
                }
                else
                {
                    EventHook.HandleEventSync(msg.fsmID, msg.fsmEventID);
                }
            });
        }