Exemple #1
0
        /// <summary>
        /// Attempts to get a matching ingredient stack for the given input.
        /// </summary>
        /// <param name="inputStack"></param>
        /// <returns></returns>
        public CookingRecipeStack GetMatchingStack(ItemStack inputStack)
        {
            if (inputStack == null)
            {
                return(null);
            }

            for (int i = 0; i < ValidStacks.Length; i++)
            {
                bool isWildCard = ValidStacks[i].Code.Path.Contains("*");
                bool found      =
                    (isWildCard && inputStack.Collectible.WildCardMatch(ValidStacks[i].Code)) ||
                    (!isWildCard && inputStack.Equals(world, ValidStacks[i].ResolvedItemstack, GlobalConstants.IgnoredStackAttributes)) ||
                    (ValidStacks[i].CookedStack?.ResolvedItemstack != null && inputStack.Equals(world, ValidStacks[i].CookedStack.ResolvedItemstack, GlobalConstants.IgnoredStackAttributes))
                ;

                if (found)
                {
                    return(ValidStacks[i]);
                }
            }


            return(null);
        }
Exemple #2
0
        public override void TryMergeStacks(ItemStackMergeOperation op)
        {
            op.MovableQuantity = GetMergableQuantity(op.SinkSlot.Itemstack, op.SourceSlot.Itemstack);
            if (op.MovableQuantity == 0)
            {
                return;
            }
            if (!op.SinkSlot.CanTakeFrom(op.SourceSlot))
            {
                return;
            }

            ItemStack sinkContent   = GetContent(op.World, op.SinkSlot.Itemstack);
            ItemStack sourceContent = GetContent(op.World, op.SourceSlot.Itemstack);

            if (sinkContent == null && sourceContent == null)
            {
                base.TryMergeStacks(op);
                return;
            }

            if (sinkContent == null || sourceContent == null)
            {
                op.MovableQuantity = 0; return;
            }

            if (!sinkContent.Equals(op.World, sourceContent, GlobalConstants.IgnoredStackAttributes))
            {
                op.MovableQuantity = 0; return;
            }

            WaterTightContainableProps props = GetStackProps(sourceContent);
            float maxItems         = BucketCapacityLitres * props.ItemsPerLitre;
            int   sourceEmptySpace = (int)(maxItems - (float)sourceContent.StackSize / props.ItemsPerLitre);
            int   sinkEmptySpace   = (int)(maxItems - (float)sinkContent.StackSize / props.ItemsPerLitre);

            if (sourceEmptySpace == 0 && sinkEmptySpace == 0)
            {
                // Full buckets are not stackable
                op.MovableQuantity = 0;
                //base.TryMergeStacks(op);
                return;
            }

            if (op.CurrentPriority == EnumMergePriority.DirectMerge)
            {
                int moved = TryAddContent(op.World, op.SinkSlot.Itemstack, sinkContent, sourceContent.StackSize);
                TryTakeContent(op.World, op.SourceSlot.Itemstack, moved);
                op.SourceSlot.MarkDirty();
                op.SinkSlot.MarkDirty();
            }


            op.MovableQuantity = 0;
            return;
        }
Exemple #3
0
        public override string GetHeldItemName(ItemStack itemStack)
        {
            ItemStack[] cStacks = GetContents(api.World, itemStack);
            if (cStacks.Length <= 1)
            {
                return(Lang.Get("pie-empty"));
            }

            ItemStack cstack = cStacks[1];

            if (cstack == null)
            {
                return(Lang.Get("pie-empty"));
            }

            bool equal = true;

            for (int i = 2; equal && i < cStacks.Length - 1; i++)
            {
                if (cStacks[i] == null)
                {
                    continue;
                }

                equal &= cstack.Equals(api.World, cStacks[i], GlobalConstants.IgnoredStackAttributes);
                cstack = cStacks[i];
            }

            string state = Variant["state"];

            if (MealMeshCache.ContentsRotten(cStacks))
            {
                return(Lang.Get("pie-single-rotten"));
            }

            if (equal)
            {
                return(Lang.Get("pie-single-" + cstack.Collectible.Code.ToShortString() + "-" + state));
            }
            else
            {
                EnumFoodCategory fillingFoodCat =
                    cStacks[1].Collectible.NutritionProps?.FoodCategory
                    ?? cStacks[1].ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory
                    ?? EnumFoodCategory.Vegetable
                ;

                return(Lang.Get("pie-mixed-" + fillingFoodCat.ToString().ToLowerInvariant() + "-" + state));
            }
        }
        /// <summary>
        /// Tries to put as much items/liquid as possible into a placed container and returns it how much items it actually moved
        /// </summary>
        /// <param name="world"></param>
        /// <param name="pos"></param>
        /// <param name="quantity"></param>
        public virtual int TryPutContent(IWorldAccessor world, BlockPos pos, ItemStack contentStack, int quantity)
        {
            if (contentStack == null)
            {
                return(0);
            }

            float availItems = contentStack.StackSize;

            ItemStack stack = GetContent(world, pos);

            if (stack == null)
            {
                WaterTightContainableProps props = GetInContainerProps(contentStack);
                if (props == null || !props.Containable)
                {
                    return(0);
                }


                float maxItems = CapacityLitres * props.ItemsPerLitre;


                int placeableItems = (int)GameMath.Min(quantity, maxItems, availItems);

                ItemStack placedstack = contentStack.Clone();
                placedstack.StackSize = Math.Min(quantity, placeableItems);
                SetContent(world, pos, placedstack);

                return(Math.Min(quantity, placeableItems));
            }
            else
            {
                if (!stack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes))
                {
                    return(0);
                }

                WaterTightContainableProps props = GetContentProps(world, pos);

                float maxItems       = CapacityLitres * props.ItemsPerLitre;
                int   placeableItems = (int)Math.Min(availItems, maxItems - (float)stack.StackSize);

                stack.StackSize += Math.Min(placeableItems, quantity);
                world.BlockAccessor.GetBlockEntity(pos).MarkDirty(true);
                (world.BlockAccessor.GetBlockEntity(pos) as BlockEntityContainer).Inventory[GetContainerSlotId(world, pos)].MarkDirty();

                return(Math.Min(placeableItems, quantity));
            }
        }
