public static bool SharedCanInteract(
            ICharacter character,
            IStaticWorldObject worldObject,
            bool writeToLog)
        {
            if (IsClient)
            {
                // cannot perform this check on the client side
                return(true);
            }

            if (SharedIsOwner(character, worldObject) ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            // not the door owner
            if (writeToLog)
            {
                ServerNotifyNotOwner(character, worldObject);
            }

            return(false);
        }
 void IInteractableProtoWorldObject.ServerOnClientInteract(ICharacter who, IWorldObject worldObject)
 {
     if (WorldObjectOwnersSystem.SharedIsOwner(who, (IStaticWorldObject)worldObject) ||
         CreativeModeSystem.SharedIsInCreativeMode(who))
     {
         Server.World.EnterPrivateScope(who, worldObject);
     }
 }
示例#3
0
        public static bool SharedCheckCanDeconstruct(IStaticWorldObject worldObject, ICharacter character)
        {
            // Please note: the game already have validated that the target object is a structure
            if (worldObject.ProtoGameObject is ObjectWallDestroyed)
            {
                // always allow deconstruct a destroyed wall object even if it's in another player's land claim
                return(true);
            }

            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                // operator can deconstruct any structure
                return(true);
            }

            RectangleInt worldObjectBounds;
            {
                var temp         = worldObject.ProtoStaticWorldObject.Layout.Bounds;
                var tilePosition = worldObject.TilePosition;
                worldObjectBounds = new RectangleInt(
                    temp.MinX + tilePosition.X,
                    temp.MinY + tilePosition.Y,
                    temp.Size.X,
                    temp.Size.Y);
            }

            var isThereAnyArea = false;

            foreach (var area in sharedLandClaimAreas)
            {
                var areaBounds = SharedGetLandClaimAreaBounds(area);
                if (!areaBounds.IntersectsLoose(worldObjectBounds))
                {
                    continue;
                }

                isThereAnyArea = true;
                // intersection with area found - check if player owns the area
                if (SharedIsOwnedArea(area, character))
                {
                    // player own the area
                    return(true);
                }
            }

            // no area or not owned area
            if (!isThereAnyArea)
            {
                // no area
                if (worldObject.ProtoGameObject is ProtoObjectConstructionSite)
                {
                    // can deconstruct blueprints if there is no land claim area
                    return(true);
                }
            }

            return(false);
        }
示例#4
0
        private void ServerRemote_RelocateStructure(IStaticWorldObject objectStructure, Vector2Ushort toPosition)
        {
            if (objectStructure.TilePosition == toPosition)
            {
                // relocation not required
                return;
            }

            var character = ServerRemoteContext.Character;

            if (!SharedValidateCanCharacterRelocateStructure(character,
                                                             objectStructure,
                                                             toPosition,
                                                             errorMessage: out _,
                                                             logErrors: true))
            {
                return;
            }

            var fromPosition = objectStructure.TilePosition;

            Api.SafeInvoke(
                () => ServerStructureBeforeRelocating?.Invoke(character, fromPosition, objectStructure));

            Server.World.SetPosition(objectStructure, toPosition);

            try
            {
                // ensure the structure is reinitialized (has its physics rebuilt, etc)
                objectStructure.ServerInitialize();
            }
            catch (Exception ex)
            {
                Logger.Exception(ex);
            }

            ConstructionPlacementSystem.Instance.ServerNotifyOnStructurePlacedOrRelocated(objectStructure, character);

            Api.SafeInvoke(
                () => ServerStructureRelocated?.Invoke(character, fromPosition, objectStructure));

            // let's deduct the tool durability
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return;
            }

            // the item in hotbar is definitely a construction tool as it was validated above
            var itemConstructionTool = character.SharedGetPlayerSelectedHotbarItem();

            ItemDurabilitySystem.ServerModifyDurability(
                itemConstructionTool,
                delta: -((IProtoObjectStructure)objectStructure.ProtoGameObject).RelocationToolDurabilityCost);
        }
