예제 #1
0
        public override void OnGroundIdle(EntityItem entityItem)
        {
            entityItem.Die(EnumDespawnReason.Removed);

            if (entityItem.World.Side == EnumAppSide.Server)
            {
                Vec3d pos = entityItem.ServerPos.XYZ;

                WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(entityItem.Itemstack);
                float litres = (float)entityItem.Itemstack.StackSize / props.ItemsPerLitre;

                entityItem.World.SpawnCubeParticles(pos, entityItem.Itemstack, 0.75f, Math.Min(100, (int)(2 * litres)), 0.45f);
                entityItem.World.PlaySoundAt(new AssetLocation("sounds/environment/smallsplash"), (float)pos.X, (float)pos.Y, (float)pos.Z, null);

                BlockEntityFarmland bef = api.World.BlockAccessor.GetBlockEntity(pos.AsBlockPos) as BlockEntityFarmland;
                if (bef != null)
                {
                    bef.WaterFarmland(Height.ToInt() / 6f, false);
                    bef.MarkDirty(true);
                }
            }



            base.OnGroundIdle(entityItem);
        }
예제 #2
0
        public override void OnHeldInteractStart(IItemSlot itemslot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, ref EnumHandHandling handHandling)
        {
            if (blockSel == null || byEntity.Controls.Sneak)
            {
                return;
            }
            IPlayer byPlayer = (byEntity as EntityPlayer)?.Player;

            Block targetedBlock = byEntity.World.BlockAccessor.GetBlock(blockSel.Position);

            if (targetedBlock.HasBehavior(typeof(BlockBehaviorLiquidContainer), true))
            {
                if (!byEntity.World.TestPlayerAccessBlock(byPlayer, blockSel.Position, EnumBlockAccessFlags.Use))
                {
                    return;
                }

                BlockBehaviorLiquidContainer bh = targetedBlock.GetBehavior(typeof(BlockBehaviorLiquidContainer), true) as BlockBehaviorLiquidContainer;

                if (bh.OnInteractWithBucket(itemslot, byEntity, blockSel))
                {
                    handHandling = EnumHandHandling.PreventDefaultAction;
                    return;
                }
            }


            if (!byEntity.World.TestPlayerAccessBlock(byPlayer, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak))
            {
                return;
            }

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

            bool isEmpty = contentStack == null;


            if (!TryFillBucketFromBlock(itemslot, byEntity, blockSel.Position))
            {
                BlockBucket targetBucket = targetedBlock as BlockBucket;
                if (targetBucket != null)
                {
                    if (targetBucket.TryAddContent(byEntity.World, blockSel.Position, contentStack, 1) > 0)
                    {
                        TryTakeContent(byEntity.World, itemslot.Itemstack, 1);
                        WaterTightContainableProps props = GetContentProps(byEntity.World, itemslot.Itemstack);

                        byEntity.World.PlaySoundAt(props.FillSpillSound, blockSel.Position.X, blockSel.Position.Y, blockSel.Position.Z, byPlayer);
                    }
                }
                else
                {
                    SpillContents(itemslot, byEntity, blockSel);
                }
            }

            // Prevent placing on normal use
            handHandling = EnumHandHandling.PreventDefaultAction;
        }
예제 #3
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;
        }
