Container注册问题

Eroslon_黎明


你使用的IDE:IntelliJ IDEA
你使用的IDE版本:2020.1
Forge版本: 31.1.0
Minecraft版本: 1.15.2
Mapping 文件版本:20200514

错误简介
我看neutrino mod的容器教程,
将里面的tileentity替换成了Capability
进行注册以后就出现了这种问题
https://neutrino.v2mcdev.com/gui/container.html

报错日志

[11:44:33] [Render thread/FATAL] [minecraft/ThreadTaskExecutor]: Error executing task on Client
java.lang.IndexOutOfBoundsException: null
	at io.netty.buffer.EmptyByteBuf.readLong(EmptyByteBuf.java:601) ~[netty-all-4.1.25.Final.jar:4.1.25.Final] {}
	at net.minecraft.network.PacketBuffer.readLong(PacketBuffer.java:784) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.network.PacketBuffer.readBlockPos(PacketBuffer.java:139) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at com.CultivationSimulator.immortal.registry.ContainerTypeRegistry.lambda$null$0(ContainerTypeRegistry.java:15) ~[classes/:?] {re:classloading}
	at net.minecraft.inventory.container.ContainerType.create(ContainerType.java:52) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraftforge.fml.network.FMLPlayMessages$OpenContainer.lambda$null$0(FMLPlayMessages.java:287) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at java.util.Optional.ifPresent(Optional.java:159) ~[?:1.8.0_241] {}
	at net.minecraftforge.fml.network.FMLPlayMessages$OpenContainer.lambda$handle$1(FMLPlayMessages.java:286) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.NetworkEvent$Context.enqueueWork(NetworkEvent.java:215) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.FMLPlayMessages$OpenContainer.handle(FMLPlayMessages.java:284) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.simple.IndexedMessageCodec.lambda$tryDecode$3(IndexedMessageCodec.java:124) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at java.util.Optional.ifPresent(Optional.java:159) ~[?:1.8.0_241] {}
	at net.minecraftforge.fml.network.simple.IndexedMessageCodec.tryDecode(IndexedMessageCodec.java:124) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.simple.IndexedMessageCodec.consume(IndexedMessageCodec.java:157) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.simple.SimpleChannel.networkEventListener(SimpleChannel.java:79) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.eventbus.EventBus.doCastFilter(EventBus.java:212) ~[eventbus-2.0.0-milestone.1-service.jar:?] {}
	at net.minecraftforge.eventbus.EventBus.lambda$addListener$11(EventBus.java:204) ~[eventbus-2.0.0-milestone.1-service.jar:?] {}
	at net.minecraftforge.eventbus.EventBus.post(EventBus.java:258) ~[eventbus-2.0.0-milestone.1-service.jar:?] {}
	at net.minecraftforge.fml.network.NetworkInstance.dispatch(NetworkInstance.java:84) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraftforge.fml.network.NetworkHooks.lambda$onCustomPayload$0(NetworkHooks.java:74) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at java.util.Optional.map(Optional.java:215) ~[?:1.8.0_241] {}
	at net.minecraftforge.fml.network.NetworkHooks.onCustomPayload(NetworkHooks.java:74) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.client.network.play.ClientPlayNetHandler.handleCustomPayload(ClientPlayNetHandler.java:1868) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:runtimedistcleaner:A}
	at net.minecraft.network.play.server.SCustomPayloadPlayPacket.processPacket(SCustomPayloadPlayPacket.java:59) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.network.play.server.SCustomPayloadPlayPacket.processPacket(SCustomPayloadPlayPacket.java:11) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.network.PacketThreadUtil.func_225383_a(SourceFile:21) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.util.concurrent.ThreadTaskExecutor.run(SourceFile:144) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.util.concurrent.RecursiveEventLoop.run(SourceFile:23) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading}
	at net.minecraft.util.concurrent.ThreadTaskExecutor.driveOne(SourceFile:118) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.util.concurrent.ThreadTaskExecutor.drainTasks(SourceFile:103) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:898) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.Minecraft.run(Minecraft.java:554) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.main.Main.main(SourceFile:204) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {re:classloading,pl:runtimedistcleaner:A}
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_241] {}
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_241] {}
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_241] {}
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_241] {}
	at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:55) ~[forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-5.0.0-milestone.4.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-5.0.0-milestone.4.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-5.0.0-milestone.4.jar:?] {}
	at cpw.mods.modlauncher.Launcher.run(Launcher.java:81) [modlauncher-5.0.0-milestone.4.jar:?] {}
	at cpw.mods.modlauncher.Launcher.main(Launcher.java:65) [modlauncher-5.0.0-milestone.4.jar:?] {}
	at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:102) [forge-1.15.2-31.1.0_mapped_snapshot_20200514-1.15.1.jar:?] {}

相关代码

public class ContainerTypeRegistry {
    public static final DeferredRegister<ContainerType<?>> CONTAINERS = new DeferredRegister<>(ForgeRegistries.CONTAINERS, "immortal");
    public static RegistryObject<ContainerType<PlayerDataFirstContainer>> playerDataFirstContainer = CONTAINERS.register("player_data_first_container", () -> IForgeContainerType.create((int windowId, PlayerInventory inv, PacketBuffer data) -> new PlayerDataFirstContainer(windowId, inv, data.readBlockPos(), Minecraft.getInstance().world.getWorld())));
}

