- 1
- 0
Всем привет, создаю мод на маинкрафт версии 1.20.1, хотел сделать такие же полки как и в новой версии 1.21.10, но не получается рендер состояния полки, то есть когда забираю предмет из полки, то текстура все равно там остается
Может подскажет кто нмбудь, что не так
Java:
package farllands.farllands_deco.blockentity;
import farllands.farllands_deco.blockentity.ModBlockEntities;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import farllands.farllands_deco.Farllands_deco;
/**
* Блок-сущность полки: 3 слота, ванильная синхронизация на клиент.
* Требования:
* - В ModBlockEntities должен быть зарегистрирован тип SHELF.
* - ShelfBlock#createBlockEntity(...) возвращает new ShelfBlockEntity(pos, state).
* - В BER рендер читать stacks через getStack(i) (без кэшей).
*/
public class ShelfBlockEntity extends BlockEntity implements Inventory {
public final DefaultedList<ItemStack> items = DefaultedList.ofSize(3, ItemStack.EMPTY);
public ShelfBlockEntity(BlockPos pos, BlockState state) {
super(ModBlockEntities.SHELF, pos, state);
}
/* ------------------------- Inventory ------------------------- */
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
for (ItemStack stack : items) {
if (!stack.isEmpty()) return false;
}
return true;
}
@Override
public ItemStack getStack(int slot) {
return items.get(slot);
}
@Override
public ItemStack removeStack(int slot, int amount) {
ItemStack out = Inventories.splitStack(items, slot, amount);
// Всегда синхронизируем, даже если результат пустой, чтобы обновить визуально
markDirtyAndSync();
return out;
}
@Override
public ItemStack removeStack(int slot) {
ItemStack out = Inventories.removeStack(items, slot);
// Всегда синхронизируем, даже если результат пустой, чтобы обновить визуально
markDirtyAndSync();
return out;
}
@Override
public void setStack(int slot, ItemStack stack) {
items.set(slot, stack);
if (stack.getCount() > getMaxCountPerStack()) {
stack.setCount(getMaxCountPerStack());
}
markDirtyAndSync();
}
@Override
public void clear() {
items.clear();
markDirtyAndSync();
}
@Override
public boolean canPlayerUse(PlayerEntity player) {
if (world == null || world.getBlockEntity(pos) != this) return false;
return player.squaredDistanceTo(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) < 64.0;
}
@Override
public int getMaxCountPerStack() {
return 1;
}
/** Возвращает индекс первого пустого слота или -1. */
public int firstEmptySlot() {
for (int i = 0; i < items.size(); i++) {
if (items.get(i).isEmpty()) return i;
}
return -1;
}
/* --------------------------- NBT ----------------------------- */
@Override
protected void writeNbt(NbtCompound nbt) {
super.writeNbt(nbt);
Inventories.writeNbt(nbt, items);
}
@Override
public void readNbt(NbtCompound nbt) {
super.readNbt(nbt);
Inventories.readNbt(nbt, items);
if (world != null && world.isClient) {
// Принудительно обновляем рендер на клиенте
world.updateListeners(pos, getCachedState(), getCachedState(), Block.NOTIFY_LISTENERS | Block.REDRAW_ON_MAIN_THREAD);
}
}
/* --------------------- Client <-> Server --------------------- */
@Nullable
@Override
public BlockEntityUpdateS2CPacket toUpdatePacket() {
return BlockEntityUpdateS2CPacket.create(this, be -> be.toInitialChunkDataNbt());
}
@Override
public NbtCompound toInitialChunkDataNbt() {
NbtCompound nbt = new NbtCompound();
Inventories.writeNbt(nbt, items);
return nbt;
}
/**
* Вызывать ПОСЛЕ любого изменения содержимого.
* - Помечает сохранение
* - Шлёт пакет на клиент
* - Перерисовывает блок (BER)
*/
public void markDirtyAndSync() {
if (world == null || world.isClient()) return;
markDirty();
// Отправляем обновление через стандартный механизм
((ServerWorld) world).getChunkManager().markForUpdate(pos);
// Отправляем кастомный пакет каждому игроку отдельно
ServerWorld serverWorld = (ServerWorld) world;
for (ServerPlayerEntity player : serverWorld.getPlayers()) {
if (player.squaredDistanceTo(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) <= 64 * 64) {
// Создаём новый буфер для каждого игрока
PacketByteBuf buf = PacketByteBufs.create();
buf.writeBlockPos(pos);
NbtCompound nbt = new NbtCompound();
Inventories.writeNbt(nbt, items);
buf.writeNbt(nbt);
ServerPlayNetworking.send(player, Farllands_deco.SHELF_UPDATE_PACKET, buf);
}
}
}
}
Может подскажет кто нмбудь, что не так