mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@812701d Do not crash when an exp orb attempts to mend an unrepairable item PaperMC/Paper@19eefe9 Fix SoundEffects only to players diff (#10966) PaperMC/Paper@95aa440 Add missing effect cause and deprecate PATROL_CAPTAIN cause (#10958) PaperMC/Paper@b2e5587 Expose LivingEntity#canUseSlot (#10930) PaperMC/Paper@97afc9a Fix StackOverflowError for new dispenser interaction (#10949) PaperMC/Paper@5ae4758 Fix speed for launched trident using api (#10936) PaperMC/Paper@897ece4 Call EntityPortalEnterEvent on endgateways and make cancellable (#10892) PaperMC/Paper@1d3fc0e Bump reflection-rewriter to 0.0.2 (#10927) PaperMC/Paper@b99d071 Swap some nullable annotations (#10960) PaperMC/Paper@dd31654 bump reflection-rewriter to 0.0.3 (#10969) PaperMC/Paper@dd49fba Fix NPE when retrieving an entity with a null UUID
6587 lines
299 KiB
Diff
6587 lines
299 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/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
|
index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..a64e5997b94cc8173f0512d1e282355f14f098ec 100644
|
|
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
|
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
|
@@ -61,6 +61,12 @@ public class BlockPos extends Vec3i {
|
|
private static final int X_OFFSET = 38;
|
|
// Paper end - Optimize Bit Operations by inlining
|
|
|
|
+ // Purpur start
|
|
+ public BlockPos(net.minecraft.world.entity.Entity entity) {
|
|
+ super(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public BlockPos(int x, int y, int z) {
|
|
super(x, y, z);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index 85ed9fd1f49163a77695524a1bb338097e4c35c3..827d994be0c486e56748f7066e0f27128f4aba5d 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -1712,6 +1712,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
|
worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
|
net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
|
+ worldserver.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur
|
|
|
|
this.profiler.push(() -> {
|
|
String s = String.valueOf(worldserver);
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
index 798016774df02c3f7ebf909c9cc125f8427a39be..df01eaebfcb759eefb512b3c7eeb861e96f88688 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
@@ -229,6 +229,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
|
|
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
|
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
|
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
|
|
+ public boolean hasRidableMoveEvent = false; // Purpur
|
|
|
|
public LevelChunk getChunkIfLoaded(int x, int z) {
|
|
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index 47afcbc699a992358871fe90929f71b4d47d9601..ae41c955ec6cfe284fec5f8e79cb827ea20facc0 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -806,6 +806,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
|
|
this.trackEnteredOrExitedLavaOnVehicle();
|
|
this.updatePlayerAttributes();
|
|
this.advancements.flushDirty(this);
|
|
+
|
|
+ // Purpur start
|
|
+ if (this.level().purpurConfig.useNightVisionWhenRiding && this.getVehicle() != null && this.getVehicle().getRider() == this && this.level().getGameTime() % 100 == 0) { // 5 seconds
|
|
+ MobEffectInstance nightVision = this.getEffect(MobEffects.NIGHT_VISION);
|
|
+ if (nightVision == null || nightVision.getDuration() <= 300) { // 15 seconds
|
|
+ this.addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, 400, 0)); // 20 seconds
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
|
|
private void updatePlayerAttributes() {
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index 7796e191747be545e744564a2b0b65790f69114d..82f60de72bc0f9b01eb97dbc0e296e80579b0968 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -2717,6 +2717,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
|
|
|
ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event);
|
|
|
|
+ player.processClick(enumhand); // Purpur
|
|
+
|
|
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
|
|
if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) {
|
|
entity.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index aafae1a6711a248627abe1bad148a2404c0974e3..050b54b4b527831316964fb5b2d8b7d86932b2b9 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -383,7 +383,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
|
private final Set<String> tags;
|
|
private final double[] pistonDeltas;
|
|
private long pistonDeltasGameTime;
|
|
- private EntityDimensions dimensions;
|
|
+ protected EntityDimensions dimensions; // Purpur - private -> protected
|
|
private float eyeHeight;
|
|
public boolean isInPowderSnow;
|
|
public boolean wasInPowderSnow;
|
|
@@ -2963,6 +2963,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
|
this.passengers = ImmutableList.copyOf(list);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ if (isRidable() && this.passengers.get(0) == passenger && passenger instanceof Player player) {
|
|
+ onMount(player);
|
|
+ this.rider = player;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
this.gameEvent(GameEvent.ENTITY_MOUNT, passenger);
|
|
}
|
|
}
|
|
@@ -3002,6 +3009,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
|
return false;
|
|
}
|
|
// CraftBukkit end
|
|
+
|
|
+ // Purpur start
|
|
+ if (this.rider != null && this.passengers.get(0) == this.rider) {
|
|
+ onDismount(this.rider);
|
|
+ this.rider = null;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
if (this.passengers.size() == 1 && this.passengers.get(0) == entity) {
|
|
this.passengers = ImmutableList.of();
|
|
} else {
|
|
@@ -4834,4 +4849,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
|
return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this);
|
|
}
|
|
// Paper end - Expose entity id counter
|
|
+ // Purpur start
|
|
+ @Nullable
|
|
+ private Player rider = null;
|
|
+
|
|
+ @Nullable
|
|
+ public Player getRider() {
|
|
+ return rider;
|
|
+ }
|
|
+
|
|
+ public boolean isRidable() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public boolean isControllable() {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public void onMount(Player rider) {
|
|
+ if (this instanceof Mob) {
|
|
+ ((Mob) this).setTarget(null, null, false);
|
|
+ ((Mob) this).getNavigation().stop();
|
|
+ }
|
|
+ rider.setJumping(false); // fixes jump on mount
|
|
+ }
|
|
+
|
|
+ public void onDismount(Player player) {
|
|
+ }
|
|
+
|
|
+ public boolean onSpacebar() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public boolean onClick(InteractionHand hand) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public boolean processClick(InteractionHand hand) {
|
|
+ return false;
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/GlowSquid.java b/src/main/java/net/minecraft/world/entity/GlowSquid.java
|
|
index 09fdea983772612ef3fff6b2da3cf469a34e4ec0..aa76a24421cdb3908a3544d92eb3d1e3c2ebedc4 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/GlowSquid.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/GlowSquid.java
|
|
@@ -23,6 +23,19 @@ public class GlowSquid extends Squid {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.glowSquidRidable;
|
|
+ }
|
|
+
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.glowSquidControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected ParticleOptions getInkParticle() {
|
|
return ParticleTypes.GLOW_SQUID_INK;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
index e980c8c356b30d25e2fc5a73b91ad2c6edd4fe05..661db9eb343b32f97d6e7ccb93e56e24213b6367 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
@@ -237,9 +237,9 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
protected int deathScore;
|
|
public float lastHurt;
|
|
public boolean jumping;
|
|
- public float xxa;
|
|
- public float yya;
|
|
- public float zza;
|
|
+ public float xxa; public float getStrafeMot() { return xxa; } public void setStrafeMot(float strafe) { xxa = strafe; } // Purpur - OBFHELPER
|
|
+ public float yya; public float getVerticalMot() { return yya; } public void setVerticalMot(float vertical) { yya = vertical; } // Purpur - OBFHELPER
|
|
+ public float zza; public float getForwardMot() { return zza; } public void setForwardMot(float forward) { zza = forward; } // Purpur - OBFHELPER
|
|
protected int lerpSteps;
|
|
protected double lerpX;
|
|
protected double lerpY;
|
|
@@ -313,7 +313,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
this.lastClimbablePos = Optional.empty();
|
|
this.activeLocationDependentEnchantments = new Reference2ObjectArrayMap();
|
|
this.appliedScale = 1.0F;
|
|
- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type));
|
|
+ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur
|
|
this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit
|
|
// CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor
|
|
this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue());
|
|
@@ -363,6 +363,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
public static AttributeSupplier.Builder createLivingAttributes() {
|
|
return AttributeSupplier.builder().add(Attributes.MAX_HEALTH).add(Attributes.KNOCKBACK_RESISTANCE).add(Attributes.MOVEMENT_SPEED).add(Attributes.ARMOR).add(Attributes.ARMOR_TOUGHNESS).add(Attributes.MAX_ABSORPTION).add(Attributes.STEP_HEIGHT).add(Attributes.SCALE).add(Attributes.GRAVITY).add(Attributes.SAFE_FALL_DISTANCE).add(Attributes.FALL_DAMAGE_MULTIPLIER).add(Attributes.JUMP_STRENGTH).add(Attributes.OXYGEN_BONUS).add(Attributes.BURNING_TIME).add(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE).add(Attributes.WATER_MOVEMENT_EFFICIENCY).add(Attributes.MOVEMENT_EFFICIENCY).add(Attributes.ATTACK_KNOCKBACK);
|
|
}
|
|
+ public boolean shouldSendAttribute(Attribute attribute) { return true; } // Purpur
|
|
|
|
@Override
|
|
protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) {
|
|
@@ -3498,8 +3499,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
this.pushEntities();
|
|
this.level().getProfiler().pop();
|
|
// Paper start - Add EntityMoveEvent
|
|
- if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) {
|
|
- if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
|
|
+ // Purpur start
|
|
+ if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
|
|
+ if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) {
|
|
+ // Purpur end
|
|
Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO);
|
|
Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
|
|
io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone());
|
|
@@ -3509,6 +3512,21 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
|
this.absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch());
|
|
}
|
|
}
|
|
+ // Purpur start
|
|
+ if (getRider() != null) {
|
|
+ getRider().resetLastActionTime();
|
|
+ if (((ServerLevel) level()).hasRidableMoveEvent && this instanceof Mob) {
|
|
+ Location from = new Location(level().getWorld(), xo, yo, zo, this.yRotO, this.xRotO);
|
|
+ Location to = new Location(level().getWorld(), getX(), getY(), getZ(), this.getYRot(), this.getXRot());
|
|
+ org.purpurmc.purpur.event.entity.RidableMoveEvent event = new org.purpurmc.purpur.event.entity.RidableMoveEvent((org.bukkit.entity.Mob) getBukkitLivingEntity(), (Player) getRider().getBukkitEntity(), from, to.clone());
|
|
+ if (!event.callEvent()) {
|
|
+ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
|
|
+ } else if (!to.equals(event.getTo())) {
|
|
+ absMoveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
// Paper end - Add EntityMoveEvent
|
|
if (!this.level().isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
|
index 7b93c6a04cca2ac31d137f06ef83bb08559b10bf..091d2b1646068657120ee4244d79cbf7867a9cf7 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
|
@@ -160,8 +160,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
|
this.restrictRadius = -1.0F;
|
|
this.goalSelector = new GoalSelector(world.getProfilerSupplier());
|
|
this.targetSelector = new GoalSelector(world.getProfilerSupplier());
|
|
- this.lookControl = new LookControl(this);
|
|
- this.moveControl = new MoveControl(this);
|
|
+ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this); // Purpur
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this); // Purpur
|
|
this.jumpControl = new JumpControl(this);
|
|
this.bodyRotationControl = this.createBodyControl();
|
|
this.navigation = this.createNavigation(world);
|
|
@@ -1506,7 +1506,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
|
protected void onOffspringSpawnedFromEgg(Player player, Mob child) {}
|
|
|
|
protected InteractionResult mobInteract(Player player, InteractionHand hand) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
|
|
public boolean isWithinRestriction() {
|
|
@@ -1804,4 +1804,56 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
|
|
|
return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg);
|
|
}
|
|
+
|
|
+ // Purpur start
|
|
+ public double getMaxY() {
|
|
+ return level().getHeight();
|
|
+ }
|
|
+
|
|
+ public InteractionResult tryRide(Player player, InteractionHand hand) {
|
|
+ return tryRide(player, hand, InteractionResult.PASS);
|
|
+ }
|
|
+
|
|
+ public InteractionResult tryRide(Player player, InteractionHand hand, InteractionResult result) {
|
|
+ if (!isRidable()) {
|
|
+ return result;
|
|
+ }
|
|
+ if (hand != InteractionHand.MAIN_HAND) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ if (player.isShiftKeyDown()) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ if (!player.getItemInHand(hand).isEmpty()) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ if (!passengers.isEmpty() || player.isPassenger()) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ if (this instanceof TamableAnimal tamable) {
|
|
+ if (tamable.isTame() && !tamable.isOwnedBy(player)) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ if (!tamable.isTame() && !level().purpurConfig.untamedTamablesAreRidable) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ }
|
|
+ if (this instanceof AgeableMob ageable) {
|
|
+ if (ageable.isBaby() && !level().purpurConfig.babiesAreRidable) {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ }
|
|
+ if (!player.getBukkitEntity().hasPermission("allow.ride." + net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getKey(getType()).getPath())) {
|
|
+ player.sendMiniMessage(org.purpurmc.purpur.PurpurConfig.cannotRideMob);
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ player.setYRot(this.getYRot());
|
|
+ player.setXRot(this.getXRot());
|
|
+ if (player.startRiding(this)) {
|
|
+ return InteractionResult.SUCCESS;
|
|
+ } else {
|
|
+ return InteractionResult.PASS;
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
index 69992ebc999ea3ff9e47e4e049bcc514c01150ca..1ec4ba9799cccb6337a63d8287e269b102f59aa1 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
@@ -23,14 +23,21 @@ public class AttributeMap {
|
|
private final Set<AttributeInstance> attributesToSync = new ObjectOpenHashSet<>();
|
|
private final Set<AttributeInstance> attributesToUpdate = new ObjectOpenHashSet<>();
|
|
private final AttributeSupplier supplier;
|
|
+ private final net.minecraft.world.entity.LivingEntity entity; // Purpur
|
|
|
|
public AttributeMap(AttributeSupplier defaultAttributes) {
|
|
+ // Purpur start
|
|
+ this(defaultAttributes, null);
|
|
+ }
|
|
+ public AttributeMap(AttributeSupplier defaultAttributes, net.minecraft.world.entity.LivingEntity entity) {
|
|
+ this.entity = entity;
|
|
+ // Purpur end
|
|
this.supplier = defaultAttributes;
|
|
}
|
|
|
|
private void onAttributeModified(AttributeInstance instance) {
|
|
this.attributesToUpdate.add(instance);
|
|
- if (instance.getAttribute().value().isClientSyncable()) {
|
|
+ if (instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur
|
|
this.attributesToSync.add(instance);
|
|
}
|
|
}
|
|
@@ -44,7 +51,7 @@ public class AttributeMap {
|
|
}
|
|
|
|
public Collection<AttributeInstance> getSyncableAttributes() {
|
|
- return this.attributes.values().stream().filter(attribute -> attribute.getAttribute().value().isClientSyncable()).collect(Collectors.toList());
|
|
+ return this.attributes.values().stream().filter(attribute -> attribute.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(attribute.getAttribute().value()))).collect(Collectors.toList()); // Purpur
|
|
}
|
|
|
|
@Nullable
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
index 10a1434313b11dae8210484583c6bf3b627416f7..35af18f371b3beaf81fcdca79fefe85e0a862b50 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
@@ -129,7 +129,7 @@ public class DefaultAttributes {
|
|
.put(EntityType.OCELOT, Ocelot.createAttributes().build())
|
|
.put(EntityType.PANDA, Panda.createAttributes().build())
|
|
.put(EntityType.PARROT, Parrot.createAttributes().build())
|
|
- .put(EntityType.PHANTOM, Monster.createMonsterAttributes().build())
|
|
+ .put(EntityType.PHANTOM, net.minecraft.world.entity.monster.Phantom.createAttributes().build()) // Purpur
|
|
.put(EntityType.PIG, Pig.createAttributes().build())
|
|
.put(EntityType.PIGLIN, Piglin.createAttributes().build())
|
|
.put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build())
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
index c8fd5696de7c3623cdb4f498190a5c2708cf843e..e403d9dfeeaa3dcf53be790d761e7e922419efb0 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
@@ -29,6 +29,20 @@ public class MoveControl implements Control {
|
|
this.mob = entity;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ public void setSpeedModifier(double speed) {
|
|
+ this.speedModifier = speed;
|
|
+ }
|
|
+
|
|
+ public void setForward(float forward) {
|
|
+ this.strafeForwards = forward;
|
|
+ }
|
|
+
|
|
+ public void setStrafe(float strafe) {
|
|
+ this.strafeRight = strafe;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public boolean hasWanted() {
|
|
return this.operation == MoveControl.Operation.MOVE_TO;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java b/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java
|
|
index fbfc2f2515ad709b2c1212aef9521e795547d66b..e77bd11af62682d5eca41f6c9e1aed30eb6879ce 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java
|
|
@@ -3,7 +3,7 @@ package net.minecraft.world.entity.ai.control;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.entity.Mob;
|
|
|
|
-public class SmoothSwimmingLookControl extends LookControl {
|
|
+public class SmoothSwimmingLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
private final int maxYRotFromCenter;
|
|
private static final int HEAD_TILT_X = 10;
|
|
private static final int HEAD_TILT_Y = 20;
|
|
@@ -14,7 +14,7 @@ public class SmoothSwimmingLookControl extends LookControl {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.lookAtCooldown > 0) {
|
|
this.lookAtCooldown--;
|
|
this.getYRotD().ifPresent(yaw -> this.mob.yHeadRot = this.rotateTowards(this.mob.yHeadRot, yaw + 20.0F, this.yMaxRotSpeed));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
|
index dc27ddf5131e7398a5390a5187261d4c7fb6ccaa..c4a09778ca6bf5c15b588234bcadec3496017e3d 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
|
@@ -44,12 +44,59 @@ public class Bat extends AmbientCreature {
|
|
|
|
public Bat(EntityType<? extends Bat> type, Level world) {
|
|
super(type, world);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.075F); // Purpur
|
|
if (!world.isClientSide) {
|
|
this.setResting(true);
|
|
}
|
|
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean shouldSendAttribute(net.minecraft.world.entity.ai.attributes.Attribute attribute) { return attribute != Attributes.FLYING_SPEED.value(); } // Fixes log spam on clients
|
|
+
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.batRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.batRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.batControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.batMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ if (isResting()) {
|
|
+ setResting(false);
|
|
+ level().levelEvent(null, 1025, new BlockPos(this).above(), 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2;
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.25, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F;
|
|
@@ -99,7 +146,7 @@ public class Bat extends AmbientCreature {
|
|
protected void pushEntities() {}
|
|
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D);
|
|
+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur
|
|
}
|
|
|
|
public boolean isResting() {
|
|
@@ -132,6 +179,14 @@ public class Bat extends AmbientCreature {
|
|
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
+ // Purpur start
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
super.customServerAiStep();
|
|
BlockPos blockposition = this.blockPosition();
|
|
BlockPos blockposition1 = blockposition.above();
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java
|
|
index 3231eaa6af2ddfe4095ff2d650f580ebd4d43aea..e8cb124d232f7316cc8c35dd8bd12f79bbcda7d6 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java
|
|
@@ -87,6 +87,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(0, new PanicGoal(this, 1.25));
|
|
this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 1.6, 1.4, EntitySelector.NO_SPECTATORS::test));
|
|
this.goalSelector.addGoal(4, new AbstractFish.FishSwimGoal(this));
|
|
@@ -100,7 +101,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
@Override
|
|
public void travel(Vec3 movementInput) {
|
|
if (this.isEffectiveAi() && this.isInWater()) {
|
|
- this.moveRelative(0.01F, movementInput);
|
|
+ this.moveRelative(getRider() != null ? getSpeed() : 0.01F, movementInput); // Purpur
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
|
|
if (this.getTarget() == null) {
|
|
@@ -161,7 +162,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
protected void playStepSound(BlockPos pos, BlockState state) {
|
|
}
|
|
|
|
- static class FishMoveControl extends MoveControl {
|
|
+ static class FishMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur
|
|
private final AbstractFish fish;
|
|
|
|
FishMoveControl(AbstractFish owner) {
|
|
@@ -169,14 +170,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
this.fish = owner;
|
|
}
|
|
|
|
+ // Purpur start
|
|
@Override
|
|
- public void tick() {
|
|
+ public void purpurTick(Player rider) {
|
|
+ super.purpurTick(rider);
|
|
+ fish.setDeltaMovement(fish.getDeltaMovement().add(0.0D, 0.005D, 0.0D));
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
+ @Override
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.fish.isEyeInFluid(FluidTags.WATER)) {
|
|
this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0, 0.005, 0.0));
|
|
}
|
|
|
|
if (this.operation == MoveControl.Operation.MOVE_TO && !this.fish.getNavigation().isDone()) {
|
|
- float f = (float)(this.speedModifier * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float f = (float)(this.getSpeedModifier() * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur
|
|
this.fish.setSpeed(Mth.lerp(0.125F, this.fish.getSpeed(), f));
|
|
double d = this.wantedX - this.fish.getX();
|
|
double e = this.wantedY - this.fish.getY();
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
|
index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..f7ff98245583ab471ce1fa2f84f4684e195cdacc 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
|
|
@@ -144,6 +144,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
public Bee(EntityType<? extends Bee> type, Level world) {
|
|
super(type, world);
|
|
this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
|
|
+ final org.purpurmc.purpur.controller.FlyingMoveControllerWASD flyingController = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this, 0.25F, 1.0F, false); // Purpur
|
|
// Paper start - Fix MC-167279
|
|
class BeeFlyingMoveControl extends FlyingMoveControl {
|
|
public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) {
|
|
@@ -152,11 +153,24 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start
|
|
+ if (mob.getRider() != null && mob.isControllable()) {
|
|
+ flyingController.purpurTick(mob.getRider());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
if (this.mob.getY() <= Bee.this.level().getMinBuildHeight()) {
|
|
this.mob.setNoGravity(false);
|
|
}
|
|
super.tick();
|
|
}
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean hasWanted() {
|
|
+ return mob.getRider() != null || !mob.isControllable() || super.hasWanted();
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
this.moveControl = new BeeFlyingMoveControl(this, 20, true);
|
|
// Paper end - Fix MC-167279
|
|
@@ -168,6 +182,40 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
this.setPathfindingMalus(PathType.FENCE, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.beeRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.beeRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.beeControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.beeMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2;
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
@@ -182,6 +230,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true));
|
|
this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal());
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
|
@@ -199,6 +248,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
this.goalSelector.addGoal(7, new Bee.BeeGrowCropGoal());
|
|
this.goalSelector.addGoal(8, new Bee.BeeWanderGoal());
|
|
this.goalSelector.addGoal(9, new FloatGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new Bee.BeeHurtByOtherGoal(this)).setAlertOthers(new Class[0]));
|
|
this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
|
|
@@ -883,16 +933,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
|
}
|
|
}
|
|
|
|
- private class BeeLookControl extends LookControl {
|
|
+ private class BeeLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
|
|
BeeLookControl(final Mob entity) {
|
|
super(entity);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (!Bee.this.isAngry()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
|
index 23d4dcc82115fd1a0a77565a0472304042d5f12d..07f0ca108d515df1ff97ba79265bbf2c8bfbc8a5 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java
|
|
@@ -103,6 +103,31 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
|
this.reassessTameGoals();
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.catRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.catRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.catControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ setInSittingPose(false);
|
|
+ setLying(false);
|
|
+ setRelaxStateOne(false);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public ResourceLocation getTextureId() {
|
|
return ((CatVariant) this.getVariant().value()).texture();
|
|
}
|
|
@@ -113,6 +138,7 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
|
return itemstack.is(ItemTags.CAT_FOOD);
|
|
}, true);
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5D));
|
|
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
|
this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this));
|
|
@@ -125,6 +151,7 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
|
this.goalSelector.addGoal(10, new BreedGoal(this, 0.8D));
|
|
this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F));
|
|
this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F));
|
|
+ this.targetSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate) null));
|
|
this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
|
|
}
|
|
@@ -367,6 +394,7 @@ public class Cat extends TamableAnimal implements VariantHolder<Holder<CatVarian
|
|
|
|
@Override
|
|
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
|
+ if (getRider() != null) return InteractionResult.PASS; // Purpur
|
|
ItemStack itemstack = player.getItemInHand(hand);
|
|
Item item = itemstack.getItem();
|
|
InteractionResult enuminteractionresult;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Chicken.java b/src/main/java/net/minecraft/world/entity/animal/Chicken.java
|
|
index 8e347718f72297398b5e6d34a893264bc10efe18..2af1bab53530bcf0e06fe6ed5577880f019f6c22 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Chicken.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Chicken.java
|
|
@@ -54,9 +54,27 @@ public class Chicken extends Animal {
|
|
this.setPathfindingMalus(PathType.WATER, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.chickenRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.chickenRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.chickenControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, (itemstack) -> {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cod.java b/src/main/java/net/minecraft/world/entity/animal/Cod.java
|
|
index 824e5e4fe7619ae46061c3c978c9a044db8c84ab..e2a98b45e56a368de19bb65e304370a5998c7cb9 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Cod.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Cod.java
|
|
@@ -13,6 +13,18 @@ public class Cod extends AbstractSchoolingFish {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.codRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.codControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public ItemStack getBucketItemStack() {
|
|
return new ItemStack(Items.COD_BUCKET);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
|
index e336934f37075a827843e4b1bb2b6b660d2c60c9..8c6bda1ed0408fa1c7cc772097159410443b7fae 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java
|
|
@@ -44,9 +44,27 @@ public class Cow extends Animal {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.cowRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.cowRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.cowControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, (itemstack) -> {
|
|
@@ -94,6 +112,7 @@ public class Cow extends Animal {
|
|
|
|
@Override
|
|
public InteractionResult mobInteract(Player player, InteractionHand hand) {
|
|
+ if (getRider() != null) return InteractionResult.PASS; // Purpur
|
|
ItemStack itemstack = player.getItemInHand(hand);
|
|
|
|
if (itemstack.is(Items.BUCKET) && !this.isBaby()) {
|
|
@@ -102,7 +121,7 @@ public class Cow extends Animal {
|
|
|
|
if (event.isCancelled()) {
|
|
player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
// CraftBukkit end
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
|
|
index da45cc62985f8b67cdfeffc21cb33837db673555..df68b516576f0984d3b18972114a1af247f0a2ad 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
|
|
@@ -81,14 +81,82 @@ public class Dolphin extends WaterAnimal {
|
|
public static final Predicate<ItemEntity> ALLOWED_ITEMS = (entityitem) -> {
|
|
return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater();
|
|
};
|
|
+ private int spitCooldown; // Purpur
|
|
|
|
public Dolphin(EntityType<? extends Dolphin> type, Level world) {
|
|
super(type, world);
|
|
- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur start
|
|
+ class DolphinMoveControl extends SmoothSwimmingMoveControl {
|
|
+ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterMoveControllerWASD;
|
|
+ private final Dolphin dolphin;
|
|
+
|
|
+ public DolphinMoveControl(Dolphin dolphin, int pitchChange, int yawChange, float speedInWater, float speedInAir, boolean buoyant) {
|
|
+ super(dolphin, pitchChange, yawChange, speedInWater, speedInAir, buoyant);
|
|
+ this.dolphin = dolphin;
|
|
+ this.waterMoveControllerWASD = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(dolphin);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (dolphin.getRider() != null && dolphin.isControllable()) {
|
|
+ purpurTick(dolphin.getRider());
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void purpurTick(Player rider) {
|
|
+ if (dolphin.getAirSupply() < 150) {
|
|
+ // if drowning override player WASD controls to find air
|
|
+ super.tick();
|
|
+ } else {
|
|
+ waterMoveControllerWASD.purpurTick(rider);
|
|
+ dolphin.setDeltaMovement(dolphin.getDeltaMovement().add(0.0D, 0.005D, 0.0D));
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ this.moveControl = new DolphinMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur end
|
|
this.lookControl = new SmoothSwimmingLookControl(this, 10);
|
|
this.setCanPickUpLoot(true);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.dolphinRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.dolphinControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (spitCooldown == 0 && getRider() != null) {
|
|
+ spitCooldown = level().purpurConfig.dolphinSpitCooldown;
|
|
+
|
|
+ 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());
|
|
+
|
|
+ org.purpurmc.purpur.entity.DolphinSpit spit = new org.purpurmc.purpur.entity.DolphinSpit(level(), this);
|
|
+ spit.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), level().purpurConfig.dolphinSpitSpeed, 5.0F);
|
|
+
|
|
+ level().addFreshEntity(spit);
|
|
+ playSound(SoundEvents.DOLPHIN_ATTACK, 1.0F, 1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Nullable
|
|
@Override
|
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) {
|
|
@@ -158,6 +226,7 @@ public class Dolphin extends WaterAnimal {
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new BreathAirGoal(this));
|
|
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this));
|
|
this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D));
|
|
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10));
|
|
@@ -168,6 +237,7 @@ public class Dolphin extends WaterAnimal {
|
|
this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal());
|
|
this.goalSelector.addGoal(8, new FollowBoatGoal(this));
|
|
this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers());
|
|
}
|
|
|
|
@@ -207,7 +277,7 @@ public class Dolphin extends WaterAnimal {
|
|
|
|
@Override
|
|
protected boolean canRide(Entity entity) {
|
|
- return true;
|
|
+ return boardingCooldown <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs;
|
|
}
|
|
|
|
@Override
|
|
@@ -242,6 +312,11 @@ public class Dolphin extends WaterAnimal {
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
+ // Purpur start
|
|
+ if (spitCooldown > 0) {
|
|
+ spitCooldown--;
|
|
+ }
|
|
+ // Purpur end
|
|
if (this.isNoAi()) {
|
|
this.setAirSupply(this.getMaxAirSupply());
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
|
index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..d23566a00226d99a4309b2b8adf49e20c1c5f19d 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
|
|
@@ -145,6 +145,44 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
|
this.setCanPickUpLoot(true);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.foxRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.foxRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.foxControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getJumpPower() {
|
|
+ return getRider() != null && this.isControllable() ? 0.5F : super.getJumpPower();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ setCanPickUpLoot(false);
|
|
+ clearStates();
|
|
+ setIsPouncing(false);
|
|
+ spitOutItem(getItemBySlot(EquipmentSlot.MAINHAND));
|
|
+ setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onDismount(Player rider) {
|
|
+ super.onDismount(rider);
|
|
+ setCanPickUpLoot(true);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
@@ -164,6 +202,7 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
|
return entityliving instanceof AbstractSchoolingFish;
|
|
});
|
|
this.goalSelector.addGoal(0, new Fox.FoxFloatGoal());
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(1, new Fox.FaceplantGoal());
|
|
this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D));
|
|
@@ -190,6 +229,7 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
|
this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal());
|
|
this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F));
|
|
this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal());
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> {
|
|
return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID());
|
|
}));
|
|
@@ -769,16 +809,16 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
|
return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F));
|
|
}
|
|
|
|
- public class FoxLookControl extends LookControl {
|
|
+ public class FoxLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
|
|
public FoxLookControl() {
|
|
super(Fox.this);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (!Fox.this.isSleeping()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
|
|
}
|
|
@@ -789,16 +829,16 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
|
|
}
|
|
}
|
|
|
|
- private class FoxMoveControl extends MoveControl {
|
|
+ private class FoxMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
|
|
public FoxMoveControl() {
|
|
super(Fox.this);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (Fox.this.canMove()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
|
index 1807da10d07d1f6e4ddbc0fa1b8da34a688d67c3..1cecb12d9c9958239a71a8599fcd787d07953c76 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
|
|
@@ -62,8 +62,27 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.ironGolemRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.ironGolemRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.ironGolemControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ if (level().purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true));
|
|
this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F));
|
|
this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6D, false));
|
|
@@ -71,6 +90,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
|
this.goalSelector.addGoal(5, new OfferFlowerGoal(this));
|
|
this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0]));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
|
|
@@ -273,13 +293,13 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
|
ItemStack itemstack = player.getItemInHand(hand);
|
|
|
|
if (!itemstack.is(Items.IRON_INGOT)) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
} else {
|
|
float f = this.getHealth();
|
|
|
|
this.heal(25.0F);
|
|
if (this.getHealth() == f) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // 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/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
|
index 0c21959f57ae88fcd0a4d6dc911c1ce347c96528..11944ee34fc7e3e5551b9e18a563164f96898a54 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
|
|
@@ -64,6 +64,23 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.mooshroomRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.mooshroomRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.mooshroomControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public float getWalkTargetValue(BlockPos pos, LevelReader world) {
|
|
return world.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : world.getPathfindingCostFromLightLevels(pos);
|
|
@@ -128,7 +145,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
|
org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
|
if (event != null) {
|
|
if (event.isCancelled()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
|
}
|
|
@@ -150,7 +167,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
|
|
Optional<SuspiciousStewEffects> optional = this.getEffectsFromItemStack(itemstack);
|
|
|
|
if (optional.isEmpty()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
|
|
itemstack.consume(1, player);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
|
index 97f4cc522706ec5914672aa4fdfbc35edc94aeb6..0083119b44ef10e8ebc4414828f0d5fd6f68a830 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
|
|
@@ -66,6 +66,23 @@ public class Ocelot extends Animal {
|
|
this.reassessTrustingGoals();
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.ocelotRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.ocelotRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.ocelotControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public boolean isTrusting() {
|
|
return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING);
|
|
}
|
|
@@ -99,12 +116,14 @@ public class Ocelot extends Animal {
|
|
return itemstack.is(ItemTags.OCELOT_FOOD);
|
|
}, true);
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(3, this.temptGoal);
|
|
this.goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3F));
|
|
this.goalSelector.addGoal(8, new OcelotAttackGoal(this));
|
|
this.goalSelector.addGoal(9, new BreedGoal(this, 0.8D));
|
|
this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F));
|
|
this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Chicken.class, false));
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR));
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
|
index e108f876d3f129c6287f13d68427aed2a6f0c5b1..fff8abfe14be823867aa9bd145146763cfe83148 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
|
|
@@ -121,6 +121,32 @@ public class Panda extends Animal {
|
|
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.pandaRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.pandaRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.pandaControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ setForwardMot(0.0F);
|
|
+ sit(false);
|
|
+ eat(false);
|
|
+ setOnBack(false);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean canTakeItem(ItemStack stack) {
|
|
EquipmentSlot enumitemslot = this.getEquipmentSlotForItem(stack);
|
|
@@ -282,6 +308,7 @@ public class Panda extends Animal {
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D));
|
|
this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2000000476837158D, true));
|
|
@@ -299,6 +326,7 @@ public class Panda extends Animal {
|
|
this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this));
|
|
this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25D));
|
|
this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0D));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new Panda.PandaHurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0]));
|
|
}
|
|
|
|
@@ -660,7 +688,7 @@ public class Panda extends Animal {
|
|
ItemStack itemstack = player.getItemInHand(hand);
|
|
|
|
if (this.isScared()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
} else if (this.isOnBack()) {
|
|
this.setOnBack(false);
|
|
return InteractionResult.sidedSuccess(this.level().isClientSide);
|
|
@@ -678,7 +706,7 @@ public class Panda extends Animal {
|
|
this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
|
|
} else {
|
|
if (this.level().isClientSide || this.isSitting() || this.isInWater()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
|
|
this.tryToSit();
|
|
@@ -697,7 +725,7 @@ public class Panda extends Animal {
|
|
|
|
return InteractionResult.SUCCESS;
|
|
} else {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
}
|
|
|
|
@@ -742,7 +770,7 @@ public class Panda extends Animal {
|
|
return this.isBaby() ? Panda.BABY_DIMENSIONS : super.getDefaultDimensions(pose);
|
|
}
|
|
|
|
- private static class PandaMoveControl extends MoveControl {
|
|
+ private static class PandaMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
|
|
private final Panda panda;
|
|
|
|
@@ -752,9 +780,9 @@ public class Panda extends Animal {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.panda.canPerformAction()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
|
|
index 97931bfd360725945ab9606ff698b518ae101076..eecf37d4dba41cb96d0893c905567130e00b66e9 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java
|
|
@@ -124,12 +124,68 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder<Parrot
|
|
|
|
public Parrot(EntityType<? extends Parrot> type, Level world) {
|
|
super(type, world);
|
|
- this.moveControl = new FlyingMoveControl(this, 10, false);
|
|
+ // Purpur start
|
|
+ final org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD flyingController = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F);
|
|
+ class ParrotMoveControl extends FlyingMoveControl {
|
|
+ public ParrotMoveControl(Mob entity, int maxPitchChange, boolean noGravity) {
|
|
+ super(entity, maxPitchChange, noGravity);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (mob.getRider() != null && mob.isControllable()) {
|
|
+ flyingController.purpurTick(mob.getRider());
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasWanted() {
|
|
+ return mob.getRider() != null && mob.isControllable() ? getForwardMot() != 0 || getStrafeMot() != 0 : super.hasWanted();
|
|
+ }
|
|
+ }
|
|
+ this.moveControl = new ParrotMoveControl(this, 10, false);
|
|
+ // Purpur end
|
|
this.setPathfindingMalus(PathType.DANGER_FIRE, -1.0F);
|
|
this.setPathfindingMalus(PathType.DAMAGE_FIRE, -1.0F);
|
|
this.setPathfindingMalus(PathType.COCOA, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.parrotRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.parrotRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.parrotControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.parrotMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 2;
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.25, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Nullable
|
|
@Override
|
|
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) {
|
|
@@ -148,8 +204,10 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder<Parrot
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
- this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25D));
|
|
+ //this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25D)); // Purpur - move down
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.25D)); // Purpur
|
|
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
|
this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.java
|
|
index 03d29d5114237f5700c188510a12f26507844c3d..a6550df2eb2ccf0f5cb2cee49b996a2457c4c142 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java
|
|
@@ -64,9 +64,27 @@ public class Pig extends Animal implements ItemSteerable, Saddleable {
|
|
this.steering = new ItemBasedSteering(this.entityData, Pig.DATA_BOOST_TIME, Pig.DATA_SADDLE_ID);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.pigRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.pigRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.pigControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D));
|
|
this.goalSelector.addGoal(3, new BreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(4, new TemptGoal(this, 1.2D, (itemstack) -> {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java
|
|
index b69a2144769e598f0d70b0d5dfeb8af01ad740ca..5aeeb7b57a37ea49a28b2e244fb99a78320ed006 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java
|
|
@@ -59,11 +59,40 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
private int remainingPersistentAngerTime;
|
|
@Nullable
|
|
private UUID persistentAngerTarget;
|
|
+ private int standTimer = 0; // Purpur
|
|
|
|
public PolarBear(EntityType<? extends PolarBear> type, Level world) {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.polarBearRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.polarBearRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.polarBearControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (!isStanding()) {
|
|
+ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0) {
|
|
+ setStanding(true);
|
|
+ playSound(SoundEvents.POLAR_BEAR_WARNING, 1.0F, 1.0F);
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Nullable
|
|
@Override
|
|
public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) {
|
|
@@ -79,6 +108,7 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal());
|
|
this.goalSelector
|
|
.addGoal(1, new PanicGoal(this, 2.0, polarBear -> polarBear.isBaby() ? DamageTypeTags.PANIC_CAUSES : DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
|
@@ -86,6 +116,7 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
|
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new PolarBear.PolarBearHurtByTargetGoal());
|
|
this.targetSelector.addGoal(2, new PolarBear.PolarBearAttackPlayersGoal());
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
|
|
@@ -202,6 +233,12 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
if (!this.level().isClientSide) {
|
|
this.updatePersistentAnger((ServerLevel)this.level(), true);
|
|
}
|
|
+
|
|
+ // Purpur start
|
|
+ if (isStanding() && --standTimer <= 0) {
|
|
+ setStanding(false);
|
|
+ }
|
|
+ // Purpur end
|
|
}
|
|
|
|
@Override
|
|
@@ -221,6 +258,7 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
|
|
public void setStanding(boolean warning) {
|
|
this.entityData.set(DATA_STANDING_ID, warning);
|
|
+ standTimer = warning ? 20 : -1; // Purpur
|
|
}
|
|
|
|
public float getStandingAnimationScale(float tickDelta) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java
|
|
index 3f0fad476fe573c3ba946a9436d1b3f7c5260ee2..d75016647c513841358d08e5931821ecf8c21c2a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java
|
|
@@ -51,6 +51,18 @@ public class Pufferfish extends AbstractFish {
|
|
this.refreshDimensions();
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.pufferfishRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.pufferfishControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
|
index 0109c8ed8bf6a053674456fa4473934e028ca418..ee13da112fb4f9b4f8543cd72485d39d2450b9e5 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java
|
|
@@ -89,6 +89,7 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
private boolean wasOnGround;
|
|
private int jumpDelayTicks;
|
|
public int moreCarrotTicks;
|
|
+ private boolean actualJump; // Purpur
|
|
|
|
public Rabbit(EntityType<? extends Rabbit> type, Level world) {
|
|
super(type, world);
|
|
@@ -96,9 +97,55 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
this.moveControl = new Rabbit.RabbitMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.rabbitRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.rabbitRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.rabbitControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (onGround) {
|
|
+ actualJump = true;
|
|
+ jumpFromGround();
|
|
+ actualJump = false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ private void handleJumping() {
|
|
+ if (onGround) {
|
|
+ RabbitJumpControl jumpController = (RabbitJumpControl) jumpControl;
|
|
+ if (!wasOnGround) {
|
|
+ setJumping(false);
|
|
+ jumpController.setCanJump(false);
|
|
+ }
|
|
+ if (!jumpController.wantJump()) {
|
|
+ if (moveControl.hasWanted()) {
|
|
+ startJumping();
|
|
+ }
|
|
+ } else if (!jumpController.canJump()) {
|
|
+ jumpController.setCanJump(true);
|
|
+ }
|
|
+ }
|
|
+ wasOnGround = onGround;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 0.8D));
|
|
@@ -115,6 +162,14 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
|
|
@Override
|
|
protected float getJumpPower() {
|
|
+ // Purpur start
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ if (getForwardMot() < 0) {
|
|
+ setSpeed(getForwardMot() * 2F);
|
|
+ }
|
|
+ return actualJump ? 0.5F : 0.3F;
|
|
+ }
|
|
+ // Purpur end
|
|
float f = 0.3F;
|
|
|
|
if (this.horizontalCollision || this.moveControl.hasWanted() && this.moveControl.getWantedY() > this.getY() + 0.5D) {
|
|
@@ -189,6 +244,13 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
|
|
@Override
|
|
public void customServerAiStep() {
|
|
+ // Purpur start
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ handleJumping();
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
if (this.jumpDelayTicks > 0) {
|
|
--this.jumpDelayTicks;
|
|
}
|
|
@@ -470,7 +532,7 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
}
|
|
}
|
|
|
|
- private static class RabbitMoveControl extends MoveControl {
|
|
+ private static class RabbitMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
|
|
private final Rabbit rabbit;
|
|
private double nextJumpSpeed;
|
|
@@ -481,14 +543,14 @@ public class Rabbit extends Animal implements VariantHolder<Rabbit.Variant> {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.rabbit.onGround() && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl) this.rabbit.jumpControl).wantJump()) {
|
|
this.rabbit.setSpeedModifier(0.0D);
|
|
} else if (this.hasWanted()) {
|
|
this.rabbit.setSpeedModifier(this.nextJumpSpeed);
|
|
}
|
|
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Salmon.java b/src/main/java/net/minecraft/world/entity/animal/Salmon.java
|
|
index 0af79daa357f53a8871e293b57e16c099e5d3f64..87c442fb198cad8671ad1419e589a5a67c4fdca8 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Salmon.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Salmon.java
|
|
@@ -13,6 +13,18 @@ public class Salmon extends AbstractSchoolingFish {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.salmonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.salmonControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public int getMaxSchoolSize() {
|
|
return 5;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
|
index 38ac2759894660be1ee7ba59b0bd1270158e9232..c70c78d7aa046995e77eadf348d434bd131c2380 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
|
|
@@ -115,10 +115,28 @@ public class Sheep extends Animal implements Shearable {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.sheepRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.sheepRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.sheepControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.eatBlockGoal = new EatBlockGoal(this);
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.1D, (itemstack) -> {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
|
index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..d51b486afb83bf3e12046ed5e61e73eec5bd7c7c 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
|
|
@@ -52,12 +52,31 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.snowGolemRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.snowGolemRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.snowGolemControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F));
|
|
this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F));
|
|
this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
|
this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> {
|
|
return entityliving instanceof Enemy;
|
|
}));
|
|
@@ -105,6 +124,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
|
return;
|
|
}
|
|
|
|
+ if (getRider() != null && this.isControllable() && !level().purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden
|
|
BlockState iblockdata = Blocks.SNOW.defaultBlockState();
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
@@ -151,7 +171,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
|
org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
|
|
if (event != null) {
|
|
if (event.isCancelled()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
|
}
|
|
@@ -165,7 +185,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
|
|
|
|
return InteractionResult.sidedSuccess(this.level().isClientSide);
|
|
} else {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur
|
|
}
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
|
index 42f4e544fe7fbc342f15eacb5e38d40849e3c419..8afab50de942ec4999f5ef849a28da92c54ab8dd 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
|
@@ -45,9 +45,32 @@ public class Squid extends WaterAnimal {
|
|
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.squidRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.squidControllable;
|
|
+ }
|
|
+
|
|
+ protected 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 registerGoals() {
|
|
this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Squid.SquidFleeGoal());
|
|
}
|
|
|
|
@@ -289,6 +312,37 @@ public class Squid extends WaterAnimal {
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start
|
|
+ net.minecraft.world.entity.player.Player rider = squid.getRider();
|
|
+ if (rider != null && squid.isControllable()) {
|
|
+ if (rider.jumping) {
|
|
+ squid.onSpacebar();
|
|
+ }
|
|
+ float forward = rider.getForwardMot();
|
|
+ float strafe = rider.getStrafeMot();
|
|
+ float speed = (float) squid.getAttributeValue(Attributes.MOVEMENT_SPEED) * 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.squid.getNoActionTime();
|
|
if (i > 100) {
|
|
this.squid.setMovementVector(0.0F, 0.0F, 0.0F);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java
|
|
index 3d03ffe2e12eca82dfa2f414471d12bb362d4552..18dcb67d246b63637d8c948b6c3f48c58d71c339 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java
|
|
@@ -67,6 +67,18 @@ public class TropicalFish extends AbstractSchoolingFish implements VariantHolder
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.tropicalFishRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.tropicalFishControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static String getPredefinedName(int variant) {
|
|
return "entity.minecraft.tropical_fish.predefined." + variant;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
|
index 4bfa947531c4a67989e18032754dabf4c69e989c..960eaebcb12d32bc51026c48e4b5e09effb66dda 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
|
@@ -87,6 +87,23 @@ public class Turtle extends Animal {
|
|
this.moveControl = new Turtle.TurtleMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.turtleRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.turtleRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.turtleControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public void setHomePos(BlockPos pos) {
|
|
this.entityData.set(Turtle.HOME_POS, pos);
|
|
}
|
|
@@ -189,6 +206,7 @@ public class Turtle extends Animal {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D));
|
|
this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D));
|
|
@@ -342,13 +360,15 @@ public class Turtle extends Animal {
|
|
return this.isBaby() ? Turtle.BABY_DIMENSIONS : super.getDefaultDimensions(pose);
|
|
}
|
|
|
|
- private static class TurtleMoveControl extends MoveControl {
|
|
+ private static class TurtleMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
|
|
private final Turtle turtle;
|
|
+ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur
|
|
|
|
TurtleMoveControl(Turtle turtle) {
|
|
super(turtle);
|
|
this.turtle = turtle;
|
|
+ waterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(turtle, 0.25D); // Purpur
|
|
}
|
|
|
|
private void updateSpeed() {
|
|
@@ -368,7 +388,7 @@ public class Turtle extends Animal {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
this.updateSpeed();
|
|
if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) {
|
|
double d0 = this.wantedX - this.turtle.getX();
|
|
@@ -384,7 +404,7 @@ public class Turtle extends Animal {
|
|
|
|
this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F));
|
|
this.turtle.yBodyRot = this.turtle.getYRot();
|
|
- float f1 = (float) (this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float f1 = (float) (this.getSpeedModifier() * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
|
|
this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1));
|
|
this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, (double) this.turtle.getSpeed() * d1 * 0.1D, 0.0D));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
|
|
index c382a8f95f612db881b9cdbd07316d1ca1cd9c4b..1ae38914582cfb17da882304c8bcba84a7793f79 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
|
|
@@ -126,9 +126,32 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder<Hol
|
|
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.wolfRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.wolfRidableInWater;
|
|
+ }
|
|
+
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ setInSittingPose(false);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.wolfControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5D, DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
|
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
|
this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5D, 1.5D));
|
|
@@ -140,6 +163,7 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder<Hol
|
|
this.goalSelector.addGoal(9, new BegGoal(this, 8.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(10, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
|
|
this.targetSelector.addGoal(3, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
|
index 69986f75d3cf729204cca0c7e5428536af31f695..49dccfc0010b5727250f7e27591502408c903739 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
|
|
@@ -102,10 +102,23 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
|
private float spinningAnimationTicks;
|
|
private float spinningAnimationTicks0;
|
|
public boolean forceDancing = false; // CraftBukkit
|
|
+ private org.purpurmc.purpur.controller.FlyingMoveControllerWASD purpurController; // Purpur
|
|
|
|
public Allay(EntityType<? extends Allay> type, Level world) {
|
|
super(type, world);
|
|
- this.moveControl = new FlyingMoveControl(this, 20, true);
|
|
+ // Purpur start
|
|
+ this.purpurController = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this, 0.1F, 0.5F);
|
|
+ this.moveControl = new FlyingMoveControl(this, 20, true) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (mob.getRider() != null && mob.isControllable()) {
|
|
+ purpurController.purpurTick(mob.getRider());
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
this.setCanPickUpLoot(this.canPickUpLoot());
|
|
this.vibrationUser = new Allay.VibrationUser();
|
|
this.vibrationData = new VibrationSystem.Data();
|
|
@@ -119,6 +132,28 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
|
}
|
|
// CraftBukkit end
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.allayRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.allayRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.allayControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected Brain.Provider<Allay> brainProvider() {
|
|
return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES);
|
|
@@ -220,6 +255,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("allayBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel) this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.level().getProfiler().push("allayActivityUpdate");
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
index 792d9039ac0561464c666977ff8308e4c629e5eb..6af72246e7f9bb845a497ef0f3394e634996fd40 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
@@ -78,6 +78,23 @@ public class Armadillo extends Animal {
|
|
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 12.0D).add(Attributes.MOVEMENT_SPEED, 0.14D);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.armadilloRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.armadilloRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.armadilloControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
index 01a0731e92d39c8718538244e34a271fb8717fc2..384fb16dac5eede49d89ad9fdcddcec442f0e7ca 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
@@ -97,6 +97,23 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder<Axolo
|
|
this.lookControl = new Axolotl.AxolotlLookControl(this, 20);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.axolotlRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.axolotlControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public Map<String, Vector3f> getModelRotationValues() {
|
|
return this.modelRotationValues;
|
|
@@ -272,6 +289,7 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder<Axolo
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("axolotlBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel) this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.level().getProfiler().push("axolotlActivityUpdate");
|
|
@@ -497,14 +515,22 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder<Axolo
|
|
private static class AxolotlMoveControl extends SmoothSwimmingMoveControl {
|
|
|
|
private final Axolotl axolotl;
|
|
+ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur
|
|
|
|
public AxolotlMoveControl(Axolotl axolotl) {
|
|
super(axolotl, 85, 10, 0.1F, 0.5F, false);
|
|
this.axolotl = axolotl;
|
|
+ waterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(axolotl, 0.5D); // Purpur
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start
|
|
+ if (axolotl.getRider() != null && axolotl.isControllable()) {
|
|
+ waterController.purpurTick(axolotl.getRider());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
if (!this.axolotl.isPlayingDead()) {
|
|
super.tick();
|
|
}
|
|
@@ -519,9 +545,9 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder<Axolo
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (!Axolotl.this.isPlayingDead()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
|
index 147974651d37e81d81ca97bfa31c9df9867492be..32c10771db71c1cd190769614edd1c24762d32c6 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
|
|
@@ -84,6 +84,13 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl
|
|
navigation.setCanWalkOverFences(true);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.camelRidableInWater;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public void addAdditionalSaveData(CompoundTag nbt) {
|
|
super.addAdditionalSaveData(nbt);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
|
index 816977990639ec0559b652fc9666afd5046f0a5d..b6a4b4e66ca67e4dcb4b14a13ab6586a94e1b020 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
|
|
@@ -103,6 +103,8 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
|
public final AnimationState croakAnimationState = new AnimationState();
|
|
public final AnimationState tongueAnimationState = new AnimationState();
|
|
public final AnimationState swimIdleAnimationState = new AnimationState();
|
|
+ private org.purpurmc.purpur.controller.MoveControllerWASD purpurLandController; // Purpur
|
|
+ private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurWaterController; // Purpur
|
|
|
|
public Frog(EntityType<? extends Animal> type, Level world) {
|
|
super(type, world);
|
|
@@ -110,7 +112,55 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
|
this.setPathfindingMalus(PathType.WATER, 4.0F);
|
|
this.setPathfindingMalus(PathType.TRAPDOOR, -1.0F);
|
|
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur start
|
|
+ this.purpurLandController = new org.purpurmc.purpur.controller.MoveControllerWASD(this, 0.2F);
|
|
+ this.purpurWaterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(this, 0.5F);
|
|
+ this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ net.minecraft.world.entity.player.Player rider = mob.getRider();
|
|
+ if (rider != null && mob.isControllable()) {
|
|
+ if (mob.isInWater()) {
|
|
+ purpurWaterController.purpurTick(rider);
|
|
+ mob.setDeltaMovement(mob.getDeltaMovement().add(0.0D, -0.005D, 0.0D));
|
|
+ } else {
|
|
+ purpurLandController.purpurTick(rider);
|
|
+ }
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
+ }
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.frogRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.frogRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.frogControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getJumpPower() {
|
|
+ return (getRider() != null && isControllable()) ? level().purpurConfig.frogRidableJumpHeight * this.getBlockJumpFactor() : super.getJumpPower();
|
|
}
|
|
+ // Purpur end
|
|
|
|
@Override
|
|
protected Brain.Provider<Frog> brainProvider() {
|
|
@@ -184,6 +234,7 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("frogBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel)this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.level().getProfiler().push("frogActivityUpdate");
|
|
@@ -371,7 +422,7 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
|
return world.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos);
|
|
}
|
|
|
|
- class FrogLookControl extends LookControl {
|
|
+ class FrogLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
FrogLookControl(final Mob entity) {
|
|
super(entity);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
index 43046f4a0cff620834ac4647efdcde227185b2ff..057096c5252e86d828a69080bdc70538e516ce99 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
@@ -51,13 +51,50 @@ public class Tadpole extends AbstractFish {
|
|
protected static final ImmutableList<SensorType<? extends Sensor<? super Tadpole>>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS);
|
|
protected static final ImmutableList<MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.NEAREST_VISIBLE_ADULT, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.BREED_TARGET, MemoryModuleType.IS_PANICKING);
|
|
public boolean ageLocked; // Paper
|
|
+ private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurController; // Purpur
|
|
|
|
public Tadpole(EntityType<? extends AbstractFish> type, Level world) {
|
|
super(type, world);
|
|
- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur start
|
|
+ this.purpurController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(this, 0.5F);
|
|
+ this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ Player rider = mob.getRider();
|
|
+ if (rider != null && mob.isControllable()) {
|
|
+ purpurController.purpurTick(rider);
|
|
+ mob.setDeltaMovement(mob.getDeltaMovement().add(0.0D, 0.002D, 0.0D));
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
this.lookControl = new SmoothSwimmingLookControl(this, 10);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.tadpoleRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.tadpoleRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.tadpoleControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected PathNavigation createNavigation(Level world) {
|
|
return new WaterBoundPathNavigation(this, world);
|
|
@@ -86,6 +123,7 @@ public class Tadpole extends AbstractFish {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("tadpoleBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel) this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.level().getProfiler().push("tadpoleActivityUpdate");
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
|
index 376bcbc189008464f4d518c1e07643431ba96306..691f5020df77b01523d1e292be40552089e2f538 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
|
|
@@ -91,6 +91,23 @@ public class Goat extends Animal {
|
|
return InstrumentItem.create(Items.GOAT_HORN, (Holder) holderset.getRandomElement(randomsource).get());
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.goatRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.goatRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.goatControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected Brain.Provider<Goat> brainProvider() {
|
|
return Brain.provider(Goat.MEMORY_TYPES, Goat.SENSOR_TYPES);
|
|
@@ -193,6 +210,7 @@ public class Goat extends Animal {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("goatBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel) this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.level().getProfiler().push("goatActivityUpdate");
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
index 1f5ed236fb7c0c1b0181675747d25d233f534284..28b5bda64b5f7a5b1ac8551bb05bf3f6fa522364 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
@@ -219,11 +219,21 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
|
|
|
protected AbstractHorse(EntityType<? extends AbstractHorse> type, Level world) {
|
|
super(type, world);
|
|
+ this.moveControl = new net.minecraft.world.entity.ai.control.MoveControl(this); // Purpur - use vanilla controller
|
|
+ this.lookControl = new net.minecraft.world.entity.ai.control.LookControl(this); // Purpur - use vanilla controller
|
|
this.createInventory();
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return false; // vanilla handles
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D));
|
|
this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D, AbstractHorse.class));
|
|
@@ -234,6 +244,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
|
if (this.canPerformRearing()) {
|
|
this.goalSelector.addGoal(9, new RandomStandGoal(this));
|
|
}
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur
|
|
|
|
this.addBehaviourGoals();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java
|
|
index ff02169ba14f5264cea8beaf1779e2890c5d74b8..1febe8e173886d501e40331c12261701bd36b0f6 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java
|
|
@@ -15,6 +15,13 @@ public class Donkey extends AbstractChestedHorse {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.donkeyRidableInWater;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected SoundEvent getAmbientSound() {
|
|
return SoundEvents.DONKEY_AMBIENT;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java
|
|
index b1188d05700cafc3a6956171bacde4962d6659be..91bee4729074fdabadd40641050e49ef0d0c760e 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java
|
|
@@ -45,6 +45,13 @@ public class Horse extends AbstractHorse implements VariantHolder<Variant> {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.horseRidableInWater;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void randomizeAttributes(RandomSource random) {
|
|
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)generateMaxHealth(random::nextInt));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
|
index cf6a3a63b6f2b96943c0f399e8c82d293fee31ba..b339f61e15f29666ca7ff2d820bc22723738f422 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
|
|
@@ -79,7 +79,51 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
|
|
public Llama(EntityType<? extends Llama> type, Level world) {
|
|
super(type, world);
|
|
this.maxDomestication = 30; // Paper - Missing entity API; configure max temper instead of a hardcoded value
|
|
+ // Purpur start
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (entity.getRider() != null && entity.isControllable() && isSaddled()) {
|
|
+ purpurTick(entity.getRider());
|
|
+ } else {
|
|
+ vanillaTick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (entity.getRider() != null && entity.isControllable() && isSaddled()) {
|
|
+ purpurTick(entity.getRider());
|
|
+ } else {
|
|
+ vanillaTick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
+ }
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.llamaRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.llamaRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.llamaControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isSaddled() {
|
|
+ return super.isSaddled() || (isTamed() && getSwag() != null);
|
|
}
|
|
+ // Purpur end
|
|
|
|
public boolean isTraderLlama() {
|
|
return false;
|
|
@@ -121,6 +165,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.LlamaHasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D));
|
|
this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.0999999046325684D));
|
|
this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25D, 40, 20.0F));
|
|
@@ -133,6 +178,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
|
|
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7D));
|
|
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
|
this.goalSelector.addGoal(9, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.LlamaHasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new Llama.LlamaHurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new Llama.LlamaAttackWolfGoal(this));
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java
|
|
index 2802a8144c823b270a0cdab445af4523c1432ceb..1d18c983efad3ea309e7bc2a7c75d60d46ab80a7 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Mule.java
|
|
@@ -14,6 +14,13 @@ public class Mule extends AbstractChestedHorse {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.muleRidableInWater;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected SoundEvent getAmbientSound() {
|
|
return SoundEvents.MULE_AMBIENT;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
|
index c12086c50bb9b5923c179108e92674b2b26d27f2..b3ce3c484c2e447e2d9fa52e1ccc30b2e4883923 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonHorse.java
|
|
@@ -42,6 +42,13 @@ public class SkeletonHorse extends AbstractHorse {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isTamed() {
|
|
+ return super.isTamed() || this.level().purpurConfig.skeletonHorseRidable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D);
|
|
}
|
|
@@ -59,7 +66,9 @@ public class SkeletonHorse extends AbstractHorse {
|
|
}
|
|
|
|
@Override
|
|
- protected void addBehaviourGoals() {}
|
|
+ protected void addBehaviourGoals() {
|
|
+ if (level().purpurConfig.skeletonHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this));
|
|
+ }
|
|
|
|
@Override
|
|
protected SoundEvent getAmbientSound() {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
|
index bbfc94237bbd546361cc4a7bde773c810e8c5d49..2abc4a5a9043d7c8643b27b7ba874d42bbdc04b7 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java
|
|
@@ -30,6 +30,28 @@ public class TraderLlama extends Llama {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.traderLlamaRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.traderLlamaRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.traderLlamaControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isSaddled() {
|
|
+ return super.isSaddled() || isTamed();
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean isTraderLlama() {
|
|
return true;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
|
index 9127b5667704d05add534a5c05a91fb38c5b6749..2cf47ea1cedc1cecfeb4d2bcebc0810a19f64022 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/ZombieHorse.java
|
|
@@ -33,6 +33,18 @@ public class ZombieHorse extends AbstractHorse {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.zombieHorseRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isTamed() {
|
|
+ return super.isTamed() || this.level().purpurConfig.zombieHorseRidable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
|
|
}
|
|
@@ -78,6 +90,7 @@ public class ZombieHorse extends AbstractHorse {
|
|
|
|
@Override
|
|
protected void addBehaviourGoals() {
|
|
+ if (level().purpurConfig.zombieHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
|
index fadd341ff398886a4da102eefa1beb95a63bbd6d..b96a041041509dbb52f325eb52f53b458ba3cc64 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
|
@@ -94,6 +94,23 @@ public class Sniffer extends Animal {
|
|
this.setPathfindingMalus(PathType.DAMAGE_CAUTIOUS, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.snifferRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.snifferRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.snifferControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java
|
|
index ca4486844a3125626e949d26fa03c325ef33343f..677ef269bb1206254d000cdbe621bfd926bddd4f 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/boss/EnderDragonPart.java
|
|
@@ -26,6 +26,13 @@ public class EnderDragonPart extends Entity {
|
|
this.name = name;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) {
|
|
+ return parentMob.isAlive() ? parentMob.tryRide(player, hand) : net.minecraft.world.InteractionResult.PASS;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
index 4d2fbade3a01ca26ff107f1323ae23db6dad8ef8..bc2bcae9e18f76c2db1a75b4db9bd9874b9f79cf 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
@@ -107,6 +107,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
@Nullable
|
|
private BlockPos podium;
|
|
// Paper end - Allow changing the EnderDragon podium
|
|
+ private boolean hadRider; // Purpur
|
|
|
|
public EnderDragon(EntityType<? extends EnderDragon> entitytypes, Level world) {
|
|
super(EntityType.ENDER_DRAGON, world);
|
|
@@ -129,6 +130,37 @@ public class EnderDragon extends Mob implements Enemy {
|
|
this.noCulling = true;
|
|
this.phaseManager = new EnderDragonPhaseManager(this);
|
|
this.explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit
|
|
+
|
|
+ // Purpur start
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this) {
|
|
+ @Override
|
|
+ public void vanillaTick() {
|
|
+ // dragon doesn't use the controller. do nothing
|
|
+ }
|
|
+ };
|
|
+ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) {
|
|
+ @Override
|
|
+ public void vanillaTick() {
|
|
+ // dragon doesn't use the controller. do nothing
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void purpurTick(Player rider) {
|
|
+ setYawPitch(rider.getYRot() - 180F, rider.xRotO * 0.5F);
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
+ }
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.enderDragonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.enderDragonRidableInWater;
|
|
}
|
|
|
|
public void setDragonFight(EndDragonFight fight) {
|
|
@@ -143,6 +175,17 @@ public class EnderDragon extends Mob implements Enemy {
|
|
return this.fightOrigin;
|
|
}
|
|
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.enderDragonControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.enderDragonMaxY;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D);
|
|
}
|
|
@@ -204,6 +247,37 @@ public class EnderDragon extends Mob implements Enemy {
|
|
|
|
@Override
|
|
public void aiStep() {
|
|
+ // Purpur start
|
|
+ boolean hasRider = getRider() != null && this.isControllable();
|
|
+ if (hasRider) {
|
|
+ if (!hadRider) {
|
|
+ hadRider = true;
|
|
+ noPhysics = false;
|
|
+ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(4.0F, 2.0F);
|
|
+ }
|
|
+
|
|
+ // dragon doesn't use controllers, so must tick manually
|
|
+ moveControl.tick();
|
|
+ lookControl.tick();
|
|
+
|
|
+ moveRelative((float) getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.1F, new Vec3(-getStrafeMot(), getVerticalMot(), -getForwardMot()));
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot);
|
|
+ move(MoverType.PLAYER, mot);
|
|
+
|
|
+ mot = mot.multiply(0.9F, 0.9F, 0.9F);
|
|
+ setDeltaMovement(mot);
|
|
+
|
|
+ // control wing flap speed on client
|
|
+ phaseManager.setPhase(mot.x() * mot.x() + mot.z() * mot.z() < 0.005F ? EnderDragonPhase.HOVERING : EnderDragonPhase.HOLDING_PATTERN);
|
|
+ } else if (hadRider) {
|
|
+ hadRider = false;
|
|
+ noPhysics = true;
|
|
+ this.dimensions = net.minecraft.world.entity.EntityDimensions.scalable(16.0F, 8.0F);
|
|
+ phaseManager.setPhase(EnderDragonPhase.HOLDING_PATTERN); // HoldingPattern
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
this.processFlappingMovement();
|
|
if (this.level().isClientSide) {
|
|
this.setHealth(this.getHealth());
|
|
@@ -230,6 +304,8 @@ public class EnderDragon extends Mob implements Enemy {
|
|
float f;
|
|
|
|
if (this.isDeadOrDying()) {
|
|
+ if (hasRider) ejectPassengers(); // Purpur
|
|
+
|
|
float f1 = (this.random.nextFloat() - 0.5F) * 8.0F;
|
|
|
|
f = (this.random.nextFloat() - 0.5F) * 4.0F;
|
|
@@ -242,9 +318,9 @@ public class EnderDragon extends Mob implements Enemy {
|
|
|
|
f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F);
|
|
f *= (float) Math.pow(2.0D, vec3d.y);
|
|
- if (this.phaseManager.getCurrentPhase().isSitting()) {
|
|
+ if (!hasRider && this.phaseManager.getCurrentPhase().isSitting()) { // Purpur
|
|
this.flapTime += 0.1F;
|
|
- } else if (this.inWall) {
|
|
+ } else if (!hasRider && this.inWall) { // Purpur
|
|
this.flapTime += f * 0.5F;
|
|
} else {
|
|
this.flapTime += f;
|
|
@@ -278,7 +354,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
}
|
|
|
|
this.phaseManager.getCurrentPhase().doClientTick();
|
|
- } else {
|
|
+ } else if (!hasRider) { // Purpur
|
|
DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase();
|
|
|
|
idragoncontroller.doServerTick();
|
|
@@ -352,7 +428,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
if (world1 instanceof ServerLevel) {
|
|
ServerLevel worldserver1 = (ServerLevel) world1;
|
|
|
|
- if (this.hurtTime == 0) {
|
|
+ if (!hasRider && this.hurtTime == 0) { // Purpur
|
|
this.knockBack(worldserver1, worldserver1.getEntities((Entity) this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR));
|
|
this.knockBack(worldserver1, worldserver1.getEntities((Entity) this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR));
|
|
this.hurt(worldserver1.getEntities((Entity) this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR));
|
|
@@ -397,7 +473,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
}
|
|
|
|
if (!this.level().isClientSide) {
|
|
- this.inWall = this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox());
|
|
+ this.inWall = !hasRider && this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); // Purpur
|
|
if (this.dragonFight != null) {
|
|
this.dragonFight.updateDragon(this);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..b3c52d0b74528136523f5194acac14cc3421ef73 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
@@ -88,16 +88,30 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
|
return !entityliving.getType().is(EntityTypeTags.WITHER_FRIENDS) && entityliving.attackable();
|
|
};
|
|
private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR);
|
|
+ private int shootCooldown = 0; // Purpur
|
|
// Paper start
|
|
private boolean canPortal = false;
|
|
|
|
public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; }
|
|
// Paper end
|
|
+ private org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD purpurController; // Purpur
|
|
|
|
public WitherBoss(EntityType<? extends WitherBoss> type, Level world) {
|
|
super(type, world);
|
|
this.bossEvent = (ServerBossEvent) (new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true);
|
|
- this.moveControl = new FlyingMoveControl(this, 10, false);
|
|
+ // Purpur start
|
|
+ this.purpurController = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.1F);
|
|
+ this.moveControl = new FlyingMoveControl(this, 10, false) {
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (mob.getRider() != null && mob.isControllable()) {
|
|
+ purpurController.purpurTick(mob.getRider());
|
|
+ } else {
|
|
+ super.tick();
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
this.setHealth(this.getMaxHealth());
|
|
this.xpReward = 50;
|
|
}
|
|
@@ -112,13 +126,114 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
|
return navigationflying;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.witherRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.witherRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.witherControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.witherMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED) * 5F;
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 0.5, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ this.entityData.set(DATA_TARGETS.get(0), 0);
|
|
+ this.entityData.set(DATA_TARGETS.get(1), 0);
|
|
+ this.entityData.set(DATA_TARGETS.get(2), 0);
|
|
+ getNavigation().stop();
|
|
+ shootCooldown = 20;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onClick(net.minecraft.world.InteractionHand hand) {
|
|
+ return shoot(getRider(), hand == net.minecraft.world.InteractionHand.MAIN_HAND ? new int[]{1} : new int[]{2});
|
|
+ }
|
|
+
|
|
+ public boolean shoot(@Nullable Player 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;
|
|
+ }
|
|
+
|
|
+ net.minecraft.world.phys.HitResult rayTrace = getRayTrace(120, net.minecraft.world.level.ClipContext.Fluid.NONE);
|
|
+ if (rayTrace == null) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ Vec3 loc;
|
|
+ if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) {
|
|
+ BlockPos pos = ((net.minecraft.world.phys.BlockHitResult) rayTrace).getBlockPos();
|
|
+ loc = new Vec3(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D);
|
|
+ } else if (rayTrace.getType() == net.minecraft.world.phys.HitResult.Type.ENTITY) {
|
|
+ Entity target = ((net.minecraft.world.phys.EntityHitResult) rayTrace).getEntity();
|
|
+ loc = new Vec3(target.getX(), target.getY() + (target.getEyeHeight() / 2), target.getZ());
|
|
+ } else {
|
|
+ org.bukkit.block.Block block = player.getTargetBlock(null, 120);
|
|
+ loc = new Vec3(block.getX() + 0.5D, block.getY() + 0.5D, block.getZ() + 0.5D);
|
|
+ }
|
|
+
|
|
+ for (int head : heads) {
|
|
+ shoot(head, loc.x(), loc.y(), loc.z(), rider);
|
|
+ }
|
|
+
|
|
+ return true; // handled
|
|
+ }
|
|
+
|
|
+ public void shoot(int head, double x, double y, double z, Player rider) {
|
|
+ level().levelEvent(null, 1024, blockPosition(), 0);
|
|
+ double headX = getHeadX(head);
|
|
+ double headY = getHeadY(head);
|
|
+ double headZ = getHeadZ(head);
|
|
+ Vec3 vec3d = new Vec3(x - headX, y - headY, z - headZ);
|
|
+ WitherSkull skull = new WitherSkull(level(), this, vec3d.normalize());
|
|
+ skull.setPosRaw(headX, headY, headZ);
|
|
+ level().addFreshEntity(skull);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal());
|
|
this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 40, 20.0F));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomFlyingGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0]));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR));
|
|
}
|
|
@@ -263,6 +378,16 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
|
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
+ // Purpur start
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z());
|
|
+ }
|
|
+ if (shootCooldown > 0) {
|
|
+ shootCooldown--;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
int i;
|
|
|
|
if (this.getInvulnerableTicks() > 0) {
|
|
@@ -580,11 +705,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
|
|
}
|
|
|
|
public int getAlternativeTarget(int headIndex) {
|
|
- return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex));
|
|
+ return getRider() != null && this.isControllable() ? 0 : this.entityData.get(WitherBoss.DATA_TARGETS.get(headIndex)); // Purpur
|
|
}
|
|
|
|
public void setAlternativeTarget(int headIndex, int id) {
|
|
- this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(headIndex), id);
|
|
+ if (getRider() == null || !this.isControllable()) this.entityData.set(WitherBoss.DATA_TARGETS.get(headIndex), id); // Purpur
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
|
index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..5c1aa5859ac411098054be9f52bac0860ee667a5 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
|
@@ -70,12 +70,14 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new RestrictSunGoal(this));
|
|
this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0D, 1.2D));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0]));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java
|
|
index 61004bb35b0edcc4578b8a9c1b280096466ba279..d4aac30f9c9b356cec9fc1450a9e684faf030391 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java
|
|
@@ -32,6 +32,7 @@ public class Blaze extends Monster {
|
|
|
|
public Blaze(EntityType<? extends Blaze> type, Level world) {
|
|
super(type, world);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); // Purpur
|
|
this.setPathfindingMalus(PathType.WATER, -1.0F);
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
this.setPathfindingMalus(PathType.DANGER_FIRE, 0.0F);
|
|
@@ -39,19 +40,55 @@ public class Blaze extends Monster {
|
|
this.xpReward = 10;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.blazeRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.blazeRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.blazeControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.blazeMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED);
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(4, new Blaze.BlazeAttackGoal(this));
|
|
this.goalSelector.addGoal(5, new MoveTowardsRestrictionGoal(this, 1.0));
|
|
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F));
|
|
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
- return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0).add(Attributes.MOVEMENT_SPEED, 0.23F).add(Attributes.FOLLOW_RANGE, 48.0);
|
|
+ return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0).add(Attributes.MOVEMENT_SPEED, 0.23F).add(Attributes.FOLLOW_RANGE, 48.0).add(Attributes.FLYING_SPEED, 0.6D); // Purpur
|
|
}
|
|
|
|
@Override
|
|
@@ -116,6 +153,13 @@ public class Blaze extends Monster {
|
|
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
+ // Purpur start
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot.x(), getVerticalMot() > 0 ? 0.07D : -0.07D, mot.z());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end
|
|
this.nextHeightOffsetChangeTick--;
|
|
if (this.nextHeightOffsetChangeTick <= 0) {
|
|
this.nextHeightOffsetChangeTick = 100;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
|
index 6e290d67b00c88ecd2cf2ce5f612f52ebda9e280..3fc3ab534b00f26cf2f1a79c20909f25021164a1 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
|
|
@@ -45,6 +45,23 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.boggedRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.boggedRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.boggedControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java
|
|
index 87e4b300ac248f6c13d9b4a8f24fd78b24b565b4..504996c8309fcd11de1dd166dee12d7e7db8db56 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java
|
|
@@ -26,6 +26,23 @@ public class CaveSpider extends Spider {
|
|
return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.caveSpiderRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.caveSpiderRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.caveSpiderControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean doHurtTarget(Entity target) {
|
|
if (super.doHurtTarget(target)) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
|
index cb1b19e2e0d8f0744b2355b8f4da0206b196b19c..bc9db0ebd4280fe4dcb43bc47d5b7fc1f831394b 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
|
|
@@ -61,21 +61,98 @@ public class Creeper extends Monster implements PowerableMob {
|
|
public int explosionRadius = 3;
|
|
private int droppedSkulls;
|
|
private Player entityIgniter; // CraftBukkit
|
|
+ // Purpur start
|
|
+ private int spacebarCharge = 0;
|
|
+ private int prevSpacebarCharge = 0;
|
|
+ private int powerToggleDelay = 0;
|
|
+ // Purpur end
|
|
|
|
public Creeper(EntityType<? extends Creeper> type, Level world) {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.creeperRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.creeperRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.creeperControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void customServerAiStep() {
|
|
+ if (powerToggleDelay > 0) {
|
|
+ powerToggleDelay--;
|
|
+ }
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ if (getRider().getForwardMot() != 0 || getRider().getStrafeMot() != 0) {
|
|
+ spacebarCharge = 0;
|
|
+ setIgnited(false);
|
|
+ setSwellDir(-1);
|
|
+ }
|
|
+ if (spacebarCharge == prevSpacebarCharge) {
|
|
+ spacebarCharge = 0;
|
|
+ }
|
|
+ prevSpacebarCharge = spacebarCharge;
|
|
+ }
|
|
+ super.customServerAiStep();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ setIgnited(false);
|
|
+ setSwellDir(-1);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (powerToggleDelay > 0) {
|
|
+ return true; // just toggled power, do not jump or ignite
|
|
+ }
|
|
+ spacebarCharge++;
|
|
+ if (spacebarCharge > maxSwell - 2) {
|
|
+ spacebarCharge = 0;
|
|
+ if (getRider() != null && getRider().getBukkitEntity().hasPermission("allow.powered.creeper")) {
|
|
+ powerToggleDelay = 20;
|
|
+ setPowered(!isPowered());
|
|
+ setIgnited(false);
|
|
+ setSwellDir(-1);
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ if (!isIgnited()) {
|
|
+ if (getRider() != null && getRider().getForwardMot() == 0 && getRider().getStrafeMot() == 0 &&
|
|
+ getRider().getBukkitEntity().hasPermission("allow.special.creeper")) {
|
|
+ setIgnited(true);
|
|
+ setSwellDir(1);
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return getForwardMot() == 0 && getStrafeMot() == 0; // do not jump if standing still
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
this.goalSelector.addGoal(2, new SwellGoal(this));
|
|
+ this.goalSelector.addGoal(3, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0D, 1.2D));
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0D, 1.2D));
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0]));
|
|
}
|
|
@@ -324,6 +401,7 @@ public class Creeper extends Monster implements PowerableMob {
|
|
com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited);
|
|
if (event.callEvent()) {
|
|
this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited());
|
|
+ if (!event.isIgnited()) setSwellDir(-1); // Purpur
|
|
}
|
|
}
|
|
// Paper end - CreeperIgniteEvent
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
|
index cff1b5e0e3fd32d82157d5f13d83d4abdfad7378..2b93338db154e6c0c3c8814adabaab761f08af08 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
|
|
@@ -71,6 +71,23 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
return Zombie.createAttributes().add(Attributes.STEP_HEIGHT, 1.0D);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.drownedRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.drownedRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.drownedControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void addBehaviourGoals() {
|
|
this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D));
|
|
@@ -262,8 +279,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
this.searchingForLand = targetingUnderwater;
|
|
}
|
|
|
|
- private static class DrownedMoveControl extends MoveControl {
|
|
-
|
|
+ private static class DrownedMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
private final Drowned drowned;
|
|
|
|
public DrownedMoveControl(Drowned drowned) {
|
|
@@ -272,7 +288,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
LivingEntity entityliving = this.drowned.getTarget();
|
|
|
|
if (this.drowned.wantsToSwim() && this.drowned.isInWater()) {
|
|
@@ -295,7 +311,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
|
|
this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F));
|
|
this.drowned.yBodyRot = this.drowned.getYRot();
|
|
- float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float f1 = (float) (this.getSpeedModifier() * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur
|
|
float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1);
|
|
|
|
this.drowned.setSpeed(f2);
|
|
@@ -305,7 +321,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D));
|
|
}
|
|
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur
|
|
}
|
|
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
index fd995b1f29c47884e9db2cb92f1dd615d62ae032..430899602940aa04c21d45ae94bcc506352389cf 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
@@ -33,6 +33,18 @@ public class ElderGuardian extends Guardian {
|
|
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.elderGuardianRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.elderGuardianControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
|
index 828c51477cd8f35d591367b30bf4feef6a250292..d77e4a354983b6d6c4d5bbc37d886193af396dff 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
|
|
@@ -95,9 +95,27 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
this.setPathfindingMalus(PathType.WATER, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.endermanRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.endermanRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.endermanControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this));
|
|
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false));
|
|
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F));
|
|
@@ -105,6 +123,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
this.goalSelector.addGoal(10, new EnderMan.EndermanLeaveBlockGoal(this));
|
|
this.goalSelector.addGoal(11, new EnderMan.EndermanTakeBlockGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0]));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false));
|
|
@@ -281,7 +300,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
- if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) {
|
|
+ if ((getRider() == null || !this.isControllable()) && this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - no random teleporting
|
|
float f = this.getLightLevelDependentMagicValue();
|
|
|
|
if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent
|
|
@@ -396,6 +415,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
public boolean hurt(DamageSource source, float amount) {
|
|
if (this.isInvulnerableTo(source)) {
|
|
return false;
|
|
+ } else if (getRider() != null && this.isControllable()) { return super.hurt(source, amount); // Purpur - no teleporting on damage
|
|
} else {
|
|
boolean flag = source.getDirectEntity() instanceof ThrownPotion;
|
|
boolean flag1;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Endermite.java b/src/main/java/net/minecraft/world/entity/monster/Endermite.java
|
|
index 9c78905762d9a484878fa9cf03a2ca3850e7e613..ee88933c7baba3bc82c6dc9d52291d5f9fc0f25d 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Endermite.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Endermite.java
|
|
@@ -38,14 +38,33 @@ public class Endermite extends Monster {
|
|
this.xpReward = 3;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.endermiteRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.endermiteRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.endermiteControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false));
|
|
this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java
|
|
index 627cf7ba8f512285228121e46208fff51f22b563..fb2409536741e814f20fa6793003c38ed898e443 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java
|
|
@@ -52,10 +52,28 @@ public class Evoker extends SpellcasterIllager {
|
|
this.xpReward = 10;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.evokerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.evokerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.evokerControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal());
|
|
this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D));
|
|
this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal());
|
|
@@ -64,6 +82,7 @@ public class Evoker extends SpellcasterIllager {
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D));
|
|
this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers());
|
|
this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300));
|
|
this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Ghast.java b/src/main/java/net/minecraft/world/entity/monster/Ghast.java
|
|
index a836a902bebf318ceabaed4e98fab1141b46a28b..24384a8bba59d335949ca641f8b2b599f769b316 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Ghast.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Ghast.java
|
|
@@ -43,11 +43,47 @@ public class Ghast extends FlyingMob implements Enemy {
|
|
this.moveControl = new Ghast.GhastMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.ghastRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.ghastRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.ghastControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.ghastMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED);
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(5, new Ghast.RandomFloatAroundGoal(this));
|
|
this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this));
|
|
this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> {
|
|
return Math.abs(entityliving.getY() - this.getY()) <= 4.0D;
|
|
}));
|
|
@@ -102,7 +138,7 @@ public class Ghast extends FlyingMob implements Enemy {
|
|
}
|
|
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D);
|
|
+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur
|
|
}
|
|
|
|
@Override
|
|
@@ -154,7 +190,7 @@ public class Ghast extends FlyingMob implements Enemy {
|
|
|
|
}
|
|
|
|
- private static class GhastMoveControl extends MoveControl {
|
|
+ private static class GhastMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur
|
|
|
|
private final Ghast ghast;
|
|
private int floatDuration;
|
|
@@ -165,7 +201,7 @@ public class Ghast extends FlyingMob implements Enemy {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.operation == MoveControl.Operation.MOVE_TO) {
|
|
if (this.floatDuration-- <= 0) {
|
|
this.floatDuration += this.ghast.getRandom().nextInt(5) + 2;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java
|
|
index 118521ae54254b0a73bb7cba7b2871c9c26f89fc..868e8383a890d76b4cfeac8b77b06e8f58d0a6dc 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Giant.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java
|
|
@@ -12,6 +12,29 @@ public class Giant extends Monster {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.giantRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.giantRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.giantControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 100.0).add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.ATTACK_DAMAGE, 50.0);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Guardian.java b/src/main/java/net/minecraft/world/entity/monster/Guardian.java
|
|
index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..8fd7d578c4875ab1d6059dc445734e378c82b40f 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java
|
|
@@ -66,15 +66,36 @@ public class Guardian extends Monster {
|
|
this.xpReward = 10;
|
|
this.setPathfindingMalus(PathType.WATER, 0.0F);
|
|
this.moveControl = new Guardian.GuardianMoveControl(this);
|
|
+ // Purpur start
|
|
+ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this) {
|
|
+ @Override
|
|
+ public void setYawPitch(float yaw, float pitch) {
|
|
+ super.setYawPitch(yaw, pitch * 0.35F);
|
|
+ }
|
|
+ };
|
|
+ // Purpur end
|
|
this.clientSideTailAnimation = this.random.nextFloat();
|
|
this.clientSideTailAnimationO = this.clientSideTailAnimation;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.guardianRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.guardianControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D);
|
|
|
|
this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80);
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field
|
|
this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction);
|
|
this.goalSelector.addGoal(7, this.randomStrollGoal);
|
|
@@ -83,6 +104,7 @@ public class Guardian extends Monster {
|
|
this.goalSelector.addGoal(9, new RandomLookAroundGoal(this));
|
|
this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
|
pathfindergoalmovetowardsrestriction.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this)));
|
|
}
|
|
|
|
@@ -333,7 +355,7 @@ public class Guardian extends Monster {
|
|
@Override
|
|
public void travel(Vec3 movementInput) {
|
|
if (this.isControlledByLocalInstance() && this.isInWater()) {
|
|
- this.moveRelative(0.1F, movementInput);
|
|
+ this.moveRelative(getRider() != null && this.isControllable() ? getSpeed() : 0.1F, movementInput); // Purpur
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.9D));
|
|
if (!this.isMoving() && this.getTarget() == null) {
|
|
@@ -345,7 +367,7 @@ public class Guardian extends Monster {
|
|
|
|
}
|
|
|
|
- private static class GuardianMoveControl extends MoveControl {
|
|
+ private static class GuardianMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur
|
|
|
|
private final Guardian guardian;
|
|
|
|
@@ -354,8 +376,17 @@ public class Guardian extends Monster {
|
|
this.guardian = guardian;
|
|
}
|
|
|
|
+ // Purpur start
|
|
@Override
|
|
- public void tick() {
|
|
+ public void purpurTick(Player rider) {
|
|
+ super.purpurTick(rider);
|
|
+ guardian.setDeltaMovement(guardian.getDeltaMovement().add(0.0D, 0.005D, 0.0D));
|
|
+ guardian.setMoving(guardian.getForwardMot() > 0.0F); // control tail speed
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
+ @Override
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) {
|
|
Vec3 vec3d = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ());
|
|
double d0 = vec3d.length();
|
|
@@ -366,7 +397,7 @@ public class Guardian extends Monster {
|
|
|
|
this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F));
|
|
this.guardian.yBodyRot = this.guardian.getYRot();
|
|
- float f1 = (float) (this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float f1 = (float) (this.getSpeedModifier() * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur
|
|
float f2 = Mth.lerp(0.125F, this.guardian.getSpeed(), f1);
|
|
|
|
this.guardian.setSpeed(f2);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Husk.java b/src/main/java/net/minecraft/world/entity/monster/Husk.java
|
|
index c34c8483a026f61fe20935697d321d7ef5d8dfbc..20ea3187626a667815245974df88189f7d6ffc76 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Husk.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Husk.java
|
|
@@ -22,6 +22,23 @@ public class Husk extends Zombie {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.huskRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.huskRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.huskControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static boolean checkHuskSpawnRules(EntityType<Husk> type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
|
return checkMonsterSpawnRules(type, world, spawnReason, pos, random) && (MobSpawnType.isSpawner(spawnReason) || world.canSeeSky(pos));
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java
|
|
index c858556ea457931aa14e338e20672cb50cb19f0e..58e9bf99ace27a59df56a378e25d9156e71aa313 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java
|
|
@@ -57,10 +57,28 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob {
|
|
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.illusionerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.illusionerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.illusionerControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal());
|
|
this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal());
|
|
this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal());
|
|
@@ -68,6 +86,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob {
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D));
|
|
this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers());
|
|
this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300));
|
|
this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java
|
|
index d85a1587a11e735b97107c53ac540cdbe2923ed0..d8501995801f636173a46481268d602f028dd034 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java
|
|
@@ -24,6 +24,28 @@ public class MagmaCube extends Slime {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.magmaCubeRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.magmaCubeRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.magmaCubeControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getJumpPower() {
|
|
+ return 0.42F * this.getBlockJumpFactor(); // from EntityLiving
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F);
|
|
}
|
|
@@ -69,6 +91,7 @@ public class MagmaCube extends Slime {
|
|
float f = (float)this.getSize() * 0.1F;
|
|
this.setDeltaMovement(vec3.x, (double)(this.getJumpPower() + f), vec3.z);
|
|
this.hasImpulse = true;
|
|
+ this.actualJump = false; // Purpur
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
|
index c277dac448a64809e93dd7a447ee3dc2a86c860e..e02992d97f552ecc8ce48e0c2e981d771dfabf19 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
|
|
@@ -59,6 +59,64 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
this.lookControl = new Phantom.PhantomLookControl(this, this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.phantomRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.phantomRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.phantomControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.phantomMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable() && !onGround) {
|
|
+ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED);
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() {
|
|
+ return Monster.createMonsterAttributes().add(Attributes.FLYING_SPEED, 3.0D);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (getRider() != null && 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());
|
|
+
|
|
+ org.purpurmc.purpur.entity.PhantomFlames flames = new org.purpurmc.purpur.entity.PhantomFlames(level(), this);
|
|
+ flames.canGrief = level().purpurConfig.phantomAllowGriefing;
|
|
+ flames.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), 1.0F, 5.0F);
|
|
+ level().addFreshEntity(flames);
|
|
+ return true;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0;
|
|
@@ -71,9 +129,11 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal());
|
|
this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal());
|
|
this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal());
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal());
|
|
}
|
|
|
|
@@ -139,6 +199,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
@Override
|
|
public void aiStep() {
|
|
if (this.isAlive() && this.shouldBurnInDay && this.isSunBurnTick()) { // Paper - shouldBurnInDay API
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur
|
|
this.igniteForSeconds(8.0F);
|
|
}
|
|
|
|
@@ -254,7 +315,7 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
private AttackPhase() {}
|
|
}
|
|
|
|
- private class PhantomMoveControl extends MoveControl {
|
|
+ private class PhantomMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur
|
|
|
|
private float speed = 0.1F;
|
|
|
|
@@ -262,8 +323,19 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
super(entity);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ public void purpurTick(Player rider) {
|
|
+ if (!Phantom.this.onGround) {
|
|
+ // phantom is always in motion when flying
|
|
+ // TODO - FIX THIS
|
|
+ // rider.setForward(1.0F);
|
|
+ }
|
|
+ super.purpurTick(rider);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (Phantom.this.horizontalCollision) {
|
|
Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F);
|
|
this.speed = 0.1F;
|
|
@@ -309,14 +381,20 @@ public class Phantom extends FlyingMob implements Enemy {
|
|
}
|
|
}
|
|
|
|
- private class PhantomLookControl extends LookControl {
|
|
+ private class PhantomLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
|
|
public PhantomLookControl(final Phantom entity, final Mob phantom) {
|
|
super(phantom);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ public void purpurTick(Player rider) {
|
|
+ setYawPitch(rider.getYRot(), -rider.xRotO * 0.75F);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
- public void tick() {}
|
|
+ public void vanillaTick() {} // Purpur
|
|
}
|
|
|
|
private class PhantomBodyRotationControl extends BodyRotationControl {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Pillager.java b/src/main/java/net/minecraft/world/entity/monster/Pillager.java
|
|
index 4b4dcee6abe7a6db43638d04665125eec560496e..adacd02cabde55a305b3643b6060f1792e122b1c 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Pillager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Pillager.java
|
|
@@ -62,15 +62,34 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.pillagerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.pillagerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.pillagerControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new Raider.HoldGroundAttackGoal(this, 10.0F)); // Paper - decomp fix
|
|
this.goalSelector.addGoal(3, new RangedCrossbowAttackGoal<>(this, 1.0D, 8.0F));
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D));
|
|
this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 15.0F, 1.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 15.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
|
index 212d341425c0f93bba0376de69bea61ffcf4dbd6..9af3d05206ae64cfffbfb3fa89318e6184469204 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
|
|
@@ -69,14 +69,39 @@ public class Ravager extends Raider {
|
|
this.setPathfindingMalus(PathType.LEAVES, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.ravagerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.ravagerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.ravagerControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void onMount(Player rider) {
|
|
+ super.onMount(rider);
|
|
+ getNavigation().stop();
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers());
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> {
|
|
@@ -129,7 +154,7 @@ public class Ravager extends Raider {
|
|
@Override
|
|
public void aiStep() {
|
|
super.aiStep();
|
|
- if (this.isAlive()) {
|
|
+ if (this.isAlive() && (getRider() == null || !this.isControllable())) { // Purpur
|
|
if (this.isImmobile()) {
|
|
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0D);
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
|
index 920c7a92643e83598f39bf984cca430d9deed2cd..f36ccb36753d1b1a6c7706729e598078f4467644 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
|
|
@@ -97,12 +97,31 @@ public class Shulker extends AbstractGolem implements VariantHolder<Optional<Dye
|
|
this.lookControl = new Shulker.ShulkerLookControl(this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.shulkerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.shulkerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.shulkerControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true));
|
|
this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal());
|
|
this.goalSelector.addGoal(7, new Shulker.ShulkerPeekGoal());
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{this.getClass()})).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this));
|
|
this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this));
|
|
@@ -608,7 +627,7 @@ public class Shulker extends AbstractGolem implements VariantHolder<Optional<Dye
|
|
return b0 != 16 && b0 <= 15 ? DyeColor.byId(b0) : null;
|
|
}
|
|
|
|
- private class ShulkerLookControl extends LookControl {
|
|
+ private class ShulkerLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur
|
|
|
|
public ShulkerLookControl(final Mob entity) {
|
|
super(entity);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
|
index 860e385fc83f9787dca92efe35d21fd69c4dd635..97cab38a47e302f40ca69ef4eb8f7dcb11eccf35 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java
|
|
@@ -43,14 +43,33 @@ public class Silverfish extends Monster {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.silverfishRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.silverfishRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.silverfishControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.friendsGoal = new Silverfish.SilverfishWakeUpFriendsGoal(this);
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(3, this.friendsGoal);
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false));
|
|
this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
|
index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..8b40824f974bba1dae9166c2425be3d5d74a5ffd 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
|
@@ -27,6 +27,23 @@ public class Skeleton extends AbstractSkeleton {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.skeletonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.skeletonRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.skeletonControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
|
index adebb66e550f805f444bec22e9a4dd575a642b43..d34892ac85b08f017221c5bb98c7442a8017afbe 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
|
|
@@ -63,6 +63,7 @@ public class Slime extends Mob implements Enemy {
|
|
public float squish;
|
|
public float oSquish;
|
|
private boolean wasOnGround;
|
|
+ protected boolean actualJump; // Purpur
|
|
|
|
public Slime(EntityType<? extends Slime> type, Level world) {
|
|
super(type, world);
|
|
@@ -70,12 +71,48 @@ public class Slime extends Mob implements Enemy {
|
|
this.moveControl = new Slime.SlimeMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.slimeRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.slimeRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.slimeControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getJumpPower() {
|
|
+ float height = super.getJumpPower();
|
|
+ return getRider() != null && this.isControllable() && actualJump ? height * 1.5F : height;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean onSpacebar() {
|
|
+ if (onGround && getRider() != null && this.isControllable()) {
|
|
+ actualJump = true;
|
|
+ if (getRider().getForwardMot() == 0 || getRider().getStrafeMot() == 0) {
|
|
+ jumpFromGround(); // jump() here if not moving
|
|
+ }
|
|
+ }
|
|
+ return true; // do not jump() in wasd controller, let vanilla controller handle
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Slime.SlimeFloatGoal(this));
|
|
this.goalSelector.addGoal(2, new Slime.SlimeAttackGoal(this));
|
|
this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this));
|
|
this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> {
|
|
return Math.abs(entityliving.getY() - this.getY()) <= 4.0D;
|
|
}));
|
|
@@ -395,6 +432,7 @@ public class Slime extends Mob implements Enemy {
|
|
|
|
this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z);
|
|
this.hasImpulse = true;
|
|
+ this.actualJump = false; // Purpur
|
|
}
|
|
|
|
@Nullable
|
|
@@ -428,7 +466,7 @@ public class Slime extends Mob implements Enemy {
|
|
return super.getDefaultDimensions(pose).scale((float) this.getSize());
|
|
}
|
|
|
|
- private static class SlimeMoveControl extends MoveControl {
|
|
+ private static class SlimeMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur
|
|
|
|
private float yRot;
|
|
private int jumpDelay;
|
|
@@ -447,21 +485,33 @@ public class Slime extends Mob implements Enemy {
|
|
}
|
|
|
|
public void setWantedMovement(double speed) {
|
|
- this.speedModifier = speed;
|
|
+ this.setSpeedModifier(speed); // Purpur
|
|
this.operation = MoveControl.Operation.MOVE_TO;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start
|
|
+ if (slime.getRider() != null && slime.isControllable()) {
|
|
+ purpurTick(slime.getRider());
|
|
+ if (slime.getForwardMot() != 0 || slime.getStrafeMot() != 0) {
|
|
+ if (jumpDelay > 10) {
|
|
+ jumpDelay = 6;
|
|
+ }
|
|
+ } else {
|
|
+ jumpDelay = 20;
|
|
+ }
|
|
+ } else {
|
|
+ // Purpur end
|
|
this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F));
|
|
this.mob.yHeadRot = this.mob.getYRot();
|
|
this.mob.yBodyRot = this.mob.getYRot();
|
|
- if (this.operation != MoveControl.Operation.MOVE_TO) {
|
|
+ } if ((slime.getRider() == null || !slime.isControllable()) && this.operation != MoveControl.Operation.MOVE_TO) { // Purpur
|
|
this.mob.setZza(0.0F);
|
|
} else {
|
|
this.operation = MoveControl.Operation.WAIT;
|
|
if (this.mob.onGround()) {
|
|
- this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
|
+ this.mob.setSpeed((float) (this.getSpeedModifier() * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED) * (slime.getRider() != null && slime.isControllable() && (slime.getRider().getForwardMot() != 0 || slime.getRider().getStrafeMot() != 0) ? 2.0D : 1.0D))); // Purpur
|
|
if (this.jumpDelay-- <= 0) {
|
|
this.jumpDelay = this.slime.getJumpDelay();
|
|
if (this.isAggressive) {
|
|
@@ -478,7 +528,7 @@ public class Slime extends Mob implements Enemy {
|
|
this.mob.setSpeed(0.0F);
|
|
}
|
|
} else {
|
|
- this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
|
+ this.mob.setSpeed((float) (this.getSpeedModifier() * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED) * (slime.getRider() != null && slime.isControllable() && (slime.getRider().getForwardMot() != 0 || slime.getRider().getStrafeMot() != 0) ? 2.0D : 1.0D))); // Purpur
|
|
}
|
|
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
|
index e675f1e3e5b6f9e1aa0d928ebb9abe76458edb38..93d7cd8fe60b0c0bc3620bca2fe2cfbbee2e9421 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
|
@@ -51,9 +51,27 @@ public class Spider extends Monster {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.spiderRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.spiderRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.spiderControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Armadillo.class, 6.0F, 1.0D, 1.2D, (entityliving) -> {
|
|
return !((Armadillo) entityliving).isScared();
|
|
}));
|
|
@@ -62,6 +80,7 @@ public class Spider extends Monster {
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D));
|
|
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0]));
|
|
this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class));
|
|
this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Stray.java b/src/main/java/net/minecraft/world/entity/monster/Stray.java
|
|
index 1b8ab3f1090ea78bdba97265e05576c9a3e2deb3..c47fb4577d31583806584dffe2b0b7674c5565af 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Stray.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Stray.java
|
|
@@ -22,6 +22,23 @@ public class Stray extends AbstractSkeleton {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.strayRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.strayRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.strayControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static boolean checkStraySpawnRules(EntityType<Stray> type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
|
BlockPos blockPos = pos;
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Strider.java b/src/main/java/net/minecraft/world/entity/monster/Strider.java
|
|
index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..cc8a169858709cf3c63bd4973018b4c40429784a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Strider.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Strider.java
|
|
@@ -97,6 +97,23 @@ public class Strider extends Animal implements ItemSteerable, Saddleable {
|
|
this.setPathfindingMalus(PathType.DAMAGE_FIRE, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.striderRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.striderRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.striderControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static boolean checkStriderSpawnRules(EntityType<Strider> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
|
BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable();
|
|
|
|
@@ -158,6 +175,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable {
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.65D));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
|
this.temptGoal = new TemptGoal(this, 1.4D, (itemstack) -> {
|
|
return itemstack.is(ItemTags.STRIDER_TEMPT_ITEMS);
|
|
@@ -468,7 +486,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable {
|
|
if (!enuminteractionresult.consumesAction()) {
|
|
ItemStack itemstack = player.getItemInHand(hand);
|
|
|
|
- return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS;
|
|
+ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : tryRide(player, hand); // Purpur
|
|
} else {
|
|
if (flag && !this.isSilent()) {
|
|
this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
|
index 2985296a9a034e535157f55e322fc8c107827752..34e88c071b5cedf0a66d5a81e70cccdb0768962e 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java
|
|
@@ -60,6 +60,50 @@ public class Vex extends Monster implements TraceableEntity {
|
|
this.xpReward = 3;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.vexRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.vexRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.vexControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public double getMaxY() {
|
|
+ return level().purpurConfig.vexMaxY;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void travel(Vec3 vec3) {
|
|
+ super.travel(vec3);
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ float speed;
|
|
+ if (onGround) {
|
|
+ speed = (float) getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.1F;
|
|
+ } else {
|
|
+ speed = (float) getAttributeValue(Attributes.FLYING_SPEED);
|
|
+ }
|
|
+ setSpeed(speed);
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ move(MoverType.SELF, mot.multiply(speed, 1.0, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
|
|
+ return false; // no fall damage please
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return this.tickCount % Vex.TICKS_PER_FLAP == 0;
|
|
@@ -73,7 +117,7 @@ public class Vex extends Monster implements TraceableEntity {
|
|
|
|
@Override
|
|
public void tick() {
|
|
- this.noPhysics = true;
|
|
+ this.noPhysics = getRider() == null || !this.isControllable(); // Purpur
|
|
super.tick();
|
|
this.noPhysics = false;
|
|
this.setNoGravity(true);
|
|
@@ -88,17 +132,19 @@ public class Vex extends Monster implements TraceableEntity {
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(4, new Vex.VexChargeAttackGoal());
|
|
this.goalSelector.addGoal(8, new Vex.VexRandomMoveGoal());
|
|
this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F));
|
|
this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new Vex.VexCopyOwnerTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D);
|
|
+ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur;
|
|
}
|
|
|
|
@Override
|
|
@@ -230,14 +276,14 @@ public class Vex extends Monster implements TraceableEntity {
|
|
this.setDropChance(EquipmentSlot.MAINHAND, 0.0F);
|
|
}
|
|
|
|
- private class VexMoveControl extends MoveControl {
|
|
+ private class VexMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur
|
|
|
|
public VexMoveControl(final Vex entityvex) {
|
|
super(entityvex);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur
|
|
if (this.operation == MoveControl.Operation.MOVE_TO) {
|
|
Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ());
|
|
double d0 = vec3d.length();
|
|
@@ -246,7 +292,7 @@ public class Vex extends Monster implements TraceableEntity {
|
|
this.operation = MoveControl.Operation.WAIT;
|
|
Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D));
|
|
} else {
|
|
- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.speedModifier * 0.05D / d0)));
|
|
+ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.getSpeedModifier() * 0.05D / d0))); // Purpur
|
|
if (Vex.this.getTarget() == null) {
|
|
Vec3 vec3d1 = Vex.this.getDeltaMovement();
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
|
|
index 0615bb305d70f660a6baa7f78078990d6db227d3..fa7af386c89f5f9181d345191dc545674a257996 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java
|
|
@@ -53,14 +53,33 @@ public class Vindicator extends AbstractIllager {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.vindicatorRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.vindicatorRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.vindicatorControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(1, new Vindicator.VindicatorBreakDoorGoal(this));
|
|
this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this));
|
|
this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F));
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
|
index b8ff1e3d280171378fe383bcc7c6a855d20ae5d1..cd299591c00c1860b252c7abfdd2afa2abcbd537 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java
|
|
@@ -56,6 +56,23 @@ public class Witch extends Raider implements RangedAttackMob {
|
|
super(type, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.witchRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.witchRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.witchControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
@@ -64,10 +81,12 @@ public class Witch extends Raider implements RangedAttackMob {
|
|
});
|
|
this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null);
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 60, 10.0F));
|
|
this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D));
|
|
this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(3, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[]{Raider.class}));
|
|
this.targetSelector.addGoal(2, this.healRaidersGoal);
|
|
this.targetSelector.addGoal(3, this.attackPlayersGoal);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
|
|
index bb2e7cee612dc1fafa042674a0b0d07d7165b54c..09f7277283bf6ec44d3f1cc068893e0e1155eb61 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
|
|
@@ -33,6 +33,23 @@ public class WitherSkeleton extends AbstractSkeleton {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.witherSkeletonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.witherSkeletonRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.witherSkeletonControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java
|
|
index aa458ede5bd645ebf524238179edb33f41bd683f..e683b14ed7bc0284fbbe93dedf6ab8c0423e0764 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java
|
|
@@ -79,6 +79,23 @@ public class Zoglin extends Monster implements Enemy, HoglinBase {
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.zoglinRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.zoglinRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.zoglinControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected Brain.Provider<Zoglin> brainProvider() {
|
|
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
|
|
@@ -234,6 +251,7 @@ public class Zoglin extends Monster implements Enemy, HoglinBase {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("zoglinBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick((ServerLevel)this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
this.updateActivity();
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
|
index 2280004638fd19ed018cb3e77d53a018b34ec516..ba630beb18830e92432669f643dfd4cf8d2386fb 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
|
@@ -108,11 +108,30 @@ public class Zombie extends Monster {
|
|
this(EntityType.ZOMBIE, world);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.zombieRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.zombieRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.zombieControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
if (this.level().paperConfig().entities.behavior.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper - Add zombie targets turtle egg config
|
|
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
|
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
this.addBehaviourGoals();
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
|
|
index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..778edd9a723459ae41f521e953ea97eeac123c5f 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
|
|
@@ -83,6 +83,23 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
|
|
});
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.zombieVillagerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.zombieVillagerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.zombieVillagerControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
super.defineSynchedData(builder);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
|
index 10388cf33f6f33070aa84b3b2d7bd14fc50ceea8..18e6a56da9f714f4e5b78ec63df6cf310deb1247 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
|
@@ -63,6 +63,23 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.zombifiedPiglinRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.zombifiedPiglinRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.zombifiedPiglinControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public void setPersistentAngerTarget(@Nullable UUID angryAt) {
|
|
this.persistentAngerTarget = angryAt;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
index d5e0c493f4c348724958193795ceb987765a465f..a2c0f73c84651f713781deaaa588a3c704eb32b3 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
@@ -90,6 +90,23 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.hoglinRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.hoglinRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.hoglinControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean canBeLeashed() {
|
|
return true;
|
|
@@ -156,6 +173,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("hoglinBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel)this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
HoglinAi.updateActivity(this);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
index bc58323801ee16fe9b63c21332144ec002a902f2..a8df353eef6ab0dc2a6bd4242f6b85af91444ae9 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
@@ -93,6 +93,23 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.piglinRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.piglinRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.piglinControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public void addAdditionalSaveData(CompoundTag nbt) {
|
|
super.addAdditionalSaveData(nbt);
|
|
@@ -296,6 +313,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("piglinBrain");
|
|
+ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
|
|
this.getBrain().tick((ServerLevel) this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
PiglinAi.updateActivity(this);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
index fcadd7f28ccb81bbb36e97d8b8d8a8ba3f3d6a16..17e2457bc83e7ee4402c10ee7d2ef5aa36901565 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
@@ -62,6 +62,23 @@ public class PiglinBrute extends AbstractPiglin {
|
|
this.xpReward = 20;
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.piglinBruteRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.piglinBruteRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.piglinBruteControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 50.0).add(Attributes.MOVEMENT_SPEED, 0.35F).add(Attributes.ATTACK_DAMAGE, 7.0);
|
|
}
|
|
@@ -107,6 +124,7 @@ public class PiglinBrute extends AbstractPiglin {
|
|
@Override
|
|
protected void customServerAiStep() {
|
|
this.level().getProfiler().push("piglinBruteBrain");
|
|
+ if (getRider() == null || this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick((ServerLevel)this.level(), this);
|
|
this.level().getProfiler().pop();
|
|
PiglinBruteAi.updateActivity(this);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
|
|
index 38bf417a9ad4647f4af24d969f3bf4fed9c4bad7..ba560ab0340c06614547dcddbdcbd1bbda44bb79 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
|
|
@@ -124,8 +124,32 @@ public class Warden extends Monster implements VibrationSystem {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
this.setPathfindingMalus(PathType.DAMAGE_FIRE, 0.0F);
|
|
this.setPathfindingMalus(PathType.DANGER_FIRE, 0.0F);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this, 0.5F); // Purpur
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.wardenRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.wardenRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.wardenControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public Packet<ClientGamePacketListener> getAddEntityPacket(ServerEntity entityTrackerEntry) {
|
|
return new ClientboundAddEntityPacket(this, entityTrackerEntry, this.hasPose(Pose.EMERGING) ? 1 : 0);
|
|
@@ -393,17 +417,14 @@ public class Warden extends Monster implements VibrationSystem {
|
|
|
|
@Contract("null->false")
|
|
public boolean canTargetEntity(@Nullable Entity entity) {
|
|
- boolean flag;
|
|
-
|
|
+ if (getRider() != null && isControllable()) return false; // Purpur
|
|
if (entity instanceof LivingEntity entityliving) {
|
|
if (this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && entityliving.getType() != EntityType.ARMOR_STAND && entityliving.getType() != EntityType.WARDEN && !entityliving.isInvulnerable() && !entityliving.isDeadOrDying() && this.level().getWorldBorder().isWithinBounds(entityliving.getBoundingBox())) {
|
|
- flag = true;
|
|
- return flag;
|
|
+ return true; // Purpur - wtf
|
|
}
|
|
}
|
|
|
|
- flag = false;
|
|
- return flag;
|
|
+ return false; // Purpur - wtf
|
|
}
|
|
|
|
public static void applyDarknessAround(ServerLevel world, Vec3 pos, @Nullable Entity entity, int range) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
index 7e1871401ec5e3e9a85232053490259f132aec0a..7c4c545fca0858caac1cf98ad24b6d59be79dc32 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
@@ -156,6 +156,28 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
this.setVillagerData(this.getVillagerData().setType(type).setProfession(VillagerProfession.NONE));
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.villagerRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.villagerRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.villagerControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public Brain<Villager> getBrain() {
|
|
return (Brain<Villager>) super.getBrain(); // CraftBukkit - decompile error
|
|
@@ -256,6 +278,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
// Paper end
|
|
this.level().getProfiler().push("villagerBrain");
|
|
if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper
|
|
+ /*// Purpur start // Purpur - TODO: Pufferfish
|
|
+ if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur - only use brain if no rider
|
|
+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper
|
|
+ }
|
|
+ // Purpur end*/ // Purpur - TODO: Pufferfish
|
|
this.level().getProfiler().pop();
|
|
if (this.assignProfessionWhenSpawned) {
|
|
this.assignProfessionWhenSpawned = false;
|
|
@@ -312,7 +339,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) {
|
|
if (this.isBaby()) {
|
|
this.setUnhappy();
|
|
- return InteractionResult.sidedSuccess(this.level().isClientSide);
|
|
+ return tryRide(player, hand, InteractionResult.sidedSuccess(this.level().isClientSide)); // Purpur
|
|
} else {
|
|
if (!this.level().isClientSide) {
|
|
boolean flag = this.getOffers().isEmpty();
|
|
@@ -326,9 +353,10 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
}
|
|
|
|
if (flag) {
|
|
- return InteractionResult.CONSUME;
|
|
+ return tryRide(player, hand, InteractionResult.CONSUME); // Purpur
|
|
}
|
|
|
|
+ if (level().purpurConfig.villagerRidable && itemstack.isEmpty()) return tryRide(player, hand); // Purpur
|
|
this.startTrading(player);
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
|
index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..d514faecb9e6b244aa043383fa072316da939518 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
|
|
@@ -71,6 +71,23 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
|
|
//this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set.
|
|
}
|
|
|
|
+ // Purpur - start
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.wanderingTraderRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.wanderingTraderRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.wanderingTraderControllable;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
@@ -119,9 +136,9 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
|
|
|
|
if (!this.level().isClientSide) {
|
|
if (this.getOffers().isEmpty()) {
|
|
- return InteractionResult.CONSUME;
|
|
+ return tryRide(player, hand, InteractionResult.CONSUME); // Purpur
|
|
}
|
|
-
|
|
+ if (level().purpurConfig.wanderingTraderRidable && itemstack.isEmpty()) return tryRide(player, hand); // Purpur
|
|
this.setTradingPlayer(player);
|
|
this.openTradingScreen(player, this.getDisplayName(), 1);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
index 54ba25632c2a9e1c93a5b3a0b92e5280864c49d6..92200ab909a9ecabd75e98d4e15e8759dd2b9c86 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
|
@@ -207,6 +207,19 @@ public abstract class Player extends LivingEntity {
|
|
}
|
|
// CraftBukkit end
|
|
|
|
+ // Purpur start
|
|
+ public abstract void resetLastActionTime();
|
|
+
|
|
+ @Override
|
|
+ public boolean processClick(InteractionHand hand) {
|
|
+ Entity vehicle = getRootVehicle();
|
|
+ if (vehicle != null && vehicle.getRider() == this) {
|
|
+ return vehicle.onClick(hand);
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
public Player(Level world, BlockPos pos, float yaw, GameProfile gameProfile) {
|
|
super(EntityType.PLAYER, world);
|
|
this.lastItemInMainHand = ItemStack.EMPTY;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
index 8575941fd238750c5d56843989a48bcbde2d8a88..b4ed2df8d0795409808df0205edce6da682c3981 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
@@ -33,6 +33,12 @@ public class LlamaSpit extends Projectile {
|
|
this.setPos(owner.getX() - (double) (owner.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(owner.yBodyRot * 0.017453292F), owner.getEyeY() - 0.10000000149011612D, owner.getZ() + (double) (owner.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(owner.yBodyRot * 0.017453292F));
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ public void super_tick() {
|
|
+ super.tick();
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
protected double getDefaultGravity() {
|
|
return 0.06D;
|
|
diff --git a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
|
index 55fd997a4e894eeab24de269d59e486196ffbe8d..63f48841c849ff49d9d43efc5de8952c5a9bba3a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
|
|
@@ -115,6 +115,14 @@ public class WitherSkull extends AbstractHurtingProjectile {
|
|
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public boolean canHitEntity(Entity target) {
|
|
+ // do not hit rider
|
|
+ return target != this.getRider() && super.canHitEntity(target);
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
@Override
|
|
public boolean hurt(DamageSource source, float amount) {
|
|
return false;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
index 2cde808bfa797256409879505ba205a71f381981..84479dad6078a2a12e6b977185bdbbe7f6b36576 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
@@ -1297,4 +1297,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
return this.getHandle().getScoreboardName();
|
|
}
|
|
// Paper end - entity scoreboard name
|
|
+
|
|
+ // Purpur start
|
|
+ @Override
|
|
+ public org.bukkit.entity.Player getRider() {
|
|
+ net.minecraft.world.entity.player.Player rider = getHandle().getRider();
|
|
+ return rider != null ? (org.bukkit.entity.Player) rider.getBukkitEntity() : null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasRider() {
|
|
+ return getHandle().getRider() != null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return getHandle().isRidable();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isRidableInWater() {
|
|
+ return !getHandle().dismountsUnderwater();
|
|
+ }
|
|
+ // 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 bd6fee3e3ad9116802ff8bb57bfa741b881c4057..9e5d4e8a70aec8619db68d75ef3447cf39e239b9 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
@@ -593,6 +593,15 @@ public class CraftEventFactory {
|
|
// Paper end
|
|
craftServer.getPluginManager().callEvent(event);
|
|
|
|
+ // Purpur start
|
|
+ if (who != null) {
|
|
+ switch (action) {
|
|
+ case LEFT_CLICK_BLOCK, LEFT_CLICK_AIR -> who.processClick(InteractionHand.MAIN_HAND);
|
|
+ case RIGHT_CLICK_BLOCK, RIGHT_CLICK_AIR -> who.processClick(InteractionHand.OFF_HAND);
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
return event;
|
|
}
|
|
|
|
@@ -1184,6 +1193,7 @@ public class CraftEventFactory {
|
|
EntityDamageEvent event;
|
|
if (damager != null) {
|
|
event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical);
|
|
+ damager.processClick(InteractionHand.MAIN_HAND); // Purpur
|
|
} else {
|
|
event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions);
|
|
}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
index f06fed3ae5631d46a953617cfdd766a02e628515..08f38c2a87feb138b202f0934abb3724ef79c4c1 100644
|
|
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
|
|
@@ -174,4 +174,9 @@ public class PurpurConfig {
|
|
}
|
|
return builder.build();
|
|
}
|
|
+
|
|
+ public static String cannotRideMob = "<red>You cannot mount that mob";
|
|
+ private static void messages() {
|
|
+ cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob);
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
index 42e502cfcb8d2e775cbf738773caf1a087d2f3f4..2e35e494134e5294fd67a0bf9abbe3f68d5faea5 100644
|
|
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
|
|
@@ -90,4 +90,744 @@ public class PurpurWorldConfig {
|
|
final Map<String, Object> value = PurpurConfig.getMap("world-settings." + worldName + "." + path, null);
|
|
return value.isEmpty() ? fallback : value;
|
|
}
|
|
+
|
|
+ public boolean babiesAreRidable = true;
|
|
+ public boolean untamedTamablesAreRidable = true;
|
|
+ public boolean useNightVisionWhenRiding = false;
|
|
+ public boolean useDismountsUnderwaterTag = true;
|
|
+ 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);
|
|
+ useDismountsUnderwaterTag = getBoolean("ridable-settings.use-dismounts-underwater-tag", useDismountsUnderwaterTag);
|
|
+ }
|
|
+
|
|
+ public boolean allayRidable = false;
|
|
+ public boolean allayRidableInWater = true;
|
|
+ public boolean allayControllable = true;
|
|
+ private void allaySettings() {
|
|
+ allayRidable = getBoolean("mobs.allay.ridable", allayRidable);
|
|
+ allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater);
|
|
+ allayControllable = getBoolean("mobs.allay.controllable", allayControllable);
|
|
+ }
|
|
+
|
|
+ public boolean armadilloRidable = false;
|
|
+ public boolean armadilloRidableInWater = true;
|
|
+ public boolean armadilloControllable = true;
|
|
+ private void armadilloSettings() {
|
|
+ armadilloRidable = getBoolean("mobs.armadillo.ridable", armadilloRidable);
|
|
+ armadilloRidableInWater = getBoolean("mobs.armadillo.ridable-in-water", armadilloRidableInWater);
|
|
+ armadilloControllable = getBoolean("mobs.armadillo.controllable", armadilloControllable);
|
|
+ }
|
|
+
|
|
+ public boolean axolotlRidable = false;
|
|
+ public boolean axolotlControllable = true;
|
|
+ private void axolotlSettings() {
|
|
+ axolotlRidable = getBoolean("mobs.axolotl.ridable", axolotlRidable);
|
|
+ axolotlControllable = getBoolean("mobs.axolotl.controllable", axolotlControllable);
|
|
+ }
|
|
+
|
|
+ public boolean batRidable = false;
|
|
+ public boolean batRidableInWater = true;
|
|
+ public boolean batControllable = true;
|
|
+ public double batMaxY = 320D;
|
|
+ private void batSettings() {
|
|
+ batRidable = getBoolean("mobs.bat.ridable", batRidable);
|
|
+ batRidableInWater = getBoolean("mobs.bat.ridable-in-water", batRidableInWater);
|
|
+ batControllable = getBoolean("mobs.bat.controllable", batControllable);
|
|
+ batMaxY = getDouble("mobs.bat.ridable-max-y", batMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean beeRidable = false;
|
|
+ public boolean beeRidableInWater = true;
|
|
+ public boolean beeControllable = true;
|
|
+ public double beeMaxY = 320D;
|
|
+ private void beeSettings() {
|
|
+ beeRidable = getBoolean("mobs.bee.ridable", beeRidable);
|
|
+ beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater);
|
|
+ beeControllable = getBoolean("mobs.bee.controllable", beeControllable);
|
|
+ beeMaxY = getDouble("mobs.bee.ridable-max-y", beeMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean blazeRidable = false;
|
|
+ public boolean blazeRidableInWater = true;
|
|
+ public boolean blazeControllable = true;
|
|
+ public double blazeMaxY = 320D;
|
|
+ private void blazeSettings() {
|
|
+ blazeRidable = getBoolean("mobs.blaze.ridable", blazeRidable);
|
|
+ blazeRidableInWater = getBoolean("mobs.blaze.ridable-in-water", blazeRidableInWater);
|
|
+ blazeControllable = getBoolean("mobs.blaze.controllable", blazeControllable);
|
|
+ blazeMaxY = getDouble("mobs.blaze.ridable-max-y", blazeMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean boggedRidable = false;
|
|
+ public boolean boggedRidableInWater = true;
|
|
+ public boolean boggedControllable = true;
|
|
+ private void boggedSettings() {
|
|
+ boggedRidable = getBoolean("mobs.bogged.ridable", boggedRidable);
|
|
+ boggedRidableInWater = getBoolean("mobs.bogged.ridable-in-water", boggedRidableInWater);
|
|
+ boggedControllable = getBoolean("mobs.bogged.controllable", boggedControllable);
|
|
+ }
|
|
+
|
|
+ public boolean camelRidableInWater = false;
|
|
+ private void camelSettings() {
|
|
+ camelRidableInWater = getBoolean("mobs.camel.ridable-in-water", camelRidableInWater);
|
|
+ }
|
|
+
|
|
+ public boolean catRidable = false;
|
|
+ public boolean catRidableInWater = true;
|
|
+ public boolean catControllable = true;
|
|
+ private void catSettings() {
|
|
+ catRidable = getBoolean("mobs.cat.ridable", catRidable);
|
|
+ catRidableInWater = getBoolean("mobs.cat.ridable-in-water", catRidableInWater);
|
|
+ catControllable = getBoolean("mobs.cat.controllable", catControllable);
|
|
+ }
|
|
+
|
|
+ public boolean caveSpiderRidable = false;
|
|
+ public boolean caveSpiderRidableInWater = true;
|
|
+ public boolean caveSpiderControllable = true;
|
|
+ private void caveSpiderSettings() {
|
|
+ caveSpiderRidable = getBoolean("mobs.cave_spider.ridable", caveSpiderRidable);
|
|
+ caveSpiderRidableInWater = getBoolean("mobs.cave_spider.ridable-in-water", caveSpiderRidableInWater);
|
|
+ caveSpiderControllable = getBoolean("mobs.cave_spider.controllable", caveSpiderControllable);
|
|
+ }
|
|
+
|
|
+ public boolean chickenRidable = false;
|
|
+ public boolean chickenRidableInWater = false;
|
|
+ public boolean chickenControllable = true;
|
|
+ private void chickenSettings() {
|
|
+ chickenRidable = getBoolean("mobs.chicken.ridable", chickenRidable);
|
|
+ chickenRidableInWater = getBoolean("mobs.chicken.ridable-in-water", chickenRidableInWater);
|
|
+ chickenControllable = getBoolean("mobs.chicken.controllable", chickenControllable);
|
|
+ }
|
|
+
|
|
+ public boolean codRidable = false;
|
|
+ public boolean codControllable = true;
|
|
+ private void codSettings() {
|
|
+ codRidable = getBoolean("mobs.cod.ridable", codRidable);
|
|
+ codControllable = getBoolean("mobs.cod.controllable", codControllable);
|
|
+ }
|
|
+
|
|
+ public boolean cowRidable = false;
|
|
+ public boolean cowRidableInWater = true;
|
|
+ public boolean cowControllable = true;
|
|
+ private void cowSettings() {
|
|
+ cowRidable = getBoolean("mobs.cow.ridable", cowRidable);
|
|
+ cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater);
|
|
+ cowControllable = getBoolean("mobs.cow.controllable", cowControllable);
|
|
+ }
|
|
+
|
|
+ public boolean creeperRidable = false;
|
|
+ public boolean creeperRidableInWater = true;
|
|
+ public boolean creeperControllable = true;
|
|
+ private void creeperSettings() {
|
|
+ creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable);
|
|
+ creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater);
|
|
+ creeperControllable = getBoolean("mobs.creeper.controllable", creeperControllable);
|
|
+ }
|
|
+
|
|
+ public boolean dolphinRidable = false;
|
|
+ public boolean dolphinControllable = true;
|
|
+ public int dolphinSpitCooldown = 20;
|
|
+ public float dolphinSpitSpeed = 1.0F;
|
|
+ public float dolphinSpitDamage = 2.0F;
|
|
+ private void dolphinSettings() {
|
|
+ dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable);
|
|
+ dolphinControllable = getBoolean("mobs.dolphin.controllable", dolphinControllable);
|
|
+ dolphinSpitCooldown = getInt("mobs.dolphin.spit.cooldown", dolphinSpitCooldown);
|
|
+ dolphinSpitSpeed = (float) getDouble("mobs.dolphin.spit.speed", dolphinSpitSpeed);
|
|
+ dolphinSpitDamage = (float) getDouble("mobs.dolphin.spit.damage", dolphinSpitDamage);
|
|
+ }
|
|
+
|
|
+ public boolean donkeyRidableInWater = false;
|
|
+ private void donkeySettings() {
|
|
+ donkeyRidableInWater = getBoolean("mobs.donkey.ridable-in-water", donkeyRidableInWater);
|
|
+ }
|
|
+
|
|
+ public boolean drownedRidable = false;
|
|
+ public boolean drownedRidableInWater = true;
|
|
+ public boolean drownedControllable = true;
|
|
+ private void drownedSettings() {
|
|
+ drownedRidable = getBoolean("mobs.drowned.ridable", drownedRidable);
|
|
+ drownedRidableInWater = getBoolean("mobs.drowned.ridable-in-water", drownedRidableInWater);
|
|
+ drownedControllable = getBoolean("mobs.drowned.controllable", drownedControllable);
|
|
+ }
|
|
+
|
|
+ public boolean elderGuardianRidable = false;
|
|
+ public boolean elderGuardianControllable = true;
|
|
+ private void elderGuardianSettings() {
|
|
+ elderGuardianRidable = getBoolean("mobs.elder_guardian.ridable", elderGuardianRidable);
|
|
+ elderGuardianControllable = getBoolean("mobs.elder_guardian.controllable", elderGuardianControllable);
|
|
+ }
|
|
+
|
|
+ public boolean enderDragonRidable = false;
|
|
+ public boolean enderDragonRidableInWater = true;
|
|
+ public boolean enderDragonControllable = true;
|
|
+ public double enderDragonMaxY = 320D;
|
|
+ private void enderDragonSettings() {
|
|
+ enderDragonRidable = getBoolean("mobs.ender_dragon.ridable", enderDragonRidable);
|
|
+ enderDragonRidableInWater = getBoolean("mobs.ender_dragon.ridable-in-water", enderDragonRidableInWater);
|
|
+ enderDragonControllable = getBoolean("mobs.ender_dragon.controllable", enderDragonControllable);
|
|
+ enderDragonMaxY = getDouble("mobs.ender_dragon.ridable-max-y", enderDragonMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean endermanRidable = false;
|
|
+ public boolean endermanRidableInWater = true;
|
|
+ public boolean endermanControllable = true;
|
|
+ private void endermanSettings() {
|
|
+ endermanRidable = getBoolean("mobs.enderman.ridable", endermanRidable);
|
|
+ endermanRidableInWater = getBoolean("mobs.enderman.ridable-in-water", endermanRidableInWater);
|
|
+ endermanControllable = getBoolean("mobs.enderman.controllable", endermanControllable);
|
|
+ }
|
|
+
|
|
+ public boolean endermiteRidable = false;
|
|
+ public boolean endermiteRidableInWater = true;
|
|
+ public boolean endermiteControllable = true;
|
|
+ private void endermiteSettings() {
|
|
+ endermiteRidable = getBoolean("mobs.endermite.ridable", endermiteRidable);
|
|
+ endermiteRidableInWater = getBoolean("mobs.endermite.ridable-in-water", endermiteRidableInWater);
|
|
+ endermiteControllable = getBoolean("mobs.endermite.controllable", endermiteControllable);
|
|
+ }
|
|
+
|
|
+ public boolean evokerRidable = false;
|
|
+ public boolean evokerRidableInWater = true;
|
|
+ public boolean evokerControllable = true;
|
|
+ private void evokerSettings() {
|
|
+ evokerRidable = getBoolean("mobs.evoker.ridable", evokerRidable);
|
|
+ evokerRidableInWater = getBoolean("mobs.evoker.ridable-in-water", evokerRidableInWater);
|
|
+ evokerControllable = getBoolean("mobs.evoker.controllable", evokerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean foxRidable = false;
|
|
+ public boolean foxRidableInWater = true;
|
|
+ public boolean foxControllable = true;
|
|
+ private void foxSettings() {
|
|
+ foxRidable = getBoolean("mobs.fox.ridable", foxRidable);
|
|
+ foxRidableInWater = getBoolean("mobs.fox.ridable-in-water", foxRidableInWater);
|
|
+ foxControllable = getBoolean("mobs.fox.controllable", foxControllable);
|
|
+ }
|
|
+
|
|
+ public boolean frogRidable = false;
|
|
+ public boolean frogRidableInWater = true;
|
|
+ public boolean frogControllable = true;
|
|
+ public float frogRidableJumpHeight = 0.65F;
|
|
+ private void frogSettings() {
|
|
+ frogRidable = getBoolean("mobs.frog.ridable", frogRidable);
|
|
+ frogRidableInWater = getBoolean("mobs.frog.ridable-in-water", frogRidableInWater);
|
|
+ frogControllable = getBoolean("mobs.frog.controllable", frogControllable);
|
|
+ frogRidableJumpHeight = (float) getDouble("mobs.frog.ridable-jump-height", frogRidableJumpHeight);
|
|
+ }
|
|
+
|
|
+ public boolean ghastRidable = false;
|
|
+ public boolean ghastRidableInWater = true;
|
|
+ public boolean ghastControllable = true;
|
|
+ public double ghastMaxY = 320D;
|
|
+ private void ghastSettings() {
|
|
+ ghastRidable = getBoolean("mobs.ghast.ridable", ghastRidable);
|
|
+ ghastRidableInWater = getBoolean("mobs.ghast.ridable-in-water", ghastRidableInWater);
|
|
+ ghastControllable = getBoolean("mobs.ghast.controllable", ghastControllable);
|
|
+ ghastMaxY = getDouble("mobs.ghast.ridable-max-y", ghastMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean giantRidable = false;
|
|
+ public boolean giantRidableInWater = true;
|
|
+ public boolean giantControllable = true;
|
|
+ private void giantSettings() {
|
|
+ giantRidable = getBoolean("mobs.giant.ridable", giantRidable);
|
|
+ giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater);
|
|
+ giantControllable = getBoolean("mobs.giant.controllable", giantControllable);
|
|
+ }
|
|
+
|
|
+ public boolean glowSquidRidable = false;
|
|
+ public boolean glowSquidControllable = true;
|
|
+ private void glowSquidSettings() {
|
|
+ glowSquidRidable = getBoolean("mobs.glow_squid.ridable", glowSquidRidable);
|
|
+ glowSquidControllable = getBoolean("mobs.glow_squid.controllable", glowSquidControllable);
|
|
+ }
|
|
+
|
|
+ public boolean goatRidable = false;
|
|
+ public boolean goatRidableInWater = true;
|
|
+ public boolean goatControllable = true;
|
|
+ private void goatSettings() {
|
|
+ goatRidable = getBoolean("mobs.goat.ridable", goatRidable);
|
|
+ goatRidableInWater = getBoolean("mobs.goat.ridable-in-water", goatRidableInWater);
|
|
+ goatControllable = getBoolean("mobs.goat.controllable", goatControllable);
|
|
+ }
|
|
+
|
|
+ public boolean guardianRidable = false;
|
|
+ public boolean guardianControllable = true;
|
|
+ private void guardianSettings() {
|
|
+ guardianRidable = getBoolean("mobs.guardian.ridable", guardianRidable);
|
|
+ guardianControllable = getBoolean("mobs.guardian.controllable", guardianControllable);
|
|
+ }
|
|
+
|
|
+ public boolean hoglinRidable = false;
|
|
+ public boolean hoglinRidableInWater = true;
|
|
+ public boolean hoglinControllable = true;
|
|
+ private void hoglinSettings() {
|
|
+ hoglinRidable = getBoolean("mobs.hoglin.ridable", hoglinRidable);
|
|
+ hoglinRidableInWater = getBoolean("mobs.hoglin.ridable-in-water", hoglinRidableInWater);
|
|
+ hoglinControllable = getBoolean("mobs.hoglin.controllable", hoglinControllable);
|
|
+ }
|
|
+
|
|
+ public boolean horseRidableInWater = false;
|
|
+ private void horseSettings() {
|
|
+ horseRidableInWater = getBoolean("mobs.horse.ridable-in-water", horseRidableInWater);
|
|
+ }
|
|
+
|
|
+ public boolean huskRidable = false;
|
|
+ public boolean huskRidableInWater = true;
|
|
+ public boolean huskControllable = true;
|
|
+ private void huskSettings() {
|
|
+ huskRidable = getBoolean("mobs.husk.ridable", huskRidable);
|
|
+ huskRidableInWater = getBoolean("mobs.husk.ridable-in-water", huskRidableInWater);
|
|
+ huskControllable = getBoolean("mobs.husk.controllable", huskControllable);
|
|
+ }
|
|
+
|
|
+ public boolean illusionerRidable = false;
|
|
+ public boolean illusionerRidableInWater = true;
|
|
+ public boolean illusionerControllable = true;
|
|
+ private void illusionerSettings() {
|
|
+ illusionerRidable = getBoolean("mobs.illusioner.ridable", illusionerRidable);
|
|
+ illusionerRidableInWater = getBoolean("mobs.illusioner.ridable-in-water", illusionerRidableInWater);
|
|
+ illusionerControllable = getBoolean("mobs.illusioner.controllable", illusionerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean ironGolemRidable = false;
|
|
+ public boolean ironGolemRidableInWater = true;
|
|
+ public boolean ironGolemControllable = true;
|
|
+ public boolean ironGolemCanSwim = false;
|
|
+ private void ironGolemSettings() {
|
|
+ ironGolemRidable = getBoolean("mobs.iron_golem.ridable", ironGolemRidable);
|
|
+ ironGolemRidableInWater = getBoolean("mobs.iron_golem.ridable-in-water", ironGolemRidableInWater);
|
|
+ ironGolemControllable = getBoolean("mobs.iron_golem.controllable", ironGolemControllable);
|
|
+ ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim);
|
|
+ }
|
|
+
|
|
+ public boolean llamaRidable = false;
|
|
+ public boolean llamaRidableInWater = false;
|
|
+ public boolean llamaControllable = true;
|
|
+ private void llamaSettings() {
|
|
+ llamaRidable = getBoolean("mobs.llama.ridable", llamaRidable);
|
|
+ llamaRidableInWater = getBoolean("mobs.llama.ridable-in-water", llamaRidableInWater);
|
|
+ llamaControllable = getBoolean("mobs.llama.controllable", llamaControllable);
|
|
+ }
|
|
+
|
|
+ public boolean magmaCubeRidable = false;
|
|
+ public boolean magmaCubeRidableInWater = true;
|
|
+ public boolean magmaCubeControllable = true;
|
|
+ private void magmaCubeSettings() {
|
|
+ magmaCubeRidable = getBoolean("mobs.magma_cube.ridable", magmaCubeRidable);
|
|
+ magmaCubeRidableInWater = getBoolean("mobs.magma_cube.ridable-in-water", magmaCubeRidableInWater);
|
|
+ magmaCubeControllable = getBoolean("mobs.magma_cube.controllable", magmaCubeControllable);
|
|
+ }
|
|
+
|
|
+ public boolean mooshroomRidable = false;
|
|
+ public boolean mooshroomRidableInWater = true;
|
|
+ public boolean mooshroomControllable = true;
|
|
+ private void mooshroomSettings() {
|
|
+ mooshroomRidable = getBoolean("mobs.mooshroom.ridable", mooshroomRidable);
|
|
+ mooshroomRidableInWater = getBoolean("mobs.mooshroom.ridable-in-water", mooshroomRidableInWater);
|
|
+ mooshroomControllable = getBoolean("mobs.mooshroom.controllable", mooshroomControllable);
|
|
+ }
|
|
+
|
|
+ public boolean muleRidableInWater = false;
|
|
+ private void muleSettings() {
|
|
+ muleRidableInWater = getBoolean("mobs.mule.ridable-in-water", muleRidableInWater);
|
|
+ }
|
|
+
|
|
+ public boolean ocelotRidable = false;
|
|
+ public boolean ocelotRidableInWater = true;
|
|
+ public boolean ocelotControllable = true;
|
|
+ private void ocelotSettings() {
|
|
+ ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable);
|
|
+ ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater);
|
|
+ ocelotControllable = getBoolean("mobs.ocelot.controllable", ocelotControllable);
|
|
+ }
|
|
+
|
|
+ public boolean pandaRidable = false;
|
|
+ public boolean pandaRidableInWater = true;
|
|
+ public boolean pandaControllable = true;
|
|
+ private void pandaSettings() {
|
|
+ pandaRidable = getBoolean("mobs.panda.ridable", pandaRidable);
|
|
+ pandaRidableInWater = getBoolean("mobs.panda.ridable-in-water", pandaRidableInWater);
|
|
+ pandaControllable = getBoolean("mobs.panda.controllable", pandaControllable);
|
|
+ }
|
|
+
|
|
+ public boolean parrotRidable = false;
|
|
+ public boolean parrotRidableInWater = true;
|
|
+ public boolean parrotControllable = true;
|
|
+ public double parrotMaxY = 320D;
|
|
+ private void parrotSettings() {
|
|
+ parrotRidable = getBoolean("mobs.parrot.ridable", parrotRidable);
|
|
+ parrotRidableInWater = getBoolean("mobs.parrot.ridable-in-water", parrotRidableInWater);
|
|
+ parrotControllable = getBoolean("mobs.parrot.controllable", parrotControllable);
|
|
+ parrotMaxY = getDouble("mobs.parrot.ridable-max-y", parrotMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean phantomRidable = false;
|
|
+ public boolean phantomRidableInWater = true;
|
|
+ public boolean phantomControllable = true;
|
|
+ public double phantomMaxY = 320D;
|
|
+ public float phantomFlameDamage = 1.0F;
|
|
+ public int phantomFlameFireTime = 8;
|
|
+ public boolean phantomAllowGriefing = false;
|
|
+ private void phantomSettings() {
|
|
+ phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
|
|
+ phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
|
|
+ phantomControllable = getBoolean("mobs.phantom.controllable", phantomControllable);
|
|
+ phantomMaxY = getDouble("mobs.phantom.ridable-max-y", phantomMaxY);
|
|
+ phantomFlameDamage = (float) getDouble("mobs.phantom.flames.damage", phantomFlameDamage);
|
|
+ phantomFlameFireTime = getInt("mobs.phantom.flames.fire-time", phantomFlameFireTime);
|
|
+ phantomAllowGriefing = getBoolean("mobs.phantom.allow-griefing", phantomAllowGriefing);
|
|
+ }
|
|
+
|
|
+ public boolean pigRidable = false;
|
|
+ public boolean pigRidableInWater = false;
|
|
+ public boolean pigControllable = true;
|
|
+ private void pigSettings() {
|
|
+ pigRidable = getBoolean("mobs.pig.ridable", pigRidable);
|
|
+ pigRidableInWater = getBoolean("mobs.pig.ridable-in-water", pigRidableInWater);
|
|
+ pigControllable = getBoolean("mobs.pig.controllable", pigControllable);
|
|
+ }
|
|
+
|
|
+ public boolean piglinRidable = false;
|
|
+ public boolean piglinRidableInWater = true;
|
|
+ public boolean piglinControllable = true;
|
|
+ private void piglinSettings() {
|
|
+ piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable);
|
|
+ piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater);
|
|
+ piglinControllable = getBoolean("mobs.piglin.controllable", piglinControllable);
|
|
+ }
|
|
+
|
|
+ public boolean piglinBruteRidable = false;
|
|
+ public boolean piglinBruteRidableInWater = true;
|
|
+ public boolean piglinBruteControllable = true;
|
|
+ private void piglinBruteSettings() {
|
|
+ piglinBruteRidable = getBoolean("mobs.piglin_brute.ridable", piglinBruteRidable);
|
|
+ piglinBruteRidableInWater = getBoolean("mobs.piglin_brute.ridable-in-water", piglinBruteRidableInWater);
|
|
+ piglinBruteControllable = getBoolean("mobs.piglin_brute.controllable", piglinBruteControllable);
|
|
+ }
|
|
+
|
|
+ public boolean pillagerRidable = false;
|
|
+ public boolean pillagerRidableInWater = true;
|
|
+ public boolean pillagerControllable = true;
|
|
+ private void pillagerSettings() {
|
|
+ pillagerRidable = getBoolean("mobs.pillager.ridable", pillagerRidable);
|
|
+ pillagerRidableInWater = getBoolean("mobs.pillager.ridable-in-water", pillagerRidableInWater);
|
|
+ pillagerControllable = getBoolean("mobs.pillager.controllable", pillagerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean polarBearRidable = false;
|
|
+ public boolean polarBearRidableInWater = true;
|
|
+ public boolean polarBearControllable = true;
|
|
+ private void polarBearSettings() {
|
|
+ polarBearRidable = getBoolean("mobs.polar_bear.ridable", polarBearRidable);
|
|
+ polarBearRidableInWater = getBoolean("mobs.polar_bear.ridable-in-water", polarBearRidableInWater);
|
|
+ polarBearControllable = getBoolean("mobs.polar_bear.controllable", polarBearControllable);
|
|
+ }
|
|
+
|
|
+ public boolean pufferfishRidable = false;
|
|
+ public boolean pufferfishControllable = true;
|
|
+ private void pufferfishSettings() {
|
|
+ pufferfishRidable = getBoolean("mobs.pufferfish.ridable", pufferfishRidable);
|
|
+ pufferfishControllable = getBoolean("mobs.pufferfish.controllable", pufferfishControllable);
|
|
+ }
|
|
+
|
|
+ public boolean rabbitRidable = false;
|
|
+ public boolean rabbitRidableInWater = true;
|
|
+ public boolean rabbitControllable = true;
|
|
+ private void rabbitSettings() {
|
|
+ rabbitRidable = getBoolean("mobs.rabbit.ridable", rabbitRidable);
|
|
+ rabbitRidableInWater = getBoolean("mobs.rabbit.ridable-in-water", rabbitRidableInWater);
|
|
+ rabbitControllable = getBoolean("mobs.rabbit.controllable", rabbitControllable);
|
|
+ }
|
|
+
|
|
+ public boolean ravagerRidable = false;
|
|
+ public boolean ravagerRidableInWater = false;
|
|
+ public boolean ravagerControllable = true;
|
|
+ private void ravagerSettings() {
|
|
+ ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable);
|
|
+ ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater);
|
|
+ ravagerControllable = getBoolean("mobs.ravager.controllable", ravagerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean salmonRidable = false;
|
|
+ public boolean salmonControllable = true;
|
|
+ private void salmonSettings() {
|
|
+ salmonRidable = getBoolean("mobs.salmon.ridable", salmonRidable);
|
|
+ salmonControllable = getBoolean("mobs.salmon.controllable", salmonControllable);
|
|
+ }
|
|
+
|
|
+ public boolean sheepRidable = false;
|
|
+ public boolean sheepRidableInWater = true;
|
|
+ public boolean sheepControllable = true;
|
|
+ private void sheepSettings() {
|
|
+ sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable);
|
|
+ sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater);
|
|
+ sheepControllable = getBoolean("mobs.sheep.controllable", sheepControllable);
|
|
+ }
|
|
+
|
|
+ public boolean shulkerRidable = false;
|
|
+ public boolean shulkerRidableInWater = true;
|
|
+ public boolean shulkerControllable = true;
|
|
+ private void shulkerSettings() {
|
|
+ shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable);
|
|
+ shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater);
|
|
+ shulkerControllable = getBoolean("mobs.shulker.controllable", shulkerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean silverfishRidable = false;
|
|
+ public boolean silverfishRidableInWater = true;
|
|
+ public boolean silverfishControllable = true;
|
|
+ private void silverfishSettings() {
|
|
+ silverfishRidable = getBoolean("mobs.silverfish.ridable", silverfishRidable);
|
|
+ silverfishRidableInWater = getBoolean("mobs.silverfish.ridable-in-water", silverfishRidableInWater);
|
|
+ silverfishControllable = getBoolean("mobs.silverfish.controllable", silverfishControllable);
|
|
+ }
|
|
+
|
|
+ public boolean skeletonRidable = false;
|
|
+ public boolean skeletonRidableInWater = true;
|
|
+ public boolean skeletonControllable = true;
|
|
+ private void skeletonSettings() {
|
|
+ skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable);
|
|
+ skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater);
|
|
+ skeletonControllable = getBoolean("mobs.skeleton.controllable", skeletonControllable);
|
|
+ }
|
|
+
|
|
+ public boolean skeletonHorseRidable = false;
|
|
+ public boolean skeletonHorseRidableInWater = true;
|
|
+ public boolean skeletonHorseCanSwim = false;
|
|
+ private void skeletonHorseSettings() {
|
|
+ skeletonHorseRidable = getBoolean("mobs.skeleton_horse.ridable", skeletonHorseRidable);
|
|
+ skeletonHorseRidableInWater = getBoolean("mobs.skeleton_horse.ridable-in-water", skeletonHorseRidableInWater);
|
|
+ skeletonHorseCanSwim = getBoolean("mobs.skeleton_horse.can-swim", skeletonHorseCanSwim);
|
|
+ }
|
|
+
|
|
+ public boolean slimeRidable = false;
|
|
+ public boolean slimeRidableInWater = true;
|
|
+ public boolean slimeControllable = true;
|
|
+ private void slimeSettings() {
|
|
+ slimeRidable = getBoolean("mobs.slime.ridable", slimeRidable);
|
|
+ slimeRidableInWater = getBoolean("mobs.slime.ridable-in-water", slimeRidableInWater);
|
|
+ slimeControllable = getBoolean("mobs.slime.controllable", slimeControllable);
|
|
+ }
|
|
+
|
|
+ public boolean snowGolemRidable = false;
|
|
+ public boolean snowGolemRidableInWater = true;
|
|
+ public boolean snowGolemControllable = true;
|
|
+ public boolean snowGolemLeaveTrailWhenRidden = false;
|
|
+ private void snowGolemSettings() {
|
|
+ snowGolemRidable = getBoolean("mobs.snow_golem.ridable", snowGolemRidable);
|
|
+ snowGolemRidableInWater = getBoolean("mobs.snow_golem.ridable-in-water", snowGolemRidableInWater);
|
|
+ snowGolemControllable = getBoolean("mobs.snow_golem.controllable", snowGolemControllable);
|
|
+ snowGolemLeaveTrailWhenRidden = getBoolean("mobs.snow_golem.leave-trail-when-ridden", snowGolemLeaveTrailWhenRidden);
|
|
+ }
|
|
+
|
|
+ public boolean snifferRidable = false;
|
|
+ public boolean snifferRidableInWater = true;
|
|
+ public boolean snifferControllable = true;
|
|
+ private void snifferSettings() {
|
|
+ snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable);
|
|
+ snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater);
|
|
+ snifferControllable = getBoolean("mobs.sniffer.controllable", snifferControllable);
|
|
+ }
|
|
+
|
|
+ public boolean squidRidable = false;
|
|
+ public boolean squidControllable = true;
|
|
+ private void squidSettings() {
|
|
+ squidRidable = getBoolean("mobs.squid.ridable", squidRidable);
|
|
+ squidControllable = getBoolean("mobs.squid.controllable", squidControllable);
|
|
+ }
|
|
+
|
|
+ public boolean spiderRidable = false;
|
|
+ public boolean spiderRidableInWater = false;
|
|
+ public boolean spiderControllable = true;
|
|
+ private void spiderSettings() {
|
|
+ spiderRidable = getBoolean("mobs.spider.ridable", spiderRidable);
|
|
+ spiderRidableInWater = getBoolean("mobs.spider.ridable-in-water", spiderRidableInWater);
|
|
+ spiderControllable = getBoolean("mobs.spider.controllable", spiderControllable);
|
|
+ }
|
|
+
|
|
+ public boolean strayRidable = false;
|
|
+ public boolean strayRidableInWater = true;
|
|
+ public boolean strayControllable = true;
|
|
+ private void straySettings() {
|
|
+ strayRidable = getBoolean("mobs.stray.ridable", strayRidable);
|
|
+ strayRidableInWater = getBoolean("mobs.stray.ridable-in-water", strayRidableInWater);
|
|
+ strayControllable = getBoolean("mobs.stray.controllable", strayControllable);
|
|
+ }
|
|
+
|
|
+ public boolean striderRidable = false;
|
|
+ public boolean striderRidableInWater = false;
|
|
+ public boolean striderControllable = true;
|
|
+ private void striderSettings() {
|
|
+ striderRidable = getBoolean("mobs.strider.ridable", striderRidable);
|
|
+ striderRidableInWater = getBoolean("mobs.strider.ridable-in-water", striderRidableInWater);
|
|
+ striderControllable = getBoolean("mobs.strider.controllable", striderControllable);
|
|
+ }
|
|
+
|
|
+ public boolean tadpoleRidable = false;
|
|
+ public boolean tadpoleRidableInWater = true;
|
|
+ public boolean tadpoleControllable = true;
|
|
+ private void tadpoleSettings() {
|
|
+ tadpoleRidable = getBoolean("mobs.tadpole.ridable", tadpoleRidable);
|
|
+ tadpoleRidableInWater = getBoolean("mobs.tadpole.ridable-in-water", tadpoleRidableInWater);
|
|
+ tadpoleControllable = getBoolean("mobs.tadpole.controllable", tadpoleControllable);
|
|
+ }
|
|
+
|
|
+ public boolean traderLlamaRidable = false;
|
|
+ public boolean traderLlamaRidableInWater = false;
|
|
+ public boolean traderLlamaControllable = true;
|
|
+ private void traderLlamaSettings() {
|
|
+ traderLlamaRidable = getBoolean("mobs.trader_llama.ridable", traderLlamaRidable);
|
|
+ traderLlamaRidableInWater = getBoolean("mobs.trader_llama.ridable-in-water", traderLlamaRidableInWater);
|
|
+ traderLlamaControllable = getBoolean("mobs.trader_llama.controllable", traderLlamaControllable);
|
|
+ }
|
|
+
|
|
+ public boolean tropicalFishRidable = false;
|
|
+ public boolean tropicalFishControllable = true;
|
|
+ private void tropicalFishSettings() {
|
|
+ tropicalFishRidable = getBoolean("mobs.tropical_fish.ridable", tropicalFishRidable);
|
|
+ tropicalFishControllable = getBoolean("mobs.tropical_fish.controllable", tropicalFishControllable);
|
|
+ }
|
|
+
|
|
+ public boolean turtleRidable = false;
|
|
+ public boolean turtleRidableInWater = true;
|
|
+ public boolean turtleControllable = true;
|
|
+ private void turtleSettings() {
|
|
+ turtleRidable = getBoolean("mobs.turtle.ridable", turtleRidable);
|
|
+ turtleRidableInWater = getBoolean("mobs.turtle.ridable-in-water", turtleRidableInWater);
|
|
+ turtleControllable = getBoolean("mobs.turtle.controllable", turtleControllable);
|
|
+ }
|
|
+
|
|
+ public boolean vexRidable = false;
|
|
+ public boolean vexRidableInWater = true;
|
|
+ public boolean vexControllable = true;
|
|
+ public double vexMaxY = 320D;
|
|
+ private void vexSettings() {
|
|
+ vexRidable = getBoolean("mobs.vex.ridable", vexRidable);
|
|
+ vexRidableInWater = getBoolean("mobs.vex.ridable-in-water", vexRidableInWater);
|
|
+ vexControllable = getBoolean("mobs.vex.controllable", vexControllable);
|
|
+ vexMaxY = getDouble("mobs.vex.ridable-max-y", vexMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean villagerRidable = false;
|
|
+ public boolean villagerRidableInWater = true;
|
|
+ public boolean villagerControllable = true;
|
|
+ private void villagerSettings() {
|
|
+ villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
|
|
+ villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
|
|
+ villagerControllable = getBoolean("mobs.villager.controllable", villagerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean vindicatorRidable = false;
|
|
+ public boolean vindicatorRidableInWater = true;
|
|
+ public boolean vindicatorControllable = true;
|
|
+ private void vindicatorSettings() {
|
|
+ vindicatorRidable = getBoolean("mobs.vindicator.ridable", vindicatorRidable);
|
|
+ vindicatorRidableInWater = getBoolean("mobs.vindicator.ridable-in-water", vindicatorRidableInWater);
|
|
+ vindicatorControllable = getBoolean("mobs.vindicator.controllable", vindicatorControllable);
|
|
+ }
|
|
+
|
|
+ public boolean wanderingTraderRidable = false;
|
|
+ public boolean wanderingTraderRidableInWater = true;
|
|
+ public boolean wanderingTraderControllable = true;
|
|
+ private void wanderingTraderSettings() {
|
|
+ wanderingTraderRidable = getBoolean("mobs.wandering_trader.ridable", wanderingTraderRidable);
|
|
+ wanderingTraderRidableInWater = getBoolean("mobs.wandering_trader.ridable-in-water", wanderingTraderRidableInWater);
|
|
+ wanderingTraderControllable = getBoolean("mobs.wandering_trader.controllable", wanderingTraderControllable);
|
|
+ }
|
|
+
|
|
+ public boolean wardenRidable = false;
|
|
+ public boolean wardenRidableInWater = true;
|
|
+ public boolean wardenControllable = true;
|
|
+ private void wardenSettings() {
|
|
+ wardenRidable = getBoolean("mobs.warden.ridable", wardenRidable);
|
|
+ wardenRidableInWater = getBoolean("mobs.warden.ridable-in-water", wardenRidableInWater);
|
|
+ wardenControllable = getBoolean("mobs.warden.controllable", wardenControllable);
|
|
+ }
|
|
+
|
|
+ public boolean witchRidable = false;
|
|
+ public boolean witchRidableInWater = true;
|
|
+ public boolean witchControllable = true;
|
|
+ private void witchSettings() {
|
|
+ witchRidable = getBoolean("mobs.witch.ridable", witchRidable);
|
|
+ witchRidableInWater = getBoolean("mobs.witch.ridable-in-water", witchRidableInWater);
|
|
+ witchControllable = getBoolean("mobs.witch.controllable", witchControllable);
|
|
+ }
|
|
+
|
|
+ public boolean witherRidable = false;
|
|
+ public boolean witherRidableInWater = true;
|
|
+ public boolean witherControllable = true;
|
|
+ public double witherMaxY = 320D;
|
|
+ private void witherSettings() {
|
|
+ witherRidable = getBoolean("mobs.wither.ridable", witherRidable);
|
|
+ witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater);
|
|
+ witherControllable = getBoolean("mobs.wither.controllable", witherControllable);
|
|
+ witherMaxY = getDouble("mobs.wither.ridable-max-y", witherMaxY);
|
|
+ }
|
|
+
|
|
+ public boolean witherSkeletonRidable = false;
|
|
+ public boolean witherSkeletonRidableInWater = true;
|
|
+ public boolean witherSkeletonControllable = true;
|
|
+ private void witherSkeletonSettings() {
|
|
+ witherSkeletonRidable = getBoolean("mobs.wither_skeleton.ridable", witherSkeletonRidable);
|
|
+ witherSkeletonRidableInWater = getBoolean("mobs.wither_skeleton.ridable-in-water", witherSkeletonRidableInWater);
|
|
+ witherSkeletonControllable = getBoolean("mobs.wither_skeleton.controllable", witherSkeletonControllable);
|
|
+ }
|
|
+
|
|
+ public boolean wolfRidable = false;
|
|
+ public boolean wolfRidableInWater = true;
|
|
+ public boolean wolfControllable = true;
|
|
+ private void wolfSettings() {
|
|
+ wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable);
|
|
+ wolfRidableInWater = getBoolean("mobs.wolf.ridable-in-water", wolfRidableInWater);
|
|
+ wolfControllable = getBoolean("mobs.wolf.controllable", wolfControllable);
|
|
+ }
|
|
+
|
|
+ public boolean zoglinRidable = false;
|
|
+ public boolean zoglinRidableInWater = true;
|
|
+ public boolean zoglinControllable = true;
|
|
+ private void zoglinSettings() {
|
|
+ zoglinRidable = getBoolean("mobs.zoglin.ridable", zoglinRidable);
|
|
+ zoglinRidableInWater = getBoolean("mobs.zoglin.ridable-in-water", zoglinRidableInWater);
|
|
+ zoglinControllable = getBoolean("mobs.zoglin.controllable", zoglinControllable);
|
|
+ }
|
|
+
|
|
+ public boolean zombieRidable = false;
|
|
+ public boolean zombieRidableInWater = true;
|
|
+ public boolean zombieControllable = true;
|
|
+ private void zombieSettings() {
|
|
+ zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
|
|
+ zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
|
|
+ zombieControllable = getBoolean("mobs.zombie.controllable", zombieControllable);
|
|
+ }
|
|
+
|
|
+ public boolean zombieHorseRidable = false;
|
|
+ public boolean zombieHorseRidableInWater = false;
|
|
+ public boolean zombieHorseCanSwim = false;
|
|
+ private void zombieHorseSettings() {
|
|
+ zombieHorseRidable = getBoolean("mobs.zombie_horse.ridable", zombieHorseRidable);
|
|
+ zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater);
|
|
+ zombieHorseCanSwim = getBoolean("mobs.zombie_horse.can-swim", zombieHorseCanSwim);
|
|
+ }
|
|
+
|
|
+ public boolean zombieVillagerRidable = false;
|
|
+ public boolean zombieVillagerRidableInWater = true;
|
|
+ public boolean zombieVillagerControllable = true;
|
|
+ private void zombieVillagerSettings() {
|
|
+ zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
|
|
+ zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
|
|
+ zombieVillagerControllable = getBoolean("mobs.zombie_villager.controllable", zombieVillagerControllable);
|
|
+ }
|
|
+
|
|
+ public boolean zombifiedPiglinRidable = false;
|
|
+ public boolean zombifiedPiglinRidableInWater = true;
|
|
+ public boolean zombifiedPiglinControllable = true;
|
|
+ private void zombifiedPiglinSettings() {
|
|
+ zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable);
|
|
+ zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater);
|
|
+ zombifiedPiglinControllable = getBoolean("mobs.zombified_piglin.controllable", zombifiedPiglinControllable);
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ed494e0ad278813a0eb261101447b84cca3ad7aa
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/controller/FlyingMoveControllerWASD.java
|
|
@@ -0,0 +1,71 @@
|
|
+package org.purpurmc.purpur.controller;
|
|
+
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+
|
|
+public class FlyingMoveControllerWASD extends MoveControllerWASD {
|
|
+ protected final float groundSpeedModifier;
|
|
+ protected final float flyingSpeedModifier;
|
|
+ protected int tooHighCooldown = 0;
|
|
+ protected boolean setNoGravityFlag;
|
|
+
|
|
+ public FlyingMoveControllerWASD(Mob entity) {
|
|
+ this(entity, 1.0F);
|
|
+ }
|
|
+
|
|
+ public FlyingMoveControllerWASD(Mob entity, float groundSpeedModifier) {
|
|
+ this(entity, groundSpeedModifier, 1.0F, true);
|
|
+ }
|
|
+
|
|
+ public FlyingMoveControllerWASD(Mob entity, float groundSpeedModifier, float flyingSpeedModifier) {
|
|
+ this(entity, groundSpeedModifier, flyingSpeedModifier, true);
|
|
+ }
|
|
+
|
|
+ public FlyingMoveControllerWASD(Mob entity, float groundSpeedModifier, float flyingSpeedModifier, boolean setNoGravityFlag) {
|
|
+ super(entity);
|
|
+ this.groundSpeedModifier = groundSpeedModifier;
|
|
+ this.flyingSpeedModifier = flyingSpeedModifier;
|
|
+ this.setNoGravityFlag = setNoGravityFlag;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void purpurTick(Player rider) {
|
|
+ float forward = Math.max(0.0F, rider.getForwardMot());
|
|
+ float vertical = forward == 0.0F ? 0.0F : -(rider.xRotO / 45.0F);
|
|
+ float strafe = rider.getStrafeMot();
|
|
+
|
|
+ if (rider.jumping && spacebarEvent(entity)) {
|
|
+ entity.onSpacebar();
|
|
+ }
|
|
+
|
|
+ if (entity.getY() >= entity.getMaxY() || --tooHighCooldown > 0) {
|
|
+ if (tooHighCooldown <= 0) {
|
|
+ tooHighCooldown = 20;
|
|
+ }
|
|
+ entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, -0.05D, 0.0D));
|
|
+ vertical = 0.0F;
|
|
+ }
|
|
+
|
|
+ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float speed = (float) getSpeedModifier();
|
|
+
|
|
+ if (entity.onGround) {
|
|
+ speed *= groundSpeedModifier; // TODO = fix this!
|
|
+ } else {
|
|
+ speed *= flyingSpeedModifier;
|
|
+ }
|
|
+
|
|
+ if (setNoGravityFlag) {
|
|
+ entity.setNoGravity(forward > 0);
|
|
+ }
|
|
+
|
|
+ entity.setSpeed(speed);
|
|
+ entity.setVerticalMot(vertical);
|
|
+ entity.setStrafeMot(strafe);
|
|
+ entity.setForwardMot(forward);
|
|
+
|
|
+ setForward(entity.getForwardMot());
|
|
+ setStrafe(entity.getStrafeMot());
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..9383c07fa53141127106a1f289366a040960d52e
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/controller/FlyingWithSpacebarMoveControllerWASD.java
|
|
@@ -0,0 +1,63 @@
|
|
+package org.purpurmc.purpur.controller;
|
|
+
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+import net.minecraft.world.phys.Vec3;
|
|
+
|
|
+public class FlyingWithSpacebarMoveControllerWASD extends FlyingMoveControllerWASD {
|
|
+ public FlyingWithSpacebarMoveControllerWASD(Mob entity) {
|
|
+ super(entity);
|
|
+ }
|
|
+
|
|
+ public FlyingWithSpacebarMoveControllerWASD(Mob entity, float groundSpeedModifier) {
|
|
+ super(entity, groundSpeedModifier);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void purpurTick(Player rider) {
|
|
+ float forward = rider.getForwardMot();
|
|
+ float strafe = rider.getStrafeMot() * 0.5F;
|
|
+ float vertical = 0;
|
|
+
|
|
+ if (forward < 0.0F) {
|
|
+ forward *= 0.5F;
|
|
+ strafe *= 0.5F;
|
|
+ }
|
|
+
|
|
+ float speed = (float) entity.getAttributeValue(Attributes.MOVEMENT_SPEED);
|
|
+
|
|
+ if (entity.onGround) {
|
|
+ speed *= groundSpeedModifier;
|
|
+ }
|
|
+
|
|
+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar()) {
|
|
+ entity.setNoGravity(true);
|
|
+ vertical = 1.0F;
|
|
+ } else {
|
|
+ entity.setNoGravity(false);
|
|
+ }
|
|
+
|
|
+ if (entity.getY() >= entity.getMaxY() || --tooHighCooldown > 0) {
|
|
+ if (tooHighCooldown <= 0) {
|
|
+ tooHighCooldown = 20;
|
|
+ }
|
|
+ entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, -0.2D, 0.0D));
|
|
+ vertical = 0.0F;
|
|
+ }
|
|
+
|
|
+ setSpeedModifier(speed);
|
|
+ entity.setSpeed((float) getSpeedModifier());
|
|
+ entity.setVerticalMot(vertical);
|
|
+ entity.setStrafeMot(strafe);
|
|
+ entity.setForwardMot(forward);
|
|
+
|
|
+ setForward(entity.getForwardMot());
|
|
+ setStrafe(entity.getStrafeMot());
|
|
+
|
|
+ Vec3 mot = entity.getDeltaMovement();
|
|
+ if (mot.y > 0.2D) {
|
|
+ entity.setDeltaMovement(mot.x, 0.2D, mot.z);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b8c25c96e95dd5ec3ad9fa4c41bd6c08e144832d
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/controller/LookControllerWASD.java
|
|
@@ -0,0 +1,76 @@
|
|
+package org.purpurmc.purpur.controller;
|
|
+
|
|
+
|
|
+import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
|
|
+import net.minecraft.util.Mth;
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.control.LookControl;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+
|
|
+public class LookControllerWASD extends LookControl {
|
|
+ protected final Mob entity;
|
|
+ private float yOffset = 0;
|
|
+ private float xOffset = 0;
|
|
+
|
|
+ public LookControllerWASD(Mob entity) {
|
|
+ super(entity);
|
|
+ this.entity = entity;
|
|
+ }
|
|
+
|
|
+ // tick
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (entity.getRider() != null && entity.isControllable()) {
|
|
+ purpurTick(entity.getRider());
|
|
+ } else {
|
|
+ vanillaTick();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected void purpurTick(Player rider) {
|
|
+ setYawPitch(rider.getYRot(), rider.getXRot());
|
|
+ }
|
|
+
|
|
+ public void vanillaTick() {
|
|
+ super.tick();
|
|
+ }
|
|
+
|
|
+ public void setYawPitch(float yRot, float xRot) {
|
|
+ entity.setXRot(normalizePitch(xRot + xOffset));
|
|
+ entity.setYRot(normalizeYaw(yRot + yOffset));
|
|
+ entity.setYHeadRot(entity.getYRot());
|
|
+ entity.xRotO = entity.getXRot();
|
|
+ entity.yRotO = entity.getYRot();
|
|
+
|
|
+ entity.tracker.broadcast(new ClientboundMoveEntityPacket
|
|
+ .PosRot(entity.getId(),
|
|
+ (short) 0, (short) 0, (short) 0,
|
|
+ (byte) Mth.floor(entity.getYRot() * 256.0F / 360.0F),
|
|
+ (byte) Mth.floor(entity.getXRot() * 256.0F / 360.0F),
|
|
+ entity.onGround));
|
|
+ }
|
|
+
|
|
+ public void setOffsets(float yaw, float pitch) {
|
|
+ yOffset = yaw;
|
|
+ xOffset = 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/org/purpurmc/purpur/controller/MoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..21fd6ea2a482758a3016e3bc2cdebe2d89267481
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java
|
|
@@ -0,0 +1,89 @@
|
|
+package org.purpurmc.purpur.controller;
|
|
+
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
+import net.minecraft.world.entity.ai.control.MoveControl;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+import org.purpurmc.purpur.event.entity.RidableSpacebarEvent;
|
|
+
|
|
+public class MoveControllerWASD extends MoveControl {
|
|
+ protected final Mob entity;
|
|
+ private final double speedModifier;
|
|
+
|
|
+ public MoveControllerWASD(Mob entity) {
|
|
+ this(entity, 1.0D);
|
|
+ }
|
|
+
|
|
+ public MoveControllerWASD(Mob entity, double speedModifier) {
|
|
+ super(entity);
|
|
+ this.entity = entity;
|
|
+ this.speedModifier = speedModifier;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasWanted() {
|
|
+ return entity.getRider() != null ? strafeForwards != 0 || strafeRight != 0 : super.hasWanted();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void tick() {
|
|
+ if (entity.getRider() != null && entity.isControllable()) {
|
|
+ purpurTick(entity.getRider());
|
|
+ } else {
|
|
+ vanillaTick();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void vanillaTick() {
|
|
+ super.tick();
|
|
+ }
|
|
+
|
|
+ public void purpurTick(Player rider) {
|
|
+ float forward = rider.getForwardMot() * 0.5F;
|
|
+ float strafe = rider.getStrafeMot() * 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;
|
|
+ }
|
|
+
|
|
+ ((LookControllerWASD) entity.getLookControl()).setOffsets(yawOffset, 0);
|
|
+
|
|
+ if (rider.jumping && spacebarEvent(entity) && !entity.onSpacebar() && entity.onGround) {
|
|
+ entity.jumpFromGround();
|
|
+ }
|
|
+
|
|
+ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED) * speedModifier);
|
|
+
|
|
+ entity.setSpeed((float) getSpeedModifier());
|
|
+ entity.setForwardMot(forward);
|
|
+
|
|
+ setForward(entity.getForwardMot());
|
|
+ setStrafe(entity.getStrafeMot());
|
|
+ }
|
|
+
|
|
+ public static boolean spacebarEvent(Mob entity) {
|
|
+ if (RidableSpacebarEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
|
+ return new RidableSpacebarEvent(entity.getBukkitEntity()).callEvent();
|
|
+ } else {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ba2a37dad43e238e54632975abea8ee6fafaa9e0
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/controller/WaterMoveControllerWASD.java
|
|
@@ -0,0 +1,50 @@
|
|
+package org.purpurmc.purpur.controller;
|
|
+
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+
|
|
+public class WaterMoveControllerWASD extends MoveControllerWASD {
|
|
+ private final double speedModifier;
|
|
+
|
|
+ public WaterMoveControllerWASD(Mob entity) {
|
|
+ this(entity, 1.0D);
|
|
+ }
|
|
+
|
|
+ public WaterMoveControllerWASD(Mob entity, double speedModifier) {
|
|
+ super(entity);
|
|
+ this.speedModifier = speedModifier;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void purpurTick(Player rider) {
|
|
+ float forward = rider.getForwardMot();
|
|
+ float strafe = rider.getStrafeMot() * 0.5F; // strafe slower by default
|
|
+ float vertical = -(rider.xRotO / 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();
|
|
+ }
|
|
+
|
|
+ setSpeedModifier(entity.getAttributeValue(Attributes.MOVEMENT_SPEED) * speedModifier);
|
|
+ entity.setSpeed((float) getSpeedModifier() * 0.1F);
|
|
+
|
|
+ entity.setForwardMot(forward * (float) speedModifier);
|
|
+ entity.setStrafeMot(strafe * (float) speedModifier);
|
|
+ entity.setVerticalMot(vertical * (float) speedModifier);
|
|
+
|
|
+ setForward(entity.getForwardMot());
|
|
+ setStrafe(entity.getStrafeMot());
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java b/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..89c476c740b4efb4f44c1dcd384b908626d96780
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/entity/DolphinSpit.java
|
|
@@ -0,0 +1,100 @@
|
|
+package org.purpurmc.purpur.entity;
|
|
+
|
|
+import net.minecraft.core.particles.ParticleTypes;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.util.Mth;
|
|
+import net.minecraft.world.damagesource.DamageSource;
|
|
+import net.minecraft.world.entity.Entity;
|
|
+import net.minecraft.world.entity.EntityType;
|
|
+import net.minecraft.world.entity.LivingEntity;
|
|
+import net.minecraft.world.entity.animal.Dolphin;
|
|
+import net.minecraft.world.entity.projectile.LlamaSpit;
|
|
+import net.minecraft.world.entity.projectile.ProjectileUtil;
|
|
+import net.minecraft.world.level.Level;
|
|
+import net.minecraft.world.level.block.state.BlockState;
|
|
+import net.minecraft.world.phys.BlockHitResult;
|
|
+import net.minecraft.world.phys.EntityHitResult;
|
|
+import net.minecraft.world.phys.HitResult;
|
|
+import net.minecraft.world.phys.Vec3;
|
|
+import org.bukkit.event.entity.EntityRemoveEvent;
|
|
+
|
|
+public class DolphinSpit extends LlamaSpit {
|
|
+ public LivingEntity dolphin;
|
|
+ public int ticksLived;
|
|
+
|
|
+ public DolphinSpit(EntityType<? extends LlamaSpit> type, Level world) {
|
|
+ super(type, world);
|
|
+ }
|
|
+
|
|
+ public DolphinSpit(Level world, Dolphin dolphin) {
|
|
+ this(EntityType.LLAMA_SPIT, world);
|
|
+ setOwner(dolphin.getRider() != null ? dolphin.getRider() : dolphin);
|
|
+ this.dolphin = dolphin;
|
|
+ this.setPos(
|
|
+ dolphin.getX() - (double) (dolphin.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(dolphin.yBodyRot * 0.017453292F),
|
|
+ dolphin.getEyeY() - 0.10000000149011612D,
|
|
+ dolphin.getZ() + (double) (dolphin.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(dolphin.yBodyRot * 0.017453292F));
|
|
+ }
|
|
+
|
|
+ public void tick() {
|
|
+ super_tick();
|
|
+
|
|
+ Vec3 mot = this.getDeltaMovement();
|
|
+ HitResult hitResult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity);
|
|
+
|
|
+ this.preHitTargetOrDeflectSelf(hitResult);
|
|
+
|
|
+ double x = this.getX() + mot.x;
|
|
+ double y = this.getY() + mot.y;
|
|
+ double z = this.getZ() + mot.z;
|
|
+
|
|
+ this.updateRotation();
|
|
+
|
|
+ Vec3 motDouble = mot.scale(2.0);
|
|
+ for (int i = 0; i < 5; i++) {
|
|
+ ((ServerLevel) level()).sendParticles(null, ParticleTypes.BUBBLE,
|
|
+ getX() + random.nextFloat() / 2 - 0.25F,
|
|
+ getY() + random.nextFloat() / 2 - 0.25F,
|
|
+ getZ() + random.nextFloat() / 2 - 0.25F,
|
|
+ 0, motDouble.x(), motDouble.y(), motDouble.z(), 0.1D, true);
|
|
+ }
|
|
+
|
|
+ if (++ticksLived > 20) {
|
|
+ this.discard(EntityRemoveEvent.Cause.DISCARD);
|
|
+ } else {
|
|
+ this.setDeltaMovement(mot.scale(0.99D));
|
|
+ if (!this.isNoGravity()) {
|
|
+ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.06D, 0.0D));
|
|
+ }
|
|
+
|
|
+ this.setPos(x, y, z);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void shoot(double x, double y, double z, float speed, float inaccuracy) {
|
|
+ setDeltaMovement(new Vec3(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));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void onHitEntity(EntityHitResult entityHitResult) {
|
|
+ Entity shooter = this.getOwner();
|
|
+ if (shooter instanceof LivingEntity) {
|
|
+ entityHitResult.getEntity().hurt(entityHitResult.getEntity().damageSources().mobProjectile(this, (LivingEntity) shooter), level().purpurConfig.dolphinSpitDamage);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void onHitBlock(BlockHitResult blockHitResult) {
|
|
+ if (this.hitCancelled) {
|
|
+ return;
|
|
+ }
|
|
+ BlockState state = this.level().getBlockState(blockHitResult.getBlockPos());
|
|
+ state.onProjectileHit(this.level(), state, blockHitResult, this);
|
|
+ this.discard(EntityRemoveEvent.Cause.DISCARD);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..c0b7e0eeffdf31b88662232b07944bf3e6fa2148
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java
|
|
@@ -0,0 +1,114 @@
|
|
+package org.purpurmc.purpur.entity;
|
|
+
|
|
+import net.minecraft.core.particles.ParticleTypes;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.util.Mth;
|
|
+import net.minecraft.world.damagesource.DamageSource;
|
|
+import net.minecraft.world.entity.Entity;
|
|
+import net.minecraft.world.entity.EntityType;
|
|
+import net.minecraft.world.entity.LivingEntity;
|
|
+import net.minecraft.world.entity.decoration.ArmorStand;
|
|
+import net.minecraft.world.entity.monster.Phantom;
|
|
+import net.minecraft.world.entity.projectile.LlamaSpit;
|
|
+import net.minecraft.world.entity.projectile.ProjectileUtil;
|
|
+import net.minecraft.world.level.Level;
|
|
+import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
+import net.minecraft.world.level.block.state.BlockState;
|
|
+import net.minecraft.world.phys.BlockHitResult;
|
|
+import net.minecraft.world.phys.EntityHitResult;
|
|
+import net.minecraft.world.phys.HitResult;
|
|
+import net.minecraft.world.phys.Vec3;
|
|
+
|
|
+public class PhantomFlames extends LlamaSpit {
|
|
+ public Phantom phantom;
|
|
+ public int ticksLived;
|
|
+ public boolean canGrief = false;
|
|
+
|
|
+ public PhantomFlames(EntityType<? extends LlamaSpit> type, Level world) {
|
|
+ super(type, world);
|
|
+ }
|
|
+
|
|
+ public PhantomFlames(Level world, Phantom phantom) {
|
|
+ this(EntityType.LLAMA_SPIT, world);
|
|
+ setOwner(phantom.getRider() != null ? phantom.getRider() : phantom);
|
|
+ this.phantom = phantom;
|
|
+ this.setPos(
|
|
+ phantom.getX() - (double) (phantom.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(phantom.yBodyRot * 0.017453292F),
|
|
+ phantom.getEyeY() - 0.10000000149011612D,
|
|
+ phantom.getZ() + (double) (phantom.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(phantom.yBodyRot * 0.017453292F));
|
|
+ }
|
|
+
|
|
+ public void tick() {
|
|
+ super_tick();
|
|
+
|
|
+ Vec3 mot = this.getDeltaMovement();
|
|
+ HitResult hitResult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity);
|
|
+
|
|
+ this.preHitTargetOrDeflectSelf(hitResult);
|
|
+
|
|
+ double x = this.getX() + mot.x;
|
|
+ double y = this.getY() + mot.y;
|
|
+ double z = this.getZ() + mot.z;
|
|
+
|
|
+ this.updateRotation();
|
|
+
|
|
+ Vec3 motDouble = mot.scale(2.0);
|
|
+ for (int i = 0; i < 5; i++) {
|
|
+ ((ServerLevel) level()).sendParticles(null, ParticleTypes.FLAME,
|
|
+ getX() + random.nextFloat() / 2 - 0.25F,
|
|
+ getY() + random.nextFloat() / 2 - 0.25F,
|
|
+ getZ() + random.nextFloat() / 2 - 0.25F,
|
|
+ 0, motDouble.x(), motDouble.y(), motDouble.z(), 0.1D, true);
|
|
+ }
|
|
+
|
|
+ if (++ticksLived > 20) {
|
|
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
|
+ } else if (this.level().getBlockStates(this.getBoundingBox()).noneMatch(BlockBehaviour.BlockStateBase::isAir)) {
|
|
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
|
+ } else if (this.isInWaterOrBubble()) {
|
|
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
|
+ } else {
|
|
+ this.setDeltaMovement(mot.scale(0.99D));
|
|
+ if (!this.isNoGravity()) {
|
|
+ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.06D, 0.0D));
|
|
+ }
|
|
+
|
|
+ this.setPos(x, y, z);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void shoot(double x, double y, double z, float speed, float inaccuracy) {
|
|
+ setDeltaMovement(new Vec3(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));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void onHitEntity(EntityHitResult entityHitResult) {
|
|
+ Entity shooter = this.getOwner();
|
|
+ if (shooter instanceof LivingEntity) {
|
|
+ Entity target = entityHitResult.getEntity();
|
|
+ if (canGrief || (target instanceof LivingEntity && !(target instanceof ArmorStand))) {
|
|
+ boolean hurt = target.hurt(target.damageSources().mobProjectile(this, (LivingEntity) shooter), level().purpurConfig.phantomFlameDamage);
|
|
+ if (hurt && level().purpurConfig.phantomFlameFireTime > 0) {
|
|
+ target.igniteForSeconds(level().purpurConfig.phantomFlameFireTime);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void onHitBlock(BlockHitResult blockHitResult) {
|
|
+ if (this.hitCancelled) {
|
|
+ return;
|
|
+ }
|
|
+ if (this.canGrief) {
|
|
+ BlockState state = this.level().getBlockState(blockHitResult.getBlockPos());
|
|
+ state.onProjectileHit(this.level(), state, blockHitResult, this);
|
|
+ }
|
|
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..8babdaddd8b33278aea0369dbbeeb445abe45016
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/entity/ai/HasRider.java
|
|
@@ -0,0 +1,20 @@
|
|
+package org.purpurmc.purpur.entity.ai;
|
|
+
|
|
+import net.minecraft.world.entity.Mob;
|
|
+import net.minecraft.world.entity.ai.goal.Goal;
|
|
+
|
|
+import java.util.EnumSet;
|
|
+
|
|
+public class HasRider extends Goal {
|
|
+ public final Mob entity;
|
|
+
|
|
+ public HasRider(Mob entity) {
|
|
+ this.entity = entity;
|
|
+ setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.TARGET, Flag.UNKNOWN_BEHAVIOR));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canUse() {
|
|
+ return entity.getRider() != null && entity.isControllable();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..432f4f3d82af2f19820890b68d33189a9f2c69f9
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/entity/ai/HorseHasRider.java
|
|
@@ -0,0 +1,17 @@
|
|
+package org.purpurmc.purpur.entity.ai;
|
|
+
|
|
+import net.minecraft.world.entity.animal.horse.AbstractHorse;
|
|
+
|
|
+public class HorseHasRider extends HasRider {
|
|
+ public final AbstractHorse horse;
|
|
+
|
|
+ public HorseHasRider(AbstractHorse entity) {
|
|
+ super(entity);
|
|
+ this.horse = entity;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canUse() {
|
|
+ return super.canUse() && horse.isSaddled();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java b/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..18a95e043cbffa65eeaaf65ff7695e5dc939820c
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/purpurmc/purpur/entity/ai/LlamaHasRider.java
|
|
@@ -0,0 +1,17 @@
|
|
+package org.purpurmc.purpur.entity.ai;
|
|
+
|
|
+import net.minecraft.world.entity.animal.horse.Llama;
|
|
+
|
|
+public class LlamaHasRider extends HasRider {
|
|
+ public final Llama llama;
|
|
+
|
|
+ public LlamaHasRider(Llama entity) {
|
|
+ super(entity);
|
|
+ this.llama = entity;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canUse() {
|
|
+ return super.canUse() && llama.isSaddled() && llama.isControllable();
|
|
+ }
|
|
+}
|