容器代码如下:

public class PlayerDataFirstContainer extends Container {
    private IInventory Inventory;

    public PlayerDataFirstContainer(int id, PlayerInventory playerInventory, BlockPos pos, World world) {
        super(ContainerTypeRegistry.playerDataFirstContainer.get(), id);
        PlayerEntity playerEntity = Minecraft.getInstance().player;
        assert playerEntity != null;
        LazyOptional<IPlayerDataContainerCapability> Capability = playerEntity.getCapability(CapabilityAPI.PLAYER_DATA_CONTAINER_CAPABILITY);
        Capability.ifPresent((capability) -> this.Inventory = capability.getInventory());
        Inventory inventory = new Inventory(4);
        //Player armor
        this.addSlot(new DataContainerSlot(inventory,0,23,65){
            {
                this.putStack(playerEntity.inventory.armorInventory.get(0));
            }
        });
        this.addSlot(new DataContainerSlot(inventory,1,23,104){
            {
                this.putStack(playerEntity.inventory.armorInventory.get(1));
            }
        });
        this.addSlot(new DataContainerSlot(inventory,2,107,65){
            {
                this.putStack(playerEntity.inventory.armorInventory.get(2));
            }
        });
        this.addSlot(new DataContainerSlot(inventory,3,107,104){
            {
                this.putStack(playerEntity.inventory.armorInventory.get(3));
            }
        });
        //Mod's ItemStack
        this.addSlot(new DataContainerSlot(Inventory,0,8,149));
        this.addSlot(new DataContainerSlot(Inventory,1,123,149));
        this.addSlot(new DataContainerSlot(Inventory,2,41,158));
        this.addSlot(new DataContainerSlot(Inventory,3,89,158));
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return true;
    }

    @Override
    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
        return ItemStack.EMPTY;
    }
}

Capability代码:

public class PlayerDataContainerCapability implements IPlayerDataContainerCapability {
    private Inventory inventory = new Inventory(4);

    @Override
    public Inventory getInventory() {
        return this.inventory;
    }

    @Override
    public CompoundNBT serializeNBT() {
        CompoundNBT compoundNBT = new CompoundNBT();
        for(int i = 0;i < inventory.getSizeInventory();i++) {
            ItemStack itemStack = this.inventory.getStackInSlot(i).copy();
            compoundNBT.put("item" + i, itemStack.serializeNBT());
        }
        return compoundNBT;
    }

    @Override
    public void deserializeNBT(CompoundNBT nbt) {
        for(int i = 0;i < inventory.getSizeInventory();i++)
        this.inventory.setInventorySlotContents(i,ItemStack.read(nbt.getCompound("item" + i)));
    }
}

Eroslon_黎明


没事了…PacketBuffer为null而已


FledgeXu


你的代码问题是在有点多,我看到什么再补充。
建议自己理理清楚Container的调用逻辑是什么,它会在哪一个端创建

  1. 既然你要存东西,请用Forge提供的ITEM_HANDLER_CAPABILITY,你不需要自己添加IInventory
  2. Container是一个在服务端和客户端的都会创建的类,而Minecraft.getInstance().player是一个只能在客户端调用的方法。
  3.  Capability.ifPresent((capability) -> this.Inventory = capability.getInventory());
     Inventory inventory = new Inventory(4);
    
    我没理解这里的重新创建Inventory的意义是什么。
  4. DataContainerSlot是什么?

Eroslon_黎明


1.我存东西是存玩家身上的

2.谢谢提醒,但是如果必须要该怎么改呢?

3.this.Inventory是cap上的inventory,
重新创建的Inventory是放玩家装备的(可以直接用PlayerInventory,可能是脑子憨了才写的)

4.DataContainerSlot代码为:

public class DataContainerSlot extends Slot {
    public DataContainerSlot(IInventory inventory, int id, int x, int y) {
        super(inventory, id, x, y);
    }

    @Override
    public boolean canTakeStack(PlayerEntity playerEntity) {
        return false;
    }
}

FledgeXu


  1. 存玩家身上和用Forge提供的ITEM_HANDLER_CAPABILITY提供的没有冲突……
  2. 你可以在构造方法了添加一个参数,然后在不同端创建的时候传入不同的PlayerEntity

Eroslon_黎明


emmm,
1.ITEM_HANDLER_CAPABILITY不是物品能力系统吗,不是只能存物品上的嘛…我打开方式是按键打开,怎么获取到物品上的呢…

2.好的,谢谢


FledgeXu


ITEM_HANDLER_CAPABILITY,这个名字的意思是,这个能力可以用来处理物品的输入输出,储存等功能。他只是一个Cap而已,Cap可以附加到任何东西上。


Eroslon_黎明


哦哦好的,我懂了


system


该主题在最后一个回复创建后7天后自动关闭。不再允许新的回复。