예제 #4
0
        public MeshData GenMesh(ICoreClientAPI capi, ItemStack contentStack, BlockPos forBlockPos = null)
        {
            Shape    shape = capi.Assets.TryGet("shapes/block/wood/bucket/empty.json").ToObject <Shape>();
            MeshData bucketmesh;

            capi.Tesselator.TesselateShape(this, shape, out bucketmesh);

            if (contentStack != null)
            {
                WaterTightContainableProps props = GetInContainerProps(contentStack);

                ContainerTextureSource contentSource = new ContainerTextureSource(capi, contentStack, props.Texture);
                shape = capi.Assets.TryGet("shapes/block/wood/bucket/contents.json").ToObject <Shape>();
                MeshData contentMesh;
                capi.Tesselator.TesselateShape("bucket", shape, out contentMesh, contentSource, new Vec3f(Shape.rotateX, Shape.rotateY, Shape.rotateZ));

                contentMesh.Translate(0, GameMath.Min(7 / 16f, contentStack.StackSize / props.ItemsPerLitre * 0.7f / 16f), 0);

                if (props.ClimateColorMap != null)
                {
                    int col = capi.World.ApplyColorMapOnRgba(props.ClimateColorMap, null, ColorUtil.WhiteArgb, 196, 128, false);
                    if (forBlockPos != null)
                    {
                        col = capi.World.ApplyColorMapOnRgba(props.ClimateColorMap, null, ColorUtil.WhiteArgb, forBlockPos.X, forBlockPos.Y, forBlockPos.Z, false);
                    }

                    byte[] rgba = ColorUtil.ToBGRABytes(col);

                    for (int i = 0; i < contentMesh.Rgba.Length; i++)
                    {
                        contentMesh.Rgba[i] = (byte)((contentMesh.Rgba[i] * rgba[i % 4]) / 255);
                    }
                }

                for (int i = 0; i < contentMesh.Flags.Length; i++)
                {
                    contentMesh.Flags[i] = contentMesh.Flags[i] & ~(1 << 12); // Remove water waving flag
                }

                bucketmesh.AddMeshData(contentMesh);

                // Water flags
                if (forBlockPos != null)
                {
                    bucketmesh.CustomInts       = new CustomMeshDataPartInt(bucketmesh.FlagsCount);
                    bucketmesh.CustomInts.Count = bucketmesh.FlagsCount;
                    bucketmesh.CustomInts.Values.Fill(0x4000000); // light foam only

                    bucketmesh.CustomFloats       = new CustomMeshDataPartFloat(bucketmesh.FlagsCount * 2);
                    bucketmesh.CustomFloats.Count = bucketmesh.FlagsCount * 2;
                }
            }


            return(bucketmesh);
        }
예제 #5
0
        string getContentsText()
        {
            string contents = "Contents:";

            if (Inventory[0].Empty && Inventory[1].Empty)
            {
                contents += "\nNone.";
            }
            else
            {
                if (!Inventory[1].Empty)
                {
                    ItemStack stack = Inventory[1].Itemstack;
                    WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(stack);

                    if (props != null)
                    {
                        string incontainername = Lang.Get("incontainer-" + stack.Class.ToString().ToLowerInvariant() + "-" + stack.Collectible.Code.Path);
                        contents += "\n" + Lang.Get(props.MaxStackSize > 0 ? "{0}x of {1}" : "{0} litres of {1}", (float)stack.StackSize / props.ItemsPerLitre, incontainername);
                    }
                    else
                    {
                        contents += "\n" + Lang.Get("{0}x of {1}", stack.StackSize, stack.GetName());
                    }
                }

                if (!Inventory[0].Empty)
                {
                    ItemStack stack = Inventory[0].Itemstack;
                    contents += "\n" + Lang.Get("{0}x of {1}", stack.StackSize, stack.GetName());
                }

                BlockEntityBarrel bebarrel = capi.World.BlockAccessor.GetBlockEntity(BlockEntityPosition) as BlockEntityBarrel;
                if (bebarrel.CurrentRecipe != null)
                {
                    ItemStack outStack = bebarrel.CurrentRecipe.Output.ResolvedItemstack;
                    WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(outStack);

                    string timeText = bebarrel.CurrentRecipe.SealHours > 24 ? Lang.Get("{0} days", Math.Round(bebarrel.CurrentRecipe.SealHours / capi.World.Calendar.HoursPerDay, 1)) : Lang.Get("{0} hours", bebarrel.CurrentRecipe.SealHours);

                    if (props != null)
                    {
                        string incontainername = Lang.Get("incontainer-" + outStack.Class.ToString().ToLowerInvariant() + "-" + outStack.Collectible.Code.Path);
                        float  litres          = (float)bebarrel.CurrentOutSize / props.ItemsPerLitre;
                        contents += "\n\n" + Lang.Get("Will turn into {0} litres of {1} after {2} of sealing.", litres, incontainername, timeText);
                    }
                    else
                    {
                        contents += "\n\n" + Lang.Get("Will turn into {0}x {1} after {2} of sealing.", bebarrel.CurrentOutSize, outStack.GetName(), timeText);
                    }
                }
            }

            return(contents);
        }
