diff --git a/patches/server/0008-Integrate-ridables.patch b/patches/server/0008-Integrate-ridables.patch index 7cc7e0660..5b7eb0877 100644 --- a/patches/server/0008-Integrate-ridables.patch +++ b/patches/server/0008-Integrate-ridables.patch @@ -1,56 +1,60 @@ -From e60b8c7f853e7a4708358f16fc60548e3c542318 Mon Sep 17 00:00:00 2001 +From 06a7a4326ebb2250a3adac29b758fcf3bdd8da76 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 30 Apr 2019 19:17:21 -0500 Subject: [PATCH] Integrate ridables --- - .../java/net/minecraft/server/BiomeBase.java | 26 ++++++- - .../net/minecraft/server/ControllerJump.java | 1 + - .../server/ControllerLookDolphin.java | 4 +- - .../java/net/minecraft/server/Entity.java | 16 +++- - .../net/minecraft/server/EntityChicken.java | 17 +++- - .../java/net/minecraft/server/EntityCow.java | 14 ++++ - .../net/minecraft/server/EntityCreeper.java | 14 ++++ - .../net/minecraft/server/EntityDolphin.java | 28 ++++++- - .../net/minecraft/server/EntityDrowned.java | 38 ++++++++- - .../net/minecraft/server/EntityEnderman.java | 15 ++++ - .../net/minecraft/server/EntityEndermite.java | 15 ++++ - .../java/net/minecraft/server/EntityFish.java | 28 ++++++- - .../minecraft/server/EntityGiantZombie.java | 36 ++++++++- - .../net/minecraft/server/EntityGuardian.java | 36 ++++++++- - .../net/minecraft/server/EntityHorse.java | 10 ++- - .../minecraft/server/EntityHorseAbstract.java | 4 +- - .../server/EntityHorseChestedAbstract.java | 18 +++-- - .../minecraft/server/EntityHorseDonkey.java | 3 + - .../net/minecraft/server/EntityHorseMule.java | 3 + - .../minecraft/server/EntityHorseSkeleton.java | 15 ++-- - .../minecraft/server/EntityHorseZombie.java | 12 +-- - .../net/minecraft/server/EntityHuman.java | 14 +++- - .../minecraft/server/EntityInsentient.java | 39 ++++++++++ - .../net/minecraft/server/EntityIronGolem.java | 15 ++++ - .../net/minecraft/server/EntityLiving.java | 21 ++++- - .../net/minecraft/server/EntityLlama.java | 37 ++++++++- - .../minecraft/server/EntityMushroomCow.java | 14 ++++ - .../net/minecraft/server/EntityOcelot.java | 14 ++++ - .../java/net/minecraft/server/EntityPig.java | 25 ++++++ - .../net/minecraft/server/EntityPolarBear.java | 15 ++++ - .../net/minecraft/server/EntitySheep.java | 14 ++++ - .../minecraft/server/EntitySilverfish.java | 15 ++++ - .../server/EntitySkeletonAbstract.java | 15 ++++ - .../net/minecraft/server/EntitySnowman.java | 15 ++++ - .../net/minecraft/server/EntitySpider.java | 15 ++++ - .../net/minecraft/server/EntitySquid.java | 57 ++++++++++++++ - .../server/EntityTameableAnimal.java | 6 ++ - .../net/minecraft/server/EntityTypes.java | 6 ++ - .../java/net/minecraft/server/EntityWolf.java | 14 ++++ - .../net/minecraft/server/EntityZombie.java | 15 ++++ - .../purpur/controller/ControllerLookWASD.java | 46 +++++++++++ - .../purpur/controller/ControllerMoveWASD.java | 77 +++++++++++++++++++ - .../controller/ControllerMoveWASDWater.java | 42 ++++++++++ - .../craftbukkit/entity/CraftLivingEntity.java | 10 +++ - 44 files changed, 851 insertions(+), 43 deletions(-) + .../java/net/minecraft/server/BiomeBase.java | 26 ++- + .../net/minecraft/server/ControllerJump.java | 1 + + .../server/ControllerLookDolphin.java | 4 +- + .../java/net/minecraft/server/Entity.java | 16 +- + .../net/minecraft/server/EntityChicken.java | 17 +- + .../java/net/minecraft/server/EntityCow.java | 14 ++ + .../net/minecraft/server/EntityCreeper.java | 14 ++ + .../net/minecraft/server/EntityDolphin.java | 28 ++- + .../net/minecraft/server/EntityDrowned.java | 38 +++- + .../minecraft/server/EntityEnderCrystal.java | 49 +++++ + .../net/minecraft/server/EntityEnderman.java | 15 ++ + .../net/minecraft/server/EntityEndermite.java | 15 ++ + .../java/net/minecraft/server/EntityFish.java | 28 ++- + .../minecraft/server/EntityGiantZombie.java | 36 +++- + .../net/minecraft/server/EntityGuardian.java | 36 +++- + .../net/minecraft/server/EntityHorse.java | 10 +- + .../minecraft/server/EntityHorseAbstract.java | 4 +- + .../server/EntityHorseChestedAbstract.java | 18 +- + .../minecraft/server/EntityHorseDonkey.java | 3 + + .../net/minecraft/server/EntityHorseMule.java | 3 + + .../minecraft/server/EntityHorseSkeleton.java | 15 +- + .../minecraft/server/EntityHorseZombie.java | 12 +- + .../net/minecraft/server/EntityHuman.java | 14 +- + .../minecraft/server/EntityInsentient.java | 39 ++++ + .../net/minecraft/server/EntityIronGolem.java | 15 ++ + .../net/minecraft/server/EntityLiving.java | 21 +- + .../net/minecraft/server/EntityLlama.java | 37 +++- + .../minecraft/server/EntityMushroomCow.java | 14 ++ + .../net/minecraft/server/EntityOcelot.java | 14 ++ + .../net/minecraft/server/EntityPhantom.java | 203 ++++++++++++++++-- + .../java/net/minecraft/server/EntityPig.java | 25 +++ + .../net/minecraft/server/EntityPolarBear.java | 15 ++ + .../net/minecraft/server/EntitySheep.java | 14 ++ + .../minecraft/server/EntitySilverfish.java | 15 ++ + .../server/EntitySkeletonAbstract.java | 15 ++ + .../net/minecraft/server/EntitySnowman.java | 15 ++ + .../net/minecraft/server/EntitySpider.java | 15 ++ + .../net/minecraft/server/EntitySquid.java | 57 +++++ + .../server/EntityTameableAnimal.java | 6 + + .../net/minecraft/server/EntityTypes.java | 6 + + .../java/net/minecraft/server/EntityWolf.java | 14 ++ + .../net/minecraft/server/EntityZombie.java | 15 ++ + .../purpur/controller/ControllerLookWASD.java | 46 ++++ + .../purpur/controller/ControllerMoveWASD.java | 77 +++++++ + .../controller/ControllerMoveWASDFlying.java | 58 +++++ + .../controller/ControllerMoveWASDWater.java | 42 ++++ + .../craftbukkit/entity/CraftLivingEntity.java | 10 + + 47 files changed, 1149 insertions(+), 55 deletions(-) create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java + create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDWater.java diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java @@ -420,6 +424,74 @@ index 0e2b5ee7..522f7d61 100644 private boolean dI() { if (this.bC) { return true; +diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java +index 79bdb82b..020a0f2d 100644 +--- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java ++++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java +@@ -13,6 +13,12 @@ public class EntityEnderCrystal extends Entity { + private static final DataWatcherObject> b = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); + private static final DataWatcherObject c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); + public int a; ++ // Purpur start ++ private EntityPhantom targetPhantom; ++ private int phantomBeamTicks = 0; ++ private int phantomDamageCooldown = 0; ++ private int idleCooldown = 0; ++ // Purpur end + + public EntityEnderCrystal(World world) { + super(EntityTypes.END_CRYSTAL, world); +@@ -52,7 +58,50 @@ public class EntityEnderCrystal extends Entity { + } + } + ++ // Purpur start ++ if (--idleCooldown > 0) { ++ return; // on cooldown ++ } ++ ++ if (targetPhantom == null) { ++ for (EntityPhantom phantom : world.a(EntityPhantom.class, getBoundingBox().grow(16, 16, 16))) { ++ if (phantom.hasLineOfSight(this)) { ++ attackPhantom(phantom); ++ break; ++ } ++ } ++ } else { ++ setBeamTarget(new BlockPosition(targetPhantom).add(0, -2, 0)); ++ if (--phantomBeamTicks > 0 && targetPhantom.isAlive()) { ++ phantomDamageCooldown--; ++ if (targetPhantom.hasLineOfSight(this)) { ++ if (phantomDamageCooldown <= 0) { ++ phantomDamageCooldown = 20; ++ targetPhantom.damageEntity(DamageSource.c(this, this), 1.0F); ++ } ++ } else { ++ forgetPhantom(); // no longer in sight ++ } ++ } else { ++ forgetPhantom(); // attacked long enough ++ } ++ } ++ } ++ ++ private void attackPhantom(EntityPhantom phantom) { ++ phantomDamageCooldown = 0; ++ phantomBeamTicks = 60; ++ targetPhantom = phantom; ++ } ++ ++ private void forgetPhantom() { ++ targetPhantom = null; ++ setBeamTarget(null); ++ phantomBeamTicks = 0; ++ phantomDamageCooldown = 0; ++ idleCooldown = 60; + } ++ // Purpur end + + protected void b(NBTTagCompound nbttagcompound) { + if (this.getBeamTarget() != null) { diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java index 94504044..7ac728ba 100644 --- a/src/main/java/net/minecraft/server/EntityEnderman.java @@ -1176,6 +1248,315 @@ index 13c84bda..bee1532a 100644 ItemStack itemstack = entityhuman.b(enumhand); if (this.isTamed()) { +diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java +index f576264a..8a5aed24 100644 +--- a/src/main/java/net/minecraft/server/EntityPhantom.java ++++ b/src/main/java/net/minecraft/server/EntityPhantom.java +@@ -1,5 +1,7 @@ + package net.minecraft.server; + ++import net.pl3x.purpur.controller.ControllerLookWASD; ++ + import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; +@@ -7,9 +9,10 @@ import javax.annotation.Nullable; + public class EntityPhantom extends EntityFlying implements IMonster { + + private static final DataWatcherObject a = DataWatcher.a(EntityPhantom.class, DataWatcherRegistry.b); +- private Vec3D b; +- private BlockPosition c; +- private EntityPhantom.AttackPhase bC; ++ private Vec3D b; public Vec3D getOrbitOffset() { return this.b; } public void setOrbitOffset(Vec3D offset) { this.b = offset; } // Purpur - OBFHELPER ++ private BlockPosition c; public BlockPosition getOrbitPosition() { return this.c; } public void setOrbitPosition(BlockPosition position) { this.c = position; } // Purpur - OBFHELPER ++ private EntityPhantom.AttackPhase bC; public AttackPhase getPhase() { return this.bC; } public void setPhase(AttackPhase phase) { this.bC = phase; } // Purpur - OBFHELPER ++ private BlockPosition totemPosition; public BlockPosition getTotemPosition() { return this.totemPosition; } public void setTotemPosition(BlockPosition position) { this.totemPosition = position; } // Purpur + + public EntityPhantom(World world) { + super(EntityTypes.PHANTOM, world); +@@ -20,6 +23,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + this.setSize(0.9F, 0.5F); + this.moveController = new EntityPhantom.g(this); + this.lookController = new EntityPhantom.f(this); ++ this.canBeRiddenInWater = false; // Purpur + } + + protected EntityAIBodyControl o() { +@@ -27,8 +31,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + + protected void n() { ++ this.goalSelector.a(0, new FindTotemGoal(this)); // Purpur + this.goalSelector.a(1, new EntityPhantom.c()); + this.goalSelector.a(2, new EntityPhantom.i()); ++ this.goalSelector.a(3, new OrbitTotemGoal(this)); // Purpur + this.goalSelector.a(3, new EntityPhantom.e()); + this.targetSelector.a(1, new EntityPhantom.b()); + } +@@ -103,7 +109,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + + public void movementTick() { +- if (this.dq()) { ++ if (getRider() == null && this.dq()) { // Purpur - do not set fire if being ridden + this.setOnFire(8); + } + +@@ -114,6 +120,25 @@ public class EntityPhantom extends EntityFlying implements IMonster { + super.mobTick(); + } + ++ // Purpur start ++ @Override ++ protected void a(boolean wasRecentlyHit, int lootingModifier, DamageSource damagesource) { // dropLoot ++ boolean dropped = false; ++ if (killer == null && damagesource.getEntity() instanceof EntityEnderCrystal) { ++ if (random.nextInt(5) < 1) { // 1 out of 5 chance (20%) ++ dropped = a_(new ItemStack(Items.PHANTOM_MEMBRANE)) != null; ++ } ++ } ++ if (!dropped) { ++ super.a(wasRecentlyHit, lootingModifier, damagesource); // dropLoot ++ } ++ } ++ ++ public boolean isCirclingTotem() { ++ return totemPosition != null; ++ } ++ // Purpur end ++ + public GroupDataEntity prepare(DifficultyDamageScaler difficultydamagescaler, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { + this.c = (new BlockPosition(this)).up(5); + this.setSize(0); +@@ -188,6 +213,138 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + // Paper end + ++ // Purpur start - processInteract ++ @Override ++ public boolean a(EntityHuman entityhuman, EnumHand enumhand) { ++ if (super.a(entityhuman, enumhand)) { ++ return true; // vanilla action handled ++ } ++ return tryRide(entityhuman, enumhand); ++ } ++ ++ class FindTotemGoal extends PathfinderGoal { ++ private final EntityPhantom phantom; ++ private EntityEnderCrystal totem; ++ private PathfinderGoalNearestAttackableTarget.DistanceComparator comparator; ++ ++ FindTotemGoal(EntityPhantom phantom) { ++ this.phantom = phantom; ++ comparator = new PathfinderGoalNearestAttackableTarget.DistanceComparator(phantom); ++ } ++ ++ @Override ++ public boolean a() { // shouldExecute ++ if (phantom.getRider() != null) { ++ return false; ++ } ++ double range = maxTargetRange(); ++ List crystals = world.a(EntityEnderCrystal.class, phantom.getBoundingBox().grow(range, range, range)); ++ if (crystals.isEmpty()) { ++ return false; ++ } ++ crystals.sort(comparator); ++ totem = crystals.get(0); ++ if (phantom.h(totem) > range * range) { ++ totem = null; ++ return false; ++ } ++ return true; ++ } ++ ++ @Override ++ public boolean b() { // shouldContinueExecuting ++ if (phantom.getRider() != null) { ++ return false; ++ } ++ if (totem == null || !totem.isAlive()) { ++ return false; ++ } ++ double range = maxTargetRange(); ++ return phantom.h(totem) <= (range * range) * 2; ++ } ++ ++ @Override ++ public void c() { // startExecuting ++ phantom.setTotemPosition(new BlockPosition(totem).add(0, phantom.getRandom().nextInt(10) + 10, 0)); ++ } ++ ++ @Override ++ public void d() { // resetTask ++ totem = null; ++ phantom.setTotemPosition(null); ++ super.d(); ++ } ++ ++ private double maxTargetRange() { ++ AttributeInstance range = phantom.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); ++ return range == null ? 16.0D : range.getValue(); ++ } ++ } ++ ++ class OrbitTotemGoal extends PathfinderGoal { ++ private final EntityPhantom phantom; ++ private float c; ++ private float radius; ++ private float verticalChange; ++ private float direction; ++ ++ OrbitTotemGoal(EntityPhantom phantom) { ++ this.phantom = phantom; ++ a(1); ++ } ++ ++ @Override ++ public boolean a() { // shouldExecute ++ return phantom.getRider() == null && phantom.isCirclingTotem(); ++ } ++ ++ @Override ++ public void c() { // startExecuting ++ this.radius = 5.0F + phantom.random.nextFloat() * 10.0F; ++ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; ++ this.direction = phantom.random.nextBoolean() ? 1.0F : -1.0F; ++ updateOffset(); ++ } ++ ++ @Override ++ public void e() { // tick ++ if (phantom.random.nextInt(350) == 0) { ++ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; ++ } ++ if (phantom.random.nextInt(250) == 0) { ++ ++this.radius; ++ if (this.radius > 15.0F) { ++ this.radius = 5.0F; ++ this.direction = -this.direction; ++ } ++ } ++ if (phantom.random.nextInt(450) == 0) { ++ this.c = phantom.random.nextFloat() * 2.0F * 3.1415927F; ++ updateOffset(); ++ } ++ if (phantom.b.c(phantom.locX, phantom.locY, phantom.locZ) < 4.0D) { ++ updateOffset(); ++ } ++ if (phantom.b.y < phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).down(1))) { ++ this.verticalChange = Math.max(1.0F, this.verticalChange); ++ updateOffset(); ++ } ++ if (phantom.b.y > phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).up(1))) { ++ this.verticalChange = Math.min(-1.0F, this.verticalChange); ++ updateOffset(); ++ } ++ } ++ ++ private void updateOffset() { ++ this.c += this.direction * 15.0F * 0.017453292F; ++ phantom.setOrbitOffset(new Vec3D(phantom.totemPosition).add( ++ (double) (this.radius * MathHelper.cos(this.c)), ++ (double) (-4.0F + this.verticalChange), ++ (double) (this.radius * MathHelper.sin(this.c)))); ++ } ++ } ++ // Purpur end ++ + class b extends PathfinderGoal { + + private int b; +@@ -237,7 +394,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + private c() {} + + public boolean a() { +- return PathfinderGoalTarget.a(EntityPhantom.this, EntityPhantom.this.getGoalTarget(), false, false); ++ return !isCirclingTotem() && PathfinderGoalTarget.a(EntityPhantom.this, EntityPhantom.this.getGoalTarget(), false, false); // Purpur + } + + public void c() { +@@ -279,13 +436,13 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + + public boolean a() { +- return EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bC == EntityPhantom.AttackPhase.SWOOP; ++ return !isCirclingTotem() && EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bC == EntityPhantom.AttackPhase.SWOOP; // Purpur + } + + public boolean b() { + EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); + +- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && (((EntityHuman) entityliving).isSpectator() || ((EntityHuman) entityliving).u()) ? false : this.a())); ++ return !isCirclingTotem() && entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && (((EntityHuman) entityliving).isSpectator() || ((EntityHuman) entityliving).u()) ? false : this.a())); // Purpur + } + + public void c() {} +@@ -322,7 +479,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + + public boolean a() { +- return EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bC == EntityPhantom.AttackPhase.CIRCLE; ++ return !isCirclingTotem() && (EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bC == EntityPhantom.AttackPhase.CIRCLE); // Purpur + } + + public void c() { +@@ -387,13 +544,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + } + +- class f extends ControllerLook { ++ class f extends ControllerLookWASD { // Purpur + + public f(EntityInsentient entityinsentient) { + super(entityinsentient); + } + +- public void a() {} ++ // Purpur start ++ @Override ++ public void tick(EntityHuman rider) { ++ setYawPitch(rider.yaw, -rider.pitch * 0.75F); ++ } ++ ++ @Override ++ public void tick() { ++ // do nothing ++ } ++ // Purpur end + } + + class d extends EntityAIBodyControl { +@@ -408,7 +575,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; + +@@ -416,7 +583,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { + super(entityinsentient); + } + +- public void a() { ++ // Purpur start ++ @Override ++ 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/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java index d1689dc3..50efffcf 100644 --- a/src/main/java/net/minecraft/server/EntityPig.java @@ -1757,6 +2138,70 @@ index 00000000..4f7dec9b + g = entity.getStrafe(); + } +} +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 00000000..197b4951 +--- /dev/null ++++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java +@@ -0,0 +1,58 @@ ++package net.pl3x.purpur.controller; ++ ++import net.minecraft.server.EntityHuman; ++import net.minecraft.server.EntityInsentient; ++import net.minecraft.server.GenericAttributes; ++ ++public class ControllerMoveWASDFlying extends ControllerMoveWASD { ++ protected final float groundSpeedModifier; ++ private final double maxY; ++ private int tooHighCooldown = 0; ++ ++ public ControllerMoveWASDFlying(EntityInsentient entity) { ++ this(entity, 1.0F, 256D); ++ } ++ ++ public ControllerMoveWASDFlying(EntityInsentient entity, float groundSpeedModifier, double maxY) { ++ super(entity); ++ this.groundSpeedModifier = groundSpeedModifier; ++ this.maxY = maxY; ++ } ++ ++ @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.isJumping()) { ++ //RidableSpacebarEvent event = new RidableSpacebarEvent(ridable); ++ //Bukkit.getPluginManager().callEvent(event); ++ //if (!event.isCancelled() && !event.isHandled()) { ++ entity.onSpacebar(); ++ //} ++ } ++ ++ if (entity.locY >= maxY || --tooHighCooldown > 0) { ++ tooHighCooldown = 60; ++ entity.motY = -0.05F; ++ vertical = 0.0F; ++ } ++ ++ float speed = (float) (e = entity.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).getValue()); ++ ++ if (entity.onGround) { ++ speed *= groundSpeedModifier; // TODO = fix this! ++ } ++ ++ entity.setNoGravity(forward > 0); ++ ++ entity.setSpeed(speed); ++ entity.setVertical(vertical); ++ entity.setStrafe(strafe); ++ entity.setForward(forward); ++ ++ f = entity.getForward(); ++ g = entity.getStrafe(); ++ } ++} 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 00000000..74ff4825