From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 5 Jul 2020 22:19:49 -0500 Subject: [PATCH] Ridables diff --git a/src/main/java/net/minecraft/server/ControllerMove.java b/src/main/java/net/minecraft/server/ControllerMove.java index ac6f9d9e52..d874b177b4 100644 --- a/src/main/java/net/minecraft/server/ControllerMove.java +++ b/src/main/java/net/minecraft/server/ControllerMove.java @@ -6,9 +6,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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java index 2d49816311..d14e4b1eef 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -80,7 +80,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper private CraftEntity bukkitEntity; - PlayerChunkMap.EntityTracker tracker; // Paper + PlayerChunkMap.EntityTracker tracker; public PlayerChunkMap.EntityTracker getTracker() { return tracker; } // Paper // Purpur boolean collisionLoadChunks = false; // Paper Throwable addedToWorldStack; // Paper - entity debug public CraftEntity getBukkitEntity() { @@ -121,7 +121,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke 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; @@ -2202,6 +2202,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke 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) { @@ -2296,7 +2297,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } else { 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 } @@ -2337,6 +2344,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke 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; } @@ -2728,6 +2741,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public void setHeadRotation(float f) {} + public void setBodyYaw(float yaw) { l(yaw); } // Purpur - OBFHELPER public void l(float f) {} public boolean bH() { @@ -3141,6 +3155,18 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke 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) {} @@ -3580,4 +3606,39 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke void accept(Entity entity, double d0, double d1, double d2); } + + // 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; + } + // Purpur end } diff --git a/src/main/java/net/minecraft/server/EntityCat.java b/src/main/java/net/minecraft/server/EntityCat.java index 20497c3962..3ac0d7afbf 100644 --- a/src/main/java/net/minecraft/server/EntityCat.java +++ b/src/main/java/net/minecraft/server/EntityCat.java @@ -15,7 +15,7 @@ public class EntityCat extends EntityTameableAnimal { private static final DataWatcherObject bA = DataWatcher.a(EntityCat.class, DataWatcherRegistry.i); private static final DataWatcherObject bB = DataWatcher.a(EntityCat.class, DataWatcherRegistry.i); private static final DataWatcherObject bC = DataWatcher.a(EntityCat.class, DataWatcherRegistry.b); - public static final Map bx = (Map) SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // CraftBukkit - decompile error + public static final Map bx = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // CraftBukkit - decompile error // Purpur - decompile error hashmap.put(0, new MinecraftKey("textures/entity/cat/tabby.png")); hashmap.put(1, new MinecraftKey("textures/entity/cat/black.png")); hashmap.put(2, new MinecraftKey("textures/entity/cat/red.png")); @@ -41,6 +41,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 eV() { return (MinecraftKey) EntityCat.bx.getOrDefault(this.getCatType(), EntityCat.bx.get(0)); } @@ -48,7 +67,8 @@ public class EntityCat extends EntityTameableAnimal { @Override protected void initPathfinder() { this.bE = new EntityCat.PathfinderGoalTemptChance(this, 0.6D, EntityCat.by, true); - this.goalSelector.a(1, new PathfinderGoalFloat(this)); + this.goalSelector.a(0, new PathfinderGoalFloat(this)); // Purpur + this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur this.goalSelector.a(1, new PathfinderGoalSit(this)); this.goalSelector.a(2, new EntityCat.b(this)); this.goalSelector.a(3, this.bE); @@ -60,6 +80,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 net.pl3x.purpur.pathfinder.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.bv)); } @@ -76,6 +97,7 @@ public class EntityCat extends EntityTameableAnimal { this.datawatcher.set(EntityCat.bz, i); } + public void setSleepingWithOwner(boolean flag) { x(flag); } // Purpur - OBFHELPER public void x(boolean flag) { this.datawatcher.set(EntityCat.bA, flag); } @@ -84,6 +106,7 @@ public class EntityCat extends EntityTameableAnimal { return (Boolean) this.datawatcher.get(EntityCat.bA); } + public void setHeadDown(boolean flag) { y(flag); } // Purpur - OBFHELPER public void y(boolean flag) { this.datawatcher.set(EntityCat.bB, flag); } @@ -302,6 +325,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(); @@ -399,6 +423,7 @@ public class EntityCat extends EntityTameableAnimal { public b(EntityCat entitycat) { this.a = entitycat; + this.a(java.util.EnumSet.of(PathfinderGoal.Type.MOVE)); // Purpur - lay on owner } @Override diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java index fa97552bb4..3a1d0a2f23 100644 --- a/src/main/java/net/minecraft/server/EntityChicken.java +++ b/src/main/java/net/minecraft/server/EntityChicken.java @@ -17,9 +17,22 @@ public class EntityChicken extends EntityAnimal { this.a(PathType.WATER, 0.0F); } + // Purpur start + @Override + public boolean isRidable() { + return world.purpurConfig.chickenRidable; + } + + @Override + public boolean isRidableInWater() { + return world.purpurConfig.chickenRidableInWater; + } + // Purpur end + @Override protected void initPathfinder() { this.goalSelector.a(0, new PathfinderGoalFloat(this)); + this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.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.bC)); @@ -30,6 +43,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 net.pl3x.purpur.pathfinder.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/server/EntityComplexPart.java b/src/main/java/net/minecraft/server/EntityComplexPart.java index 920f4c7671..7fec83387a 100644 --- a/src/main/java/net/minecraft/server/EntityComplexPart.java +++ b/src/main/java/net/minecraft/server/EntityComplexPart.java @@ -47,4 +47,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/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java index d6baddb9d3..a4b1255add 100644 --- a/src/main/java/net/minecraft/server/EntityCow.java +++ b/src/main/java/net/minecraft/server/EntityCow.java @@ -11,9 +11,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 net.pl3x.purpur.pathfinder.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 @@ -55,6 +68,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()) { @@ -62,7 +76,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 super.b(entityhuman, enumhand); } // CraftBukkit end @@ -73,7 +87,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); @@ -96,7 +110,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) { @@ -107,7 +121,7 @@ public class EntityCow extends EntityAnimal { } EntityMushroomCow mooshroom = EntityTypes.MOOSHROOM.create(world); if (mooshroom == null) { - return EnumInteractionResult.PASS; + return super.b(entityhuman, enumhand); } if (itemstack.getItem() == Blocks.BROWN_MUSHROOM.getItem()) { mooshroom.setVariant(EntityMushroomCow.Type.BROWN); @@ -126,10 +140,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 super.b(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 super.b(entityhuman, enumhand); } this.world.addEntity(mooshroom); this.die(); diff --git a/src/main/java/net/minecraft/server/EntityFox.java b/src/main/java/net/minecraft/server/EntityFox.java index 90b01adbec..26de8c3ad6 100644 --- a/src/main/java/net/minecraft/server/EntityFox.java +++ b/src/main/java/net/minecraft/server/EntityFox.java @@ -55,6 +55,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(); @@ -74,6 +107,7 @@ public class EntityFox extends EntityAnimal { return entityliving instanceof EntityFishSchool; }); this.goalSelector.a(0, new EntityFox.g()); + this.goalSelector.a(0, new net.pl3x.purpur.pathfinder.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)); @@ -99,6 +133,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 net.pl3x.purpur.pathfinder.PathfinderGoalHasRider(this)); // Purpur this.targetSelector.a(3, new EntityFox.a(EntityLiving.class, false, false, (entityliving) -> { return EntityFox.bA.test(entityliving) && !this.c(entityliving.getUniqueID()); })); @@ -386,6 +421,7 @@ public class EntityFox extends EntityAnimal { return itemstack1.isEmpty() || this.bK > 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); @@ -480,6 +516,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); } @@ -522,6 +559,7 @@ public class EntityFox extends EntityAnimal { this.setSleeping(false); } + public void stopActions() { fe(); } // Purpur - OBFHELPER private void fe() { this.w(false); this.setCrouching(false); @@ -687,16 +725,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 } } @@ -1365,16 +1403,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.ff()) { - super.a(); + super.tick(); // Purpur } } diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java index adf414b479..a6c2119be9 100644 --- a/src/main/java/net/minecraft/server/EntityHorse.java +++ b/src/main/java/net/minecraft/server/EntityHorse.java @@ -12,6 +12,13 @@ public class EntityHorse extends EntityHorseAbstract { super(entitytypes, world); } + // Purpur start + @Override + public boolean isRidableInWater() { + return world.purpurConfig.horseRidableInWater; + } + // Purpur end + @Override protected void eL() { this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue((double) this.fq()); diff --git a/src/main/java/net/minecraft/server/EntityHorseAbstract.java b/src/main/java/net/minecraft/server/EntityHorseAbstract.java index c9ab80ccd1..94fd1b14f3 100644 --- a/src/main/java/net/minecraft/server/EntityHorseAbstract.java +++ b/src/main/java/net/minecraft/server/EntityHorseAbstract.java @@ -39,12 +39,27 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven protected EntityHorseAbstract(EntityTypes 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 net.pl3x.purpur.pathfinder.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)); diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java index d349e8a34b..01672ed635 100644 --- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java +++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java @@ -8,6 +8,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/server/EntityHorseMule.java b/src/main/java/net/minecraft/server/EntityHorseMule.java index 5105418c42..4d45976d7c 100644 --- a/src/main/java/net/minecraft/server/EntityHorseMule.java +++ b/src/main/java/net/minecraft/server/EntityHorseMule.java @@ -8,6 +8,13 @@ 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/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java index 43e605f682..ca8f73c752 100644 --- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java +++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java @@ -12,6 +12,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 eM() { return fj().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); } @@ -22,7 +34,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { } @Override - protected void eW() {} + protected void eW() { if (world.purpurConfig.skeletonHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur @Override protected SoundEffect getSoundAmbient() { @@ -117,7 +129,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { @Override public boolean bp() { - return true; + return super.bp(); // Purpur } @Override diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java index 0cbdccf4c5..19a21ff98d 100644 --- a/src/main/java/net/minecraft/server/EntityHorseZombie.java +++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java @@ -8,6 +8,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 eM() { return fj().a(GenericAttributes.MAX_HEALTH, 15.0D).a(GenericAttributes.MOVEMENT_SPEED, 0.20000000298023224D); } @@ -79,5 +91,5 @@ public class EntityHorseZombie extends EntityHorseAbstract { } @Override - protected void eW() {} + protected void eW() { if (world.purpurConfig.zombieHorseCanSwim) goalSelector.a(0, new PathfinderGoalFloat(this)); } // Purpur } diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java index 8def5fbfb4..a64de2248b 100644 --- a/src/main/java/net/minecraft/server/EntityInsentient.java +++ b/src/main/java/net/minecraft/server/EntityInsentient.java @@ -67,8 +67,8 @@ public abstract class EntityInsentient extends EntityLiving { this.bH = -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.moveController = new net.pl3x.purpur.controller.ControllerMoveWASD(this); // Purpur + this.lookController = new net.pl3x.purpur.controller.ControllerLookWASD(this); // Purpur this.bp = new ControllerJump(this); this.c = this.r(); this.navigation = this.b(world); @@ -532,6 +532,7 @@ public abstract class EntityInsentient extends EntityLiving { this.aY = f; } + public void setSpeed(float speed) { n(speed); } // Purpur - OBFHELPER @Override public void n(float f) { super.n(f); @@ -1200,7 +1201,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 ew() { @@ -1559,4 +1560,42 @@ public abstract class EntityInsentient extends EntityLiving { this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit this.unleash(true, false); } + + // 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 (!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 (!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/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java index cb9fdfd114..22b13896d0 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -458,7 +458,7 @@ public abstract class EntityLiving extends Entity { @Override public boolean bp() { - return false; + return isRidableInWater(); // Purpur } protected void cT() { @@ -2156,7 +2156,7 @@ public abstract class EntityLiving extends Entity { return 0.42F * this.getBlockJumpFactor(); } - protected void jump() { + public void jump() { // Purpur - protected -> public float f = this.dI(); if (this.hasEffect(MobEffects.JUMP)) { diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java index cf31920850..e8a87e6bed 100644 --- a/src/main/java/net/minecraft/server/EntityLlama.java +++ b/src/main/java/net/minecraft/server/EntityLlama.java @@ -18,6 +18,28 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn public EntityLlama(EntityTypes 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 } public void setStrength(int i) { diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java index 1be0f943b0..8a8e745846 100644 --- a/src/main/java/net/minecraft/server/EntityRabbit.java +++ b/src/main/java/net/minecraft/server/EntityRabbit.java @@ -60,7 +60,7 @@ public class EntityRabbit extends EntityAnimal { } @Override - protected void jump() { + public void jump() { // Purpur - protected -> public super.jump(); double d0 = this.moveController.c(); diff --git a/src/main/java/net/minecraft/server/EntitySlime.java b/src/main/java/net/minecraft/server/EntitySlime.java index a4642cc739..ecf2059b00 100644 --- a/src/main/java/net/minecraft/server/EntitySlime.java +++ b/src/main/java/net/minecraft/server/EntitySlime.java @@ -324,7 +324,7 @@ 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.dI(), vec3d.z); diff --git a/src/main/java/net/minecraft/server/EntityTameableAnimal.java b/src/main/java/net/minecraft/server/EntityTameableAnimal.java index 9b0d937f06..0b0cca4e35 100644 --- a/src/main/java/net/minecraft/server/EntityTameableAnimal.java +++ b/src/main/java/net/minecraft/server/EntityTameableAnimal.java @@ -130,6 +130,7 @@ public abstract class EntityTameableAnimal extends EntityAnimal { return this.j(entityliving) ? false : super.d(entityliving); } + public boolean isOwner(EntityLiving entityLiving) { return j(entityLiving); } // Purpur - OBFHELPER public boolean j(EntityLiving entityliving) { return entityliving == this.getOwner(); } diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java index 494d36085e..9cde3693c5 100644 --- a/src/main/java/net/pl3x/purpur/PurpurConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java @@ -132,10 +132,12 @@ public class PurpurConfig { public static String afkBroadcastAway = "§e§o%s is now AFK"; public static String afkBroadcastBack = "§e§o%s is no longer 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); pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput); + cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob); } public static String serverModName = "Purpur"; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java index 2f5bc77e03..9d6894a24c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -266,22 +266,34 @@ public class PurpurWorldConfig { turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts); } + 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 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 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); } @@ -292,6 +304,11 @@ public class PurpurWorldConfig { creeperChargedChance = getDouble("mobs.creeper.naturally-charged-chance", creeperChargedChance); } + public boolean donkeyRidableInWater = false; + private void donkeySettings() { + donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater); + } + public boolean drownedJockeyOnlyBaby = true; public double drownedJockeyChance = 0.05D; public boolean drownedJockeyTryExistingChickens = true; @@ -315,8 +332,12 @@ public class PurpurWorldConfig { endermanAllowGriefing = getBoolean("mobs.enderman.allow-griefing", endermanAllowGriefing); } + 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); } @@ -337,6 +358,11 @@ public class PurpurWorldConfig { giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI); } + public boolean horseRidableInWater = false; + private void horseSettings() { + horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater); + } + public boolean huskJockeyOnlyBaby = true; public double huskJockeyChance = 0.05D; public boolean huskJockeyTryExistingChickens = true; @@ -360,6 +386,11 @@ public class PurpurWorldConfig { ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim); } + public boolean muleRidableInWater = false; + private void muleSettings() { + muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater); + } + public double phantomAttackedByCrystalRadius = 0.0D; public float phantomAttackedByCrystalDamage = 1.0F; public double phantomOrbitCrystalRadius = 0.0D; @@ -413,6 +444,13 @@ public class PurpurWorldConfig { rabbitNaturalKiller = getDouble("mobs.rabbit.spawn-killer-rabbit-chance", rabbitNaturalKiller); } + 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 snowGolemDropsPumpkin = false; public boolean snowGolemPutPumpkinBack = false; private void snowGolemSettings() { @@ -460,8 +498,12 @@ public class PurpurWorldConfig { 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); } 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 0000000000..828e1b8730 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java @@ -0,0 +1,75 @@ +package net.pl3x.purpur.controller; + +import net.minecraft.server.ControllerLook; +import net.minecraft.server.EntityHuman; +import net.minecraft.server.EntityInsentient; +import net.minecraft.server.MathHelper; +import net.minecraft.server.PacketPlayOutEntity; + +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.setHeadRotation(entity.yaw); + entity.pitch = normalizePitch(pitch + pitchOffset); + + entity.getTracker().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 0000000000..6086f63119 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java @@ -0,0 +1,86 @@ +package net.pl3x.purpur.controller; + +import net.minecraft.server.ControllerMove; +import net.minecraft.server.Entity; +import net.minecraft.server.EntityHuman; +import net.minecraft.server.EntityInsentient; +import net.minecraft.server.GenericAttributes; +import net.pl3x.purpur.event.entity.RidableSpacebarEvent; + +public class ControllerMoveWASD extends ControllerMove { + protected final EntityInsentient entity; + + public ControllerMoveWASD(EntityInsentient entity) { + super(entity); + this.entity = entity; + } + + // 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(); + } + } + + protected void tick() { + super.a(); // tick + } + + protected 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()); + + 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/pathfinder/PathfinderGoalHasRider.java b/src/main/java/net/pl3x/purpur/pathfinder/PathfinderGoalHasRider.java new file mode 100644 index 0000000000..6e50344c07 --- /dev/null +++ b/src/main/java/net/pl3x/purpur/pathfinder/PathfinderGoalHasRider.java @@ -0,0 +1,21 @@ +package net.pl3x.purpur.pathfinder; + +import net.minecraft.server.Entity; +import net.minecraft.server.PathfinderGoal; + +import java.util.EnumSet; + +public class PathfinderGoalHasRider extends PathfinderGoal { + public final Entity entity; + + public PathfinderGoalHasRider(Entity entity) { + this.entity = entity; + setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET)); + } + + // shouldExecute + @Override + public boolean a() { + return entity.hasRider(); + } +} diff --git a/src/main/java/net/pl3x/purpur/pathfinder/PathfinderGoalHorseHasRider.java b/src/main/java/net/pl3x/purpur/pathfinder/PathfinderGoalHorseHasRider.java new file mode 100644 index 0000000000..fb18f72a6a --- /dev/null +++ b/src/main/java/net/pl3x/purpur/pathfinder/PathfinderGoalHorseHasRider.java @@ -0,0 +1,21 @@ +package net.pl3x.purpur.pathfinder; + +import net.minecraft.server.EntityHorseAbstract; +import net.minecraft.server.PathfinderGoal; + +import java.util.EnumSet; + +public class PathfinderGoalHorseHasRider extends PathfinderGoal { + public final EntityHorseAbstract entity; + + public PathfinderGoalHorseHasRider(EntityHorseAbstract entity) { + this.entity = entity; + setTypes(EnumSet.of(Type.JUMP, Type.MOVE, Type.LOOK, Type.TARGET)); + } + + // shouldExecute + @Override + public boolean a() { + return super.a() && entity.hasSaddle(); + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index 309e7f6ee7..2d9320b059 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -1125,4 +1125,26 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return getHandle().isInLava(); } // 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 }