package net.minecraft.server; import javax.annotation.Nullable; // CraftBukkit start import org.bukkit.event.entity.SlimeSplitEvent; // CraftBukkit end public class EntitySlime extends EntityInsentient implements IMonster { private static final DataWatcherObject<Integer> bu = DataWatcher.a(EntitySlime.class, DataWatcherRegistry.b); public float a; public float b; public float c; private boolean bv; public EntitySlime(World world) { super(world); this.moveController = new EntitySlime.ControllerMoveSlime(this); } @Override protected void r() { this.goalSelector.a(1, new EntitySlime.PathfinderGoalSlimeRandomJump(this)); this.goalSelector.a(2, new EntitySlime.PathfinderGoalSlimeNearestPlayer(this)); this.goalSelector.a(3, new EntitySlime.PathfinderGoalSlimeRandomDirection(this)); this.goalSelector.a(5, new EntitySlime.PathfinderGoalSlimeIdle(this)); this.targetSelector.a(1, new PathfinderGoalTargetNearestPlayer(this)); this.targetSelector.a(3, new PathfinderGoalNearestAttackableTargetInsentient(this, EntityIronGolem.class)); } @Override protected void i() { super.i(); this.datawatcher.register(EntitySlime.bu, Integer.valueOf(1)); } public void setSize(int i, boolean flag) { this.datawatcher.set(EntitySlime.bu, Integer.valueOf(i)); this.setSize(0.51000005F * i, 0.51000005F * i); this.setPosition(this.locX, this.locY, this.locZ); this.getAttributeInstance(GenericAttributes.maxHealth).setValue(i * i); this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.2F + 0.1F * i); if (flag) { this.setHealth(this.getMaxHealth()); } this.b_ = i; } public int getSize() { return this.datawatcher.get(EntitySlime.bu).intValue(); } public static void c(DataConverterManager dataconvertermanager) { EntityInsentient.a(dataconvertermanager, EntitySlime.class); } @Override public void b(NBTTagCompound nbttagcompound) { super.b(nbttagcompound); nbttagcompound.setInt("Size", this.getSize() - 1); nbttagcompound.setBoolean("wasOnGround", this.bv); } @Override public void a(NBTTagCompound nbttagcompound) { super.a(nbttagcompound); int i = nbttagcompound.getInt("Size"); if (i < 0) { i = 0; } this.setSize(i + 1, false); this.bv = nbttagcompound.getBoolean("wasOnGround"); } public boolean di() { return this.getSize() <= 1; } protected EnumParticle o() { return EnumParticle.SLIME; } @Override public void A_() { if (!this.world.isClientSide && this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.getSize() > 0) { this.dead = true; } this.b += (this.a - this.b) * 0.5F; this.c = this.b; super.A_(); if (this.onGround && !this.bv) { int i = this.getSize(); for (int j = 0; j < i * 8; ++j) { float f = this.random.nextFloat() * 6.2831855F; float f1 = this.random.nextFloat() * 0.5F + 0.5F; float f2 = MathHelper.sin(f) * i * 0.5F * f1; float f3 = MathHelper.cos(f) * i * 0.5F * f1; World world = this.world; EnumParticle enumparticle = this.o(); double d0 = this.locX + f2; double d1 = this.locZ + f3; world.addParticle(enumparticle, d0, this.getBoundingBox().b, d1, 0.0D, 0.0D, 0.0D, new int[0]); } this.a(this.df(), this.ci(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) / 0.8F); this.a = -0.5F; } else if (!this.onGround && this.bv) { this.a = 1.0F; } this.bv = this.onGround; this.dc(); } protected void dc() { this.a *= 0.6F; } protected int db() { return this.random.nextInt(20) + 10; } protected EntitySlime da() { return new EntitySlime(this.world); } @Override public void a(DataWatcherObject<?> datawatcherobject) { if (EntitySlime.bu.equals(datawatcherobject)) { int i = this.getSize(); this.setSize(0.51000005F * i, 0.51000005F * i); this.yaw = this.aP; this.aN = this.aP; if (this.isInWater() && this.random.nextInt(20) == 0) { this.al(); } } super.a(datawatcherobject); } @Override public void die() { int i = this.getSize(); if (!this.world.isClientSide && i > 1 && this.getHealth() <= 0.0F) { int j = 2 + this.random.nextInt(3); // CraftBukkit start SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), j); this.world.getServer().getPluginManager().callEvent(event); if (!event.isCancelled() && event.getCount() > 0) { j = event.getCount(); } else { super.die(); return; } // CraftBukkit end for (int k = 0; k < j; ++k) { float f = (k % 2 - 0.5F) * i / 4.0F; float f1 = (k / 2 - 0.5F) * i / 4.0F; EntitySlime entityslime = this.da(); if (this.hasCustomName()) { entityslime.setCustomName(this.getCustomName()); } if (this.isPersistent()) { entityslime.cS(); } entityslime.setSize(i / 2, true); entityslime.setPositionRotation(this.locX + f, this.locY + 0.5D, this.locZ + f1, this.random.nextFloat() * 360.0F, 0.0F); this.world.addEntity(entityslime, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason } } super.die(); } @Override public void collide(Entity entity) { super.collide(entity); if (entity instanceof EntityIronGolem && this.dd()) { this.e((EntityLiving) entity); } } @Override public void d(EntityHuman entityhuman) { if (this.dd()) { this.e(entityhuman); } } protected void e(EntityLiving entityliving) { int i = this.getSize(); if (this.hasLineOfSight(entityliving) && this.h(entityliving) < 0.6D * i * 0.6D * i && entityliving.damageEntity(DamageSource.mobAttack(this), this.de())) { this.a(SoundEffects.fX, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); this.a(this, entityliving); } } @Override public float getHeadHeight() { return 0.625F * this.length; } protected boolean dd() { return !this.di(); } protected int de() { return this.getSize(); } @Override protected SoundEffect bW() { return this.di() ? SoundEffects.gl : SoundEffects.gc; } @Override protected SoundEffect bX() { return this.di() ? SoundEffects.gk : SoundEffects.fZ; } protected SoundEffect df() { return this.di() ? SoundEffects.gn : SoundEffects.gf; } @Override protected Item getLoot() { return this.getSize() == 1 ? Items.SLIME : null; } @Override @Nullable protected MinecraftKey J() { return this.getSize() == 1 ? LootTables.ah : LootTables.a; } @Override public boolean cM() { BlockPosition blockposition = new BlockPosition(MathHelper.floor(this.locX), 0, MathHelper.floor(this.locZ)); Chunk chunk = this.world.getChunkAtWorldCoords(blockposition); if (this.world.getWorldData().getType() == WorldType.FLAT && this.random.nextInt(4) != 1) { return false; } else { if (this.world.getDifficulty() != EnumDifficulty.PEACEFUL) { BiomeBase biomebase = this.world.getBiome(blockposition); if (biomebase == Biomes.h && this.locY > 50.0D && this.locY < 70.0D && this.random.nextFloat() < 0.5F && this.random.nextFloat() < this.world.E() && this.world.getLightLevel(new BlockPosition(this)) <= this.random.nextInt(8)) { return super.cM(); } boolean isSlimeChunk = world.paperConfig.allChunksAreSlimeChunks || chunk.a(world.spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper if (this.random.nextInt(10) == 0 && isSlimeChunk && this.locY < 40.0D) { // Paper return super.cM(); } } return false; } } @Override protected float ci() { return 0.4F * this.getSize(); } @Override public int N() { return 0; } protected boolean dj() { return this.getSize() > 0; } @Override protected void cm() { this.motY = 0.41999998688697815D; this.impulse = true; } @Override @Nullable public GroupDataEntity prepare(DifficultyDamageScaler difficultydamagescaler, @Nullable GroupDataEntity groupdataentity) { int i = this.random.nextInt(3); if (i < 2 && this.random.nextFloat() < 0.5F * difficultydamagescaler.d()) { ++i; } int j = 1 << i; this.setSize(j, true); return super.prepare(difficultydamagescaler, groupdataentity); } protected SoundEffect dg() { return this.di() ? SoundEffects.gm : SoundEffects.gd; } static class PathfinderGoalSlimeIdle extends PathfinderGoal { private final EntitySlime a; public PathfinderGoalSlimeIdle(EntitySlime entityslime) { this.a = entityslime; this.a(5); } @Override public boolean a() { return true; } @Override public void e() { ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(1.0D); } } static class PathfinderGoalSlimeRandomJump extends PathfinderGoal { private final EntitySlime a; public PathfinderGoalSlimeRandomJump(EntitySlime entityslime) { this.a = entityslime; this.a(5); ((Navigation) entityslime.getNavigation()).c(true); } @Override public boolean a() { return this.a.isInWater() || this.a.ao(); } @Override public void e() { if (this.a.getRandom().nextFloat() < 0.8F) { this.a.getControllerJump().a(); } ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(1.2D); } } static class PathfinderGoalSlimeRandomDirection extends PathfinderGoal { private final EntitySlime a; private float b; private int c; public PathfinderGoalSlimeRandomDirection(EntitySlime entityslime) { this.a = entityslime; this.a(2); } @Override public boolean a() { return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.ao() || this.a.hasEffect(MobEffects.LEVITATION)); } @Override public void e() { if (--this.c <= 0) { this.c = 40 + this.a.getRandom().nextInt(60); this.b = this.a.getRandom().nextInt(360); } ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.b, false); } } static class PathfinderGoalSlimeNearestPlayer extends PathfinderGoal { private final EntitySlime a; private int b; public PathfinderGoalSlimeNearestPlayer(EntitySlime entityslime) { this.a = entityslime; this.a(2); } @Override public boolean a() { EntityLiving entityliving = this.a.getGoalTarget(); return entityliving == null ? false : (!entityliving.isAlive() ? false : !(entityliving instanceof EntityHuman) || !((EntityHuman) entityliving).abilities.isInvulnerable); } @Override public void c() { this.b = 300; super.c(); } @Override public boolean b() { EntityLiving entityliving = this.a.getGoalTarget(); return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : --this.b > 0)); } @Override public void e() { this.a.a(this.a.getGoalTarget(), 10.0F, 10.0F); ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.a.yaw, this.a.dd()); } } static class ControllerMoveSlime extends ControllerMove { private float i; private int j; private final EntitySlime k; private boolean l; public ControllerMoveSlime(EntitySlime entityslime) { super(entityslime); this.k = entityslime; this.i = 180.0F * entityslime.yaw / 3.1415927F; } public void a(float f, boolean flag) { this.i = f; this.l = flag; } public void a(double d0) { this.e = d0; this.h = ControllerMove.Operation.MOVE_TO; } @Override public void c() { this.a.yaw = this.a(this.a.yaw, this.i, 90.0F); this.a.aP = this.a.yaw; this.a.aN = this.a.yaw; if (this.h != ControllerMove.Operation.MOVE_TO) { this.a.o(0.0F); } else { this.h = ControllerMove.Operation.WAIT; if (this.a.onGround) { this.a.l((float) (this.e * this.a.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue())); if (this.j-- <= 0) { this.j = this.k.db(); if (this.l) { this.j /= 3; } this.k.getControllerJump().a(); if (this.k.dj()) { this.k.a(this.k.dg(), this.k.ci(), ((this.k.getRandom().nextFloat() - this.k.getRandom().nextFloat()) * 0.2F + 1.0F) * 0.8F); } } else { this.k.be = 0.0F; this.k.bf = 0.0F; this.a.l(0.0F); } } else { this.a.l((float) (this.e * this.a.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue())); } } } } }