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); }
public override float GetMeltingDuration(IWorldAccessor world, ISlotProvider cookingSlotsProvider, ItemSlot inputSlot) { float duration = 0; ItemStack[] stacks = GetCookingStacks(cookingSlotsProvider, false); for (int i = 0; i < stacks.Length; i++) { var stack = stacks[i]; int portionSize = stack.StackSize; if (stack.Collectible?.CombustibleProps == null) { if (stack.Collectible.Attributes?["waterTightContainerProps"].Exists == true) { var props = BlockLiquidContainerBase.GetContainableProps(stack); portionSize = (int)(stack.StackSize / props.ItemsPerLitre); } duration += 20 * portionSize; continue; } float singleDuration = stack.Collectible.GetMeltingDuration(world, cookingSlotsProvider, inputSlot); duration += singleDuration * portionSize / stack.Collectible.CombustibleProps.SmeltedRatio; } duration = Math.Max(40, duration / 3); return(duration); }
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); }
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handHandling) { if (blockSel != null) { BlockEntityBarrel beba = api.World.BlockAccessor.GetBlockEntity(blockSel.Position) as BlockEntityBarrel; var liqslot = beba?.Inventory[1]; if (beba != null && !liqslot.Empty) { if (liqslot.Itemstack.Item?.Code?.Path == "cottagecheeseportion") { var props = BlockLiquidContainerBase.GetContainableProps(liqslot.Itemstack); float curLitres = liqslot.Itemstack.StackSize / props.ItemsPerLitre; if (curLitres < 25) { (api as ICoreClientAPI)?.TriggerIngameError(this, "notenough", Lang.Get("Need at least 25 litres to create a roll of cheese")); handHandling = EnumHandHandling.PreventDefault; return; } if (api.World.Side == EnumAppSide.Server) { ItemStack ccStack = beba.Inventory[1].TakeOut((int)(25 * props.ItemsPerLitre)); BlockCheeseCurdsBundle block = api.World.GetBlock(new AssetLocation("curdbundle")) as BlockCheeseCurdsBundle; ItemStack bundleStack = new ItemStack(block); block.SetContents(bundleStack, ccStack); slot.TakeOut(1); slot.MarkDirty(); beba.MarkDirty(true); if (!byEntity.TryGiveItemStack(bundleStack)) { api.World.SpawnItemEntity(bundleStack, byEntity.Pos.XYZ.AddCopy(0, 0.5, 0)); } } handHandling = EnumHandHandling.PreventDefault; return; } } } base.OnHeldInteractStart(slot, byEntity, blockSel, entitySel, firstEvent, ref handHandling); }
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); }
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.GetContainableProps(sourceStack); return(props != null && (itemstack == null || itemstack.Collectible.GetMergableQuantity(itemstack, sourceStack, priority) > 0) && GetRemainingSlotSpace(sourceStack) > 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.GetContainableProps(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); CompositeTexture tex = props?.Texture ?? liquidSlot.Itemstack.Collectible.Attributes?["inContainerTexture"].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, true, false, tex.Alpha); ctx.Restore(); } }
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); } }
public bool Resolve(IWorldAccessor world, string sourceForErrorLogging) { bool ok = true; for (int i = 0; i < Ingredients.Length; i++) { var ingred = Ingredients[i]; bool iOk = ingred.Resolve(world, sourceForErrorLogging); ok &= iOk; if (iOk) { var lprops = BlockLiquidContainerBase.GetContainableProps(ingred.ResolvedItemstack); if (lprops != null) { if (ingred.Litres < 0) { if (ingred.Quantity > 0) { world.Logger.Warning("Barrel recipe {0}, ingredient {1} does not define a litres attribute but a quantity, will assume quantity=litres for backwards compatibility.", sourceForErrorLogging, ingred.Code); ingred.Litres = ingred.Quantity; ingred.ConsumeLitres = ingred.ConsumeQuantity; } else { ingred.Litres = 1; } } ingred.Quantity = (int)(lprops.ItemsPerLitre * ingred.Litres); if (ingred.ConsumeLitres != null) { ingred.ConsumeQuantity = (int)(lprops.ItemsPerLitre * ingred.ConsumeLitres); } } } } ok &= Output.Resolve(world, sourceForErrorLogging); if (ok) { var lprops = BlockLiquidContainerBase.GetContainableProps(Output.ResolvedItemstack); if (lprops != null) { if (Output.Litres < 0) { if (Output.Quantity > 0) { world.Logger.Warning("Barrel recipe {0}, output {1} does not define a litres attribute but a stacksize, will assume stacksize=litres for backwards compatibility.", sourceForErrorLogging, Output.Code); Output.Litres = Output.Quantity; } else { Output.Litres = 1; } } Output.Quantity = (int)(lprops.ItemsPerLitre * Output.Litres); } } return(ok); }
public bool Matches(ItemStack[] inputStacks, ref int quantityServings) { List <ItemStack> inputStacksList = new List <ItemStack>(inputStacks); List <CookingRecipeIngredient> ingredientList = new List <CookingRecipeIngredient>(Ingredients); int totalOutputQuantity = 99999; int[] curQuantities = new int[ingredientList.Count]; for (int i = 0; i < curQuantities.Length; i++) { curQuantities[i] = 0; } while (inputStacksList.Count > 0) { ItemStack inputStack = inputStacksList[0]; inputStacksList.RemoveAt(0); if (inputStack == null) { continue; } bool found = false; for (int i = 0; i < ingredientList.Count; i++) { CookingRecipeIngredient ingred = ingredientList[i]; if (ingred.Matches(inputStack)) { if (curQuantities[i] >= ingred.MaxQuantity) { continue; } totalOutputQuantity = Math.Min(totalOutputQuantity, inputStack.StackSize); curQuantities[i]++; found = true; break; } } // This input stack does not fit in this cooking recipe if (!found) { return(false); } } // Any required ingredients left? for (int i = 0; i < ingredientList.Count; i++) { if (curQuantities[i] < ingredientList[i].MinQuantity) { return(false); } } quantityServings = totalOutputQuantity; // Too many ingredients? for (int i = 0; i < inputStacks.Length; i++) { var stack = inputStacks[i]; if (stack == null) { continue; } int qportions = stack.StackSize; if (stack.Collectible.Attributes?["waterTightContainerProps"].Exists == true) { var props = BlockLiquidContainerBase.GetContainableProps(stack); qportions = (int)(stack.StackSize / props.ItemsPerLitre / GetIngrendientFor(stack).PortionSizeLitres); } if (qportions != quantityServings) { return(false); } } return(true); }
protected override void ActivateSlotLeftClick(ItemSlot sourceSlot, ref ItemStackMoveOperation op) { IWorldAccessor world = inventory.Api.World; BlockLiquidContainerBase liqCntBlock = sourceSlot.Itemstack?.Block as BlockLiquidContainerBase; if (liqCntBlock != null) { ItemStack contentStack = liqCntBlock.GetContent(sourceSlot.Itemstack); var liqProps = BlockLiquidContainerBase.GetContainableProps(contentStack); bool stackable = !Empty && itemstack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes); if ((Empty || stackable) && contentStack != null) { ItemStack bucketStack = sourceSlot.Itemstack; float toMoveLitres = (op?.ActingPlayer?.Entity.Controls.Sneak ?? false) ? liqCntBlock.CapacityLitres : liqCntBlock.TransferSizeLitres; float curDestLitres = StackSize / liqProps.ItemsPerLitre; float curSrcLitres = contentStack.StackSize / liqProps.ItemsPerLitre; toMoveLitres = Math.Min(toMoveLitres, curSrcLitres); toMoveLitres *= bucketStack.StackSize; toMoveLitres = Math.Min(toMoveLitres, capacityLitres - curDestLitres); if (toMoveLitres > 0) { int moveQuantity = (int)(liqProps.ItemsPerLitre * toMoveLitres); ItemStack takenContentStack = liqCntBlock.TryTakeContent(bucketStack, moveQuantity / bucketStack.StackSize); takenContentStack.StackSize *= bucketStack.StackSize; takenContentStack.StackSize += StackSize; this.itemstack = takenContentStack; MarkDirty(); op.MovedQuantity = moveQuantity; } } return; } string contentItemCode = sourceSlot.Itemstack?.ItemAttributes?["contentItemCode"].AsString(); if (contentItemCode != null) { ItemStack contentStack = new ItemStack(world.GetItem(AssetLocation.Create(contentItemCode, sourceSlot.Itemstack.Collectible.Code.Domain))); bool stackable = !Empty && itemstack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes); if ((Empty || stackable) && contentStack != null) { if (stackable) { this.itemstack.StackSize++; } else { this.itemstack = contentStack; } MarkDirty(); ItemStack bowlStack = new ItemStack(world.GetBlock(AssetLocation.Create(sourceSlot.Itemstack.ItemAttributes["emptiedBlockCode"].AsString(), sourceSlot.Itemstack.Collectible.Code.Domain))); if (sourceSlot.StackSize == 1) { sourceSlot.Itemstack = bowlStack; } else { sourceSlot.Itemstack.StackSize--; if (!op.ActingPlayer.InventoryManager.TryGiveItemstack(bowlStack)) { world.SpawnItemEntity(bowlStack, op.ActingPlayer.Entity.Pos.XYZ); } } sourceSlot.MarkDirty(); } return; } if (sourceSlot.Itemstack?.ItemAttributes?["contentItem2BlockCodes"].Exists == true) { return; } base.ActivateSlotLeftClick(sourceSlot, ref op); }
protected override void ActivateSlotRightClick(ItemSlot sourceSlot, ref ItemStackMoveOperation op) { IWorldAccessor world = inventory.Api.World; BlockLiquidContainerBase liqCntBlock = sourceSlot.Itemstack?.Block as BlockLiquidContainerBase; if (liqCntBlock != null) { if (Empty) { return; } ItemStack contentStack = liqCntBlock.GetContent(sourceSlot.Itemstack); float toMoveLitres = op.ShiftDown ? liqCntBlock.CapacityLitres : liqCntBlock.TransferSizeLitres; var srcProps = BlockLiquidContainerBase.GetContainableProps(Itemstack); float availableLitres = StackSize / (srcProps?.ItemsPerLitre ?? 1); toMoveLitres = Math.Min(toMoveLitres, availableLitres); toMoveLitres *= sourceSlot.Itemstack.StackSize; if (contentStack == null) { int moved = liqCntBlock.TryPutLiquid(sourceSlot.Itemstack, Itemstack, toMoveLitres / sourceSlot.Itemstack.StackSize); TakeOut(moved * sourceSlot.Itemstack.StackSize); MarkDirty(); } else { if (itemstack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes)) { int moved = liqCntBlock.TryPutLiquid(sourceSlot.Itemstack, liqCntBlock.GetContent(sourceSlot.Itemstack), toMoveLitres / sourceSlot.Itemstack.StackSize); TakeOut(moved * sourceSlot.Itemstack.StackSize); MarkDirty(); return; } } return; } if (itemstack != null && sourceSlot.Itemstack?.ItemAttributes?["contentItem2BlockCodes"].Exists == true) { string outBlockCode = sourceSlot.Itemstack.ItemAttributes["contentItem2BlockCodes"][itemstack.Collectible.Code.ToShortString()].AsString(); if (outBlockCode != null) { ItemStack outBlockStack = new ItemStack(world.GetBlock(AssetLocation.Create(outBlockCode, sourceSlot.Itemstack.Collectible.Code.Domain))); if (sourceSlot.StackSize == 1) { sourceSlot.Itemstack = outBlockStack; } else { sourceSlot.Itemstack.StackSize--; if (!op.ActingPlayer.InventoryManager.TryGiveItemstack(outBlockStack)) { world.SpawnItemEntity(outBlockStack, op.ActingPlayer.Entity.Pos.XYZ); } } sourceSlot.MarkDirty(); TakeOut(1); } return; } if (sourceSlot.Itemstack?.ItemAttributes?["contentItem2BlockCodes"].Exists == true || sourceSlot.Itemstack?.ItemAttributes?["contentItemCode"].AsString() != null) { return; } base.ActivateSlotRightClick(sourceSlot, ref op); }
public override bool CanHold(ItemSlot itemstackFromSourceSlot) { WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(itemstackFromSourceSlot.Itemstack); return(props != null); }