示例#5
0
        private void ControlWorldMapMouseRightButtonUpHandler(object sender, MouseButtonEventArgs e)
        {
            var mapPositionWithOffset = this.controlWorldMap.WorldMapController.PointedMapPositionWithOffset;

            this.CloseContextMenu();

            var contextMenu = new ContextMenu();

            contextMenu.Items.Add(new MenuItem()
            {
                Header  = ContextMenuCopyCoordinates,
                Command = new ActionCommand(
                    () => Api.Client.Core.CopyToClipboard(mapPositionWithOffset.ToString()))
            });

            var character = Api.Client.Characters.CurrentPlayerCharacter;

            if (character.ProtoCharacter is PlayerCharacterSpectator ||
                ServerOperatorSystem.SharedIsOperator(character) ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                var mapPositionWithoutOffset = this.controlWorldMap.WorldMapController.PointedMapPositionWithoutOffset;
                contextMenu.Items.Add(new MenuItem()
                {
                    Header  = ContextMenuTeleport,
                    Command = new ActionCommand(
                        () => this.CallTeleport(mapPositionWithoutOffset.ToVector2D()))
                });
            }

            var position = Mouse.GetPosition(this);

            contextMenu.PlacementRectangle = new Rect(position.X, position.Y, 0, 0);

            this.ContextMenu    = contextMenu;
            contextMenu.Closed += ContextMenuOnClosed;
            contextMenu.IsOpen  = true;

            void ContextMenuOnClosed(object s, RoutedEventArgs _)
            {
                contextMenu.Closed -= ContextMenuOnClosed;
                // remove context menu with the delay (to avoid teleport-on-click when context menu is closed)
                ClientTimersSystem.AddAction(
                    delaySeconds: 0.1,
                    () =>
                {
                    if (this.ContextMenu == contextMenu)
                    {
                        this.ContextMenu = null;
                    }
                });
            }
        }
示例#6
0
        private void ServerRemote_SetDirectAccessMode(IStaticWorldObject worldObject, WorldObjectDirectAccessMode mode)
        {
            var character = ServerRemoteContext.Character;

            if (!(worldObject.ProtoGameObject is IProtoObjectWithAccessMode protoObjectWithAccessMode))
            {
                throw new Exception("This world object doesn't have an access mode");
            }

            if (!protoObjectWithAccessMode.SharedCanInteract(character, worldObject, writeToLog: true))
            {
                return;
            }

            var areasGroup = LandClaimSystem.SharedGetLandClaimAreasGroup(worldObject);

            if (areasGroup is not null &&
                LandClaimAreasGroup.GetPublicState(areasGroup).ServerFaction is not null)
            {
                throw new Exception(
                          "Cannot modify direct access mode for an object within a faction land claim area");
            }

            if (!WorldObjectOwnersSystem.SharedIsOwner(character, worldObject) &&
                !CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                throw new Exception("The player character is not an owner of " + worldObject);
            }

            if (mode == WorldObjectDirectAccessMode.Closed &&
                !protoObjectWithAccessMode.IsClosedAccessModeAvailable)
            {
                throw new Exception("Closed access mode is not supported for " + protoObjectWithAccessMode);
            }

            if (mode == WorldObjectDirectAccessMode.OpensToEveryone &&
                !protoObjectWithAccessMode.IsEveryoneAccessModeAvailable)
            {
                throw new Exception("Everyone access mode is not supported for " + protoObjectWithAccessMode);
            }

            var privateState = worldObject.GetPrivateState <IObjectWithAccessModePrivateState>();

            if (privateState.DirectAccessMode == mode)
            {
                return;
            }

            privateState.DirectAccessMode = mode;
            Logger.Info($"Direct access mode changed: {mode}; {worldObject}", character);
        }
示例#7
0
        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();
        }
示例#8
0
        public bool SharedCanEditOwners(IStaticWorldObject worldObject, ICharacter byOwner)
        {
            var area         = GetPublicState(worldObject).LandClaimAreaObject;
            var privateState = LandClaimArea.GetPrivateState(area);

            if (privateState.LandClaimFounder == byOwner.Name ||
                CreativeModeSystem.SharedIsInCreativeMode(byOwner))
            {
                // only founder or character in creative mode can edit the owners list
                return(true);
            }

            return(false);
        }
