public override void Process(PlayFMODCustomLoopingEmitter packet)
    {
        GameObject            soundSource           = NitroxEntity.RequireObjectFrom(packet.Id);
        FMODEmitterController fmodEmitterController = soundSource.RequireComponent <FMODEmitterController>();

        fmodEmitterController.PlayCustomLoopingEmitter(packet.AssetPath);
    }
Example #2
0
        public void ToggleEngineState(NitroxId id, bool isStarting, bool isOn, bool silent = false)
        {
            GameObject cyclops = NitroxEntity.RequireObjectFrom(id);
            CyclopsEngineChangeState engineState = cyclops.RequireComponentInChildren <CyclopsEngineChangeState>();
            CyclopsMotorMode         motorMode   = cyclops.RequireComponentInChildren <CyclopsMotorMode>();

            if (isOn == engineState.motorMode.engineOn)
            {
                if ((isStarting != (bool)engineState.ReflectionGet("startEngine")) != isOn)
                {
                    if (Player.main.currentSub != engineState.subRoot || silent)
                    {
                        engineState.ReflectionSet("startEngine", !isOn);
                        engineState.ReflectionSet("invalidButton", true);
                        engineState.Invoke("ResetInvalidButton", 2.5f);
                        engineState.subRoot.BroadcastMessage("InvokeChangeEngineState", !isOn, SendMessageOptions.RequireReceiver);
                    }
                    else
                    {
                        engineState.ReflectionSet("invalidButton", false);
                        using (packetSender.Suppress <CyclopsToggleInternalLighting>())
                        {
                            engineState.OnClick();
                        }
                    }
                }
            }
        }
        public override void Process(DeconstructionBegin packet)
        {
            GameObject    deconstructing = NitroxEntity.RequireObjectFrom(packet.Id);
            Constructable constructable  = deconstructing.RequireComponent <Constructable>();

            constructable.SetState(false, false);
        }
Example #4
0
        public override void Process(ModuleRemoved packet)
        {
            GameObject           owner       = NitroxEntity.RequireObjectFrom(packet.OwnerId);
            GameObject           item        = NitroxEntity.RequireObjectFrom(packet.ItemId);
            Pickupable           pickupable  = item.RequireComponent <Pickupable>();
            Optional <Equipment> opEquipment = EquipmentHelper.GetBasedOnOwnersType(owner);

            if (opEquipment.IsPresent())
            {
                Equipment equipment = opEquipment.Get();

                Dictionary <string, InventoryItem> itemsBySlot = (Dictionary <string, InventoryItem>)equipment.ReflectionGet("equipment");
                InventoryItem inventoryItem = itemsBySlot[packet.Slot];
                itemsBySlot[packet.Slot] = null;

                equipment.ReflectionCall("UpdateCount", false, false, new object[] { pickupable.GetTechType(), false });
                Equipment.SendEquipmentEvent(pickupable, UNEQUIP_EVENT_TYPE_ID, owner, packet.Slot);
                equipment.ReflectionCall("NotifyUnequip", false, false, new object[] { packet.Slot, inventoryItem });
            }
            else
            {
                Log.Error("Could not find equipment type for " + owner.name);
            }

            UnityEngine.Object.Destroy(item);
        }
Example #5
0
        public void RemoveItem(NitroxId ownerId, bool silent = false)
        {
            GameObject             owner   = NitroxEntity.RequireObjectFrom(ownerId);
            Optional <EnergyMixin> opMixin = Optional.OfNullable(owner.GetComponent <EnergyMixin>());

            if (opMixin.HasValue)
            {
                EnergyMixin mixin = opMixin.Value;
                StorageSlot slot  = mixin.batterySlot;

                // Suppress sound when silent is active
                // Will be used to suppress swap sound at the initialisation of the game
                bool allowedToPlaySounds = true;
                if (silent)
                {
                    allowedToPlaySounds       = mixin.allowedToPlaySounds;
                    mixin.allowedToPlaySounds = !silent;
                }
                using (packetSender.Suppress <StorageSlotItemRemove>())
                {
                    slot.RemoveItem();
                }
                if (silent)
                {
                    mixin.allowedToPlaySounds = allowedToPlaySounds;
                }
            }
            else
            {
                Log.Error("Removing storage slot item: Could not find storage slot field on object " + owner.name);
            }
        }
