private void RemoveItemsFromVehicle(NitroxId id) { // Remove items in vehicles (for now just batteries) VehicleModel vehicle = vehiclesById[id]; InventoryData data = NitroxServiceLocator.LocateService <InventoryData>(); data.StorageItemRemoved(vehicle.Id); if (vehicle.InteractiveChildIdentifiers.IsPresent()) { foreach (InteractiveChildObjectIdentifier child in vehicle.InteractiveChildIdentifiers.Get()) { data.StorageItemRemoved(child.Id); } } }
public static bool Prefix(CyclopsLightingPanel __instance) { // Suppress powered on if a cyclops´s floodlight is set to false GameObject gameObject = __instance.gameObject.transform.parent.gameObject; // GO = LightsControl, Parent = main cyclops game object NitroxId id = NitroxEntity.GetId(gameObject); Optional <CyclopsModel> model = NitroxServiceLocator.LocateService <Vehicles>().TryGetVehicle <CyclopsModel>(id); if (!model.HasValue) { Log.Error($"{nameof(CyclopsLightingPanel_OnSubConstructionComplete_Patch)}: Could not find {nameof(CyclopsModel)} by Nitrox id {id}.\nGO containing wrong id: {__instance.GetHierarchyPath()}"); return(false); } return(model.Value.FloodLightsOn); }
private IEnumerator InitializeLocalPlayerState() { ILocalNitroxPlayer localPlayer = NitroxServiceLocator.LocateService <ILocalNitroxPlayer>(); IEnumerable <IColorSwapManager> colorSwapManagers = NitroxServiceLocator.LocateService <IEnumerable <IColorSwapManager> >(); ColorSwapAsyncOperation swapOperation = new ColorSwapAsyncOperation(localPlayer, colorSwapManagers).BeginColorSwap(); yield return(new WaitUntil(() => swapOperation.IsColorSwapComplete())); swapOperation.ApplySwappedColors(); // UWE developers added noisy logging for non-whitelisted components during serialization. // We add NitroxEntiy in here to avoid a large amount of log spam. ProtobufSerializer.componentWhitelist.Add(nameof(NitroxEntity)); }
public static void Execute() { Log.SetLevel(Log.LogLevel.ConsoleInfo | Log.LogLevel.ConsoleDebug | Log.LogLevel.InGameMessages | Log.LogLevel.FileLog); if (patches != null) { Log.Warn("Patches have already been detected! Call Apply or Restore instead."); return; } Log.Info("Registering Dependencies"); // Our application's entry point. First, register client dependencies with AutoFac. NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar()); Log.Info("Patching Subnautica..."); // Enabling this creates a log file on your desktop (why there?), showing the emitted IL instructions. HarmonyInstance.DEBUG = false; IEnumerable <NitroxPatch> discoveredPatches = Assembly.GetExecutingAssembly() .GetTypes() .Where(p => typeof(NitroxPatch).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract ) .Select(Activator.CreateInstance) .Cast <NitroxPatch>(); IEnumerable <IGrouping <string, NitroxPatch> > splittedPatches = discoveredPatches.GroupBy(p => p.GetType().Namespace); splittedPatches.First(g => g.Key == "NitroxPatcher.Patches.Persistent").ForEach(p => { Log.Info("Applying persistent patch " + p.GetType()); p.Patch(harmony); }); patches = splittedPatches.First(g => g.Key == "NitroxPatcher.Patches").ToArray(); Multiplayer.OnBeforeMultiplayerStart += Apply; Multiplayer.OnAfterMultiplayerEnd += Restore; Log.Info("Completed patching using " + Assembly.GetExecutingAssembly().FullName); Log.Info("Enabling developer console."); DevConsole.disableConsole = false; Application.runInBackground = true; Log.Info($"Unity run in background set to {Application.runInBackground.ToString().ToUpperInvariant()}."); ApplyNitroxBehaviours(); }
public static void Postfix(float?__state, LiveMixin __instance, float healthBack) { // Did we realize a change in health? if (__state.HasValue && __state.Value != __instance.health) { // Let others know if we have a lock on this entity NitroxId id = NitroxEntity.GetId(__instance.gameObject); bool hasLock = NitroxServiceLocator.LocateService <SimulationOwnership>().HasAnyLockType(id); if (hasLock) { TechType techType = CraftData.GetTechType(__instance.gameObject); NitroxServiceLocator.LocateService <LiveMixinManager>().BroadcastAddHealth(techType, id, healthBack, __instance.health); } } }
public static bool Prefix(ToggleLights __instance, bool powered) { // Find the right gameobject in the hierarchy to sync on: GameObject gameObject = null; // Suppress powered on if a seamoth´s default is set to false if (__instance.GetComponentInParent <SeaMoth>() != null && powered) { gameObject = __instance.transform.parent.gameObject; NitroxId id = NitroxEntity.GetId(gameObject); SeamothModel model = NitroxServiceLocator.LocateService <Vehicles>().GetVehicles <SeamothModel>(id); return(model.LightOn == __instance.lightsActive); } return(true); }
private void ProcessUnauthenticated(Packet packet, NitroxConnection connection) { try { Type serverPacketProcessorType = typeof(UnauthenticatedPacketProcessor <>); Type packetType = packet.GetType(); Type packetProcessorType = serverPacketProcessorType.MakeGenericType(packetType); PacketProcessor processor = (PacketProcessor)NitroxServiceLocator.LocateService(packetProcessorType); processor.ProcessPacket(packet, connection); } catch (Exception ex) { Log.Error(ex, $"Received invalid, unauthenticated packet: {packet}"); } }
public static bool Prefix(out float?__state, LiveMixin __instance) { __state = null; LiveMixinManager liveMixinManager = NitroxServiceLocator.LocateService <LiveMixinManager>(); if (!liveMixinManager.IsWhitelistedUpdateType(__instance)) { return(true); // everyone should process this locally } // Persist the previous health value __state = __instance.health; return(liveMixinManager.ShouldApplyNextHealthUpdate(__instance)); }
public static bool Prefix(SeaMoth __instance, TechType techType, int slotID, out PacketSuppressor <ItemContainerRemove> __state) { __state = null; if (techType == TechType.SeamothElectricalDefense) { NitroxServiceLocator.LocateService <SeamothModulesEvent>().BroadcastElectricalDefense(techType, slotID, __instance); } else if (techType == TechType.SeamothTorpedoModule) { __state = NitroxServiceLocator.LocateService <IPacketSender>().Suppress <ItemContainerRemove>(); NitroxServiceLocator.LocateService <SeamothModulesEvent>().BroadcastTorpedoLaunch(techType, slotID, __instance); } return(true); }
public void ShouldResolveGenericDependencies() { IServicer <ServiceRecipientA> servicerA = NitroxServiceLocator.LocateService <IServicer <ServiceRecipientA> >(); IServicer <ServiceRecipientB> servicerB = NitroxServiceLocator.LocateService <IServicer <ServiceRecipientB> >(); servicerA.Should().NotBeNull(); servicerA.Should().BeOfType <ServiceAProvider>(); Assert.ThrowsException <NotImplementedException>(() => servicerA.PerformService(null)); servicerB.Should().NotBeNull(); servicerB.Should().BeOfType <ServiceBProvider>(); Assert.ThrowsException <NotImplementedException>(() => servicerB.PerformService(null)); }
private World CreateWorld(DateTime serverStartTime, List <Entity> entities, List <BasePiece> partiallyConstructedPieces, List <BasePiece> completedBasePieceHistory, List <VehicleModel> vehicles, List <Player> players, List <ItemData> inventoryItems, List <ItemData> storageSlotItems, GameData gameData, List <Int3> parsedBatchCells, List <EscapePodModel> escapePods, StoryTimingData storyTimingData, string gameMode) { World world = new World(); world.TimeKeeper = new TimeKeeper(); world.TimeKeeper.ServerStartTime = serverStartTime; world.SimulationOwnershipData = new SimulationOwnershipData(); world.PlayerManager = new PlayerManager(players, config); world.EventTriggerer = new EventTriggerer(world.PlayerManager, storyTimingData.ElapsedTime, storyTimingData.AuroraExplosionTime); world.BaseManager = new BaseManager(partiallyConstructedPieces, completedBasePieceHistory); world.InventoryManager = new InventoryManager(inventoryItems, storageSlotItems); world.VehicleManager = new VehicleManager(vehicles, world.InventoryManager); world.GameData = gameData; world.EscapePodManager = new EscapePodManager(escapePods); world.GameMode = gameMode; world.BatchEntitySpawner = new BatchEntitySpawner(NitroxServiceLocator.LocateService <EntitySpawnPointFactory>(), NitroxServiceLocator.LocateService <UweWorldEntityFactory>(), NitroxServiceLocator.LocateService <UwePrefabFactory>(), parsedBatchCells, serializer, NitroxServiceLocator.LocateService <Dictionary <TechType, IEntityBootstrapper> >(), NitroxServiceLocator.LocateService <Dictionary <string, List <PrefabAsset> > >()); world.EntityManager = new EntityManager(entities, world.BatchEntitySpawner); HashSet <TechType> serverSpawnedSimulationWhiteList = NitroxServiceLocator.LocateService <HashSet <TechType> >(); world.EntitySimulation = new EntitySimulation(world.EntityManager, world.SimulationOwnershipData, world.PlayerManager, serverSpawnedSimulationWhiteList); Log.Info($"World GameMode: {gameMode}"); Log.Info($"Server Password: {(string.IsNullOrEmpty(config.ServerPassword) ? "None. Public Server." : config.ServerPassword)}"); Log.Info($"Admin Password: {config.AdminPassword}"); Log.Info($"Autosave: {(config.DisableAutoSave ? "DISABLED" : $"ENABLED ({config.SaveInterval / 60000} min)")}");
private World CreateWorld(DateTime serverStartTime, List <Entity> entities, List <BasePiece> partiallyConstructedPieces, List <BasePiece> completedBasePieceHistory, List <VehicleModel> vehicles, List <Player> players, List <ItemData> inventoryItems, List <ItemData> storageSlotItems, GameData gameData, List <Int3> parsedBatchCells, List <EscapePodModel> escapePods, StoryTimingData storyTimingData, ServerGameMode gameMode) { World world = new World(); world.TimeKeeper = new TimeKeeper(); world.TimeKeeper.ServerStartTime = serverStartTime; world.SimulationOwnershipData = new SimulationOwnershipData(); world.PlayerManager = new PlayerManager(players, config); world.EventTriggerer = new EventTriggerer(world.PlayerManager, storyTimingData.ElapsedTime, storyTimingData.AuroraExplosionTime); world.BaseManager = new BaseManager(partiallyConstructedPieces, completedBasePieceHistory); world.InventoryManager = new InventoryManager(inventoryItems, storageSlotItems); world.VehicleManager = new VehicleManager(vehicles, world.InventoryManager); world.GameData = gameData; world.EscapePodManager = new EscapePodManager(escapePods); world.GameMode = gameMode; world.BatchEntitySpawner = new BatchEntitySpawner( NitroxServiceLocator.LocateService <EntitySpawnPointFactory>(), NitroxServiceLocator.LocateService <UweWorldEntityFactory>(), NitroxServiceLocator.LocateService <UwePrefabFactory>(), parsedBatchCells, protoBufSerializer, NitroxServiceLocator.LocateService <Dictionary <NitroxTechType, IEntityBootstrapper> >(), NitroxServiceLocator.LocateService <Dictionary <string, PrefabPlaceholdersGroupAsset> >() ); world.EntityManager = new EntityManager(entities, world.BatchEntitySpawner); HashSet <NitroxTechType> serverSpawnedSimulationWhiteList = NitroxServiceLocator.LocateService <HashSet <NitroxTechType> >(); world.EntitySimulation = new EntitySimulation(world.EntityManager, world.SimulationOwnershipData, world.PlayerManager, serverSpawnedSimulationWhiteList); return(world); }
public static void Execute() { Log.EnableInGameMessages(); if (container != null) { Log.Warn("Patches have already been detected! Call Apply or Restore instead."); return; } Log.Info("Registering Dependencies"); container = CreatePatchingContainer(); NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar()); InitPatches(); ApplyNitroxBehaviours(); }
public static void Prefix(ref Player __instance, EscapePod value) { NitroxId podId = null; if (value != null) { podId = NitroxEntity.GetId(value.gameObject); } // Why only send when podId is empty? // At the moment, SubrootId saves if a player is in an escape pod // Every time you leave an escape pod, BroadcastSubrootChange is called anyway, so this will reduce the load // and some bugs that can occur, due to both pod and base/cyclops use of the same field, will be suppressed if (podId != null) { NitroxServiceLocator.LocateService <LocalPlayer>().BroadcastEscapePodChange(Optional.OfNullable(podId)); } }
public static bool Prefix(PropulsionCannon __instance) { GameObject grabbed = __instance.grabbedObject; if (!grabbed) { return(false); } NitroxId id = NitroxEntity.GetId(grabbed); SimulationOwnership simulationOwnership = NitroxServiceLocator.LocateService <SimulationOwnership>(); // Request to be downgraded to a transient lock so we can still simulate the positioning. simulationOwnership.RequestSimulationLock(id, SimulationLockType.TRANSIENT); return(true); }
private static void ReceivedSimulationLockResponse(NitroxId id, bool lockAquired) { if (lockAquired) { NitroxServiceLocator.LocateService <Vehicles>().BroadcastVehicleUndocking(vehicleDockingBay, vehicleDockingBay.GetDockedVehicle()); skipPrefix = true; TARGET_METHOD.Invoke(dockedVehicle, new[] { guiHand }); skipPrefix = false; } else { HandReticle.main.SetInteractText("Another player is using this vehicle!"); HandReticle.main.SetIcon(HandReticle.IconType.HandDeny, 1f); dockedVehicle.isValidHandTarget = false; } }
public static void Postfix(VehicleDockingBay __instance) { Vehicle interpolatingVehicle = __instance.interpolatingVehicle; // Only send data, when interpolatingVehicle changes to avoid multiple packages send if (!interpolatingVehicle || interpolatingVehicle == prevInterpolatingVehicle) { return; } NitroxId id = NitroxEntity.GetId(interpolatingVehicle.gameObject); if (NitroxServiceLocator.LocateService <SimulationOwnership>().HasAnyLockType(id)) { Log.Debug($"Will send vehicle docking for {id}"); NitroxServiceLocator.LocateService <Vehicles>().BroadcastVehicleDocking(__instance, interpolatingVehicle); } }
public static void Callback() { // When a player scans a fragment, it will be deleted from the world. We want to send out a pickup event // before the object can be removed and corresponding scan data is invalidated. TechType techType = PDAScanner.scanTarget.techType; PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType); // Only do this for fragments and player scans or nearby fish if (entryData != null && entryData.destroyAfterScan && PDAScanner.scanTarget.gameObject && !PDAScanner.scanTarget.isPlayer) { // A lot of fragments are virtual entities (spawned by placeholders in the world). Sometimes the server only knows the id // of the placeholder and not the virtual entity. TODO: we will need to propagate deterministic ids to children entities for // these virtual entities. NitroxServiceLocator.LocateService <Item>().PickedUp(PDAScanner.scanTarget.gameObject, techType); } }
private IEnumerator InitializeLocalPlayerState() { ILocalNitroxPlayer localPlayer = NitroxServiceLocator.LocateService <ILocalNitroxPlayer>(); IEnumerable <IColorSwapManager> colorSwapManagers = NitroxServiceLocator.LocateService <IEnumerable <IColorSwapManager> >(); ColorSwapAsyncOperation swapOperation = new ColorSwapAsyncOperation(localPlayer, colorSwapManagers).BeginColorSwap(); yield return(new WaitUntil(() => swapOperation.IsColorSwapComplete())); swapOperation.ApplySwappedColors(); // UWE developers added noisy logging for non-whitelisted components during serialization. // We add NitroxEntiy in here to avoid a large amount of log spam. HashSet <string> whiteListedSerializableComponents = (HashSet <string>)ReflectionHelper.ReflectionGet <ProtobufSerializer>(null, "componentWhitelist", false, true); whiteListedSerializableComponents.Add("NitroxEntity"); }
public static void Execute() { Log.Setup(true); Optional.ApplyHasValueCondition <Object>(o => (bool)o); if (container != null) { Log.Warn($"Patches have already been detected! Call {nameof(Apply)} or {nameof(Restore)} instead."); return; } Log.Info("Registering dependencies"); container = CreatePatchingContainer(); NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar()); InitPatches(); ApplyNitroxBehaviours(); }
public static bool Prefix(SeaMoth __instance) { // Suppress powered on if a seamoth´s default is set to false GameObject gameObject = __instance.gameObject; NitroxId id = NitroxEntity.GetId(gameObject); Optional <SeamothModel> model = NitroxServiceLocator.LocateService <Vehicles>().TryGetVehicle <SeamothModel>(id); if (!model.HasValue) { Log.Error($"{nameof(Seamoth_SubConstructionComplete_Patch)}: Could not find {nameof(CyclopsModel)} by Nitrox id {id}.\nGO containing wrong id: {__instance.GetHierarchyPath()}"); return(false); } // Set lights of seamoth Validate.NotNull(__instance.toggleLights, $"toggleLights is Null on {__instance.gameObject.name} {__instance.transform.position}"); __instance.toggleLights.SetLightsActive(model.Value.LightOn); return(model.Value.LightOn); }
private static void ReceivedSimulationLockResponse(NitroxId id, bool lockAquired, HandInteraction <Incubator> context) { if (lockAquired) { IncubatorMetadata metadata = new IncubatorMetadata(true, true); Entities entities = NitroxServiceLocator.LocateService <Entities>(); entities.BroadcastMetadataUpdate(id, metadata); skipPrefix = true; TARGET_METHOD.Invoke(context.Target, new[] { context.GuiHand }); skipPrefix = false; } else { context.Target.gameObject.AddComponent <DenyOwnershipHand>(); } }
private static void ReceivedSimulationLockResponse(NitroxId id, bool lockAquired, HandInteraction <DockedVehicleHandTarget> context) { if (lockAquired) { VehicleDockingBay dockingBay = context.Target.dockingBay; NitroxServiceLocator.LocateService <Vehicles>().BroadcastVehicleUndocking(dockingBay, dockingBay.GetDockedVehicle(), true); skipPrefix = true; context.Target.OnHandClick(context.GuiHand); skipPrefix = false; } else { HandReticle.main.SetInteractText("Another player is using this vehicle!"); HandReticle.main.SetIcon(HandReticle.IconType.HandDeny, 1f); context.Target.isValidHandTarget = false; } }
private void ProcessAuthenticated(Packet packet, Player player) { Type serverPacketProcessorType = typeof(AuthenticatedPacketProcessor <>); Type packetType = packet.GetType(); Type packetProcessorType = serverPacketProcessorType.MakeGenericType(packetType); Optional <object> opProcessor = NitroxServiceLocator.LocateOptionalService(packetProcessorType); if (opProcessor.HasValue) { PacketProcessor processor = (PacketProcessor)opProcessor.Value; processor.ProcessPacket(packet, player); } else { defaultServerPacketProcessor.ProcessPacket(packet, player); } }
private void SetUpSound() { FMODSystem fmodSystem = NitroxServiceLocator.LocateService <FMODSystem>(); rpmSound = seamoth.engineSound.engineRpmSFX; revSound = seamoth.engineSound.engineRevUp; rpmSound.followParent = true; revSound.followParent = true; fmodSystem.IsWhitelisted(rpmSound.asset.path, out bool _, out radiusRpmSound); fmodSystem.IsWhitelisted(revSound.asset.path, out bool _, out radiusRevSound); rpmSound.GetEventInstance().setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f); revSound.GetEventInstance().setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 1f); rpmSound.GetEventInstance().setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, radiusRpmSound); revSound.GetEventInstance().setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, radiusRevSound); }
private static void SetLoadingComplete() { PropertyInfo property = PAXTerrainController.main.GetType().GetProperty("isWorking"); property.SetValue(PAXTerrainController.main, false, null); WaitScreen waitScreen = (WaitScreen)ReflectionHelper.ReflectionGet <WaitScreen>(null, "main", false, true); waitScreen.ReflectionCall("Hide"); List <WaitScreen.IWaitItem> items = (List <WaitScreen.IWaitItem>)waitScreen.ReflectionGet("items"); items.Clear(); PlayerManager remotePlayerManager = NitroxServiceLocator.LocateService <PlayerManager>(); DiscordController.Main.InitDRPDiving(Main.multiplayerSession.AuthenticationContext.Username, remotePlayerManager.GetTotalPlayerCount(), Main.multiplayerSession.IpAddress + ":" + Main.multiplayerSession.ServerPort); }
private static void SetLoadingComplete() { PropertyInfo property = PAXTerrainController.main.GetType().GetProperty("isWorking"); property.SetValue(PAXTerrainController.main, false, null); WaitScreen waitScreen = (WaitScreen)ReflectionHelper.ReflectionGet <WaitScreen>(null, "main", false, true); waitScreen.ReflectionCall("Hide"); List <WaitScreen.IWaitItem> items = (List <WaitScreen.IWaitItem>)waitScreen.ReflectionGet("items"); items.Clear(); PlayerManager remotePlayerManager = NitroxServiceLocator.LocateService <PlayerManager>(); LoadingScreenVersionText.DisableWarningText(); NitroxServiceLocator.LocateService <PlayerChatManager>().LoadChatKeyHint(); }
public static bool Prefix(SeaMoth __instance) { // Suppress powered on if a seamoth´s default is set to false GameObject gameObject = __instance.gameObject; NitroxId id = NitroxEntity.GetId(gameObject); Optional <SeamothModel> model = NitroxServiceLocator.LocateService <Vehicles>().TryGetVehicle <SeamothModel>(id); if (!model.HasValue) { Log.Error($"{nameof(Seamoth_SubConstructionComplete_Patch)}: Could not find {nameof(CyclopsModel)} by Nitrox id {id}.\nGO containing wrong id: {__instance.GetHierarchyPath()}"); return(false); } // Set lights of seamoth ToggleLights toggleLights = gameObject.RequireComponentInChildren <ToggleLights>(); toggleLights.lightsActive = model.Value.LightOn; return(model.Value.LightOn); }
public static Optional <ItemsContainer> TryGetContainerByOwner(GameObject owner) { SeamothStorageContainer seamothStorageContainer = owner.GetComponent <SeamothStorageContainer>(); if (seamothStorageContainer) { return(Optional.Of(seamothStorageContainer.container)); } StorageContainer storageContainer = owner.GetComponentInChildren <StorageContainer>(); if (storageContainer) { return(Optional.Of(storageContainer.container)); } BaseBioReactor baseBioReactor = owner.GetComponentInChildren <BaseBioReactor>(); if (baseBioReactor) { ItemsContainer container = (ItemsContainer)baseBioReactor.ReflectionGetProperty("container"); return(Optional.Of(container)); } if (owner.name == "Player") { return(Optional.Of(Inventory.Get().container)); } if (owner.GetComponentInChildren <PingInstance>().GetLabel().StartsWith("Player ")) { if (playerManager == null) { playerManager = NitroxServiceLocator.LocateService <PlayerManager>(); } Optional <RemotePlayer> opPlayer = playerManager.FindByName(owner.name); if (opPlayer.HasValue) { return(Optional.Of(opPlayer.Value.Inventory)); } } Log.Debug("Couldn't resolve container from gameObject: " + owner.name); return(Optional.Empty); }
public override void Process(StoryEventSend packet) { switch (packet.StoryEventType) { case StoryEventType.PDA: case StoryEventType.RADIO: case StoryEventType.ENCYCLOPEDIA: case StoryEventType.STORY: using (NitroxServiceLocator.LocateService <IPacketSender>().Suppress <StoryEventSend>()) { StoryGoal.Execute(packet.Key, (Story.GoalType)packet.StoryEventType); } break; case StoryEventType.EXTRA: ExecuteExtraEvent(packet.Key); break; } }