示例#9
0
        protected override void ServerOnStaticObjectZeroStructurePoints(
            WeaponFinalCache weaponCache,
            ICharacter byCharacter,
            IWorldObject targetObject)
        {
            // do not use default implementation because it will destroy the object automatically
            //base.ServerOnStaticObjectZeroStructurePoints(weaponCache, targetObject);

            var worldObject = (IStaticWorldObject)targetObject;
            var publicState = GetPublicState(worldObject);

            if (byCharacter != null &&
                (LandClaimSystem.ServerIsOwnedArea(publicState.LandClaimAreaObject, byCharacter) ||
                 CreativeModeSystem.SharedIsInCreativeMode(byCharacter)))
            {
                // this is the owner of the area or the player is in a creative mode
                if (byCharacter.SharedGetPlayerSelectedHotbarItemProto() is ProtoItemToolCrowbar)
                {
                    publicState.ServerTimeForDestruction = 0;
                    Logger.Important(
                        $"Land claim object {targetObject} destroyed by the owner with a crowbar - no destruction timer",
                        byCharacter);

                    this.ServerForceUpdate(worldObject, publicState);
                    return;
                }
            }

            if (byCharacter != null)
            {
                var areaPrivateState = LandClaimArea.GetPrivateState(publicState.LandClaimAreaObject);
                areaPrivateState.IsDestroyedByPlayers = true;
            }

            if (publicState.ServerTimeForDestruction.HasValue)
            {
                // destruction timer is already set
                return;
            }

            // the land claim structure points is zero - it's broken now - set timer for destruction
            var timeout = PveSystem.ServerIsPvE
                              ? 0
                              : this.DestructionTimeout.TotalSeconds;

            publicState.ServerTimeForDestruction = Server.Game.FrameTime + timeout;

            Logger.Important($"Timer for destruction set: {targetObject}. Timeout: {timeout}");
            this.ServerForceUpdate(worldObject, publicState);
        }
示例#10
0
        private static void ValidateCanAdminAndInteract(ICharacter character, IStaticWorldObject tradingStation)
        {
            if (!tradingStation.ProtoStaticWorldObject
                .SharedCanInteract(character, tradingStation, writeToLog: true))
            {
                throw new Exception($"{character} cannot interact with {tradingStation}");
            }

            if (!WorldObjectOwnersSystem.SharedIsOwner(character, tradingStation) &&
                !CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                throw new Exception($"{character} is not owner of {tradingStation}");
            }
        }
示例#11
0
        public override bool CanRemoveItem(CanRemoveItemContext context)
        {
            if (!(context.Item.ProtoItem is IProtoItemEquipment protoItem))
            {
                return(true);
            }

            var itemEquipmentType = protoItem.EquipmentType;

            //MOD
            if (itemEquipmentType == EquipmentType.Device &&
                context.Item.ProtoGameObject is ProtoItemBackpack backpack)
            {
                return(backpack.SharedCanRemoveItem(context.Item, context.ByCharacter, false));
            }

            if (!(context.Item.ProtoItem is IProtoItemEquipmentImplant protoItemEquipment))
            {
                // impossible - how did it end up here?
                return(true);
            }

            if (itemEquipmentType == EquipmentType.Implant)
            {
                // implant item
                if (context.ByCharacter is null ||
                    CreativeModeSystem.SharedIsInCreativeMode(context.ByCharacter))
                {
                    // Allowed to add/remove implant item by the game only (via medical station).
                    // But allow to characters in the creative mode to do this directly.
                    return(true);
                }

                if (IsClient)
                {
                    ClientShowNotificationCannotRemoveImplant(protoItemEquipment);
                }
                else
                {
                    this.CallClient(context.ByCharacter,
                                    _ => _.ClientRemote_ClientShowNotificationCannotRemoveImplant(protoItemEquipment));
                }

                return(false);
            }

            // can remove anything
            return(true);
        }
示例#12
0
        private void MapClickHandler(Vector2D worldPosition)
        {
            if (this.ContextMenu != null)
            {
                // context menu is still exist, don't process this click
                return;
            }

            var character = ClientCurrentCharacterHelper.Character;

            if (character.ProtoCharacter is PlayerCharacterSpectator ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                this.CallTeleport(worldPosition);
            }
        }