Example #6
0
        public override void Process(ModuleRemoved packet)
        {
            GameObject           owner       = NitroxEntity.RequireObjectFrom(packet.OwnerId);
            Optional <Equipment> opEquipment = EquipmentHelper.FindEquipmentComponent(owner);

            if (!opEquipment.HasValue)
            {
                Log.Error("Could not find equipment type for " + owner.name);
                return;
            }

            GameObject item       = NitroxEntity.RequireObjectFrom(packet.ItemId);
            Pickupable pickupable = item.RequireComponent <Pickupable>();
            Equipment  equipment  = opEquipment.Value;
            Dictionary <string, InventoryItem> itemsBySlot = equipment.equipment;
            InventoryItem inventoryItem = itemsBySlot[packet.Slot];

            itemsBySlot[packet.Slot] = null;

            equipment.UpdateCount(pickupable.GetTechType(), false);
            Equipment.SendEquipmentEvent(pickupable, UNEQUIP_EVENT_TYPE_ID, owner, packet.Slot);
            equipment.NotifyUnequip(packet.Slot, inventoryItem);

            UnityEngine.Object.Destroy(item);
        }
Example #7
0
        public void ProcessRemoteHealthChange(NitroxId id, float LifeChanged, Optional <DamageTakenData> opDamageTakenData, float totalHealth)
        {
            if (simulationOwnership.HasAnyLockType(id))
            {
                Log.Error($"Got LiveMixin change health for {id} but we have the simulation already. This should not happen!");
                return;
            }
            LiveMixin liveMixin = NitroxEntity.RequireObjectFrom(id).GetComponent <LiveMixin>();

            // For remote processing, we add an outstanding health change that makes it possible to pass execution
            outstandingChangeHealth.Add(id, new Tuple <float, float>(LifeChanged, liveMixin.health));
            if (LifeChanged < 0)
            {
                DamageTakenData       damageTakenData = opDamageTakenData.OrElse(null);
                Optional <GameObject> opDealer        = damageTakenData.DealerId.HasValue ? NitroxEntity.GetObjectFrom(damageTakenData.DealerId.Value) : Optional.Empty;
                GameObject            dealer          = opDealer.HasValue ? opDealer.Value : null;
                if (!dealer && damageTakenData.DealerId.HasValue)
                {
                    Log.Warn($"Could not find entity {damageTakenData.DealerId.Value} for damage calculation. This could lead to problems.");
                }
                liveMixin.TakeDamage(-LifeChanged, damageTakenData.Position.ToUnity(), (DamageType)damageTakenData.DamageType, dealer);
            }
            else
            {
                liveMixin.AddHealth(LifeChanged);
            }

            // Check if the health calculated by the game is the same as the calculated damage from the simulator
            if (liveMixin.health != totalHealth)
            {
                Log.Warn($"Calculated health and send health for {id} do not align (Calculated: {liveMixin.health}, send:{totalHealth}). This will be correted but should be investigated");
                liveMixin.health = totalHealth;
            }
        }
        public override void Process(VehicleNameChange namePacket)
        {
            SubNameInput subNameInput;

            if (namePacket.ParentId.HasValue)
            {
                GameObject moonpool = NitroxEntity.RequireObjectFrom(namePacket.ParentId.Value);
                GameObject baseCell = moonpool.RequireComponentInParent <BaseCell>().gameObject;

                subNameInput = baseCell.GetComponentInChildren <SubNameInput>();
            }
            else
            {
                GameObject vehicleObject = NitroxEntity.RequireObjectFrom(namePacket.VehicleId);
                subNameInput = vehicleObject.GetComponentInChildren <SubNameInput>();
            }

            using (packetSender.Suppress <VehicleNameChange>())
            {
                if (subNameInput && subNameInput.target)
                {
                    // OnColorChange calls these two methods, in order to update the vehicle name on the ingame panel:
                    subNameInput.target.SetName(namePacket.Name);
                    subNameInput.SetName(namePacket.Name);
                }
                else
                {
                    Log.Error($"[VehicleNameChangeProcessor] SubNameInput or targeted SubName is null with {namePacket}.");
                }
            }
        }
