public override string GetPlacedBlockInfo(IWorldAccessor world, BlockPos pos, IPlayer forPlayer) { string text = ""; float litres = GetCurrentLitres(pos); if (litres <= 0) { text = ""; } BlockEntityCauld becauld = world.BlockAccessor.GetBlockEntity(pos) as BlockEntityCauld; if (becauld != null) { ItemSlot outslot = becauld.Inventory[5]; ItemSlot inslot = becauld.Inventory[6]; if (text.Length > 0) { text += "\n"; } else { text += Lang.Get("Contents:"); } if (inslot.Empty && outslot.Empty) { text += "\nEmpty"; } else { if (!outslot.Empty) { WaterTightContainableProps outprops = BlockLiquidContainerBase.GetContainableProps(outslot.Itemstack); text += "\n" + Lang.Get("Potion out: {0} Litres of {1}", outslot.Itemstack.StackSize / outprops.ItemsPerLitre, outslot.Itemstack.GetName()); } if (!inslot.Empty) { WaterTightContainableProps inprops = BlockLiquidContainerBase.GetContainableProps(inslot.Itemstack); text += "\n" + Lang.Get("Potion in: {0} Litres of {1}", becauld.Inventory[6].Itemstack.StackSize / inprops.ItemsPerLitre, becauld.Inventory[6].Itemstack.GetName()); } if (becauld.isFull) { text += "\nEmpty output to mix new potions"; } } } return(text); }
protected override void ActivateSlotRightClick(ItemSlot sourceSlot, ref ItemStackMoveOperation op) { ItemSlotLiquidOnly liquidSlot = inventory[1] as ItemSlotLiquidOnly; IWorldAccessor world = inventory.Api.World; if (sourceSlot?.Itemstack?.Collectible is ILiquidSink sink && !liquidSlot.Empty && sink.AllowHeldLiquidTransfer) { ItemStack liqSlotStack = liquidSlot.Itemstack; var curTargetLiquidStack = sink.GetContent(sourceSlot.Itemstack); bool liquidstackable = curTargetLiquidStack == null || liqSlotStack.Equals(world, curTargetLiquidStack, GlobalConstants.IgnoredStackAttributes); if (liquidstackable) { var lprops = BlockLiquidContainerBase.GetContainableProps(liqSlotStack); float curSourceLitres = liqSlotStack.StackSize / lprops.ItemsPerLitre; float curTargetLitres = sink.GetCurrentLitres(sourceSlot.Itemstack); float toMoveLitres = op.CtrlDown ? sink.TransferSizeLitres : (sink.CapacityLitres - curTargetLitres); toMoveLitres *= sourceSlot.StackSize; toMoveLitres = Math.Min(curSourceLitres, toMoveLitres); if (toMoveLitres > 0) { op.MovedQuantity = sink.TryPutLiquid(sourceSlot.Itemstack, liqSlotStack, toMoveLitres / sourceSlot.StackSize); liquidSlot.Itemstack.StackSize -= op.MovedQuantity * sourceSlot.StackSize; if (liquidSlot.Itemstack.StackSize <= 0) { liquidSlot.Itemstack = null; } liquidSlot.MarkDirty(); sourceSlot.MarkDirty(); var pos = op.ActingPlayer?.Entity?.Pos; if (pos != null) { op.World.PlaySoundAt(lprops.PourSound, pos.X, pos.Y, pos.Z); } } } return; } base.ActivateSlotRightClick(sourceSlot, ref op); }
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); }
private void fullnessMeterDraw(Context ctx, ImageSurface surface, ElementBounds currentBounds) { ItemSlot liquidSlot = Inventory[6] as ItemSlot; if (liquidSlot.Empty) { return; } BlockEntityCauld becauld = capi.World.BlockAccessor.GetBlockEntity(BlockEntityPosition) as BlockEntityCauld; float itemsPerLitre = 1f; int capacity = becauld.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 override void OnItemSlotModified(ItemStack stack) { base.OnItemSlotModified(stack); if (itemstack == null) { return; } ItemSlotLiquidOnly liquidSlot = inventory[1] as ItemSlotLiquidOnly; bool stackable = !liquidSlot.Empty && liquidSlot.Itemstack.Equals(inventory.Api.World, itemstack, GlobalConstants.IgnoredStackAttributes); if (stackable) { int remaining = liquidSlot.Itemstack.Collectible.MaxStackSize - liquidSlot.Itemstack.StackSize; WaterTightContainableProps props = BlockLiquidContainerBase.GetContainableProps(liquidSlot.Itemstack); if (props != null) { int max = (int)(liquidSlot.CapacityLitres * props.ItemsPerLitre); int maxOverride = props.MaxStackSize; // allows 64 rot to be placed in barrel remaining = Math.Max(max, maxOverride) - liquidSlot.Itemstack.StackSize; } int moved = GameMath.Clamp(itemstack.StackSize, 0, remaining); liquidSlot.Itemstack.StackSize += moved; itemstack.StackSize -= moved; if (itemstack.StackSize <= 0) { itemstack = null; } liquidSlot.MarkDirty(); MarkDirty(); return; } if (itemstack.Collectible.Attributes?.IsTrue("barrelMoveToLiquidSlot") == true || itemstack.Collectible.Attributes?["waterTightContainerProps"].Exists == true) { if (stackable) { int remainingspace = itemstack.Collectible.MaxStackSize - liquidSlot.StackSize; int movableq = Math.Min(itemstack.StackSize, remainingspace); liquidSlot.Itemstack.StackSize += movableq; this.itemstack.StackSize -= movableq; if (StackSize <= 0) { itemstack = null; } MarkDirty(); liquidSlot.MarkDirty(); return; } if (liquidSlot.Empty) { liquidSlot.Itemstack = this.itemstack.Clone(); this.itemstack = null; MarkDirty(); liquidSlot.MarkDirty(); } } return; }
protected override void ActivateSlotLeftClick(ItemSlot sourceSlot, ref ItemStackMoveOperation op) { if (sourceSlot.Empty) { base.ActivateSlotLeftClick(sourceSlot, ref op); return; } IWorldAccessor world = inventory.Api.World; if (sourceSlot.Itemstack.Collectible is ILiquidSource source && source.AllowHeldLiquidTransfer) { ItemSlotLiquidOnly liquidSlot = inventory[1] as ItemSlotLiquidOnly; ItemStack bucketContents = source.GetContent(sourceSlot.Itemstack); bool stackable = !liquidSlot.Empty && liquidSlot.Itemstack.Equals(world, bucketContents, GlobalConstants.IgnoredStackAttributes); if ((liquidSlot.Empty || stackable) && bucketContents != null) { ItemStack bucketStack = sourceSlot.Itemstack; var lprops = BlockLiquidContainerBase.GetContainableProps(bucketContents); float toMoveLitres = op.CtrlDown ? source.TransferSizeLitres : source.CapacityLitres; float curSourceLitres = bucketContents.StackSize / lprops.ItemsPerLitre * bucketStack.StackSize; float curDestLitres = liquidSlot.StackSize / lprops.ItemsPerLitre; // Cap by source amount toMoveLitres = Math.Min(toMoveLitres, curSourceLitres); // Cap by target capacity toMoveLitres = Math.Min(toMoveLitres, liquidSlot.CapacityLitres - curDestLitres); if (toMoveLitres > 0) { int moveQuantity = (int)(toMoveLitres * lprops.ItemsPerLitre); ItemStack takenContentStack = source.TryTakeContent(bucketStack, moveQuantity / bucketStack.StackSize); takenContentStack.StackSize *= bucketStack.StackSize; takenContentStack.StackSize += liquidSlot.StackSize; liquidSlot.Itemstack = takenContentStack; liquidSlot.MarkDirty(); op.MovedQuantity = moveQuantity; var pos = op.ActingPlayer?.Entity?.Pos; if (pos != null) { op.World.PlaySoundAt(lprops.FillSound, pos.X, pos.Y, pos.Z); } } return; } return; } string contentItemCode = sourceSlot.Itemstack?.ItemAttributes?["contentItemCode"].AsString(); if (contentItemCode != null) { ItemSlot liquidSlot = inventory[1]; ItemStack contentStack = new ItemStack(world.GetItem(new AssetLocation(contentItemCode))); bool stackable = !liquidSlot.Empty && liquidSlot.Itemstack.Equals(world, contentStack, GlobalConstants.IgnoredStackAttributes); if ((liquidSlot.Empty || stackable) && contentStack != null) { if (stackable) { liquidSlot.Itemstack.StackSize++; } else { liquidSlot.Itemstack = contentStack; } liquidSlot.MarkDirty(); ItemStack bowlStack = new ItemStack(world.GetBlock(new AssetLocation(sourceSlot.Itemstack.ItemAttributes["emptiedBlockCode"].AsString()))); 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; } base.ActivateSlotLeftClick(sourceSlot, ref op); }
string getContentsText() { string contents = "Contents:"; if (Inventory[0].Empty && Inventory[1].Empty && Inventory[2].Empty && Inventory[3].Empty && Inventory[4].Empty && Inventory[5].Empty && Inventory[6].Empty) { contents += "\nNone."; } else { BlockEntityCauld becauld = capi.World.BlockAccessor.GetBlockEntity(BlockEntityPosition) as BlockEntityCauld; if (!Inventory[6].Empty) { ItemStack stack = Inventory[6].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 ? "Potion in: {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[5].Empty) { ItemStack stack = Inventory[5].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 ? "Potion out: {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()); } } Dictionary <string, float> essencesDic = new Dictionary <string, float>(); Dictionary <string, float> maxEssenceDic = new Dictionary <string, float>(); try { IAsset maxEssences = capi.Assets.TryGet("alchemy:config/essences.json"); if (maxEssences != null) { maxEssenceDic = maxEssences.ToObject <Dictionary <string, float> >(); } } catch (Exception e) { capi.World.Logger.Error("Failed loading potion effects for potion {0}. Will ignore. Exception: {1}", e); } for (int i = 0; i < 5; i++) { if (!Inventory[i].Empty) { JsonObject essences = Inventory[i].Itemstack.ItemAttributes?["potionessences"]; foreach (var essence in maxEssenceDic.Keys.ToList()) { if (essences[essence].Exists) { if (!essencesDic.ContainsKey(essence)) { essencesDic.Add(essence, 0); } essencesDic[essence] = (essencesDic[essence] + essences[essence].AsFloat() < maxEssenceDic[essence]) ? essencesDic[essence] += essences[essence].AsFloat() : maxEssenceDic[essence]; if (essencesDic[essence] == 0.0f) { essencesDic.Remove(essence); } } } } } foreach (var essence in essencesDic.Keys.ToList()) { if (essence == "duration") { contents += "\n" + Lang.Get("increased duration by {0}", essencesDic[essence]); } else { contents += "\n" + Lang.Get("{0} units of {1} essence", essencesDic[essence], essence); } } if (!Inventory[5].Empty) { contents += "\n\nEmpty output to mix different new potions"; } } return(contents); }
//Is there such thing as minimum litre amount? Can I dynamcally change colour and can I have a ghost item? public void MixCauld() { if (!inventory[6].Empty) { if (inventory[6].Itemstack.StackSize < 8) { return; } float strongEffect; if (inventory[6].Itemstack.MatchesSearchText(Api.World, "Potion tea")) { strongEffect = 1; } else if (inventory[6].Itemstack.MatchesSearchText(Api.World, "Aqua Vitae")) { strongEffect = 2; } else { return; } int canMix = 0; int isEmpty = 0; Dictionary <string, float> essencesDic = new Dictionary <string, float>(); for (int i = 0; i < 5; i++) { if (!inventory[i].Empty) { JsonObject essences = inventory[i].Itemstack.ItemAttributes?["potionessences"]; //Api.Logger.Debug("{0}, {1}", inventory[i].Itemstack.Item.Code.ToShortString(), inventory[i].Itemstack.ItemAttributes.ToString()); if (inventory[i].Itemstack.ItemAttributes["potionessences"].KeyExists(inventory[i].Itemstack.Collectible.Code.ToShortString())) { essences = inventory[i].Itemstack.ItemAttributes?["potionessences"][inventory[i].Itemstack.Collectible.Code.ToShortString()]; } bool hasEss = false; foreach (var essence in maxEssenceDic.Keys.ToList()) { if (essences[essence].Exists) { if (!essencesDic.ContainsKey(essence)) { essencesDic.Add(essence, 0); } essencesDic[essence] = (essencesDic[essence] + essences[essence].AsFloat() < maxEssenceDic[essence]) ? essencesDic[essence] += essences[essence].AsFloat() : maxEssenceDic[essence]; if (essencesDic[essence] == 0.0f) { essencesDic.Remove(essence); } hasEss = true; } } if (hasEss) { canMix += 1; } } else { isEmpty += 1; } } JsonObject baseEssences = inventory[6].Itemstack.ItemAttributes?["potionessences"]; foreach (var essence in maxEssenceDic.Keys.ToList()) { if (baseEssences[essence].Exists) { if (!essencesDic.ContainsKey(essence)) { essencesDic.Add(essence, 0); } essencesDic[essence] = (essencesDic[essence] + baseEssences[essence].AsFloat() < maxEssenceDic[essence]) ? essencesDic[essence] += baseEssences[essence].AsFloat() : maxEssenceDic[essence]; if (essencesDic[essence] == 0.0f) { essencesDic.Remove(essence); } } } canMix += isEmpty; if (canMix >= 5 && isEmpty < 5) { if (!inventory[5].Empty) { ITreeAttribute outputEssences = Inventory[5].Itemstack.Attributes; foreach (var essence in maxEssenceDic.Keys.ToList()) { if (outputEssences.TryGetFloat("potion" + essence) != null) { if (!essencesDic.TryGetValue(essence, out float value)) { return; } else if (!(Math.Abs(essencesDic[essence] - outputEssences.GetFloat("potion" + essence)) < 1e-7)) { return; } } else if (essencesDic.TryGetValue(essence, out float value)) { return; } } } for (int i = 0; i <= 4; i++) { if (!inventory[i].Empty) { if (inventory[i].Itemstack.Collectible.IsLiquid()) { var srcProps = BlockLiquidContainerBase.GetContainableProps(inventory[0].Itemstack); int liquid = (int)(inventory[0].Itemstack.StackSize / srcProps?.ItemsPerLitre) * 25; inventory[i].TakeOut(liquid); } else { inventory[i].TakeOut(1); } } } //investigate litres change in ItemSlotWaterTight.cs and ItemsPerLitre inventory[6].TakeOut(8); if (inventory[5].Empty) { inventory[5].Itemstack = new ItemStack(Api.World.GetItem(new AssetLocation("alchemy:potionportion")), 8); foreach (var essence in maxEssenceDic.Keys.ToList()) { float value; if (essencesDic.TryGetValue(essence, out value)) { inventory[5].Itemstack.Attributes.SetFloat("potion" + essence, (float)Math.Round(value * strongEffect, 2)); } } } else { inventory[5].Itemstack.StackSize += 8; } if (Api?.Side == EnumAppSide.Server) { MarkDirty(true); Api.World.BlockAccessor.MarkBlockEntityDirty(Pos); } invDialog?.UpdateContents(); if (Api?.Side == EnumAppSide.Client) { currentMesh = GenMesh(); MarkDirty(true); } return; } } }