示例#13
0
        private void ServerRemote_Repair()
        {
            var character         = ServerRemoteContext.Character;
            var tinkerTableObject =
                InteractionCheckerSystem.SharedGetCurrentInteraction(character) as IStaticWorldObject;

            this.VerifyGameObject(tinkerTableObject);

            var worldObjectPrivateState = GetPrivateState(tinkerTableObject);
            var containerInput          = worldObjectPrivateState.ContainerInput;
            var containerOutput         = worldObjectPrivateState.ContainerOutput;
            var inputItem1 = containerInput.GetItemAtSlot(0);
            var inputItem2 = containerInput.GetItemAtSlot(1);

            if (!ValidateCanRepair(character, tinkerTableObject, out var error))
            {
                Logger.Warning(tinkerTableObject + " cannot repair: " + error, character);
                return;
            }

            if (!CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                InputItemsHelper.ServerDestroyItems(character, RequiredRepairComponentItems);
            }

            var resultDurabilityFraction = SharedCalculateResultDurabilityFraction(inputItem1, inputItem2, character);

            Server.Items.DestroyItem(inputItem2);
            Server.Items.MoveOrSwapItem(inputItem1,
                                        containerOutput,
                                        out _);

            var resultItemProto        = (IProtoItemWithDurablity)inputItem1.ProtoGameObject;
            var resultItemPrivateState = inputItem1.GetPrivateState <IItemWithDurabilityPrivateState>();

            resultItemPrivateState.DurabilityCurrent = (uint)Math.Round(
                resultDurabilityFraction * resultItemProto.DurabilityMax,
                MidpointRounding.AwayFromZero);

            character.ServerAddSkillExperience <SkillMaintenance>(
                SkillMaintenance.ExperiencePerItemRepaired);

            Logger.Info(
                $"Item repaired: {inputItem1}. Second item was destroyed to use for repair components: {inputItem2}");
        }
示例#14
0
        private static bool SharedValidateHasRequiredComponentItems(ICharacter character)
        {
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            foreach (var requiredItem in RequiredRepairComponentItems)
            {
                if (!character.ContainsItemsOfType(requiredItem.ProtoItem, requiredItem.Count))
                {
                    // some item is not available
                    return(false);
                }
            }

            return(true);
        }
示例#15
0
        public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
        {
            if (!base.SharedCanInteract(character, worldObject, writeToLog))
            {
                return(false);
            }

            if (IsClient)
            {
                // cannot perform further checks on client side
                return(true);
            }

            var publicState = GetPublicState(worldObject);

            if (LandClaimSystem.ServerIsOwnedArea(publicState.LandClaimAreaObject, character))
            {
                return(true);
            }

            if (PlayerCharacterSpectator.SharedIsSpectator(character) ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            // not the land owner
            if (writeToLog)
            {
                Logger.Warning(
                    $"Character cannot interact with {worldObject} - not the land owner.",
                    character);

                this.CallClient(
                    character,
                    _ => _.ClientRemote_OnCannotInteract(
                        worldObject,
                        LandClaimMenuOpenResult.FailPlayerIsNotOwner));
            }

            return(false);
        }
示例#16
0
        void IInteractableProtoStaticWorldObject.ServerOnMenuClosed(ICharacter who, IStaticWorldObject worldObject)
        {
            var area = LandClaimSystem.ServerGetLandClaimArea(worldObject);

            if (area == null)
            {
                // area could be null in the Editor for the land claim without owners
                return;
            }

            var areasGroup = LandClaimArea.GetPublicState(area).LandClaimAreasGroup;

            if (CreativeModeSystem.SharedIsInCreativeMode(who) &&
                !LandClaimSystem.ServerIsOwnedArea(area, who))
            {
                Server.World.ExitPrivateScope(who, area);
            }

            Server.World.ExitPrivateScope(who, areasGroup);
        }
示例#17
0
        protected override GatheringActionState SharedTryCreateState(WorldActionRequest request)
        {
            var worldObject = request.WorldObject;
            var character   = request.Character;

            var staticWorldObject = (IStaticWorldObject)worldObject;

            if (!(worldObject.ProtoGameObject is IProtoObjectGatherable protoGatherable))
            {
                throw new Exception("Not a gatherable resource: " + worldObject);
            }

            if (!protoGatherable.SharedIsCanGather(staticWorldObject))
            {
                Logger.Warning("Cannot gather now: " + worldObject, character);
                if (Api.IsClient)
                {
                    CannotInteractMessageDisplay.ShowOn(worldObject, NotificationNothingToHarvestYet);
                    worldObject.ProtoWorldObject.SharedGetObjectSoundPreset()
                    .PlaySound(ObjectSound.InteractFail);
                }

                return(null);
            }

            var durationSeconds = protoGatherable.DurationGatheringSeconds;

            var multiplier = protoGatherable.GetGatheringSpeedMultiplier(staticWorldObject, character);

            durationSeconds /= multiplier;

            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                durationSeconds = 0.1;
            }

            return(new GatheringActionState(
                       character,
                       staticWorldObject,
                       durationSeconds));
        }
