mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +00:00 
			
		
		
		
	Make upgrade recipe requirements a little more lax
- Move some common upgrade code to IUpgradeBase. 99% sure this this preserves binary compatibility (on the JVM at least). - Instead of requiring the share tag to match, allow upgrades to specify their own predicate. IMO this is a little ugly, but required to fix #614 as other mods chuck their own NBT on items.
This commit is contained in:
		
							
								
								
									
										81
									
								
								src/main/java/dan200/computercraft/api/IUpgradeBase.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/main/java/dan200/computercraft/api/IUpgradeBase.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | package dan200.computercraft.api; | ||||||
|  |  | ||||||
|  | import dan200.computercraft.api.pocket.IPocketUpgrade; | ||||||
|  | import dan200.computercraft.api.turtle.ITurtleUpgrade; | ||||||
|  | import net.minecraft.item.ItemStack; | ||||||
|  | import net.minecraft.nbt.CompoundTag; | ||||||
|  | import net.minecraft.util.Identifier; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Common functionality between {@link ITurtleUpgrade} and {@link IPocketUpgrade}. | ||||||
|  |  */ | ||||||
|  | public interface IUpgradeBase | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" | ||||||
|  |      * or "my_mod:my_upgrade". | ||||||
|  |      * | ||||||
|  |      * You should use a unique resource domain to ensure this upgrade is uniquely identified. | ||||||
|  |      * The upgrade will fail registration if an already used ID is specified. | ||||||
|  |      * | ||||||
|  |      * @return The unique ID for this upgrade. | ||||||
|  |      */ | ||||||
|  |     @Nonnull | ||||||
|  |     Identifier getUpgradeID(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Return an unlocalised string to describe this type of computer in item names. | ||||||
|  |      * | ||||||
|  |      * Examples of built-in adjectives are "Wireless", "Mining" and "Crafty". | ||||||
|  |      * | ||||||
|  |      * @return The localisation key for this upgrade's adjective. | ||||||
|  |      */ | ||||||
|  |     @Nonnull | ||||||
|  |     String getUnlocalisedAdjective(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Return an item stack representing the type of item that a computer must be crafted | ||||||
|  |      * with to create a version which holds this upgrade. This item stack is also used | ||||||
|  |      * to determine the upgrade given by {@code turtle.equipLeft()} or {@code pocket.equipBack()} | ||||||
|  |      * | ||||||
|  |      * This should be constant over a session (or at least a datapack reload). It is recommended | ||||||
|  |      * that you cache the stack too, in order to prevent constructing it every time the method | ||||||
|  |      * is called. | ||||||
|  |      * | ||||||
|  |      * @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted. | ||||||
|  |      */ | ||||||
|  |     @Nonnull | ||||||
|  |     ItemStack getCraftingItem(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Determine if an item is suitable for being used for this upgrade. | ||||||
|  |      * | ||||||
|  |      * When un-equipping an upgrade, we return {@link #getCraftingItem()} rather than | ||||||
|  |      * the original stack. In order to prevent people losing items with enchantments (or | ||||||
|  |      * repairing items with non-0 damage), we impose additional checks on the item. | ||||||
|  |      * | ||||||
|  |      * The default check requires that any non-capability NBT is exactly the same as the | ||||||
|  |      * crafting item, but this may be relaxed for your upgrade. | ||||||
|  |      * | ||||||
|  |      * @param stack The stack to check. This is guaranteed to be non-empty and have the same item as | ||||||
|  |      *              {@link #getCraftingItem()}. | ||||||
|  |      * @return If this stack may be used to equip this upgrade. | ||||||
|  |      * @see net.minecraftforge.common.crafting.NBTIngredient#test(ItemStack) For the implementation of the default | ||||||
|  |      * check. | ||||||
|  |      */ | ||||||
|  |     default boolean isItemSuitable( @Nonnull ItemStack stack ) | ||||||
|  |     { | ||||||
|  |         ItemStack crafting = getCraftingItem(); | ||||||
|  |  | ||||||
|  |         // A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a | ||||||
|  |         // null one. | ||||||
|  |         CompoundTag shareTag = stack.getTag(); | ||||||
|  |         CompoundTag craftingShareTag = crafting.getTag(); | ||||||
|  |         if( shareTag == craftingShareTag ) return true; | ||||||
|  |         if( shareTag == null ) return craftingShareTag.isEmpty(); | ||||||
|  |         if( craftingShareTag == null ) return shareTag.isEmpty(); | ||||||
|  |         return shareTag.equals( craftingShareTag ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -10,56 +10,18 @@ import javax.annotation.Nonnull; | |||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
| import dan200.computercraft.api.ComputerCraftAPI; | import dan200.computercraft.api.ComputerCraftAPI; | ||||||
|  | import dan200.computercraft.api.IUpgradeBase; | ||||||
| import dan200.computercraft.api.peripheral.IPeripheral; | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
| import dan200.computercraft.api.turtle.ITurtleUpgrade; |  | ||||||
|  |  | ||||||
| import net.minecraft.item.ItemStack; |  | ||||||
| import net.minecraft.util.Identifier; |  | ||||||
| import net.minecraft.world.World; | import net.minecraft.world.World; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Additional peripherals for pocket computers. |  * Additional peripherals for pocket computers. | ||||||
|  * |  * | ||||||
|  * This is similar to {@link ITurtleUpgrade}. |  | ||||||
|  */ |  | ||||||
| public interface IPocketUpgrade { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or "my_mod:my_upgrade". |  | ||||||
|      * |  | ||||||
|      * You should use a unique resource domain to ensure this upgrade is uniquely identified. The upgrade will fail registration if an already used ID is |  | ||||||
|      * specified. |  | ||||||
|      * |  | ||||||
|      * @return The upgrade's id. |  | ||||||
|      * @see IPocketUpgrade#getUpgradeID() |  | ||||||
|  * @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade) |  * @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade) | ||||||
|  */ |  */ | ||||||
|     @Nonnull | public interface IPocketUpgrade extends IUpgradeBase | ||||||
|     Identifier getUpgradeID(); | { | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Return an unlocalised string to describe the type of pocket computer this upgrade provides. |  | ||||||
|      * |  | ||||||
|      * An example of a built-in adjectives is "Wireless" - this is converted to "Wireless Pocket Computer". |  | ||||||
|      * |  | ||||||
|      * @return The unlocalised adjective. |  | ||||||
|      * @see ITurtleUpgrade#getUnlocalisedAdjective() |  | ||||||
|      */ |  | ||||||
|     @Nonnull |  | ||||||
|     String getUnlocalisedAdjective(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Return an item stack representing the type of item that a pocket computer must be crafted with to create a pocket computer which holds this upgrade. |  | ||||||
|      * This item stack is also used to determine the upgrade given by {@code pocket.equip()}/{@code pocket.unequip()}. |  | ||||||
|      * |  | ||||||
|      * Ideally this should be constant over a session. It is recommended that you cache the item too, in order to prevent constructing it every time the |  | ||||||
|      * method is called. |  | ||||||
|      * |  | ||||||
|      * @return The item stack used for crafting. This can be {@link ItemStack#EMPTY} if crafting is disabled. |  | ||||||
|      */ |  | ||||||
|     @Nonnull |  | ||||||
|     ItemStack getCraftingItem(); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Creates a peripheral for the pocket computer. |      * Creates a peripheral for the pocket computer. | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -10,11 +10,10 @@ import javax.annotation.Nonnull; | |||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
| import dan200.computercraft.api.ComputerCraftAPI; | import dan200.computercraft.api.ComputerCraftAPI; | ||||||
|  | import dan200.computercraft.api.IUpgradeBase; | ||||||
| import dan200.computercraft.api.client.TransformedModel; | import dan200.computercraft.api.client.TransformedModel; | ||||||
| import dan200.computercraft.api.peripheral.IPeripheral; | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
|  |  | ||||||
| import net.minecraft.item.ItemStack; |  | ||||||
| import net.minecraft.util.Identifier; |  | ||||||
| import net.minecraft.util.math.Direction; | import net.minecraft.util.math.Direction; | ||||||
|  |  | ||||||
| import net.fabricmc.api.EnvType; | import net.fabricmc.api.EnvType; | ||||||
| @@ -25,27 +24,8 @@ import net.fabricmc.api.Environment; | |||||||
|  * |  * | ||||||
|  * @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade) |  * @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade) | ||||||
|  */ |  */ | ||||||
| public interface ITurtleUpgrade { | public interface ITurtleUpgrade extends IUpgradeBase | ||||||
|     /** | { | ||||||
|      * Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or "my_mod:my_upgrade". You should use a unique |  | ||||||
|      * resource domain to ensure this upgrade is uniquely identified. The turtle will fail registration if an already used ID is specified. |  | ||||||
|      * |  | ||||||
|      * @return The unique ID for this upgrade. |  | ||||||
|      * @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade) |  | ||||||
|      */ |  | ||||||
|     @Nonnull |  | ||||||
|     Identifier getUpgradeID(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Return an unlocalised string to describe this type of turtle in turtle item names. |  | ||||||
|      * |  | ||||||
|      * Examples of built-in adjectives are "Wireless", "Mining" and "Crafty". |  | ||||||
|      * |  | ||||||
|      * @return The localisation key for this upgrade's adjective. |  | ||||||
|      */ |  | ||||||
|     @Nonnull |  | ||||||
|     String getUnlocalisedAdjective(); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Return whether this turtle adds a tool or a peripheral to the turtle. |      * Return whether this turtle adds a tool or a peripheral to the turtle. | ||||||
|      * |      * | ||||||
| @@ -55,18 +35,6 @@ public interface ITurtleUpgrade { | |||||||
|     @Nonnull |     @Nonnull | ||||||
|     TurtleUpgradeType getType(); |     TurtleUpgradeType getType(); | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Return an item stack representing the type of item that a turtle must be crafted with to create a turtle which holds this upgrade. This item stack is |  | ||||||
|      * also used to determine the upgrade given by {@code turtle.equip()} |  | ||||||
|      * |  | ||||||
|      * Ideally this should be constant over a session. It is recommended that you cache the item too, in order to prevent constructing it every time the |  | ||||||
|      * method is called. |  | ||||||
|      * |  | ||||||
|      * @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted. |  | ||||||
|      */ |  | ||||||
|     @Nonnull |  | ||||||
|     ItemStack getCraftingItem(); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade. |      * Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade. | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -59,7 +59,8 @@ public final class PocketUpgrades { | |||||||
|  |  | ||||||
|         for (IPocketUpgrade upgrade : upgrades.values()) { |         for (IPocketUpgrade upgrade : upgrades.values()) { | ||||||
|             ItemStack craftingStack = upgrade.getCraftingItem(); |             ItemStack craftingStack = upgrade.getCraftingItem(); | ||||||
|             if (!craftingStack.isEmpty() && InventoryUtil.areItemsSimilar(stack, craftingStack)) { |             if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.isItemSuitable( stack ) ) | ||||||
|  |             { | ||||||
|                 return upgrade; |                 return upgrade; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ import javax.annotation.Nullable; | |||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.api.turtle.ITurtleUpgrade; | import dan200.computercraft.api.turtle.ITurtleUpgrade; | ||||||
| import dan200.computercraft.shared.computer.core.ComputerFamily; | import dan200.computercraft.shared.computer.core.ComputerFamily; | ||||||
| import dan200.computercraft.shared.util.InventoryUtil; |  | ||||||
|  |  | ||||||
| import net.minecraft.item.ItemStack; | import net.minecraft.item.ItemStack; | ||||||
|  |  | ||||||
| @@ -96,7 +95,8 @@ public final class TurtleUpgrades { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             ItemStack craftingStack = wrapper.upgrade.getCraftingItem(); |             ItemStack craftingStack = wrapper.upgrade.getCraftingItem(); | ||||||
|             if (!craftingStack.isEmpty() && InventoryUtil.areItemsSimilar(stack, craftingStack)) { |             if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && wrapper.upgrade.isItemSuitable( stack ) ) | ||||||
|  |             { | ||||||
|                 return wrapper.upgrade; |                 return wrapper.upgrade; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -11,6 +11,8 @@ import java.util.function.Function; | |||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
|  |  | ||||||
|  | import org.apache.commons.lang3.tuple.Pair; | ||||||
|  |  | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.api.client.TransformedModel; | import dan200.computercraft.api.client.TransformedModel; | ||||||
| import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; | import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; | ||||||
| @@ -29,8 +31,6 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer; | |||||||
| import dan200.computercraft.shared.util.DropConsumer; | import dan200.computercraft.shared.util.DropConsumer; | ||||||
| import dan200.computercraft.shared.util.InventoryUtil; | import dan200.computercraft.shared.util.InventoryUtil; | ||||||
| import dan200.computercraft.shared.util.WorldUtil; | import dan200.computercraft.shared.util.WorldUtil; | ||||||
| import org.apache.commons.lang3.tuple.Pair; |  | ||||||
|  |  | ||||||
| import net.minecraft.block.Block; | import net.minecraft.block.Block; | ||||||
| import net.minecraft.block.BlockState; | import net.minecraft.block.BlockState; | ||||||
| import net.minecraft.block.Blocks; | import net.minecraft.block.Blocks; | ||||||
| @@ -41,9 +41,9 @@ import net.minecraft.entity.Entity; | |||||||
| import net.minecraft.entity.attribute.EntityAttributes; | import net.minecraft.entity.attribute.EntityAttributes; | ||||||
| import net.minecraft.entity.damage.DamageSource; | import net.minecraft.entity.damage.DamageSource; | ||||||
| import net.minecraft.entity.decoration.ArmorStandEntity; | import net.minecraft.entity.decoration.ArmorStandEntity; | ||||||
| import net.minecraft.fluid.FluidState; |  | ||||||
| import net.minecraft.item.Item; | import net.minecraft.item.Item; | ||||||
| import net.minecraft.item.ItemStack; | import net.minecraft.item.ItemStack; | ||||||
|  | import net.minecraft.nbt.CompoundTag; | ||||||
| import net.minecraft.util.ActionResult; | import net.minecraft.util.ActionResult; | ||||||
| import net.minecraft.util.Hand; | import net.minecraft.util.Hand; | ||||||
| import net.minecraft.util.Identifier; | import net.minecraft.util.Identifier; | ||||||
| @@ -59,6 +59,9 @@ import net.fabricmc.fabric.api.event.player.AttackEntityCallback; | |||||||
| public class TurtleTool extends AbstractTurtleUpgrade { | public class TurtleTool extends AbstractTurtleUpgrade { | ||||||
|     protected final ItemStack item; |     protected final ItemStack item; | ||||||
|  |  | ||||||
|  |     private static final int TAG_LIST = 9; | ||||||
|  |     private static final int TAG_COMPOUND = 10; | ||||||
|  |  | ||||||
|     public TurtleTool(Identifier id, String adjective, Item item) { |     public TurtleTool(Identifier id, String adjective, Item item) { | ||||||
|         super(id, TurtleUpgradeType.TOOL, adjective, item); |         super(id, TurtleUpgradeType.TOOL, adjective, item); | ||||||
|         this.item = new ItemStack(item); |         this.item = new ItemStack(item); | ||||||
| @@ -74,6 +77,24 @@ public class TurtleTool extends AbstractTurtleUpgrade { | |||||||
|         this.item = toolItem; |         this.item = toolItem; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean isItemSuitable( @Nonnull ItemStack stack ) | ||||||
|  |     { | ||||||
|  |         CompoundTag tag = stack.getTag(); | ||||||
|  |         if( tag == null || tag.isEmpty() ) return true; | ||||||
|  |  | ||||||
|  |         // Check we've not got anything vaguely interesting on the item. We allow other mods to add their | ||||||
|  |         // own NBT, with the understanding such details will be lost to the mist of time. | ||||||
|  |         if( stack.isDamaged() || stack.hasEnchantments() || stack.hasCustomName() ) return false; | ||||||
|  |         if( tag.contains( "AttributeModifiers", TAG_LIST ) && | ||||||
|  |             !tag.getList( "AttributeModifiers", TAG_COMPOUND ).isEmpty() ) | ||||||
|  |         { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Nonnull |     @Nonnull | ||||||
|     @Override |     @Override | ||||||
|     public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) { |     public TurtleCommandResult useTool(@Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction) { | ||||||
| @@ -183,7 +204,6 @@ public class TurtleTool extends AbstractTurtleUpgrade { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         BlockState state = world.getBlockState(blockPosition); |         BlockState state = world.getBlockState(blockPosition); | ||||||
|         FluidState fluidState = world.getFluidState(blockPosition); |  | ||||||
|  |  | ||||||
|         TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, turtlePosition, direction); |         TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, turtlePosition, direction); | ||||||
|         turtlePlayer.loadInventory(this.item.copy()); |         turtlePlayer.loadInventory(this.item.copy()); | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ import net.minecraft.block.entity.BlockEntity; | |||||||
| import net.minecraft.entity.Entity; | import net.minecraft.entity.Entity; | ||||||
| import net.minecraft.inventory.Inventory; | import net.minecraft.inventory.Inventory; | ||||||
| import net.minecraft.item.ItemStack; | import net.minecraft.item.ItemStack; | ||||||
| import net.minecraft.nbt.CompoundTag; |  | ||||||
| import net.minecraft.util.math.BlockPos; | import net.minecraft.util.math.BlockPos; | ||||||
| import net.minecraft.util.math.Direction; | import net.minecraft.util.math.Direction; | ||||||
| import net.minecraft.util.math.Vec3d; | import net.minecraft.util.math.Vec3d; | ||||||
| @@ -28,53 +27,6 @@ public final class InventoryUtil { | |||||||
|         return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual(a, b)); |         return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual(a, b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Determines if two items are "mostly" equivalent. Namely, they have the same item and damage, and identical share stacks. |  | ||||||
|      * |  | ||||||
|      * sufficient to ensure basic information (such as enchantments) are the same, while not having to worry about capabilities. |  | ||||||
|      * |  | ||||||
|      * @param a The first stack to check |  | ||||||
|      * @param b The second stack to check |  | ||||||
|      * @return If these items are largely the same. |  | ||||||
|      */ |  | ||||||
|     public static boolean areItemsSimilar(@Nonnull ItemStack a, @Nonnull ItemStack b) { |  | ||||||
|         if (a == b) { |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         if (a.isEmpty()) { |  | ||||||
|             return !b.isEmpty(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (a.getItem() != b.getItem()) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a |  | ||||||
|         // null one. |  | ||||||
|         CompoundTag shareTagA = a.getTag(); |  | ||||||
|         CompoundTag shareTagB = b.getTag(); |  | ||||||
|         if (shareTagA == shareTagB) { |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         if (shareTagA == null) { |  | ||||||
|             return shareTagB.isEmpty(); |  | ||||||
|         } |  | ||||||
|         if (shareTagB == null) { |  | ||||||
|             return shareTagA.isEmpty(); |  | ||||||
|         } |  | ||||||
|         return shareTagA.equals(shareTagB); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     public static ItemStack copyItem(@Nonnull ItemStack a) { |  | ||||||
|         return a.copy(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static ItemStorage getStorage(World world, BlockPos pos, Direction side) { |  | ||||||
|         Inventory inventory = getInventory(world, pos, side); |  | ||||||
|         return inventory == null ? null : ItemStorage.wrap(inventory, side); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Methods for finding inventories: |     // Methods for finding inventories: | ||||||
|  |  | ||||||
|     public static Inventory getInventory(World world, BlockPos pos, Direction side) { |     public static Inventory getInventory(World world, BlockPos pos, Direction side) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jummit
					Jummit