Yatopia/patches/Purpur/patches/server/0102-Ridables.patch

6934 lines
314 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 5 Jul 2020 22:19:49 -0500
Subject: [PATCH] Ridables
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index cdddae4ff5178112d4523079144803f2694267d5..f6637353fb358e7720edabc355ea036d37d039ca 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1540,6 +1540,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
WorldServer worldserver = (WorldServer) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ worldserver.hasRidableMoveEvent = net.pl3x.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur
TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
this.methodProfiler.a(() -> {
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java
new file mode 100644
index 0000000000000000000000000000000000000000..70961ec1d385dfd7c17fed6f33e4eb7fd57bc34a
--- /dev/null
+++ b/src/main/java/net/minecraft/server/PathfinderGoalHasRider.java
@@ -0,0 +1,21 @@
+package net.minecraft.server;
+
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.ai.goal.PathfinderGoal;
+
+import java.util.EnumSet;
+
+public class PathfinderGoalHasRider extends PathfinderGoal {
+ public final EntityInsentient entity;
+
+ public PathfinderGoalHasRider(EntityInsentient entity) {
+ this.entity = entity;
+ setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET, Type.UNKNOWN_BEHAVIOR));
+ }
+
+ // shouldExecute
+ @Override
+ public boolean a() {
+ return entity.hasRider();
+ }
+}
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b66d1215a6eef1302b5ecb46a4b3d502846fef8
--- /dev/null
+++ b/src/main/java/net/minecraft/server/PathfinderGoalHorseHasRider.java
@@ -0,0 +1,18 @@
+package net.minecraft.server;
+
+import net.minecraft.world.entity.animal.horse.EntityHorseAbstract;
+
+public class PathfinderGoalHorseHasRider extends PathfinderGoalHasRider {
+ private final EntityHorseAbstract horse;
+
+ public PathfinderGoalHorseHasRider(EntityHorseAbstract entity) {
+ super(entity);
+ this.horse = entity;
+ }
+
+ // shouldExecute
+ @Override
+ public boolean a() {
+ return super.a() && horse.hasSaddle();
+ }
+}
diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java
index 8e76c11e6bec5357322ea906af9e30f71e5718be..86bd39af6e3240b82f5afd6e7c554471f7bbd6ba 100644
--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java
@@ -643,6 +643,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
}
this.advancementDataPlayer.b(this);
+
+ // Purpur start
+ if (this.world.purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && world.getTime() % 100 == 0) { // 5 seconds
+ MobEffect nightVision = this.getEffect(MobEffects.NIGHT_VISION);
+ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds
+ this.addEffect(new MobEffect(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds
+ }
+ }
+ // Purpur end
}
public void playerTick() {
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index 50fac6013f14ddd427f51ba78ecf101df43f5b4a..8d1debb8152176581041a14e28cfcca8f92ae261 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -216,6 +216,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public final UUID uuid;
public boolean hasPhysicsEvent = true; // Paper
public boolean hasEntityMoveEvent = false; // Paper
+ public boolean hasRidableMoveEvent = false; // Purpur
private static Throwable getAddToWorldStackTrace(Entity entity) {
return new Throwable(entity + " Added to world at " + new java.util.Date());
}
diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java
index 77e7f3f33b13050ff383458ae294906c5ff77476..cbd8b1b98256847795aca1a7b08f7eb3f9e232a7 100644
--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java
@@ -2466,6 +2466,8 @@ public class PlayerConnection implements PacketListenerPlayIn {
}
this.server.getPluginManager().callEvent(event);
+ player.processClick(enumhand); // Purpur
+
// Fish bucket - SPIGOT-4048
if ((entity instanceof EntityFish && origItem != null && origItem.getItem() == Items.WATER_BUCKET) && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) {
this.sendPacket(new PacketPlayOutSpawnEntityLiving((EntityFish) entity));
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index 6ba14f603b8ec69597c70677cc317f802d6afae9..24fd920394774bf38d2818a4cd013670f7b20ba9 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -67,6 +67,7 @@ public class DamageSource {
return new EntityDamageSource("mob", entityliving);
}
+ public static DamageSource indirectMobAttack(Entity entity, EntityLiving entityliving) { return a(entity, entityliving); } // Purpur - OBFHELPER
public static DamageSource a(Entity entity, EntityLiving entityliving) {
return new EntityDamageSourceIndirect("mob", entity, entityliving);
}
@@ -128,6 +129,7 @@ public class DamageSource {
return this.B;
}
+ public DamageSource setProjectile() { return c(); } // Purpur - OBFHELPER
public DamageSource c() {
this.B = true;
return this;
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 240f30f6ca6007ba8e7de1c3e033b2a8493838e7..d1bbf4127a2e0836bedb33a81e3fd18a8e8eb962 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -22,6 +22,7 @@ import net.minecraft.BlockUtil;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportSystemDetails;
import net.minecraft.ReportedException;
+import net.minecraft.SystemUtils;
import net.minecraft.advancements.CriterionTriggers;
import net.minecraft.commands.CommandListenerWrapper;
import net.minecraft.commands.ICommandListener;
@@ -197,7 +198,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
private int id;
public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER
public final List<Entity> passengers;
- protected int j;
+ protected int j; public int getRideCooldown() { return j; } // Purpur - OBFHELPER
@Nullable
private Entity vehicle;
public boolean attachedToPlayer;
@@ -213,7 +214,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
public float lastYaw;
public float lastPitch;
private AxisAlignedBB boundingBox;
- protected boolean onGround;
+ public boolean onGround; // Purpur - protected -> public
public boolean positionChanged;
public boolean v;
public boolean velocityChanged;
@@ -269,7 +270,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
private boolean az;
private final double[] aA;
private long aB;
- private EntitySize size;
+ protected EntitySize size; // Purpur - private -> protected
private float headHeight;
// CraftBukkit start
public boolean persist = true;
@@ -1590,6 +1591,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D;
}
+ public void moveRelative(float speed, Vec3D motion) { this.a(speed, motion); } // Purpur - OBFHELPER
public void a(float f, Vec3D vec3d) {
Vec3D vec3d1 = a(vec3d, f, this.yaw);
@@ -2346,6 +2348,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
return this.a(entity, false);
}
+ public boolean startRiding(Entity entity, boolean flag) { return a(entity, flag); } // Purpur - OBFHELPER
public boolean a(Entity entity, boolean flag) {
for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) {
if (entity1.vehicle == this) {
@@ -2441,6 +2444,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
this.passengers.add(entity);
}
+ // Purpur start
+ if (isRidable() && passengers.get(0) == entity && entity instanceof EntityHuman) {
+ EntityHuman entityhuman = (EntityHuman) entity;
+ onMount(entityhuman);
+ this.rider = entityhuman;
+ }
+ // Purpur end
}
return true; // CraftBukkit
}
@@ -2481,6 +2491,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
return false;
}
// Spigot end
+ // Purpur start
+ if (rider != null && passengers.get(0) == rider) {
+ onDismount(rider);
+ this.rider = null;
+ }
+ // Purpur end
this.passengers.remove(entity);
entity.j = 60;
}
@@ -2646,6 +2662,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
this.setFlag(4, flag);
}
+ public boolean isGlowing() { return bE(); } // Purpur - OBFHELPER
public boolean bE() {
return this.glowing || this.world.isClientSide && this.getFlag(6);
}
@@ -2868,6 +2885,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
public void setHeadRotation(float f) {}
+ public void setBodyYaw(float yaw) { n(yaw); } // Purpur - OBFHELPER
public void n(float f) {}
public boolean bL() {
@@ -3309,6 +3327,18 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
return false;
}
+ // Purpur Start
+ public void sendMessage(String str) {
+ sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(str));
+ }
+
+ public void sendMessage(IChatBaseComponent ichatbasecomponent) {
+ if (ichatbasecomponent != null) {
+ sendMessage(ichatbasecomponent, SystemUtils.getNullUUID());
+ }
+ }
+ // Purpur end
+
@Override
public void sendMessage(IChatBaseComponent ichatbasecomponent, UUID uuid) {}
@@ -3761,4 +3791,47 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this);
}
// Paper end
+
+ // Purpur start
+ private EntityHuman rider;
+
+ public EntityHuman getRider() {
+ return rider;
+ }
+
+ public boolean hasRider() {
+ return rider != null;
+ }
+
+ public boolean isRidable() {
+ return false;
+ }
+
+ public boolean isRidableInWater() {
+ return false;
+ }
+
+ public void onMount(EntityHuman entityhuman) {
+ if (this instanceof EntityInsentient) {
+ ((EntityInsentient) this).setGoalTarget(null, null, false);
+ ((EntityInsentient) this).getNavigation().stopPathfinding();
+ }
+ entityhuman.setJumping(false); // fixes jump on mount
+ }
+
+ public void onDismount(EntityHuman entityhuman) {
+ }
+
+ public boolean onSpacebar() {
+ return false;
+ }
+
+ public boolean onClick(EnumHand hand) {
+ return false;
+ }
+
+ public boolean processClick(EnumHand hand) {
+ return false;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
index c9136f1b54ff0620a621b703b4e7487f4a63b01d..8b7f840bb1b24996b40c9bef85f4c1e98e39caec 100644
--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java
+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
@@ -100,7 +100,7 @@ public abstract class EntityInsentient extends EntityLiving {
protected int f;
protected ControllerLook lookController;
protected ControllerMove moveController;
- protected ControllerJump bi;
+ protected ControllerJump bi; public ControllerJump getJumpController() { return bi; } // Purpur - OBFHELPER
private final EntityAIBodyControl c;
protected NavigationAbstract navigation;
public PathfinderGoalSelector goalSelector;
@@ -138,8 +138,8 @@ public abstract class EntityInsentient extends EntityLiving {
this.bA = -1.0F;
this.goalSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier());
this.targetSelector = new PathfinderGoalSelector(world.getMethodProfilerSupplier());
- this.lookController = new ControllerLook(this);
- this.moveController = new ControllerMove(this);
+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this); // Purpur
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this); // Purpur
this.bi = new ControllerJump(this);
this.c = this.r();
this.navigation = this.b(world);
@@ -328,10 +328,10 @@ public abstract class EntityInsentient extends EntityLiving {
// Purpur start
private void incrementTicksSinceLastInteraction() {
++ticksSinceLastInteraction;
- //if (hasRider()) {
- // ticksSinceLastInteraction = 0;
- // return;
- //}
+ if (hasRider()) {
+ ticksSinceLastInteraction = 0;
+ return;
+ }
if (world.purpurConfig.entityLifeSpan <= 0) {
return; // feature disabled
}
@@ -626,14 +626,17 @@ public abstract class EntityInsentient extends EntityLiving {
return super.dp();
}
+ public void setForwardSpeed(float speed) { this.t(speed); } // Purpur - OBFHELPER
public void t(float f) {
this.aT = f;
}
+ public void setVerticalSpeed(float speed) { this.u(speed); } // Purpur - OBFHELPER
public void u(float f) {
this.aS = f;
}
+ public void setStrafeSpeed(float speed) { this.v(speed); } // Purpur - OBFHELPER
public void v(float f) {
this.aR = f;
}
@@ -1325,7 +1328,7 @@ public abstract class EntityInsentient extends EntityLiving {
protected void a(EntityHuman entityhuman, EntityInsentient entityinsentient) {}
protected EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
public boolean ev() {
@@ -1706,4 +1709,54 @@ public abstract class EntityInsentient extends EntityLiving {
this.unleash(true, event.isDropLeash());
// Paper end
}
+
+ // Purpur start
+ public double getMaxY() {
+ return world.getHeight();
+ }
+
+ public EnumInteractionResult tryRide(EntityHuman entityhuman, EnumHand enumhand) {
+ if (!isRidable()) {
+ return EnumInteractionResult.PASS;
+ }
+ if (enumhand != EnumHand.MAIN_HAND) {
+ return EnumInteractionResult.PASS;
+ }
+ if (entityhuman.isSneaking()) {
+ return EnumInteractionResult.PASS;
+ }
+ if (!entityhuman.getItemInHand(enumhand).isEmpty()) {
+ return EnumInteractionResult.PASS;
+ }
+ if (!passengers.isEmpty() || entityhuman.isPassenger()) {
+ return EnumInteractionResult.PASS;
+ }
+ if (this instanceof EntityTameableAnimal) {
+ EntityTameableAnimal tameable = (EntityTameableAnimal) this;
+ if (tameable.isTamed() && !tameable.isOwner(entityhuman)) {
+ return EnumInteractionResult.PASS;
+ }
+ if (!tameable.isTamed() && !world.purpurConfig.untamedTamablesAreRidable) {
+ return EnumInteractionResult.PASS;
+ }
+ }
+ if (this instanceof EntityAgeable) {
+ EntityAgeable ageable = (EntityAgeable) this;
+ if (ageable.isBaby() && !world.purpurConfig.babiesAreRidable) {
+ return EnumInteractionResult.PASS;
+ }
+ }
+ if (!entityhuman.getBukkitEntity().hasPermission("allow.ride." + getEntityType().getName())) {
+ entityhuman.sendMessage(net.pl3x.purpur.PurpurConfig.cannotRideMob);
+ return EnumInteractionResult.PASS;
+ }
+ entityhuman.yaw = this.yaw;
+ entityhuman.pitch = this.pitch;
+ if (entityhuman.startRiding(this)) {
+ return EnumInteractionResult.SUCCESS;
+ } else {
+ return EnumInteractionResult.PASS;
+ }
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
index 8930ab8a39c50eaa84372f0e8caf8b92789bb0c4..bcf1d77f627e800b9dbbfd7f9ed99887e2aca714 100644
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
@@ -559,7 +559,7 @@ public abstract class EntityLiving extends Entity {
@Override
public boolean bt() {
- return false;
+ return isRidableInWater(); // Purpur
}
protected void cU() {
@@ -2300,7 +2300,7 @@ public abstract class EntityLiving extends Entity {
return 0.42F * this.getBlockJumpFactor();
}
- protected void jump() {
+ public void jump() { // Purpur - protected -> public
float f = this.dJ();
if (this.hasEffect(MobEffects.JUMP)) {
@@ -2549,10 +2549,12 @@ public abstract class EntityLiving extends Entity {
return this.onGround ? this.dN() * (0.21600002F / (f * f * f)) : this.aE;
}
+ public float getSpeed() { return dN(); } // Purpur - OBFHELPER
public float dN() {
return this.bu;
}
+ public void setSpeed(float speed) { q(speed); } // Purpur - OBFHELPER
public void q(float f) {
this.bu = f;
}
@@ -2938,8 +2940,10 @@ public abstract class EntityLiving extends Entity {
this.collideNearby();
this.world.getMethodProfiler().exit();
// Paper start
- if (((WorldServer) world).hasEntityMoveEvent) {
- if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) {
+ // Purpur start
+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) {
+ if (((WorldServer) world).hasEntityMoveEvent) {
+ // Purpur end
Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch);
Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch);
EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone());
@@ -2949,6 +2953,21 @@ public abstract class EntityLiving extends Entity {
setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch());
}
}
+ // Purpur start
+ if (hasRider()) {
+ getRider().resetIdleTimer();
+ if (((WorldServer) world).hasRidableMoveEvent && this instanceof EntityInsentient) {
+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch);
+ Location to = new Location(world.getWorld(), locX(), locY(), locZ(), yaw, pitch);
+ net.pl3x.purpur.event.entity.RidableMoveEvent event = new net.pl3x.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getRider().getBukkitEntity(), from, to.clone());
+ if (!event.callEvent()) {
+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
+ } else if (!to.equals(event.getTo())) {
+ setLocation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
+ }
+ }
+ }
+ // Purpur end
}
// Paper end
if (!this.world.isClientSide && this.dO() && this.aG()) {
diff --git a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java
index 74636c4c0851da1cd5732daa0a2d1a4edda2050f..cdb56555889d17913d7b0c03d5ba23408a500f26 100644
--- a/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/EntityTameableAnimal.java
@@ -144,6 +144,7 @@ public abstract class EntityTameableAnimal extends EntityAnimal {
return this.i(entityliving) ? false : super.c(entityliving);
}
+ public boolean isOwner(EntityLiving entityLiving) { return i(entityLiving); } // Purpur - OBFHELPER
public boolean i(EntityLiving entityliving) {
return entityliving == this.getOwner();
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java
index 1b9cf77aa5d73b4834e5260a91d338620e0bb6b3..b6cc0e1286294e64568d11c452684071d4c5b636 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeDefaults.java
@@ -50,6 +50,7 @@ import net.minecraft.world.entity.monster.EntityGuardianElder;
import net.minecraft.world.entity.monster.EntityIllagerIllusioner;
import net.minecraft.world.entity.monster.EntityMagmaCube;
import net.minecraft.world.entity.monster.EntityMonster;
+import net.minecraft.world.entity.monster.EntityPhantom;
import net.minecraft.world.entity.monster.EntityPigZombie;
import net.minecraft.world.entity.monster.EntityPillager;
import net.minecraft.world.entity.monster.EntityRavager;
@@ -74,7 +75,80 @@ import org.apache.logging.log4j.Logger;
public class AttributeDefaults {
private static final Logger LOGGER = LogManager.getLogger();
- private static final Map<EntityTypes<? extends EntityLiving>, AttributeProvider> b = ImmutableMap.builder().put(EntityTypes.ARMOR_STAND, EntityLiving.cL().a()).put(EntityTypes.BAT, EntityBat.m().a()).put(EntityTypes.BEE, EntityBee.eZ().a()).put(EntityTypes.BLAZE, EntityBlaze.m().a()).put(EntityTypes.CAT, EntityCat.fa().a()).put(EntityTypes.CAVE_SPIDER, EntityCaveSpider.m().a()).put(EntityTypes.CHICKEN, EntityChicken.eK().a()).put(EntityTypes.COD, EntityFish.m().a()).put(EntityTypes.COW, EntityCow.eK().a()).put(EntityTypes.CREEPER, EntityCreeper.m().a()).put(EntityTypes.DOLPHIN, EntityDolphin.eM().a()).put(EntityTypes.DONKEY, EntityHorseChestedAbstract.eL().a()).put(EntityTypes.DROWNED, EntityZombie.eS().a()).put(EntityTypes.ELDER_GUARDIAN, EntityGuardianElder.m().a()).put(EntityTypes.ENDERMAN, EntityEnderman.m().a()).put(EntityTypes.ENDERMITE, EntityEndermite.m().a()).put(EntityTypes.ENDER_DRAGON, EntityEnderDragon.m().a()).put(EntityTypes.EVOKER, EntityEvoker.eK().a()).put(EntityTypes.FOX, EntityFox.eK().a()).put(EntityTypes.GHAST, EntityGhast.eJ().a()).put(EntityTypes.GIANT, EntityGiantZombie.m().a()).put(EntityTypes.GUARDIAN, EntityGuardian.eM().a()).put(EntityTypes.HOGLIN, EntityHoglin.eK().a()).put(EntityTypes.HORSE, EntityHorseAbstract.fi().a()).put(EntityTypes.HUSK, EntityZombie.eS().a()).put(EntityTypes.ILLUSIONER, EntityIllagerIllusioner.eK().a()).put(EntityTypes.IRON_GOLEM, EntityIronGolem.m().a()).put(EntityTypes.LLAMA, EntityLlama.fw().a()).put(EntityTypes.MAGMA_CUBE, EntityMagmaCube.m().a()).put(EntityTypes.MOOSHROOM, EntityCow.eK().a()).put(EntityTypes.MULE, EntityHorseChestedAbstract.eL().a()).put(EntityTypes.OCELOT, EntityOcelot.eK().a()).put(EntityTypes.PANDA, EntityPanda.eY().a()).put(EntityTypes.PARROT, EntityParrot.eU().a()).put(EntityTypes.PHANTOM, EntityMonster.eR().a()).put(EntityTypes.PIG, EntityPig.eK().a()).put(EntityTypes.PIGLIN, EntityPiglin.eT().a()).put(EntityTypes.PIGLIN_BRUTE, EntityPiglinBrute.eS().a()).put(EntityTypes.PILLAGER, EntityPillager.eK().a()).put(EntityTypes.PLAYER, EntityHuman.ep().a()).put(EntityTypes.POLAR_BEAR, EntityPolarBear.eK().a()).put(EntityTypes.PUFFERFISH, EntityFish.m().a()).put(EntityTypes.RABBIT, EntityRabbit.eL().a()).put(EntityTypes.RAVAGER, EntityRavager.m().a()).put(EntityTypes.SALMON, EntityFish.m().a()).put(EntityTypes.SHEEP, EntitySheep.eK().a()).put(EntityTypes.SHULKER, EntityShulker.m().a()).put(EntityTypes.SILVERFISH, EntitySilverfish.m().a()).put(EntityTypes.SKELETON, EntitySkeletonAbstract.m().a()).put(EntityTypes.SKELETON_HORSE, EntityHorseSkeleton.eL().a()).put(EntityTypes.SLIME, EntityMonster.eR().a()).put(EntityTypes.SNOW_GOLEM, EntitySnowman.m().a()).put(EntityTypes.SPIDER, EntitySpider.eK().a()).put(EntityTypes.SQUID, EntitySquid.m().a()).put(EntityTypes.STRAY, EntitySkeletonAbstract.m().a()).put(EntityTypes.STRIDER, EntityStrider.eM().a()).put(EntityTypes.TRADER_LLAMA, EntityLlama.fw().a()).put(EntityTypes.TROPICAL_FISH, EntityFish.m().a()).put(EntityTypes.TURTLE, EntityTurtle.eM().a()).put(EntityTypes.VEX, EntityVex.m().a()).put(EntityTypes.VILLAGER, EntityVillager.eY().a()).put(EntityTypes.VINDICATOR, EntityVindicator.eK().a()).put(EntityTypes.WANDERING_TRADER, EntityInsentient.p().a()).put(EntityTypes.WITCH, EntityWitch.eK().a()).put(EntityTypes.WITHER, EntityWither.eK().a()).put(EntityTypes.WITHER_SKELETON, EntitySkeletonAbstract.m().a()).put(EntityTypes.WOLF, EntityWolf.eU().a()).put(EntityTypes.ZOGLIN, EntityZoglin.m().a()).put(EntityTypes.ZOMBIE, EntityZombie.eS().a()).put(EntityTypes.ZOMBIE_HORSE, EntityHorseZombie.eL().a()).put(EntityTypes.ZOMBIE_VILLAGER, EntityZombie.eS().a()).put(EntityTypes.ZOMBIFIED_PIGLIN, EntityPigZombie.eW().a()).build();
+ private static final Map<EntityTypes<? extends EntityLiving>, AttributeProvider> b = ImmutableMap.<EntityTypes<? extends EntityLiving>, AttributeProvider>builder() // Purpur decompile error
+ .put(EntityTypes.ARMOR_STAND, EntityLiving.cL().a())
+ .put(EntityTypes.BAT, EntityBat.m().a())
+ .put(EntityTypes.BEE, EntityBee.eZ().a())
+ .put(EntityTypes.BLAZE, EntityBlaze.m().a())
+ .put(EntityTypes.CAT, EntityCat.fa().a())
+ .put(EntityTypes.CAVE_SPIDER, EntityCaveSpider.m().a())
+ .put(EntityTypes.CHICKEN, EntityChicken.eK().a())
+ .put(EntityTypes.COD, EntityFish.m().a())
+ .put(EntityTypes.COW, EntityCow.eK().a())
+ .put(EntityTypes.CREEPER, EntityCreeper.m().a())
+ .put(EntityTypes.DOLPHIN, EntityDolphin.eM().a())
+ .put(EntityTypes.DONKEY, EntityHorseChestedAbstract.eL().a())
+ .put(EntityTypes.DROWNED, EntityZombie.eS().a())
+ .put(EntityTypes.ELDER_GUARDIAN, EntityGuardianElder.m().a())
+ .put(EntityTypes.ENDERMAN, EntityEnderman.m().a())
+ .put(EntityTypes.ENDERMITE, EntityEndermite.m().a())
+ .put(EntityTypes.ENDER_DRAGON, EntityEnderDragon.m().a())
+ .put(EntityTypes.EVOKER, EntityEvoker.eK().a())
+ .put(EntityTypes.FOX, EntityFox.eK().a())
+ .put(EntityTypes.GHAST, EntityGhast.eJ().a())
+ .put(EntityTypes.GIANT, EntityGiantZombie.m().a())
+ .put(EntityTypes.GUARDIAN, EntityGuardian.eM().a())
+ .put(EntityTypes.HOGLIN, EntityHoglin.eK().a())
+ .put(EntityTypes.HORSE, EntityHorseAbstract.fi().a())
+ .put(EntityTypes.HUSK, EntityZombie.eS().a())
+ .put(EntityTypes.ILLUSIONER, EntityIllagerIllusioner.eK().a())
+ .put(EntityTypes.IRON_GOLEM, EntityIronGolem.m().a())
+ .put(EntityTypes.LLAMA, EntityLlama.fw().a())
+ .put(EntityTypes.MAGMA_CUBE, EntityMagmaCube.m().a())
+ .put(EntityTypes.MOOSHROOM, EntityCow.eK().a())
+ .put(EntityTypes.MULE, EntityHorseChestedAbstract.eL().a())
+ .put(EntityTypes.OCELOT, EntityOcelot.eK().a())
+ .put(EntityTypes.PANDA, EntityPanda.eY().a())
+ .put(EntityTypes.PARROT, EntityParrot.eU().a())
+ .put(EntityTypes.PHANTOM, EntityPhantom.defaultAttributes().build()) // Purpur
+ .put(EntityTypes.PIG, EntityPig.eK().a())
+ .put(EntityTypes.PIGLIN, EntityPiglin.eT().a())
+ .put(EntityTypes.PIGLIN_BRUTE, EntityPiglinBrute.eS().a())
+ .put(EntityTypes.PILLAGER, EntityPillager.eK().a())
+ .put(EntityTypes.PLAYER, EntityHuman.ep().a())
+ .put(EntityTypes.POLAR_BEAR, EntityPolarBear.eK().a())
+ .put(EntityTypes.PUFFERFISH, EntityFish.m().a())
+ .put(EntityTypes.RABBIT, EntityRabbit.eL().a())
+ .put(EntityTypes.RAVAGER, EntityRavager.m().a())
+ .put(EntityTypes.SALMON, EntityFish.m().a())
+ .put(EntityTypes.SHEEP, EntitySheep.eK().a())
+ .put(EntityTypes.SHULKER, EntityShulker.m().a())
+ .put(EntityTypes.SILVERFISH, EntitySilverfish.m().a())
+ .put(EntityTypes.SKELETON, EntitySkeletonAbstract.m().a())
+ .put(EntityTypes.SKELETON_HORSE, EntityHorseSkeleton.eL().a())
+ .put(EntityTypes.SLIME, EntityMonster.eR().a())
+ .put(EntityTypes.SNOW_GOLEM, EntitySnowman.m().a())
+ .put(EntityTypes.SPIDER, EntitySpider.eK().a())
+ .put(EntityTypes.SQUID, EntitySquid.m().a())
+ .put(EntityTypes.STRAY, EntitySkeletonAbstract.m().a())
+ .put(EntityTypes.STRIDER, EntityStrider.eM().a())
+ .put(EntityTypes.TRADER_LLAMA, EntityLlama.fw().a())
+ .put(EntityTypes.TROPICAL_FISH, EntityFish.m().a())
+ .put(EntityTypes.TURTLE, EntityTurtle.eM().a())
+ .put(EntityTypes.VEX, EntityVex.m().a())
+ .put(EntityTypes.VILLAGER, EntityVillager.eY().a())
+ .put(EntityTypes.VINDICATOR, EntityVindicator.eK().a())
+ .put(EntityTypes.WANDERING_TRADER, EntityInsentient.p().a())
+ .put(EntityTypes.WITCH, EntityWitch.eK().a())
+ .put(EntityTypes.WITHER, EntityWither.eK().a())
+ .put(EntityTypes.WITHER_SKELETON, EntitySkeletonAbstract.m().a())
+ .put(EntityTypes.WOLF, EntityWolf.eU().a())
+ .put(EntityTypes.ZOGLIN, EntityZoglin.m().a())
+ .put(EntityTypes.ZOMBIE, EntityZombie.eS().a())
+ .put(EntityTypes.ZOMBIE_HORSE, EntityHorseZombie.eL().a())
+ .put(EntityTypes.ZOMBIE_VILLAGER, EntityZombie.eS().a())
+ .put(EntityTypes.ZOMBIFIED_PIGLIN, EntityPigZombie.eW().a())
+ .build();
public static AttributeProvider a(EntityTypes<? extends EntityLiving> entitytypes) {
return (AttributeProvider) AttributeDefaults.b.get(entitytypes);
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java
index c75659d0f2a6a198f338c38b600e639a4cb3d9ee..5edad3ee07cc0357442ede3a1e14e8d5c121e530 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeProvider.java
@@ -102,6 +102,7 @@ public class AttributeProvider {
return this;
}
+ public AttributeProvider build() { return a(); } // Purpur - OBFHELPER
public AttributeProvider a() {
this.b = true;
return new AttributeProvider(this.a);
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java
index bf059f201c662d6492b093184e7feec711b846e8..1b472a659c140b368173237d54633f0dfbeb7419 100644
--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java
+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLookDolphin.java
@@ -3,7 +3,7 @@ package net.minecraft.world.entity.ai.control;
import net.minecraft.util.MathHelper;
import net.minecraft.world.entity.EntityInsentient;
-public class ControllerLookDolphin extends ControllerLook {
+public class ControllerLookDolphin extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur
private final int h;
@@ -13,7 +13,7 @@ public class ControllerLookDolphin extends ControllerLook {
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.d) {
this.d = false;
this.a.aC = this.a(this.a.aC, this.h() + 20.0F, this.b);
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java
index 2aa5789437ba7eb20579da238c407a65a25b1d44..434229b146978ba7dc08a83ea55fdb3ab743fbf8 100644
--- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java
+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java
@@ -20,9 +20,9 @@ public class ControllerMove {
protected double b;
protected double c;
protected double d;
- protected double e;
- protected float f;
- protected float g;
+ protected double e; public double getSpeed() { return e; } public void setSpeed(double speed) { this.e = speed; } // Purpur - OBFHELPER
+ protected float f; public float getForward() { return f; } public void setForward(float forward) { this.f = forward; } // Purpur - OBFHELPER
+ protected float g; public float getStrafe() { return g; } public void setStrafe(float strafe) { this.g = strafe; } // Purpur - OBFHELPER
protected ControllerMove.Operation h;
public ControllerMove(EntityInsentient entityinsentient) {
diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
index 61ebb278cf4ef57ae7a86c6c6ef1fa14559f21e2..ce40df98f61b9176989c0000d078597d44e996e2 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java
@@ -21,6 +21,7 @@ import net.minecraft.world.entity.EntityPose;
import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMobSpawn;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
@@ -40,9 +41,48 @@ public class EntityBat extends EntityAmbient {
public EntityBat(EntityTypes<? extends EntityBat> entitytypes, World world) {
super(entitytypes, world);
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.075F); // Purpur
this.setAsleep(true);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.batRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.batRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.batMaxY;
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ if (isAsleep()) {
+ setAsleep(false);
+ world.playEffect(null, 1025, new BlockPosition(this).up(), 0);
+ }
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2;
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+ // Purpur end
+
@Override
protected void initDatawatcher() {
super.initDatawatcher();
@@ -87,7 +127,7 @@ public class EntityBat extends EntityAmbient {
protected void collideNearby() {}
public static AttributeProvider.Builder m() {
- return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 6.0D);
+ return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 6.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur
}
public boolean isAsleep() {
@@ -119,6 +159,13 @@ public class EntityBat extends EntityAmbient {
@Override
protected void mobTick() {
+ // Purpur start
+ if (hasRider()) {
+ Vec3D mot = getMot();
+ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z);
+ return;
+ }
+ // Purpur end
super.mobTick();
BlockPosition blockposition = this.getChunkCoordinates();
BlockPosition blockposition1 = blockposition.up();
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java
index 1d1f71a995a99b2101891a7a5bda7bec5d67f118..0c6d3dae70eeea844a31f9edf54410db13e0b04b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java
@@ -22,6 +22,7 @@ import net.minecraft.network.protocol.game.PacketDebug;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -44,6 +45,7 @@ import net.minecraft.world.entity.EntityPose;
import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMonsterType;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.IEntityAngerable;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
@@ -111,6 +113,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
public EntityBee(EntityTypes<? extends EntityBee> entitytypes, World world) {
super(entitytypes, world);
+ final net.pl3x.purpur.controller.ControllerMoveWASDFlying flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this, 0.25F, false); // Purpur
// Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279
this.moveController = new ControllerMoveFlying(this, 20, true) {
@Override
@@ -120,6 +123,22 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
}
super.tick();
}
+
+ // Purpur start
+ @Override
+ public void a() { // tick
+ if (getEntity().hasRider()) {
+ flyingController.tick(getEntity().getRider());
+ } else {
+ tick();
+ }
+ }
+
+ @Override
+ public boolean b() { // isUpdating
+ return getEntity().hasRider() || super.b();
+ }
+ // Purpur end
};
// Paper end
this.lookController = new EntityBee.j(this);
@@ -130,6 +149,35 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
this.a(PathType.FENCE, -1.0F);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.beeRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.beeRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.beeMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2;
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, speed, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+ // Purpur end
+
@Override
protected void initDatawatcher() {
super.initDatawatcher();
@@ -144,6 +192,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(0, new EntityBee.b(this, 1.399999976158142D, true));
this.goalSelector.a(1, new EntityBee.d());
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
@@ -159,6 +208,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
this.goalSelector.a(7, new EntityBee.g());
this.goalSelector.a(8, new EntityBee.l());
this.goalSelector.a(9, new PathfinderGoalFloat(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new EntityBee.h(this)).a(new Class[0]));
this.targetSelector.a(2, new EntityBee.c(this));
this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true));
@@ -629,6 +679,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
private d() {
super(); // CraftBukkit - decompile error
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - enter hive
}
@Override
@@ -691,6 +742,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
private g() {
super(); // CraftBukkit - decompile error
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - grow crop
}
@Override
@@ -755,6 +807,7 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
private i() {
super(); // CraftBukkit - decompile error
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - go to hive
}
@Override
@@ -978,16 +1031,16 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
}
}
- class j extends ControllerLook {
+ class j extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur
j(EntityInsentient entityinsentient) {
super(entityinsentient);
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (!EntityBee.this.isAngry()) {
- super.a();
+ super.tick(); // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java
index c8f529b3fd227ce3354f442038b27cd716f57254..3efb010d0e045d14051a33bd7465669e415c26bd 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityCat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCat.java
@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.MinecraftKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -104,6 +105,25 @@ public class EntityCat extends EntityTameableAnimal {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.catRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.catRidableInWater;
+ }
+
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ setSitting(false);
+ setSleepingWithOwner(false);
+ setHeadDown(false);
+ }
+ // Purpur end
+
public MinecraftKey eU() {
return (MinecraftKey) EntityCat.bq.getOrDefault(this.getCatType(), EntityCat.bq.get(0));
}
@@ -111,7 +131,8 @@ public class EntityCat extends EntityTameableAnimal {
@Override
protected void initPathfinder() {
this.bx = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.br, true);
- this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalSit(this));
this.goalSelector.a(2, new EntityCat.b(this));
this.goalSelector.a(3, this.bx);
@@ -123,6 +144,7 @@ public class EntityCat extends EntityTameableAnimal {
this.goalSelector.a(10, new PathfinderGoalBreed(this, 0.8D));
this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F));
this.goalSelector.a(12, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityRabbit.class, false, (Predicate) null));
this.targetSelector.a(1, new PathfinderGoalRandomTargetNonTamed<>(this, EntityTurtle.class, false, EntityTurtle.bo));
}
@@ -139,6 +161,7 @@ public class EntityCat extends EntityTameableAnimal {
this.datawatcher.set(EntityCat.bs, i);
}
+ public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER
public void x(boolean flag) {
this.datawatcher.set(EntityCat.bt, flag);
}
@@ -147,6 +170,7 @@ public class EntityCat extends EntityTameableAnimal {
return (Boolean) this.datawatcher.get(EntityCat.bt);
}
+ public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER
public void y(boolean flag) {
this.datawatcher.set(EntityCat.bu, flag);
}
@@ -365,6 +389,7 @@ public class EntityCat extends EntityTameableAnimal {
@Override
public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) {
+ if (hasRider()) return EnumInteractionResult.PASS; // Purpur
ItemStack itemstack = entityhuman.b(enumhand);
Item item = itemstack.getItem();
@@ -462,6 +487,7 @@ public class EntityCat extends EntityTameableAnimal {
public b(EntityCat entitycat) {
this.a = entitycat;
+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on owner
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java
index 600d6ebdf554dbaa8ca46a22a12d8b4e3255d987..5c744f1eac19e144c39a2c146d312f0547d6e589 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityChicken.java
@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal;
import net.minecraft.core.BlockPosition;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -54,6 +55,16 @@ public class EntityChicken extends EntityAnimal {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.chickenRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.chickenRidableInWater;
+ }
+
@Override
protected void initAttributes() {
if (world.purpurConfig.chickenRetaliate) {
@@ -65,6 +76,7 @@ public class EntityChicken extends EntityAnimal {
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
//this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D)); // Purpur - moved down
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, EntityChicken.bv));
@@ -75,6 +87,7 @@ public class EntityChicken extends EntityAnimal {
// Purpur start
if (world.purpurConfig.chickenRetaliate) {
this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, false));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this));
} else {
this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.4D));
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java
index aac7992a30a0b69cb34097aeb0fe021f54a3cdac..897e0d5ca44a0c475634f08e7d4fcf129ee197ab 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityCod.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCod.java
@@ -14,6 +14,18 @@ public class EntityCod extends EntityFishSchool {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.codRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
@Override
protected ItemStack eK() {
return new ItemStack(Items.COD_BUCKET);
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java
index 962dde5fcc617bc39b7d06a1e295370b9d60696c..cad256514c7df92847522c8d7ddf45ebe02658c4 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java
@@ -2,6 +2,7 @@ package net.minecraft.world.entity.animal;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.particles.Particles;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -43,9 +44,22 @@ public class EntityCow extends EntityAnimal {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.cowRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.cowRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalPanic(this, 2.0D));
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
if (world.purpurConfig.cowFeedMushrooms > 0) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.25D, RecipeItemStack.a(Items.WHEAT, Blocks.RED_MUSHROOM.getItem(), Blocks.BROWN_MUSHROOM.getItem()), false)); else // Purpur
@@ -87,6 +101,7 @@ public class EntityCow extends EntityAnimal {
@Override
public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) {
+ if (hasRider()) return EnumInteractionResult.PASS; // Purpur
ItemStack itemstack = entityhuman.b(enumhand);
if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) {
@@ -94,7 +109,7 @@ public class EntityCow extends EntityAnimal {
org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand
if (event.isCancelled()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
// CraftBukkit end
@@ -105,7 +120,7 @@ public class EntityCow extends EntityAnimal {
return EnumInteractionResult.a(this.world.isClientSide);
// Purpur start - feed mushroom to change to mooshroom
} else if (world.purpurConfig.cowFeedMushrooms > 0 && getEntityType() != EntityTypes.MOOSHROOM && isMushroom(itemstack)) {
- return feedMushroom(entityhuman, itemstack);
+ return feedMushroom(entityhuman, enumhand, itemstack);
// Purpur end
} else {
return super.b(entityhuman, enumhand);
@@ -128,7 +143,7 @@ public class EntityCow extends EntityAnimal {
}
}
- private EnumInteractionResult feedMushroom(EntityHuman entityhuman, ItemStack itemstack) {
+ private EnumInteractionResult feedMushroom(EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack) {
world.broadcastEntityEffect(this, (byte) 18); // hearts
playSound(SoundEffects.ENTITY_COW_MILK, 1.0F, 1.0F);
if (incrementFeedCount(itemstack) < world.purpurConfig.cowFeedMushrooms) {
@@ -139,7 +154,7 @@ public class EntityCow extends EntityAnimal {
}
EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world);
if (mooshroom == null) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand);
}
if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) {
mooshroom.setVariant(EntityMushroomCow.Type.BROWN);
@@ -158,10 +173,10 @@ public class EntityCow extends EntityAnimal {
mooshroom.setCustomName(this.getCustomName());
}
if (CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand);
}
if (!new com.destroystokyo.paper.event.entity.EntityTransformedEvent(this.getBukkitEntity(), mooshroom.getBukkitEntity(), com.destroystokyo.paper.event.entity.EntityTransformedEvent.TransformedReason.INFECTED).callEvent()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand);
}
this.world.addEntity(mooshroom);
this.die();
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java
index e0a9b931c26dbd4e7739d09ae45e1cee72ab210c..880c3aaf4e684209879dc921480619e7c61ee4a0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityDolphin.java
@@ -16,6 +16,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -81,6 +82,7 @@ public class EntityDolphin extends EntityWaterAnimal {
public static final Predicate<EntityItem> b = (entityitem) -> {
return !entityitem.p() && entityitem.isAlive() && entityitem.isInWater();
};
+ private int spitCooldown; // Purpur
public EntityDolphin(EntityTypes<? extends EntityDolphin> entitytypes, World world) {
super(entitytypes, world);
@@ -89,6 +91,45 @@ public class EntityDolphin extends EntityWaterAnimal {
this.setCanPickupLoot(true);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.dolphinRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (spitCooldown == 0 && hasRider()) {
+ spitCooldown = world.purpurConfig.dolphinSpitCooldown;
+ if (!hasRider()) {
+ return false;
+ }
+
+ org.bukkit.craftbukkit.entity.CraftPlayer player = (org.bukkit.craftbukkit.entity.CraftPlayer) getRider().getBukkitEntity();
+ if (!player.hasPermission("allow.special.dolphin")) {
+ return false;
+ }
+
+ org.bukkit.Location loc = player.getEyeLocation();
+ loc.setPitch(loc.getPitch() - 10);
+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(10).add(loc.toVector());
+
+ net.pl3x.purpur.entity.DolphinSpit spit = new net.pl3x.purpur.entity.DolphinSpit(world, this);
+ spit.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), world.purpurConfig.dolphinSpitSpeed, 5.0F);
+
+ world.addEntity(spit);
+ playSound(SoundEffects.ENTITY_DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F);
+ return true;
+ }
+ return false;
+ }
+ // Purpur end
+
@Nullable
@Override
public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) {
@@ -163,6 +204,7 @@ public class EntityDolphin extends EntityWaterAnimal {
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalBreath(this));
this.goalSelector.a(0, new PathfinderGoalWater(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityDolphin.b(this));
this.goalSelector.a(2, new EntityDolphin.c(this, 4.0D));
this.goalSelector.a(4, new PathfinderGoalRandomSwim(this, 1.0D, 10));
@@ -173,6 +215,7 @@ public class EntityDolphin extends EntityWaterAnimal {
this.goalSelector.a(8, new EntityDolphin.d());
this.goalSelector.a(8, new PathfinderGoalFollowBoat(this));
this.goalSelector.a(9, new PathfinderGoalAvoidTarget<>(this, EntityGuardian.class, 8.0F, 1.0D, 1.0D));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityGuardian.class})).a(new Class[0])); // CraftBukkit - decompile error
}
@@ -224,7 +267,7 @@ public class EntityDolphin extends EntityWaterAnimal {
@Override
protected boolean n(Entity entity) {
- return true;
+ return getRideCooldown() <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs
}
@Override
@@ -259,6 +302,9 @@ public class EntityDolphin extends EntityWaterAnimal {
@Override
public void tick() {
super.tick();
+ if (spitCooldown > 0) {
+ spitCooldown--;
+ }
if (this.isNoAI()) {
this.setAirTicks(this.bH());
} else {
@@ -532,7 +578,7 @@ public class EntityDolphin extends EntityWaterAnimal {
private int b;
- private d() {}
+ private d() { this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); } // Purpur - play with item
@Override
public boolean a() {
@@ -600,7 +646,7 @@ public class EntityDolphin extends EntityWaterAnimal {
}
}
- static class a extends ControllerMove {
+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur
private final EntityDolphin i;
@@ -610,7 +656,20 @@ public class EntityDolphin extends EntityWaterAnimal {
}
@Override
- public void a() {
+ // Purpur start
+ public void tick(EntityHuman rider) {
+ if (this.i.getAirTicks() < 150) {
+ // if drowning override player WASD controls to find air
+ tick();
+ } else {
+ super.tick(rider);
+ this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D));
+ }
+ }
+
+ @Override
+ public void tick() {
+ // Purpur end
if (this.i.isInWater()) {
this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D));
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java
index e28f84be745647960c936c7208a87713dfa75682..e1e4ea73f42a09ac20d36a58f4d7232d4e1a2f08 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityFish.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFish.java
@@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -108,13 +109,12 @@ public abstract class EntityFish extends EntityWaterAnimal {
@Override
protected void initPathfinder() {
super.initPathfinder();
- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D));
- PathfinderGoalSelector pathfindergoalselector = this.goalSelector;
- Predicate predicate = IEntitySelector.g;
-
- predicate.getClass();
- pathfindergoalselector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, predicate::test));
- this.goalSelector.a(4, new EntityFish.b(this));
+ // Purpur start
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D));
+ this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 1.6D, 1.4D, IEntitySelector.g::test)); // Purpur - decompile error
+ this.goalSelector.a(5, new EntityFish.b(this));
+ // Purpur end
}
@Override
@@ -125,7 +125,7 @@ public abstract class EntityFish extends EntityWaterAnimal {
@Override
public void g(Vec3D vec3d) {
if (this.doAITick() && this.isInWater()) {
- this.a(0.01F, vec3d);
+ this.a(hasRider() ? getSpeed() : 0.01F, vec3d); // Purpur
this.move(EnumMoveType.SELF, this.getMot());
this.setMot(this.getMot().a(0.9D));
if (this.getGoalTarget() == null) {
@@ -199,9 +199,9 @@ public abstract class EntityFish extends EntityWaterAnimal {
@Override
protected void b(BlockPosition blockposition, IBlockData iblockdata) {}
- static class a extends ControllerMove {
+ static class a extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur
- private final EntityFish i;
+ private final EntityFish i; public EntityFish getFish() { return i; } // Purpur - OBFHELPER
a(EntityFish entityfish) {
super(entityfish);
@@ -209,7 +209,15 @@ public abstract class EntityFish extends EntityWaterAnimal {
}
@Override
- public void a() {
+ // Purpur start
+ public void tick(EntityHuman rider) {
+ super.tick(rider);
+ getFish().setMot(getFish().getMot().add(0.0D, 0.005D, 0.0D));
+ }
+
+ @Override
+ public void tick() {
+ // Purpur end
if (this.i.a((Tag) TagsFluid.WATER)) {
this.i.setMot(this.i.getMot().add(0.0D, 0.005D, 0.0D));
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java
index 21780f5dbcd4384649f08161f0812202ee94c96d..a03b0ed0a3f74ccb7572e1c4fa8e345a9e9bc49f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFishSchool.java
@@ -25,7 +25,7 @@ public abstract class EntityFishSchool extends EntityFish {
@Override
protected void initPathfinder() {
super.initPathfinder();
- this.goalSelector.a(5, new PathfinderGoalFishSchool(this));
+ this.goalSelector.a(6, new PathfinderGoalFishSchool(this)); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java
index cea46348c0876e168376061fbaf258048e9358cb..0c1151b598aa681e63ddaac29e4a589f917fd03b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java
@@ -21,6 +21,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
@@ -127,6 +128,39 @@ public class EntityFox extends EntityAnimal {
this.setCanPickupLoot(true);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.foxRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.foxRidableInWater;
+ }
+
+ @Override
+ public float getJumpHeight() {
+ return !hasRider() ? super.getJumpHeight() : 0.5F;
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ setCanPickupLoot(false);
+ stopActions();
+ setChasing(false);
+ spit(getEquipment(EnumItemSlot.MAINHAND));
+ setSlot(EnumItemSlot.MAINHAND, ItemStack.NULL_ITEM);
+ }
+
+ @Override
+ public void onDismount(EntityHuman entityhuman) {
+ super.onDismount(entityhuman);
+ setCanPickupLoot(true);
+ }
+ // Purpur end
+
@Override
protected void initDatawatcher() {
super.initDatawatcher();
@@ -146,6 +180,7 @@ public class EntityFox extends EntityAnimal {
return entityliving instanceof EntityFishSchool;
});
this.goalSelector.a(0, new EntityFox.g());
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityFox.b());
this.goalSelector.a(2, new EntityFox.n(2.2D));
this.goalSelector.a(3, new EntityFox.e(1.0D));
@@ -171,6 +206,7 @@ public class EntityFox extends EntityAnimal {
this.goalSelector.a(11, new EntityFox.p());
this.goalSelector.a(12, new EntityFox.j(this, EntityHuman.class, 24.0F));
this.goalSelector.a(13, new EntityFox.r());
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> {
return EntityFox.bt.test(entityliving) && !this.c(entityliving.getUniqueID());
}));
@@ -458,6 +494,7 @@ public class EntityFox extends EntityAnimal {
return itemstack1.isEmpty() || this.bD > 0 && item.isFood() && !itemstack1.getItem().isFood();
}
+ public void spit(ItemStack itemstack) { m(itemstack); } // Purpur - OBFHELPER
private void m(ItemStack itemstack) {
if (!itemstack.isEmpty() && !this.world.isClientSide) {
EntityItem entityitem = new EntityItem(this.world, this.locX() + this.getLookDirection().x, this.locY() + 1.0D, this.locZ() + this.getLookDirection().z, itemstack);
@@ -553,6 +590,7 @@ public class EntityFox extends EntityAnimal {
return this.t(16);
}
+ public void setChasing(boolean flag) { u(flag); } // Purpur - OBFHELPER
public void u(boolean flag) {
this.d(16, flag);
}
@@ -595,6 +633,7 @@ public class EntityFox extends EntityAnimal {
this.setSleeping(false);
}
+ public void stopActions() { fd(); } // Purpur - OBFHELPER
private void fd() {
this.w(false);
this.setCrouching(false);
@@ -760,16 +799,16 @@ public class EntityFox extends EntityAnimal {
}
}
- public class k extends ControllerLook {
+ public class k extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur
public k() {
super(EntityFox.this);
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (!EntityFox.this.isSleeping()) {
- super.a();
+ super.tick(); // Purpur
}
}
@@ -1439,16 +1478,16 @@ public class EntityFox extends EntityAnimal {
}
}
- class m extends ControllerMove {
+ class m extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
public m() {
super(EntityFox.this);
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (EntityFox.this.fe()) {
- super.a();
+ super.tick(); // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java
index 62cff5faafa076d05ebc59ad5c4fb020bea0509e..23e614f0c3cf1178acff8e72e0441c42c658e76b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java
@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -69,9 +70,22 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable {
this.G = 1.0F;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.ironGolemRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.ironGolemRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
if (world.purpurConfig.ironGolemCanSwim) this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalMeleeAttack(this, 1.0D, true));
this.goalSelector.a(2, new PathfinderGoalMoveTowardsTarget(this, 0.9D, 32.0F));
this.goalSelector.a(2, new PathfinderGoalStrollVillage(this, 0.6D, false));
@@ -79,6 +93,7 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable {
this.goalSelector.a(5, new PathfinderGoalOfferFlower(this));
this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalDefendVillage(this));
this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0]));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_));
@@ -248,13 +263,13 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable {
Item item = itemstack.getItem();
if (item != Items.IRON_INGOT) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
} else {
float f = this.getHealth();
this.heal(25.0F);
if (this.getHealth() == f) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
} else {
float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java
index d28d4d2c1eff2c130f49c2bce3c19da212dba5dc..815e907e8db721f2a6f0f831b69c44a9573b5c9b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityMushroomCow.java
@@ -57,6 +57,18 @@ public class EntityMushroomCow extends EntityCow implements IShearable {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.mooshroomRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.mooshroomRidableInWater;
+ }
+ // Purpur end
+
@Override
public float a(BlockPosition blockposition, IWorldReader iworldreader) {
return iworldreader.getType(blockposition.down()).a(Blocks.MYCELIUM) ? 10.0F : iworldreader.y(blockposition) - 0.5F;
@@ -118,7 +130,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable {
} else if (itemstack.getItem() == Items.SHEARS && this.canShear()) {
// CraftBukkit start
if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
// CraftBukkit end
this.shear(SoundCategory.PLAYERS);
@@ -138,7 +150,7 @@ public class EntityMushroomCow extends EntityCow implements IShearable {
Optional<Pair<MobEffectList, Integer>> optional = this.l(itemstack);
if (!optional.isPresent()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
Pair<MobEffectList, Integer> pair = (Pair) optional.get();
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java
index f3e9c73f28584bcccd6f82d8974eabe4b4a892fa..d7938ff0dca305f1d47fdfdbc57648892debe367 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java
@@ -10,6 +10,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -63,6 +64,18 @@ public class EntityOcelot extends EntityAnimal {
this.eL();
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.ocelotRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.ocelotRidableInWater;
+ }
+ // Purpur end
+
private boolean isTrusting() {
return (Boolean) this.datawatcher.get(EntityOcelot.bp);
}
@@ -94,12 +107,14 @@ public class EntityOcelot extends EntityAnimal {
protected void initPathfinder() {
this.br = new EntityOcelot.b(this, 0.6D, EntityOcelot.bo, true);
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(3, this.br);
this.goalSelector.a(7, new PathfinderGoalLeapAtTarget(this, 0.3F));
this.goalSelector.a(8, new PathfinderGoalOcelotAttack(this));
this.goalSelector.a(9, new PathfinderGoalBreed(this, 0.8D));
this.goalSelector.a(10, new PathfinderGoalRandomStrollLand(this, 0.8D, 1.0000001E-5F));
this.goalSelector.a(11, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 10.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityChicken.class, false));
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, false, false, EntityTurtle.bo));
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java
index 711b322007a0973ff0aebf3c25efbae8fc7741d0..0d912399e1975d9c0d5525f5b89049f40e7efcc0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java
@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -101,6 +102,27 @@ public class EntityPanda extends EntityAnimal {
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.pandaRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.pandaRidableInWater;
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ this.setForwardSpeed(0.0F);
+ this.setScared(false);
+ this.setEating(false);
+ this.setLayingOnBack(false);
+ }
+ // Purpur end
+
@Override
public boolean e(ItemStack itemstack) {
EnumItemSlot enumitemslot = EntityInsentient.j(itemstack);
@@ -124,6 +146,7 @@ public class EntityPanda extends EntityAnimal {
return this.w(8);
}
+ public void setScared(boolean scared) { this.t(scared); } // Purpur - OBFHELPER
public void t(boolean flag) {
this.d(8, flag);
}
@@ -132,6 +155,7 @@ public class EntityPanda extends EntityAnimal {
return this.w(16);
}
+ public void setLayingOnBack(boolean layingOnBack) { this.u(layingOnBack); } // Purpur - OBFHELPER
public void u(boolean flag) {
this.d(16, flag);
}
@@ -148,6 +172,7 @@ public class EntityPanda extends EntityAnimal {
return (Integer) this.datawatcher.get(EntityPanda.br);
}
+ public void setEating(boolean eating) { this.v(eating); } // Purpur - OBFHELPER
private void v(int i) {
this.datawatcher.set(EntityPanda.br, i);
}
@@ -256,6 +281,7 @@ public class EntityPanda extends EntityAnimal {
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new EntityPanda.i(this, 2.0D));
this.goalSelector.a(2, new EntityPanda.d(this, 1.0D));
this.goalSelector.a(3, new EntityPanda.b(this, 1.2000000476837158D, true));
@@ -271,6 +297,7 @@ public class EntityPanda extends EntityAnimal {
this.goalSelector.a(12, new EntityPanda.j(this));
this.goalSelector.a(13, new PathfinderGoalFollowParent(this, 1.25D));
this.goalSelector.a(14, new PathfinderGoalRandomStrollLand(this, 1.0D));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new EntityPanda.e(this, new Class[0])).a(new Class[0]));
}
@@ -591,7 +618,7 @@ public class EntityPanda extends EntityAnimal {
ItemStack itemstack = entityhuman.b(enumhand);
if (this.ff()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
} else if (this.eN()) {
this.u(false);
return EnumInteractionResult.a(this.world.isClientSide);
@@ -608,7 +635,7 @@ public class EntityPanda extends EntityAnimal {
this.g(entityhuman);
} else {
if (this.world.isClientSide || this.eM() || this.isInWater()) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
this.ft();
@@ -625,7 +652,7 @@ public class EntityPanda extends EntityAnimal {
return EnumInteractionResult.SUCCESS;
} else {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
}
@@ -738,6 +765,7 @@ public class EntityPanda extends EntityAnimal {
public f(EntityPanda entitypanda) {
this.a = entitypanda;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - lay on back
}
@Override
@@ -901,6 +929,7 @@ public class EntityPanda extends EntityAnimal {
public l(EntityPanda entitypanda) {
this.a = entitypanda;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - sneeze
}
@Override
@@ -1030,7 +1059,7 @@ public class EntityPanda extends EntityAnimal {
}
}
- static class h extends ControllerMove {
+ static class h extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
private final EntityPanda i;
@@ -1040,9 +1069,9 @@ public class EntityPanda extends EntityAnimal {
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.i.fh()) {
- super.a();
+ super.tick(); // Purpur
}
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java
index 699dd0ac1f8d0d340ab1a560106336fc7cc95d5b..5c26eea7e3e93dc7bcd8b86519e84db58b70cecb 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java
@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -38,6 +39,7 @@ import net.minecraft.world.entity.EntityPose;
import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMobSpawn;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.GroupDataEntity;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
@@ -119,12 +121,58 @@ public class EntityParrot extends EntityPerchable implements EntityBird {
public EntityParrot(EntityTypes<? extends EntityParrot> entitytypes, World world) {
super(entitytypes, world);
- this.moveController = new ControllerMoveFlying(this, 10, false);
+ // Purpur start
+ final net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar flyingController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F);
+ this.moveController = new ControllerMoveFlying(this, 10, false) {
+ @Override
+ public void a() { // tick
+ if (getEntity().hasRider()) {
+ flyingController.tick(getEntity().getRider());
+ } else {
+ tick();
+ }
+ }
+
+ @Override
+ public boolean b() { // isUpdating
+ return getEntity().hasRider() ? getForward() != 0 || getStrafe() != 0 : super.b();
+ }
+ };
+ // Purpur end
this.a(PathType.DANGER_FIRE, -1.0F);
this.a(PathType.DAMAGE_FIRE, -1.0F);
this.a(PathType.COCOA, -1.0F);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.parrotRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.parrotRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.parrotMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 2;
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 0.25, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+ // Purpur end
+
@Nullable
@Override
public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) {
@@ -143,8 +191,10 @@ public class EntityParrot extends EntityPerchable implements EntityBird {
@Override
protected void initPathfinder() {
- this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D));
+ // this.goalSelector.a(0, new PathfinderGoalPanic(this, 1.25D)); // Purpur - move down
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D)); // Purpur
this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(2, new PathfinderGoalSit(this));
this.goalSelector.a(2, new PathfinderGoalFollowOwner(this, 1.0D, 5.0F, 1.0F, true));
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java
index 1a540e41e6161d011ca4ed30c68ae9df4567b8db..cef69f99d7bc9b6605b9654c50f43a1ebc1a8509 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java
@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -66,9 +67,22 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable {
this.saddleStorage = new SaddleStorage(this.datawatcher, EntityPig.bp, EntityPig.bo);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.pigRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.pigRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D));
this.goalSelector.a(3, new PathfinderGoalBreed(this, 1.0D));
this.goalSelector.a(4, new PathfinderGoalTempt(this, 1.2D, RecipeItemStack.a(Items.CARROT_ON_A_STICK), false));
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java
index f25f5ced218555af0d62844a78842cfc7599d608..e686491a469573a3fc466c46be1b7430ff02ba53 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPolarBear.java
@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -66,12 +67,34 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable {
private static final IntRange bs = TimeRange.a(20, 39);
private int bt;
private UUID bu;
+ private int standTimer = 0; // Purpur
public EntityPolarBear(EntityTypes<? extends EntityPolarBear> entitytypes, World world) {
super(entitytypes, world);
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.polarBearRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.polarBearRidableInWater;
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (!isStanding()) {
+ if (hasRider() && getRider().getForward() == 0 && getRider().getStrafe() == 0) {
+ setStanding(true);
+ playSound(SoundEffects.ENTITY_POLAR_BEAR_WARNING, 1.0F, 1.0F);
+ }
+ }
+ return false;
+ }
+
@Override
public boolean mate(EntityAnimal entityanimal) {
if (entityanimal == this) {
@@ -109,6 +132,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable {
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityPolarBear.c());
this.goalSelector.a(1, new EntityPolarBear.d());
// Purpur start
@@ -121,6 +145,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable {
this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new EntityPolarBear.b());
this.targetSelector.a(2, new EntityPolarBear.a());
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_));
@@ -233,6 +258,11 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable {
this.a((WorldServer) this.world, true);
}
+ // Purpur start
+ if (isStanding() && --standTimer <= 0) {
+ setStanding(false);
+ }
+ // Purpur end
}
@Override
@@ -266,6 +296,7 @@ public class EntityPolarBear extends EntityAnimal implements IEntityAngerable {
public void setStanding(boolean standing) { t(standing); } // Purpur - OBFHELPER
public void t(boolean flag) {
this.datawatcher.set(EntityPolarBear.bo, flag);
+ standTimer = flag ? 20 : -1; // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java
index e9f20d387ccdacfbb1a48dc31e2a6cd4843a0d7b..38fe79872b4b7f4ad4a030fbdf505efbc0352fc0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java
@@ -39,6 +39,18 @@ public class EntityPufferFish extends EntityFish {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.pufferfishRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
@Override
protected void initDatawatcher() {
super.initDatawatcher();
@@ -82,7 +94,7 @@ public class EntityPufferFish extends EntityFish {
@Override
protected void initPathfinder() {
super.initPathfinder();
- this.goalSelector.a(1, new EntityPufferFish.a(this));
+ this.goalSelector.a(2, new EntityPufferFish.a(this)); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java
index 180fc927074dc683ad4d482a00dd4e04ff7923d0..fff6bcff9d44c7d49cd2d0c334ea702531c74ea1 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityRabbit.java
@@ -10,6 +10,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.MinecraftKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -75,6 +76,18 @@ public class EntityRabbit extends EntityAnimal {
this.initializePathFinderGoals(); // CraftBukkit - moved code
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.rabbitRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.rabbitRidableInWater;
+ }
+ // Purpur end
+
// CraftBukkit start - code from constructor
public void initializePathFinderGoals(){
this.i(0.0D);
@@ -83,7 +96,8 @@ public class EntityRabbit extends EntityAnimal {
@Override
public void initPathfinder() {
- this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityRabbit.PathfinderGoalRabbitPanic(this, 2.2D));
this.goalSelector.a(2, new PathfinderGoalBreed(this, 0.8D));
this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, RecipeItemStack.a(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false));
@@ -96,7 +110,15 @@ public class EntityRabbit extends EntityAnimal {
}
@Override
- protected float dJ() {
+ // Purpur start
+ public float getJumpHeight() {
+ if (hasRider()) {
+ if (getForward() < 0) {
+ setSpeed(getForward() * 2F);
+ }
+ return actualJump ? 0.5F : 0.3F;
+ }
+ // Purpur end
if (!this.positionChanged && (!this.moveController.b() || this.moveController.e() <= this.locY() + 0.5D)) {
PathEntity pathentity = this.navigation.k();
@@ -115,7 +137,7 @@ public class EntityRabbit extends EntityAnimal {
}
@Override
- protected void jump() {
+ public void jump() { // Purpur - protected -> public
super.jump();
double d0 = this.moveController.c();
@@ -147,6 +169,7 @@ public class EntityRabbit extends EntityAnimal {
}
+ public void startJumping() { eK(); } // Purpur - OBFHELPER
public void eK() {
this.setJumping(true);
this.br = 10;
@@ -161,6 +184,13 @@ public class EntityRabbit extends EntityAnimal {
@Override
public void mobTick() {
+ // Purpur start
+ if (hasRider()) {
+ handleJumping();
+ return;
+ }
+ // Purpur end
+
if (this.bt > 0) {
--this.bt;
}
@@ -211,6 +241,39 @@ public class EntityRabbit extends EntityAnimal {
this.bs = this.onGround;
}
+ // Purpur start
+ private boolean wasOnGround;
+ private boolean actualJump;
+
+ private void handleJumping() {
+ if (onGround) {
+ ControllerJumpRabbit jumpController = (ControllerJumpRabbit) getJumpController();
+ if (!wasOnGround) {
+ setJumping(false);
+ jumpController.setCanJump(false);
+ }
+ if (!jumpController.isJumping()) {
+ if (moveController.b()) { // isUpdating
+ startJumping();
+ }
+ } else if (!jumpController.canJump()) {
+ jumpController.setCanJump(true);
+ }
+ }
+ wasOnGround = onGround;
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (onGround) {
+ actualJump = true;
+ jump();
+ actualJump = false;
+ }
+ return true;
+ }
+ // Purpur end
+
@Override
public boolean aO() {
return false;
@@ -540,7 +603,7 @@ public class EntityRabbit extends EntityAnimal {
}
}
- static class ControllerMoveRabbit extends ControllerMove {
+ static class ControllerMoveRabbit extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
private final EntityRabbit i;
private double j;
@@ -551,14 +614,14 @@ public class EntityRabbit extends EntityAnimal {
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.i.onGround && !this.i.jumping && !((EntityRabbit.ControllerJumpRabbit) this.i.bi).c()) {
this.i.i(0.0D);
} else if (this.b()) {
this.i.i(this.j);
}
- super.a();
+ super.tick(); // Purpur
}
@Override
@@ -585,14 +648,17 @@ public class EntityRabbit extends EntityAnimal {
this.c = entityrabbit;
}
+ public boolean isJumping() { return c(); } // Purpur - OBFHELPER
public boolean c() {
return this.a;
}
+ public boolean canJump() { return d(); } // Purpur - OBFHELPER
public boolean d() {
return this.d;
}
+ public void setCanJump(boolean canJump) { a(canJump); } // Purpur - OBFHELPER
public void a(boolean flag) {
this.d = flag;
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java
index ca125342f189d5db95ebd04043a2d11e5fbfd3fd..bf565671c167162b3d935447961f0d44ed4a2779 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySalmon.java
@@ -14,6 +14,18 @@ public class EntitySalmon extends EntityFishSchool {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.salmonRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
@Override
public int eN() {
return 5;
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java
index 88bed962bc17242ee6a9c93b7e0fec8bc578b35f..8f3296031f220dd7bb3ae9fe2443e479954ebad3 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySheep.java
@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.MinecraftKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -110,10 +111,23 @@ public class EntitySheep extends EntityAnimal implements IShearable {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.sheepRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.sheepRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.bs = new PathfinderGoalEatTile(this);
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.25D));
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.1D, RecipeItemStack.a(Items.WHEAT), false));
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java
index 44119f52a4f169ffcea53fb69393bfedfd1a62a7..cfcf67e99ae345f77a55771e6a25bdcdb4a9740a 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySnowman.java
@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -50,12 +51,26 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.snowGolemRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.snowGolemRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalArrowAttack(this, 1.25D, 20, 10.0F));
this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D, 1.0000001E-5F));
this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(4, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 10, true, false, (entityliving) -> {
return entityliving instanceof IMonster;
}));
@@ -107,6 +122,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt
return;
}
+ if (hasRider() && !world.purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden
IBlockData iblockdata = Blocks.SNOW.getBlockData();
for (int l = 0; l < 4; ++l) {
@@ -149,7 +165,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt
if (itemstack.getItem() == Items.SHEARS && this.canShear()) {
// CraftBukkit start
if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
// CraftBukkit end
this.shear(SoundCategory.PLAYERS);
@@ -169,7 +185,7 @@ public class EntitySnowman extends EntityGolem implements IShearable, IRangedEnt
return EnumInteractionResult.SUCCESS;
// Purpur end
} else {
- return EnumInteractionResult.PASS;
+ return tryRide(entityhuman, enumhand); // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java
index e6757b22497c6e274c3999d58671653e931ebe2b..a9fa18931d93dd7fa428b8cd6a414d4b3a3b4fbb 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java
@@ -4,6 +4,7 @@ package net.minecraft.world.entity.animal;
import java.util.Random;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.particles.Particles;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -23,6 +24,7 @@ import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
+import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.level.GeneratorAccess;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.state.IBlockData;
@@ -54,17 +56,38 @@ public class EntitySquid extends EntityWaterAnimal {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.squidRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+
@Override
public AxisAlignedBB getAxisForFluidCheck() {
// Stops squids from floating just over the water
return this.getBoundingBox().shrink(0.001D).offsetY(world.purpurConfig.squidOffsetWaterCheck);
}
+
+ private void rotateVectorAroundY(org.bukkit.util.Vector vector, double degrees) {
+ double rad = Math.toRadians(degrees);
+ double cos = Math.cos(rad);
+ double sine = Math.sin(rad);
+ double x = vector.getX();
+ double z = vector.getZ();
+ vector.setX(cos * x - sine * z);
+ vector.setZ(sine * x + cos * z);
+ }
// Purpur end
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new EntitySquid.PathfinderGoalSquid(this));
- this.goalSelector.a(1, new EntitySquid.a());
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
+ this.goalSelector.a(2, new EntitySquid.a()); // Purpur
}
public static AttributeProvider.Builder m() {
@@ -209,6 +232,7 @@ public class EntitySquid extends EntityWaterAnimal {
return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper
}
+ public void setMovementVector(float x, float y, float z) { a(x, y, z); } // Purpur - OBFHELPER
public void a(float f, float f1, float f2) {
this.bw = f;
this.bx = f1;
@@ -280,7 +304,7 @@ public class EntitySquid extends EntityWaterAnimal {
class PathfinderGoalSquid extends PathfinderGoal {
- private final EntitySquid b;
+ private final EntitySquid b; public EntitySquid getSquid() { return b; } // Purpur - OBFHELPER
public PathfinderGoalSquid(EntitySquid entitysquid) {
this.b = entitysquid;
@@ -293,6 +317,38 @@ public class EntitySquid extends EntityWaterAnimal {
@Override
public void e() {
+ // Purpur start
+ EntitySquid squid = getSquid();
+ EntityHuman rider = squid.getRider();
+ if (rider != null) {
+ if (rider.jumping) {
+ squid.onSpacebar();
+ }
+ float forward = rider.getForward();
+ float strafe = rider.getStrafe();
+ float speed = (float) squid.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 10F;
+ if (forward < 0.0F) {
+ speed *= -0.5;
+ }
+ org.bukkit.util.Vector dir = rider.getBukkitEntity().getEyeLocation().getDirection().normalize().multiply(speed / 20.0F);
+ if (strafe != 0.0F) {
+ if (forward == 0.0F) {
+ dir.setY(0);
+ rotateVectorAroundY(dir, strafe > 0.0F ? -90 : 90);
+ } else if (forward < 0.0F) {
+ rotateVectorAroundY(dir, strafe > 0.0F ? 45 : -45);
+ } else {
+ rotateVectorAroundY(dir, strafe > 0.0F ? -45 : 45);
+ }
+ }
+ if (forward != 0.0F || strafe != 0.0F) {
+ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ());
+ } else {
+ squid.setMovementVector(0.0F, 0.0F, 0.0F);
+ }
+ return;
+ }
+ // Purpur end
int i = this.b.dd();
if (i > 100) {
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java
index 29f6835da58c73a99fe620d6de7d86fede6ac893..478e55475ccc1410a442f4e30a1cbc08f479dbda 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTropicalFish.java
@@ -37,6 +37,18 @@ public class EntityTropicalFish extends EntityFishSchool {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.tropicalFishRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
@Override
protected void initDatawatcher() {
super.initDatawatcher();
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java
index ecec8a3c4d4b5d491f79ad60d7ce5a118f30b3db..28d6e673f55fc8fae40dff4a96ac2c2b5eeab9d6 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java
@@ -15,6 +15,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.MCUtil;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
@@ -90,6 +91,18 @@ public class EntityTurtle extends EntityAnimal {
this.G = 1.0F;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.turtleRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.turtleRidableInWater;
+ }
+ // Purpur end
+
public void setHomePos(BlockPosition blockposition) {
this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos...
}
@@ -198,12 +211,13 @@ public class EntityTurtle extends EntityAnimal {
@Override
protected void initPathfinder() {
- this.goalSelector.a(0, new EntityTurtle.f(this, 1.2D));
- this.goalSelector.a(1, new EntityTurtle.a(this, 1.0D));
- this.goalSelector.a(1, new EntityTurtle.d(this, 1.0D));
- this.goalSelector.a(2, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem()));
- this.goalSelector.a(3, new EntityTurtle.c(this, 1.0D));
- this.goalSelector.a(4, new EntityTurtle.b(this, 1.0D));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.goalSelector.a(1, new EntityTurtle.f(this, 1.2D)); // Purpur
+ this.goalSelector.a(2, new EntityTurtle.a(this, 1.0D)); // Purpur
+ this.goalSelector.a(2, new EntityTurtle.d(this, 1.0D)); // Purpur
+ this.goalSelector.a(3, new EntityTurtle.i(this, 1.1D, Blocks.SEAGRASS.getItem())); // Purpur
+ this.goalSelector.a(4, new EntityTurtle.c(this, 1.0D)); // Purpur
+ this.goalSelector.a(5, new EntityTurtle.b(this, 1.0D)); // Purpur
this.goalSelector.a(7, new EntityTurtle.j(this, 1.0D));
this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(9, new EntityTurtle.h(this, 1.0D, 100));
@@ -386,13 +400,15 @@ public class EntityTurtle extends EntityAnimal {
}
}
- static class e extends ControllerMove {
+ static class e extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
- private final EntityTurtle i;
+ private final EntityTurtle i; public EntityTurtle getTurtle() { return i; } // Purpur - OBFHELPER
+ private final net.pl3x.purpur.controller.ControllerMoveWASDWater waterController; // Purpur
e(EntityTurtle entityturtle) {
- super(entityturtle);
+ super(entityturtle, 0.1D); // Purpur
this.i = entityturtle;
+ waterController = new net.pl3x.purpur.controller.ControllerMoveWASDWater(entityturtle, 0.25D); // Purpur
}
private void g() {
@@ -412,7 +428,18 @@ public class EntityTurtle extends EntityAnimal {
}
@Override
- public void a() {
+ // Purpur start
+ public void tick(EntityHuman rider) {
+ if (getTurtle().isInWater()) {
+ waterController.tick(rider);
+ } else {
+ super.tick(rider);
+ }
+ }
+
+ @Override
+ public void tick() {
+ // Purpur end
this.g();
if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) {
double d0 = this.b - this.i.locX();
diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java
index b44b1544f401c1a5127bed3239bfd60420d17329..3fbd8f9122d7a5ac23af4d872f877030644ef86a 100644
--- a/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java
+++ b/src/main/java/net/minecraft/world/entity/animal/EntityWolf.java
@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -91,9 +92,27 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable
this.setTamed(false);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.wolfRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.wolfRidableInWater;
+ }
+
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ setSitting(false);
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new PathfinderGoalSit(this));
this.goalSelector.a(3, new EntityWolf.a<>(this, EntityLlama.class, 24.0F, 1.5D, 1.5D));
this.goalSelector.a(4, new PathfinderGoalLeapAtTarget(this, 0.4F));
@@ -104,6 +123,7 @@ public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable
this.goalSelector.a(9, new PathfinderGoalBeg(this, 8.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(10, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalOwnerHurtByTarget(this));
this.targetSelector.a(2, new PathfinderGoalOwnerHurtTarget(this));
this.targetSelector.a(3, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java
index 48f67652a0a6797e217ce1f6040b5dc0f7a74938..650f13b1133e4c61f71b36f3f91a9d2913996435 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorse.java
@@ -41,6 +41,13 @@ public class EntityHorse extends EntityHorseAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.horseRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void eK() {
this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fp());
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java
index cb6e2053d1315b65812e7bff8a17988b5b8ab0e4..d4556fa190c754406d0c65baae941fb23af3f81f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java
@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHorseHasRider;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.server.players.NameReferencingFileConverter;
@@ -43,6 +44,8 @@ import net.minecraft.world.entity.IJumpable;
import net.minecraft.world.entity.ISaddleable;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.ai.control.ControllerLook;
+import net.minecraft.world.entity.ai.control.ControllerMove;
import net.minecraft.world.entity.ai.goal.PathfinderGoalBreed;
import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat;
import net.minecraft.world.entity.ai.goal.PathfinderGoalFollowParent;
@@ -101,12 +104,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven
protected EntityHorseAbstract(EntityTypes<? extends EntityHorseAbstract> entitytypes, World world) {
super(entitytypes, world);
+ this.moveController = new ControllerMove(this); // Purpur - use vanilla controller
+ this.lookController = new ControllerLook(this); // Purpur - use vanilla controller
this.G = 1.0F;
this.loadChest();
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return false; // vanilla handles
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return false;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalPanic(this, 1.2D));
this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D));
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D, EntityHorseAbstract.class));
@@ -114,6 +132,7 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven
this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D));
this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur
this.eV();
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java
index d9c87411f5c636bee3f28b724abf665826788be4..50700bf85a296b87fe3155651f869e2bbdb0875d 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseDonkey.java
@@ -16,6 +16,13 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.donkeyRidableInWater;
+ }
+ // Purpur end
+
@Override
protected SoundEffect getSoundAmbient() {
super.getSoundAmbient();
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java
index 7a5c14c1e80bde623473a39acb01b78b79d593e4..b6385a23050296611dbc8864b92d2cdd8321a1d0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseMule.java
@@ -15,6 +15,12 @@ public class EntityHorseMule extends EntityHorseChestedAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.muleRidableInWater;
+ }
+ // Purpur end
@Override
protected SoundEffect getSoundAmbient() {
super.getSoundAmbient();
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java
index da5365372e89b847d626e52c5541544467f14702..d21399fbb6ddc4f26a7509ce547f8c4ad6458089 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java
@@ -17,6 +17,7 @@ import net.minecraft.world.entity.EnumMonsterType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat;
import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@@ -32,6 +33,18 @@ public class EntityHorseSkeleton extends EntityHorseAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.skeletonHorseRidableInWater;
+ }
+
+ @Override
+ public boolean isTamed() {
+ return true;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder eL() {
return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D);
}
@@ -42,7 +55,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract {
}
@Override
- protected void eV() {}
+ protected void eV() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur
@Override
protected SoundEffect getSoundAmbient() {
@@ -137,7 +150,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract {
@Override
public boolean bt() {
- return true;
+ return super.bt(); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java
index 2e448a40dbf2fa5b4df4493f14738210615bab38..d57e7c02268e5d8a00b0b5897fa03dcee10cd2e0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseZombie.java
@@ -13,6 +13,7 @@ import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMonsterType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat;
import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@@ -24,6 +25,18 @@ public class EntityHorseZombie extends EntityHorseAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.zombieHorseRidableInWater;
+ }
+
+ @Override
+ public boolean isTamed() {
+ return true;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder eL() {
return fi().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D);
}
@@ -95,5 +108,5 @@ public class EntityHorseZombie extends EntityHorseAbstract {
}
@Override
- protected void eV() {}
+ protected void eV() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java
index 1c6435bf2cd870b795f87368057d8dfc1e1c938a..d1bd7b9a6a8cfb6b609db4229b2f42a40b8b484f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java
@@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHorseHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -68,7 +69,46 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
public EntityLlama(EntityTypes<? extends EntityLlama> entitytypes, World world) {
super(entitytypes, world);
+ // Purpur start
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this) {
+ @Override
+ public void a() { // tick
+ if (entity.hasRider() && hasSaddle()) {
+ tick(entity.getRider());
+ } else {
+ tick();
+ }
+ }
+ };
+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) {
+ @Override
+ public void a() { // tick
+ if (entity.hasRider() && hasSaddle()) {
+ tick(entity.getRider());
+ } else {
+ tick();
+ }
+ }
+ };
+ // Purpur end
+ }
+
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.llamaRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.llamaRidableInWater;
+ }
+
+ @Override
+ public boolean hasSaddle() {
+ return super.hasSaddle() || (isTamed() && getColor() != null);
}
+ // Purpur end
public void setStrength(int i) {
this.datawatcher.set(EntityLlama.bx, Math.max(1, Math.min(5, i)));
@@ -116,6 +156,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalTame(this, 1.2D));
this.goalSelector.a(2, new PathfinderGoalLlamaFollow(this, 2.0999999046325684D));
this.goalSelector.a(3, new PathfinderGoalArrowAttack(this, 1.25D, 40, 20.0F));
@@ -125,6 +166,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
this.goalSelector.a(6, new PathfinderGoalRandomStrollLand(this, 0.7D));
this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHorseHasRider(this)); // Purpur
this.targetSelector.a(1, new EntityLlama.c(this));
this.targetSelector.a(2, new EntityLlama.a(this));
}
@@ -362,7 +404,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
}
@Nullable
- public EnumColor fy() {
+ public EnumColor fy() { return getColor(); } public EnumColor getColor() { // Purpur - OBFHELPER
int i = (Integer) this.datawatcher.get(EntityLlama.by);
return i == -1 ? null : EnumColor.fromColorIndex(i);
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java
index f761e37f7329342f01f04df5602573a51c0aca4e..0fb651bcde1109b0eb30b60226d3512648dceb41 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java
@@ -27,6 +27,23 @@ public class EntityLlamaTrader extends EntityLlama {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.llamaTraderRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.llamaTraderRidableInWater;
+ }
+
+ @Override
+ public boolean hasSaddle() {
+ return super.hasSaddle() || isTamed();
+ }
+ // Purpur end
+
@Override
protected EntityLlama fz() {
return (EntityLlama) EntityTypes.TRADER_LLAMA.a(this.world);
diff --git a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java
index f1065c2a37835d760fb57194f7edfd029f426b48..3f2065e2939be54639f44501f7aa8ee5500dfc84 100644
--- a/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java
+++ b/src/main/java/net/minecraft/world/entity/boss/EntityComplexPart.java
@@ -2,11 +2,14 @@ package net.minecraft.world.entity.boss;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.protocol.Packet;
+import net.minecraft.world.EnumHand;
+import net.minecraft.world.EnumInteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityPose;
import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon;
+import net.minecraft.world.entity.player.EntityHuman;
public class EntityComplexPart extends Entity {
@@ -55,4 +58,11 @@ public class EntityComplexPart extends Entity {
public EntitySize a(EntityPose entitypose) {
return this.d;
}
+
+ // Purpur start
+ @Override
+ public EnumInteractionResult a(EntityHuman entityhuman, EnumHand enumhand) {
+ return owner.isAlive() ? owner.tryRide(entityhuman, enumhand) : EnumInteractionResult.PASS;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java
index 3fff101637708a1a12f9a457bd3512ae94a8f884..7f583c6c15f0191219eb911d901ea28d86c11489 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java
@@ -23,6 +23,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityExperienceOrb;
import net.minecraft.world.entity.EntityInsentient;
import net.minecraft.world.entity.EntityLiving;
+import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.IEntitySelector;
@@ -95,6 +96,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
private final int[] bK = new int[24];
private final Path bL = new Path();
private Explosion explosionSource = new Explosion(null, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY); // CraftBukkit - reusable source for CraftTNTPrimed.getSource()
+ private boolean hadRider; // Purpur
public EntityEnderDragon(EntityTypes<? extends EntityEnderDragon> entitytypes, World world) {
super(EntityTypes.ENDER_DRAGON, world);
@@ -109,8 +111,44 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
}
this.bG = new DragonControllerManager(this);
+ // Purpur start
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlying(this) {
+ @Override
+ public void tick() {
+ // dragon doesn't use the controller. do nothing
+ }
+ };
+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) {
+ @Override
+ public void tick() {
+ // dragon doesn't use the controller. do nothing
+ }
+
+ @Override
+ public void tick(EntityHuman rider) {
+ setYawPitch(rider.yaw - 180F, rider.pitch * 0.5F);
+ }
+ };
+ // Purpur end
+ }
+
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.enderDragonRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.enderDragonRidableInWater;
}
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.enderDragonMaxY;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder m() {
return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 200.0D);
}
@@ -143,6 +181,37 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
@Override
public void movementTick() {
+ // Purpur start
+ boolean hasRider = getRider() != null;
+ if (hasRider) {
+ if (!hadRider) {
+ hadRider = true;
+ noclip = false;
+ this.size = EntitySize.b(4.0F, 2.0F);
+ }
+
+ // dragon doesn't use controllers, so must tick manually
+ moveController.a();
+ lookController.a();
+
+ moveRelative((float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F, new Vec3D(-getStrafe(), getVertical(), -getForward()));
+ Vec3D mot = getMot();
+ setMot(mot);
+ move(EnumMoveType.PLAYER, mot);
+
+ mot = mot.multiply(0.9F, 0.9F, 0.9F);
+ setMot(mot);
+
+ // control wing flap speed on client
+ getDragonControllerManager().setControllerPhase(mot.getX() * mot.getX() + mot.getZ() * mot.getZ() < 0.005F ? DragonControllerPhase.HOVER : DragonControllerPhase.HOLDING_PATTERN);
+ } else if (hadRider) {
+ hadRider = false;
+ noclip = true;
+ this.size = EntitySize.b(16.0F, 8.0F);
+ getDragonControllerManager().setControllerPhase(DragonControllerPhase.HOLDING_PATTERN); // HoldingPattern
+ }
+ // Purpur end
+
float f;
float f1;
@@ -164,6 +233,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
this.bp = this.bq;
if (this.dl()) {
+ if (hasRider) ejectPassengers(); // Purpur
f = (this.random.nextFloat() - 0.5F) * 8.0F;
f1 = (this.random.nextFloat() - 0.5F) * 4.0F;
float f2 = (this.random.nextFloat() - 0.5F) * 8.0F;
@@ -175,9 +245,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
f1 = 0.2F / (MathHelper.sqrt(c(vec3d)) * 10.0F + 1.0F);
f1 *= (float) Math.pow(2.0D, vec3d.y);
- if (this.bG.a().a()) {
+ if (!hasRider && this.bG.a().a()) { // Purpur
this.bq += 0.1F;
- } else if (this.br) {
+ } else if (!hasRider && this.br) { // Purpur
this.bq += f1 * 0.5F;
} else {
this.bq += f1;
@@ -221,7 +291,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
}
this.bG.a().b();
- } else {
+ } else if (!hasRider) { // Purpur
IDragonController idragoncontroller = this.bG.a();
idragoncontroller.c();
@@ -288,7 +358,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
this.a(this.bz, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F));
this.a(this.bD, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F));
this.a(this.bE, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F));
- if (!this.world.isClientSide && this.hurtTicks == 0) {
+ if (!hasRider && !this.world.isClientSide && this.hurtTicks == 0) { // Purpur
this.a(this.world.getEntities(this, this.bD.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e));
this.a(this.world.getEntities(this, this.bE.getBoundingBox().grow(4.0D, 2.0D, 4.0D).d(0.0D, -2.0D, 0.0D), IEntitySelector.e));
this.b(this.world.getEntities(this, this.bo.getBoundingBox().g(1.0D), IEntitySelector.e));
@@ -331,7 +401,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
}
if (!this.world.isClientSide) {
- this.br = this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox());
+ this.br = !hasRider && this.b(this.bo.getBoundingBox()) | this.b(this.by.getBoundingBox()) | this.b(this.bz.getBoundingBox()); // Purpur
if (this.bF != null) {
this.bF.b(this);
}
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java
index 930fc752ec0a988b17bc556cd428161638a14f27..4c0a555cdb5bc34c73040b9533beaee56cbce70a 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java
@@ -12,6 +12,7 @@ import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.BossBattleServer;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.sounds.SoundEffect;
@@ -20,6 +21,7 @@ import net.minecraft.tags.TagsBlock;
import net.minecraft.util.MathHelper;
import net.minecraft.world.BossBattle;
import net.minecraft.world.EnumDifficulty;
+import net.minecraft.world.EnumHand;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffects;
@@ -28,6 +30,7 @@ import net.minecraft.world.entity.EntityInsentient;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMonsterType;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
@@ -48,8 +51,12 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.IMaterial;
+import net.minecraft.world.level.RayTrace;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.world.phys.MovingObjectPosition;
+import net.minecraft.world.phys.MovingObjectPositionBlock;
+import net.minecraft.world.phys.MovingObjectPositionEntity;
import net.minecraft.world.phys.Vec3D;
// CraftBukkit start
@@ -82,6 +89,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei();
};
private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by);
+ private int shootCooldown = 0; // Purpur
// Paper start
private boolean canPortal = false;
@@ -94,15 +102,122 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
this.setHealth(this.getMaxHealth());
this.getNavigation().d(true);
this.f = 50;
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.1F); // Purpur
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.witherRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.witherRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.witherMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue() * 5F;
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 0.5, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ this.datawatcher.set(bo.get(0), 0);
+ this.datawatcher.set(bo.get(1), 0);
+ this.datawatcher.set(bo.get(2), 0);
+ getNavigation().stopPathfinding();
+ shootCooldown = 20;
+ }
+
+ @Override
+ public boolean onClick(EnumHand hand) {
+ return shoot(getRider(), hand == EnumHand.MAIN_HAND ? new int[]{1} : new int[]{2});
+ }
+
+ public boolean shoot(EntityHuman rider, int[] heads) {
+ if (shootCooldown > 0) {
+ return false;
+ }
+
+ shootCooldown = 20;
+ if (rider == null) {
+ return false;
+ }
+
+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = rider.getBukkitEntity();
+ if (!player.hasPermission("allow.special.wither")) {
+ return false;
+ }
+
+ MovingObjectPosition rayTrace = getRayTrace(120, RayTrace.FluidCollisionOption.NONE);
+ if (rayTrace == null) {
+ return false;
+ }
+
+ Vec3D loc;
+ if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) {
+ BlockPosition pos = ((MovingObjectPositionBlock) rayTrace).getBlockPosition();
+ loc = new Vec3D(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D);
+ } else if (rayTrace.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY) {
+ Entity target = ((MovingObjectPositionEntity) rayTrace).getEntity();
+ loc = new Vec3D(target.locX(), target.locY() + (target.getHeadHeight() / 2), target.locZ());
+ } else {
+ org.bukkit.block.Block block = player.getTargetBlock(null, 120);
+ loc = new Vec3D(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D);
+ }
+
+ for (int head : heads) {
+ shoot(head, loc.getX(), loc.getY(), loc.getZ(), rider);
+ }
+
+ return true; // handled
+ }
+
+ public void shoot(int head, double x, double y, double z, EntityHuman rider) {
+ world.playEvent(null, 1024, getChunkCoordinates(), 0);
+ double headX = getHeadX(head);
+ double headY = getHeadY(head);
+ double headZ = getHeadZ(head);
+ EntityWitherSkull skull = new EntityWitherSkull(world, this, x - headX, y - headY, z - headZ) {
+ @Override
+ public boolean canSaveToDisk() {
+ return false;
+ }
+
+ @Override
+ public boolean hitPredicate(Entity target) {
+ // do not hit rider
+ return target != rider && super.hitPredicate(target);
+ }
+ };
+ skull.setPositionRaw(headX, headY, headZ);
+ world.addEntity(skull);
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
- this.goalSelector.a(0, new EntityWither.a());
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.goalSelector.a(1, new EntityWither.a()); // Purpur
this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 40, 20.0F));
this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0]));
if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by));
@@ -245,6 +360,16 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
@Override
protected void mobTick() {
+ // Purpur start
+ if (hasRider()) {
+ Vec3D mot = getMot();
+ setMot(mot.x, mot.y + (getVertical() > 0 ? 0.07D : 0.0D), mot.z);
+ }
+ if (shootCooldown > 0) {
+ shootCooldown--;
+ }
+ // Purpur end
+
int i;
if (this.getInvul() > 0) {
@@ -428,7 +553,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
this.bossBattle.removePlayer(entityplayer);
}
- private double u(int i) {
+ private double u(int i) { return getHeadX(i); } private double getHeadX(int i) { // Purpur - OBFHELPER
if (i <= 0) {
return this.locX();
} else {
@@ -439,11 +564,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
}
}
- private double v(int i) {
+ private double v(int i) { return getHeadY(i); } private double getHeadY(int i) { // Purpur - OBFHELPER
return i <= 0 ? this.locY() + 3.0D : this.locY() + 2.2D;
}
- private double w(int i) {
+ private double w(int i) { return getHeadZ(i); } private double getHeadZ(int i) { // Purpur - OBFHELPER
if (i <= 0) {
return this.locZ();
} else {
@@ -567,7 +692,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
}
public static AttributeProvider.Builder eK() {
- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D);
+ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 300.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.6000000238418579D).a(GenericAttributes.FOLLOW_RANGE, 40.0D).a(GenericAttributes.ARMOR, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur
}
public int getInvul() {
@@ -579,11 +704,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
}
public int getHeadTarget(int i) {
- return (Integer) this.datawatcher.get((DataWatcherObject) EntityWither.bo.get(i));
+ return hasRider() ? 0 : this.datawatcher.get(EntityWither.bo.get(i)); // Purpur
}
public void setHeadTarget(int i, int j) {
- this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j);
+ if (!hasRider()) this.datawatcher.set(EntityWither.bo.get(i), j); // Purpur
}
public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java
index 88a4dcf9feaa5f66da1394c139b795582c00a8ac..9a109ed062e5abedaad295383aca6441321da276 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityBlaze.java
@@ -5,6 +5,7 @@ import net.minecraft.core.particles.Particles;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -12,6 +13,7 @@ import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
@@ -35,6 +37,7 @@ public class EntityBlaze extends EntityMonster {
public EntityBlaze(EntityTypes<? extends EntityBlaze> entitytypes, World world) {
super(entitytypes, world);
+ this.moveController = new net.pl3x.purpur.controller.ControllerMoveWASDFlyingWithSpacebar(this, 0.3F); // Purpur
this.a(PathType.WATER, -1.0F);
this.a(PathType.LAVA, 8.0F);
this.a(PathType.DANGER_FIRE, 0.0F);
@@ -42,19 +45,50 @@ public class EntityBlaze extends EntityMonster {
this.f = 10;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.blazeRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.blazeRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.blazeMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue();
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(4, new EntityBlaze.PathfinderGoalBlazeFireball(this));
this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D, 0.0F));
this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a());
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // Purpur - decompile error
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
}
public static AttributeProvider.Builder m() {
- return EntityMonster.eR().a(GenericAttributes.ATTACK_DAMAGE, 6.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.23000000417232513D).a(GenericAttributes.FOLLOW_RANGE, 48.0D);
+ return EntityMonster.eR().a(GenericAttributes.ATTACK_DAMAGE, 6.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.23000000417232513D).a(GenericAttributes.FOLLOW_RANGE, 48.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur
}
@Override
@@ -109,6 +143,14 @@ public class EntityBlaze extends EntityMonster {
@Override
protected void mobTick() {
+ // Purpur start
+ if (hasRider()) {
+ Vec3D mot = getMot();
+ setMot(mot.x, getVertical() > 0 ? 0.07D : -0.07D, mot.z);
+ return;
+ }
+ // Purpur end
+
--this.c;
if (this.c <= 0) {
this.c = 100;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java
index 65d0027186f19f10292ea64976ebb93c12b98394..27baf5cde99d8f25b1e7583c30339fcc71a3786f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCaveSpider.java
@@ -24,6 +24,18 @@ public class EntityCaveSpider extends EntitySpider {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.caveSpiderRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.caveSpiderRidableInWater;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder m() {
return EntitySpider.eK().a(GenericAttributes.MAX_HEALTH, 12.0D);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java
index 09df2bd3b523072de0e9858e6e707e3721474422..2cb9908a5c53528b2e02a1231752adc5ad8354f8 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java
@@ -6,6 +6,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -58,12 +59,27 @@ public class EntityCreeper extends EntityMonster {
public int maxFuseTicks = 30;
public int explosionRadius = 3;
private int bs;
+ // Purpur start
+ private int spacebarCharge = 0;
+ private int prevSpacebarCharge = 0;
+ private int powerToggleDelay = 0;
+ // Purpur end
public EntityCreeper(EntityTypes<? extends EntityCreeper> entitytypes, World world) {
super(entitytypes, world);
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.creeperRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.creeperRidableInWater;
+ }
+
@Override
public GroupDataEntity prepare(WorldAccess worldaccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @javax.annotation.Nullable GroupDataEntity groupdataentity, @javax.annotation.Nullable NBTTagCompound nbttagcompound) {
double chance = worldaccess.getMinecraftWorld().purpurConfig.creeperChargedChance;
@@ -72,18 +88,69 @@ public class EntityCreeper extends EntityMonster {
}
return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound);
}
+
+ @Override
+ protected void mobTick() {
+ if (powerToggleDelay > 0) {
+ powerToggleDelay--;
+ }
+ if (hasRider()) {
+ if (getRider().getForward() != 0 || getRider().getStrafe() != 0) {
+ spacebarCharge = 0;
+ setIgnited(false);
+ }
+ if (spacebarCharge == prevSpacebarCharge) {
+ spacebarCharge = 0;
+ }
+ prevSpacebarCharge = spacebarCharge;
+ }
+ super.mobTick();
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ setIgnited(false);
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (powerToggleDelay > 0) {
+ return true; // just toggled power, do not jump or ignite
+ }
+ spacebarCharge++;
+ if (spacebarCharge > maxFuseTicks - 2) {
+ spacebarCharge = 0;
+ if (getRider().getBukkitEntity().hasPermission("allow.powered.creeper")) {
+ powerToggleDelay = 20;
+ setPowered(!isPowered());
+ setIgnited(false);
+ return true;
+ }
+ }
+ if (!isIgnited()) {
+ if (hasRider() && getRider().getForward() == 0 && getRider().getStrafe() == 0 &&
+ getRider().getBukkitEntity().hasPermission("allow.special.creeper")) {
+ setIgnited(true);
+ return true;
+ }
+ }
+ return getForward() == 0 && getStrafe() == 0; // do not jump if standing still
+ }
// Purpur end
@Override
protected void initPathfinder() {
this.goalSelector.a(1, new PathfinderGoalFloat(this));
this.goalSelector.a(2, new PathfinderGoalSwell(this));
+ this.goalSelector.a(3, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityOcelot.class, 6.0F, 1.0D, 1.2D));
this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityCat.class, 6.0F, 1.0D, 1.2D));
this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.8D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0]));
}
@@ -214,6 +281,7 @@ public class EntityCreeper extends EntityMonster {
return (Integer) this.datawatcher.get(EntityCreeper.b);
}
+ public void setSwellDirection(int i) { a(i); } // Purpur - OBFHELPER
public void a(int i) {
this.datawatcher.set(EntityCreeper.b, i);
}
@@ -314,6 +382,7 @@ public class EntityCreeper extends EntityMonster {
com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited);
if (event.callEvent()) {
this.datawatcher.set(EntityCreeper.d, event.isIgnited());
+ if (!event.isIgnited()) setSwellDirection(-1); // Purpur
}
}
// Paper end
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java
index ea776755767f29e49de2792afa30f79420d0fa4c..1d4039d61a2c77a38a31947010cee26f41c0becd 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java
@@ -73,6 +73,16 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.drownedRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.drownedRidableInWater;
+ }
+
@Override
public boolean jockeyOnlyBaby() {
return world.purpurConfig.drownedJockeyOnlyBaby;
@@ -270,7 +280,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity {
this.d = flag;
}
- static class d extends ControllerMove {
+ static class d extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
private final EntityDrowned i;
@@ -280,7 +290,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity {
}
@Override
- public void a() {
+ public void tick() { // Purpur
EntityLiving entityliving = this.i.getGoalTarget();
if (this.i.eW() && this.i.isInWater()) {
@@ -313,7 +323,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity {
this.i.setMot(this.i.getMot().add(0.0D, -0.008D, 0.0D));
}
- super.a();
+ super.tick(); // Purpur
}
}
@@ -452,6 +462,7 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity {
this.a = entitydrowned;
this.b = d0;
this.c = i;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - swim up
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java
index 52aa47036acee2ec21ae2d6f4df634ecbf04b3b0..03fa2cfc1d5bc27e03e9979b3f33d88362c19066 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java
@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -85,9 +86,22 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
this.a(PathType.WATER, -1.0F);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.endermanRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.endermanRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityEnderman.a(this));
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D, 0.0F));
@@ -95,6 +109,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
this.goalSelector.a(10, new EntityEnderman.PathfinderGoalEndermanPlaceBlock(this));
this.goalSelector.a(11, new EntityEnderman.PathfinderGoalEndermanPickupBlock(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new EntityEnderman.PathfinderGoalPlayerWhoLookedAtTarget(this, this::a_));
this.targetSelector.a(2, new PathfinderGoalHurtByTarget(this, new Class[0]));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityEndermite.class, 10, true, false, EntityEnderman.bq));
@@ -275,7 +290,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
@Override
protected void mobTick() {
- if (this.world.isDay() && this.ticksLived >= this.bs + 600) {
+ if (!hasRider() && this.world.isDay() && this.ticksLived >= this.bs + 600) { // Purpur - no random teleporting
float f = this.aR();
if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper
@@ -384,6 +399,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
if (this.isInvulnerable(damagesource)) {
return false;
} else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && damagesource == DamageSource.STUCK) { return false; // Purpur - no suffocation damage if short height
+ } else if (hasRider()) { return super.damageEntity(damagesource, f); // Purpur - no teleporting on damage
} else if (damagesource instanceof EntityDamageSourceIndirect) {
if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start
for (int i = 0; i < 64; ++i) {
@@ -428,6 +444,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
public PathfinderGoalEndermanPickupBlock(EntityEnderman entityenderman) {
this.enderman = entityenderman;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur
}
@Override
@@ -470,6 +487,7 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable {
public PathfinderGoalEndermanPlaceBlock(EntityEnderman entityenderman) {
this.a = entityenderman;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java
index 906ac1f861241a184819b4b113abe56625ff5e60..1c87bea9de812e57f8ccd3c9aa85330af87ed240 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEndermite.java
@@ -4,6 +4,7 @@ import java.util.Random;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.particles.Particles;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.world.damagesource.DamageSource;
@@ -36,14 +37,28 @@ public class EntityEndermite extends EntityMonster {
this.f = 3;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.endermiteRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.endermiteRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(3, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector.a(7, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a());
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // Purpur - decompile error
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java
index 2aa6b6ca93c25c59ad224348aad1bb34d9bbc6a3..55607910183155080e3d96296421438d17f19c8f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java
@@ -5,6 +5,7 @@ import javax.annotation.Nullable;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.EnumDirection;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -19,6 +20,7 @@ import net.minecraft.world.entity.EnumMonsterType;
import net.minecraft.world.entity.GroupDataEntity;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget;
import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat;
import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer;
@@ -47,10 +49,23 @@ public class EntityEvoker extends EntityIllagerWizard {
this.f = 10;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.evokerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.evokerRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityEvoker.b());
this.goalSelector.a(2, new PathfinderGoalAvoidTarget<>(this, EntityHuman.class, 8.0F, 0.6D, 1.0D));
this.goalSelector.a(4, new EntityEvoker.c());
@@ -59,6 +74,7 @@ public class EntityEvoker extends EntityIllagerWizard {
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
@@ -139,6 +155,7 @@ public class EntityEvoker extends EntityIllagerWizard {
public d() {
super();
+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - wolololo spell
}
@Override
@@ -217,6 +234,7 @@ public class EntityEvoker extends EntityIllagerWizard {
private c() {
super();
this.e = (new PathfinderTargetCondition()).a(16.0D).c().e().a().b();
+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - summon spell
}
@Override
@@ -273,6 +291,7 @@ public class EntityEvoker extends EntityIllagerWizard {
private a() {
super();
+ this.a(java.util.EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur - attack with spell
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java
index a3e3f6e07674c54c2d2a02661ce4342b43aafe44..8784647f512d280ee0a092ecd406321268359314 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGhast.java
@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -21,6 +22,7 @@ import net.minecraft.world.entity.EntityPose;
import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMobSpawn;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.control.ControllerMove;
@@ -44,11 +46,42 @@ public class EntityGhast extends EntityFlying implements IMonster {
this.moveController = new EntityGhast.ControllerGhast(this);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.ghastRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.ghastRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.ghastMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue();
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(5, new EntityGhast.PathfinderGoalGhastIdleMove(this));
this.goalSelector.a(7, new EntityGhast.PathfinderGoalGhastMoveTowardsTarget(this));
this.goalSelector.a(7, new EntityGhast.PathfinderGoalGhastAttackTarget(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> {
return Math.abs(entityliving.locY() - this.locY()) <= 4.0D;
}));
@@ -86,7 +119,7 @@ public class EntityGhast extends EntityFlying implements IMonster {
}
public static AttributeProvider.Builder eJ() {
- return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 10.0D).a(GenericAttributes.FOLLOW_RANGE, 100.0D);
+ return EntityInsentient.p().a(GenericAttributes.MAX_HEALTH, 10.0D).a(GenericAttributes.FOLLOW_RANGE, 100.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur
}
@Override
@@ -285,7 +318,7 @@ public class EntityGhast extends EntityFlying implements IMonster {
}
}
- static class ControllerGhast extends ControllerMove {
+ static class ControllerGhast extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur
private final EntityGhast i;
private int j;
@@ -296,7 +329,7 @@ public class EntityGhast extends EntityFlying implements IMonster {
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.h == ControllerMove.Operation.MOVE_TO) {
if (this.j-- <= 0) {
this.j += this.i.getRandom().nextInt(5) + 2;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java
index a188a89143cb1b0243dacdec33c446ca4120219f..7395fa90198a9138b2c33273d8f3540355300029 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGiantZombie.java
@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster;
import net.minecraft.core.BlockPosition;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.world.DifficultyDamageScaler;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.entity.EntityPose;
@@ -41,16 +42,28 @@ public class EntityGiantZombie extends EntityMonster {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.giantRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.giantRidableInWater;
+ }
+
@Override
protected void initPathfinder() {
if (world.purpurConfig.giantHaveAI) {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 16.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
this.goalSelector.a(5, new PathfinderGoalMoveTowardsRestriction(this, 1.0D));
if (world.purpurConfig.giantHaveHostileAI) {
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(EntityPigZombie.class));
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillager.class, false));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java
index d53e2a9d27f9976d1fd8ea30b88a0da089aec7b6..6980b6988549b37a33d204a6e84c9e81d384a57a 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardian.java
@@ -9,6 +9,7 @@ import net.minecraft.core.particles.Particles;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.tags.Tag;
@@ -63,15 +64,36 @@ public class EntityGuardian extends EntityMonster {
this.f = 10;
this.a(PathType.WATER, 0.0F);
this.moveController = new EntityGuardian.ControllerMoveGuardian(this);
+ // Purpur start
+ this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this) {
+ @Override
+ public void setYawPitch(float yaw, float pitch) {
+ super.setYawPitch(yaw, pitch * 0.35F);
+ }
+ };
+ // Purpur end
this.bo = this.random.nextFloat();
this.bp = this.bo;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.guardianRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
PathfinderGoalMoveTowardsRestriction pathfindergoalmovetowardsrestriction = new PathfinderGoalMoveTowardsRestriction(this, 1.0D);
this.goalRandomStroll = new PathfinderGoalRandomStroll(this, 1.0D, 80);
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(4, new EntityGuardian.PathfinderGoalGuardianAttack(this));
this.goalSelector.a(5, pathfindergoalmovetowardsrestriction);
this.goalSelector.a(7, this.goalRandomStroll);
@@ -80,6 +102,7 @@ public class EntityGuardian extends EntityMonster {
this.goalSelector.a(9, new PathfinderGoalRandomLookaround(this));
this.goalRandomStroll.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK));
pathfindergoalmovetowardsrestriction.a(EnumSet.of(PathfinderGoal.Type.MOVE, PathfinderGoal.Type.LOOK));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityLiving.class, 10, true, false, new EntityGuardian.EntitySelectorGuardianTargetHumanSquid(this)));
}
@@ -113,6 +136,7 @@ public class EntityGuardian extends EntityMonster {
return (Boolean) this.datawatcher.get(EntityGuardian.b);
}
+ private void setMovingFlag(boolean movingFlag) { t(movingFlag); } // Purpur - OBFHELPER
private void t(boolean flag) {
this.datawatcher.set(EntityGuardian.b, flag);
}
@@ -327,7 +351,7 @@ public class EntityGuardian extends EntityMonster {
@Override
public void g(Vec3D vec3d) {
if (this.doAITick() && this.isInWater()) {
- this.a(0.1F, vec3d);
+ this.a(hasRider() ? getSpeed() : 0.1F, vec3d); // Purpur
this.move(EnumMoveType.SELF, this.getMot());
this.setMot(this.getMot().a(0.9D));
if (!this.eN() && this.getGoalTarget() == null) {
@@ -339,17 +363,26 @@ public class EntityGuardian extends EntityMonster {
}
- static class ControllerMoveGuardian extends ControllerMove {
+ static class ControllerMoveGuardian extends net.pl3x.purpur.controller.ControllerMoveWASDWater { // Purpur
- private final EntityGuardian i;
+ private final EntityGuardian i; private EntityGuardian getGuardian() { return i; } // Purpur - OBFHELPER
public ControllerMoveGuardian(EntityGuardian entityguardian) {
super(entityguardian);
this.i = entityguardian;
}
+ // Purpur start
+ @Override
+ public void tick(EntityHuman rider) {
+ super.tick(rider);
+ getGuardian().setMot(getGuardian().getMot().add(0.0D, 0.005D, 0.0D));
+ getGuardian().setMovingFlag(getGuardian().getForward() > 0.0F); // control tail speed
+ }
+ // Purpur end
+
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.h == ControllerMove.Operation.MOVE_TO && !this.i.getNavigation().m()) {
Vec3D vec3d = new Vec3D(this.b - this.i.locX(), this.c - this.i.locY(), this.d - this.i.locZ());
double d0 = vec3d.f();
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java
index 9bd6f5d988c1e50e1bb729c407178b9cbcc62115..16b8606be2835dccdfa75f29827be4b88aaa1810 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java
@@ -30,6 +30,18 @@ public class EntityGuardianElder extends EntityGuardian {
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.elderGuardianRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return true;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder m() {
return EntityGuardian.eM().a(GenericAttributes.MOVEMENT_SPEED, 0.30000001192092896D).a(GenericAttributes.ATTACK_DAMAGE, 8.0D).a(GenericAttributes.MAX_HEALTH, 80.0D);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java
index cb092bee9d6827d4b0276bfa9b033cf7ca86ead4..5186d9957c94be359da5b08fd821e9471c159f03 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java
@@ -3,6 +3,7 @@ package net.minecraft.world.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.core.particles.Particles;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -57,6 +58,16 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.illusionerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.illusionerRidableInWater;
+ }
+
@Override
protected void initAttributes() {
this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(this.world.purpurConfig.illusionerMovementSpeed);
@@ -69,6 +80,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityIllagerWizard.b());
this.goalSelector.a(4, new EntityIllagerIllusioner.b());
this.goalSelector.a(5, new EntityIllagerIllusioner.a());
@@ -76,6 +88,7 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java
index fe80e93b00f3bb2f297c6528c3951313fa3c08c7..15ed51a2746c09538a425fce25fa25f2619b7033 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMagmaCube.java
@@ -29,6 +29,23 @@ public class EntityMagmaCube extends EntitySlime {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.magmaCubeRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.magmaCubeRidableInWater;
+ }
+
+ @Override
+ public float getJumpHeight() {
+ return 0.42F * this.getBlockJumpFactor(); // from EntityLiving
+ }
+ // Purpur end
+
public static AttributeProvider.Builder m() {
return EntityMonster.eR().a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D);
}
@@ -79,11 +96,12 @@ public class EntityMagmaCube extends EntitySlime {
}
@Override
- protected void jump() {
+ public void jump() { // Purpur - protected -> public
Vec3D vec3d = this.getMot();
this.setMot(vec3d.x, (double) (this.dJ() + (float) this.getSize() * 0.1F), vec3d.z);
this.impulse = true;
+ this.actualJump = false; // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
index 07ede7b75a65a5815f1ae1ebf03ec0fdb4621afb..a836839b17cbda8ac269f032b141ba448e3bab8c 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
@@ -13,6 +13,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.level.WorldServer;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -29,11 +30,11 @@ import net.minecraft.world.entity.EntitySize;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMobSpawn;
import net.minecraft.world.entity.EnumMonsterType;
+import net.minecraft.world.entity.EnumMoveType;
import net.minecraft.world.entity.GroupDataEntity;
import net.minecraft.world.entity.IEntitySelector;
+import net.minecraft.world.entity.ai.attributes.AttributeProvider;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
-import net.minecraft.world.entity.ai.control.ControllerLook;
-import net.minecraft.world.entity.ai.control.ControllerMove;
import net.minecraft.world.entity.ai.control.EntityAIBodyControl;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
@@ -68,6 +69,59 @@ public class EntityPhantom extends EntityFlying implements IMonster {
this.lookController = new EntityPhantom.f(this);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.phantomRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.phantomRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.phantomMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider() && !onGround) {
+ float speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue();
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, speed, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+
+ public static AttributeProvider.Builder defaultAttributes() {
+ return EntityMonster.eR().a(GenericAttributes.FLYING_SPEED, 3.0D);
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (hasRider() && getRider().getBukkitEntity().hasPermission("allow.special.phantom")) {
+ shoot();
+ }
+ return false;
+ }
+
+ public boolean shoot() {
+ org.bukkit.Location loc = ((org.bukkit.entity.LivingEntity) getBukkitEntity()).getEyeLocation();
+ loc.setPitch(-loc.getPitch());
+ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(100).add(loc.toVector());
+
+ net.pl3x.purpur.entity.PhantomFlames flames = new net.pl3x.purpur.entity.PhantomFlames(world, this);
+ flames.canGrief = world.purpurConfig.phantomAllowGriefing;
+ flames.shoot(target.getX() - locX(), target.getY() - locY(), target.getZ() - locZ(), 1.0F, 5.0F);
+ world.addEntity(flames);
+ return true;
+ }
+ // Purpur end
+
@Override
protected EntityAIBodyControl r() {
return new EntityPhantom.d(this);
@@ -76,6 +130,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
protected void initPathfinder() {
// Purpur start
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this));
if (world.purpurConfig.phantomOrbitCrystalRadius > 0) {
this.goalSelector.a(1, new FindCrystalGoal(this));
this.goalSelector.a(2, new OrbitCrystalGoal(this));
@@ -83,6 +138,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
this.goalSelector.a(3, new EntityPhantom.c()); // PickAttackGoal
this.goalSelector.a(4, new EntityPhantom.i()); // SweepAttackGoal
this.goalSelector.a(5, new EntityPhantom.e()); // OrbitPointGoal
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this));
this.targetSelector.a(1, new EntityPhantom.b()); // AttackPlayer Goal
// Purpur end
}
@@ -169,7 +225,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public void movementTick() {
- if (this.isAlive() && ((world.purpurConfig.phantomBurnInDaylight && this.isInDaylight()) || (world.purpurConfig.phantomBurnInLight > 0 && world.getLightLevel(new BlockPosition(this)) >= world.purpurConfig.phantomBurnInLight))) { // Purpur
+ if (this.isAlive() && !hasRider() && ((world.purpurConfig.phantomBurnInDaylight && this.isInDaylight()) || (world.purpurConfig.phantomBurnInLight > 0 && world.getLightLevel(new BlockPosition(this)) >= world.purpurConfig.phantomBurnInLight))) { // Purpur
this.setOnFire(8);
}
@@ -412,7 +468,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean a() {
- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
+ if (getRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
if (this.c > 0) {
--this.c;
return false;
@@ -441,7 +497,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean b() {
- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
+ if (getRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false;
@@ -456,7 +512,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
@Override
public boolean a() {
- if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
+ if (getRider() != null || isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false;
@@ -654,14 +710,23 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
}
- class f extends ControllerLook {
+ class f extends net.pl3x.purpur.controller.ControllerLookWASD { // Purpur
public f(EntityInsentient entityinsentient) {
super(entityinsentient);
}
@Override
- public void a() {}
+ // Purpur start
+ public void tick(EntityHuman rider) {
+ setYawPitch(rider.yaw, -rider.pitch * 0.75F);
+ }
+
+ @Override
+ public void tick() {
+ // do nothing
+ }
+ // Purpur end
}
class d extends EntityAIBodyControl {
@@ -677,7 +742,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
}
- class g extends ControllerMove {
+ class g extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur
private float j = 0.1F;
@@ -686,7 +751,19 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
@Override
- public void a() {
+ // Purpur start
+ public void tick(EntityHuman rider) {
+ if (!EntityPhantom.this.onGround) {
+ // phantom is always in motion when flying
+ // TODO - FIX THIS
+ // rider.setForward(1.0F);
+ }
+ super.tick(rider);
+ }
+
+ @Override
+ public void tick() {
+ // Purpur end
if (EntityPhantom.this.positionChanged) {
EntityPhantom.this.yaw += 180.0F;
this.j = 0.1F;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java
index af00a4245ca39f208810d1ec758e512cbf5648f3..816a2bd7438f66a5d7ff761b8fcf8b42483561c7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java
@@ -56,6 +56,16 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.zombifiedPiglinRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.zombifiedPiglinRidableInWater;
+ }
+
@Override
public boolean jockeyOnlyBaby() {
return world.purpurConfig.zombifiedPiglinJockeyOnlyBaby;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java
index ea105fb86553f5212d616c976eaf2a16bf5b6561..2a4ac6e608650d56cc2b564e715b7b685e7f3f62 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPillager.java
@@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.world.DifficultyDamageScaler;
@@ -61,15 +62,29 @@ public class EntityPillager extends EntityIllagerAbstract implements ICrossbow {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.pillagerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.pillagerRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new EntityRaider.a(this, 10.0F));
this.goalSelector.a(3, new PathfinderGoalCrossbowAttack<>(this, 1.0D, 8.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 15.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 15.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java
index 16d5cae64887b82e67eeb61ccb714e6125ff0c09..dc1ca7b334e89b4d0be775b6f6e6f4222ea02dcc 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java
@@ -7,6 +7,7 @@ import javax.annotation.Nullable;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.particles.Particles;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.tags.Tag;
@@ -61,14 +62,37 @@ public class EntityRavager extends EntityRaider {
this.f = 20;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.ravagerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.ravagerRidableInWater;
+ }
+
+ @Override
+ public void onMount(EntityHuman entityhuman) {
+ super.onMount(entityhuman);
+ getNavigation().stopPathfinding();
+
+ double speed = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getBaseValue();
+ getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(speed);
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(4, new EntityRavager.a());
this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.4D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 6.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(2, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(4, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true));
@@ -140,7 +164,7 @@ public class EntityRavager extends EntityRaider {
@Override
public void movementTick() {
super.movementTick();
- if (this.isAlive()) {
+ if (this.isAlive() && !hasRider()) {
if (this.isFrozen()) {
this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.0D);
} else {
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java
index bfecaa56c3d93436d71082f1398e0ceb12336e38..0294ab119407dc45a40c8444fb5a91e154017234 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityShulker.java
@@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -71,12 +72,26 @@ public class EntityShulker extends EntityGolem implements IMonster {
this.f = 5;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.shulkerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.shulkerRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(4, new EntityShulker.a());
this.goalSelector.a(7, new EntityShulker.e());
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(2, new EntityShulker.d(this));
this.targetSelector.a(3, new EntityShulker.c(this));
@@ -560,7 +575,7 @@ public class EntityShulker extends EntityGolem implements IMonster {
private int b;
- private e() {}
+ private e() { this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); } // Purpur - peek
@Override
public boolean a() {
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java
index e1fcb1be102822e87eaf7757fbd64a516b2f58ac..c0601af022d85c7b03463f0df975d713c0366b2c 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java
@@ -4,6 +4,7 @@ import java.util.EnumSet;
import java.util.Random;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.EnumDirection;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.world.damagesource.DamageSource;
@@ -38,13 +39,27 @@ public class EntitySilverfish extends EntityMonster {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.silverfishRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.silverfishRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.b = new EntitySilverfish.PathfinderGoalSilverfishWakeOthers(this);
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(3, this.b);
this.goalSelector.a(4, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(5, new EntitySilverfish.PathfinderGoalSilverfishHideInBlock(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[0])).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
}
@@ -204,6 +219,7 @@ public class EntitySilverfish extends EntityMonster {
public PathfinderGoalSilverfishWakeOthers(EntitySilverfish entitysilverfish) {
this.silverfish = entitysilverfish;
+ this.a(EnumSet.of(PathfinderGoal.Type.UNKNOWN_BEHAVIOR)); // Purpur
}
public void g() {
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java
index 342bc9b586ef835e865d6f84bf66f1069ab10f00..0b8517d4e83d14ddf8b6d1f1cf4c538f9e4cc68f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeleton.java
@@ -15,6 +15,18 @@ public class EntitySkeleton extends EntitySkeletonAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.skeletonRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.skeletonRidableInWater;
+ }
+ // Purpur end
+
@Override
protected SoundEffect getSoundAmbient() {
return SoundEffects.ENTITY_SKELETON_AMBIENT;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java
index 06d50b22ede102556fdb3e2a6f1424f7ff13f120..7ec60987229927e5fe7164f1d4eae8222832e920 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java
@@ -5,6 +5,7 @@ import java.time.temporal.ChronoField;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPosition;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -70,12 +71,14 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new PathfinderGoalRestrictSun(this));
this.goalSelector.a(3, new PathfinderGoalFleeSun(this, 1.0D));
this.goalSelector.a(3, new PathfinderGoalAvoidTarget<>(this, EntityWolf.class, 6.0F, 1.0D, 1.2D));
this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0]));
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java
index 8481b8fffed3f1f60e2e72e115e79e9ae1aaa635..8484000a1b0d9c252d6fab205b1e316e3f6f33bd 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonStray.java
@@ -21,6 +21,18 @@ public class EntitySkeletonStray extends EntitySkeletonAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.strayRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.strayRidableInWater;
+ }
+ // Purpur end
+
public static boolean a(EntityTypes<EntitySkeletonStray> entitytypes, WorldAccess worldaccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) {
return b(entitytypes, worldaccess, enummobspawn, blockposition, random) && (enummobspawn == EnumMobSpawn.SPAWNER || worldaccess.e(blockposition));
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java
index a90ac635ef7aef5289d21f948db7b170b23160d3..cb52c4e63ac487d55dc16accca6976f44f904112 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonWither.java
@@ -34,6 +34,18 @@ public class EntitySkeletonWither extends EntitySkeletonAbstract {
this.a(PathType.LAVA, 8.0F);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.witherSkeletonRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.witherSkeletonRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityPiglinAbstract.class, true));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java
index 0af0b232ff1b6f1d58cf3fb543d32bd108be0af7..0cbe3032fd3b048b0eb8ec3d8592a662c69c9e30 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java
@@ -14,6 +14,7 @@ import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.resources.MinecraftKey;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -74,12 +75,45 @@ public class EntitySlime extends EntityInsentient implements IMonster {
this.moveController = new EntitySlime.ControllerMoveSlime(this);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.slimeRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.slimeRidableInWater;
+ }
+
+ protected boolean actualJump;
+
+ @Override
+ public float getJumpHeight() {
+ float height = super.getJumpHeight();
+ return hasRider() && actualJump ? height * 1.5F : height;
+ }
+
+ @Override
+ public boolean onSpacebar() {
+ if (onGround && hasRider()) {
+ actualJump = true;
+ if (getRider().getForward() == 0 || getRider().getStrafe() == 0) {
+ jump(); // jump() here if not moving
+ }
+ }
+ return true; // do not jump() in wasd controller, let vanilla controller handle
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
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(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, (entityliving) -> {
return Math.abs(entityliving.locY() - this.locY()) <= 4.0D;
}));
@@ -365,11 +399,12 @@ public class EntitySlime extends EntityInsentient implements IMonster {
}
@Override
- protected void jump() {
+ public void jump() { // Purpur - protected -> public
Vec3D vec3d = this.getMot();
this.setMot(vec3d.x, (double) this.dJ(), vec3d.z);
this.impulse = true;
+ this.actualJump = false; // Purpur
}
@Nullable
@@ -538,10 +573,10 @@ public class EntitySlime extends EntityInsentient implements IMonster {
// Paper end
}
- static class ControllerMoveSlime extends ControllerMove {
+ static class ControllerMoveSlime extends net.pl3x.purpur.controller.ControllerMoveWASD { // Purpur
private float i;
- private int j;
+ private int j; private int getJumpDelay() { return j; } private void setJumpDelay(int delay) { j = delay; } // Purpur - OBFHELPER
private final EntitySlime k;
private boolean l;
@@ -563,15 +598,27 @@ public class EntitySlime extends EntityInsentient implements IMonster {
@Override
public void a() {
+ // Purpur start
+ if (entity.hasRider()) {
+ tick(entity.getRider());
+ if (entity.getForward() != 0 || entity.getStrafe() != 0) {
+ if (getJumpDelay() > 10) {
+ setJumpDelay(6);
+ }
+ } else {
+ setJumpDelay(20);
+ }
+ } else {
+ // Purpur end
this.a.yaw = this.a(this.a.yaw, this.i, 90.0F);
this.a.aC = this.a.yaw;
this.a.aA = this.a.yaw;
- if (this.h != ControllerMove.Operation.MOVE_TO) {
+ } if (!entity.hasRider() && this.h != ControllerMove.Operation.MOVE_TO) { // Purpur
this.a.t(0.0F);
} else {
this.h = ControllerMove.Operation.WAIT;
if (this.a.isOnGround()) {
- this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED)));
+ this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED) * (entity.hasRider() && (entity.getRider().getForward() != 0 || entity.getRider().getStrafe() != 0) ? 2.0D : 1.0D))); // Purpur
if (this.j-- <= 0) {
this.j = this.k.eJ();
if (this.l) {
@@ -588,7 +635,7 @@ public class EntitySlime extends EntityInsentient implements IMonster {
this.a.q(0.0F);
}
} else {
- this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED)));
+ this.a.q((float) (this.e * this.a.b(GenericAttributes.MOVEMENT_SPEED) * (entity.hasRider() && (entity.getRider().getForward() != 0 || entity.getRider().getStrafe() != 0) ? 2.0D : 1.0D))); // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java
index c7b443623f3dd90741e52216199d8ed90bcea6b3..fbf7c31f57f6dbfac997480eb7db55efc15ef4cc 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySpider.java
@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.world.DifficultyDamageScaler;
@@ -50,14 +51,28 @@ public class EntitySpider extends EntityMonster {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.spiderRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.spiderRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(3, new PathfinderGoalLeapAtTarget(this, 0.4F));
this.goalSelector.a(4, new EntitySpider.PathfinderGoalSpiderMeleeAttack(this));
this.goalSelector.a(5, new PathfinderGoalRandomStrollLand(this, 0.8D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(6, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0]));
this.targetSelector.a(2, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityHuman.class));
this.targetSelector.a(3, new EntitySpider.PathfinderGoalSpiderNearestAttackableTarget<>(this, EntityIronGolem.class));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java
index 5ce50c6fe788fbd6db95f6406bacbf218b7e691c..14dda6743ed9e6f4880bc560f7ba8892d8e84afe 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityStrider.java
@@ -13,6 +13,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -94,6 +95,18 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab
this.a(PathType.DAMAGE_FIRE, 0.0F);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.striderRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.striderRidableInWater;
+ }
+ // Purpur end
+
public static boolean c(EntityTypes<EntityStrider> entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) {
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i();
@@ -155,6 +168,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab
@Override
protected void initPathfinder() {
this.bv = new PathfinderGoalPanic(this, 1.65D);
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, this.bv);
this.goalSelector.a(2, new PathfinderGoalBreed(this, 1.0D));
this.bu = new PathfinderGoalTempt(this, 1.4D, false, EntityStrider.bp);
@@ -434,7 +448,7 @@ public class EntityStrider extends EntityAnimal implements ISteerable, ISaddleab
if (!enuminteractionresult.a()) {
ItemStack itemstack = entityhuman.b(enumhand);
- return itemstack.getItem() == Items.SADDLE ? itemstack.a(entityhuman, (EntityLiving) this, enumhand) : EnumInteractionResult.PASS;
+ return itemstack.getItem() == Items.SADDLE ? itemstack.a(entityhuman, (EntityLiving) this, enumhand) : tryRide(entityhuman, enumhand); // Purpur
} else {
if (flag && !this.isSilent()) {
this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_STRIDER_EAT, this.getSoundCategory(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F);
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java
index 9645d052069957311478a1ceca42ad52f7a9aa0b..4301ece0a04f3f2b4d198a684d0ca314deef2aef 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java
@@ -7,6 +7,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.util.MathHelper;
@@ -54,6 +55,45 @@ public class EntityVex extends EntityMonster {
this.f = 3;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.vexRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.vexRidableInWater;
+ }
+
+ @Override
+ public double getMaxY() {
+ return world.purpurConfig.vexMaxY;
+ }
+
+ @Override
+ public void g(Vec3D vec3d) {
+ super.g(vec3d);
+ if (hasRider()) {
+ float speed;
+ if (onGround) {
+ speed = (float) getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * 0.1F;
+ } else {
+ speed = (float) getAttributeInstance(GenericAttributes.FLYING_SPEED).getValue();
+ }
+ setSpeed(speed);
+ Vec3D mot = getMot();
+ move(EnumMoveType.SELF, mot.multiply(speed, 1.0, speed));
+ setMot(mot.a(0.9D));
+ }
+ }
+
+ @Override
+ public boolean b(float f, float f1) {
+ return false; // no fall damage please
+ }
+ // Purpur end
+
@Override
public void move(EnumMoveType enummovetype, Vec3D vec3d) {
super.move(enummovetype, vec3d);
@@ -62,7 +102,7 @@ public class EntityVex extends EntityMonster {
@Override
public void tick() {
- this.noclip = true;
+ this.noclip = !hasRider(); // Purpur
super.tick();
this.noclip = false;
this.setNoGravity(true);
@@ -77,17 +117,19 @@ public class EntityVex extends EntityMonster {
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(4, new EntityVex.a());
this.goalSelector.a(8, new EntityVex.d());
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // CraftBukkit - decompile error
this.targetSelector.a(2, new EntityVex.b(this));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
}
public static AttributeProvider.Builder m() {
- return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 14.0D).a(GenericAttributes.ATTACK_DAMAGE, 4.0D);
+ return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 14.0D).a(GenericAttributes.ATTACK_DAMAGE, 4.0D).a(GenericAttributes.FLYING_SPEED, 0.6D); // Purpur
}
@Override
@@ -319,14 +361,14 @@ public class EntityVex extends EntityMonster {
}
}
- class c extends ControllerMove {
+ class c extends net.pl3x.purpur.controller.ControllerMoveWASDFlying { // Purpur
public c(EntityVex entityvex) {
super(entityvex);
}
@Override
- public void a() {
+ public void tick() { // Purpur
if (this.h == ControllerMove.Operation.MOVE_TO) {
Vec3D vec3d = new Vec3D(this.b - EntityVex.this.locX(), this.c - EntityVex.this.locY(), this.d - EntityVex.this.locZ());
double d0 = vec3d.f();
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java
index fe84d6d2b74b6ae00c4c66682107296a40b69adc..28d345e87f45fa839bc3bd758f79f34aba546db7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java
@@ -8,6 +8,7 @@ import javax.annotation.Nullable;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.chat.ChatMessage;
import net.minecraft.network.chat.IChatBaseComponent;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -59,14 +60,28 @@ public class EntityVindicator extends EntityIllagerAbstract {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.vindicatorRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.vindicatorRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
super.initPathfinder();
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(1, new EntityVindicator.a(this));
this.goalSelector.a(2, new EntityIllagerAbstract.b(this));
this.goalSelector.a(3, new EntityRaider.a(this, 10.0F));
this.goalSelector.a(4, new EntityVindicator.c(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true));
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java
index 63fb08e7b4290353e5148d1acb58f091dc5b08be..c4663c5b02363bd1499ce1f3b50027f8aa7c68e7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java
@@ -2,6 +2,7 @@ package net.minecraft.world.entity.monster;
// Paper start
import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent;
+import net.minecraft.server.PathfinderGoalHasRider;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.Witch;
// Paper end
@@ -63,6 +64,18 @@ public class EntityWitch extends EntityRaider implements IRangedEntity {
super(entitytypes, world);
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.witchRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.witchRidableInWater;
+ }
+ // Purpur end
+
@Override
protected void initPathfinder() {
super.initPathfinder();
@@ -71,10 +84,12 @@ public class EntityWitch extends EntityRaider implements IRangedEntity {
});
this.bs = new PathfinderGoalNearestAttackableTargetWitch<>(this, EntityHuman.class, 10, true, false, (Predicate) null);
this.goalSelector.a(1, new PathfinderGoalFloat(this));
+ this.goalSelector.a(1, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 60, 10.0F));
this.goalSelector.a(2, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector.a(3, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(3, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class}));
this.targetSelector.a(2, this.br);
this.targetSelector.a(3, this.bs);
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java
index aed585e2c1c88a4d09318c6be7ebe7168eac3631..c5b1ce9268d6e6f3ec26eda4b5d8e7ae2a2ea672 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZoglin.java
@@ -62,6 +62,18 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin {
this.f = 5;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.zoglinRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.zoglinRidableInWater;
+ }
+ // Purpur end
+
@Override
protected BehaviorController.b<EntityZoglin> cK() {
return BehaviorController.a((Collection) EntityZoglin.c, (Collection) EntityZoglin.b);
@@ -93,10 +105,10 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin {
}
private Optional<? extends EntityLiving> eO() {
- return ((List) this.getBehaviorController().getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(ImmutableList.of())).stream().filter(EntityZoglin::i).findFirst();
+ return (this.getBehaviorController().getMemory(MemoryModuleType.VISIBLE_MOBS).orElse(ImmutableList.of())).stream().filter(EntityZoglin::predicate).findFirst(); // Purpur - decompile error
}
- private static boolean i(EntityLiving entityliving) {
+ private static boolean predicate(EntityLiving entityliving) { // Purpur - decompile error
EntityTypes<?> entitytypes = entityliving.getEntityType();
return entitytypes != EntityTypes.ZOGLIN && entitytypes != EntityTypes.CREEPER && IEntitySelector.f.test(entityliving);
@@ -181,14 +193,14 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin {
@Override
public BehaviorController<EntityZoglin> getBehaviorController() {
- return super.getBehaviorController();
+ return (BehaviorController<EntityZoglin>) super.getBehaviorController(); // Purpur - decompile error
}
protected void eL() {
- Activity activity = (Activity) this.bg.f().orElse((Object) null);
+ Activity activity = (Activity) this.bg.f().orElse(null); // Purpur - decompile error
this.bg.a((List) ImmutableList.of(Activity.FLIGHT, Activity.IDLE));
- Activity activity1 = (Activity) this.bg.f().orElse((Object) null);
+ Activity activity1 = (Activity) this.bg.f().orElse(null); // Purpur - decompile error
if (activity1 == Activity.FLIGHT && activity != Activity.FLIGHT) {
this.eN();
@@ -200,7 +212,8 @@ public class EntityZoglin extends EntityMonster implements IMonster, IOglin {
@Override
protected void mobTick() {
this.world.getMethodProfiler().enter("zoglinBrain");
- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this);
+ if (getRider() == null) // Purpur - only use brain if no rider
+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error
this.world.getMethodProfiler().exit();
this.eL();
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java
index 5ac950614fc90d02a568bb38f71faee124584c16..901fe8d224130c67bad00636b065bc798859a18e 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java
@@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundCategory;
import net.minecraft.sounds.SoundEffect;
@@ -108,6 +109,16 @@ public class EntityZombie extends EntityMonster {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.zombieRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.zombieRidableInWater;
+ }
+
public boolean jockeyOnlyBaby() {
return world.purpurConfig.zombieJockeyOnlyBaby;
}
@@ -123,9 +134,11 @@ public class EntityZombie extends EntityMonster {
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper
this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this));
+ this.targetSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.m();
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java
index 5d3e5873f19aaf8389eb5525693b9378ea9f94ee..ad801fc394fbb83cf280ee96f962e7f311615d72 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieHusk.java
@@ -23,6 +23,16 @@ public class EntityZombieHusk extends EntityZombie {
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.huskRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.huskRidableInWater;
+ }
+
@Override
public boolean jockeyOnlyBaby() {
return world.purpurConfig.huskJockeyOnlyBaby;
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java
index 99d0932e5352589cfbcc48a5e789651d0d77edde..b8395c7317494adf36010080931a1c8635ab6cfa 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombieVillager.java
@@ -71,6 +71,16 @@ public class EntityZombieVillager extends EntityZombie implements VillagerDataHo
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.zombieVillagerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.zombieVillagerRidableInWater;
+ }
+
@Override
public boolean jockeyOnlyBaby() {
return world.purpurConfig.zombieVillagerJockeyOnlyBaby;
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
index 9aa4850e021076fde306eea7eec104c31086c57f..64253428ef66145d07f74f8d0e5bdeb5aa5fe02b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
@@ -61,6 +61,18 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin {
this.f = 5;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.hoglinRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.hoglinRidableInWater;
+ }
+ // Purpur end
+
@Override
public boolean a(EntityHuman entityhuman) {
return !this.isLeashed();
@@ -127,6 +139,7 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin {
// Airplane - dynamic tick
if (!gg.airplane.AirplaneConfig.dynamicHoglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
this.world.getMethodProfiler().enter("hoglinBrain");
+ if (getRider() == null) // Purpur - only use brain if no rider
this.getBehaviorController().a((WorldServer) this.world, (EntityHoglin) this); // Airplane - decompile error
this.world.getMethodProfiler().exit();
HoglinAI.a(this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
index 48acef830eb1d919499e9b79dc6a9af4bdf8a17b..8c6f5273ed2ab4ec63b7854e290f790b2eca8c2f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
@@ -70,6 +70,18 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow {
this.f = 5;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.piglinRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.piglinRidableInWater;
+ }
+ // Purpur end
+
@Override
public void saveData(NBTTagCompound nbttagcompound) {
super.saveData(nbttagcompound);
@@ -250,6 +262,7 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow {
// Airplane - dynamic tick
if (!gg.airplane.AirplaneConfig.dynamicPiglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
this.world.getMethodProfiler().enter("piglinBrain");
+ if (getRider() == null) // Purpur - only use brain if no rider
this.getBehaviorController().a((WorldServer) this.world, (EntityPiglin) this); // Airplane - compile error
this.world.getMethodProfiler().exit();
PiglinAI.b(this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java
index 3d85501791fce621335f34bf508becb74b80210d..da2220b08a9cd9c2d7d3fd06702e6690e12f095e 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglinBrute.java
@@ -39,6 +39,18 @@ public class EntityPiglinBrute extends EntityPiglinAbstract {
this.f = 20;
}
+ // Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.piglinBruteRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.piglinBruteRidableInWater;
+ }
+ // Purpur end
+
public static AttributeProvider.Builder eS() {
return EntityMonster.eR().a(GenericAttributes.MAX_HEALTH, 50.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.3499999940395355D).a(GenericAttributes.ATTACK_DAMAGE, 7.0D);
}
@@ -68,7 +80,7 @@ public class EntityPiglinBrute extends EntityPiglinAbstract {
@Override
public BehaviorController<EntityPiglinBrute> getBehaviorController() {
- return super.getBehaviorController();
+ return (BehaviorController<EntityPiglinBrute>) super.getBehaviorController(); // Purpur - decompile error
}
@Override
@@ -84,7 +96,8 @@ public class EntityPiglinBrute extends EntityPiglinAbstract {
@Override
protected void mobTick() {
this.world.getMethodProfiler().enter("piglinBruteBrain");
- this.getBehaviorController().a((WorldServer) this.world, (EntityLiving) this);
+ if (getRider() == null) // Purpur - only use brain if no rider
+ this.getBehaviorController().a((WorldServer) this.world, this); // Purpur - decompile error
this.world.getMethodProfiler().exit();
PiglinBruteAI.b(this);
PiglinBruteAI.c(this);
diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
index d3032682af94428419daa02f55b6040090d8df73..a0f0d5e0909da5cfe87078d4722b030635cfeadd 100644
--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
@@ -32,6 +32,7 @@ import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -145,8 +146,19 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
}
// Purpur start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.villagerRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.villagerRidableInWater;
+ }
+
@Override
protected void initPathfinder() {
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS));
}
@@ -317,7 +329,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
if (itemstack.getItem() != Items.VILLAGER_SPAWN_EGG && this.isAlive() && !this.eN() && !this.isSleeping()) {
if (this.isBaby()) {
this.fk();
- return EnumInteractionResult.a(this.world.isClientSide);
+ return super.b(entityhuman, enumhand); // Purpur
} else {
boolean flag = this.getOffers().isEmpty();
@@ -330,8 +342,9 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
}
if (flag) {
- return EnumInteractionResult.a(this.world.isClientSide);
+ return tryRide(entityhuman, enumhand); // Purpur
} else {
+ if (world.purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur
if (!this.world.isClientSide && !this.trades.isEmpty()) {
this.h(entityhuman);
}
diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java
index e0324cdb2d4c85714eaad490a7a5c826b38e6b16..90cbef7fe8803295f82bddd6709fdf303aedcaba 100644
--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java
@@ -6,6 +6,7 @@ import net.minecraft.core.BlockPosition;
import net.minecraft.core.IPosition;
import net.minecraft.nbt.GameProfileSerializer;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.server.PathfinderGoalHasRider;
import net.minecraft.server.level.WorldServer;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
@@ -69,6 +70,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
@Override
protected void initPathfinder() {
this.goalSelector.a(0, new PathfinderGoalFloat(this));
+ this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur
this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> {
return this.world.isNight() && !entityvillagertrader.isInvisible();
}));
@@ -94,6 +96,16 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
}
// Purpur - start
+ @Override
+ public boolean isRidable() {
+ return world.purpurConfig.villagerTraderRidable;
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return world.purpurConfig.villagerTraderRidableInWater;
+ }
+
@Override
public boolean a(EntityHuman entityhuman) {
return world.purpurConfig.villagerTraderCanBeLeashed && !this.isLeashed();
@@ -121,8 +133,9 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
}
if (this.getOffers().isEmpty()) {
- return EnumInteractionResult.a(this.world.isClientSide);
+ return tryRide(entityhuman, enumhand); // Purpur
} else {
+ if (world.purpurConfig.villagerTraderRidable && itemstack.isEmpty()) return tryRide(entityhuman, enumhand); // Purpur
if (!this.world.isClientSide) {
this.setTradingPlayer(entityhuman);
this.openTrade(entityhuman, this.getScoreboardDisplayName(), 1);
diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
index 2ee7daa155d812af8f84ba646106d801d2fb0fec..644f94002bfe2686f4c765251c3804c854b27869 100644
--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java
@@ -183,6 +183,8 @@ public abstract class EntityHuman extends EntityLiving {
// CraftBukkit end
// Purpur start
+ public abstract void resetIdleTimer();
+
private javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino");
public void setAfk(boolean setAfk){
@@ -2258,4 +2260,15 @@ public abstract class EntityHuman extends EntityLiving {
return this.g;
}
}
+
+ // Purpur start
+ @Override
+ public boolean processClick(EnumHand hand) {
+ Entity vehicle = getRootVehicle();
+ if (vehicle != null && vehicle.getRider() == this) {
+ return vehicle.onClick(hand);
+ }
+ return false;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java
index 2e2e4ee98619cfbeaecffa1ebae78ccc1d7666ca..3914081629669aea19d50530db996728bbfa607f 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java
@@ -24,7 +24,7 @@ public abstract class IProjectile extends Entity {
private UUID shooter;
private int c;
- private boolean d;
+ private boolean d; public boolean leftOwner() { return d; } public void setLeftOwner(boolean leftOwner) { this.d = leftOwner; } // Purpur - OBFHELPER
IProjectile(EntityTypes<? extends IProjectile> entitytypes, World world) {
super(entitytypes, world);
@@ -86,6 +86,7 @@ public abstract class IProjectile extends Entity {
super.tick();
}
+ public boolean checkIfLeftOwner() { return this.h(); } // Purpur - OBFHELPER
private boolean h() {
Entity entity = this.getShooter();
@@ -149,7 +150,7 @@ public abstract class IProjectile extends Entity {
iblockdata.a(this.world, iblockdata, movingobjectpositionblock, this);
}
- protected boolean a(Entity entity) {
+ protected boolean a(Entity entity) { return hitPredicate(entity); } public boolean hitPredicate(Entity entity) { // Purpur - OBFHELPER
if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) {
Entity entity1 = this.getShooter();
// Paper start - Cancel hit for vanished players
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java
index 75889ac851d1c2b26c0b57bea6b75c1b65c2309f..80834537eba8bd33a0688e19d0aa9b963de4398a 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ProjectileHelper.java
@@ -21,6 +21,7 @@ import net.minecraft.world.phys.Vec3D;
public final class ProjectileHelper {
+ public static MovingObjectPosition getHitResult(Entity entity, Predicate<Entity> predicate) { return a(entity, predicate); } // Purpur - OBFHELPER
public static MovingObjectPosition a(Entity entity, Predicate<Entity> predicate) {
Vec3D vec3d = entity.getMot();
World world = entity.world;
diff --git a/src/main/java/net/minecraft/world/level/GeneratorAccess.java b/src/main/java/net/minecraft/world/level/GeneratorAccess.java
index 96efd974f1eb9c1e7c70e576e51ed69e15aacb99..fc86ef53c48503139667f7703019a07c40814fd4 100644
--- a/src/main/java/net/minecraft/world/level/GeneratorAccess.java
+++ b/src/main/java/net/minecraft/world/level/GeneratorAccess.java
@@ -48,6 +48,7 @@ public interface GeneratorAccess extends ICombinedAccess, IWorldTime {
void addParticle(ParticleParam particleparam, double d0, double d1, double d2, double d3, double d4, double d5);
+ default void playEvent(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { a(entityhuman, i, blockposition, j); } // Purpur - OBFHELPER
void a(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j);
default int getHeight() {
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index bf239526681ef2060e4dbedcb46a4a9d6b022fc1..b40de7edffa9c14bc5c04217a430c6d7bf0d25b1 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -1833,5 +1833,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public boolean isTheEnd() {
return getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END;
}
+
+ // Purpur start
+ public void playEffect(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) {
+ this.a(entityhuman, i, blockposition, j);
+ }
// Purpur end
}
diff --git a/src/main/java/net/minecraft/world/phys/Vec3D.java b/src/main/java/net/minecraft/world/phys/Vec3D.java
index a19a26a88f247d359354902efeece9923f3e0e0b..1119f60890784d953c2cd4e0078af4d04d10d557 100644
--- a/src/main/java/net/minecraft/world/phys/Vec3D.java
+++ b/src/main/java/net/minecraft/world/phys/Vec3D.java
@@ -50,6 +50,7 @@ public class Vec3D implements IPosition {
return new Vec3D(vec3d.x - this.x, vec3d.y - this.y, vec3d.z - this.z);
}
+ public Vec3D normalize() { return d(); } // Purpur - OBFHELPER
public Vec3D d() {
double d0 = (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
@@ -109,6 +110,7 @@ public class Vec3D implements IPosition {
return d3 * d3 + d4 * d4 + d5 * d5;
}
+ public Vec3D scale(double scale) { return a(scale); } // Purpur - OBFHELPER
public Vec3D a(double d0) {
return this.d(d0, d0, d0);
}
@@ -117,6 +119,7 @@ public class Vec3D implements IPosition {
return this.d(vec3d.x, vec3d.y, vec3d.z);
}
+ public Vec3D multiply (double x, double y, double z) { return d(x, y, z); } // Purpur - OBFHELPER
public Vec3D d(double d0, double d1, double d2) {
return new Vec3D(this.x * d0, this.y * d1, this.z * d2);
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java
index 76a1f157dc4ae0fdf804f3340b72dfa17ffbbb94..b587c96084a1ec3dd8fdec5a830fb8680e33e729 100644
--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java
@@ -137,11 +137,13 @@ public class PurpurConfig {
public static String afkBroadcastBack = "§e§o%s is no longer AFK";
public static String afkTabListPrefix = "[AFK] ";
public static String pingCommandOutput = "§a%s's ping is %sms";
+ public static String cannotRideMob = "§cYou cannot mount that mob";
private static void messages() {
afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway);
afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack);
afkTabListPrefix = getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix);
pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput);
+ cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob);
}
public static int dungeonSeed = -1;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index a13f5e2f242f5ff7bfe7fbd56439a1c1b8b7df2c..19e79cd7ec2c624963affa8587b40d6fc50d0f05 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -42,11 +42,6 @@ public class PurpurWorldConfig {
}
}
- public double vindicatorJohnnySpawnChance = 0D;
- private void vindicatorSettings() {
- vindicatorJohnnySpawnChance = getDouble("mobs.vindicator.johnny.spawn-chance", vindicatorJohnnySpawnChance);
- }
-
private ConfigurationSection getConfigurationSection(String path) {
ConfigurationSection section = PurpurConfig.config.getConfigurationSection("world-settings." + worldName + "." + path);
return section != null ? section : PurpurConfig.config.getConfigurationSection("world-settings.default." + path);
@@ -339,61 +334,186 @@ public class PurpurWorldConfig {
turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts);
}
+ public boolean babiesAreRidable = true;
+ public boolean untamedTamablesAreRidable = true;
+ public boolean useNightVisionWhenRiding = false;
+ private void ridableSettings() {
+ babiesAreRidable = getBoolean("ridable-settings.babies-are-ridable", babiesAreRidable);
+ untamedTamablesAreRidable = getBoolean("ridable-settings.untamed-tamables-are-ridable", untamedTamablesAreRidable);
+ useNightVisionWhenRiding = getBoolean("ridable-settings.use-night-vision", useNightVisionWhenRiding);
+ }
+
+ public boolean batRidable = false;
+ public boolean batRidableInWater = false;
+ public double batMaxY = 256D;
+ private void batSettings() {
+ batRidable = getBoolean("mobs.bat.ridable", batRidable);
+ batRidableInWater = getBoolean("mobs.bat.ridable-in-water", batRidableInWater);
+ batMaxY = getDouble("mobs.bat.ridable-max-y", batMaxY);
+ }
+
+ public boolean beeRidable = false;
+ public boolean beeRidableInWater = false;
+ public double beeMaxY = 256D;
+ private void beeSettings() {
+ beeRidable = getBoolean("mobs.bee.ridable", beeRidable);
+ beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater);
+ beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY);
+ }
+
+ public boolean blazeRidable = false;
+ public boolean blazeRidableInWater = false;
+ public double blazeMaxY = 256D;
+ private void blazeSettings() {
+ blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable);
+ blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater);
+ blazeMaxY = getDouble("mobs.blaze.ridable-max-y", blazeMaxY);
+ }
+
+ public boolean catRidable = false;
+ public boolean catRidableInWater = false;
public int catSpawnDelay = 1200;
public int catSpawnSwampHutScanRange = 16;
public int catSpawnVillageScanRange = 48;
private void catSettings() {
+ catRidable = getBoolean("mobs.cat.ridable", catRidable);
+ catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater);
catSpawnDelay = getInt("mobs.cat.spawn-delay", catSpawnDelay);
catSpawnSwampHutScanRange = getInt("mobs.cat.scan-range-for-other-cats.swamp-hut", catSpawnSwampHutScanRange);
catSpawnVillageScanRange = getInt("mobs.cat.scan-range-for-other-cats.village", catSpawnVillageScanRange);
}
+ public boolean caveSpiderRidable = false;
+ public boolean caveSpiderRidableInWater = false;
+ private void caveSpiderSettings() {
+ caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable);
+ caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater);
+ }
+
+ public boolean chickenRidable = false;
+ public boolean chickenRidableInWater = false;
public boolean chickenRetaliate = false;
private void chickenSettings() {
+ chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable);
+ chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater);
chickenRetaliate = getBoolean("mobs.chicken.retaliate", chickenRetaliate);
}
+ public boolean codRidable = false;
+ private void codSettings() {
+ codRidable = getBoolean("mobs.cod.ridable", codRidable);
+ }
+
+ public boolean cowRidable = false;
+ public boolean cowRidableInWater = false;
public int cowFeedMushrooms = 0;
private void cowSettings() {
+ cowRidable = getBoolean("mobs.cow.ridable", cowRidable);
+ cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater);
cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms);
}
+ public boolean creeperRidable = false;
+ public boolean creeperRidableInWater = false;
public boolean creeperAllowGriefing = true;
public double creeperChargedChance = 0.0D;
private void creeperSettings() {
+ creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable);
+ creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater);
creeperAllowGriefing = getBoolean("mobs.creeper.allow-griefing", creeperAllowGriefing);
creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance);
}
+ public boolean dolphinRidable = false;
+ public int dolphinSpitCooldown = 20;
+ public float dolphinSpitSpeed = 1.0F;
+ public float dolphinSpitDamage = 2.0F;
public boolean dolphinDisableTreasureSearching = false;
private void dolphinSettings() {
+ dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable);
+ dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown);
+ dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed);
+ dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage);
dolphinDisableTreasureSearching = getBoolean("mobs.dolphin.disable-treasure-searching", dolphinDisableTreasureSearching);
}
+ public boolean donkeyRidableInWater = false;
+ private void donkeySettings() {
+ donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater);
+ }
+
+ public boolean drownedRidable = false;
+ public boolean drownedRidableInWater = false;
public boolean drownedJockeyOnlyBaby = true;
public double drownedJockeyChance = 0.05D;
public boolean drownedJockeyTryExistingChickens = true;
private void drownedSettings() {
+ drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable);
+ drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater);
drownedJockeyOnlyBaby = getBoolean("mobs.drowned.jockey.only-babies", drownedJockeyOnlyBaby);
drownedJockeyChance = getDouble("mobs.drowned.jockey.chance", drownedJockeyChance);
drownedJockeyTryExistingChickens = getBoolean("mobs.drowned.jockey.try-existing-chickens", drownedJockeyTryExistingChickens);
}
+ public boolean elderGuardianRidable = false;
+ private void elderGuardianSettings() {
+ elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable);
+ }
+
+ public boolean enderDragonRidable = false;
+ public boolean enderDragonRidableInWater = false;
+ public double enderDragonMaxY = 256D;
public boolean enderDragonAlwaysDropsFullExp = false;
private void enderDragonSettings() {
+ enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable);
+ enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater);
+ enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY);
enderDragonAlwaysDropsFullExp = getBoolean("mobs.ender_dragon.always-drop-full-exp", enderDragonAlwaysDropsFullExp);
}
+ public boolean endermanRidable = false;
+ public boolean endermanRidableInWater = false;
public boolean endermanAllowGriefing = true;
private void endermanSettings() {
+ endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable);
+ endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater);
endermanAllowGriefing = getBoolean("mobs.enderman.allow-griefing", endermanAllowGriefing);
}
+ public boolean endermiteRidable = false;
+ public boolean endermiteRidableInWater = false;
+ private void endermiteSettings() {
+ endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable);
+ endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater);
+ }
+
+ public boolean evokerRidable = false;
+ public boolean evokerRidableInWater = false;
+ private void evokerSettings() {
+ evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable);
+ evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater);
+ }
+
+ public boolean foxRidable = false;
+ public boolean foxRidableInWater = false;
public boolean foxTypeChangesWithTulips = false;
private void foxSettings() {
+ foxRidable = getBoolean("mobs.fox.ridable", foxRidable);
+ foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater);
foxTypeChangesWithTulips = getBoolean("mobs.fox.tulips-change-type", foxTypeChangesWithTulips);
}
+ public boolean ghastRidable = false;
+ public boolean ghastRidableInWater = false;
+ public double ghastMaxY = 256D;
+ private void ghastSettings() {
+ ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable);
+ ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater);
+ ghastMaxY = getDouble("mobs.ghast.ridable-max-y", ghastMaxY);
+ }
+
+ public boolean giantRidable = false;
+ public boolean giantRidableInWater = false;
public float giantStepHeight = 2.0F;
public float giantJumpHeight = 1.0F;
public double giantMovementSpeed = 0.5D;
@@ -402,6 +522,8 @@ public class PurpurWorldConfig {
public boolean giantHaveHostileAI = false;
public double giantMaxHealth = 100.0D;
private void giantSettings() {
+ giantRidable = getBoolean("mobs.giant.ridable", giantRidable);
+ giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater);
giantStepHeight = (float) getDouble("mobs.giant.step-height", giantStepHeight);
giantJumpHeight = (float) getDouble("mobs.giant.jump-height", giantJumpHeight);
giantMovementSpeed = getDouble("mobs.giant.movement-speed", giantMovementSpeed);
@@ -416,19 +538,44 @@ public class PurpurWorldConfig {
giantMaxHealth = getDouble("mobs.giant.attributes.max-health", giantMaxHealth);
}
+ public boolean guardianRidable = false;
+ private void guardianSettings() {
+ guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable);
+ }
+
+ public boolean hoglinRidable = false;
+ public boolean hoglinRidableInWater = false;
+ private void hoglinSettings() {
+ hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable);
+ hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater);
+ }
+
+ public boolean horseRidableInWater = false;
+ private void horseSettings() {
+ horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater);
+ }
+
+ public boolean huskRidable = false;
+ public boolean huskRidableInWater = false;
public boolean huskJockeyOnlyBaby = true;
public double huskJockeyChance = 0.05D;
public boolean huskJockeyTryExistingChickens = true;
private void huskSettings() {
+ huskRidable = getBoolean("mobs.husk.ridable", huskRidable);
+ huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater);
huskJockeyOnlyBaby = getBoolean("mobs.husk.jockey.only-babies", huskJockeyOnlyBaby);
huskJockeyChance = getDouble("mobs.husk.jockey.chance", huskJockeyChance);
huskJockeyTryExistingChickens = getBoolean("mobs.husk.jockey.try-existing-chickens", huskJockeyTryExistingChickens);
}
+ public boolean illusionerRidable = false;
+ public boolean illusionerRidableInWater = false;
public double illusionerMovementSpeed = 0.5D;
public double illusionerFollowRange = 18.0D;
public double illusionerMaxHealth = 32.0D;
private void illusionerSettings() {
+ illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable);
+ illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater);
illusionerMovementSpeed = getDouble("mobs.illusioner.movement-speed", illusionerMovementSpeed);
illusionerFollowRange = getDouble("mobs.illusioner.follow-range", illusionerFollowRange);
if (PurpurConfig.version < 8) {
@@ -439,11 +586,76 @@ public class PurpurWorldConfig {
illusionerMaxHealth = getDouble("mobs.illusioner.attributes.max-health", illusionerMaxHealth);
}
+ public boolean ironGolemRidable = false;
+ public boolean ironGolemRidableInWater = false;
public boolean ironGolemCanSwim = false;
private void ironGolemSettings() {
+ ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable);
+ ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater);
ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim);
}
+ public boolean llamaRidable = false;
+ public boolean llamaRidableInWater = false;
+ private void llamaSettings() {
+ llamaRidable = getBoolean("mobs.llama.ridable", llamaRidable);
+ llamaRidableInWater = getBoolean("mobs.llama.ridable-in-water", llamaRidableInWater);
+ }
+
+ public boolean llamaTraderRidable = false;
+ public boolean llamaTraderRidableInWater = false;
+ private void llamaTraderSettings() {
+ llamaTraderRidable = getBoolean("mobs.trader_llama.ridable", llamaTraderRidable);
+ llamaTraderRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", llamaTraderRidableInWater);
+ }
+
+ public boolean magmaCubeRidable = false;
+ public boolean magmaCubeRidableInWater = false;
+ private void magmaCubeSettings() {
+ magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable);
+ magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater);
+ }
+
+ public boolean mooshroomRidable = false;
+ public boolean mooshroomRidableInWater = false;
+ private void mooshroomSettings() {
+ mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable);
+ mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater);
+ }
+
+ public boolean muleRidableInWater = false;
+ private void muleSettings() {
+ muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater);
+ }
+
+ public boolean ocelotRidable = false;
+ public boolean ocelotRidableInWater = false;
+ private void ocelotSettings() {
+ ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable);
+ ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater);
+ }
+
+ public boolean pandaRidable = false;
+ public boolean pandaRidableInWater = false;
+ private void pandaSettings() {
+ pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable);
+ pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater);
+ }
+
+ public boolean parrotRidable = false;
+ public boolean parrotRidableInWater = false;
+ public double parrotMaxY = 256D;
+ private void parrotSettings() {
+ parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable);
+ parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater);
+ parrotMaxY = getDouble("mobs.parrot.ridable-max-y", parrotMaxY);
+ }
+
+ public boolean phantomRidable = false;
+ public boolean phantomRidableInWater = false;
+ public double phantomMaxY = 256D;
+ public float phantomFlameDamage = 1.0F;
+ public int phantomFlameFireTime = 8;
public double phantomAttackedByCrystalRadius = 0.0D;
public float phantomAttackedByCrystalDamage = 1.0F;
public double phantomOrbitCrystalRadius = 0.0D;
@@ -462,7 +674,13 @@ public class PurpurWorldConfig {
public int phantomBurnInLight = 0;
public boolean phantomIgnorePlayersWithTorch = false;
public boolean phantomBurnInDaylight = true;
+ public boolean phantomAllowGriefing = false;
private void phantomSettings() {
+ phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
+ phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
+ phantomMaxY = getDouble("mobs.phantom.ridable-max-y", phantomMaxY);
+ phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage);
+ phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime);
phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
@@ -481,42 +699,187 @@ public class PurpurWorldConfig {
phantomBurnInLight = getInt("mobs.phantom.burn-in-light", phantomBurnInLight);
phantomBurnInDaylight = getBoolean("mobs.phantom.burn-in-daylight", phantomBurnInDaylight);
phantomIgnorePlayersWithTorch = getBoolean("mobs.phantom.ignore-players-with-torch", phantomIgnorePlayersWithTorch);
+ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
}
+ public boolean pigRidable = false;
+ public boolean pigRidableInWater = false;
public boolean pigGiveSaddleBack = false;
private void pigSettings() {
+ pigRidable = getBoolean("mobs.pig.ridable", pigRidable);
+ pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater);
pigGiveSaddleBack = getBoolean("mobs.pig.give-saddle-back", pigGiveSaddleBack);
}
+ public boolean piglinRidable = false;
+ public boolean piglinRidableInWater = false;
+ private void piglinSettings() {
+ piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable);
+ piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater);
+ }
+
+ public boolean piglinBruteRidable = false;
+ public boolean piglinBruteRidableInWater = false;
+ private void piglinBruteSettings() {
+ piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable);
+ piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater);
+ }
+
+ public boolean pillagerRidable = false;
+ public boolean pillagerRidableInWater = false;
+ private void pillagerSettings() {
+ pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable);
+ pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater);
+ }
+
+ public boolean polarBearRidable = false;
+ public boolean polarBearRidableInWater = false;
public String polarBearBreedableItemString = "";
public Item polarBearBreedableItem = null;
private void polarBearSettings() {
+ polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable);
+ polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater);
polarBearBreedableItemString = getString("mobs.polar_bear.breedable-item", polarBearBreedableItemString);
Item item = IRegistry.ITEM.get(new MinecraftKey(polarBearBreedableItemString));
if (item != Items.AIR) polarBearBreedableItem = item;
}
+ public boolean pufferfishRidable = false;
+ private void pufferfishSettings() {
+ pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable);
+ }
+
+ public boolean rabbitRidable = false;
+ public boolean rabbitRidableInWater = false;
public double rabbitNaturalToast = 0.0D;
public double rabbitNaturalKiller = 0.0D;
private void rabbitSettings() {
+ rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable);
+ rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater);
rabbitNaturalToast = getDouble("mobs.rabbit.spawn-toast-chance", rabbitNaturalToast);
rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller);
}
+ public boolean ravagerRidable = false;
+ public boolean ravagerRidableInWater = false;
+ private void ravagerSettings() {
+ ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable);
+ ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater);
+ }
+
+ public boolean salmonRidable = false;
+ private void salmonSettings() {
+ salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable);
+ }
+
+ public boolean sheepRidable = false;
+ public boolean sheepRidableInWater = false;
+ private void sheepSettings() {
+ sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable);
+ sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater);
+ }
+
+ public boolean shulkerRidable = false;
+ public boolean shulkerRidableInWater = false;
+ private void shulkerSettings() {
+ shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable);
+ shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater);
+ }
+
+ public boolean silverfishRidable = false;
+ public boolean silverfishRidableInWater = false;
+ private void silverfishSettings() {
+ silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable);
+ silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater);
+ }
+
+ public boolean skeletonRidable = false;
+ public boolean skeletonRidableInWater = false;
+ private void skeletonSettings() {
+ skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable);
+ skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater);
+ }
+
+ public boolean skeletonHorseCanSwim = false;
+ public boolean skeletonHorseRidableInWater = true;
+ private void skeletonHorseSettings() {
+ skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim);
+ skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater);
+ }
+
+ public boolean slimeRidable = false;
+ public boolean slimeRidableInWater = false;
+ private void slimeSettings() {
+ slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable);
+ slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater);
+ }
+
+ public boolean snowGolemRidable = false;
+ public boolean snowGolemRidableInWater = false;
+ public boolean snowGolemLeaveTrailWhenRidden = false;
public boolean snowGolemDropsPumpkin = true;
public boolean snowGolemPutPumpkinBack = false;
private void snowGolemSettings() {
+ snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable);
+ snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater);
+ snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden);
snowGolemDropsPumpkin = getBoolean("mobs.snow_golem.drop-pumpkin-when-sheared", snowGolemDropsPumpkin);
snowGolemPutPumpkinBack = getBoolean("mobs.snow_golem.pumpkin-can-be-added-back", snowGolemPutPumpkinBack);
}
+ public boolean squidRidable = false;
public boolean squidImmuneToEAR = true;
public double squidOffsetWaterCheck = 0.0D;
private void squidSettings() {
+ squidRidable = getBoolean("mobs.squid.ridable", squidRidable);
squidImmuneToEAR = getBoolean("mobs.squid.immune-to-EAR", squidImmuneToEAR);
squidOffsetWaterCheck = getDouble("mobs.squid.water-offset-check", squidOffsetWaterCheck);
}
+ public boolean spiderRidable = false;
+ public boolean spiderRidableInWater = false;
+ private void spiderSettings() {
+ spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable);
+ spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater);
+ }
+
+ public boolean strayRidable = false;
+ public boolean strayRidableInWater = false;
+ private void straySettings() {
+ strayRidable = getBoolean("mobs.stray.ridable", strayRidable);
+ strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater);
+ }
+
+ public boolean striderRidable = false;
+ public boolean striderRidableInWater = false;
+ private void striderSettings() {
+ striderRidable = getBoolean("mobs.strider.ridable", striderRidable);
+ striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater);
+ }
+
+ public boolean tropicalFishRidable = false;
+ private void tropicalFishSettings() {
+ tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable);
+ }
+
+ public boolean turtleRidable = false;
+ public boolean turtleRidableInWater = false;
+ private void turtleSettings() {
+ turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable);
+ turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater);
+ }
+
+ public boolean vexRidable = false;
+ public boolean vexRidableInWater = false;
+ public double vexMaxY = 256D;
+ private void vexSettings() {
+ vexRidable = getBoolean("mobs.vex.ridable", vexRidable);
+ vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater);
+ vexMaxY = getDouble("mobs.vex.ridable-max-y", vexMaxY);
+ }
+
+ public boolean villagerRidable = false;
+ public boolean villagerRidableInWater = false;
public int villagerBrainTicks = 1;
public boolean villagerUseBrainTicksOnlyWhenLagging = true;
public boolean villagerCanBeLeashed = false;
@@ -526,6 +889,8 @@ public class PurpurWorldConfig {
public int villagerSpawnIronGolemLimit = 0;
public boolean villagerCanBreed = true;
private void villagerSettings() {
+ villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
+ villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
villagerBrainTicks = getInt("mobs.villager.brain-ticks", villagerBrainTicks);
villagerUseBrainTicksOnlyWhenLagging = getBoolean("mobs.villager.use-brain-ticks-only-when-lagging", villagerUseBrainTicksOnlyWhenLagging);
villagerCanBeLeashed = getBoolean("mobs.villager.can-be-leashed", villagerCanBeLeashed);
@@ -536,45 +901,108 @@ public class PurpurWorldConfig {
villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed);
}
+ public boolean villagerTraderRidable = false;
+ public boolean villagerTraderRidableInWater = false;
public boolean villagerTraderCanBeLeashed = false;
public boolean villagerTraderFollowEmeraldBlock = false;
private void villagerTraderSettings() {
+ villagerTraderRidable = getBoolean("mobs.wandering_trader.ridable", villagerTraderRidable);
+ villagerTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", villagerTraderRidableInWater);
villagerTraderCanBeLeashed = getBoolean("mobs.wandering_trader.can-be-leashed", villagerTraderCanBeLeashed);
villagerTraderFollowEmeraldBlock = getBoolean("mobs.wandering_trader.follow-emerald-blocks", villagerTraderFollowEmeraldBlock);
}
+ public boolean vindicatorRidable = false;
+ public boolean vindicatorRidableInWater = false;
+ public double vindicatorJohnnySpawnChance = 0D;
+ private void vindicatorSettings() {
+ vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable);
+ vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater);
+ vindicatorJohnnySpawnChance = getDouble("mobs.vindicator.johnny.spawn-chance", vindicatorJohnnySpawnChance);
+ }
+
+ public boolean witchRidable = false;
+ public boolean witchRidableInWater = false;
+ private void witchSettings() {
+ witchRidable = getBoolean("mobs.witch.ridable", witchRidable);
+ witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater);
+ }
+
+ public boolean witherRidable = false;
+ public boolean witherRidableInWater = false;
+ public double witherMaxY = 256D;
+ private void witherSettings() {
+ witherRidable = getBoolean("mobs.wither.ridable", witherRidable);
+ witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater);
+ witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY);
+ }
+
+ public boolean witherSkeletonRidable = false;
+ public boolean witherSkeletonRidableInWater = false;
public boolean witherSkeletonTakesWitherDamage = false;
private void witherSkeletonSettings() {
+ witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable);
+ witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater);
witherSkeletonTakesWitherDamage = getBoolean("mobs.wither_skeleton.takes-wither-damage", witherSkeletonTakesWitherDamage);
}
+ public boolean wolfRidable = false;
+ public boolean wolfRidableInWater = false;
+ private void wolfSettings() {
+ wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable);
+ wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater);
+ }
+
+ public boolean zoglinRidable = false;
+ public boolean zoglinRidableInWater = false;
+ private void zoglinSettings() {
+ zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable);
+ zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater);
+ }
+
+ public boolean zombieRidable = false;
+ public boolean zombieRidableInWater = false;
public boolean zombieJockeyOnlyBaby = true;
public double zombieJockeyChance = 0.05D;
public boolean zombieJockeyTryExistingChickens = true;
private void zombieSettings() {
+ zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
+ zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
zombieJockeyOnlyBaby = getBoolean("mobs.zombie.jockey.only-babies", zombieJockeyOnlyBaby);
zombieJockeyChance = getDouble("mobs.zombie.jockey.chance", zombieJockeyChance);
zombieJockeyTryExistingChickens = getBoolean("mobs.zombie.jockey.try-existing-chickens", zombieJockeyTryExistingChickens);
}
+ public boolean zombieHorseCanSwim = false;
+ public boolean zombieHorseRidableInWater = false;
public double zombieHorseSpawnChance = 0.0D;
private void zombieHorseSettings() {
+ zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim);
+ zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater);
zombieHorseSpawnChance = getDouble("mobs.zombie_horse.spawn-chance", zombieHorseSpawnChance);
}
+ public boolean zombifiedPiglinRidable = false;
+ public boolean zombifiedPiglinRidableInWater = false;
public boolean zombifiedPiglinJockeyOnlyBaby = true;
public double zombifiedPiglinJockeyChance = 0.05D;
public boolean zombifiedPiglinJockeyTryExistingChickens = true;
private void zombifiedPiglinSettings() {
+ zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable);
+ zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater);
zombifiedPiglinJockeyOnlyBaby = getBoolean("mobs.zombified_piglin.jockey.only-babies", zombifiedPiglinJockeyOnlyBaby);
zombifiedPiglinJockeyChance = getDouble("mobs.zombified_piglin.jockey.chance", zombifiedPiglinJockeyChance);
zombifiedPiglinJockeyTryExistingChickens = getBoolean("mobs.zombified_piglin.jockey.try-existing-chickens", zombifiedPiglinJockeyTryExistingChickens);
}
+ public boolean zombieVillagerRidable = false;
+ public boolean zombieVillagerRidableInWater = false;
public boolean zombieVillagerJockeyOnlyBaby = true;
public double zombieVillagerJockeyChance = 0.05D;
public boolean zombieVillagerJockeyTryExistingChickens = true;
private void zombieVillagerSettings() {
+ zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
+ zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
zombieVillagerJockeyOnlyBaby = getBoolean("mobs.zombie_villager.jockey.only-babies", zombieVillagerJockeyOnlyBaby);
zombieVillagerJockeyChance = getDouble("mobs.zombie_villager.jockey.chance", zombieVillagerJockeyChance);
zombieVillagerJockeyTryExistingChickens = getBoolean("mobs.zombie_villager.jockey.try-existing-chickens", zombieVillagerJockeyTryExistingChickens);
diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java
new file mode 100644
index 0000000000000000000000000000000000000000..292821f039d99a03ba4daeb3a941616ef5f6287e
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java
@@ -0,0 +1,76 @@
+package net.pl3x.purpur.controller;
+
+import net.minecraft.network.protocol.game.PacketPlayOutEntity;
+import net.minecraft.world.entity.ai.control.ControllerLook;
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.entity.player.EntityHuman;
+
+public class ControllerLookWASD extends ControllerLook {
+ protected final EntityInsentient entity;
+ private float yawOffset = 0;
+ private float pitchOffset = 0;
+
+ public ControllerLookWASD(EntityInsentient entity) {
+ super(entity);
+ this.entity = entity;
+ }
+
+ // tick
+ @Override
+ public void a() {
+ if (entity.hasRider()) {
+ tick(entity.getRider());
+ } else {
+ tick();
+ }
+ }
+
+ protected void tick() {
+ super.a(); // tick
+ }
+
+ protected void tick(EntityHuman rider) {
+ setYawPitch(rider.yaw, rider.pitch);
+ }
+
+ public void setYawPitch(float yaw, float pitch) {
+ entity.yaw = normalizeYaw(yaw + yawOffset);
+ entity.lastYaw = entity.yaw;
+ entity.setBodyYaw(entity.yaw);
+ entity.setRenderYawOffset(entity.yaw);
+ entity.setHeadRotation(entity.yaw);
+ entity.pitch = normalizePitch(pitch + pitchOffset);
+
+ entity.tracker.broadcast(new PacketPlayOutEntity
+ .PacketPlayOutRelEntityMoveLook(entity.getId(),
+ (short) 0, (short) 0, (short) 0,
+ (byte) MathHelper.d(entity.yaw * 256.0F / 360.0F),
+ (byte) MathHelper.d(entity.pitch * 256.0F / 360.0F),
+ entity.onGround));
+ }
+
+ public void setOffsets(float yaw, float pitch) {
+ yawOffset = yaw;
+ pitchOffset = pitch;
+ }
+
+ public float normalizeYaw(float yaw) {
+ yaw %= 360.0f;
+ if (yaw >= 180.0f) {
+ yaw -= 360.0f;
+ } else if (yaw < -180.0f) {
+ yaw += 360.0f;
+ }
+ return yaw;
+ }
+
+ public float normalizePitch(float pitch) {
+ if (pitch > 90.0f) {
+ pitch = 90.0f;
+ } else if (pitch < -90.0f) {
+ pitch = -90.0f;
+ }
+ return pitch;
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java
new file mode 100644
index 0000000000000000000000000000000000000000..266e734e8c20d6e414bd4a453118ad75fa4f97e5
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java
@@ -0,0 +1,92 @@
+package net.pl3x.purpur.controller;
+
+import net.minecraft.world.entity.ai.control.ControllerMove;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.pl3x.purpur.event.entity.RidableSpacebarEvent;
+
+public class ControllerMoveWASD extends ControllerMove {
+ protected final EntityInsentient entity;
+ private final double speedModifier;
+
+ public ControllerMoveWASD(EntityInsentient entity) {
+ this(entity, 1.0D);
+ }
+
+ public ControllerMoveWASD(EntityInsentient entity, double speedModifier) {
+ super(entity);
+ this.entity = entity;
+ this.speedModifier = speedModifier;
+ }
+
+ // isUpdating
+ @Override
+ public boolean b() {
+ return entity.hasRider() ? getForward() != 0 || getStrafe() != 0 : super.b();
+ }
+
+ // tick
+ @Override
+ public void a() {
+ if (entity.hasRider()) {
+ tick(entity.getRider());
+ } else {
+ tick();
+ }
+ }
+
+ public void tick() {
+ super.a(); // tick
+ }
+
+ public void tick(EntityHuman rider) {
+ float forward = rider.getForward() * 0.5F;
+ float strafe = rider.getStrafe() * 0.25F;
+
+ if (forward <= 0.0F) {
+ forward *= 0.5F;
+ }
+
+ float yawOffset = 0;
+ if (strafe != 0) {
+ if (forward == 0) {
+ yawOffset += strafe > 0 ? -90 : 90;
+ forward = Math.abs(strafe * 2);
+ } else {
+ yawOffset += strafe > 0 ? -30 : 30;
+ strafe /= 2;
+ if (forward < 0) {
+ yawOffset += strafe > 0 ? -110 : 110;
+ forward *= -1;
+ }
+ }
+ } else if (forward < 0) {
+ yawOffset -= 180;
+ forward *= -1;
+ }
+
+ ((ControllerLookWASD) entity.getControllerLook()).setOffsets(yawOffset, 0);
+
+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar() && entity.onGround) {
+ entity.jump();
+ }
+
+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * speedModifier);
+
+ entity.setSpeed((float) getSpeed());
+ entity.setForward(forward);
+
+ setForward(entity.getForward());
+ setStrafe(entity.getStrafe());
+ }
+
+ public static boolean spacebarEvent(Entity entity) {
+ if (RidableSpacebarEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ return new RidableSpacebarEvent(entity.getBukkitEntity()).callEvent();
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java
new file mode 100644
index 0000000000000000000000000000000000000000..7737e87048e88b40c0b6b4a1093e2256ae252802
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java
@@ -0,0 +1,61 @@
+package net.pl3x.purpur.controller;
+
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.player.EntityHuman;
+
+public class ControllerMoveWASDFlying extends ControllerMoveWASD {
+ protected final float groundSpeedModifier;
+ protected int tooHighCooldown = 0;
+ protected boolean setGravityFlag = true;
+
+ public ControllerMoveWASDFlying(EntityInsentient entity) {
+ this(entity, 1.0F);
+ }
+
+ public ControllerMoveWASDFlying(EntityInsentient entity, float groundSpeedModifier) {
+ this(entity, groundSpeedModifier, true);
+ }
+
+ public ControllerMoveWASDFlying(EntityInsentient entity, float groundSpeedModifier, boolean setGravityFlag) {
+ super(entity);
+ this.groundSpeedModifier = groundSpeedModifier;
+ this.setGravityFlag = setGravityFlag;
+ }
+
+ @Override
+ public void tick(EntityHuman rider) {
+ float forward = Math.max(0.0F, rider.getForward());
+ float vertical = forward == 0.0F ? 0.0F : -(rider.pitch / 45.0F);
+ float strafe = rider.getStrafe();
+
+ if (rider.jumping && spacebarEvent(entity)) {
+ entity.onSpacebar();
+ }
+
+ if (entity.locY() >= entity.getMaxY() || --tooHighCooldown > 0) {
+ tooHighCooldown = 60;
+ entity.setMot(entity.getMot().add(0.0D, -0.05D, 0.0D));
+ vertical = 0.0F;
+ }
+
+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue());
+ float speed = (float) getSpeed();
+
+ if (entity.onGround) {
+ speed *= groundSpeedModifier; // TODO = fix this!
+ }
+
+ if (setGravityFlag) {
+ entity.setNoGravity(forward > 0);
+ }
+
+ entity.setSpeed(speed);
+ entity.setVertical(vertical);
+ entity.setStrafe(strafe);
+ entity.setForward(forward);
+
+ setForward(entity.getForward());
+ setStrafe(entity.getStrafe());
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdd32aa66b6bd9c01854e3d9baf25757c7e2a707
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlyingWithSpacebar.java
@@ -0,0 +1,61 @@
+package net.pl3x.purpur.controller;
+
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.phys.Vec3D;
+
+public class ControllerMoveWASDFlyingWithSpacebar extends ControllerMoveWASDFlying {
+ public ControllerMoveWASDFlyingWithSpacebar(EntityInsentient entity) {
+ super(entity);
+ }
+
+ public ControllerMoveWASDFlyingWithSpacebar(EntityInsentient entity, float groundSpeedModifier) {
+ super(entity, groundSpeedModifier);
+ }
+
+ @Override
+ public void tick(EntityHuman rider) {
+ float forward = rider.getForward();
+ float strafe = rider.getStrafe() * 0.5F;
+ float vertical = 0;
+
+ if (forward < 0.0F) {
+ forward *= 0.5F;
+ strafe *= 0.5F;
+ }
+
+ float speed = (float) entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue();
+
+ if (entity.onGround) {
+ speed *= groundSpeedModifier;
+ }
+
+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar()) {
+ entity.setNoGravity(true);
+ vertical = 1.0F;
+ } else {
+ entity.setNoGravity(false);
+ }
+
+ if (entity.locY() >= entity.getMaxY() || --tooHighCooldown > 0) {
+ tooHighCooldown = 60;
+ entity.setMot(entity.getMot().add(0.0D, -0.2D, 0.0D));
+ vertical = 0.0F;
+ }
+
+ setSpeed(speed);
+ entity.setSpeed((float) getSpeed());
+ entity.setVertical(vertical);
+ entity.setStrafe(strafe);
+ entity.setForward(forward);
+
+ setForward(entity.getForward());
+ setStrafe(entity.getStrafe());
+
+ Vec3D mot = entity.getMot();
+ if (mot.y > 0.2D) {
+ entity.setMot(mot.x, 0.2D, mot.z);
+ }
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa7eb0b3bd7be8d1992e99bf156dbad167e571aa
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java
@@ -0,0 +1,50 @@
+package net.pl3x.purpur.controller;
+
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.ai.attributes.GenericAttributes;
+import net.minecraft.world.entity.player.EntityHuman;
+
+public class ControllerMoveWASDWater extends ControllerMoveWASD {
+ private final double speedModifier;
+
+ public ControllerMoveWASDWater(EntityInsentient entity) {
+ this(entity, 1.0D);
+ }
+
+ public ControllerMoveWASDWater(EntityInsentient entity, double speedModifier) {
+ super(entity);
+ this.speedModifier = speedModifier;
+ }
+
+ @Override
+ public void tick(EntityHuman rider) {
+ float forward = rider.getForward();
+ float strafe = rider.getStrafe() * 0.5F; // strafe slower by default
+ float vertical = -(rider.pitch / 90);
+
+ if (forward == 0.0F) {
+ // strafe slower if not moving forward
+ strafe *= 0.5F;
+ // do not move vertically if not moving forward
+ vertical = 0.0F;
+ } else if (forward < 0.0F) {
+ // water animals can't swim backwards
+ forward = 0.0F;
+ vertical = 0.0F;
+ }
+
+ if (rider.jumping && spacebarEvent(entity)) {
+ entity.onSpacebar();
+ }
+
+ setSpeed(entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue() * speedModifier);
+ entity.setSpeed((float) getSpeed() * 0.1F);
+
+ entity.setForward(forward * (float) speedModifier);
+ entity.setStrafe(strafe * (float) speedModifier);
+ entity.setVertical(vertical * (float) speedModifier);
+
+ setForward(entity.getForward());
+ setStrafe(entity.getStrafe());
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c7b1cb54bf0d64ae71d50532b61bb648396b2dc
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/entity/DolphinSpit.java
@@ -0,0 +1,119 @@
+package net.pl3x.purpur.entity;
+
+import net.minecraft.world.entity.animal.EntityDolphin;
+import net.minecraft.world.entity.projectile.EntityLlamaSpit;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityLiving;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.phys.MovingObjectPosition;
+import net.minecraft.world.phys.MovingObjectPositionBlock;
+import net.minecraft.world.phys.MovingObjectPositionEntity;
+import net.minecraft.core.particles.Particles;
+import net.minecraft.world.entity.projectile.ProjectileHelper;
+import net.minecraft.world.phys.Vec3D;
+import net.minecraft.world.level.World;
+import net.minecraft.server.level.WorldServer;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+
+public class DolphinSpit extends EntityLlamaSpit {
+ public EntityLiving dolphin;
+ public int ticksLived;
+
+ public DolphinSpit(EntityTypes<? extends EntityLlamaSpit> entitytypes, World world) {
+ super(entitytypes, world);
+ }
+
+ public DolphinSpit(World world, EntityDolphin dolphin) {
+ this(EntityTypes.LLAMA_SPIT, world);
+ setShooter(dolphin.hasRider() ? dolphin.getRider() : dolphin);
+ this.dolphin = dolphin;
+ this.setPosition(
+ dolphin.locX() - (double) (dolphin.getWidth() + 1.0F) * 0.5D * (double) MathHelper.sin(dolphin.getRenderYawOffset() * 0.017453292F),
+ dolphin.getHeadY() - 0.10000000149011612D,
+ dolphin.locZ() + (double) (dolphin.getWidth() + 1.0F) * 0.5D * (double) MathHelper.cos(dolphin.getRenderYawOffset() * 0.017453292F));
+ }
+
+ @Override
+ public boolean canSaveToDisk() {
+ return false;
+ }
+
+ public void tick() {
+ if (dead || !valid) {
+ return;
+ }
+
+ if (!leftOwner()) {
+ setLeftOwner(checkIfLeftOwner());
+ }
+
+ setFlag(6, isGlowing());
+ entityBaseTick();
+
+ Vec3D mot = getMot();
+
+ MovingObjectPosition hitResult = ProjectileHelper.getHitResult(this, this::hitPredicate);
+ if (hitResult != null) {
+ onHit(hitResult);
+ }
+
+ double x = this.locX() + mot.x;
+ double y = this.locY() + mot.y;
+ double z = this.locZ() + mot.z;
+ setMot(mot.scale(0.99D));
+
+ Vec3D motDouble = mot.scale(2.0);
+ for (int i = 0; i < 5; i++) {
+ ((WorldServer) world).sendParticles(null, Particles.BUBBLE,
+ locX() + random.nextFloat() / 2 - 0.25F,
+ locY() + random.nextFloat() / 2 - 0.25F,
+ locZ() + random.nextFloat() / 2 - 0.25F,
+ 0, motDouble.getX(), motDouble.getY(), motDouble.getZ(), 0.1, true);
+ }
+
+ if (++ticksLived > 20) {
+ die();
+ } else {
+ setMot(mot.scale(0.99D));
+ if (!isNoGravity()) {
+ setMot(getMot().add(0.0D, -0.06D, 0.0D));
+ }
+ setPosition(x, y, z);
+ }
+ }
+
+ @Override
+ public void shoot(double x, double y, double z, float speed, float inaccuracy) {
+ setMot(new Vec3D(x, y, z).normalize().add(
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy,
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy,
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy)
+ .scale(speed));
+ }
+
+ public void onHit(MovingObjectPosition rayTrace) {
+ CraftEventFactory.callProjectileHitEvent(this, rayTrace);
+ MovingObjectPosition.EnumMovingObjectType type = rayTrace.getType();
+ if (type == MovingObjectPosition.EnumMovingObjectType.ENTITY) {
+ onHit((MovingObjectPositionEntity) rayTrace);
+ } else if (type == MovingObjectPosition.EnumMovingObjectType.BLOCK) {
+ onHit((MovingObjectPositionBlock) rayTrace);
+ }
+ }
+
+ protected void onHit(MovingObjectPositionEntity rayTrace) {
+ Entity shooter = getShooter();
+ if (shooter instanceof EntityLiving) {
+ rayTrace.getEntity().damageEntity(DamageSource.indirectMobAttack(this, (EntityLiving) shooter).setProjectile(), world.purpurConfig.dolphinSpitDamage);
+ }
+ }
+
+ protected void onHit(MovingObjectPositionBlock rayTrace) {
+ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition());
+ iblockdata.a(world, iblockdata, rayTrace, this);
+ die();
+ }
+}
diff --git a/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d83a495cbe08e2f129a583ec2760391edb819ba
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/entity/PhantomFlames.java
@@ -0,0 +1,140 @@
+package net.pl3x.purpur.entity;
+
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityLiving;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.decoration.EntityArmorStand;
+import net.minecraft.world.entity.monster.EntityPhantom;
+import net.minecraft.world.entity.projectile.EntityLlamaSpit;
+import net.minecraft.world.level.block.state.BlockBase;
+import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.phys.MovingObjectPosition;
+import net.minecraft.world.phys.MovingObjectPositionBlock;
+import net.minecraft.world.phys.MovingObjectPositionEntity;
+import net.minecraft.core.particles.Particles;
+import net.minecraft.world.entity.projectile.ProjectileHelper;
+import net.minecraft.world.phys.Vec3D;
+import net.minecraft.world.level.World;
+import net.minecraft.server.level.WorldServer;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+
+public class PhantomFlames extends EntityLlamaSpit {
+ public EntityPhantom phantom;
+ public int ticksLived;
+ public boolean canGrief = false;
+
+ public PhantomFlames(EntityTypes<? extends EntityLlamaSpit> entitytypes, World world) {
+ super(entitytypes, world);
+ }
+
+ public PhantomFlames(World world, EntityPhantom phantom) {
+ this(EntityTypes.LLAMA_SPIT, world);
+ setShooter(phantom.hasRider() ? phantom.getRider() : phantom);
+ this.phantom = phantom;
+ this.setPosition(
+ phantom.locX() - (double) (phantom.getWidth() + 1.0F) * 0.5D * (double) MathHelper.sin(phantom.getRenderYawOffset() * 0.017453292F),
+ phantom.getHeadY() - 0.10000000149011612D,
+ phantom.locZ() + (double) (phantom.getWidth() + 1.0F) * 0.5D * (double) MathHelper.cos(phantom.getRenderYawOffset() * 0.017453292F));
+ }
+
+ @Override
+ public boolean canSaveToDisk() {
+ return false;
+ }
+
+ @Override
+ public void tick() {
+ if (dead || !valid) {
+ return;
+ }
+
+ if (!leftOwner()) {
+ setLeftOwner(checkIfLeftOwner());
+ }
+
+ setFlag(6, isGlowing());
+ entityBaseTick();
+
+ Vec3D mot = getMot();
+
+ MovingObjectPosition hitResult = ProjectileHelper.getHitResult(this, this::hitPredicate);
+ if (hitResult != null) {
+ onHit(hitResult);
+ }
+
+ if (dead) {
+ return;
+ }
+
+ double x = this.locX() + mot.x;
+ double y = this.locY() + mot.y;
+ double z = this.locZ() + mot.z;
+ setMot(mot.scale(0.99D));
+
+ Vec3D motDouble = mot.scale(2.0);
+ for (int i = 0; i < 5; i++) {
+ ((WorldServer) world).sendParticles(null, Particles.FLAME,
+ locX() + random.nextFloat() / 2 - 0.25F,
+ locY() + random.nextFloat() / 2 - 0.25F,
+ locZ() + random.nextFloat() / 2 - 0.25F,
+ 0, motDouble.getX(), motDouble.getY(), motDouble.getZ(), 0.1, true);
+ }
+
+ if (world.a(getBoundingBox()).noneMatch(BlockBase.BlockData::isAir)) {
+ die();
+ } else if (isInWaterOrBubbleColumn()) {
+ die();
+ } else if (++ticksLived > 20) {
+ die();
+ } else {
+ setMot(mot.scale(0.99D));
+ if (!isNoGravity()) {
+ setMot(getMot().add(0.0D, -0.06D, 0.0D));
+ }
+ setPosition(x, y, z);
+ }
+ }
+
+ @Override
+ public void shoot(double x, double y, double z, float speed, float inaccuracy) {
+ setMot(new Vec3D(x, y, z).normalize().add(
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy,
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy,
+ random.nextGaussian() * (double) 0.0075F * (double) inaccuracy)
+ .scale(speed));
+ }
+
+ public void onHit(MovingObjectPosition rayTrace) {
+ CraftEventFactory.callProjectileHitEvent(this, rayTrace);
+ MovingObjectPosition.EnumMovingObjectType type = rayTrace.getType();
+ if (type == MovingObjectPosition.EnumMovingObjectType.ENTITY) {
+ onHit((MovingObjectPositionEntity) rayTrace);
+ } else if (type == MovingObjectPosition.EnumMovingObjectType.BLOCK) {
+ onHit((MovingObjectPositionBlock) rayTrace);
+ }
+ }
+
+ protected void onHit(MovingObjectPositionEntity rayTrace) {
+ Entity shooter = getShooter();
+ if (shooter instanceof EntityLiving) {
+ Entity target = rayTrace.getEntity();
+ if (canGrief || (target instanceof EntityLiving && !(target instanceof EntityArmorStand))) {
+ target.damageEntity(DamageSource.indirectMobAttack(this, (EntityLiving) shooter).setProjectile(), world.purpurConfig.phantomFlameDamage);
+ if (world.purpurConfig.phantomFlameFireTime > 0) {
+ target.setOnFire(world.purpurConfig.phantomFlameFireTime);
+ }
+ }
+ }
+ die();
+ }
+
+ protected void onHit(MovingObjectPositionBlock rayTrace) {
+ if (canGrief) {
+ IBlockData iblockdata = world.getType(rayTrace.getBlockPosition());
+ iblockdata.a(world, iblockdata, rayTrace, this);
+ }
+ die();
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index dee4d12a49468d38f077784b219199f0070786f2..c524a0994f1c9ef1d0534403efa4e4481955b2f3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1175,4 +1175,26 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return getHandle().isTicking();
}
// Paper end
+
+ // Purpur start
+ @Override
+ public org.bukkit.entity.Player getRider() {
+ return hasRider() ? (org.bukkit.entity.Player) getHandle().getRider().getBukkitEntity() : null;
+ }
+
+ @Override
+ public boolean hasRider() {
+ return getHandle().hasRider();
+ }
+
+ @Override
+ public boolean isRidable() {
+ return getHandle().isRidable();
+ }
+
+ @Override
+ public boolean isRidableInWater() {
+ return getHandle().isRidableInWater();
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 9084aa4b7c0059c995a3d1a89188379b52c9d620..7341b1956123d8e5d45d9041e7319de8ee8b768a 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -530,6 +530,18 @@ public class CraftEventFactory {
}
craftServer.getPluginManager().callEvent(event);
+ // Purpur start
+ switch (action) {
+ case LEFT_CLICK_BLOCK:
+ case LEFT_CLICK_AIR:
+ who.processClick(EnumHand.MAIN_HAND);
+ break;
+ case RIGHT_CLICK_BLOCK:
+ case RIGHT_CLICK_AIR:
+ who.processClick(EnumHand.OFF_HAND);
+ }
+ // Purpur end
+
return event;
}
@@ -930,6 +942,7 @@ public class CraftEventFactory {
damageCause = DamageCause.ENTITY_EXPLOSION;
}
event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions);
+ damager.processClick(EnumHand.MAIN_HAND); // Purpur
}
event.setCancelled(cancelled);
@@ -1014,6 +1027,7 @@ public class CraftEventFactory {
if (!event.isCancelled()) {
event.getEntity().setLastDamageCause(event);
}
+ damager.getHandle().processClick(EnumHand.MAIN_HAND); // Purpur
return event;
}
@@ -1063,6 +1077,7 @@ public class CraftEventFactory {
EntityDamageEvent event;
if (damager != null) {
event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions);
+ damager.processClick(EnumHand.MAIN_HAND); // Purpur
} else {
event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, modifiers, modifierFunctions);
}