示例#18
0
        void IInteractableProtoWorldObject.ServerOnClientInteract(ICharacter who, IWorldObject worldObject)
        {
            var area = LandClaimSystem.ServerGetLandClaimArea((IStaticWorldObject)worldObject);

            if (area == null)
            {
                // area could be null in the Editor for the land claim without owners
                return;
            }

            var areasGroup = LandClaimArea.GetPublicState(area).LandClaimAreasGroup;

            if (!LandClaimSystem.ServerIsOwnedArea(area, who) &&
                (PlayerCharacterSpectator.SharedIsSpectator(who) ||
                 CreativeModeSystem.SharedIsInCreativeMode(who)))
            {
                Server.World.EnterPrivateScope(who, area);
            }

            Server.World.EnterPrivateScope(who, areasGroup);
        }
        public DeconstructionActionState(
            ICharacter character,
            IStaticWorldObject worldObject,
            IItem itemCrowbarTool)
            : base(character)
        {
            this.WorldObject          = worldObject;
            this.ItemCrowbarTool      = itemCrowbarTool;
            this.ProtoItemCrowbarTool = (IProtoItemToolCrowbar)itemCrowbarTool?.ProtoGameObject;
            this.protoStructure       = (IProtoObjectStructure)worldObject.ProtoWorldObject;

            this.currentStageDurationSeconds = this.CalculateStageDurationSeconds(character, isFirstStage: true);

            this.currentStageTimeRemainsSeconds = this.currentStageDurationSeconds;
            this.ObjectPublicState = worldObject.GetPublicState <StaticObjectPublicState>();

            this.structurePointsMax = this.protoStructure.SharedGetStructurePointsMax(worldObject);

            // use build config to determine how many deconstruction steps required
            var stagesCount = this.protoStructure.GetStructureActiveConfig(worldObject)
                              .StagesCount;

            if (stagesCount <= 0)
            {
                // force at least 1 deconstruction stage
                stagesCount = 1;
            }

            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                // force single stage
                stagesCount = 1;
            }

            this.stageStructureRemoveValue = this.structurePointsMax / stagesCount;
            if (this.stageStructureRemoveValue < 1)
            {
                this.stageStructureRemoveValue = 1;
            }
        }
        private void ServerRemote_RelocateStructure(IStaticWorldObject objectStructure, Vector2Ushort toPosition)
        {
            if (objectStructure.TilePosition == toPosition)
            {
                // relocation not required
                return;
            }

            var character = ServerRemoteContext.Character;

            if (!SharedValidateCanCharacterRelocateStructure(character,
                                                             objectStructure,
                                                             toPosition,
                                                             logErrors: true))
            {
                return;
            }

            Api.SafeInvoke(
                () => ServerStructureBeforeRelocating?.Invoke(character, objectStructure));

            Server.World.SetPosition(objectStructure, toPosition);
            ConstructionPlacementSystem.Instance.ServerNotifyOnStructurePlacedOrRelocated(objectStructure, character);

            Api.SafeInvoke(
                () => ServerStructureRelocated?.Invoke(character, objectStructure));

            // let's deduct the tool durability
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return;
            }

            // the item in hotbar is definitely a construction tool as it was validated above
            var itemConstructionTool = character.SharedGetPlayerSelectedHotbarItem();

            ItemDurabilitySystem.ServerModifyDurability(itemConstructionTool,
                                                        delta: -ToolDurabilityCostForStructureRelocation);
        }
示例#21
0
        private bool SharedValidateCanUpgradeToNextStage(
            IStaticWorldObject objectLaunchpad,
            ICharacter character,
            out IProtoObjectStructure upgradeStructure)
        {
            if (!this.SharedCanInteract(character, objectLaunchpad, writeToLog: true))
            {
                // cannot interact
                upgradeStructure = null;
                return(false);
            }

            upgradeStructure = this.ConfigUpgrade.Entries[0].ProtoStructure;
            if (upgradeStructure is null)
            {
                // no upgrade exists
                return(false);
            }

            if (!upgradeStructure.ListedInTechNodes.Any(
                    techNode => character.SharedGetTechnologies().SharedIsNodeUnlocked(techNode)) &&
                !CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                // has not yet researched the relevant technology
                return(false);
            }

            var privateState        = GetPrivateState(objectLaunchpad);
            var taskCompletionState = privateState.TaskCompletionState;

            if (!taskCompletionState.All(flag => flag))
            {
                Logger.Warning(character + " has not completed all the tasks yet - cannot upgrade: " + objectLaunchpad);
                return(false);
            }

            // all tasks completed
            return(true);
        }
