package cn.nukkit.entity.item; import cn.nukkit.block.Block; import cn.nukkit.entity.Entity; import cn.nukkit.entity.data.IntEntityData; import cn.nukkit.event.entity.EntityBlockChangeEvent; import cn.nukkit.event.entity.EntityDamageEvent; import cn.nukkit.event.entity.EntityDamageEvent.DamageCause; import cn.nukkit.item.Item; import cn.nukkit.level.GameRule; import cn.nukkit.level.GlobalBlockPalette; import cn.nukkit.level.Sound; import cn.nukkit.level.format.FullChunk; import cn.nukkit.math.Vector3; import cn.nukkit.nbt.tag.CompoundTag; /** * @author MagicDroidX */ public class EntityFallingBlock extends Entity { public static final int NETWORK_ID = 66; @Override public float getWidth() { return 0.98f; } @Override public float getLength() { return 0.98f; } @Override public float getHeight() { return 0.98f; } @Override protected float getGravity() { return 0.04f; } @Override protected float getDrag() { return 0.02f; } @Override protected float getBaseOffset() { return 0.49f; } @Override public boolean canCollide() { return false; } protected int blockId; protected int damage; public EntityFallingBlock(FullChunk chunk, CompoundTag nbt) { super(chunk, nbt); } @Override protected void initEntity() { super.initEntity(); if (namedTag != null) { if (namedTag.contains("TileID")) { blockId = namedTag.getInt("TileID"); } else if (namedTag.contains("Tile")) { blockId = namedTag.getInt("Tile"); namedTag.putInt("TileID", blockId); } if (namedTag.contains("Data")) { damage = namedTag.getByte("Data"); } } if (blockId == 0) { close(); return; } this.fireProof = true; setDataProperty(new IntEntityData(DATA_VARIANT, GlobalBlockPalette.getOrCreateRuntimeId(this.getBlock(), this.getDamage()))); } public boolean canCollideWith(Entity entity) { return false; } @Override public boolean attack(EntityDamageEvent source) { return source.getCause() == DamageCause.VOID && super.attack(source); } @Override public boolean onUpdate(int currentTick) { if (closed) { return false; } this.timing.startTiming(); int tickDiff = currentTick - lastUpdate; if (tickDiff <= 0 && !justCreated) { return true; } lastUpdate = currentTick; boolean hasUpdate = entityBaseTick(tickDiff); if (isAlive()) { motionY -= getGravity(); move(motionX, motionY, motionZ); float friction = 1 - getDrag(); motionX *= friction; motionY *= 1 - getDrag(); motionZ *= friction; Vector3 pos = (new Vector3(x - 0.5, y, z - 0.5)).round(); if (onGround) { close(); Block block = level.getBlock(pos); if (block.getId() > 0 && block.isTransparent() && !block.canBeReplaced()) { if (this.level.getGameRules().getBoolean(GameRule.DO_ENTITY_DROPS)) { getLevel().dropItem(this, Item.get(this.getBlock(), this.getDamage(), 1)); } } else { EntityBlockChangeEvent event = new EntityBlockChangeEvent(this, block, Block.get(getBlock(), getDamage())); server.getPluginManager().callEvent(event); if (!event.isCancelled()) { getLevel().setBlock(pos, event.getTo(), true); if (event.getTo().getId() == Item.ANVIL) { getLevel().addSound(pos, Sound.RANDOM_ANVIL_LAND); } } } hasUpdate = true; } updateMovement(); } this.timing.stopTiming(); return hasUpdate || !onGround || Math.abs(motionX) > 0.00001 || Math.abs(motionY) > 0.00001 || Math.abs(motionZ) > 0.00001; } public int getBlock() { return blockId; } public int getDamage() { return damage; } @Override public int getNetworkId() { return NETWORK_ID; } @Override public void saveNBT() { namedTag.putInt("TileID", blockId); namedTag.putByte("Data", damage); } @Override public boolean canBeMovedByCurrents() { return false; } }