aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch853
1 files changed, 853 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch
new file mode 100644
index 0000000000..109f273887
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch
@@ -0,0 +1,853 @@
+--- a/net/minecraft/world/entity/monster/Shulker.java
++++ b/net/minecraft/world/entity/monster/Shulker.java
+@@ -1,6 +1,8 @@
+ package net.minecraft.world.entity.monster;
+
+ import java.util.EnumSet;
++import java.util.Iterator;
++import java.util.List;
+ import java.util.Optional;
+ import java.util.UUID;
+ import javax.annotation.Nullable;
+@@ -23,14 +25,14 @@
+ import net.minecraft.world.damagesource.DamageSource;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.EntityDimensions;
++import net.minecraft.world.entity.EntityPose;
+ import net.minecraft.world.entity.EntitySelector;
+ import net.minecraft.world.entity.EntityType;
++import net.minecraft.world.entity.EnumMobSpawn;
++import net.minecraft.world.entity.EnumMoveType;
++import net.minecraft.world.entity.GroupDataEntity;
+ import net.minecraft.world.entity.LivingEntity;
+ import net.minecraft.world.entity.Mob;
+-import net.minecraft.world.entity.MobSpawnType;
+-import net.minecraft.world.entity.MoverType;
+-import net.minecraft.world.entity.Pose;
+-import net.minecraft.world.entity.SpawnGroupData;
+ import net.minecraft.world.entity.VariantHolder;
+ import net.minecraft.world.entity.ai.attributes.AttributeModifier;
+ import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
+@@ -50,20 +52,26 @@
+ import net.minecraft.world.level.Level;
+ import net.minecraft.world.level.ServerLevelAccessor;
+ import net.minecraft.world.level.block.Blocks;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
++import net.minecraft.world.level.entity.EntityTypeTest;
+ import net.minecraft.world.level.gameevent.GameEvent;
+ import net.minecraft.world.phys.AABB;
+ import net.minecraft.world.phys.Vec3;
+ import org.joml.Vector3f;
+
+-public class Shulker extends AbstractGolem implements VariantHolder<Optional<DyeColor>>, Enemy {
++// CraftBukkit start
++import org.bukkit.craftbukkit.util.CraftLocation;
++import org.bukkit.event.entity.EntityTeleportEvent;
++import org.bukkit.craftbukkit.event.CraftEventFactory;
++// CraftBukkit end
++
++public class Shulker extends AbstractGolem implements VariantHolder<Optional<DyeColor>>, IMonster {
++
+ private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F");
+- private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(
+- COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0, AttributeModifier.Operation.ADDITION
+- );
++ private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(Shulker.COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0D, AttributeModifier.Operation.ADDITION);
+ protected static final EntityDataAccessor<Direction> DATA_ATTACH_FACE_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.DIRECTION);
+ protected static final EntityDataAccessor<Byte> DATA_PEEK_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE);
+- protected static final EntityDataAccessor<Byte> DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE);
++ public static final EntityDataAccessor<Byte> DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE);
+ private static final int TELEPORT_STEPS = 6;
+ private static final byte NO_COLOR = 16;
+ private static final byte DEFAULT_COLOR = 16;
+@@ -71,9 +79,10 @@
+ private static final int OTHER_SHULKER_SCAN_RADIUS = 8;
+ private static final int OTHER_SHULKER_LIMIT = 5;
+ private static final float PEEK_PER_TICK = 0.05F;
+- static final Vector3f FORWARD = Util.make(() -> {
+- Vec3i normal = Direction.SOUTH.getNormal();
+- return new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ());
++ static final Vector3f FORWARD = (Vector3f) Util.make(() -> {
++ Vec3i baseblockposition = Direction.SOUTH.getNormal();
++
++ return new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ());
+ });
+ private float currentPeekAmountO;
+ private float currentPeekAmount;
+@@ -94,7 +103,7 @@
+ this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal());
+ this.goalSelector.addGoal(7, new Shulker.ShulkerPeekGoal());
+ this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
+- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, this.getClass()).setAlertOthers());
++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{this.getClass()})).setAlertOthers());
+ this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this));
+ this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this));
+ }
+@@ -119,6 +128,7 @@
+ if (!this.isClosed()) {
+ super.playAmbientSound();
+ }
++
+ }
+
+ @Override
+@@ -134,13 +144,13 @@
+ @Override
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+- this.entityData.define(DATA_ATTACH_FACE_ID, Direction.DOWN);
+- this.entityData.define(DATA_PEEK_ID, (byte)0);
+- this.entityData.define(DATA_COLOR_ID, (byte)16);
++ this.entityData.define(Shulker.DATA_ATTACH_FACE_ID, Direction.DOWN);
++ this.entityData.define(Shulker.DATA_PEEK_ID, (byte) 0);
++ this.entityData.define(Shulker.DATA_COLOR_ID, (byte) 16);
+ }
+
+ public static AttributeSupplier.Builder createAttributes() {
+- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0);
++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D);
+ }
+
+ @Override
+@@ -152,18 +162,19 @@
+ public void readAdditionalSaveData(CompoundTag compound) {
+ super.readAdditionalSaveData(compound);
+ this.setAttachFace(Direction.from3DDataValue(compound.getByte("AttachFace")));
+- this.entityData.set(DATA_PEEK_ID, compound.getByte("Peek"));
++ this.entityData.set(Shulker.DATA_PEEK_ID, compound.getByte("Peek"));
+ if (compound.contains("Color", 99)) {
+- this.entityData.set(DATA_COLOR_ID, compound.getByte("Color"));
++ this.entityData.set(Shulker.DATA_COLOR_ID, compound.getByte("Color"));
+ }
++
+ }
+
+ @Override
+ public void addAdditionalSaveData(CompoundTag compound) {
+ super.addAdditionalSaveData(compound);
+- compound.putByte("AttachFace", (byte)this.getAttachFace().get3DDataValue());
+- compound.putByte("Peek", this.entityData.get(DATA_PEEK_ID));
+- compound.putByte("Color", this.entityData.get(DATA_COLOR_ID));
++ compound.putByte("AttachFace", (byte) this.getAttachFace().get3DDataValue());
++ compound.putByte("Peek", (Byte) this.entityData.get(Shulker.DATA_PEEK_ID));
++ compound.putByte("Color", (Byte) this.entityData.get(Shulker.DATA_COLOR_ID));
+ }
+
+ @Override
+@@ -179,37 +190,42 @@
+
+ if (this.level().isClientSide) {
+ if (this.clientSideTeleportInterpolation > 0) {
+- this.clientSideTeleportInterpolation--;
++ --this.clientSideTeleportInterpolation;
+ } else {
+ this.clientOldAttachPosition = null;
+ }
+ }
++
+ }
+
+ private void findNewAttachment() {
+- Direction direction = this.findAttachableSurface(this.blockPosition());
+- if (direction != null) {
+- this.setAttachFace(direction);
++ Direction enumdirection = this.findAttachableSurface(this.blockPosition());
++
++ if (enumdirection != null) {
++ this.setAttachFace(enumdirection);
+ } else {
+ this.teleportSomewhere();
+ }
++
+ }
+
+ @Override
+ protected AABB makeBoundingBox() {
+- float physicalPeek = getPhysicalPeek(this.currentPeekAmount);
+- Direction opposite = this.getAttachFace().getOpposite();
+- float f = this.getType().getWidth() / 2.0F;
+- return getProgressAabb(opposite, physicalPeek).move(this.getX() - (double)f, this.getY(), this.getZ() - (double)f);
++ float f = getPhysicalPeek(this.currentPeekAmount);
++ Direction enumdirection = this.getAttachFace().getOpposite();
++ float f1 = this.getType().getWidth() / 2.0F;
++
++ return getProgressAabb(enumdirection, f).move(this.getX() - (double) f1, this.getY(), this.getZ() - (double) f1);
+ }
+
+ private static float getPhysicalPeek(float peek) {
+- return 0.5F - Mth.sin((0.5F + peek) * (float) Math.PI) * 0.5F;
++ return 0.5F - Mth.sin((0.5F + peek) * 3.1415927F) * 0.5F;
+ }
+
+ private boolean updatePeekAmount() {
+ this.currentPeekAmountO = this.currentPeekAmount;
+- float f = (float)this.getRawPeekAmount() * 0.01F;
++ float f = (float) this.getRawPeekAmount() * 0.01F;
++
+ if (this.currentPeekAmount == f) {
+ return false;
+ } else {
+@@ -225,24 +241,25 @@
+
+ private void onPeekAmountChange() {
+ this.reapplyPosition();
+- float physicalPeek = getPhysicalPeek(this.currentPeekAmount);
+- float physicalPeek1 = getPhysicalPeek(this.currentPeekAmountO);
+- Direction opposite = this.getAttachFace().getOpposite();
+- float f = physicalPeek - physicalPeek1;
+- if (!(f <= 0.0F)) {
+- for (Entity entity : this.level()
+- .getEntities(
+- this,
+- getProgressDeltaAabb(opposite, physicalPeek1, physicalPeek).move(this.getX() - 0.5, this.getY(), this.getZ() - 0.5),
+- EntitySelector.NO_SPECTATORS.and(entity1 -> !entity1.isPassengerOfSameVehicle(this))
+- )) {
++ float f = getPhysicalPeek(this.currentPeekAmount);
++ float f1 = getPhysicalPeek(this.currentPeekAmountO);
++ Direction enumdirection = this.getAttachFace().getOpposite();
++ float f2 = f - f1;
++
++ if (f2 > 0.0F) {
++ List<Entity> list = this.level().getEntities((Entity) this, getProgressDeltaAabb(enumdirection, f1, f).move(this.getX() - 0.5D, this.getY(), this.getZ() - 0.5D), EntitySelector.NO_SPECTATORS.and((entity) -> {
++ return !entity.isPassengerOfSameVehicle(this);
++ }));
++ Iterator iterator = list.iterator();
++
++ while (iterator.hasNext()) {
++ Entity entity = (Entity) iterator.next();
++
+ if (!(entity instanceof Shulker) && !entity.noPhysics) {
+- entity.move(
+- MoverType.SHULKER,
+- new Vec3((double)(f * (float)opposite.getStepX()), (double)(f * (float)opposite.getStepY()), (double)(f * (float)opposite.getStepZ()))
+- );
++ entity.move(EnumMoveType.SHULKER, new Vec3((double) (f2 * (float) enumdirection.getStepX()), (double) (f2 * (float) enumdirection.getStepY()), (double) (f2 * (float) enumdirection.getStepZ())));
+ }
+ }
++
+ }
+ }
+
+@@ -251,11 +268,10 @@
+ }
+
+ public static AABB getProgressDeltaAabb(Direction direction, float delta, float deltaO) {
+- double d = (double)Math.max(delta, deltaO);
+- double d1 = (double)Math.min(delta, deltaO);
+- return new AABB(BlockPos.ZERO)
+- .expandTowards((double)direction.getStepX() * d, (double)direction.getStepY() * d, (double)direction.getStepZ() * d)
+- .contract((double)(-direction.getStepX()) * (1.0 + d1), (double)(-direction.getStepY()) * (1.0 + d1), (double)(-direction.getStepZ()) * (1.0 + d1));
++ double d0 = (double) Math.max(delta, deltaO);
++ double d1 = (double) Math.min(delta, deltaO);
++
++ return (new AABB(BlockPos.ZERO)).expandTowards((double) direction.getStepX() * d0, (double) direction.getStepY() * d0, (double) direction.getStepZ() * d0).contract((double) (-direction.getStepX()) * (1.0D + d1), (double) (-direction.getStepY()) * (1.0D + d1), (double) (-direction.getStepZ()) * (1.0D + d1));
+ }
+
+ @Override
+@@ -282,9 +298,7 @@
+
+ @Nullable
+ @Override
+- public SpawnGroupData finalizeSpawn(
+- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag
+- ) {
++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) {
+ this.setYRot(0.0F);
+ this.yHeadRot = this.getYRot();
+ this.setOldPosAndRot();
+@@ -292,12 +306,13 @@
+ }
+
+ @Override
+- public void move(MoverType type, Vec3 pos) {
+- if (type == MoverType.SHULKER_BOX) {
++ public void move(EnumMoveType type, Vec3 pos) {
++ if (type == EnumMoveType.SHULKER_BOX) {
+ this.teleportSomewhere();
+ } else {
+ super.move(type, pos);
+ }
++
+ }
+
+ @Override
+@@ -306,39 +321,46 @@
+ }
+
+ @Override
+- public void setDeltaMovement(Vec3 deltaMovement) {
+- }
++ public void setDeltaMovement(Vec3 deltaMovement) {}
+
+ @Override
+- public void setPos(double x, double y, double z) {
+- BlockPos blockPos = this.blockPosition();
++ public void setPos(double x, double d1, double y) {
++ BlockPos blockposition = this.blockPosition();
++
+ if (this.isPassenger()) {
+- super.setPos(x, y, z);
++ super.setPos(x, d1, y);
+ } else {
+- super.setPos((double)Mth.floor(x) + 0.5, (double)Mth.floor(y + 0.5), (double)Mth.floor(z) + 0.5);
++ super.setPos((double) Mth.floor(x) + 0.5D, (double) Mth.floor(d1 + 0.5D), (double) Mth.floor(y) + 0.5D);
+ }
+
+ if (this.tickCount != 0) {
+- BlockPos blockPos1 = this.blockPosition();
+- if (!blockPos1.equals(blockPos)) {
+- this.entityData.set(DATA_PEEK_ID, (byte)0);
++ BlockPos blockposition1 = this.blockPosition();
++
++ if (!blockposition1.equals(blockposition)) {
++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0);
+ this.hasImpulse = true;
+- if (this.level().isClientSide && !this.isPassenger() && !blockPos1.equals(this.clientOldAttachPosition)) {
+- this.clientOldAttachPosition = blockPos;
++ if (this.level().isClientSide && !this.isPassenger() && !blockposition1.equals(this.clientOldAttachPosition)) {
++ this.clientOldAttachPosition = blockposition;
+ this.clientSideTeleportInterpolation = 6;
+ this.xOld = this.getX();
+ this.yOld = this.getY();
+ this.zOld = this.getZ();
+ }
+ }
++
+ }
+ }
+
+ @Nullable
+ protected Direction findAttachableSurface(BlockPos pos) {
+- for (Direction direction : Direction.values()) {
+- if (this.canStayAt(pos, direction)) {
+- return direction;
++ Direction[] aenumdirection = Direction.values();
++ int i = aenumdirection.length;
++
++ for (int j = 0; j < i; ++j) {
++ Direction enumdirection = aenumdirection[j];
++
++ if (this.canStayAt(pos, enumdirection)) {
++ return enumdirection;
+ }
+ }
+
+@@ -349,49 +371,56 @@
+ if (this.isPositionBlocked(pos)) {
+ return false;
+ } else {
+- Direction opposite = facing.getOpposite();
+- if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, opposite)) {
++ Direction enumdirection1 = facing.getOpposite();
++
++ if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, enumdirection1)) {
+ return false;
+ } else {
+- AABB aABB = getProgressAabb(opposite, 1.0F).move(pos).deflate(1.0E-6);
+- return this.level().noCollision(this, aABB);
++ AABB axisalignedbb = getProgressAabb(enumdirection1, 1.0F).move(pos).deflate(1.0E-6D);
++
++ return this.level().noCollision(this, axisalignedbb);
+ }
+ }
+ }
+
+ private boolean isPositionBlocked(BlockPos pos) {
+- BlockState blockState = this.level().getBlockState(pos);
+- if (blockState.isAir()) {
++ IBlockData iblockdata = this.level().getBlockState(pos);
++
++ if (iblockdata.isAir()) {
+ return false;
+ } else {
+- boolean flag = blockState.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition());
++ boolean flag = iblockdata.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition());
++
+ return !flag;
+ }
+ }
+
+ protected boolean teleportSomewhere() {
+ if (!this.isNoAi() && this.isAlive()) {
+- BlockPos blockPos = this.blockPosition();
++ BlockPos blockposition = this.blockPosition();
+
+- for (int i = 0; i < 5; i++) {
+- BlockPos blockPos1 = blockPos.offset(
+- Mth.randomBetweenInclusive(this.random, -8, 8),
+- Mth.randomBetweenInclusive(this.random, -8, 8),
+- Mth.randomBetweenInclusive(this.random, -8, 8)
+- );
+- if (blockPos1.getY() > this.level().getMinBuildHeight()
+- && this.level().isEmptyBlock(blockPos1)
+- && this.level().getWorldBorder().isWithinBounds(blockPos1)
+- && this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) {
+- Direction direction = this.findAttachableSurface(blockPos1);
+- if (direction != null) {
++ for (int i = 0; i < 5; ++i) {
++ BlockPos blockposition1 = blockposition.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8));
++
++ if (blockposition1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockposition1) && this.level().getWorldBorder().isWithinBounds(blockposition1) && this.level().noCollision(this, (new AABB(blockposition1)).deflate(1.0E-6D))) {
++ Direction enumdirection = this.findAttachableSurface(blockposition1);
++
++ if (enumdirection != null) {
++ // CraftBukkit start
++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
++ if (teleportEvent.isCancelled()) {
++ return false;
++ } else {
++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo());
++ }
++ // CraftBukkit end
+ this.unRide();
+- this.setAttachFace(direction);
++ this.setAttachFace(enumdirection);
+ this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F);
+- this.setPos((double)blockPos1.getX() + 0.5, (double)blockPos1.getY(), (double)blockPos1.getZ() + 0.5);
+- this.level().gameEvent(GameEvent.TELEPORT, blockPos, GameEvent.Context.of(this));
+- this.entityData.set(DATA_PEEK_ID, (byte)0);
+- this.setTarget(null);
++ this.setPos((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D);
++ this.level().gameEvent(GameEvent.TELEPORT, blockposition, GameEvent.Context.of((Entity) this));
++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0);
++ this.setTarget((LivingEntity) null);
+ return true;
+ }
+ }
+@@ -404,17 +433,19 @@
+ }
+
+ @Override
+- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) {
++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) {
+ this.lerpSteps = 0;
+- this.setPos(d, d1, d2);
++ this.setPos(d0, d1, d2);
+ this.setRot(f, f1);
+ }
+
+ @Override
+ public boolean hurt(DamageSource source, float amount) {
++ Entity entity;
++
+ if (this.isClosed()) {
+- Entity directEntity = source.getDirectEntity();
+- if (directEntity instanceof AbstractArrow) {
++ entity = source.getDirectEntity();
++ if (entity instanceof AbstractArrow) {
+ return false;
+ }
+ }
+@@ -422,11 +453,11 @@
+ if (!super.hurt(source, amount)) {
+ return false;
+ } else {
+- if ((double)this.getHealth() < (double)this.getMaxHealth() * 0.5 && this.random.nextInt(4) == 0) {
++ if ((double) this.getHealth() < (double) this.getMaxHealth() * 0.5D && this.random.nextInt(4) == 0) {
+ this.teleportSomewhere();
+ } else if (source.is(DamageTypeTags.IS_PROJECTILE)) {
+- Entity directEntity = source.getDirectEntity();
+- if (directEntity != null && directEntity.getType() == EntityType.SHULKER_BULLET) {
++ entity = source.getDirectEntity();
++ if (entity != null && entity.getType() == EntityType.SHULKER_BULLET) {
+ this.hitByShulkerBullet();
+ }
+ }
+@@ -440,18 +471,22 @@
+ }
+
+ private void hitByShulkerBullet() {
+- Vec3 vec3 = this.position();
+- AABB boundingBox = this.getBoundingBox();
++ Vec3 vec3d = this.position();
++ AABB axisalignedbb = this.getBoundingBox();
++
+ if (!this.isClosed() && this.teleportSomewhere()) {
+- int size = this.level().getEntities(EntityType.SHULKER, boundingBox.inflate(8.0), Entity::isAlive).size();
+- float f = (float)(size - 1) / 5.0F;
+- if (!(this.level().random.nextFloat() < f)) {
+- Shulker shulker = EntityType.SHULKER.create(this.level());
+- if (shulker != null) {
+- shulker.setVariant(this.getVariant());
+- shulker.moveTo(vec3);
+- this.level().addFreshEntity(shulker);
++ int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, axisalignedbb.inflate(8.0D), Entity::isAlive).size();
++ float f = (float) (i - 1) / 5.0F;
++
++ if (this.level().random.nextFloat() >= f) {
++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(this.level());
++
++ if (entityshulker != null) {
++ entityshulker.setVariant(this.getVariant());
++ entityshulker.moveTo(vec3d);
++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life
+ }
++
+ }
+ }
+ }
+@@ -462,31 +497,31 @@
+ }
+
+ public Direction getAttachFace() {
+- return this.entityData.get(DATA_ATTACH_FACE_ID);
++ return (Direction) this.entityData.get(Shulker.DATA_ATTACH_FACE_ID);
+ }
+
+- private void setAttachFace(Direction attachFace) {
+- this.entityData.set(DATA_ATTACH_FACE_ID, attachFace);
++ public void setAttachFace(Direction attachFace) {
++ this.entityData.set(Shulker.DATA_ATTACH_FACE_ID, attachFace);
+ }
+
+ @Override
+ public void onSyncedDataUpdated(EntityDataAccessor<?> key) {
+- if (DATA_ATTACH_FACE_ID.equals(key)) {
++ if (Shulker.DATA_ATTACH_FACE_ID.equals(key)) {
+ this.setBoundingBox(this.makeBoundingBox());
+ }
+
+ super.onSyncedDataUpdated(key);
+ }
+
+- private int getRawPeekAmount() {
+- return this.entityData.get(DATA_PEEK_ID);
++ public int getRawPeekAmount() {
++ return (Byte) this.entityData.get(Shulker.DATA_PEEK_ID);
+ }
+
+- void setRawPeekAmount(int peekAmount) {
++ public void setRawPeekAmount(int peekAmount) {
+ if (!this.level().isClientSide) {
+- this.getAttribute(Attributes.ARMOR).removeModifier(COVERED_ARMOR_MODIFIER.getId());
++ this.getAttribute(Attributes.ARMOR).removeModifier(Shulker.COVERED_ARMOR_MODIFIER.getId());
+ if (peekAmount == 0) {
+- this.getAttribute(Attributes.ARMOR).addPermanentModifier(COVERED_ARMOR_MODIFIER);
++ this.getAttribute(Attributes.ARMOR).addPermanentModifier(Shulker.COVERED_ARMOR_MODIFIER);
+ this.playSound(SoundEvents.SHULKER_CLOSE, 1.0F, 1.0F);
+ this.gameEvent(GameEvent.CONTAINER_CLOSE);
+ } else {
+@@ -495,7 +530,7 @@
+ }
+ }
+
+- this.entityData.set(DATA_PEEK_ID, (byte)peekAmount);
++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) peekAmount);
+ }
+
+ public float getClientPeekAmount(float partialTick) {
+@@ -503,7 +538,7 @@
+ }
+
+ @Override
+- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) {
++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) {
+ return 0.5F;
+ }
+
+@@ -525,26 +560,28 @@
+ }
+
+ @Override
+- public void push(Entity entity) {
+- }
++ public void push(Entity entity) {}
+
+ public Optional<Vec3> getRenderPosition(float partial) {
+ if (this.clientOldAttachPosition != null && this.clientSideTeleportInterpolation > 0) {
+- double d = (double)((float)this.clientSideTeleportInterpolation - partial) / 6.0;
+- d *= d;
+- BlockPos blockPos = this.blockPosition();
+- double d1 = (double)(blockPos.getX() - this.clientOldAttachPosition.getX()) * d;
+- double d2 = (double)(blockPos.getY() - this.clientOldAttachPosition.getY()) * d;
+- double d3 = (double)(blockPos.getZ() - this.clientOldAttachPosition.getZ()) * d;
++ double d0 = (double) ((float) this.clientSideTeleportInterpolation - partial) / 6.0D;
++
++ d0 *= d0;
++ BlockPos blockposition = this.blockPosition();
++ double d1 = (double) (blockposition.getX() - this.clientOldAttachPosition.getX()) * d0;
++ double d2 = (double) (blockposition.getY() - this.clientOldAttachPosition.getY()) * d0;
++ double d3 = (double) (blockposition.getZ() - this.clientOldAttachPosition.getZ()) * d0;
++
+ return Optional.of(new Vec3(-d1, -d2, -d3));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+- @Override
+ public void setVariant(Optional<DyeColor> variant) {
+- this.entityData.set(DATA_COLOR_ID, variant.<Byte>map(color -> (byte)color.getId()).orElse((byte)16));
++ this.entityData.set(Shulker.DATA_COLOR_ID, (Byte) variant.map((enumcolor) -> {
++ return (byte) enumcolor.getId();
++ }).orElse((byte) 16));
+ }
+
+ @Override
+@@ -554,21 +591,57 @@
+
+ @Nullable
+ public DyeColor getColor() {
+- byte b = this.entityData.get(DATA_COLOR_ID);
+- return b != 16 && b <= 15 ? DyeColor.byId(b) : null;
++ byte b0 = (Byte) this.entityData.get(Shulker.DATA_COLOR_ID);
++
++ return b0 != 16 && b0 <= 15 ? DyeColor.byId(b0) : null;
+ }
+
+- class ShulkerAttackGoal extends Goal {
++ private class ShulkerLookControl extends LookControl {
++
++ public ShulkerLookControl(Mob mob) {
++ super(mob);
++ }
++
++ @Override
++ protected void clampHeadRotationToBody() {}
++
++ @Override
++ protected Optional<Float> getYRotD() {
++ Direction enumdirection = Shulker.this.getAttachFace().getOpposite();
++ Vector3f vector3f = enumdirection.getRotation().transform(new Vector3f(Shulker.FORWARD));
++ Vec3i baseblockposition = enumdirection.getNormal();
++ Vector3f vector3f1 = new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ());
++
++ vector3f1.cross(vector3f);
++ double d0 = this.wantedX - this.mob.getX();
++ double d1 = this.wantedY - this.mob.getEyeY();
++ double d2 = this.wantedZ - this.mob.getZ();
++ Vector3f vector3f2 = new Vector3f((float) d0, (float) d1, (float) d2);
++ float f = vector3f1.dot(vector3f2);
++ float f1 = vector3f.dot(vector3f2);
++
++ return Math.abs(f) <= 1.0E-5F && Math.abs(f1) <= 1.0E-5F ? Optional.empty() : Optional.of((float) (Mth.atan2((double) (-f), (double) f1) * 57.2957763671875D));
++ }
++
++ @Override
++ protected Optional<Float> getXRotD() {
++ return Optional.of(0.0F);
++ }
++ }
++
++ private class ShulkerAttackGoal extends Goal {
++
+ private int attackTime;
+
+ public ShulkerAttackGoal() {
+- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK));
+ }
+
+ @Override
+ public boolean canUse() {
+- LivingEntity target = Shulker.this.getTarget();
+- return target != null && target.isAlive() && Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL;
++ LivingEntity entityliving = Shulker.this.getTarget();
++
++ return entityliving != null && entityliving.isAlive() ? Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL : false;
+ }
+
+ @Override
+@@ -590,22 +663,21 @@
+ @Override
+ public void tick() {
+ if (Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL) {
+- this.attackTime--;
+- LivingEntity target = Shulker.this.getTarget();
+- if (target != null) {
+- Shulker.this.getLookControl().setLookAt(target, 180.0F, 180.0F);
+- double d = Shulker.this.distanceToSqr(target);
+- if (d < 400.0) {
++ --this.attackTime;
++ LivingEntity entityliving = Shulker.this.getTarget();
++
++ if (entityliving != null) {
++ Shulker.this.getLookControl().setLookAt(entityliving, 180.0F, 180.0F);
++ double d0 = Shulker.this.distanceToSqr((Entity) entityliving);
++
++ if (d0 < 400.0D) {
+ if (this.attackTime <= 0) {
+ this.attackTime = 20 + Shulker.this.random.nextInt(10) * 20 / 2;
+- Shulker.this.level()
+- .addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, target, Shulker.this.getAttachFace().getAxis()));
+- Shulker.this.playSound(
+- SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F
+- );
++ Shulker.this.level().addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, entityliving, Shulker.this.getAttachFace().getAxis()));
++ Shulker.this.playSound(SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F);
+ }
+ } else {
+- Shulker.this.setTarget(null);
++ Shulker.this.setTarget((LivingEntity) null);
+ }
+
+ super.tick();
+@@ -614,126 +686,89 @@
+ }
+ }
+
+- static class ShulkerBodyRotationControl extends BodyRotationControl {
+- public ShulkerBodyRotationControl(Mob mob) {
+- super(mob);
+- }
++ private class ShulkerPeekGoal extends Goal {
+
+- @Override
+- public void clientTick() {
+- }
+- }
++ private int peekTime;
+
+- static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal<LivingEntity> {
+- public ShulkerDefenseAttackGoal(Shulker shulker) {
+- super(shulker, LivingEntity.class, 10, true, false, entity -> entity instanceof Enemy);
+- }
++ ShulkerPeekGoal() {}
+
+ @Override
+ public boolean canUse() {
+- return this.mob.getTeam() != null && super.canUse();
++ return Shulker.this.getTarget() == null && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace());
+ }
+
+ @Override
+- protected AABB getTargetSearchArea(double targetDistance) {
+- Direction attachFace = ((Shulker)this.mob).getAttachFace();
+- if (attachFace.getAxis() == Direction.Axis.X) {
+- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance);
+- } else {
+- return attachFace.getAxis() == Direction.Axis.Z
+- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0)
+- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance);
+- }
++ public boolean canContinueToUse() {
++ return Shulker.this.getTarget() == null && this.peekTime > 0;
+ }
+- }
+
+- class ShulkerLookControl extends LookControl {
+- public ShulkerLookControl(Mob mob) {
+- super(mob);
+- }
+-
+ @Override
+- protected void clampHeadRotationToBody() {
++ public void start() {
++ this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3)));
++ Shulker.this.setRawPeekAmount(30);
+ }
+
+ @Override
+- protected Optional<Float> getYRotD() {
+- Direction opposite = Shulker.this.getAttachFace().getOpposite();
+- Vector3f vector3f = opposite.getRotation().transform(new Vector3f(Shulker.FORWARD));
+- Vec3i normal = opposite.getNormal();
+- Vector3f vector3f1 = new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ());
+- vector3f1.cross(vector3f);
+- double d = this.wantedX - this.mob.getX();
+- double d1 = this.wantedY - this.mob.getEyeY();
+- double d2 = this.wantedZ - this.mob.getZ();
+- Vector3f vector3f2 = new Vector3f((float)d, (float)d1, (float)d2);
+- float f = vector3f1.dot(vector3f2);
+- float f1 = vector3f.dot(vector3f2);
+- return !(Math.abs(f) > 1.0E-5F) && !(Math.abs(f1) > 1.0E-5F)
+- ? Optional.empty()
+- : Optional.of((float)(Mth.atan2((double)(-f), (double)f1) * 180.0F / (float)Math.PI));
++ public void stop() {
++ if (Shulker.this.getTarget() == null) {
++ Shulker.this.setRawPeekAmount(0);
++ }
++
+ }
+
+ @Override
+- protected Optional<Float> getXRotD() {
+- return Optional.of(0.0F);
++ public void tick() {
++ --this.peekTime;
+ }
+ }
+
+- class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal<Player> {
+- public ShulkerNearestAttackGoal(Shulker shulker) {
+- super(shulker, Player.class, true);
++ private class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal<Player> {
++
++ public ShulkerNearestAttackGoal(Shulker entityshulker) {
++ super(entityshulker, Player.class, true);
+ }
+
+ @Override
+ public boolean canUse() {
+- return Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL && super.canUse();
++ return Shulker.this.level().getDifficulty() == Difficulty.PEACEFUL ? false : super.canUse();
+ }
+
+ @Override
+ protected AABB getTargetSearchArea(double targetDistance) {
+- Direction attachFace = ((Shulker)this.mob).getAttachFace();
+- if (attachFace.getAxis() == Direction.Axis.X) {
+- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance);
+- } else {
+- return attachFace.getAxis() == Direction.Axis.Z
+- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0)
+- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance);
+- }
++ Direction enumdirection = ((Shulker) this.mob).getAttachFace();
++
++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance));
+ }
+ }
+
+- class ShulkerPeekGoal extends Goal {
+- private int peekTime;
++ private static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal<LivingEntity> {
+
+- @Override
+- public boolean canUse() {
+- return Shulker.this.getTarget() == null
+- && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0
+- && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace());
++ public ShulkerDefenseAttackGoal(Shulker shulker) {
++ super(shulker, LivingEntity.class, 10, true, false, (entityliving) -> {
++ return entityliving instanceof IMonster;
++ });
+ }
+
+ @Override
+- public boolean canContinueToUse() {
+- return Shulker.this.getTarget() == null && this.peekTime > 0;
++ public boolean canUse() {
++ return this.mob.getTeam() == null ? false : super.canUse();
+ }
+
+ @Override
+- public void start() {
+- this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3)));
+- Shulker.this.setRawPeekAmount(30);
++ protected AABB getTargetSearchArea(double targetDistance) {
++ Direction enumdirection = ((Shulker) this.mob).getAttachFace();
++
++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance));
+ }
++ }
+
+- @Override
+- public void stop() {
+- if (Shulker.this.getTarget() == null) {
+- Shulker.this.setRawPeekAmount(0);
+- }
++ private static class ShulkerBodyRotationControl extends BodyRotationControl {
++
++ public ShulkerBodyRotationControl(Mob mob) {
++ super(mob);
+ }
+
+ @Override
+- public void tick() {
+- this.peekTime--;
+- }
++ public void clientTick() {}
+ }
+ }