예제 #6
0
        /// <summary>
        /// Fill level in litres. From 0...BucketCapacity. From a placed bucket block
        /// </summary>
        /// <param name="world"></param>
        /// <param name="bucketStack"></param>
        /// <returns></returns>
        public float GetCurrentLitres(IWorldAccessor world, BlockPos pos)
        {
            WaterTightContainableProps props = GetContentProps(world, pos);

            if (props == null)
            {
                return(0);
            }

            return(GetContent(world, pos).StackSize / props.ItemsPerLitre);
        }
예제 #7
0
        /// <summary>
        /// Fill level in litres. From 0...BucketCapacity
        /// </summary>
        /// <param name="world"></param>
        /// <param name="bucketStack"></param>
        /// <returns></returns>
        public float GetCurrentLitres(IWorldAccessor world, ItemStack bucketStack)
        {
            WaterTightContainableProps props = GetContentProps(world, bucketStack);

            if (props == null)
            {
                return(0);
            }

            return(GetContent(world, bucketStack).StackSize / props.ItemsPerLitre);
        }
예제 #8
0
        protected MeshData getContentMesh(ItemStack stack, BlockPos forBlockPos, string shapefilename)
        {
            ICoreClientAPI capi = api as ICoreClientAPI;

            WaterTightContainableProps props = GetContainableProps(stack);
            ITexPositionSource         contentSource;
            float fillHeight;

            if (props != null)
            {
                contentSource = new ContainerTextureSource(capi, stack, props.Texture);
                fillHeight    = GameMath.Min(1f, stack.StackSize / props.ItemsPerLitre / Math.Max(50, props.MaxStackSize)) * 10f / 16f;

                if (props.Texture == null)
                {
                    return(null);
                }
            }
            else
            {
                contentSource = getContentTexture(capi, stack, out fillHeight);
            }


            if (stack != null && contentSource != null)
            {
                Shape    shape = capi.Assets.TryGet("shapes/block/wood/barrel/" + shapefilename).ToObject <Shape>();
                MeshData contentMesh;
                capi.Tesselator.TesselateShape("barrel", shape, out contentMesh, contentSource, new Vec3f(Shape.rotateX, Shape.rotateY, Shape.rotateZ));

                contentMesh.Translate(0, fillHeight, 0);

                if (props?.ClimateColorMap != null)
                {
                    int col = capi.World.ApplyColorMapOnRgba(props.ClimateColorMap, null, ColorUtil.WhiteArgb, 196, 128, false);
                    if (forBlockPos != null)
                    {
                        col = capi.World.ApplyColorMapOnRgba(props.ClimateColorMap, null, ColorUtil.WhiteArgb, forBlockPos.X, forBlockPos.Y, forBlockPos.Z, false);
                    }

                    byte[] rgba = ColorUtil.ToBGRABytes(col);

                    for (int i = 0; i < contentMesh.Rgba.Length; i++)
                    {
                        contentMesh.Rgba[i] = (byte)((contentMesh.Rgba[i] * rgba[i % 4]) / 255);
                    }
                }


                return(contentMesh);
            }

            return(null);
        }
예제 #9
0
        /// <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));
            }
        }
예제 #10
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);
        }
        public override void OnGroundIdle(EntityItem entityItem)
        {
            entityItem.Die(EnumDespawnReason.Removed);

            if (entityItem.World.Side == EnumAppSide.Server)
            {
                WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(entityItem.Itemstack);
                float litres = (float)entityItem.Itemstack.StackSize / props.ItemsPerLitre;

                entityItem.World.SpawnCubeParticles(entityItem.SidedPos.XYZ, entityItem.Itemstack, 0.75f, (int)(litres * 2), 0.45f);
                entityItem.World.PlaySoundAt(new AssetLocation("sounds/environment/smallsplash"), (float)entityItem.SidedPos.X, (float)entityItem.SidedPos.Y, (float)entityItem.SidedPos.Z, null);
            }


            base.OnGroundIdle(entityItem);
        }
예제 #12
0
        /// <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));
            }
        }
