Example #1
0
        /// <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);
        }
Example #3
0
        /// <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);
                }
            }
        }
Example #4
0
        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);
        }
Example #6
0
        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);
        }
Example #8
0
        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]);
        }
Example #9
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);
        }
Example #11
0
        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);
        }
Example #12
0
        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);
        }
Example #17
0
        /// <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);
 }
Example #19
0
 /// <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));
     }
 }
Example #21
0
 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);
     }
 }
Example #22
0
 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));
 }
Example #25
0
 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);
        }
Example #28
0
        /// <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));
 }