All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.blockentity.BlockEntityEndGateway Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.blockentity;

import cn.nukkit.api.Since;
import cn.nukkit.block.Block;
import cn.nukkit.blockstate.BlockState;
import cn.nukkit.entity.Entity;
import cn.nukkit.entity.projectile.EntityEnderPearl;
import cn.nukkit.entity.projectile.EntityProjectile;
import cn.nukkit.event.player.PlayerTeleportEvent.TeleportCause;
import cn.nukkit.level.format.FullChunk;
import cn.nukkit.math.BlockVector3;
import cn.nukkit.nbt.tag.CompoundTag;
import cn.nukkit.nbt.tag.IntTag;
import cn.nukkit.nbt.tag.ListTag;
import cn.nukkit.network.protocol.BlockEventPacket;

import static cn.nukkit.block.BlockID.BEDROCK;

/**
 * @author GoodLucky777
 */
public class BlockEntityEndGateway extends BlockEntitySpawnable {

    // NBT data
    private int age;
    private BlockVector3 exitPortal;
    
    // Default value
    private static final BlockVector3 defaultExitPortal = new BlockVector3(0, 0, 0);
    
    // Others
    public int teleportCooldown;
    
    private static final BlockState STATE_BEDROCK = BlockState.of(BEDROCK);
    
    public BlockEntityEndGateway(FullChunk chunk, CompoundTag nbt) {
        super(chunk, nbt);
    }
    
    @Override
    protected void initBlockEntity() {
        if (this.namedTag.contains("Age")) {
            this.age = this.namedTag.getInt("Age");
        } else {
            this.age = 0;
        }
        
        if (this.namedTag.contains("ExitPortal")) {
            ListTag exitPortalList = this.namedTag.getList("ExitPortal", IntTag.class);
            this.exitPortal = new BlockVector3(exitPortalList.get(0).data, exitPortalList.get(1).data, exitPortalList.get(2).data);
        } else {
            this.exitPortal = this.defaultExitPortal.clone();
        }
        
        this.teleportCooldown = 0;
        
        super.initBlockEntity();
        
        scheduleUpdate();
    }
    
    @Override
    public boolean isBlockEntityValid() {
        return this.getLevel().getBlockIdAt(getFloorX(), getFloorY(), getFloorZ()) == Block.END_GATEWAY;
    }
    
    @Override
    public void saveNBT() {
        super.saveNBT();
        
        this.namedTag.putInt("Age", this.age);
        this.namedTag.putList(new ListTag("ExitPortal")
            .add(new IntTag("0", this.exitPortal.x))
            .add(new IntTag("1", this.exitPortal.y))
            .add(new IntTag("2", this.exitPortal.z))
        );
    }

    @Since("1.6.0.0-PNX")
    @Override
    public void loadNBT() {
        super.loadNBT();
        this.age = this.namedTag.getInt("Age");
        ListTag exitPortalList = this.namedTag.getList("ExitPortal", IntTag.class);
        this.exitPortal = new BlockVector3(exitPortalList.get(0).data, exitPortalList.get(1).data, exitPortalList.get(2).data);
    }

    @Override
    public boolean onUpdate() {
        if (this.closed) {
            return false;
        }
        
        this.timing.startTiming();
        
        boolean isGenerated = isGenerating();
        
        this.age++;
        
        if (teleportCooldown > 0) {
            teleportCooldown--;
            if (teleportCooldown == 0) {
                setDirty();
                this.spawnToAll();
            }
        } else {
            if (this.age % 2400 == 0) {
                this.setTeleportCooldown();
            }
        }
        
        if (isGenerated != isGenerating()) {
            setDirty();
            this.spawnToAll();
        }
        
        this.timing.stopTiming();
        
        return true;
    }
    
    public void teleportEntity(Entity entity) {
        if (exitPortal != null) {
            if (entity instanceof EntityEnderPearl) {
                if (((EntityProjectile) entity).shootingEntity != null) {
                    ((EntityProjectile) entity).shootingEntity.teleport(getSafeExitPortal().asVector3().add(0.5, 0, 0.5), TeleportCause.END_GATEWAY);
                    entity.close();
                } else {
                    entity.teleport(getSafeExitPortal().asVector3().add(0.5, 0, 0.5), TeleportCause.END_GATEWAY);
                }
            } else {
                entity.teleport(getSafeExitPortal().asVector3().add(0.5, 0, 0.5), TeleportCause.END_GATEWAY);
            }
        }
        
        setTeleportCooldown();
    }
    
    public BlockVector3 getSafeExitPortal() {
        // TODO: Find better way
        for (int x = -1; x <= 1; x++) {
            for (int z = -1; z <= 1; z++) {
                int chunkX = (exitPortal.getX() >> 4) + x;
                int chunkZ = (exitPortal.getZ() >> 4) + z;
                FullChunk chunk = this.getLevel().getChunk(chunkX, chunkZ, false);
                if (chunk == null || !(chunk.isGenerated() || chunk.isPopulated())) {
                    this.getLevel().generateChunk(chunkX, chunkZ, true);
                }
            }
        }
        
        for (int x = exitPortal.getX() - 5; x <= exitPortal.getX() + 5; x++) {
            for (int z = exitPortal.getZ() - 5; z <= exitPortal.getZ() + 5; z++) {
                for (int y = 255; y > Math.max(0, exitPortal.getY() + 2); y--) {
                    if (!this.getLevel().getBlockStateAt(x, y, z).equals(BlockState.AIR)) {
                        if (!this.getLevel().getBlockStateAt(x, y, z).equals(STATE_BEDROCK)) {
                            return new BlockVector3(x, y + 1, z);
                        }
                    }
                }
            }
        }
        
        return this.exitPortal.up(2);
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public BlockVector3 getExitPortal() {
        return exitPortal;
    }
    
    public void setExitPortal(BlockVector3 exitPortal) {
        this.exitPortal = exitPortal;
    }
    
    public boolean isGenerating() {
        return age < 200;
    }
    
    public boolean isTeleportCooldown() {
        return teleportCooldown > 0;
    }
    
    public void setTeleportCooldown() {
        this.setTeleportCooldown(40);
    }
    
    public void setTeleportCooldown(int teleportCooldown) {
        this.teleportCooldown = teleportCooldown;
        setDirty();
        sendBlockEventPacket(0);
        this.spawnToAll();
    }
    
    private void sendBlockEventPacket(int eventData) {
        if (this.closed) {
            return;
        }
        
        if (this.getLevel() == null) {
            return;
        }
        
        BlockEventPacket pk = new BlockEventPacket();
        pk.x = this.getFloorX();
        pk.y = this.getFloorY();
        pk.z = this.getFloorZ();
        pk.case1 = 1;
        pk.case2 = eventData;
        this.getLevel().addChunkPacket(this.getChunkX(), this.getChunkZ(), pk);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy