package net.glowstone.block.entity; import net.glowstone.block.GlowBlock; import net.glowstone.block.GlowBlockState; import net.glowstone.chunk.GlowChunk.Key; import net.glowstone.entity.GlowPlayer; import net.glowstone.util.nbt.CompoundTag; import org.bukkit.block.Block; /** * Base class for block entities (blocks with NBT data) in the world. * Most access to block entities should occur through the Bukkit BlockState API. */ public abstract class BlockEntity { protected final GlowBlock block; private String saveId; /** * Create a new BlockEntity at the given location. * * @param block The block the BlockEntity is attached to. */ public BlockEntity(GlowBlock block) { this.block = block; } //////////////////////////////////////////////////////////////////////////// // Utility stuff /** * Get the block this BlockEntity is associated with. * * @return The entity's block. */ public final Block getBlock() { return block; } /** * Update this BlockEntity's visible state to all players in range. */ public final void updateInRange() { Key key = new Key(block.getChunk().getX(), block.getChunk().getZ()); block.getWorld().getRawPlayers().stream().filter(player -> player.canSeeChunk(key)).forEach(this::update); } //////////////////////////////////////////////////////////////////////////// // World I/O /** * Set the text ID this block entity is saved to disk with. If this is not * set, then load and save of the "id" tag must be performed manually. * * @param saveId The ID. */ protected final void setSaveId(String saveId) { if (this.saveId != null) { throw new IllegalStateException("Can only set saveId once"); } this.saveId = saveId; } /** * Read this BlockEntity's data from the saved tag. * * @param tag The tag to load from. */ public void loadNbt(CompoundTag tag) { // verify id and coordinates if (saveId != null) { if (!tag.isString("id") || !tag.getString("id").equals(saveId)) { throw new IllegalArgumentException("Expected block entity id of " + saveId + ", got " + tag.getString("id")); } } // verify coordinates if provided if (tag.isInt("x")) { int x = tag.getInt("x"); int y = tag.getInt("y"); int z = tag.getInt("z"); int rx = block.getX(), ry = block.getY(), rz = block.getZ(); if (x != rx || y != ry || z != rz) { throw new IllegalArgumentException("Tried to load block entity with coords (" + x + "," + y + "," + z + ") into (" + rx + "," + ry + "," + rz + ")"); } } } /** * Save this BlockEntity's data to NBT. * * @param tag The tag to save to. */ public void saveNbt(CompoundTag tag) { if (saveId != null) { tag.putString("id", saveId); } tag.putInt("x", block.getX()); tag.putInt("y", block.getY()); tag.putInt("z", block.getZ()); } //////////////////////////////////////////////////////////////////////////// // Overridable stuff /** * Create a new BlockState which will correspond to this block entity. * * @return A GlowBlockState, or null to use a standard BlockState. */ public GlowBlockState getState() { return null; } /** * Destroy this BlockEntity. */ public void destroy() { // nothing by default } /** * Update this BlockEntity's visible state to the given player. * * @param player The player to update. */ public void update(GlowPlayer player) { // nothing by default } }