示例#22
0
        private double CalculateStageDurationSeconds(ICharacter character, bool isFirstStage)
        {
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                // force instant deconstruct
                return(0);
            }

            var durationSeconds = DefaultDeconstructionStepDurationSeconds;

            durationSeconds /= (this.ProtoItemCrowbarTool?.DeconstructionSpeedMultiplier ?? 1);
            durationSeconds /= character.SharedGetFinalStatMultiplier(StatName.BuildingSpeed);
            if (isFirstStage && Api.IsClient)
            {
                // Add ping to all client action durations.
                // Otherwise the client will not see immediately the result of the action
                // - the client will receive it only after RTT (ping) time.
                // TODO: currently it's possible to cancel action earlier and start a new one, but completed action result will come from server - which looks like a bug to player
                durationSeconds += Api.Client.CurrentGame.PingGameSeconds;
            }

            return(durationSeconds);
        }
示例#23
0
        public static bool SharedPlayerHasRequiredItems(
            ICharacter character,
            IReadOnlyList<ProtoItemWithCount> requiredItems,
            bool noCheckInCreativeMode)
        {
            if (noCheckInCreativeMode
                && CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return true;
            }

            foreach (var requiredItem in requiredItems)
            {
                if (!character.ContainsItemsOfType(requiredItem.ProtoItem, requiredItem.Count))
                {
                    // some item is not available
                    return false;
                }
            }

            // all required items are available
            return true;
        }
示例#24
0
        private double CalculateStageDurationSeconds(ICharacter character, bool isFirstStage)
        {
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                // force instant hacking
                return(0);
            }

            var durationSeconds = this.protoHackableContainer.HackingStageDuration;

            durationSeconds = Api.Shared.RoundDurationByServerFrameDuration(durationSeconds);

            if (isFirstStage && Api.IsClient)
            {
                // Add ping to all client action durations.
                // Otherwise the client will not see immediately the result of the action
                // - the client will receive it only after RTT (ping) time.
                // TODO: currently it's possible to cancel action earlier and start a new one, but completed action result will come from server - which looks like a bug to player
                durationSeconds += Api.Client.CurrentGame.PingGameSeconds;
            }

            return(durationSeconds);
        }
        public void ServerDestroyRequiredItems(ICharacter character)
        {
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                Api.Logger.Important(character + " is in the admin mode - free construction is allowed.");
                return;
            }

            // assume all the validation has been done before this action
            var serverItemsService = Api.Server.Items;
            var itemsChangedCount  = new Dictionary <IProtoItem, int>();

            foreach (var requiredItem in this.RequiredItems)
            {
                serverItemsService.DestroyItemsOfType(
                    character,
                    requiredItem.ProtoItem,
                    requiredItem.Count,
                    out _);
                itemsChangedCount[requiredItem.ProtoItem] = -requiredItem.Count;
            }

            NotificationSystem.ServerSendItemsNotification(character, itemsChangedCount);
        }
        public bool CheckRequirementsSatisfied(ICharacter character)
        {
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            if (!this.ProtoStructure.SharedIsTechUnlocked(character))
            {
                // the tech is locked
                return(false);
            }

            foreach (var requiredItem in this.RequiredItems)
            {
                if (!character.ContainsItemsOfType(requiredItem.ProtoItem, requiredItem.Count))
                {
                    // some item is not available
                    return(false);
                }
            }

            return(true);
        }