예제 #13
0
        public override void OnHeldInteractStart(ItemSlot itemslot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handHandling)
        {
            if (blockSel == null || byEntity.Controls.Sneak)
            {
                base.OnHeldInteractStart(itemslot, byEntity, blockSel, entitySel, firstEvent, ref handHandling);
                return;
            }

            IPlayer byPlayer = (byEntity as EntityPlayer)?.Player;

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

            Block targetedBlock = byEntity.World.BlockAccessor.GetBlock(blockSel.Position);

            if (!byEntity.World.Claims.TryAccess(byPlayer, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak))
            {
                byEntity.World.BlockAccessor.MarkBlockDirty(blockSel.Position.AddCopy(blockSel.Face));
                byPlayer?.InventoryManager.ActiveHotbarSlot?.MarkDirty();
                return;
            }

            if (!TryFillFromBlock(itemslot, byEntity, blockSel.Position))
            {
                BlockBucket targetBucket = targetedBlock as BlockBucket;
                if (targetBucket != null)
                {
                    WaterTightContainableProps props = GetContentProps(byEntity.World, itemslot.Itemstack);

                    if (targetBucket.TryPutContent(byEntity.World, blockSel.Position, contentStack, 1) > 0)
                    {
                        TryTakeContent(byEntity.World, itemslot.Itemstack, 1);
                        byEntity.World.PlaySoundAt(props.FillSpillSound, blockSel.Position.X, blockSel.Position.Y, blockSel.Position.Z, byPlayer);
                    }
                }
                else
                {
                    if (byEntity.Controls.Sprint)
                    {
                        SpillContents(itemslot, byEntity, blockSel);
                    }
                }
            }

            // Prevent placing on normal use
            handHandling = EnumHandHandling.PreventDefaultAction;
        }
예제 #14
0
        public MeshData GenMesh(ICoreClientAPI capi, ItemStack contentStack, BlockPos forBlockPos = null)
        {
            Shape    shape = capi.Assets.TryGet("shapes/block/wood/bucket/empty.json").ToObject <Shape>();
            MeshData bucketmesh;

            capi.Tesselator.TesselateShape(this, shape, out bucketmesh);

            if (contentStack != null)
            {
                WaterTightContainableProps props = GetStackProps(contentStack);
                Block contentBlock = capi.World.GetBlock(props.BlockTextureSource);
                if (contentBlock == null)
                {
                    return(bucketmesh);
                }

                BucketTextureSource contentSource = new BucketTextureSource(capi, contentStack, contentBlock);
                shape = capi.Assets.TryGet("shapes/block/wood/bucket/contents.json").ToObject <Shape>();
                MeshData contentMesh;
                capi.Tesselator.TesselateShape("bucket", shape, out contentMesh, contentSource, new Vec3f(Shape.rotateX, Shape.rotateY, Shape.rotateZ));


                contentMesh.Translate(0, GameMath.Min(7 / 16f, contentStack.StackSize / props.ItemsPerLitre * 0.7f / 16f), 0);

                if (contentBlock.TintIndex > 0)
                {
                    int col = capi.ApplyColorTintOnRgba(contentBlock.TintIndex, ColorUtil.WhiteArgb, 196, 128, false);
                    if (forBlockPos != null)
                    {
                        col = capi.ApplyColorTintOnRgba(contentBlock.TintIndex, ColorUtil.WhiteArgb, forBlockPos.X, forBlockPos.Y, forBlockPos.Z, false);
                    }

                    byte[] rgba = ColorUtil.ToBGRABytes(col);

                    for (int i = 0; i < contentMesh.Rgba.Length; i++)
                    {
                        contentMesh.Rgba[i] = (byte)((contentMesh.Rgba[i] * rgba[i % 4]) / 255);
                    }
                }

                bucketmesh.AddMeshData(contentMesh);
            }

            return(bucketmesh);
        }
예제 #15
0
        public override bool CanTakeFrom(ItemSlot sourceSlot, EnumMergePriority priority = EnumMergePriority.AutoMerge)
        {
            if (inventory?.PutLocked == true)
            {
                return(false);
            }

            ItemStack sourceStack = sourceSlot.Itemstack;

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

            WaterTightContainableProps props = BlockLiquidContainerBase.GetInContainerProps(sourceStack);

            return(props != null && (itemstack == null || itemstack.Collectible.GetMergableQuantity(itemstack, sourceStack, priority) > 0) && RemainingSlotSpace > 0);
        }