Example #9
0
        public void ChangeSonarMode(NitroxId id, bool isOn)
        {
            GameObject         cyclops = NitroxEntity.RequireObjectFrom(id);
            CyclopsSonarButton sonar   = cyclops.GetComponentInChildren <CyclopsSonarButton>();

            if (sonar != null)
            {
                using (packetSender.Suppress <CyclopsChangeSonarMode>())
                {
                    // At this moment the code is "non functional" as for some reason changing the sprite will never happen
                    // Also setting sonar as active will never work

                    MethodInfo sonarSetActiveInfo = sonar.GetType().GetMethod("set_sonarActive", BindingFlags.NonPublic | BindingFlags.Instance);
                    if (sonarSetActiveInfo != null)
                    {
                        sonarSetActiveInfo.Invoke(sonar, new object[] { isOn });
                    }
                    if (isOn)
                    {
                        sonar.image.sprite = sonar.activeSprite;
                    }
                    else
                    {
                        sonar.image.sprite = sonar.inactiveSprite;
                    }
                }
            }
        }
Example #10
0
        public void ChangeSilentRunning(NitroxId id, bool isOn)
        {
            GameObject cyclops = NitroxEntity.RequireObjectFrom(id);
            CyclopsSilentRunningAbilityButton ability = cyclops.RequireComponentInChildren <CyclopsSilentRunningAbilityButton>();

            using (packetSender.Suppress <CyclopsChangeSilentRunning>())
            {
                if ((bool)ability.ReflectionGet("active") != isOn)
                {
                    Log.Debug("Set silent running to " + isOn + " for " + id);
                    ability.ReflectionSet("active", isOn);
                    if (isOn)
                    {
                        ability.image.sprite = ability.activeSprite;
                        ability.subRoot.BroadcastMessage("RigForSilentRunning");
                        ability.InvokeRepeating("SilentRunningIteration", 0f, ability.silentRunningIteration);
                    }
                    else
                    {
                        ability.image.sprite = ability.inactiveSprite;
                        ability.subRoot.BroadcastMessage("SecureFromSilentRunning");
                        ability.CancelInvoke("SilentRunningIteration");
                    }
                }
            }
        }
Example #11
0
        // The next two functions could potentially reside outside of this specific serializer.
        // They only happen to be in here because dropped items use this code path.

        private void AssignToWaterPark(GameObject gameObject, NitroxId waterParkId)
        {
            Pickupable pickupable  = gameObject.RequireComponent <Pickupable>();
            GameObject waterParkGo = NitroxEntity.RequireObjectFrom(waterParkId);
            WaterPark  waterPark   = waterParkGo.RequireComponent <WaterPark>();

            waterPark.AddItem(pickupable);
        }
Example #12
0
        /// <summary>
        /// Finds and executes <see cref="Fire.Douse(float)"/>. If the fire is extinguished, it will pass a large float to trigger the private
        /// <see cref="Fire.Extinguish()"/> method.
        /// </summary>
        public override void Process(FireDoused packet)
        {
            GameObject fireGameObject = NitroxEntity.RequireObjectFrom(packet.Id);

            using (packetSender.Suppress <FireDoused>())
            {
                fireGameObject.RequireComponent <Fire>().Douse(packet.DouseAmount);
            }
        }
        public override void Process(GhostCrafterBeginCrafting packet)
        {
            GameObject   gameObject   = NitroxEntity.RequireObjectFrom(packet.GhostCrafterId);
            GhostCrafter ghostCrafter = gameObject.RequireComponentInChildren <GhostCrafter>(true);

            float buildDuration = packet.Duration + 0.2f; // small increase to prevent this player from swiping item from remote player

            ghostCrafter.logic.Craft(packet.TechType.ToUnity(), buildDuration);
        }
Example #14
0
        public void ChangeEngineMode(NitroxId id, CyclopsMotorMode.CyclopsMotorModes mode)
        {
            GameObject       cyclops   = NitroxEntity.RequireObjectFrom(id);
            CyclopsMotorMode motorMode = cyclops.RequireComponentInChildren <CyclopsMotorMode>();

            if (motorMode.cyclopsMotorMode != mode)
            {
                motorMode.BroadcastMessage("SetCyclopsMotorMode", mode, SendMessageOptions.RequireReceiver);
            }
        }
        public override void Process(VehicleNameChange namePacket)
        {
            GameObject   target       = NitroxEntity.RequireObjectFrom(namePacket.Id);
            SubNameInput subNameInput = target.RequireComponentInChildren <SubNameInput>();

            using (packetSender.Suppress <VehicleNameChange>())
            {
                subNameInput.OnNameChange(namePacket.Name);
            }
        }