示例#27
0
        public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
        {
            if (!base.SharedCanInteract(character, worldObject, writeToLog))
            {
                return(false);
            }

            if (LandClaimSystem.SharedIsObjectInsideOwnedOrFreeArea(worldObject,
                                                                    character,
                                                                    requireFactionPermission: false) ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return(true);
            }

            // not the land owner and not in creative mode
            if (writeToLog)
            {
                Logger.Warning(
                    $"Character cannot interact with {worldObject} - not the land owner.",
                    character);

                if (IsClient)
                {
                    this.ClientRemote_OnCannotInteract(worldObject);
                }
                else
                {
                    this.CallClient(
                        character,
                        _ => _.ClientRemote_OnCannotInteract(worldObject));
                }
            }

            return(false);
        }
        public override bool CanRemoveItem(CanRemoveItemContext context)
        {
            if (!(context.Item.ProtoItem is IProtoItemEquipmentImplant protoItemEquipment))
            {
                // impossible - how did it end up here?
                return(true);
            }

            var itemEquipmentType = protoItemEquipment.EquipmentType;

            if (itemEquipmentType == EquipmentType.Implant)
            {
                // implant item
                if (context.ByCharacter == null ||
                    CreativeModeSystem.SharedIsInCreativeMode(context.ByCharacter))
                {
                    // Allowed to add/remove implant item by the game only (via medical station).
                    // But allow to characters in the creative mode to do this directly.
                    return(true);
                }

                if (IsClient)
                {
                    NotificationSystem.ClientShowNotification(
                        NotificationUseStationToRemoveImplant_Title,
                        NotificationUseStationToRemoveImplant_Message,
                        NotificationColor.Bad,
                        protoItemEquipment.Icon);
                }

                return(false);
            }

            // can remove anything
            return(true);
        }
            public string ServerRemote_Teleport(Vector2D worldPosition)
            {
                try
                {
                    var character = ServerRemoteContext.Character;
                    if (character.ProtoCharacter is PlayerCharacterSpectator ||
                        ServerOperatorSystem.SharedIsOperator(character) ||
                        CreativeModeSystem.SharedIsInCreativeMode(character))
                    {
                        ServerTeleport(character, worldPosition);
                        var message = CreateResultMessage(character);
                        Logger.Important(message);
                        return(message);
                    }

                    return("Error: you're not in creative mode and not a spectator. You cannot use the teleport system.");
                }
                catch (Exception ex)
                {
                    var message = ex.Message;
                    Logger.Important(message);
                    return("Error: " + message);
                }
            }
        public static string ServerSetOwners(
            IWorldObject worldObject,
            List <string> newOwners,
            ICharacter byOwner)
        {
            var protoObject = (IProtoObjectWithOwnersList)worldObject.ProtoGameObject;

            if (!protoObject.HasOwnersList)
            {
                throw new Exception("This object doesn't support owners list: " + worldObject);
            }

            var currentOwners = GetPrivateState(worldObject).Owners;

            if (!currentOwners.Contains(byOwner.Name) &&
                !CreativeModeSystem.SharedIsInCreativeMode(byOwner))
            {
                return(DialogCannotSetOwners_MessageNotOwner);
            }

            if (!((IProtoObjectWithOwnersList)worldObject.ProtoGameObject)
                .SharedCanEditOwners(worldObject, byOwner))
            {
                return(DialogCannotSetOwners_MessageCannotEdit);
            }

            currentOwners.GetDiff(newOwners, out var ownersToAdd, out var ownersToRemove);
            if (ownersToRemove.Count > 0 &&
                currentOwners.Count == ownersToRemove.Count)
            {
                return(DialogCannotSetOwners_MessageCannotRemoveLastOwner);
            }

            if (ownersToRemove.Contains(byOwner.Name))
            {
                return(DialogCannotSetOwners_MessageCannotRemoveSelf);
            }

            if (ownersToAdd.Count == 0 &&
                ownersToRemove.Count == 0)
            {
                Logger.Warning(
                    "No need to change the owners - the new owners list is the same as the current owners list: "
                    + worldObject,
                    characterRelated: byOwner);
                return(null);
            }

            foreach (var n in ownersToAdd)
            {
                var name        = n;
                var playerToAdd = Api.Server.Characters.GetPlayerCharacter(name);
                if (playerToAdd is null)
                {
                    return(string.Format(DialogCannotSetOwners_MessageFormatPlayerNotFound, name));
                }

                // get proper player name
                name = playerToAdd.Name;
                if (currentOwners.AddIfNotContains(name))
                {
                    Api.Logger.Important($"Added owner: {name}; {worldObject}", characterRelated: byOwner);
                }
            }

            foreach (var name in ownersToRemove)
            {
                if (!currentOwners.Remove(name))
                {
                    continue;
                }

                Api.Logger.Important($"Removed owner: {name}; {worldObject}", characterRelated: byOwner);

                var removedPlayer = Api.Server.Characters.GetPlayerCharacter(name);
                if (removedPlayer is null)
                {
                    continue;
                }

                InteractableWorldObjectHelper.ServerTryAbortInteraction(removedPlayer, worldObject);
            }

            ServerInvokeOwnersChangedEvent(worldObject);
            return(null);
        }