Exemple #5
0
        public void TryFillBucketFromBlock(EntityItem byEntityItem, BlockPos pos)
        {
            IWorldAccessor world = byEntityItem.World;

            Block block = world.BlockAccessor.GetBlock(pos);

            if (block.Attributes?["waterTightContainerProps"].Exists == false)
            {
                return;
            }
            WaterTightContainableProps props = block.Attributes?["waterTightContainerProps"].AsObject <WaterTightContainableProps>();

            if (props?.WhenFilled == null || !props.Containable)
            {
                return;
            }

            if (props.WhenFilled.Stack.ResolvedItemstack == null)
            {
                props.WhenFilled.Stack.Resolve(world, "blockbucket");
            }

            ItemStack whenFilledStack = props.WhenFilled.Stack.ResolvedItemstack;
            ItemStack contentStack    = GetContent(world, byEntityItem.Itemstack);
            bool      canFill         = contentStack == null || (contentStack.Equals(world, whenFilledStack, GlobalConstants.IgnoredStackAttributes) && GetCurrentLitres(world, byEntityItem.Itemstack) < BucketCapacityLitres);

            if (!canFill)
            {
                return;
            }

            whenFilledStack.StackSize = (int)(props.ItemsPerLitre * BucketCapacityLitres);

            ItemStack fullBucketStack = new ItemStack(this);

            SetContent(fullBucketStack, whenFilledStack);

            if (byEntityItem.Itemstack.StackSize <= 1)
            {
                byEntityItem.Itemstack = fullBucketStack;
            }
            else
            {
                byEntityItem.Itemstack.StackSize--;
                world.SpawnItemEntity(fullBucketStack, byEntityItem.LocalPos.XYZ);
            }

            world.PlaySoundAt(props.FillSpillSound, pos.X, pos.Y, pos.Z, null);
        }
        /// <summary>
        /// Tries to place in items/liquid and returns actually inserted quantity
        /// </summary>
        /// <param name="world"></param>
        /// <param name="containerStack"></param>
        /// <param name="desiredItems"></param>
        /// <returns></returns>
        public virtual int TryPutContent(IWorldAccessor world, ItemStack containerStack, ItemStack contentStack, int desiredItems)
        {
            if (contentStack == null)
            {
                return(0);
            }

            ItemStack stack = GetContent(world, containerStack);

            int availItems = contentStack.StackSize;

            ILiquidSink sink = containerStack.Collectible as ILiquidSink;

            if (stack == null)
            {
                WaterTightContainableProps props = GetInContainerProps(contentStack);
                if (props == null || !props.Containable)
                {
                    return(0);
                }


                int placeableItems = (int)(sink.CapacityLitres * props.ItemsPerLitre);

                ItemStack placedstack = contentStack.Clone();
                placedstack.StackSize = GameMath.Min(availItems, desiredItems, placeableItems);
                SetContent(containerStack, placedstack);

                return(Math.Min(desiredItems, placeableItems));
            }
            else
            {
                if (!stack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes))
                {
                    return(0);
                }

                WaterTightContainableProps props = GetContentProps(world, containerStack);

                float maxItems       = sink.CapacityLitres * props.ItemsPerLitre;
                int   placeableItems = (int)(maxItems - (float)stack.StackSize / props.ItemsPerLitre);

                stack.StackSize += Math.Min(placeableItems, desiredItems);

                return(Math.Min(placeableItems, desiredItems));
            }
        }
    public static bool tryFloorCraft(CraftingRecipe recipe, Vector3 pos)
    {
        List <ItemStack> itemStacks = Item.getItemStackInRadius(pos, floorCraftingRadius);

        if (canCraftRecipe(recipe, itemStacks))
        {
            List <Entity> items = GameManager.getEntityInRadius(ReuseableGameObject.ITEM_ENTITY, pos, floorCraftingRadius);
            foreach (ItemStack neededItem in recipe.requiredItems)
            {
                int neededAmount = neededItem.getAmount();
                foreach (Entity e in items)
                {
                    Item      item      = (Item)e;
                    ItemStack itemStack = item.getItemStack();
                    if (itemStack.Equals(neededItem))
                    {
                        if (itemStack.getAmount() > neededAmount)
                        {
                            itemStack.setAmount(itemStack.getAmount() - neededAmount);
                            neededAmount = 0;
                        }
                        else
                        {
                            neededAmount -= itemStack.getAmount();
                            item.remove();
                        }
                    }
                    if (neededAmount <= 0)
                    {
                        break;
                    }
                }
            }
            foreach (ItemStack item in recipe.getResults())
            {
                new Item(item, new Location(pos + new Vector3(0, 0.5f, 0)));;
            }
            return(true);
        }
        return(false);
    }