Example #16
0
        public override void Process(EntityMetadataUpdate update)
        {
            GameObject gameObject = NitroxEntity.RequireObjectFrom(update.Id);

            Optional <EntityMetadataProcessor> metadataProcessor = EntityMetadataProcessor.FromMetaData(update.NewValue);

            Validate.IsTrue(metadataProcessor.HasValue, $"No processor found for EntityMetadata of type {update.NewValue.GetType()}");

            metadataProcessor.Value.ProcessMetadata(gameObject, update.NewValue);
        }
        public override void Process(OpenableStateChanged packet)
        {
            GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id);
            Openable   openable   = gameObject.RequireComponent <Openable>();

            using (packetSender.Suppress <OpenableStateChanged>())
            {
                openable.PlayOpenAnimation(packet.IsOpen, packet.Duration);
            }
        }
        public override void Process(EnergyMixinValueChanged energyMixinPacket)
        {
            GameObject  target      = NitroxEntity.RequireObjectFrom(energyMixinPacket.Id);
            EnergyMixin energyMixin = target.RequireComponent <EnergyMixin>();

            using (packetSender.Suppress <EnergyMixinValueChanged>())
            {
                energyMixin.ModifyCharge(energyMixinPacket.Value - energyMixin.charge);
            }
        }
        public override void Process(CyclopsDamagePointRepaired packet)
        {
            GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id);
            SubRoot    cyclops    = gameObject.RequireComponent <SubRoot>();

            using (packetSender.Suppress <CyclopsDamage>())
                using (packetSender.Suppress <CyclopsDamagePointRepaired>())
                {
                    cyclops.damageManager.damagePoints[packet.DamagePointIndex].liveMixin.AddHealth(packet.RepairAmount);
                }
        }
Example #20
0
        public override void UpdateMetadata(NitroxId id, SignMetadata metadata)
        {
            GameObject     gameObject = NitroxEntity.RequireObjectFrom(id);
            uGUI_SignInput sign       = gameObject.GetComponentInChildren <uGUI_SignInput>();

            sign.text          = metadata.Text;
            sign.colorIndex    = metadata.ColorIndex;
            sign.elementsState = metadata.Elements;
            sign.scaleIndex    = metadata.ScaleIndex;
            sign.SetBackground(metadata.Background);
        }