예제 #16
0
        private void fullnessMeterDraw(Context ctx, ImageSurface surface, ElementBounds currentBounds)
        {
            ItemSlot liquidSlot = Inventory[1];

            if (liquidSlot.Empty)
            {
                return;
            }

            BlockEntityBarrel bebarrel      = capi.World.BlockAccessor.GetBlockEntity(BlockEntityPosition) as BlockEntityBarrel;
            float             itemsPerLitre = 1f;
            int capacity = bebarrel.CapacityLitres;

            WaterTightContainableProps props = BlockLiquidContainerBase.GetInContainerProps(liquidSlot.Itemstack);

            if (props != null)
            {
                itemsPerLitre = props.ItemsPerLitre;
                capacity      = Math.Max(capacity, props.MaxStackSize);
            }

            float fullnessRelative = liquidSlot.StackSize / itemsPerLitre / capacity;

            double offY = (1 - fullnessRelative) * currentBounds.InnerHeight;

            ctx.Rectangle(0, offY, currentBounds.InnerWidth, currentBounds.InnerHeight - offY);
            //ctx.SetSourceRGBA(ravg/255.0, gavg / 255.0, bavg / 255.0, aavg / 255.0);
            //ctx.Fill();

            CompositeTexture tex = liquidSlot.Itemstack.Collectible.Attributes?["waterTightContainerProps"]?["texture"]?.AsObject <CompositeTexture>(null, liquidSlot.Itemstack.Collectible.Code.Domain);

            if (tex != null)
            {
                ctx.Save();
                Matrix m = ctx.Matrix;
                m.Scale(GuiElement.scaled(3), GuiElement.scaled(3));
                ctx.Matrix = m;

                AssetLocation loc = tex.Base.Clone().WithPathAppendixOnce(".png");
                GuiElement.fillWithPattern(capi, ctx, loc.Path, true, false);

                ctx.Restore();
            }
        }
예제 #17
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));
            }
        }
예제 #18
0
        public void RenderLiquidItemStackGui(ItemSlot inSlot, ItemRenderInfo renderInfo, Matrixf modelMat, double posX, double posY, double posZ, float size, int color, bool rotate = false, bool showStackSize = true)
        {
            ItemStack itemstack = inSlot.Itemstack;

            WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(itemstack);

            capi.Render.RenderMesh(renderInfo.ModelRef);


            if (showStackSize)
            {
                float  litreFloat = (float)itemstack.StackSize / props.ItemsPerLitre;
                string litres;
                if (litreFloat < 0.1)
                {
                    litres = Lang.Get("{0} mL", (int)(litreFloat * 1000));
                }
                else
                {
                    litres = Lang.Get("{0:0.##} L", litreFloat);
                }

                float mul = size / (float)GuiElement.scaled(32 * 0.8f);

                var texttex = GetOrCreateLitreTexture(litres, size, mul);

                capi.Render.GlToggleBlend(true, EnumBlendMode.PremultipliedAlpha);

                capi.Render.Render2DLoadedTexture(texttex,
                                                  (int)(posX + size + 1 - texttex.Width - GuiElement.scaled(1)),
                                                  (int)(posY + size - texttex.Height + mul * GuiElement.scaled(3) - GuiElement.scaled(5)),
                                                  (int)posZ + 60
                                                  );

                capi.Render.GlToggleBlend(true, EnumBlendMode.Standard);
            }
        }
