/// <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); }
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; }
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)); } }
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); }
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); } }
/// <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); }
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); } }
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); } }
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); }
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); } }
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); }
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); }
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(); } }
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; }