Example #21
0
        public override void Process(PowerLevelChanged packet)
        {
            GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.Id);

            if (packet.PowerType == PowerType.ENERGY_INTERFACE)
            {
                EnergyInterface energyInterface = gameObject.RequireComponent <EnergyInterface>();

                float amount = packet.Amount;
                float num    = 0f;
                if (GameModeUtils.RequiresPower())
                {
                    int num2 = 0;
                    if (packet.Amount > 0f)
                    {
                        float num3 = energyInterface.TotalCanConsume(out num2);
                        if (num3 > 0f)
                        {
                            float amount2 = amount / (float)num2;
                            for (int i = 0; i < energyInterface.sources.Length; i++)
                            {
                                EnergyMixin energyMixin = energyInterface.sources[i];
                                if (energyMixin != null && energyMixin.charge < energyMixin.capacity)
                                {
                                    num += energyMixin.ModifyCharge(amount2);
                                }
                            }
                        }
                    }
                    else
                    {
                        float num4 = energyInterface.TotalCanProvide(out num2);
                        if (num2 > 0)
                        {
                            amount = ((-amount <= num4) ? amount : (-num4));
                            for (int j = 0; j < energyInterface.sources.Length; j++)
                            {
                                EnergyMixin energyMixin2 = energyInterface.sources[j];
                                if (energyMixin2 != null && energyMixin2.charge > 0f)
                                {
                                    float num5 = energyMixin2.charge / num4;
                                    num += energyMixin2.ModifyCharge(amount * num5);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Log.Error("Unsupported packet power type: " + packet.PowerType);
            }
        }
Example #22
0
        public override void Process(CyclopsActivateHorn hornPacket)
        {
            GameObject         cyclops = NitroxEntity.RequireObjectFrom(hornPacket.Id);
            CyclopsHornControl horn    = cyclops.RequireComponentInChildren <CyclopsHornControl>();

            EventInstance eventInstance = (EventInstance)fieldInfo.GetValue(horn.hornSound);

            eventInstance.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, 150f);
            fieldInfo.SetValue(horn.hornSound, eventInstance);

            horn.OnHandClick(null);
        }
Example #23
0
        public override void Process(FabricatorBeginCrafting packet)
        {
            GameObject gameObject = NitroxEntity.RequireObjectFrom(packet.FabricatorId);
            Fabricator fabricator = gameObject.RequireComponentInChildren <Fabricator>(true);

            float buildDuration = packet.Duration + 0.2f; // small increase to prevent this player from swiping item from remote player

            FieldInfo    logic        = typeof(Crafter).GetField("_logic", BindingFlags.Instance | BindingFlags.NonPublic);
            CrafterLogic crafterLogic = (CrafterLogic)logic.GetValue(fabricator);

            crafterLogic.Craft(packet.TechType.ToUnity(), buildDuration);
        }
Example #24
0
        public void StartFireSuppression(NitroxId id)
        {
            GameObject cyclops = NitroxEntity.RequireObjectFrom(id);
            CyclopsFireSuppressionSystemButton fireSuppButton = cyclops.RequireComponentInChildren <CyclopsFireSuppressionSystemButton>();

            using (packetSender.Suppress <CyclopsFireSuppression>())
            {
                // Infos from SubFire.StartSystem
                fireSuppButton.subFire.StartCoroutine(StartFireSuppressionSystem(fireSuppButton.subFire));
                fireSuppButton.StartCooldown();
            }
        }
Example #25
0
        public override void Process(RocketStageUpdate packet)
        {
            GameObject gameObjectRocket = NitroxEntity.RequireObjectFrom(packet.Id);

            Rocket     rocket = gameObjectRocket.RequireComponent <Rocket>();
            GameObject build  = rocket.StartRocketConstruction();

            ItemGoalTracker.OnConstruct(packet.CurrentStageTech);

            RocketConstructor rocketConstructor = gameObjectRocket.RequireComponentInChildren <RocketConstructor>(true);

            rocketConstructor.SendBuildBots(build);
        }
Example #26
0
        public void SonarPing(NitroxId id)
        {
            GameObject         cyclops = NitroxEntity.RequireObjectFrom(id);
            CyclopsSonarButton sonar   = cyclops.GetComponentInChildren <CyclopsSonarButton>();

            if (sonar != null)
            {
                using (packetSender.Suppress <CyclopsSonarPing>())
                {
                    sonar.ReflectionCall("SonarPing");
                }
            }
        }
Example #27
0
        public void BeginCrafting(GameObject constructor, TechType techType, float duration)
        {
            NitroxId constructorId = NitroxEntity.GetId(constructor);

            Log.Debug("Building item from constructor with id: " + constructorId);

            Optional <object> opConstructedObject = TransientLocalObjectManager.Get(TransientObjectType.CONSTRUCTOR_INPUT_CRAFTED_GAMEOBJECT);

            if (opConstructedObject.HasValue)
            {
                GameObject constructedObject = (GameObject)opConstructedObject.Value;

                List <InteractiveChildObjectIdentifier> childIdentifiers = VehicleChildObjectIdentifierHelper.ExtractInteractiveChildren(constructedObject);
                Vehicle   vehicle             = constructedObject.GetComponent <Vehicle>();
                NitroxId  constructedObjectId = NitroxEntity.GetId(constructedObject);
                Vector3[] HSB       = new Vector3[5];
                Vector3[] Colours   = new Vector3[5];
                Vector4   tmpColour = Color.white;
                string    name      = "";
                float     health    = 1;

                if (!vehicle)
                { // Cyclops
                    GameObject   target        = NitroxEntity.RequireObjectFrom(constructedObjectId);
                    SubNameInput subNameInput  = target.RequireComponentInChildren <SubNameInput>();
                    SubName      subNameTarget = (SubName)subNameInput.ReflectionGet("target");

                    Colours = subNameTarget.GetColors();
                    HSB     = subNameTarget.GetColors();
                    name    = subNameTarget.GetName();
                    health  = target.GetComponent <LiveMixin>().health;
                }
                else if (vehicle)
                { // Seamoth & Prawn Suit
                    health  = vehicle.GetComponent <LiveMixin>().health;
                    name    = (string)vehicle.ReflectionCall("GetName", true);
                    HSB     = vehicle.subName.GetColors();
                    Colours = vehicle.subName.GetColors();
                }
                ConstructorBeginCrafting beginCrafting = new ConstructorBeginCrafting(constructorId, constructedObjectId, techType.Model(), duration, childIdentifiers, constructedObject.transform.position, constructedObject.transform.rotation,
                                                                                      name, HSB, Colours, health);
                vehicles.AddVehicle(VehicleModelFactory.BuildFrom(beginCrafting));
                packetSender.Send(beginCrafting);

                SpawnDefaultBatteries(constructedObject, childIdentifiers);
            }
            else
            {
                Log.Error("Could not send packet because there wasn't a corresponding constructed object!");
            }
        }
        public override void Process(RocketPreflightComplete packet)
        {
            GameObject gameObjectRocket = NitroxEntity.RequireObjectFrom(packet.Id);

            switch (packet.FlightCheck)
            {
            //Preflights inside the cockpit, we do want to ignore TimeCapsule for now
            case PreflightCheck.LifeSupport:
            case PreflightCheck.PrimaryComputer:

                CockpitSwitch[] cockpitSwitches = gameObjectRocket.GetComponentsInChildren <CockpitSwitch>(true);

                foreach (CockpitSwitch cockpitSwitch in cockpitSwitches)
                {
                    if (!cockpitSwitch.completed && cockpitSwitch.preflightCheck == packet.FlightCheck)
                    {
                        cockpitSwitch.animator.SetBool("Completed", true);
                        cockpitSwitch.completed = true;

                        cockpitSwitch.preflightCheckSwitch?.CompletePreflightCheck();

                        if (cockpitSwitch.collision)
                        {
                            cockpitSwitch.collision.SetActive(false);
                        }
                    }
                }

                break;

            //CommunicationsArray, Hydraulics, AuxiliaryPowerUnit
            default:

                ThrowSwitch[] throwSwitches = gameObjectRocket.GetComponentsInChildren <ThrowSwitch>(true);

                foreach (ThrowSwitch throwSwitch in throwSwitches)
                {
                    if (!throwSwitch.completed && throwSwitch.preflightCheck == packet.FlightCheck)
                    {
                        throwSwitch.animator?.SetTrigger("Throw");
                        throwSwitch.completed = true;
                        throwSwitch.preflightCheckSwitch?.CompletePreflightCheck();
                        throwSwitch.cinematicTrigger.showIconOnHandHover = false;
                        throwSwitch.triggerCollider.enabled = false;
                        throwSwitch.lamp.GetComponent <SkinnedMeshRenderer>().material = throwSwitch.completeMat;
                    }
                }

                break;
            }
        }
Example #29
0
        public override void Process(DeconstructionBegin packet)
        {
            Log.Info("Received deconstruction packet for basePieceId: " + packet.Id);

            GameObject          deconstructing      = NitroxEntity.RequireObjectFrom(packet.Id);
            BaseDeconstructable baseDeconstructable = deconstructing.RequireComponent <BaseDeconstructable>();

            TransientLocalObjectManager.Add(TransientObjectType.LATEST_DECONSTRUCTED_BASE_PIECE_GUID, packet.Id);

            using (packetSender.Suppress <DeconstructionBegin>())
            {
                baseDeconstructable.Deconstruct();
            }
        }
        public override void Process(VehicleOnPilotModeChanged packet)
        {
            GameObject vehicleGo = NitroxEntity.RequireObjectFrom(packet.VehicleId);
            Vehicle    vehicle   = vehicleGo.RequireComponent <Vehicle>();

            // If the vehicle is docked, then we will manually set the piloting mode
            // once the animations complete.  This prevents weird behaviour such as the
            // player existing the vehicle while it is about to dock (the event fires
            // before the animation completes on the remote player.)
            if (!vehicle.docked)
            {
                vehicles.SetOnPilotMode(packet.VehicleId, packet.PlayerId, packet.IsPiloting);
            }
        }