Exemple #8
0
        void UpdateRenderer()
        {
            if (renderer == null)
            {
                return;
            }

            ItemStack contentStack = inputStack == null ? outputStack : inputStack;
            ItemStack prevStack    = renderer.ContentStack;

            if (prevStack != null && prevStack.Equals(api.World, contentStack, GlobalConstants.IgnoredStackAttributes))
            {
                // But still update the stack for the temperature update
                renderer.ContentStack = contentStack;
                return;
            }

            renderer.contentStackRenderer?.Dispose();
            renderer.contentStackRenderer = null;

            if (contentStack?.Collectible is IInFirepitRendererSupplier)
            {
                IInFirepitRenderer childrenderer = (contentStack.Collectible as IInFirepitRendererSupplier).GetRendererWhenInFirepit(contentStack, this, contentStack == outputStack);
                if (childrenderer != null)
                {
                    renderer.SetChildRenderer(contentStack, childrenderer);
                    return;
                }
            }

            InFirePitProps props = GetRenderProps(contentStack);

            if (contentStack?.Collectible != null && !(contentStack?.Collectible is IInFirepitMeshSupplier) && (props == null || contentStack.Class == EnumItemClass.Item))
            {
                renderer.SetContents(contentStack, props?.Transform);
            }
            else
            {
                renderer.SetContents(null, null);
            }
        }
