private void ServerRebuildReactorStats( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState, ObjectGeneratorPragmiumReactorPublicState reactorPublicState) { reactorPrivateState.Stats = this.SharedGetReactorStats(reactorPrivateState); reactorPrivateState.ServerItemsContainerLastStateHash = reactorPrivateState.ItemsContainer.StateHash; // verify that the reactor has at least a single fuel item, otherwise deactivate it var hasAnyFuel = false; foreach (var item in reactorPrivateState.ItemsContainer.Items) { if (item.ProtoItem is ItemReactorFuelRod) { hasAnyFuel = true; break; } } if (!hasAnyFuel && (reactorPrivateState.IsEnabled || reactorPrivateState.ActivationProgressPercents > 0)) { reactorPrivateState.IsEnabled = false; reactorPrivateState.ActivationProgressPercents = 0; reactorPublicState.ActivationProgressPercents = 0; //Logger.Info("Fuel depleted: " + reactorPrivateState.GameObject); } }
private void ServerApplyItemsDecay( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState, double deltaTime) { var activationProgress = reactorPrivateState.ActivationProgressPercents / 100.0; if (activationProgress <= 0) { reactorPrivateState.ServerAccumulatedDecayDuration = 0; return; } using var tempItemsList = Api.Shared.WrapInTempList(reactorPrivateState.ItemsContainer.Items); if (tempItemsList.Count == 0) { return; } reactorPrivateState.ServerAccumulatedDecayDuration += deltaTime; if (reactorPrivateState.ServerAccumulatedDecayDuration < ItemDecayIntervalDuration) { return; } // apply accumulated decay reactorPrivateState.ServerAccumulatedDecayDuration -= ItemDecayIntervalDuration; var decayMultiplier = activationProgress * ItemDecayIntervalDuration; var fuelDecayMultiplier = 100.0 / reactorPrivateState.Stats.FuelLifetimePercent; foreach (var item in tempItemsList.AsList()) { var protoGameObject = item.ProtoGameObject; switch (protoGameObject) { case ItemReactorFuelRod protoFuelRod: { var decayAmount = decayMultiplier * protoFuelRod.DurabilityMax / protoFuelRod.LifetimeDuration; decayAmount *= fuelDecayMultiplier; ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount); break; } case ProtoItemReactorModule protoItemModule: { var decayAmount = decayMultiplier * protoItemModule.DurabilityMax / protoItemModule.LifetimeDuration; ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount); break; } } } }
/// <summary> /// When the reactor completely shut downs, it will destroy all modules /// that have remaining durability below 1%. /// </summary> private static void ServerOnReactorShutdown(ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState) { foreach (var item in reactorPrivateState.ItemsContainer.Items.ToList()) { if (item.ProtoGameObject is ProtoItemReactorModule && ItemDurabilitySystem.SharedGetDurabilityPercent(item) < 1) { ItemDurabilitySystem.ServerBreakItem(item); } } }
private void ServerRemote_BuildReactor(IStaticWorldObject worldObjectGenerator, byte reactorIndex) { this.VerifyGameObject(worldObjectGenerator); var character = ServerRemoteContext.Character; if (!this.SharedCanInteract(character, worldObjectGenerator, writeToLog: true)) { return; } if (reactorIndex >= this.ReactorsCountMax) { throw new ArgumentOutOfRangeException(nameof(reactorIndex)); } var privateState = GetPrivateState(worldObjectGenerator); var publicState = GetPublicState(worldObjectGenerator); var reactorPrivateStates = privateState.ReactorStates; var reactorPrivateState = reactorPrivateStates[reactorIndex]; if (reactorPrivateState is not null) { throw new Exception($"The reactor is already built: #{reactorIndex} in {worldObjectGenerator}"); } if (!InputItemsHelper.SharedPlayerHasRequiredItems(character, this.BuildAdditionalReactorRequiredItems, noCheckInCreativeMode: true)) { throw new Exception($"Not enough items to build a reactor: #{reactorIndex} in {worldObjectGenerator}"); } if (!CreativeModeSystem.SharedIsInCreativeMode(character)) { InputItemsHelper.ServerDestroyItems(character, this.BuildAdditionalReactorRequiredItems); } reactorPrivateState = new ObjectGeneratorPragmiumReactorPrivateState(); reactorPrivateStates[reactorIndex] = reactorPrivateState; this.ServerSetupReactorPrivateState(worldObjectGenerator, reactorPrivateState); var reactorPublicStates = publicState.ReactorStates; reactorPublicStates[reactorIndex] = new ObjectGeneratorPragmiumReactorPublicState(); // force refresh over the network and properly binding the state owner object privateState.ReactorStates = reactorPrivateStates.ToArray(); publicState.ReactorStates = reactorPublicStates.ToArray(); }
private static bool SharedCanActivateReactor( IStaticWorldObject worldObjectGenerator, ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState, bool logErrors) { if (!reactorPrivateState.ItemsContainer.Items .Any(item => item.ProtoItem is ItemReactorFuelRod)) { if (logErrors) { Logger.Warning("Cannot activate reactor - no rods: " + worldObjectGenerator); if (IsClient) { NotificationSystem.ClientShowNotification( ErrorCannotStartReactor_Title, message: string.Format(ErrorCannotStartReactor_Description_Format, Api.GetProtoEntity <ItemReactorFuelRod>().Name), NotificationColor.Bad, GetProtoEntity <ItemReactorFuelRod>().Icon); } } return(false); } var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(worldObjectGenerator); if (areasGroup is null) { // no power grid exists if (logErrors) { Logger.Warning("Cannot activate reactor - no power grid exists: " + worldObjectGenerator); if (IsClient) { NotificationSystem.ClientShowNotification( ErrorCannotStartReactor_Title, message: PowerGridSystem.SetPowerModeResult.NoPowerGridExist.GetDescription(), NotificationColor.Bad, worldObjectGenerator.ProtoStaticWorldObject.Icon); } } return(false); } return(true); }
protected PragmiumReactorStatsData SharedGetReactorStats( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState) { double outputValue = 0, efficiencyPercents = 100, fuelLifetimePercent = 100, psiEmissionLevel = 0, startupShutdownTimePercent = 100; foreach (var item in reactorPrivateState.ItemsContainer.Items) { switch (item.ProtoGameObject) { case ItemReactorFuelRod protoRod: psiEmissionLevel += protoRod.PsiEmissionLevel; outputValue += protoRod.OutputElectricityPerSecond; break; case ProtoItemReactorModule protoModule: efficiencyPercents += protoModule.EfficiencyModifierPercents; fuelLifetimePercent += protoModule.FuelLifetimeModifierPercents; psiEmissionLevel += protoModule.PsiEmissionModifierValue; startupShutdownTimePercent += protoModule.StartupShutdownTimeModifierPercents; break; } } var generatorRate = RateTimeDependentGeneratorsRate.SharedValue; // do not apply it here as the player should not see the change here! //fuelLifetimePercent /= generatorRate; // apply generator rate (faster generation but faster fuel decay) fuelLifetimePercent = MathHelper.Clamp(fuelLifetimePercent, 1, ushort.MaxValue); efficiencyPercents = MathHelper.Clamp(efficiencyPercents, 0, ushort.MaxValue); // apply generator rate (faster generation and activation but faster fuel decay) startupShutdownTimePercent /= generatorRate; startupShutdownTimePercent = MathHelper.Clamp(startupShutdownTimePercent, 5, ushort.MaxValue); psiEmissionLevel = MathHelper.Clamp(psiEmissionLevel, 0, byte.MaxValue); outputValue *= efficiencyPercents / 100.0; outputValue *= generatorRate; // apply generator rate (faster generation but faster fuel decay) return(new PragmiumReactorStatsData((ushort)fuelLifetimePercent, (ushort)efficiencyPercents, psiEmissionLevel, outputValue, (ushort)startupShutdownTimePercent)); }
public virtual double SharedGetPsiEmissionLevelCurrent( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState) { if (reactorPrivateState is null) { return(0); } var emissionLevel = reactorPrivateState.Stats.PsiEmissionLevel; if (emissionLevel <= 0) { return(0); } return(emissionLevel * Math.Min(100, 2 * reactorPrivateState.ActivationProgressPercents) / 100.0); }
protected void ServerSetupReactorPrivateState( IStaticWorldObject worldObjectGenerator, ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState) { var itemsContainer = reactorPrivateState.ItemsContainer; var itemsSlotsCount = this.ItemSlotsCountPerReactor; if (itemsContainer is not null) { // container already created - update slots count Server.Items.SetSlotsCount(itemsContainer, slotsCount: itemsSlotsCount); return; } itemsContainer = Server.Items.CreateContainer <ItemsContainerGeneratorPragmium>( owner: worldObjectGenerator, slotsCount: itemsSlotsCount); reactorPrivateState.ItemsContainer = itemsContainer; }
protected PragmiumReactorStatsData SharedGetReactorStats( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState) { double outputValue = 0, efficiencyPercents = 100, fuelLifetimePercent = 100, psiEmissionLevel = 0, startupShutdownTimePercent = 100; foreach (var item in reactorPrivateState.ItemsContainer.Items) { switch (item.ProtoGameObject) { case ItemReactorFuelRod protoRod: psiEmissionLevel += protoRod.PsiEmissionLevel; outputValue += protoRod.OutputElectricityPerSecond; break; case ProtoItemReactorModule protoModule: efficiencyPercents += protoModule.EfficiencyModifierPercents; fuelLifetimePercent += protoModule.FuelLifetimeModifierPercents; psiEmissionLevel += protoModule.PsiEmissionModifierValue; startupShutdownTimePercent += protoModule.StartupShutdownTimeModifierPercents; break; } } fuelLifetimePercent = MathHelper.Clamp(fuelLifetimePercent, 1, ushort.MaxValue); efficiencyPercents = MathHelper.Clamp(efficiencyPercents, 0, ushort.MaxValue); startupShutdownTimePercent = MathHelper.Clamp(startupShutdownTimePercent, 5, ushort.MaxValue); psiEmissionLevel = MathHelper.Clamp(psiEmissionLevel, 0, byte.MaxValue); outputValue *= efficiencyPercents / 100.0; return(new PragmiumReactorStatsData((ushort)fuelLifetimePercent, (ushort)efficiencyPercents, psiEmissionLevel, outputValue, (ushort)startupShutdownTimePercent)); }
protected override void ServerInitialize(ServerInitializeData data) { base.ServerInitialize(data); var worldObjectGenerator = data.GameObject; var publicState = data.PublicState; var privateState = data.PrivateState; var reactorPrivateStates = privateState.ReactorStates; if (reactorPrivateStates?.Length != this.ReactorsCountMax) { privateState.ReactorStates = null; publicState.ReactorStates = null; reactorPrivateStates = new ObjectGeneratorPragmiumReactorPrivateState[this.ReactorsCountMax]; } var reactorPublicStates = publicState.ReactorStates ?? new ObjectGeneratorPragmiumReactorPublicState[this.ReactorsCountMax]; for (var index = 0; index < reactorPrivateStates.Length; index++) { var reactorPrivateState = reactorPrivateStates[index]; if (reactorPrivateState is null && index < this.ReactorsCountInitial) { reactorPrivateState = new ObjectGeneratorPragmiumReactorPrivateState(); reactorPrivateStates[index] = reactorPrivateState; } if (reactorPrivateState is not null) { this.ServerSetupReactorPrivateState(worldObjectGenerator, reactorPrivateState); reactorPublicStates[index] = new ObjectGeneratorPragmiumReactorPublicState(); } } // force refresh over the network and properly binding the state owner object privateState.ReactorStates = reactorPrivateStates.ToArray(); publicState.ReactorStates = reactorPublicStates.ToArray(); }
private static void ServerApplyItemsDecay( ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState, double deltaTime) { var activationProgress = reactorPrivateState.ActivationProgressPercents / 100.0; if (activationProgress <= 0) { reactorPrivateState.ServerAccumulatedDecayDuration = 0; return; } using var tempItemsList = Api.Shared.WrapInTempList(reactorPrivateState.ItemsContainer.Items); if (tempItemsList.Count == 0) { return; } reactorPrivateState.ServerAccumulatedDecayDuration += deltaTime; if (reactorPrivateState.ServerAccumulatedDecayDuration < ItemDecayIntervalDuration) { return; } // let's apply accumulated decay reactorPrivateState.ServerAccumulatedDecayDuration -= ItemDecayIntervalDuration; var decayMultiplier = activationProgress * ItemDecayIntervalDuration; // apply generator rate (faster generation but faster fuel decay) decayMultiplier *= RateTimeDependentGeneratorsRate.SharedValue; var fuelDecayMultiplier = 100.0 / reactorPrivateState.Stats.FuelLifetimePercent; foreach (var item in tempItemsList.AsList()) { var protoGameObject = item.ProtoGameObject; switch (protoGameObject) { case ItemReactorFuelRod protoFuelRod: { var decayAmount = decayMultiplier * protoFuelRod.DurabilityMax / protoFuelRod.LifetimeDuration; decayAmount *= fuelDecayMultiplier; ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount); break; } case ProtoItemReactorModule protoItemModule: { var decayAmount = decayMultiplier * protoItemModule.DurabilityMax / protoItemModule.LifetimeDuration; // Don't allow for modules to decay completely. // When the reactor completely shut downs, it will destroy all modules // that have remaining durability below 1% (see ServerOnReactorShutdown). var privateState = item.GetPrivateState <IItemWithDurabilityPrivateState>(); decayAmount = Math.Min(decayAmount, privateState.DurabilityCurrent - 1); if (decayAmount > 0) { ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount); } break; } } } }