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); } }
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); }
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); }
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; } }); } }
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); }
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(); }
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); }
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); }
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}"); } }
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); }
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); } }
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}"); }
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); }
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); }
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); }
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)); }
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); }
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); }
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); }
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; }
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); }
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); }