Posted October 23, 20178 yr I'm attempting to make a tile-entity inventory slot that permits only one instance of a single item (specifically, an anvil), and have not been having much success. Creating an AnvilSlot class which extends ItemSlotHandler and overriding the method public boolean isItemValid(ItemStack stack) { return stack.getItem() instanceof ItemAnvilBlock; } causes non-anvil items to be rejected through the GUI while accepting anvils just fine, but dispensers and other automation tools will crash the server upon attempting to insert any item at all: Spoiler [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:600]: ---- Minecraft Crash Report ---- // This doesn't make any sense! Time: 10/23/17 5:48 PM Description: Ticking block entity java.lang.NullPointerException: Ticking block entity at net.minecraftforge.items.VanillaInventoryCodeHooks.isFull(VanillaInventoryCodeHooks.java:232) at net.minecraftforge.items.VanillaInventoryCodeHooks.insertHook(VanillaInventoryCodeHooks.java:132) at net.minecraft.tileentity.TileEntityHopper.transferItemsOut(TileEntityHopper.java:212) at net.minecraft.tileentity.TileEntityHopper.updateHopper(TileEntityHopper.java:155) at net.minecraft.tileentity.TileEntityHopper.update(TileEntityHopper.java:140) at net.minecraft.world.World.updateEntities(World.java:1950) at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:648) at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:795) at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:699) at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:548) at java.lang.Thread.run(Thread.java:745) A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Client thread Stacktrace: at net.minecraftforge.items.VanillaInventoryCodeHooks.isFull(VanillaInventoryCodeHooks.java:232) at net.minecraftforge.items.VanillaInventoryCodeHooks.insertHook(VanillaInventoryCodeHooks.java:132) at net.minecraft.tileentity.TileEntityHopper.transferItemsOut(TileEntityHopper.java:212) at net.minecraft.tileentity.TileEntityHopper.updateHopper(TileEntityHopper.java:155) at net.minecraft.tileentity.TileEntityHopper.update(TileEntityHopper.java:140) -- Block entity being ticked -- Details: Name: minecraft:hopper // net.minecraft.tileentity.TileEntityHopper Block type: ID #154 (tile.hopper // net.minecraft.block.BlockHopper) Block data value: 0 / 0x0 / 0b0000 Block location: World: (263,65,265), Chunk: (at 7,4,9 in 16,16; contains blocks 256,0,256 to 271,255,271), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511) Actual block type: ID #154 (tile.hopper // net.minecraft.block.BlockHopper) Actual block data value: 0 / 0x0 / 0b0000 Stacktrace: at net.minecraft.world.World.updateEntities(World.java:1950) at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:648) -- Affected level -- Details: Level name: QFFR All players: 1 total; [EntityPlayerMP['Player655'/158, l='QFFR', x=262.27, y=64.00, z=263.71]] Chunk stats: ServerChunkCache: 625 Drop: 0 Level seed: 3546731182753150837 Level generator: ID 00 - default, ver 1. Features enabled: true Level generator options: Level spawn location: World: (256,64,256), Chunk: (at 0,4,0 in 16,16; contains blocks 256,0,256 to 271,255,271), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511) Level time: 1505 game time, 1505 day time Level dimension: 0 Level storage version: 0x04ABD - Anvil Level weather: Rain time: 31402 (now: false), thunder time: 111770 (now: false) Level game mode: Game mode: creative (ID 1). Hardcore: false. Cheats: true Stacktrace: at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:795) at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:699) at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:548) at java.lang.Thread.run(Thread.java:745) -- System Details -- Details: Minecraft Version: 1.11.2 Operating System: Windows 10 (amd64) version 10.0 Java Version: 1.8.0_101, Oracle Corporation Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation Memory: 189822984 bytes (181 MB) / 988807168 bytes (943 MB) up to 1871708160 bytes (1785 MB) JVM Flags: 0 total; IntCache: cache: 4, tcache: 0, allocated: 13, tallocated: 95 FML: MCP 9.38 Powered by Forge 13.20.1.2386 5 mods loaded, 5 mods active States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored UCHIJAAAA minecraft{1.11.2} [Minecraft] (minecraft.jar) UCHIJAAAA mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) UCHIJAAAA FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.11.2-13.20.1.2386.jar) UCHIJAAAA forge{13.20.1.2386} [Minecraft Forge] (forgeSrc-1.11.2-13.20.1.2386.jar) UCHIJAAAA lwae{1.0} [Lightweight Auto Enchanting] (bin) Loaded coremods (and transformers): GL info: ~~ERROR~~ RuntimeException: No OpenGL context found in the current thread. Profiler Position: N/A (disabled) Player Count: 1 / 8; [EntityPlayerMP['Player655'/158, l='QFFR', x=262.27, y=64.00, z=263.71]] Type: Integrated Server (map_client.txt) Is Modded: Definitely; Client brand changed to 'fml,forge' Furthermore, I'm not entirely sure how to go about reducing the size of the slot to 1: I tried checking against this.getHasStack() such that it would only accept if the slot was empty, but the number of anvils I could put into the slot via GUI remained 64. I'm using a TileEntity that implements ICapabilityProvider (and ITickable), and a container that extends the base Container class. Edited October 24, 20178 yr by Autom Solved the issue.
October 24, 20178 yr Author Got it working; I ran into a bit of a hiccup when I realized there are some slots I want the player to do something with (usually extract from) but not automation. However, this was solved by giving the ItemStackHandler classes a member to determine whether they were being accessed by the player or by automation, and setting that when they were passed through the TileEntity's getCapability() method. There are probably other ways to do that, but this is my preferred version due to being lightweight and simple.
October 24, 20178 yr Author UPDATE: Doing the above actually causes some weird concurrency issues when automation is adding items while the player is taking them away, resulting in temporary duplication of items. To have a slot that presents different options to players and automation, one needs to make a separate handler class for each type of capability and have the more restrictive ones wrap the least restrictive one to control what can be done to it. The determination of which handler to provide then needs to be made in getCapability(). The implementation is very similar to what is discussed here.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.