Exemple #9
0
        /// <summary>
        /// Tries to put as much items/liquid as possible into a placed bucket and returns it how much items it actually moved
        /// </summary>
        /// <param name="world"></param>
        /// <param name="pos"></param>
        /// <param name="quantity"></param>
        public int TryAddContent(IWorldAccessor world, BlockPos pos, ItemStack contentStack, int quantity)
        {
            ItemStack stack = GetContent(world, pos);

            if (stack == null)
            {
                WaterTightContainableProps props = GetStackProps(contentStack);
                if (props == null || !props.Containable)
                {
                    return(0);
                }


                float maxItems       = BucketCapacityLitres * props.ItemsPerLitre;
                int   placeableItems = (int)(maxItems - (float)contentStack.StackSize / props.ItemsPerLitre);

                ItemStack placedstack = contentStack.Clone();
                placedstack.StackSize = Math.Min(quantity, placeableItems);
                SetContent(world, pos, placedstack);

                return(Math.Min(quantity, placeableItems));
            }
            else
            {
                if (!stack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes))
                {
                    return(0);
                }

                WaterTightContainableProps props = GetContentProps(world, pos);

                float maxItems       = BucketCapacityLitres * props.ItemsPerLitre;
                int   placeableItems = (int)(maxItems - (float)stack.StackSize);

                stack.StackSize += Math.Min(placeableItems, quantity);
                world.BlockAccessor.GetBlockEntity(pos).MarkDirty(true);

                return(Math.Min(placeableItems, quantity));
            }
        }
        protected bool isSameMatAsPreviouslyAdded(ItemStack newStack)
        {
            BuildStage bstage = buildStages[currentBuildStage];

            for (int i = 0; i < inventory.Count; i++)
            {
                ItemSlot slot = inventory[i];
                if (slot.Empty)
                {
                    continue;
                }

                if (bstage.Materials.FirstOrDefault(bsm => bsm.ItemStack.Equals(Api.World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes)) != null)
                {
                    if (!newStack.Equals(Api.World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// Adds the passed stack to the container, returning any we couldn't add.
        /// </summary>
        public ItemStack addItemStack(ItemStack stack)
        {
            if (stack == null)
            {
                return(null);
            }

            // First try to fill up any slots that already have items
            for (int i = 0; i < this.items.Length; i++)
            {
                //slot = this.slots[i];
                ItemStack contents = this.items[i];
                if (contents == null || (!contents.Equals(stack)) || contents.count >= contents.item.maxStackSize)
                {
                    continue;
                }
                // Stacks are equal and slot is not full
                stack = contents.merge(stack);

                if (stack == null)
                {
                    return(null);
                }
            }

            // If we still have stuff to deposite, add it to an empty slot
            for (int i = 0; i < this.items.Length; i++)
            {
                if (this.items[i] == null)
                {
                    this.items[i] = stack;
                    return(null);
                }
            }
            return(stack);
        }
Exemple #12
0
        internal bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel)
        {
            ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;

            if (!byPlayer.Entity.Controls.Sneak)
            {
                if (contents == null)
                {
                    return(false);
                }
                ItemStack split = contents.Clone();
                split.StackSize = 1;
                contents.StackSize--;

                if (contents.StackSize == 0)
                {
                    contents = null;
                }

                if (!byPlayer.InventoryManager.TryGiveItemstack(split))
                {
                    world.SpawnItemEntity(split, Pos.ToVec3d().Add(0.5, 0.5, 0.5));
                }

                renderer?.SetContents(contents, stackRenderHeight, burning, true);
                MarkDirty(true);
                Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

                return(true);
            }
            else
            {
                if (slot.Itemstack == null)
                {
                    return(false);
                }

                // Add fuel
                CombustibleProperties combprops = slot.Itemstack.Collectible.CombustibleProps;
                if (combprops != null && combprops.BurnTemperature > 1000)
                {
                    (Api as ICoreClientAPI)?.World.Player.TriggerFpAnimation(EnumHandInteract.HeldItemInteract);

                    renderer?.SetContents(contents, stackRenderHeight, burning, false);
                    MarkDirty(true);

                    if (byPlayer.WorldData.CurrentGameMode != EnumGameMode.Creative)
                    {
                        slot.TakeOut(1);
                        slot.MarkDirty();
                    }


                    return(true);
                }


                string firstCodePart   = slot.Itemstack.Collectible.FirstCodePart();
                bool   forgableGeneric = slot.Itemstack.Collectible.Attributes?.IsTrue("forgable") == true;

                // Add heatable item
                if (contents == null && (firstCodePart == "ingot" || firstCodePart == "metalplate" || firstCodePart == "workitem" || forgableGeneric))
                {
                    contents           = slot.Itemstack.Clone();
                    contents.StackSize = 1;

                    slot.TakeOut(1);
                    slot.MarkDirty();

                    renderer?.SetContents(contents, stackRenderHeight, burning, true);
                    MarkDirty();
                    Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

                    return(true);
                }

                // Merge heatable item
                if (!forgableGeneric && contents != null && contents.Equals(Api.World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes) && contents.StackSize < maxItems && contents.StackSize < contents.Collectible.MaxStackSize)
                {
                    float myTemp  = contents.Collectible.GetTemperature(Api.World, contents);
                    float histemp = slot.Itemstack.Collectible.GetTemperature(Api.World, slot.Itemstack);

                    contents.Collectible.SetTemperature(world, contents, (myTemp * contents.StackSize + histemp * 1) / (contents.StackSize + 1));
                    contents.StackSize++;

                    slot.TakeOut(1);
                    slot.MarkDirty();

                    renderer?.SetContents(contents, stackRenderHeight, burning, true);
                    Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

                    MarkDirty();
                    return(true);
                }

                return(false);
            }
        }
Exemple #13
0
    internal bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel)
    {
        ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;

        if (!byPlayer.Entity.Controls.Sneak)
        {
            if (contents == null)
            {
                return(false);
            }
            ItemStack split = contents.Clone();
            split.StackSize = 1;
            contents.StackSize--;

            if (contents.StackSize == 0)
            {
                contents = null;
            }

            if (!byPlayer.InventoryManager.TryGiveItemstack(split))
            {
                world.SpawnItemEntity(split, Pos.ToVec3d().Add(0.5, 0.5, 0.5));
            }

            if (renderer != null)
            {
                renderer.SetContents(contents, burning, true);
            }
            MarkDirty();
            Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

            return(true);
        }
        else
        {
            if (slot.Itemstack == null)
            {
                return(false);
            }

            string firstCodePart   = slot.Itemstack.Collectible.FirstCodePart();
            bool   forgableGeneric = false;
            if (slot.Itemstack.Collectible.Attributes != null)
            {
                forgableGeneric = slot.Itemstack.Collectible.Attributes.IsTrue("forgable") == true;
            }

            // Add heatable item
            if (contents == null && (firstCodePart == "ingot" || firstCodePart == "metalplate" || firstCodePart == "workitem" || forgableGeneric))
            {
                contents           = slot.Itemstack.Clone();
                contents.StackSize = 1;

                slot.TakeOut(1);
                slot.MarkDirty();

                if (renderer != null)
                {
                    renderer.SetContents(contents, burning, true);
                }
                MarkDirty();
                Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

                return(true);
            }

            // Merge heatable item
            if (!forgableGeneric && contents != null && contents.Equals(Api.World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes) && contents.StackSize < 4 && contents.StackSize < contents.Collectible.MaxStackSize)
            {
                float myTemp  = contents.Collectible.GetTemperature(Api.World, contents);
                float histemp = slot.Itemstack.Collectible.GetTemperature(Api.World, slot.Itemstack);

                contents.Collectible.SetTemperature(world, contents, (myTemp * contents.StackSize + histemp * 1) / (contents.StackSize + 1));
                contents.StackSize++;

                slot.TakeOut(1);
                slot.MarkDirty();

                if (renderer != null)
                {
                    renderer.SetContents(contents, burning, true);
                }
                Api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), Pos.X, Pos.Y, Pos.Z, byPlayer, false);

                MarkDirty();
                return(true);
            }

            return(false);
        }
    }
Exemple #14
0
        public bool ReceiveDistillate(ItemSlot sourceSlot, DistillationProps props)
        {
            if (sourceSlot.Empty)
            {
                lastReceivedDistillateTotalMs = -99999;
                return(true);
            }
            if (inventory[1].Empty)
            {
                lastReceivedDistillateTotalMs = Api.World.ElapsedMilliseconds;
                lastReceivedDistillate        = props.DistilledStack.ResolvedItemstack.Clone();
                return(false);
            }

            ItemStack distilledStack = props.DistilledStack.ResolvedItemstack.Clone();

            lastReceivedDistillate = distilledStack.Clone();

            ItemStack bucketStack = inventory[1].Itemstack;
            BlockLiquidContainerTopOpened bucketBlock = bucketStack.Collectible as BlockLiquidContainerTopOpened;

            if (bucketBlock.IsEmpty(bucketStack))
            {
                if (Api.Side == EnumAppSide.Server)
                {
                    distilledStack.StackSize = 1;
                    bucketBlock.SetContent(bucketStack, distilledStack);
                }
            }
            else
            {
                ItemStack currentLiquidStack = bucketBlock.GetContent(bucketStack);
                if (!currentLiquidStack.Equals(Api.World, distilledStack, GlobalConstants.IgnoredStackAttributes))
                {
                    lastReceivedDistillateTotalMs = -99999;
                    return(false);
                }

                if (Api.Side == EnumAppSide.Server)
                {
                    if (!inventory[0].Empty || Api.World.Rand.NextDouble() > 0.5f) // Missing coolant reduces distillation efficeny by 50%
                    {
                        currentLiquidStack.StackSize++;
                        bucketBlock.SetContent(bucketStack, currentLiquidStack);
                    }

                    if (!inventory[0].Empty && Api.World.Rand.NextDouble() < 0.5f)
                    {
                        inventory[0].TakeOut(1);
                    }
                }
            }


            float itemsToRemove = 1 / props.Ratio - partialStackAccum;
            int   stackSize     = (int)Math.Ceiling(itemsToRemove);

            partialStackAccum = itemsToRemove - stackSize;

            if (stackSize > 0)
            {
                sourceSlot.TakeOut(stackSize);
            }

            MarkDirty(true);
            lastReceivedDistillateTotalMs = Api.World.ElapsedMilliseconds;

            return(true);
        }
Exemple #15
0
        internal bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel)
        {
            IItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;

            if (!byPlayer.Entity.Controls.Sneak)
            {
                if (contents == null)
                {
                    return(false);
                }
                ItemStack split = contents.Clone();
                split.StackSize = 1;
                contents.StackSize--;

                if (contents.StackSize == 0)
                {
                    contents = null;
                }

                //api.World.Logger.Notification("Forge item retrieve temp: {0}, side {1}", split.Collectible.GetTemperature(api.World, split), api.Side);

                if (!byPlayer.InventoryManager.TryGiveItemstack(split))
                {
                    world.SpawnItemEntity(contents, pos.ToVec3d().Add(0.5, 0.5, 0.5));
                }

                renderer?.SetContents(contents, fuelLevel, burning, true);
                MarkDirty();
                api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), pos.X, pos.Y, pos.Z, byPlayer, false);

                return(true);
            }
            else
            {
                if (slot.Itemstack == null)
                {
                    return(false);
                }

                // Add fuel
                CombustibleProperties combprops = slot.Itemstack.Collectible.CombustibleProps;
                if (combprops != null && combprops.BurnTemperature > 1000)
                {
                    if (fuelLevel >= 10 / 16f)
                    {
                        return(false);
                    }
                    fuelLevel += 1 / 16f;

                    renderer?.SetContents(contents, fuelLevel, burning, false);
                    MarkDirty();

                    slot.TakeOut(1);
                    slot.MarkDirty();


                    return(true);
                }


                string firstCodePart = slot.Itemstack.Collectible.FirstCodePart();

                // Add heatable item
                if (contents == null && (firstCodePart == "ingot" || firstCodePart == "metalplate" || firstCodePart == "workitem"))
                {
                    contents           = slot.Itemstack.Clone();
                    contents.StackSize = 1;

                    slot.TakeOut(1);
                    slot.MarkDirty();

                    renderer?.SetContents(contents, fuelLevel, burning, true);
                    MarkDirty();
                    api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), pos.X, pos.Y, pos.Z, byPlayer, false);

                    return(true);
                }

                // Merge heatable item
                if (contents != null && contents.Equals(api.World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes) && contents.StackSize < 4 && contents.StackSize < contents.Collectible.MaxStackSize)
                {
                    float myTemp  = contents.Collectible.GetTemperature(api.World, contents);
                    float histemp = slot.Itemstack.Collectible.GetTemperature(api.World, slot.Itemstack);

                    contents.Collectible.SetTemperature(world, contents, (myTemp * contents.StackSize + histemp * 1) / (contents.StackSize + 1));
                    contents.StackSize++;

                    slot.TakeOut(1);
                    slot.MarkDirty();

                    renderer?.SetContents(contents, fuelLevel, burning, true);
                    api.World.PlaySoundAt(new AssetLocation("sounds/block/ingot"), pos.X, pos.Y, pos.Z, byPlayer, false);

                    MarkDirty();
                    return(true);
                }

                return(false);
            }
        }
