Newer
Older
void-pack-super-server / work / nms.old.1585251758016 / minecraft / server / TileEntityBeacon.java
package net.minecraft.server;

import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

// CraftBukkit start
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.entity.HumanEntity;
import org.bukkit.potion.PotionEffect;
// CraftBukkit end

public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable {

    public static final MobEffectList[][] a = new MobEffectList[][]{{MobEffects.FASTER_MOVEMENT, MobEffects.FASTER_DIG}, {MobEffects.RESISTANCE, MobEffects.JUMP}, {MobEffects.INCREASE_DAMAGE}, {MobEffects.REGENERATION}};
    private static final Set<MobEffectList> b = (Set) Arrays.stream(TileEntityBeacon.a).flatMap(Arrays::stream).collect(Collectors.toSet());
    private List<TileEntityBeacon.BeaconColorTracker> c = Lists.newArrayList();
    private List<TileEntityBeacon.BeaconColorTracker> g = Lists.newArrayList();
    public int levels;
    private int i = -1;
    @Nullable
    public MobEffectList primaryEffect;
    @Nullable
    public MobEffectList secondaryEffect;
    @Nullable
    public IChatBaseComponent customName;
    public ChestLock chestLock;
    private final IContainerProperties containerProperties;
    // CraftBukkit start - add fields and methods
    public PotionEffect getPrimaryEffect() {
        return (this.primaryEffect != null) ? CraftPotionUtil.toBukkit(new MobEffect(this.primaryEffect, getLevel(), getAmplification(), true, true)) : null;
    }

    public PotionEffect getSecondaryEffect() {
        return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryEffect, getLevel(), getAmplification(), true, true)) : null;
    }
    // CraftBukkit end

    public TileEntityBeacon() {
        super(TileEntityTypes.BEACON);
        this.chestLock = ChestLock.a;
        this.containerProperties = new IContainerProperties() {
            @Override
            public int getProperty(int i) {
                switch (i) {
                    case 0:
                        return TileEntityBeacon.this.levels;
                    case 1:
                        return MobEffectList.getId(TileEntityBeacon.this.primaryEffect);
                    case 2:
                        return MobEffectList.getId(TileEntityBeacon.this.secondaryEffect);
                    default:
                        return 0;
                }
            }

            @Override
            public void setProperty(int i, int j) {
                switch (i) {
                    case 0:
                        TileEntityBeacon.this.levels = j;
                        break;
                    case 1:
                        if (!TileEntityBeacon.this.world.isClientSide && !TileEntityBeacon.this.c.isEmpty()) {
                            TileEntityBeacon.this.a(SoundEffects.BLOCK_BEACON_POWER_SELECT);
                        }

                        TileEntityBeacon.this.primaryEffect = TileEntityBeacon.b(j);
                        break;
                    case 2:
                        TileEntityBeacon.this.secondaryEffect = TileEntityBeacon.b(j);
                }

            }

            @Override
            public int a() {
                return 3;
            }
        };
    }

    @Override
    public void tick() {
        int i = this.position.getX();
        int j = this.position.getY();
        int k = this.position.getZ();
        BlockPosition blockposition;

        if (this.i < j) {
            blockposition = this.position;
            this.g = Lists.newArrayList();
            this.i = blockposition.getY() - 1;
        } else {
            blockposition = new BlockPosition(i, this.i + 1, k);
        }

        TileEntityBeacon.BeaconColorTracker tileentitybeacon_beaconcolortracker = this.g.isEmpty() ? null : (TileEntityBeacon.BeaconColorTracker) this.g.get(this.g.size() - 1);
        int l = this.world.a(HeightMap.Type.WORLD_SURFACE, i, k);

        int i1;

        for (i1 = 0; i1 < 10 && blockposition.getY() <= l; ++i1) {
            IBlockData iblockdata = this.world.getType(blockposition);
            Block block = iblockdata.getBlock();

            if (block instanceof IBeaconBeam) {
                float[] afloat = ((IBeaconBeam) block).a().d();

                if (this.g.size() <= 1) {
                    tileentitybeacon_beaconcolortracker = new TileEntityBeacon.BeaconColorTracker(afloat);
                    this.g.add(tileentitybeacon_beaconcolortracker);
                } else if (tileentitybeacon_beaconcolortracker != null) {
                    if (Arrays.equals(afloat, tileentitybeacon_beaconcolortracker.a)) {
                        tileentitybeacon_beaconcolortracker.a();
                    } else {
                        tileentitybeacon_beaconcolortracker = new TileEntityBeacon.BeaconColorTracker(new float[]{(tileentitybeacon_beaconcolortracker.a[0] + afloat[0]) / 2.0F, (tileentitybeacon_beaconcolortracker.a[1] + afloat[1]) / 2.0F, (tileentitybeacon_beaconcolortracker.a[2] + afloat[2]) / 2.0F});
                        this.g.add(tileentitybeacon_beaconcolortracker);
                    }
                }
            } else {
                if (tileentitybeacon_beaconcolortracker == null || iblockdata.b((IBlockAccess) this.world, blockposition) >= 15 && block != Blocks.BEDROCK) {
                    this.g.clear();
                    this.i = l;
                    break;
                }

                tileentitybeacon_beaconcolortracker.a();
            }

            blockposition = blockposition.up();
            ++this.i;
        }

        i1 = this.levels;
        if (this.world.getTime() % 80L == 0L) {
            if (!this.c.isEmpty()) {
                this.a(i, j, k);
            }

            if (this.levels > 0 && !this.c.isEmpty()) {
                this.applyEffects();
                this.a(SoundEffects.BLOCK_BEACON_AMBIENT);
            }
        }

        if (this.i >= l) {
            this.i = -1;
            boolean flag = i1 > 0;

            this.c = this.g;
            if (!this.world.isClientSide) {
                boolean flag1 = this.levels > 0;

                if (!flag && flag1) {
                    this.a(SoundEffects.BLOCK_BEACON_ACTIVATE);
                    Iterator iterator = this.world.a(EntityPlayer.class, (new AxisAlignedBB((double) i, (double) j, (double) k, (double) i, (double) (j - 4), (double) k)).grow(10.0D, 5.0D, 10.0D)).iterator();

                    while (iterator.hasNext()) {
                        EntityPlayer entityplayer = (EntityPlayer) iterator.next();

                        CriterionTriggers.l.a(entityplayer, this);
                    }
                } else if (flag && !flag1) {
                    this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE);
                }
            }
        }

    }

    private void a(int i, int j, int k) {
        this.levels = 0;

        for (int l = 1; l <= 4; this.levels = l++) {
            int i1 = j - l;

            if (i1 < 0) {
                break;
            }

            boolean flag = true;

            for (int j1 = i - l; j1 <= i + l && flag; ++j1) {
                for (int k1 = k - l; k1 <= k + l; ++k1) {
                    Block block = this.world.getType(new BlockPosition(j1, i1, k1)).getBlock();

                    if (block != Blocks.EMERALD_BLOCK && block != Blocks.GOLD_BLOCK && block != Blocks.DIAMOND_BLOCK && block != Blocks.IRON_BLOCK) {
                        flag = false;
                        break;
                    }
                }
            }

            if (!flag) {
                break;
            }
        }

    }

    @Override
    public void ab_() {
        this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE);
        super.ab_();
    }

    // CraftBukkit start - split into components
    private byte getAmplification() {
        {
            byte b0 = 0;

            if (this.levels >= 4 && this.primaryEffect == this.secondaryEffect) {
                b0 = 1;
            }

            return b0;
        }
    }

    private int getLevel() {
        {
            int i = (9 + this.levels * 2) * 20;
            return i;
        }
    }

    public List getHumansInRange() {
        {
            double d0 = (double) (this.levels * 10 + 10);

            AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.position)).g(d0).b(0.0D, (double) this.world.getBuildHeight(), 0.0D);
            List<EntityHuman> list = this.world.a(EntityHuman.class, axisalignedbb);

            return list;
        }
    }

    private void applyEffect(List list, MobEffectList effects, int i, int b0) {
        {
            Iterator iterator = list.iterator();

            EntityHuman entityhuman;

            while (iterator.hasNext()) {
                entityhuman = (EntityHuman) iterator.next();
                entityhuman.addEffect(new MobEffect(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON);
            }
        }
    }

    private boolean hasSecondaryEffect() {
        {
            if (this.levels >= 4 && this.primaryEffect != this.secondaryEffect && this.secondaryEffect != null) {
                return true;
            }

            return false;
        }
    }

    private void applyEffects() {
        if (!this.world.isClientSide && this.primaryEffect != null) {
            double d0 = (double) (this.levels * 10 + 10);
            byte b0 = getAmplification();

            int i = getLevel();
            List list = getHumansInRange();

            applyEffect(list, this.primaryEffect, i, b0);

            if (hasSecondaryEffect()) {
                applyEffect(list, this.secondaryEffect, i, 0);
            }
        }

    }
    // CraftBukkit end

    public void a(SoundEffect soundeffect) {
        this.world.playSound((EntityHuman) null, this.position, soundeffect, SoundCategory.BLOCKS, 1.0F, 1.0F);
    }

    public int h() {
        return this.levels;
    }

    @Nullable
    @Override
    public PacketPlayOutTileEntityData getUpdatePacket() {
        return new PacketPlayOutTileEntityData(this.position, 3, this.b());
    }

    @Override
    public NBTTagCompound b() {
        return this.save(new NBTTagCompound());
    }

    @Nullable
    private static MobEffectList b(int i) {
        MobEffectList mobeffectlist = MobEffectList.fromId(i);

        return TileEntityBeacon.b.contains(mobeffectlist) ? mobeffectlist : null;
    }

    @Override
    public void load(NBTTagCompound nbttagcompound) {
        super.load(nbttagcompound);
        // CraftBukkit start - persist manually set non-default beacon effects (SPIGOT-3598)
        this.primaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Primary"));
        this.secondaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Secondary"));
        this.levels = nbttagcompound.getInt("Levels"); // SPIGOT-5053, use where available
        // CraftBukkit end
        if (nbttagcompound.hasKeyOfType("CustomName", 8)) {
            this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"));
        }

        this.chestLock = ChestLock.b(nbttagcompound);
    }

    @Override
    public NBTTagCompound save(NBTTagCompound nbttagcompound) {
        super.save(nbttagcompound);
        nbttagcompound.setInt("Primary", MobEffectList.getId(this.primaryEffect));
        nbttagcompound.setInt("Secondary", MobEffectList.getId(this.secondaryEffect));
        nbttagcompound.setInt("Levels", this.levels);
        if (this.customName != null) {
            nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(this.customName));
        }

        this.chestLock.a(nbttagcompound);
        return nbttagcompound;
    }

    public void setCustomName(@Nullable IChatBaseComponent ichatbasecomponent) {
        this.customName = ichatbasecomponent;
    }

    @Nullable
    @Override
    public Container createMenu(int i, PlayerInventory playerinventory, EntityHuman entityhuman) {
        return TileEntityContainer.a(entityhuman, this.chestLock, this.getScoreboardDisplayName()) ? new ContainerBeacon(i, playerinventory, this.containerProperties, ContainerAccess.at(this.world, this.getPosition())) : null;
    }

    @Override
    public IChatBaseComponent getScoreboardDisplayName() {
        return (IChatBaseComponent) (this.customName != null ? this.customName : new ChatMessage("container.beacon", new Object[0]));
    }

    public static class BeaconColorTracker {

        private final float[] a;
        private int b;

        public BeaconColorTracker(float[] afloat) {
            this.a = afloat;
            this.b = 1;
        }

        protected void a() {
            ++this.b;
        }
    }
}