예제 #19
0
        protected MeshData getContentMesh(ItemStack stack, BlockPos forBlockPos, string shapefilename)
        {
            ICoreClientAPI capi = api as ICoreClientAPI;

            WaterTightContainableProps props         = GetStackProps(stack);
            ITexPositionSource         contentSource = null;


            float fillHeight = 0;

            if (props != null)
            {
                contentSource = new ContainerTextureSource(capi, stack, props.Texture);
                fillHeight    = GameMath.Min(10 / 16f, 0.2f * stack.StackSize / props.ItemsPerLitre / 16f);
            }
            else
            {
                JsonObject obj = stack?.ItemAttributes?["inContainerTexture"];
                if (obj != null && obj.Exists)
                {
                    contentSource = new ContainerTextureSource(capi, stack, obj.AsObject <CompositeTexture>());
                    fillHeight    = GameMath.Min(10 / 16f, 0.7f * stack.StackSize / stack.Collectible.MaxStackSize);
                }
                else
                {
                    if (stack?.Block != null && (stack.Block.DrawType == EnumDrawType.Cube || stack.Block.Shape.Base.Path.Contains("basic/cube")))
                    {
                        contentSource = new BlockTopTextureSource(capi, stack.Block);
                        fillHeight    = GameMath.Min(10 / 16f, 0.7f * 1);
                    }
                }
            }

            if (stack != null && contentSource != null)
            {
                Shape    shape = capi.Assets.TryGet("shapes/block/wood/barrel/" + shapefilename).ToObject <Shape>();
                MeshData contentMesh;
                capi.Tesselator.TesselateShape("barrel", shape, out contentMesh, contentSource, new Vec3f(Shape.rotateX, Shape.rotateY, Shape.rotateZ));

                contentMesh.Translate(0, fillHeight, 0);

                if (props != null && props.TintIndex > 0)
                {
                    int col = capi.ApplyColorTintOnRgba(props.TintIndex, ColorUtil.WhiteArgb, 196, 128, false);
                    if (forBlockPos != null)
                    {
                        col = capi.ApplyColorTintOnRgba(props.TintIndex, ColorUtil.WhiteArgb, forBlockPos.X, forBlockPos.Y, forBlockPos.Z, false);
                    }

                    byte[] rgba = ColorUtil.ToBGRABytes(col);

                    for (int i = 0; i < contentMesh.Rgba.Length; i++)
                    {
                        contentMesh.Rgba[i] = (byte)((contentMesh.Rgba[i] * rgba[i % 4]) / 255);
                    }
                }


                return(contentMesh);
            }

            return(null);
        }
예제 #20
0
        public override bool CanHold(ItemSlot itemstackFromSourceSlot)
        {
            WaterTightContainableProps props = BlockLiquidContainerBase.GetInContainerProps(itemstackFromSourceSlot.Itemstack);

            return(props != null);
        }
예제 #21
0
        private bool SpillContents(IItemSlot bucketSlot, IEntityAgent byEntity, BlockSelection blockSel)
        {
            BlockPos       pos       = blockSel.Position;
            IPlayer        byPlayer  = (byEntity as EntityPlayer)?.Player;
            IBlockAccessor blockAcc  = byEntity.World.BlockAccessor;
            BlockPos       secondPos = blockSel.Position.AddCopy(blockSel.Face);


            WaterTightContainableProps props = GetContentProps(byEntity.World, bucketSlot.Itemstack);

            if (props == null || !props.AllowSpill || props.WhenSpilled == null)
            {
                return(false);
            }

            if (props.WhenSpilled.Action == WaterTightContainableProps.EnumSpilledAction.PlaceBlock)
            {
                Block waterBlock = byEntity.World.GetBlock(props.WhenSpilled.Stack.Code);

                if (props.WhenSpilled.StackByFillLevel != null)
                {
                    float         currentlitres  = GetCurrentLitres(byEntity.World, bucketSlot.Itemstack);
                    JsonItemStack fillLevelStack = null;
                    props.WhenSpilled.StackByFillLevel.TryGetValue((int)currentlitres, out fillLevelStack);
                    if (fillLevelStack != null)
                    {
                        waterBlock = byEntity.World.GetBlock(fillLevelStack.Code);
                    }
                }

                if (blockAcc.GetBlock(pos).Replaceable >= 6000)
                {
                    blockAcc.SetBlock(waterBlock.BlockId, pos);
                    blockAcc.MarkBlockDirty(pos);
                }
                else
                {
                    if (blockAcc.GetBlock(secondPos).Replaceable >= 6000)
                    {
                        blockAcc.SetBlock(waterBlock.BlockId, secondPos);
                        blockAcc.MarkBlockDirty(secondPos);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (props.WhenSpilled.Action == WaterTightContainableProps.EnumSpilledAction.DropContents)
            {
                props.WhenSpilled.Stack.Resolve(byEntity.World, "bucketspill");

                ItemStack stack = props.WhenSpilled.Stack.ResolvedItemstack.Clone();
                stack.StackSize = (int)(props.ItemsPerLitre * GetContent(byEntity.World, bucketSlot.Itemstack).StackSize);

                byEntity.World.SpawnItemEntity(stack, blockSel.Position.ToVec3d().Add(blockSel.HitPosition));
            }


            ItemStack emptyBucketStack = new ItemStack(this);

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

            byEntity.World.PlaySoundAt(props.FillSpillSound, pos.X, pos.Y, pos.Z, byPlayer);
            return(true);
        }
예제 #22
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);
        }