Exemple #16
0
        public MeshData GetPieMesh(ItemStack pieStack, ModelTransform transform = null)
        {
            // Slot 0: Base dough
            // Slot 1: Filling
            // Slot 2: Crust dough

            nowTesselatingBlock = pieStack.Block as BlockPie;
            if (nowTesselatingBlock == null)
            {
                return(null);                              //This will occur if the pieStack changed to rot
            }
            contentStacks = nowTesselatingBlock.GetContents(capi.World, pieStack);

            int pieSize = pieStack.Attributes.GetInt("pieSize");


            // At this spot we have to determine the textures for "dough" and "filling"
            // Texture determination rules:
            // 1. dough is simple: first itemstack must be dough, take from attributes
            // 2. pie allows 4 items as fillings, but with specific mixing rules
            //    - berries/fruit can be mixed
            //    - vegetables can be mixed
            //    - meat can be mixed
            // no other mixing allowed

            // Thus we deduce: It's enough to test if
            // a) all 4 fillings are equal: Then use texture from inPieProperties from first one
            // b) Otherwise use hardcoded
            //    for item.NutritionProps.FoodCategory == Vegetable   => block/food/pie/fill-mixedvegetable.png
            //    for item.NutritionProps.FoodCategory == Protein   => block/food/pie/fill-mixedmeat.png
            //    for item.NutritionProps.FoodCategory == Fruit   => block/food/pie/fill-mixedfruit.png

            var stackprops = contentStacks.Select(stack => stack?.ItemAttributes?["inPieProperties"]?.AsObject <InPieProperties>(null, stack.Collectible.Code.Domain)).ToArray();

            int bakeLevel = pieStack.Attributes.GetInt("bakeLevel", 0);

            if (stackprops.Length == 0)
            {
                return(null);
            }


            ItemStack cstack = contentStacks[1];
            bool      equal  = true;

            for (int i = 2; equal && i < contentStacks.Length - 1; i++)
            {
                if (contentStacks[i] == null || cstack == null)
                {
                    continue;
                }

                equal &= cstack.Equals(capi.World, contentStacks[i], GlobalConstants.IgnoredStackAttributes);
                cstack = contentStacks[i];
            }


            if (ContentsRotten(contentStacks))
            {
                crustTextureLoc    = new AssetLocation("block/rot/rot");
                fillingTextureLoc  = new AssetLocation("block/rot/rot");
                topCrustTextureLoc = new AssetLocation("block/rot/rot");
            }
            else
            {
                if (stackprops[0] != null)
                {
                    crustTextureLoc      = stackprops[0].Texture.Clone();
                    crustTextureLoc.Path = crustTextureLoc.Path.Replace("{bakelevel}", "" + (bakeLevel + 1));
                    fillingTextureLoc    = new AssetLocation("block/transparent");
                }

                topCrustTextureLoc = new AssetLocation("block/transparent");
                if (stackprops[5] != null)
                {
                    topCrustTextureLoc      = stackprops[5].Texture.Clone();
                    topCrustTextureLoc.Path = topCrustTextureLoc.Path.Replace("{bakelevel}", "" + (bakeLevel + 1));
                }

                if (contentStacks[1] != null)
                {
                    EnumFoodCategory fillingFoodCat =
                        contentStacks[1].Collectible.NutritionProps?.FoodCategory
                        ?? contentStacks[1].ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory
                        ?? EnumFoodCategory.Vegetable
                    ;

                    fillingTextureLoc = equal ? stackprops[1]?.Texture : pieMixedFillingTextures[(int)fillingFoodCat];
                }
            }


            int  fillLevel  = (contentStacks[1] != null ? 1 : 0) + (contentStacks[2] != null ? 1 : 0) + (contentStacks[3] != null ? 1 : 0) + (contentStacks[4] != null ? 1 : 0);
            bool isComplete = fillLevel == 4;

            AssetLocation shapeloc = isComplete ? pieShapeBySize[pieSize - 1] : pieShapeLocByFillLevel[fillLevel];

            shapeloc.WithPathAppendixOnce(".json").WithPathPrefixOnce("shapes/");
            Shape    shape = capi.Assets.TryGet(shapeloc).ToObject <Shape>();
            MeshData mesh;

            int topCrustType = pieStack.Attributes.GetInt("topCrustType");

            string[] topCrusts         = new string[] { "origin/base/top crust full/*", "origin/base/top crust square/*", "origin/base/top crust diagonal/*" };
            string[] selectiveElements = new string[] { "origin/base/crust regular/*", "origin/base/filling/*", "origin/base/base-quarter/*", "origin/base/fillingquarter/*", topCrusts[topCrustType] };

            capi.Tesselator.TesselateShape("pie", shape, out mesh, this, null, 0, 0, 0, null, selectiveElements);
            if (transform != null)
            {
                mesh.ModelTransform(transform);
            }

            return(mesh);
        }
