[1.12.2] TileEntityRender получает всегда air как предмет из TileEntity

Версия Minecraft
1.12.2
API
Forge
39
2
0
Короче есть полка, она должна рендерить предмет, всё почти готово, только когда в методе render пытаюсь получить предмет, который находиться в полке, всегда выдаёт air, я пробовал поставить чисто один предмет и с ним работает
TileEntityRender:
public class TileEntityRackRender extends TileEntitySpecialRenderer<TileEntityRack> {
    private EntityItem entityItem = new EntityItem(Minecraft.getMinecraft().world, 0D, 0D, 0D);
    @Override
    public void render(TileEntityRack tileEntityRack, double x, double y, double z, float partialTicks, int destroyStage, float alpha)
    {
        ItemStack item = tileEntityRack.getItem(); //всегда air
        System.out.println(item);
        GL11.glPushMatrix();
        {
            GL11.glTranslated((float) x + 0.5F, (float) y + 0.2F, (float) z + 0.5F);
            GL11.glScalef(0.65F, 0.65F, 0.65F);
            entityItem.hoverStart = 0.0F;
            entityItem.setItem(item);  //если тут поставить любой предмет, то он будет рендериться
            GL11.glRotatef(-90F, 0, 1, 0);
            GL11.glRotatef(0, 0, 1, 0);
            Minecraft.getMinecraft().getRenderManager().renderEntity(entityItem, 0.0D, 0.2D, 0.0D, 0.0F, 0.0F, false);
        }
        GL11.glPopMatrix();

    }
}
TileEntity:
public class TileEntityRack extends TileEntity {
    private ItemStack item = ItemStack.EMPTY;

    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        this.setItem(new ItemStack(compound.getCompoundTag("item")));
    }

    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);
        compound.setTag("item", this.getItem().writeToNBT(new NBTTagCompound()));
        return compound;
    }

    public ItemStack getItem()
    {
        System.out.println(item + " tileEntity");
        return this.item;
    }

    public void setItem(ItemStack itemStack)
    {
        this.item = itemStack;
        this.markDirty();
    }
}
Сама полка хранит в себе предмет, то есть тайл работает
 
Решение
Использовать ItemStack в NBT без обёртки в виде IInventory или ItemStackHandler - не лучшее решение. Просто потому, что большинство методов, которые отвечают за обмен пакетами придётся писать вручную. Это, кстати, и есть причина не-рендера твоего предмета.
Решения есть 2: либо написать свои пакеты, либо использовать IInventory или ItemStackHandler (первый Forge не рекомендует использовать).
Недоработки касательно рендера описали выше, решения там же.
116
13
13
Minecraft.getMinecraft().getRenderManager().renderEntity(entityItem, 0.0D, 0.2D, 0.0D, 0.0F, 0.0F, false);
Если тебе нужно рендерить предмет, то лучше будет воспользоваться Minecraft.getMinecraft().getRenderItem().renderItem(ItemStack, ItemCameraTransforms.TransformType.FIXED).
Это поможет убрать 4 ненужные строчки из твоего рендера.

Еще, вероятнее всего, твой рендер предмета будет тёмным - тогда вначале метода отключи lightmap через Minecraft.getMinecraft().entityRenderer.disableLightmap(), а в конце включай обратно через Minecraft.getMinecraft().entityRenderer.enableLightmap()
 
Последнее редактирование:
440
42
112
Последнее редактирование:
1,374
113
241
Использовать ItemStack в NBT без обёртки в виде IInventory или ItemStackHandler - не лучшее решение. Просто потому, что большинство методов, которые отвечают за обмен пакетами придётся писать вручную. Это, кстати, и есть причина не-рендера твоего предмета.
Решения есть 2: либо написать свои пакеты, либо использовать IInventory или ItemStackHandler (первый Forge не рекомендует использовать).
Недоработки касательно рендера описали выше, решения там же.
 
