/// <summary> /// Handles an event from a container content updated. /// </summary> /// <param name="container">The container.</param> /// <param name="indexOfUpdated">The index that was updated.</param> /// <param name="updatedItem">The updated item.</param> private void OnContainerContentUpdated(IItemsContainer container, byte indexOfUpdated, IItem updatedItem) { if (!(container is IContainerItem containerItem)) { return; } if (updatedItem == null) { return; } lock (this.internalDictionariesLock) { if (!this.containersToCreatureIds.ContainsKey(containerItem.UniqueId)) { return; } // The request has to be sent this way since the container id may be different for each player. foreach (var(containerId, creatureId) in this.containersToCreatureIds[containerItem.UniqueId].ToList()) { if (!(this.creatureFinder.FindPlayerById(creatureId) is IPlayer player)) { continue; } // var notification = new GenericNotification(() => player.YieldSingleItem(), new ContainerUpdateItemPacket(indexOfUpdated, containerId, updatedItem)); this.ItemUpdated?.Invoke(player, containerId, updatedItem); } } }
private void CreateInnerPipe() { _queue = new Queue <string>(); _itemsContainer = Mock.Create <IItemsContainer <string> >(); Mock.Arrange(() => _itemsContainer.TryAdd(null)).IgnoreArguments().Returns <string>(o => { _queue.Enqueue(o); return(true); }); string item; Mock.Arrange(() => _itemsContainer.TryGet(out item)).DoInstead <OutAction <string> >((out string item2) => { if (_queue.Count == 0) { item2 = null; return(false); } item2 = _queue.Dequeue(); return(true); }).Returns <string>(o => o != null); }
/// <summary> /// Handles an event from a container content removed. /// </summary> /// <param name="container">The container.</param> /// <param name="indexRemoved">The index that was removed.</param> private void OnContainerContentRemoved(IItemsContainer container, byte indexRemoved) { if (!(container is IContainerItem containerItem)) { return; } lock (this.internalDictionariesLock) { if (!this.containersToCreatureIds.ContainsKey(containerItem.UniqueId)) { return; } // The request has to be sent this way since the container id may be different for each player. foreach (var(containerId, creatureId) in this.containersToCreatureIds[containerItem.UniqueId].ToList()) { if (!(this.creatureFinder.FindPlayerById(creatureId) is IPlayer player)) { continue; } this.ItemRemoved?.Invoke(player, containerId, indexRemoved); } } }
private static void ServerCancelCraftingQueueItem( ICharacter character, CraftingQueueItem item, CraftingQueue craftingQueue, ref IItemsContainer groundContainer) { if (!item.Recipe.IsCancellable) { Logger.Info("Crafting queue item is not cancellable: " + item, character); return; } var index = craftingQueue.QueueItems.IndexOf(item); if (index < 0) { throw new Exception("Doesn't have the crafting queue item: " + item); } ServerReturnCharacterCraftingQueueItemInputItems(character, item, ref groundContainer); craftingQueue.QueueItems.RemoveAt(index); if (index == 0) { // first queue item was removed - reset crafting duration craftingQueue.SetDurationFromCurrentRecipe(); } Logger.Info("Crafting queue item successfully cancelled: " + item, character); }
protected override void ServerOnUse(ICharacter character) { IItemsContainer container = GetItemsContainer(character); if (container is null) { return; } int newContainerSize = container.SlotsCount + ContainerSlotIncrease; if (newContainerSize < 1) { newContainerSize = 1; } else if (ContainerType == ContainerType.HotBar && newContainerSize > 10) { newContainerSize = 10; } else if (ContainerType == ContainerType.Inventory && newContainerSize > 255) { newContainerSize = 255; } Server.Items.SetSlotsCount(container, (byte)newContainerSize); }
public static void ServerTrySpawnItemToCharacterOrGround( ICharacter character, IProtoItem protoItem, uint countToSpawn, ref IItemsContainer groundContainer) { var result = character.ProtoCharacter.ServerCreateItem(character, protoItem, countToSpawn); if (result.IsEverythingCreated) { // successfully spawned at character return; } countToSpawn -= result.TotalCreatedCount; // cannot spawn - try spawn to the ground if (groundContainer is null) { groundContainer = ObjectGroundItemsContainer.ServerTryGetOrCreateGroundContainerAtTileOrNeighbors( character, character.Tile); if (groundContainer is null) { return; } } ServerItemsService.CreateItem(protoItem, groundContainer, count: countToSpawn); }
public static ItemsContainer GetOpenContainer() { int storageCount = Inventory.main.usedStorage.Count; if (Inventory.main.usedStorage.Count > 0) { IItemsContainer itemsContainer = Inventory.main.usedStorage[storageCount - 1]; if (itemsContainer is ItemsContainer) { ItemsContainer container = itemsContainer as ItemsContainer; GameObject parent = container.tr.parent.gameObject; //AddDebug(" parent " + parent.name); //Main.Log(" parent " + parent.name); //if (parent.GetComponentInChildren<Aquarium>()) if (parent.name == "Aquarium(Clone)") { //AddDebug(container.tr.name + " Aquarium "); return(null); } return(container); } } return(null); }
public override byte?FindSlotForItem(IItemsContainer container, IProtoItem protoItem) { var allowedSlotsIds = this.GetAllowedSlotsIds(protoItem); if (allowedSlotsIds is null) { return(null); } if (allowedSlotsIds.Length == 1) { // return only one appropriate slot return(allowedSlotsIds[0]); } // this equipment type allows placing to multiple slots // find an empty one of them foreach (var allowedSlotsId in allowedSlotsIds) { if (!container.IsSlotOccupied(allowedSlotsId)) { // empty slot found return(allowedSlotsId); } } // no empty slots found, return first allowed slot id return(allowedSlotsIds[0]); }
private void ServerItemRemovedHandler(IItemsContainer container, IItem item, ICharacter character) { if (character == null || !IsValidContainer(container)) { return; } var context = this.GetActiveContext(character, out var state); if (context == null) { return; } var protoItem = item.ProtoItem; if (!this.List.Contains(protoItem)) { return; } state.SetCountCurrent(state.CountCurrent + item.Count, this.RequiredCount); context.Refresh(); }
public static CreateItemResult TryDropToGround( IReadOnlyDropItemsList dropItemsList, Vector2Ushort tilePosition, double probabilityMultiplier, DropItemContext context, [CanBeNull] out IItemsContainer groundContainer) { // obtain the ground container to drop the items into var tile = Api.Server.World.GetTile(tilePosition); groundContainer = ObjectGroundItemsContainer .ServerTryGetOrCreateGroundContainerAtTileOrNeighbors(tile); if (groundContainer == null) { // cannot drop because there are no free space available on the ground return(new CreateItemResult() { IsEverythingCreated = false }); } var result = dropItemsList.TryDropToContainer(groundContainer, context, probabilityMultiplier); if (result.TotalCreatedCount == 0 && groundContainer.OccupiedSlotsCount == 0) { // nothing is spawned, the ground container should be destroyed Api.Server.World.DestroyObject(groundContainer.OwnerAsStaticObject); groundContainer = null; } return(result); }
public ViewModelItemsContainerExchange(IItemsContainer container, Action callbackTakeAllItemsSuccess) { this.callbackTakeAllItemsSuccess = callbackTakeAllItemsSuccess; this.Container = (IClientItemsContainer)container; var character = ClientCurrentCharacterHelper.Character; ClientContainersExchangeManager.Register( this, this.Container, allowedTargets: new[] { character.SharedGetPlayerContainerInventory(), character.SharedGetPlayerContainerHotbar() }); ClientContainersExchangeManager.Register( this, character.SharedGetPlayerContainerHotbar(), allowedTargets: new[] { this.Container }); ClientContainersExchangeManager.Register( this, character.SharedGetPlayerContainerInventory(), allowedTargets: new[] { this.Container }); // ReSharper disable once CanExtractXamlLocalizableStringCSharp this.inputListener = ClientInputContext .Start("Container exchange") .HandleButtonDown(GameButton.ContainerTakeAll, this.ExecuteCommandTakeAll) .HandleButtonDown(GameButton.ContainerMoveItemsMatchDown, this.ExecuteCommandMatchDown) .HandleButtonDown(GameButton.ContainerMoveItemsMatchUp, this.ExecuteCommandMatchUp); }
public override byte?FindSlotForItem(IItemsContainer container, IProtoItem protoItem) { if (protoItem is not IProtoItemEquipment protoEquipment) { // not an equipment - cannot be placed here return(null); } var allowedSlotsIds = protoEquipment.CompatibleContainerSlotsIds; if (allowedSlotsIds.Length == 1) { // return only one appropriate slot return(allowedSlotsIds[0]); } // this equipment type allows placing to multiple slots // find an empty one of them foreach (var allowedSlotsId in allowedSlotsIds) { if (!container.IsSlotOccupied(allowedSlotsId)) { // empty slot found return(allowedSlotsId); } } // no empty slots found, return first allowed slot id return(allowedSlotsIds[0]); }
public virtual MoveItemsResult ClientTryTakeAllItems( ICharacter character, IItemsContainer fromContainer, bool showNotificationIfInventoryFull = true) { throw new NotImplementedException(); }
public static CreateItemResult CalculateItemsResultExceptContainer( CreateItemResult result, IItemsContainer itemsContainer) { if (itemsContainer == null) { return(result); } var itemAmounts = new Dictionary <IItem, ushort>(result.ItemAmounts); foreach (var groundItem in itemsContainer.Items) { if (!itemAmounts.TryGetValue(groundItem, out var count)) { continue; } var newCount = count - groundItem.Count; if (newCount > 0) { itemAmounts[groundItem] = (ushort)newCount; } else { itemAmounts.Remove(groundItem); } } var newResult = new CreateItemResult(itemAmounts, (uint)itemAmounts.Sum(p => p.Value)); return(newResult); }
private static void ServerTryCompactContainer(IItemsContainer container) { if (isCompactingNow || container.IsDestroyed) { return; } var slotsCount = container.SlotsCount; if (slotsCount <= ServerSafeItemsSlotsCapacity) { return; } try { isCompactingNow = true; using var tempList = Api.Shared.WrapInTempList(container.Items); Server.Items.ReorderItems(container, tempList.AsList()); Server.Items.SetSlotsCount(container, slotsCount: Math.Max(container.OccupiedSlotsCount, ServerSafeItemsSlotsCapacity)); } finally { isCompactingNow = false; } }
private static bool ServerCanPlayerInteract(IItemsContainer itemsContainer, bool allowClientNotifications) { var worldObjectReactor = itemsContainer.OwnerAsStaticObject; var protoObject = (ProtoObjectGeneratorPragmium) itemsContainer.OwnerAsStaticObject.ProtoGameObject; if (!ProtoObjectGeneratorPragmium.SharedIsReactorActiveForItemsContainer(worldObjectReactor, itemsContainer)) { // can interact as the reactor is shut down return(true); } // reactor is active if (IsClient && allowClientNotifications) { NotificationSystem.ClientShowNotification(Notification_ReactorActive_Title, Notification_ReactorActive_Message, NotificationColor.Bad, icon: protoObject.Icon); } return(false); }
/// <summary> /// Immediately attempts to perform an item movement between two containers. /// </summary> /// <param name="context">A reference to the operation context.</param> /// <param name="item">The item being moved.</param> /// <param name="fromContainer">The container from which the movement is being performed.</param> /// <param name="toContainer">The container to which the movement is being performed.</param> /// <param name="fromIndex">Optional. The index within the container to move the item from.</param> /// <param name="toIndex">Optional. The index within the container to move the item to.</param> /// <param name="amountToMove">Optional. The amount of the thing to move. Defaults to 1.</param> /// <param name="requestorCreature">Optional. The creature that this movement is being performed in behalf of, if any.</param> /// <returns>True if the movement was successfully performed, false otherwise.</returns> /// <remarks>Changes game state, should only be performed after all pertinent validations happen.</remarks> private bool PerformItemMovement(IOperationContext context, IItem item, IItemsContainer fromContainer, IItemsContainer toContainer, byte fromIndex = byte.MaxValue, byte toIndex = byte.MaxValue, byte amountToMove = 1, ICreature requestorCreature = null) { const byte FallbackIndex = byte.MaxValue; if (item == null || fromContainer == null || toContainer == null) { return(false); } var sameContainer = fromContainer == toContainer; if (sameContainer && fromIndex == toIndex) { // no change at all. return(true); } // Edge case, check if the moving item is the target container. if (item is IContainerItem containerItem && toContainer is IContainerItem targetContainer && targetContainer.IsDescendantOf(containerItem)) { return(false); } (bool removeSuccessful, IThing removeRemainder) = fromContainer.RemoveItem(context.ItemFactory, ref item, amountToMove, fromIndex); if (!removeSuccessful) { // Failing to remove the item from the original container stops the entire operation. return(false); } if (fromContainer is ITile fromTile) { this.SendNotification(context, new TileUpdatedNotification(context.Map.FindPlayersThatCanSee(fromTile.Location), fromTile)); } /* context.EventRulesApi.EvaluateRules(this, EventRuleType.Separation, new SeparationEventRuleArguments(fromThingContainer.Location, item, requestorCreature)); */ IItem remainder = item; if (sameContainer && removeRemainder == null && fromIndex < toIndex) { // If the move happens within the same container, we need to adjust the index of where we're adding, depending if it is before or after. toIndex--; } if (!toContainer.AddItemToContainerRecursively(context.ItemFactory, ref remainder, toIndex, includeTileAsFallback: false) || remainder != null) { // There is some rollback to do, as we failed to add the entire thing. IItem rollbackRemainder = remainder ?? item; if (!fromContainer.AddItemToContainerRecursively(context.ItemFactory, ref rollbackRemainder, FallbackIndex, includeTileAsFallback: true)) { context.Logger.LogError($"Rollback failed on {nameof(this.PerformItemMovement)}. Thing: {rollbackRemainder.DescribeForLogger()}"); } } return(true); }
public static void ServerSendItemsNotification( ICharacter character, CreateItemResult createItemResult, IItemsContainer exceptItemsContainer) { createItemResult = CalculateItemsResultExceptContainer(createItemResult, exceptItemsContainer); ServerSendItemsNotification(character, createItemResult); }
/// <summary> /// Create crafting queue. Store it in server state of the object and update with Update() method. /// </summary> /// <param name="containerInput">Container with ingredients.</param> /// <param name="containerOutput">Container where the crafted items will go.</param> public CraftingQueue( [NotNull] IItemsContainer containerInput, [NotNull] IItemsContainer containerOutput) { this.QueueItems = new NetworkSyncList <CraftingQueueItem>(); this.ContainerInput = containerInput; this.ContainerOutput = containerOutput; }
public override void ClientOnItemPick(IItem item, IItemsContainer fromContainer) { base.ClientOnItemPick(item, fromContainer); if (fromContainer?.ProtoItemsContainer is ItemsContainerCharacterEquipment) { this.CallServer(_ => _.ServerRemote_Unequip(item, fromContainer)); } }
public override void ServerOnItemBrokeAndDestroyed(IItem item, IItemsContainer container, byte slotId) { if (container.ProtoItemsContainer is ItemsContainerGeneratorPragmium) { // place a broken part to the released container slot Server.Items.CreateItem <ItemReactorBrokenModule>(container, slotId: slotId); } }
public void ServerOnItemBrokeAndDestroyed(IItem item, IItemsContainer container, byte slotId) { if (container.ProtoItemsContainer is ItemsContainerGeneratorSolar) { // place a broken solar panel in the released container slot Server.Items.CreateItem <ItemSolarPanelBroken>(container, slotId: slotId); } }
/// <summary> /// Создаёт объект <see cref="UniqueItemsContainer{TItem}"/> /// </summary> /// <param name="itemsContainer">Контейнер, над элементами которого будет проверяться уникальность.</param> /// <param name="equalityComparer">Сравниватель элементов друг с другом.</param> public UniqueItemsContainer(IItemsContainer <TItem> itemsContainer, IEqualityComparer <TItem> equalityComparer) { Contract.Requires <ArgumentNullException>(itemsContainer != null); Contract.Requires <ArgumentNullException>(equalityComparer != null); _itemsContainer = itemsContainer; _itemsInQueue = new ConcurrentDictionary <TItem, TItem>(Environment.ProcessorCount * 3, 4, equalityComparer); }
public override void ServerOnItemRemoved( IItemsContainer container, IItem item, ICharacter character) { base.ServerOnItemRemoved(container, item, character); Api.SafeInvoke(() => ServerItemRemoved?.Invoke(container, item, character)); }
public override void ServerOnItemBrokeAndDestroyed(IItem item, IItemsContainer container, byte slotId) { if (container.OwnerAsCharacter is not null && container == container.OwnerAsCharacter.SharedGetPlayerContainerEquipment()) { // the equipped item is broken - explode immediately this.ServerExplode(item); } }
public static void Register( object key, IItemsContainer container, IItemsContainer[] allowedTargets = null, bool registerAllowedTargetsReverse = true) { //Api.Logger.Dev( // string.Format("Registering container for exchange:{0}(by {1}){2}{3}Allowed targets: {4}", // Environment.NewLine, // key.GetType().Name, // container, // Environment.NewLine, // allowedTargets?.Select(t => t.Id).GetJoinedString())); if (!ContainersOpenedBy.TryGetValue(key, out List <WrappedContainer> list)) { list = new List <WrappedContainer>(); ContainersOpenedBy.Add(key, list); } var clientItemsContainer = (IClientItemsContainer)container; var wrappedContainer = list.FirstOrDefault(p => p.Container == clientItemsContainer); if (wrappedContainer == null) { wrappedContainer = new WrappedContainer(clientItemsContainer); list.Add(wrappedContainer); if (!ActiveContainersReferencesCount.TryGetValue(clientItemsContainer, out int referencesCount)) { referencesCount = 1; ActiveContainersList.Add(clientItemsContainer); } else { referencesCount++; } ActiveContainersReferencesCount[clientItemsContainer] = referencesCount; } if (allowedTargets != null) { wrappedContainer.AddAllowedTargetContainers(allowedTargets); if (registerAllowedTargetsReverse) { foreach (var allowedTargetContainer in allowedTargets) { Register(key, allowedTargetContainer, new[] { container }, registerAllowedTargetsReverse: false); } } } }
public override void ServerOnDestroy(IItem gameObject) { base.ServerOnDestroy(gameObject); ICharacter character = gameObject.Container.OwnerAsCharacter; if (character is null) { return; } var playerPrivateState = PlayerCharacter.GetPrivateState(character); IItemsContainer objectGroundContainer = null; objectGroundContainer = ObjectPlayerLootContainer.ServerTryCreateLootContainer(character); if (objectGroundContainer is not null) { int slotCount = this.GetGroundSlotCount(playerPrivateState); // set slots count matching the total occupied slots count Server.Items.SetSlotsCount(objectGroundContainer, (byte)Math.Min(byte.MaxValue, objectGroundContainer.OccupiedSlotsCount + slotCount)); } if (objectGroundContainer is null) { objectGroundContainer = ObjectGroundItemsContainer.ServerTryGetOrCreateGroundContainerAtTileOrNeighbors(character, character.Tile); if (objectGroundContainer is null) { return; } } for (byte i = PlayerConstants.InventorySlotsCount; i < playerPrivateState.ContainerInventory.SlotsCount; i++) { IItem itemToDrop = playerPrivateState.ContainerInventory.GetItemAtSlot(i); if (itemToDrop is not null) { Server.Items.MoveOrSwapItem(itemToDrop, objectGroundContainer, out _); } } if (playerPrivateState.ContainerInventory.SlotsCount != PlayerConstants.InventorySlotsCount) { Api.Server.Items.SetSlotsCount(playerPrivateState.ContainerInventory, PlayerConstants.InventorySlotsCount); } WorldObjectClaimSystem.ServerTryClaim(objectGroundContainer.OwnerAsStaticObject, character, durationSeconds: objectGroundContainer.OwnerAsStaticObject.ProtoStaticWorldObject is ObjectPlayerLootContainer ? ObjectPlayerLootContainer.AutoDestroyTimeoutSeconds + (10 * 60) : WorldObjectClaimDuration.DroppedGoods); }
/// <summary> /// Конструктор для создания <see cref="InfinityPipe{TItem}"/>. /// </summary> /// <param name="itemsContainer">Внутреннее хранилище элементов.</param> public InfinityPipe(IItemsContainer <TItem> itemsContainer) { Contract.Requires <ArgumentNullException>(itemsContainer != null); _itemsContainer = itemsContainer; _awaitedSources = new ConcurrentQueue <TaskCompletionSource <TItem> >(); _completedTask = TaskEx.FromResult(true); _readerWriterLock = new ReaderWriterLockSlim(); }
public sealed override void ServerOnItemBrokeAndDestroyed(IItem item, IItemsContainer container, byte slotId) { base.ServerOnItemBrokeAndDestroyed(item, container, slotId); if (!(item.ProtoItem is ItemImplantBroken)) { // place a broken implant to the released container slot Server.Items.CreateItem <ItemImplantBroken>(container, slotId: slotId); } }
public override void ServerOnItemCountChanged( IItemsContainer container, IItem item, ushort oldCount, ushort newCount, ICharacter character) { base.ServerOnItemCountChanged(container, item, oldCount, newCount, character); Api.SafeInvoke(() => ServerItemCountChanged?.Invoke(container, item, oldCount, newCount, character)); }