Exemple #17
0
        public bool TryFillBucketFromBlock(IItemSlot itemslot, IEntityAgent byEntity, BlockPos pos)
        {
            IPlayer        byPlayer = (byEntity as EntityPlayer)?.Player;
            IBlockAccessor blockAcc = byEntity.World.BlockAccessor;

            Block block = blockAcc.GetBlock(pos);

            if (block.Attributes?["waterTightContainerProps"].Exists == false)
            {
                return(false);
            }

            WaterTightContainableProps props = block.Attributes?["waterTightContainerProps"]?.AsObject <WaterTightContainableProps>();

            if (props?.WhenFilled == null || !props.Containable)
            {
                return(false);
            }

            props.WhenFilled.Stack.Resolve(byEntity.World, "blockbucket");

            ItemStack contentStack = GetContent(byEntity.World, itemslot.Itemstack);

            if (contentStack != null && contentStack.Equals(props.WhenFilled.Stack.ResolvedItemstack))
            {
                SetContent(itemslot.Itemstack, contentStack);
                itemslot.MarkDirty();
                return(true);
            }

            // Is full
            if (contentStack != null && contentStack.StackSize == (int)(props.ItemsPerLitre * BucketCapacityLitres))
            {
                return(false);
            }

            contentStack           = props.WhenFilled.Stack.ResolvedItemstack.Clone();
            contentStack.StackSize = (int)(props.ItemsPerLitre * BucketCapacityLitres);

            ItemStack fullBucketStack = new ItemStack(this);

            SetContent(fullBucketStack, contentStack);


            if (itemslot.Itemstack.StackSize <= 1)
            {
                itemslot.Itemstack = fullBucketStack;
            }
            else
            {
                itemslot.TakeOut(1);
                if (!byPlayer.InventoryManager.TryGiveItemstack(fullBucketStack, true))
                {
                    byEntity.World.SpawnItemEntity(fullBucketStack, byEntity.LocalPos.XYZ);
                }
            }

            itemslot.MarkDirty();
            byEntity.World.PlaySoundAt(props.FillSpillSound, pos.X, pos.Y, pos.Z, byPlayer);

            return(true);
        }