39
2
0
либо использовать IInventory или ItemStackHandler
Я вроде сделал обёртку для ItemStack через ItemStackHandler, но всё равно в TileEntitySpecialRenderer при получении предмета через tileEntityRack.getItem() выдаёт AIR
TileEntity:
public class TileEntityRack extends TileEntity{
    private ItemStackHandler item = new ItemStackHandler(2); //если ставить 1, то случается исключение при вызове методов setStackInSlot и getStackInSlot, а оно вызывает его из-за метода validateSlotIndex, который не даёт ничего сделать если размер 1

    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        item.deserializeNBT(compound.getCompoundTag("item"));
    }

    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);
        compound.setTag("item", this.item.serializeNBT());
        return compound;
    }

    public ItemStack getItem()
    {
        return this.item.getStackInSlot(1);
    }

    public void setItem(ItemStack itemStack)
    {
        this.item.setStackInSlot(1,itemStack);
        this.markDirty();
    }
}
 
1,374
113
241
public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setTag("item", this.item.serializeNBT()); return compound; }
Вызывай super в return. @Override проставь (читать не оч удобно, java вроде понимает что ты хочешь перезаписать метод).
//если ставить 1, то случается исключение при вызове методов setStackInSlot и getStackInSlot, а оно вызывает его из-за метода validateSlotIndex, который не даёт ничего сделать если размер 1
Ну так переопредели методы.

Также не вижу у тебя использования капы. У меня реализовано вот так (код старый, ему уже года 2, прошу не бить палками):

Java:
public class TileEntityDryer extends TileEntity implements ITickable{
    
    public ItemStackHandler inventory = new ItemStackHandler(1) {
        @Override
        protected void onContentsChanged(int slot) {
            if (!world.isRemote) {
                lastChangeTime = world.getTotalWorldTime();
                System.out.println(inventory.getStackInSlot(0).getItem().getRegistryName().toString());
                TweaksMain.network.sendToAllAround(new PacketUpdateDryer(TileEntityDryer.this),
                        new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), pos.getY(), pos.getZ(), 64));
            }
        }
        @Override
        public int getSlotLimit(int slot) { return 64; }
        @Override
        public boolean isItemValid(int slot, @Nonnull ItemStack stack) { return true; }
    };
    public long lastChangeTime;
    public int timer = 0;
    
    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound) {
        compound.setTag("inventory", inventory.serializeNBT());
        compound.setLong("lastChangeTime", lastChangeTime);
        return super.writeToNBT(compound);
    }
    
    @Override
    public void readFromNBT(NBTTagCompound compound) {
        inventory.deserializeNBT(compound.getCompoundTag("inventory"));
        lastChangeTime = compound.getLong("lastChangeTime");
        super.readFromNBT(compound);
    }
    
    @Override
    public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
        return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
    }
    
    
    @Nullable
    @Override
    public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
        return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ? (T)inventory : super.getCapability(capability, facing);
    }

    @Override
    public void onLoad() {
        if (world.isRemote) {
            TweaksMain.network.sendToServer(new PacketRequestUpdateDryer(this));
        }
        timer = 0;
    }
    
    @Override
    public void update() {
        if(!world.isRemote) {
            if(TweaksConfig.dryerRecipes.containsValue(inventory.getStackInSlot(0).getItem().getRegistryName().toString())) {
                timer++;
                if(timer == 20*2) {
                    timer = 0;
                    if(getItemFromCollection(inventory.getStackInSlot(0)) != null) {
                        System.out.println(getItemFromCollection(inventory.getStackInSlot(0)));
                        inventory.setStackInSlot(0, new ItemStack(Item.getByNameOrId(getItemFromCollection(inventory.getStackInSlot(0))),
                                inventory.getStackInSlot(0).getCount()));
                    }
                }
            } else
                timer = 0;
        }
    }
    
    private String getItemFromCollection(ItemStack stack) {
        if(TweaksConfig.dryerRecipes.containsValue(stack.getItem().getRegistryName().toString())) {
            for(int i = 0; i < TweaksConfig.dryerRecipes.size(); i++) {
                String key = (String)Arrays.asList(TweaksConfig.dryerRecipes.keySet().toArray()).get(i);
                String value = TweaksConfig.dryerRecipes.get(key);
                if(stack.getItem() == Item.getByNameOrId(value)) {
                    return key;
                }
            }
        }
        return null;
    }
Здесь я использую пакеты для передачи lastChangeTime, так что пришлось пакет писать вручную. Но если тебе не понадобятся подобные переменные, то капа должна (по идее) сделать всё за тебя.
 
Сверху