Exemple #18
0
        public override void FromTreeAttributes(ITreeAttribute tree, IWorldAccessor worldForResolving)
        {
            bool      wasEmpty    = Inventory.Empty;
            ItemStack beforeStack = mashStack;

            base.FromTreeAttributes(tree, worldForResolving);

            if (worldForResolving.Side == EnumAppSide.Client)
            {
                if (listenerId > 0 && juiceableLitresLeft <= 0)
                {
                    UnregisterGameTickListener(listenerId);
                    listenerId = 0;
                }
                renderer?.reloadMeshes(getJuiceableProps(mashStack), wasEmpty != Inventory.Empty || (beforeStack != null && mashStack != null && !beforeStack.Equals(Api.World, mashStack, GlobalConstants.IgnoredStackAttributes)));
                genBucketMesh();
            }
        }
Exemple #19
0
        private bool TryAddIngredientFrom(ItemSlot slot, IPlayer byPlayer = null)
        {
            var pieProps = slot.Itemstack.ItemAttributes?["inPieProperties"]?.AsObject <InPieProperties>(null, slot.Itemstack.Collectible.Code.Domain);

            if (pieProps == null)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "notpieable", Lang.Get("This item can not be added to pies"));
                }
                return(false);
            }

            if (slot.StackSize < 2)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "notpieable", Lang.Get("Need at least 2 items each"));
                }
                return(false);
            }

            var pieBlock = (inv[0].Itemstack.Block as BlockPie);

            if (pieBlock == null)
            {
                return(false);
            }

            ItemStack[] cStacks = pieBlock.GetContents(Api.World, inv[0].Itemstack);

            bool isFull     = cStacks[1] != null && cStacks[2] != null && cStacks[3] != null && cStacks[4] != null;
            bool hasFilling = cStacks[1] != null || cStacks[2] != null || cStacks[3] != null || cStacks[4] != null;

            if (isFull)
            {
                if (pieProps.PartType == EnumPiePartType.Crust)
                {
                    if (cStacks[5] == null)
                    {
                        cStacks[5] = slot.TakeOut(2);
                        pieBlock.SetContents(inv[0].Itemstack, cStacks);
                    }
                    else
                    {
                        ItemStack stack = inv[0].Itemstack;
                        stack.Attributes.SetInt("topCrustType", (stack.Attributes.GetInt("topCrustType") + 1) % 3);
                    }
                    return(true);
                }
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "piefullfilling", Lang.Get("Can't add more filling - already completely filled pie"));
                }
                return(false);
            }

            if (pieProps.PartType != EnumPiePartType.Filling)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "pieneedsfilling", Lang.Get("Need to add a filling next"));
                }
                return(false);
            }


            if (!hasFilling)
            {
                cStacks[1] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }

            var foodCats   = cStacks.Select(stack => stack?.Collectible.NutritionProps?.FoodCategory ?? stack?.ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory ?? EnumFoodCategory.Vegetable).ToArray();
            var stackprops = cStacks.Select(stack => stack?.ItemAttributes["inPieProperties"]?.AsObject <InPieProperties>(null, stack.Collectible.Code.Domain)).ToArray();

            ItemStack        cstack  = slot.Itemstack;
            EnumFoodCategory foodCat = slot.Itemstack?.Collectible.NutritionProps?.FoodCategory ?? slot.Itemstack?.ItemAttributes?["nutritionPropsWhenInMeal"]?.AsObject <FoodNutritionProperties>()?.FoodCategory ?? EnumFoodCategory.Vegetable;

            bool equal         = true;
            bool foodCatEquals = true;

            for (int i = 1; equal && i < cStacks.Length - 1; i++)
            {
                if (cstack == null)
                {
                    continue;
                }

                equal         &= cStacks[i] == null || cstack.Equals(Api.World, cStacks[i], GlobalConstants.IgnoredStackAttributes);
                foodCatEquals &= cStacks[i] == null || foodCats[i] == foodCat;

                cstack  = cStacks[i];
                foodCat = foodCats[i];
            }

            int emptySlotIndex = 2 + (cStacks[2] != null ? 1 + (cStacks[3] != null ? 1 : 0) : 0);

            if (equal)
            {
                cStacks[emptySlotIndex] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }

            if (!foodCatEquals)
            {
                if (byPlayer != null && capi != null)
                {
                    capi.TriggerIngameError(this, "piefullfilling", Lang.Get("Can't mix fillings from different food categories"));
                }
                return(false);
            }
            else
            {
                if (!stackprops[1].AllowMixing)
                {
                    if (byPlayer != null && capi != null)
                    {
                        capi.TriggerIngameError(this, "piefullfilling", Lang.Get("You really want to mix these to ingredients?! That would taste horrible!"));
                    }
                    return(false);
                }

                cStacks[emptySlotIndex] = slot.TakeOut(2);
                pieBlock.SetContents(inv[0].Itemstack, cStacks);
                return(true);
            }
        }
        public override void OnMouseMove(ICoreClientAPI api, MouseEvent args)
        {
            if (!Bounds.ParentBounds.PointInside(args.X, args.Y))
            {
                if (hoverSlotId != -1)
                {
                    api.Input.TriggerOnMouseLeaveSlot(inventory[hoverSlotId]);
                }
                hoverSlotId = -1;
                return;
            }

            for (int i = 0; i < slotBounds.Length; i++)
            {
                if (i >= renderedSlots.Count)
                {
                    break;
                }

                if (slotBounds[i].PointInside(args.X, args.Y))
                {
                    int       newHoverSlotid = renderedSlots.GetKeyAtIndex(i);
                    ItemSlot  newHoverSlot   = inventory[newHoverSlotid];
                    ItemStack stack          = newHoverSlot.Itemstack;

                    // Cheap hax for hover-right-mouse-down slot filling
                    if (isRightMouseDownStartedInsideElem && !wasMouseDownOnSlotIndex.Contains(i))
                    {
                        wasMouseDownOnSlotIndex.Add(i);

                        if (stack == null || stack.Equals(api.World, api.World.Player.InventoryManager.MouseItemSlot.Itemstack, GlobalConstants.IgnoredStackAttributes))
                        {
                            SlotClick(
                                api,
                                newHoverSlotid,
                                EnumMouseButton.Right,
                                api.Input.KeyboardKeyState[(int)GlKeys.ShiftLeft],
                                api.Input.KeyboardKeyState[(int)GlKeys.LControl],
                                api.Input.KeyboardKeyState[(int)GlKeys.LAlt]
                                );
                        }
                    }

                    // Cheap hax for hover-left-mouse-down slot filling
                    if (isLeftMouseDownStartedInsideElem && !wasMouseDownOnSlotIndex.Contains(i))
                    {
                        if (stack == null || stack.Equals(api.World, referenceDistributStack, GlobalConstants.IgnoredStackAttributes))
                        {
                            wasMouseDownOnSlotIndex.Add(i);
                            leftMouseDownDistributeSlotsBySlotid.Add(newHoverSlotid, stack == null ? 0 : stack.StackSize);

                            if (api.World.Player.InventoryManager.MouseItemSlot.StackSize > 0)
                            {
                                SlotClick(
                                    api,
                                    newHoverSlotid,
                                    EnumMouseButton.Left,
                                    api.Input.KeyboardKeyState[(int)GlKeys.ShiftLeft],
                                    api.Input.KeyboardKeyState[(int)GlKeys.LControl],
                                    api.Input.KeyboardKeyState[(int)GlKeys.LAlt]
                                    );
                            }

                            if (api.World.Player.InventoryManager.MouseItemSlot.StackSize <= 0)
                            {
                                RedistributeStacks(newHoverSlotid);
                            }
                        }
                    }



                    if (newHoverSlotid != hoverSlotId && newHoverSlot != null)
                    {
                        api.Input.TriggerOnMouseEnterSlot(newHoverSlot);
                        hoverInv = newHoverSlot.Inventory;
                    }

                    if (newHoverSlotid != hoverSlotId)
                    {
                        tabbedSlotId = -1;
                    }

                    hoverSlotId = newHoverSlotid;
                    return;
                }
            }

            if (hoverSlotId != -1)
            {
                api.Input.TriggerOnMouseLeaveSlot(inventory[hoverSlotId]);
            }
            hoverSlotId = -1;
        }