mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-06-21 17:57:50 +02:00
5250 lines
243 KiB
Diff
5250 lines
243 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/net/minecraft/gametest/framework/GameTestHelper.java b/net/minecraft/gametest/framework/GameTestHelper.java
|
|
index 33bc4b330abf8745a379eff0d79aabd2a1b7cd40..772136351beb00825388f79e66f3e0532794e939 100644
|
|
--- a/net/minecraft/gametest/framework/GameTestHelper.java
|
|
+++ b/net/minecraft/gametest/framework/GameTestHelper.java
|
|
@@ -354,6 +354,8 @@ public class GameTestHelper {
|
|
|
|
public void setAfk(final boolean afk) {} // Purpur - AFK API
|
|
|
|
+ public void resetLastActionTime() {} // Purpur - Ridables
|
|
+
|
|
@Override
|
|
public boolean isClientAuthoritative() {
|
|
return false;
|
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
index c26dd9cdd6fb0dcecc6a166dd71167c4a88a3d91..838898572cc30207a1b915dcea11f612254ac453 100644
|
|
--- a/net/minecraft/server/MinecraftServer.java
|
|
+++ b/net/minecraft/server/MinecraftServer.java
|
|
@@ -1866,6 +1866,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
for (ServerLevel level : this.getAllLevels()) {
|
|
level.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
|
level.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
|
+ level.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - Ridables
|
|
level.updateLagCompensationTick(); // Paper - lag compensation
|
|
net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = level.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
|
profiler.push(() -> level + " " + level.dimension().identifier());
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index 316fece122a3b71b5c809ed15c46c8cb37d1cdbf..ba1dba4903c8d3c023e9555af67e5d62ac3b3f55 100644
|
|
--- a/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
|
@@ -236,6 +236,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
|
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 - Ridables
|
|
|
|
@Override
|
|
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
|
index 3b655453f22be6eb65ea8b32f79e9d9b953120ee..228c81791dcc1ea0971e70bcb0cb289106466c67 100644
|
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -776,6 +776,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
this.trackEnteredOrExitedLavaOnVehicle();
|
|
this.updatePlayerAttributes();
|
|
this.advancements.flushDirty(this, true);
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
}
|
|
|
|
private void updatePlayerAttributes() {
|
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index cf05034e3f37508466c61a41533e3f6c3ef2e3a5..3671945aa5d94052629c97dfbf6de581c9b20d04 100644
|
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -3002,6 +3002,8 @@ public class ServerGamePacketListenerImpl
|
|
ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event);
|
|
final boolean resendData = event.isCancelled() || !ServerGamePacketListenerImpl.this.player.getItemInHand(hand).is(itemType);
|
|
|
|
+ player.processClick(hand); // Purpur - Ridables
|
|
+
|
|
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859
|
|
if (itemType == Items.WATER_BUCKET && target instanceof net.minecraft.world.entity.animal.Bucketable && target instanceof LivingEntity && resendData) {
|
|
target.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it
|
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
|
index a4a0683c0287da0543a5c869163c925f899b1550..241ff14c2c27204fc8615b19700f946afdcfa2d1 100644
|
|
--- a/net/minecraft/world/entity/Entity.java
|
|
+++ b/net/minecraft/world/entity/Entity.java
|
|
@@ -3400,6 +3400,13 @@ public abstract class Entity
|
|
|
|
this.passengers = ImmutableList.copyOf(newPassengers);
|
|
}
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ if (isRidable() && this.passengers.get(0) == passenger && passenger instanceof Player player) {
|
|
+ onMount(player);
|
|
+ this.rider = player;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
|
|
// Paper start - Force entity dismount during teleportation
|
|
@@ -3440,6 +3447,14 @@ public abstract class Entity
|
|
return false;
|
|
}
|
|
// CraftBukkit end
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ if (this.rider != null && this.passengers.get(0) == this.rider) {
|
|
+ onDismount(this.rider);
|
|
+ this.rider = null;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) {
|
|
this.passengers = ImmutableList.of();
|
|
} else {
|
|
@@ -5419,4 +5434,44 @@ public abstract class Entity
|
|
return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition());
|
|
}
|
|
// Paper end - Expose entity id counter
|
|
+ // Purpur start - Ridables
|
|
+ @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);
|
|
+ ((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 - Ridables
|
|
}
|
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
|
index aecec886b7fc1eed340fdae1074f229fd49f06ee..bb6dc165d393a527564810e0cd2f8137e5272b9e 100644
|
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
|
@@ -243,9 +243,9 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
protected int noActionTime;
|
|
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 final InterpolationHandler interpolation = new InterpolationHandler(this);
|
|
protected double lerpYHeadRot;
|
|
protected int lerpHeadSteps;
|
|
@@ -295,7 +295,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
|
|
protected LivingEntity(final EntityType<? extends LivingEntity> type, final Level level) {
|
|
super(type, level);
|
|
- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type));
|
|
+ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur - Ridables
|
|
this.craftAttributes = new org.bukkit.craftbukkit.attribute.CraftAttributeMap(this.attributes); // CraftBukkit
|
|
// CraftBukkit - this.setHealth(this.getMaxHealth()) inlined and simplified to skip the instanceof check for Player, as getBukkitEntity() is not initialized in constructor
|
|
this.entityData.set(LivingEntity.DATA_HEALTH_ID, this.getMaxHealth());
|
|
@@ -365,6 +365,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
.add(Attributes.CAMERA_DISTANCE)
|
|
.add(Attributes.WAYPOINT_TRANSMIT_RANGE);
|
|
}
|
|
+ public boolean shouldSendAttribute(Attribute attribute) { return true; } // Purpur - Ridables
|
|
|
|
@Override
|
|
protected void checkFallDamage(final double ya, final boolean onGround, final BlockState onState, final BlockPos pos) {
|
|
@@ -3158,6 +3159,20 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.5));
|
|
} else {
|
|
+ // Purpur start - Ridables
|
|
+ if (this.getRider() != null && this.isControllable()) {
|
|
+ float friction = 0.91F;
|
|
+ if (this.onGround()) {
|
|
+ friction = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F;
|
|
+ }
|
|
+
|
|
+ float frictionCompensation = 0.16277137F / (friction * friction * friction);
|
|
+ this.moveRelative(this.onGround() ? 0.1F * frictionCompensation : 0.02F, input);
|
|
+ this.move(MoverType.SELF, this.getDeltaMovement());
|
|
+ this.setDeltaMovement(this.getDeltaMovement().scale(friction));
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
this.moveRelative(airSpeed, input);
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.91F));
|
|
@@ -3862,8 +3877,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
this.pushEntities();
|
|
profiler.pop();
|
|
// Paper start - Add EntityMoveEvent
|
|
- if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof Player)) {
|
|
- if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) {
|
|
+ // Purpur start - Ridables
|
|
+ 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 Player)) {
|
|
+ // Purpur end - Ridables
|
|
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());
|
|
@@ -3873,6 +3890,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
|
this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch());
|
|
}
|
|
}
|
|
+ // Purpur start - Ridables
|
|
+ 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(), (org.bukkit.entity.Player) getRider().getBukkitEntity(), from, to.clone());
|
|
+ if (!event.callEvent()) {
|
|
+ this.absSnapTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch());
|
|
+ } else if (!to.equals(event.getTo())) {
|
|
+ this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
// Paper end - Add EntityMoveEvent
|
|
if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) {
|
|
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
|
index 6916de6628676fc775ab4dda949ebb7facdf58b2..d9c5d2e1c638370434e52422c9643c3521f1bb42 100644
|
|
--- a/net/minecraft/world/entity/Mob.java
|
|
+++ b/net/minecraft/world/entity/Mob.java
|
|
@@ -156,8 +156,8 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
|
super(type, level);
|
|
this.goalSelector = new GoalSelector();
|
|
this.targetSelector = new GoalSelector();
|
|
- this.lookControl = new LookControl(this);
|
|
- this.moveControl = new MoveControl(this);
|
|
+ this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this); // Purpur - Ridables
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this); // Purpur - Ridables
|
|
this.jumpControl = new JumpControl(this);
|
|
this.bodyRotationControl = this.createBodyControl();
|
|
this.navigation = this.createNavigation(level);
|
|
@@ -603,6 +603,7 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
|
}
|
|
}
|
|
} else {
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - Ridables
|
|
this.igniteForSeconds(8.0F);
|
|
}
|
|
}
|
|
@@ -1362,7 +1363,7 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
|
}
|
|
|
|
protected InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
|
|
protected void usePlayerItem(final Player player, final InteractionHand hand, final ItemStack itemStack) {
|
|
@@ -1705,4 +1706,58 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
|
public float chargeSpeedModifier() {
|
|
return 1.0F;
|
|
}
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ 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())) {
|
|
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
|
+ serverPlayer.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 - Ridables
|
|
}
|
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
index 68bad6752bd313ca3ebde7fd4e3b2c46c5dee3ef..fe5f4f79e5a1b091d15fa3bfd876b831e493655c 100644
|
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
@@ -18,14 +18,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 - Ridables
|
|
|
|
public AttributeMap(final AttributeSupplier supplier) {
|
|
- this.supplier = supplier;
|
|
+ // Purpur start - Ridables
|
|
+ this(supplier, null);
|
|
+ }
|
|
+ public AttributeMap(AttributeSupplier defaultAttributes, net.minecraft.world.entity.LivingEntity entity) {
|
|
+ this.entity = entity;
|
|
+ // Purpur end - Ridables
|
|
+ this.supplier = defaultAttributes;
|
|
}
|
|
|
|
private void onAttributeModified(final AttributeInstance attributeInstance) {
|
|
this.attributesToUpdate.add(attributeInstance);
|
|
- if (attributeInstance.getAttribute().value().isClientSyncable()) {
|
|
+ if (attributeInstance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(attributeInstance.getAttribute().value()))) { // Purpur - Ridables
|
|
this.attributesToSync.add(attributeInstance);
|
|
}
|
|
}
|
|
@@ -39,7 +46,7 @@ public class AttributeMap {
|
|
}
|
|
|
|
public Collection<AttributeInstance> getSyncableAttributes() {
|
|
- return this.attributes.values().stream().filter(instance -> instance.getAttribute().value().isClientSyncable()).collect(Collectors.toList());
|
|
+ return this.attributes.values().stream().filter(instance -> instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))).collect(Collectors.toList()); // Purpur - Ridables
|
|
}
|
|
|
|
public @Nullable AttributeInstance getInstance(final Holder<Attribute> attribute) {
|
|
diff --git a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
index 3b122f0bdfd8490297d173c05c1412c9fcfc886e..6b78ddb4ec40d45634288796a98e34714e0deb68 100644
|
|
--- a/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
+++ b/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java
|
|
@@ -142,7 +142,7 @@ public class DefaultAttributes {
|
|
.put(EntityType.PANDA, Panda.createAttributes().build())
|
|
.put(EntityType.PARCHED, Parched.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 - Ridables
|
|
.put(EntityType.PIG, Pig.createAttributes().build())
|
|
.put(EntityType.PIGLIN, Piglin.createAttributes().build())
|
|
.put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build())
|
|
diff --git a/net/minecraft/world/entity/ai/control/MoveControl.java b/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
index 21b524a24257526f40bd6864a2ac6f5e8fd29d96..a6f3c9ca1235b77bff243120bedeea9cc1293328 100644
|
|
--- a/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
+++ b/net/minecraft/world/entity/ai/control/MoveControl.java
|
|
@@ -29,6 +29,20 @@ public class MoveControl implements Control {
|
|
this.mob = mob;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+
|
|
public boolean hasWanted() {
|
|
return this.operation == MoveControl.Operation.MOVE_TO;
|
|
}
|
|
diff --git a/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java b/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java
|
|
index 99493ad5ca4222a2817ee061be01fb888666b3a4..5829ea72b321b2b63f60407aabd83e1b2bd9681c 100644
|
|
--- a/net/minecraft/world/entity/ai/control/SmoothSwimmingLookControl.java
|
|
+++ b/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 - Ridables
|
|
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 - Ridables
|
|
if (this.lookAtCooldown > 0) {
|
|
this.lookAtCooldown--;
|
|
this.getYRotD().ifPresent(yRotD -> this.mob.yHeadRot = this.rotateTowards(this.mob.yHeadRot, yRotD + 20.0F, this.yMaxRotSpeed));
|
|
diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java
|
|
index 5dd0c83e44eb68d90cda5743bc24d97044a02f6e..9861837c1d10e5ffe5dada9f4a75fb9adaccc161 100644
|
|
--- a/net/minecraft/world/entity/ambient/Bat.java
|
|
+++ b/net/minecraft/world/entity/ambient/Bat.java
|
|
@@ -42,11 +42,58 @@ public class Bat extends AmbientCreature {
|
|
|
|
public Bat(final EntityType<? extends Bat> type, final Level level) {
|
|
super(type, level);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.075F); // Purpur - Ridables
|
|
if (!level.isClientSide()) {
|
|
this.setResting(true);
|
|
}
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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(net.minecraft.world.entity.player.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 - Ridables
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return !this.isResting() && this.tickCount % 10.0F == 0.0F;
|
|
@@ -97,7 +144,7 @@ public class Bat extends AmbientCreature {
|
|
}
|
|
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0);
|
|
+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0).add(Attributes.FLYING_SPEED, 0.6D); // Purpur - Ridables
|
|
}
|
|
|
|
public boolean isResting() {
|
|
@@ -128,6 +175,13 @@ public class Bat extends AmbientCreature {
|
|
|
|
@Override
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
+ // Purpur start - Ridables
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot.x(), mot.y() + (getVerticalMot() > 0 ? 0.07D : 0.0D), mot.z());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
super.customServerAiStep(level);
|
|
BlockPos pos = this.blockPosition();
|
|
BlockPos above = pos.above();
|
|
diff --git a/net/minecraft/world/entity/animal/allay/Allay.java b/net/minecraft/world/entity/animal/allay/Allay.java
|
|
index 69638b9f5c4631ec056ec8066d091e553d814252..931726ddada92a4b1063dd9dbdc89723f6a283cc 100644
|
|
--- a/net/minecraft/world/entity/animal/allay/Allay.java
|
|
+++ b/net/minecraft/world/entity/animal/allay/Allay.java
|
|
@@ -100,10 +100,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 - Ridables
|
|
|
|
public Allay(final EntityType<? extends Allay> type, final Level level) {
|
|
super(type, level);
|
|
- this.moveControl = new FlyingMoveControl(this, 20, true);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
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 - Ridables
|
|
+ @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 - Ridables
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected Brain<Allay> makeBrain(final Brain.Packed packedBrain) {
|
|
return BRAIN_PROVIDER.makeBrain(this, packedBrain);
|
|
@@ -209,6 +244,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("allayBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("allayActivityUpdate");
|
|
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
index 14491f7136266a738bbc463731d0785bcce2b4cd..d8dcb325325ba2fc6b78ff62c95cb818c5fcf3fc 100644
|
|
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
|
@@ -89,6 +89,23 @@ public class Armadillo extends Animal {
|
|
return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 12.0).add(Attributes.MOVEMENT_SPEED, 0.14);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
index 317e16e3a78a7d7af71b83cc25f5a00b474bc12a..993f8195bf67d675eccef47314de0ba0f257b855 100644
|
|
--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
|
@@ -117,6 +117,23 @@ public class Axolotl extends Animal implements Bucketable {
|
|
this.lookControl = new Axolotl.AxolotlLookControl(this, 20);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public float getWalkTargetValue(final BlockPos pos, final LevelReader level) {
|
|
return 0.0F;
|
|
@@ -365,6 +382,7 @@ public class Axolotl extends Animal implements Bucketable {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("axolotlBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("axolotlActivityUpdate");
|
|
@@ -603,23 +621,31 @@ public class Axolotl extends Animal implements Bucketable {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (!Axolotl.this.isPlayingDead()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class AxolotlMoveControl extends SmoothSwimmingMoveControl {
|
|
private final Axolotl axolotl;
|
|
+ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur - Ridables
|
|
|
|
public AxolotlMoveControl(final 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 - Ridables
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start - Ridables
|
|
+ if (axolotl.getRider() != null && axolotl.isControllable()) {
|
|
+ waterController.purpurTick(axolotl.getRider());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
if (!this.axolotl.isPlayingDead()) {
|
|
super.tick();
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/bee/Bee.java b/net/minecraft/world/entity/animal/bee/Bee.java
|
|
index 28cf7f1b7b947639a686b83a5a7d617af9b83e15..67971c3054fd17ee75c69c6168bd74f11dca4c86 100644
|
|
--- a/net/minecraft/world/entity/animal/bee/Bee.java
|
|
+++ b/net/minecraft/world/entity/animal/bee/Bee.java
|
|
@@ -153,6 +153,7 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
|
|
public Bee(final EntityType<? extends Bee> type, final Level level) {
|
|
super(type, level);
|
|
+ final org.purpurmc.purpur.controller.FlyingMoveControllerWASD flyingController = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this, 0.25F, 1.0F, false); // Purpur - Ridables
|
|
// Paper start - Fix MC-167279
|
|
class BeeFlyingMoveControl extends FlyingMoveControl {
|
|
public BeeFlyingMoveControl(final Mob mob, final int maxTurn, final boolean hoversInPlace) {
|
|
@@ -161,11 +162,24 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start - Ridables
|
|
+ if (mob.getRider() != null && mob.isControllable()) {
|
|
+ flyingController.purpurTick(mob.getRider());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
if (this.mob.getY() <= Bee.this.level().getMinY()) {
|
|
this.mob.setNoGravity(false);
|
|
}
|
|
super.tick();
|
|
}
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean hasWanted() {
|
|
+ return mob.getRider() != null || !mob.isControllable() || super.hasWanted();
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
this.moveControl = new BeeFlyingMoveControl(this, 20, true);
|
|
// Paper end - Fix MC-167279
|
|
@@ -177,6 +191,40 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
this.setPathfindingMalus(PathType.FENCE, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
@@ -191,6 +239,7 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.4F, true));
|
|
this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal());
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
|
@@ -208,6 +257,7 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new Bee.BeeHurtByOtherGoal(this).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
|
|
@@ -1087,15 +1137,15 @@ public class Bee extends Animal implements FlyingAnimal, NeutralMob {
|
|
}
|
|
}
|
|
|
|
- private class BeeLookControl extends LookControl {
|
|
+ private class BeeLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables
|
|
BeeLookControl(final Mob mob) {
|
|
super(mob);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (!Bee.this.isAngry()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/entity/animal/camel/Camel.java b/net/minecraft/world/entity/animal/camel/Camel.java
|
|
index 7b30263e2064d5d30a68a055bde2ad28582f4620..fcbb743a07b691f11f14febe5a05959326999293 100644
|
|
--- a/net/minecraft/world/entity/animal/camel/Camel.java
|
|
+++ b/net/minecraft/world/entity/animal/camel/Camel.java
|
|
@@ -95,6 +95,13 @@ public class Camel extends AbstractHorse {
|
|
navigation.setCanWalkOverFences(true);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.camelRidableInWater;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void addAdditionalSaveData(final ValueOutput output) {
|
|
super.addAdditionalSaveData(output);
|
|
diff --git a/net/minecraft/world/entity/animal/chicken/Chicken.java b/net/minecraft/world/entity/animal/chicken/Chicken.java
|
|
index 1012283390664fb31bc318864501e14dca5b4208..b0b7398e36a30e5a932ce4a9d531d0c258e64604 100644
|
|
--- a/net/minecraft/world/entity/animal/chicken/Chicken.java
|
|
+++ b/net/minecraft/world/entity/animal/chicken/Chicken.java
|
|
@@ -76,9 +76,27 @@ public class Chicken extends Animal {
|
|
this.setPathfindingMalus(PathType.WATER, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.4));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, i -> i.is(ItemTags.CHICKEN_FOOD), false));
|
|
diff --git a/net/minecraft/world/entity/animal/cow/AbstractCow.java b/net/minecraft/world/entity/animal/cow/AbstractCow.java
|
|
index 51e3873470372cbe7ce8b1d484d9235bba1c76a0..d398abfcb198b18fd4e41e3f3ecddb40d069bfb0 100644
|
|
--- a/net/minecraft/world/entity/animal/cow/AbstractCow.java
|
|
+++ b/net/minecraft/world/entity/animal/cow/AbstractCow.java
|
|
@@ -38,6 +38,7 @@ public abstract class AbstractCow 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 - Ridables
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, i -> level().purpurConfig.cowFeedMushrooms > 0 && (i.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || i.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || i.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms
|
|
@@ -87,13 +88,14 @@ public abstract class AbstractCow extends Animal {
|
|
|
|
@Override
|
|
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
|
+ if (getRider() != null) return InteractionResult.PASS; // Purpur - Ridables
|
|
ItemStack itemStack = player.getItemInHand(hand);
|
|
if (itemStack.is(Items.BUCKET) && !this.isBaby()) {
|
|
// CraftBukkit start - Got milk?
|
|
org.bukkit.event.player.PlayerBucketFillEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent(player.level(), player, this.blockPosition(), this.blockPosition(), null, itemStack, Items.MILK_BUCKET, hand);
|
|
if (event.isCancelled()) {
|
|
player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
// CraftBukkit end
|
|
player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F);
|
|
diff --git a/net/minecraft/world/entity/animal/cow/Cow.java b/net/minecraft/world/entity/animal/cow/Cow.java
|
|
index 340f3b24842a064044f6bf338f3888af90068eac..e200b9a459c3f410d2e9affbad8ba8e37e1a1ca5 100644
|
|
--- a/net/minecraft/world/entity/animal/cow/Cow.java
|
|
+++ b/net/minecraft/world/entity/animal/cow/Cow.java
|
|
@@ -34,6 +34,23 @@ public class Cow extends AbstractCow {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/animal/cow/MushroomCow.java b/net/minecraft/world/entity/animal/cow/MushroomCow.java
|
|
index c299da2b15d270445fab7a84a1d8542dd9b3fee6..7411d6aafa9ec3b5d6305bb8c1b8d03444cf6aa2 100644
|
|
--- a/net/minecraft/world/entity/animal/cow/MushroomCow.java
|
|
+++ b/net/minecraft/world/entity/animal/cow/MushroomCow.java
|
|
@@ -61,6 +61,23 @@ public class MushroomCow extends AbstractCow implements Shearable {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public float getWalkTargetValue(final BlockPos pos, final LevelReader level) {
|
|
return level.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : level.getPathfindingCostFromLightLevels(pos);
|
|
@@ -121,7 +138,7 @@ public class MushroomCow extends AbstractCow implements Shearable {
|
|
java.util.List<ItemStack> drops = this.generateDefaultDrops(level, itemStack);
|
|
org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemStack, hand, drops);
|
|
if (event != null) {
|
|
- if (event.isCancelled()) return InteractionResult.PASS;
|
|
+ if (event.isCancelled()) return tryRide(player, hand); // Purpur - Ridables
|
|
drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
|
// Paper end - custom shear drops
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/dolphin/Dolphin.java b/net/minecraft/world/entity/animal/dolphin/Dolphin.java
|
|
index 7c52d11673b6cd6c4ad6db598da1e03a68fa5a16..82a56ecf76f53e72d1af67228ce7f9c74678b59f 100644
|
|
--- a/net/minecraft/world/entity/animal/dolphin/Dolphin.java
|
|
+++ b/net/minecraft/world/entity/animal/dolphin/Dolphin.java
|
|
@@ -78,14 +78,82 @@ public class Dolphin extends AgeableWaterCreature {
|
|
private static final boolean DEFAULT_GOT_FISH = false;
|
|
public @Nullable BlockPos treasurePos;
|
|
private boolean isNaturallyAggressiveToPlayers; // Purpur - Dolphins naturally aggressive to players chance
|
|
+ private int spitCooldown; // Purpur - Ridables
|
|
|
|
public Dolphin(final EntityType<? extends Dolphin> type, final Level level) {
|
|
super(type, level);
|
|
- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
this.lookControl = new SmoothSwimmingLookControl(this, 10);
|
|
this.setCanPickUpLoot(true);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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.projectile.DolphinSpit spit = new org.purpurmc.purpur.entity.projectile.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 - Ridables
|
|
+
|
|
@Override
|
|
public @Nullable SpawnGroupData finalizeSpawn(
|
|
final ServerLevelAccessor level, final DifficultyInstance difficulty, final EntitySpawnReason spawnReason, final @Nullable SpawnGroupData groupData
|
|
@@ -160,6 +228,7 @@ public class Dolphin extends AgeableWaterCreature {
|
|
this.goalSelector.addGoal(0, new BreathAirGoal(this));
|
|
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
|
|
this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - Dolphins naturally aggressive to players chance
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this));
|
|
this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0));
|
|
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0, 10));
|
|
@@ -171,6 +240,7 @@ public class Dolphin extends AgeableWaterCreature {
|
|
this.goalSelector.addGoal(8, new FollowPlayerRiddenEntityGoal(this, AbstractBoat.class));
|
|
this.goalSelector.addGoal(8, new FollowPlayerRiddenEntityGoal(this, AbstractNautilus.class));
|
|
this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0, 1.0));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Guardian.class).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Dolphins naturally aggressive to players chance
|
|
}
|
|
@@ -216,7 +286,7 @@ public class Dolphin extends AgeableWaterCreature {
|
|
|
|
@Override
|
|
protected boolean canRide(final Entity vehicle) {
|
|
- return true;
|
|
+ return boardingCooldown <= 0; // Purpur - make dolphin honor ride cooldown like all other non-boss mobs;
|
|
}
|
|
|
|
@Override
|
|
@@ -245,6 +315,11 @@ public class Dolphin extends AgeableWaterCreature {
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
+ // Purpur start - Ridables
|
|
+ if (spitCooldown > 0) {
|
|
+ spitCooldown--;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
if (this.isNoAi()) {
|
|
this.setAirSupply(this.getMaxAirSupply());
|
|
} else {
|
|
diff --git a/net/minecraft/world/entity/animal/equine/AbstractHorse.java b/net/minecraft/world/entity/animal/equine/AbstractHorse.java
|
|
index 52fc3d9600a7bd256647fbbfc1e460ca2b10a424..59bf0106908fba34500d1e44d6a02bb27b71ffe5 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/AbstractHorse.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/AbstractHorse.java
|
|
@@ -128,11 +128,21 @@ public abstract class AbstractHorse extends Animal implements PlayerRideableJump
|
|
|
|
protected AbstractHorse(final EntityType<? extends AbstractHorse> type, final Level level) {
|
|
super(type, level);
|
|
+ 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 - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return false; // vanilla handles
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0, AbstractHorse.class));
|
|
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.0));
|
|
@@ -142,6 +152,7 @@ public abstract class AbstractHorse extends Animal implements PlayerRideableJump
|
|
if (this.canPerformRearing()) {
|
|
this.goalSelector.addGoal(9, new RandomStandGoal(this));
|
|
}
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HorseHasRider(this)); // Purpur - Ridables
|
|
|
|
this.addBehaviourGoals();
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/equine/Donkey.java b/net/minecraft/world/entity/animal/equine/Donkey.java
|
|
index 1c171229997aa5c8e586918d9ed003b7f3c6e5f3..980160d37a51b862df3bda18a1bdb92e83badf3c 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/Donkey.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/Donkey.java
|
|
@@ -16,6 +16,13 @@ public class Donkey extends AbstractChestedHorse {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.donkeyRidableInWater;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public SoundEvent getAmbientSound() {
|
|
return SoundEvents.DONKEY_AMBIENT;
|
|
diff --git a/net/minecraft/world/entity/animal/equine/Horse.java b/net/minecraft/world/entity/animal/equine/Horse.java
|
|
index 87e34dd94340be58ade945992e26dd81ee19b0a4..d2dc51d7a8d97db64bf87f8337b10442acc5bc47 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/Horse.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/Horse.java
|
|
@@ -48,6 +48,13 @@ public class Horse extends AbstractHorse {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.horseRidableInWater;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void randomizeAttributes(final RandomSource random) {
|
|
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt));
|
|
diff --git a/net/minecraft/world/entity/animal/equine/Llama.java b/net/minecraft/world/entity/animal/equine/Llama.java
|
|
index 22fc7041bd98b54d094ee66cdb62cf983ffa5588..90928f2a840493b16b34bf870fc511e74d1150ea 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/Llama.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/Llama.java
|
|
@@ -81,7 +81,58 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
|
|
super(type, level);
|
|
this.getNavigation().setRequiredPathLength(40.0F);
|
|
this.maxDomestication = 30; // Paper - Missing entity API; configure max temper instead of a hardcoded value
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+ }
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ @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.isWearingBodyArmor() || this.isTamed();
|
|
+ }
|
|
+
|
|
+ @Nullable
|
|
+ @Override
|
|
+ public LivingEntity getControllingPassenger() {
|
|
+ Entity firstPassenger = this.getFirstPassenger();
|
|
+ return !this.isNoAi() && firstPassenger instanceof net.minecraft.world.entity.Mob mob && firstPassenger.canControlVehicle() ? mob : null;
|
|
}
|
|
+ // Purpur end - Ridables
|
|
|
|
public boolean isTraderLlama() {
|
|
return false;
|
|
@@ -119,6 +170,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.LlamaHasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2));
|
|
this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.1F));
|
|
this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25, 40, 20.0F));
|
|
@@ -129,6 +181,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
|
|
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new Llama.LlamaHurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new Llama.LlamaAttackWolfGoal(this));
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/equine/Mule.java b/net/minecraft/world/entity/animal/equine/Mule.java
|
|
index 1ebf80bac3e4cc17bbee795b9cb15c656b168396..ce4c2424cd6922c03cf44cc731526775eba25220 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/Mule.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/Mule.java
|
|
@@ -15,6 +15,13 @@ public class Mule extends AbstractChestedHorse {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.muleRidableInWater;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public SoundEvent getAmbientSound() {
|
|
return SoundEvents.MULE_AMBIENT;
|
|
diff --git a/net/minecraft/world/entity/animal/equine/SkeletonHorse.java b/net/minecraft/world/entity/animal/equine/SkeletonHorse.java
|
|
index 03d0e52213707fb052d5298000e5cd14c2e25636..8a9f46e45ce077230ec918d46f599092fbe3e851 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/SkeletonHorse.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/SkeletonHorse.java
|
|
@@ -43,6 +43,13 @@ public class SkeletonHorse extends AbstractHorse {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isTamed() {
|
|
+ return super.isTamed() || this.level().purpurConfig.skeletonHorseRidable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 15.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
|
|
}
|
|
@@ -62,6 +69,7 @@ public class SkeletonHorse extends AbstractHorse {
|
|
|
|
@Override
|
|
protected void addBehaviourGoals() {
|
|
+ if (level().purpurConfig.skeletonHorseCanSwim) goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - Ridables
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/entity/animal/equine/TraderLlama.java b/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
|
index 95f499b7fdbe1620c6eb13b9a2e86bb6091af085..19497883e03603bc0a0f63c3b3734e32f9ed2e1d 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
|
@@ -31,6 +31,28 @@ public class TraderLlama extends Llama {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public boolean isTraderLlama() {
|
|
return true;
|
|
diff --git a/net/minecraft/world/entity/animal/equine/ZombieHorse.java b/net/minecraft/world/entity/animal/equine/ZombieHorse.java
|
|
index a279cdff95c37434f44bdda7558286045e606f33..13857de6c4be09b7d0798d2a0fd420c705ac1d5d 100644
|
|
--- a/net/minecraft/world/entity/animal/equine/ZombieHorse.java
|
|
+++ b/net/minecraft/world/entity/animal/equine/ZombieHorse.java
|
|
@@ -49,6 +49,18 @@ public class ZombieHorse extends AbstractHorse {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return createBaseHorseAttributes().add(Attributes.MAX_HEALTH, 25.0);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/feline/Cat.java b/net/minecraft/world/entity/animal/feline/Cat.java
|
|
index 0834b837b84c337366e051cec88da2c2789e7bef..36688a571cdf35697d0cd97bee316f5474bcae73 100644
|
|
--- a/net/minecraft/world/entity/animal/feline/Cat.java
|
|
+++ b/net/minecraft/world/entity/animal/feline/Cat.java
|
|
@@ -95,10 +95,36 @@ public class Cat extends TamableAnimal {
|
|
this.reassessTameGoals();
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.temptGoal = new Cat.CatTemptGoal(this, 0.6, i -> i.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 - Ridables
|
|
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5));
|
|
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
|
this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this));
|
|
@@ -111,6 +137,7 @@ public class Cat extends TamableAnimal {
|
|
this.goalSelector.addGoal(10, new BreedGoal(this, 0.8));
|
|
this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8, 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 - Ridables
|
|
this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, null));
|
|
this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
|
|
}
|
|
@@ -402,6 +429,7 @@ public class Cat extends TamableAnimal {
|
|
|
|
@Override
|
|
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
|
+ if (getRider() != null) return InteractionResult.PASS; // Purpur - Ridables
|
|
ItemStack itemStack = player.getItemInHand(hand);
|
|
if (this.isTame()) {
|
|
if (this.isOwnedBy(player)) {
|
|
diff --git a/net/minecraft/world/entity/animal/feline/Ocelot.java b/net/minecraft/world/entity/animal/feline/Ocelot.java
|
|
index 9fb38aaf63588cfe8a6f006a256c54a75ebbef46..93bfc93ae24d483f8a6c856d9ce978e34a064cd4 100644
|
|
--- a/net/minecraft/world/entity/animal/feline/Ocelot.java
|
|
+++ b/net/minecraft/world/entity/animal/feline/Ocelot.java
|
|
@@ -66,6 +66,23 @@ public class Ocelot extends Animal {
|
|
this.reassessTrustingGoals();
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public boolean isTrusting() {
|
|
return this.entityData.get(DATA_TRUSTING);
|
|
}
|
|
@@ -97,12 +114,14 @@ public class Ocelot extends Animal {
|
|
protected void registerGoals() {
|
|
this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6, i -> i.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 - Ridables
|
|
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.8));
|
|
this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8, 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 - Ridables
|
|
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/net/minecraft/world/entity/animal/fish/AbstractFish.java b/net/minecraft/world/entity/animal/fish/AbstractFish.java
|
|
index 62303a59d3e0ec28bc3d6bf6fc459527ad80b1f1..5619119cce83a0c2d5efbb0579345510978716f1 100644
|
|
--- a/net/minecraft/world/entity/animal/fish/AbstractFish.java
|
|
+++ b/net/minecraft/world/entity/animal/fish/AbstractFish.java
|
|
@@ -91,6 +91,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 - Ridables
|
|
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));
|
|
this.goalSelector.addGoal(4, new AbstractFish.FishSwimGoal(this));
|
|
@@ -103,7 +104,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
|
|
@Override
|
|
protected void travelInWater(final Vec3 input, final double baseGravity, final boolean isFalling, final double oldY) {
|
|
- this.moveRelative(0.01F, input);
|
|
+ this.moveRelative(getRider() != null ? getSpeed() : 0.01F, input); // Purpur - Ridables
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
|
|
if (this.getTarget() == null) {
|
|
@@ -160,7 +161,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
protected void playStepSound(final BlockPos pos, final BlockState blockState) {
|
|
}
|
|
|
|
- private static class FishMoveControl extends MoveControl {
|
|
+ private static class FishMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur - Ridables
|
|
private final AbstractFish fish;
|
|
|
|
FishMoveControl(final AbstractFish fish) {
|
|
@@ -168,14 +169,22 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable {
|
|
this.fish = fish;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
@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 - Ridables
|
|
+
|
|
+ @Override
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
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 targetSpeed = (float)(this.speedModifier * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float targetSpeed = (float)(this.getSpeedModifier() * this.fish.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - Ridables
|
|
this.fish.setSpeed(Mth.lerp(0.125F, this.fish.getSpeed(), targetSpeed));
|
|
double xd = this.wantedX - this.fish.getX();
|
|
double yd = this.wantedY - this.fish.getY();
|
|
diff --git a/net/minecraft/world/entity/animal/fish/Cod.java b/net/minecraft/world/entity/animal/fish/Cod.java
|
|
index 1909fefa4af14a9aca43ccb8b93317b12ee4a092..becb5c214adacd36372bbe2b21ab15e341640f7d 100644
|
|
--- a/net/minecraft/world/entity/animal/fish/Cod.java
|
|
+++ b/net/minecraft/world/entity/animal/fish/Cod.java
|
|
@@ -13,6 +13,18 @@ public class Cod extends AbstractSchoolingFish {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.codRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.codControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public ItemStack getBucketItemStack() {
|
|
return new ItemStack(Items.COD_BUCKET);
|
|
diff --git a/net/minecraft/world/entity/animal/fish/Pufferfish.java b/net/minecraft/world/entity/animal/fish/Pufferfish.java
|
|
index 9981452e2dda0675defd279c4460031dae5fd25f..8d3e8575120145f572b2c1834d243bac8eb28586 100644
|
|
--- a/net/minecraft/world/entity/animal/fish/Pufferfish.java
|
|
+++ b/net/minecraft/world/entity/animal/fish/Pufferfish.java
|
|
@@ -47,6 +47,18 @@ public class Pufferfish extends AbstractFish {
|
|
this.refreshDimensions();
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.pufferfishRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.pufferfishControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/animal/fish/Salmon.java b/net/minecraft/world/entity/animal/fish/Salmon.java
|
|
index a967d067c3e97859a88672a3b9daf1b89d81ed3c..e96062cd57e1866c398418ebbb8f2443a668f480 100644
|
|
--- a/net/minecraft/world/entity/animal/fish/Salmon.java
|
|
+++ b/net/minecraft/world/entity/animal/fish/Salmon.java
|
|
@@ -41,6 +41,18 @@ public class Salmon extends AbstractSchoolingFish {
|
|
this.refreshDimensions();
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.salmonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.salmonControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public int getMaxSchoolSize() {
|
|
return 5;
|
|
diff --git a/net/minecraft/world/entity/animal/fish/TropicalFish.java b/net/minecraft/world/entity/animal/fish/TropicalFish.java
|
|
index f846e5c736baea99fe5e411e36cf56a074145752..d48f8dc3e806ffe767565158bcfa17631839a61c 100644
|
|
--- a/net/minecraft/world/entity/animal/fish/TropicalFish.java
|
|
+++ b/net/minecraft/world/entity/animal/fish/TropicalFish.java
|
|
@@ -77,6 +77,18 @@ public class TropicalFish extends AbstractSchoolingFish {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.tropicalFishRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.tropicalFishControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
public static String getPredefinedName(final int index) {
|
|
return "entity.minecraft.tropical_fish.predefined." + index;
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/fox/Fox.java b/net/minecraft/world/entity/animal/fox/Fox.java
|
|
index b3dcc836f5bf756b11194ff534535b69d98490c5..c60343771f5490236212221e7d5f2b73dee4865c 100644
|
|
--- a/net/minecraft/world/entity/animal/fox/Fox.java
|
|
+++ b/net/minecraft/world/entity/animal/fox/Fox.java
|
|
@@ -154,6 +154,44 @@ public class Fox extends Animal {
|
|
this.getNavigation().setRequiredPathLength(32.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
@@ -173,6 +211,7 @@ public class Fox extends Animal {
|
|
this, AbstractFish.class, 20, false, false, (target, level) -> target instanceof AbstractSchoolingFish
|
|
);
|
|
this.goalSelector.addGoal(0, new Fox.FoxFloatGoal());
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(1, new Fox.FaceplantGoal());
|
|
this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2));
|
|
@@ -197,6 +236,7 @@ public class Fox extends Animal {
|
|
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 - Ridables
|
|
this.targetSelector
|
|
.addGoal(
|
|
3,
|
|
@@ -1125,15 +1165,15 @@ public class Fox extends Animal {
|
|
}
|
|
}
|
|
|
|
- public class FoxLookControl extends LookControl {
|
|
+ public class FoxLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables
|
|
public FoxLookControl() {
|
|
super(Fox.this);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (!Fox.this.isSleeping()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
|
|
@@ -1169,15 +1209,15 @@ public class Fox extends Animal {
|
|
}
|
|
}
|
|
|
|
- private class FoxMoveControl extends MoveControl {
|
|
+ private class FoxMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
public FoxMoveControl() {
|
|
super(Fox.this);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (Fox.this.canMove()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java
|
|
index ef9f543aea1e88e1f81d888c7b21aeac934f102b..bedbe9adede69efa4c4f2e6def9aeb3e8429fc2e 100644
|
|
--- a/net/minecraft/world/entity/animal/frog/Frog.java
|
|
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
|
|
@@ -82,6 +82,8 @@ public class Frog extends Animal {
|
|
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 - Ridables
|
|
+ private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurWaterController; // Purpur - Ridables
|
|
|
|
public Frog(final EntityType<? extends Animal> type, final Level level) {
|
|
super(type, level);
|
|
@@ -89,7 +91,55 @@ public class Frog extends Animal {
|
|
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 - Ridables
|
|
+ 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 - Ridables
|
|
+ }
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public float getJumpPower() {
|
|
+ return (getRider() != null && isControllable()) ? level().purpurConfig.frogRidableJumpHeight * this.getBlockJumpFactor() : super.getJumpPower();
|
|
}
|
|
+ // Purpur end - Ridables
|
|
|
|
@Override
|
|
protected Brain<Frog> makeBrain(final Brain.Packed packedBrain) {
|
|
@@ -176,6 +226,7 @@ public class Frog extends Animal {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("frogBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("frogActivityUpdate");
|
|
@@ -345,7 +396,7 @@ public class Frog extends Animal {
|
|
return level.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos);
|
|
}
|
|
|
|
- private class FrogLookControl extends LookControl {
|
|
+ private class FrogLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables
|
|
FrogLookControl(final Mob mob) {
|
|
super(mob);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
index 3d4bfeae2fddb9ace26e7dea8870704d8309862b..ed8fa3aa3d0bb3c83f46a902dfe603942c4a8f96 100644
|
|
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
|
@@ -54,13 +54,50 @@ public class Tadpole extends AbstractFish {
|
|
List.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS),
|
|
var0 -> TadpoleAi.getActivities()
|
|
);
|
|
+ private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurController; // Purpur - Ridables
|
|
|
|
public Tadpole(final EntityType<? extends AbstractFish> type, final Level level) {
|
|
super(type, level);
|
|
- this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
this.lookControl = new SmoothSwimmingLookControl(this, 10);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected PathNavigation createNavigation(final Level level) {
|
|
return new WaterBoundPathNavigation(this, level);
|
|
@@ -85,6 +122,7 @@ public class Tadpole extends AbstractFish {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("tadpoleBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("tadpoleActivityUpdate");
|
|
diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java
|
|
index 7df6194d8fd844b9cd4aec55bb0f613fdfefaad2..cd0f514fa6deef90efc697d30af9a88797b456f8 100644
|
|
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
|
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
|
@@ -100,6 +100,23 @@ public class Goat extends Animal {
|
|
.orElseGet(() -> new ItemStack(Items.GOAT_HORN));
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected Brain<Goat> makeBrain(final Brain.Packed packedBrain) {
|
|
return BRAIN_PROVIDER.makeBrain(this, packedBrain);
|
|
@@ -170,6 +187,7 @@ public class Goat extends Animal {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("goatBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("goatActivityUpdate");
|
|
diff --git a/net/minecraft/world/entity/animal/golem/CopperGolem.java b/net/minecraft/world/entity/animal/golem/CopperGolem.java
|
|
index 61612645df4ece5f3f6abf5f37fd717c99be10e1..d842d79bbd5253a2a701a87221258751aa112c3e 100644
|
|
--- a/net/minecraft/world/entity/animal/golem/CopperGolem.java
|
|
+++ b/net/minecraft/world/entity/animal/golem/CopperGolem.java
|
|
@@ -112,6 +112,28 @@ public class CopperGolem extends AbstractGolem implements ContainerUser, Shearab
|
|
}
|
|
// Purpur end - Summoner API
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.copperGolemRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.copperGolemRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.copperGolemControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F).add(Attributes.STEP_HEIGHT, 1.0).add(Attributes.MAX_HEALTH, 12.0);
|
|
}
|
|
@@ -197,6 +219,7 @@ public class CopperGolem extends AbstractGolem implements ContainerUser, Shearab
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("copperGolemBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
profiler.push("copperGolemActivityUpdate");
|
|
@@ -236,7 +259,7 @@ public class CopperGolem extends AbstractGolem implements ContainerUser, Shearab
|
|
java.util.List<ItemStack> drops = this.generateDefaultDrops(serverLevel, itemStack);
|
|
org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemStack, hand, drops);
|
|
if (event != null) {
|
|
- if (event.isCancelled()) return InteractionResult.PASS;
|
|
+ if (event.isCancelled()) return tryRide(player, hand); // Purpur - Ridables
|
|
drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
|
}
|
|
this.shear(serverLevel, SoundSource.PLAYERS, itemStack, drops);
|
|
@@ -278,6 +301,8 @@ public class CopperGolem extends AbstractGolem implements ContainerUser, Shearab
|
|
}
|
|
}
|
|
|
|
+ if (level().purpurConfig.villagerRidable && itemStack.isEmpty()) return tryRide(player, hand); // Purpur - Ridables
|
|
+
|
|
return super.mobInteract(player, hand);
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/golem/IronGolem.java b/net/minecraft/world/entity/animal/golem/IronGolem.java
|
|
index cc49b2582073c2dbc19e3c857390b0fa0e8ad2d2..c6e0038cb3314b4db17d307b99de65dde107d5a1 100644
|
|
--- a/net/minecraft/world/entity/animal/golem/IronGolem.java
|
|
+++ b/net/minecraft/world/entity/animal/golem/IronGolem.java
|
|
@@ -74,9 +74,28 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
|
}
|
|
// Purpur end - Summoner API
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
if (this.level().purpurConfig.ironGolemPoppyCalm) this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.ReceiveFlower(this)); // Purpur - Iron golem calm anger options
|
|
+ if (level().purpurConfig.ironGolemCanSwim) this.goalSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.FloatGoal(this)); // Purpur - Ridables
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true));
|
|
this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32.0F));
|
|
this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6, false));
|
|
@@ -84,6 +103,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 - Ridables
|
|
this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
|
|
@@ -271,13 +291,13 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
|
|
protected InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
|
ItemStack itemStack = player.getItemInHand(hand);
|
|
if (!itemStack.is(Items.IRON_INGOT)) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
|
|
float healthBefore = this.getHealth();
|
|
this.heal(25.0F);
|
|
if (this.getHealth() == healthBefore) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
|
|
float pitch = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
|
|
diff --git a/net/minecraft/world/entity/animal/golem/SnowGolem.java b/net/minecraft/world/entity/animal/golem/SnowGolem.java
|
|
index 0993ec37f58cbc6b201ebc9aeb39aee438bd1cf9..6875e40687bbde6aba25da7d3145eccdccea6f52 100644
|
|
--- a/net/minecraft/world/entity/animal/golem/SnowGolem.java
|
|
+++ b/net/minecraft/world/entity/animal/golem/SnowGolem.java
|
|
@@ -62,12 +62,31 @@ public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearab
|
|
}
|
|
// Purpur end - Summoner API
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new RangedAttackGoal(this, level().purpurConfig.snowGolemAttackDistance, level().purpurConfig.snowGolemSnowBallMin, level().purpurConfig.snowGolemSnowBallMax, level().purpurConfig.snowGolemSnowBallModifier)); // Purpur - Snow Golem rate of fire config
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (target, level) -> target instanceof Enemy));
|
|
}
|
|
|
|
@@ -112,6 +131,7 @@ public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearab
|
|
return;
|
|
}
|
|
|
|
+ if (getRider() != null && this.isControllable() && !level().purpurConfig.snowGolemLeaveTrailWhenRidden) return; // Purpur - don't leave snow trail when being ridden
|
|
BlockState snow = Blocks.SNOW.defaultBlockState();
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
@@ -157,7 +177,7 @@ public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearab
|
|
org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemStack, hand, drops);
|
|
if (event != null) {
|
|
if (event.isCancelled()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
|
|
// Paper end - custom shear drops
|
|
@@ -178,7 +198,7 @@ public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearab
|
|
return InteractionResult.SUCCESS;
|
|
// Purpur end - Snowman drop and put back pumpkin
|
|
} else {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java
|
|
index 9624a1f4cd829411e46213201200e3af54d57699..0ffa1ed6fe9e8aa01c91dee4cefb8b9a1273770b 100644
|
|
--- a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java
|
|
+++ b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java
|
|
@@ -133,6 +133,13 @@ public class HappyGhast extends Animal {
|
|
this.removeAllGoals(goal -> true);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.happyGhastRidableInWater;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void ageBoundaryReached() {
|
|
if (this.isBaby()) {
|
|
diff --git a/net/minecraft/world/entity/animal/panda/Panda.java b/net/minecraft/world/entity/animal/panda/Panda.java
|
|
index 7bb37a2efaec248a51da2b89ecad536d424d5393..e551907cd2721fa330639aa590ef76711e7e21d6 100644
|
|
--- a/net/minecraft/world/entity/animal/panda/Panda.java
|
|
+++ b/net/minecraft/world/entity/animal/panda/Panda.java
|
|
@@ -110,6 +110,32 @@ public class Panda extends Animal {
|
|
}
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected boolean canDispenserEquipIntoSlot(final EquipmentSlot slot) {
|
|
return slot == EquipmentSlot.MAINHAND && this.canPickUpLoot();
|
|
@@ -262,6 +288,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 - Ridables
|
|
this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0));
|
|
this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2F, true));
|
|
@@ -277,6 +304,7 @@ public class Panda extends Animal {
|
|
this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this));
|
|
this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25));
|
|
this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.targetSelector.addGoal(1, new Panda.PandaHurtByTargetGoal(this).setAlertOthers());
|
|
}
|
|
|
|
@@ -615,7 +643,7 @@ public class Panda extends Animal {
|
|
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
|
ItemStack interactionItemStack = player.getItemInHand(hand);
|
|
if (this.isScared()) {
|
|
- return InteractionResult.PASS;
|
|
+ return tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
|
|
if (this.isOnBack()) {
|
|
@@ -661,7 +689,7 @@ public class Panda extends Animal {
|
|
|
|
return InteractionResult.SUCCESS_SERVER;
|
|
} else {
|
|
- return this.isBaby() && player.isHolding(Items.GOLDEN_DANDELION) ? super.mobInteract(player, hand) : InteractionResult.PASS;
|
|
+ return tryRide(player, hand, this.isBaby() && player.isHolding(Items.GOLDEN_DANDELION) ? super.mobInteract(player, hand) : InteractionResult.PASS); // Purpur - Ridables
|
|
}
|
|
}
|
|
|
|
@@ -968,7 +996,7 @@ public class Panda extends Animal {
|
|
}
|
|
}
|
|
|
|
- private static class PandaMoveControl extends MoveControl {
|
|
+ private static class PandaMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
private final Panda panda;
|
|
|
|
public PandaMoveControl(final Panda mob) {
|
|
@@ -977,9 +1005,9 @@ public class Panda extends Animal {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (this.panda.canPerformAction()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/parrot/Parrot.java b/net/minecraft/world/entity/animal/parrot/Parrot.java
|
|
index 2fb6b134794d232ddb06176a6c3bb69431c7663c..0cc9e9dcdaeaee8db350b4dc4acb1e6c370aa2c3 100644
|
|
--- a/net/minecraft/world/entity/animal/parrot/Parrot.java
|
|
+++ b/net/minecraft/world/entity/animal/parrot/Parrot.java
|
|
@@ -137,12 +137,68 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
|
|
|
|
public Parrot(final EntityType<? extends Parrot> type, final Level level) {
|
|
super(type, level);
|
|
- this.moveControl = new FlyingMoveControl(this, 10, false);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
this.setPathfindingMalus(PathType.FIRE_IN_NEIGHBOR, -1.0F);
|
|
this.setPathfindingMalus(PathType.FIRE, -1.0F);
|
|
this.setPathfindingMalus(PathType.COCOA, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public @Nullable SpawnGroupData finalizeSpawn(
|
|
final ServerLevelAccessor level, final DifficultyInstance difficulty, final EntitySpawnReason spawnReason, @Nullable SpawnGroupData groupData
|
|
@@ -162,9 +218,11 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
- this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25));
|
|
+ //this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25)); // Purpur - move down
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
if (this.level().purpurConfig.parrotBreedable) this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D)); // Purpur - Breedable parrots
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
+ this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.25D)); // Purpur - Ridables
|
|
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.0, 5.0F, 1.0F));
|
|
diff --git a/net/minecraft/world/entity/animal/pig/Pig.java b/net/minecraft/world/entity/animal/pig/Pig.java
|
|
index ff9c2cd82c89c5c6be00467360dfef84a9ca7a96..ed655afebba29cccb7c15e6f15aee6478ecdaee4 100644
|
|
--- a/net/minecraft/world/entity/animal/pig/Pig.java
|
|
+++ b/net/minecraft/world/entity/animal/pig/Pig.java
|
|
@@ -68,9 +68,27 @@ public class Pig extends Animal implements ItemSteerable {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25));
|
|
this.goalSelector.addGoal(3, new BreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, i -> i.is(Items.CARROT_ON_A_STICK), false));
|
|
diff --git a/net/minecraft/world/entity/animal/polarbear/PolarBear.java b/net/minecraft/world/entity/animal/polarbear/PolarBear.java
|
|
index 8bcfe80e696fe2f0a781a496772b2995f0151ab4..a7a77f9cae2f524ce7abbc694cdae7c95bef3e16 100644
|
|
--- a/net/minecraft/world/entity/animal/polarbear/PolarBear.java
|
|
+++ b/net/minecraft/world/entity/animal/polarbear/PolarBear.java
|
|
@@ -61,6 +61,7 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39);
|
|
private long persistentAngerEndTime;
|
|
private @Nullable EntityReference<LivingEntity> persistentAngerTarget;
|
|
+ private int standTimer = 0; // Purpur - Ridables
|
|
|
|
public PolarBear(final EntityType<? extends PolarBear> type, final Level level) {
|
|
super(type, level);
|
|
@@ -89,6 +90,34 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
}
|
|
// Purpur end - Breedable Polar Bears
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public @Nullable AgeableMob getBreedOffspring(final ServerLevel level, final AgeableMob partner) {
|
|
return EntityType.POLAR_BEAR.create(level, EntitySpawnReason.BREEDING);
|
|
@@ -103,6 +132,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 - Ridables
|
|
this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal());
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0, bear -> bear.isBaby() ? DamageTypeTags.PANIC_CAUSES : DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
|
// Purpur start - Breedable Polar Bears
|
|
@@ -115,6 +145,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 - Ridables
|
|
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));
|
|
@@ -232,6 +263,12 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
if (!this.level().isClientSide()) {
|
|
this.updatePersistentAnger((ServerLevel)this.level(), true);
|
|
}
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ if (isStanding() && --standTimer <= 0) {
|
|
+ setStanding(false);
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -251,6 +288,7 @@ public class PolarBear extends Animal implements NeutralMob {
|
|
|
|
public void setStanding(final boolean value) {
|
|
this.entityData.set(DATA_STANDING_ID, value);
|
|
+ standTimer = value ? 20 : -1; // Purpur - Ridables
|
|
}
|
|
|
|
public float getStandingAnimationScale(final float a) {
|
|
diff --git a/net/minecraft/world/entity/animal/rabbit/Rabbit.java b/net/minecraft/world/entity/animal/rabbit/Rabbit.java
|
|
index 977143e1072b5691f32a0aa11e24a4e8b907476c..0053a1e7ed9b577128241e0c72f59d66eb532726 100644
|
|
--- a/net/minecraft/world/entity/animal/rabbit/Rabbit.java
|
|
+++ b/net/minecraft/world/entity/animal/rabbit/Rabbit.java
|
|
@@ -108,6 +108,7 @@ public class Rabbit extends Animal {
|
|
private boolean wasOnGround;
|
|
private int jumpDelayTicks;
|
|
public int moreCarrotTicks = 0;
|
|
+ private boolean actualJump; // Purpur - Ridables
|
|
|
|
public Rabbit(final EntityType<? extends Rabbit> type, final Level level) {
|
|
super(type, level);
|
|
@@ -116,9 +117,55 @@ public class Rabbit extends Animal {
|
|
// this.setSpeedModifier(0.0); // CraftBukkit
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 0.8));
|
|
@@ -138,6 +185,14 @@ public class Rabbit extends Animal {
|
|
|
|
@Override
|
|
protected float getJumpPower() {
|
|
+ // Purpur start - Ridables
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ if (getForwardMot() < 0) {
|
|
+ setSpeed(getForwardMot() * 2F);
|
|
+ }
|
|
+ return actualJump ? 0.5F : 0.3F;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
float baseJumpPower = 0.3F;
|
|
if (this.moveControl.getSpeedModifier() <= 0.6) {
|
|
baseJumpPower = 0.2F;
|
|
@@ -205,6 +260,12 @@ public class Rabbit extends Animal {
|
|
|
|
@Override
|
|
public void customServerAiStep(final ServerLevel level) {
|
|
+ // Purpur start - Ridables
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ handleJumping();
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
if (this.jumpDelayTicks > 0) {
|
|
this.jumpDelayTicks--;
|
|
}
|
|
@@ -487,7 +548,7 @@ public class Rabbit extends Animal {
|
|
}
|
|
|
|
private boolean shouldPlayIdleAnimation() {
|
|
- return this.idleAnimationTimeout <= 0 && (this.getLeashData() == null || this.getLeashData().leashHolder == null) && !this.isNoAi();
|
|
+ return getRider() == null && this.idleAnimationTimeout <= 0 && (this.getLeashData() == null || this.getLeashData().leashHolder == null) && !this.isNoAi(); // Purpur - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -559,7 +620,7 @@ public class Rabbit extends Animal {
|
|
}
|
|
}
|
|
|
|
- private static class RabbitMoveControl extends MoveControl {
|
|
+ private static class RabbitMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
private final Rabbit rabbit;
|
|
private double nextJumpSpeed;
|
|
|
|
@@ -569,14 +630,14 @@ public class Rabbit extends Animal {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (this.rabbit.onGround() && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl)this.rabbit.jumpControl).wantJump()) {
|
|
this.rabbit.setSpeedModifier(0.0);
|
|
} else if (this.hasWanted() || this.operation == MoveControl.Operation.JUMPING) {
|
|
this.rabbit.setSpeedModifier(this.nextJumpSpeed);
|
|
}
|
|
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/entity/animal/sheep/Sheep.java b/net/minecraft/world/entity/animal/sheep/Sheep.java
|
|
index 87fd91714510638386b13d285db889c075669f3e..08cd6e675107bf622b634c1f0e2cd53e33ef3569 100644
|
|
--- a/net/minecraft/world/entity/animal/sheep/Sheep.java
|
|
+++ b/net/minecraft/world/entity/animal/sheep/Sheep.java
|
|
@@ -63,10 +63,28 @@ public class Sheep extends Animal implements Shearable {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.1, i -> i.is(ItemTags.SHEEP_FOOD), false));
|
|
diff --git a/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
|
index 42c6100b82b82e3cebd6d808f644f4fc666037e3..b980ed12f7f20d89c6bd01d2c94cb2cc15f5c561 100644
|
|
--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
|
+++ b/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 - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
@@ -467,6 +484,7 @@ public class Sniffer extends Animal {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("snifferBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.popPush("snifferActivityUpdate");
|
|
SnifferAi.updateActivity(this);
|
|
diff --git a/net/minecraft/world/entity/animal/squid/GlowSquid.java b/net/minecraft/world/entity/animal/squid/GlowSquid.java
|
|
index 7db02196ed1dd9057c9418d3d96164bb5082380b..51a0771819abfdde5043eaeca62b0ce45c40039e 100644
|
|
--- a/net/minecraft/world/entity/animal/squid/GlowSquid.java
|
|
+++ b/net/minecraft/world/entity/animal/squid/GlowSquid.java
|
|
@@ -37,6 +37,19 @@ public class GlowSquid extends Squid {
|
|
}
|
|
// Purpur end - Flying squids! Oh my!
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.glowSquidRidable;
|
|
+ }
|
|
+
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.glowSquidControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected ParticleOptions getInkParticle() {
|
|
return ParticleTypes.GLOW_SQUID_INK;
|
|
diff --git a/net/minecraft/world/entity/animal/squid/Squid.java b/net/minecraft/world/entity/animal/squid/Squid.java
|
|
index 45e170bbcc72206ed0018440c435359084749a7f..76c9c4cb6f7567946bc90e2d59990d5aabd8e4d9 100644
|
|
--- a/net/minecraft/world/entity/animal/squid/Squid.java
|
|
+++ b/net/minecraft/world/entity/animal/squid/Squid.java
|
|
@@ -74,9 +74,32 @@ public class Squid extends AgeableWaterCreature {
|
|
}
|
|
// Purpur end - Flying squids! Oh my!
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.squidRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.squidControllable;
|
|
+ }
|
|
+
|
|
+ protected static 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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new Squid.SquidFleeGoal());
|
|
}
|
|
|
|
@@ -333,6 +356,37 @@ public class Squid extends AgeableWaterCreature {
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start - Ridables
|
|
+ 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.movementVector = new Vec3((float) dir.getX(), (float) dir.getY(), (float) dir.getZ());
|
|
+ } else {
|
|
+ squid.movementVector = Vec3.ZERO;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
int noActionTime = this.squid.getNoActionTime();
|
|
if (noActionTime > 100) {
|
|
this.squid.movementVector = Vec3.ZERO;
|
|
diff --git a/net/minecraft/world/entity/animal/turtle/Turtle.java b/net/minecraft/world/entity/animal/turtle/Turtle.java
|
|
index d03a219af35e3c577386b87d553cc53c1e922553..53fc1012d46e20b623246cecae87b3feb1a0fda6 100644
|
|
--- a/net/minecraft/world/entity/animal/turtle/Turtle.java
|
|
+++ b/net/minecraft/world/entity/animal/turtle/Turtle.java
|
|
@@ -87,6 +87,23 @@ public class Turtle extends Animal {
|
|
this.moveControl = new Turtle.TurtleMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public void setHomePos(final BlockPos pos) {
|
|
this.homePos = pos;
|
|
}
|
|
@@ -145,6 +162,7 @@ public class Turtle extends Animal {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2));
|
|
this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0));
|
|
this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0));
|
|
@@ -485,12 +503,14 @@ public class Turtle extends Animal {
|
|
}
|
|
}
|
|
|
|
- private static class TurtleMoveControl extends MoveControl {
|
|
+ private static class TurtleMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
private final Turtle turtle;
|
|
+ private final org.purpurmc.purpur.controller.WaterMoveControllerWASD waterController; // Purpur - Ridables
|
|
|
|
TurtleMoveControl(final Turtle turtle) {
|
|
super(turtle);
|
|
this.turtle = turtle;
|
|
+ waterController = new org.purpurmc.purpur.controller.WaterMoveControllerWASD(turtle, 0.25D); // Purpur - Ridables
|
|
}
|
|
|
|
private void updateSpeed() {
|
|
@@ -509,7 +529,7 @@ public class Turtle extends Animal {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
this.updateSpeed();
|
|
if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) {
|
|
double xd = this.wantedX - this.turtle.getX();
|
|
@@ -523,7 +543,7 @@ public class Turtle extends Animal {
|
|
float yRotD = (float)(Mth.atan2(zd, xd) * 180.0F / (float)Math.PI) - 90.0F;
|
|
this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), yRotD, 90.0F));
|
|
this.turtle.yBodyRot = this.turtle.getYRot();
|
|
- float targetSpeed = (float)(this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float targetSpeed = (float)(this.getSpeedModifier() * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - Ridables
|
|
this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), targetSpeed));
|
|
this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, this.turtle.getSpeed() * yd * 0.1, 0.0));
|
|
}
|
|
diff --git a/net/minecraft/world/entity/animal/wolf/Wolf.java b/net/minecraft/world/entity/animal/wolf/Wolf.java
|
|
index 3519e9289f79d89bcaa3ad51fe07657018aa607f..17c3d76f0d606722dbc657250a85de9306838356 100644
|
|
--- a/net/minecraft/world/entity/animal/wolf/Wolf.java
|
|
+++ b/net/minecraft/world/entity/animal/wolf/Wolf.java
|
|
@@ -182,9 +182,32 @@ public class Wolf extends TamableAnimal implements NeutralMob {
|
|
}
|
|
// Purpur end - Configurable default collar color
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5, DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
|
|
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
|
|
this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5, 1.5));
|
|
@@ -197,6 +220,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new HurtByTargetGoal(this).setAlertOthers());
|
|
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
index 166361e45756b0cfce09502a89bd3a878820df08..bede0e9ce5b7c73d589511b71ad2a5f9e628eebc 100644
|
|
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
|
@@ -90,6 +90,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
private final net.minecraft.world.level.Explosion explosionSource; // Paper - reusable source for CraftTNTPrimed.getSource()
|
|
private @Nullable BlockPos podium;
|
|
// Paper end
|
|
+ private boolean hadRider; // Purpur - Ridables
|
|
|
|
public EnderDragon(final EntityType<? extends EnderDragon> type, final Level level) {
|
|
super(EntityType.ENDER_DRAGON, level);
|
|
@@ -106,6 +107,37 @@ public class EnderDragon extends Mob implements Enemy {
|
|
this.noPhysics = true;
|
|
this.phaseManager = new EnderDragonPhaseManager(this);
|
|
this.explosionSource = new net.minecraft.world.level.ServerExplosion(level.getMinecraftWorld(), this, null, null, new Vec3(Double.NaN, Double.NaN, Double.NaN), Float.NaN, true, net.minecraft.world.level.Explosion.BlockInteraction.DESTROY); // Paper
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+ }
|
|
+
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.enderDragonRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.enderDragonRidableInWater;
|
|
}
|
|
|
|
public void setDragonFight(final EnderDragonFight fight) {
|
|
@@ -120,6 +152,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 - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0).add(Attributes.CAMERA_DISTANCE, 16.0);
|
|
}
|
|
@@ -169,6 +212,37 @@ public class EnderDragon extends Mob implements Enemy {
|
|
|
|
@Override
|
|
public void aiStep() {
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+
|
|
this.processFlappingMovement();
|
|
if (this.level().isClientSide()) {
|
|
this.setHealth(this.getHealth());
|
|
@@ -197,6 +271,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
|
|
this.oFlapTime = this.flapTime;
|
|
if (this.isDeadOrDying()) {
|
|
+ if (hasRider) ejectPassengers(); // Purpur - Ridables
|
|
float xo = (this.random.nextFloat() - 0.5F) * 8.0F;
|
|
float yo = (this.random.nextFloat() - 0.5F) * 4.0F;
|
|
float zo = (this.random.nextFloat() - 0.5F) * 8.0F;
|
|
@@ -206,9 +281,9 @@ public class EnderDragon extends Mob implements Enemy {
|
|
Vec3 movement = this.getDeltaMovement();
|
|
float flapSpeed = 0.2F / ((float)movement.horizontalDistance() * 10.0F + 1.0F);
|
|
flapSpeed *= (float)Math.pow(2.0, movement.y);
|
|
- if (this.phaseManager.getCurrentPhase().isSitting()) {
|
|
+ if (!hasRider && this.phaseManager.getCurrentPhase().isSitting()) { // Purpur - Ridables
|
|
this.flapTime += 0.1F;
|
|
- } else if (this.inWall) {
|
|
+ } else if (!hasRider && this.inWall) { // Purpur - Ridables
|
|
this.flapTime += flapSpeed * 0.5F;
|
|
} else {
|
|
this.flapTime += flapSpeed;
|
|
@@ -219,7 +294,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
this.flapTime = 0.5F;
|
|
} else {
|
|
this.flightHistory.record(this.getY(), this.getYRot());
|
|
- if (this.level() instanceof ServerLevel level) {
|
|
+ if (this.level() instanceof ServerLevel level && !hasRider) { // Purpur - Ridables
|
|
DragonPhaseInstance currentPhase = this.phaseManager.getCurrentPhase();
|
|
currentPhase.doServerTick(level);
|
|
if (this.phaseManager.getCurrentPhase() != currentPhase) {
|
|
@@ -290,7 +365,7 @@ public class EnderDragon extends Mob implements Enemy {
|
|
this.tickPart(this.body, ss1 * 0.5F, 0.0, -cc1 * 0.5F);
|
|
this.tickPart(this.wing1, cc1 * 4.5F, 2.0, ss1 * 4.5F);
|
|
this.tickPart(this.wing2, cc1 * -4.5F, 2.0, ss1 * -4.5F);
|
|
- if (this.level() instanceof ServerLevel serverLevel && this.hurtTime == 0) {
|
|
+ if (this.level() instanceof ServerLevel serverLevel && this.hurtTime == 0 && !hasRider) { // Purpur - Ridables
|
|
this.knockBack(
|
|
serverLevel,
|
|
serverLevel.getEntities(
|
|
@@ -338,9 +413,9 @@ public class EnderDragon extends Mob implements Enemy {
|
|
}
|
|
|
|
if (this.level() instanceof ServerLevel level) {
|
|
- this.inWall = this.checkWalls(level, this.head.getBoundingBox())
|
|
+ this.inWall = !hasRider && this.checkWalls(level, this.head.getBoundingBox())
|
|
| this.checkWalls(level, this.neck.getBoundingBox())
|
|
- | this.checkWalls(level, this.body.getBoundingBox());
|
|
+ | this.checkWalls(level, this.body.getBoundingBox()); // Purpur - Ridables
|
|
if (this.dragonFight != null) {
|
|
this.dragonFight.updateDragon(this);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragonPart.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragonPart.java
|
|
index a8e3df21c27b9c86f9f03ea436ef4099a0805b71..a677aed54e16f3150ea1eabe22935a3d0d1507c4 100644
|
|
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragonPart.java
|
|
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragonPart.java
|
|
@@ -27,6 +27,13 @@ public class EnderDragonPart extends Entity {
|
|
this.name = name;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public net.minecraft.world.InteractionResult interact(final net.minecraft.world.entity.player.Player player, final net.minecraft.world.InteractionHand hand, final net.minecraft.world.phys.Vec3 location) {
|
|
+ return parentMob.isAlive() ? parentMob.tryRide(player, hand) : net.minecraft.world.InteractionResult.PASS;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
}
|
|
diff --git a/net/minecraft/world/entity/boss/wither/WitherBoss.java b/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
index 356e7f28786643e9cf2288addc3dac2a1ff4d617..852a604d8c06e9871da4c28d60b44a5869258011 100644
|
|
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
|
@@ -73,6 +73,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
private final int[] nextHeadUpdate = new int[2];
|
|
private final int[] idleHeadUpdates = new int[2];
|
|
private int destroyBlocksTick;
|
|
+ private int shootCooldown = 0; // Purpur - Ridables
|
|
private boolean canPortal = false; // Paper
|
|
public final ServerBossEvent bossEvent = Util.make(
|
|
new ServerBossEvent(Mth.createInsecureUUID(this.random), this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS),
|
|
@@ -82,10 +83,23 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
&& target.attackable();
|
|
private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0).selector(LIVING_ENTITY_SELECTOR);
|
|
private java.util.@Nullable UUID summoner; // Purpur - Summoner API
|
|
+ private org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD purpurController; // Purpur - Ridables
|
|
|
|
public WitherBoss(final EntityType<? extends WitherBoss> type, final Level level) {
|
|
super(type, level);
|
|
- this.moveControl = new FlyingMoveControl(this, 10, false);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
this.setHealth(this.getMaxHealth());
|
|
this.xpReward = 50;
|
|
}
|
|
@@ -100,6 +114,105 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
}
|
|
// Purpur end - Summoner API
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected PathNavigation createNavigation(final Level level) {
|
|
FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level);
|
|
@@ -110,11 +223,13 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal());
|
|
this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0, 40, 20.0F));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomFlyingGoal(this, 1.0));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, LIVING_ENTITY_SELECTOR));
|
|
}
|
|
@@ -274,6 +389,15 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
|
|
@Override
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
if (this.getInvulnerableTicks() > 0) {
|
|
int newCount = this.getInvulnerableTicks() - 1;
|
|
this.bossEvent.setProgress(1.0F - newCount / 220.0F);
|
|
@@ -581,11 +705,11 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
|
}
|
|
|
|
public int getAlternativeTarget(final int headIndex) {
|
|
- return this.entityData.get(DATA_TARGETS.get(headIndex));
|
|
+ return getRider() != null && this.isControllable() ? 0 : this.entityData.get(DATA_TARGETS.get(headIndex)); // Purpur - Ridables
|
|
}
|
|
|
|
public void setAlternativeTarget(final int headIndex, final int entityId) {
|
|
- this.entityData.set(DATA_TARGETS.get(headIndex), entityId);
|
|
+ if (getRider() == null || !this.isControllable()) this.entityData.set(DATA_TARGETS.get(headIndex), entityId); // Purpur - Ridables
|
|
}
|
|
|
|
public boolean isPowered() {
|
|
diff --git a/net/minecraft/world/entity/monster/Blaze.java b/net/minecraft/world/entity/monster/Blaze.java
|
|
index d48e066e8c43494aa74158452da369e5617d6a7e..c1acc0a648493ec33ef4fc4a48b52fe0b3dc04b2 100644
|
|
--- a/net/minecraft/world/entity/monster/Blaze.java
|
|
+++ b/net/minecraft/world/entity/monster/Blaze.java
|
|
@@ -34,6 +34,7 @@ public class Blaze extends Monster {
|
|
|
|
public Blaze(final EntityType<? extends Blaze> blaze, final Level level) {
|
|
super(blaze, level);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingWithSpacebarMoveControllerWASD(this, 0.3F); // Purpur - Ridables
|
|
this.setPathfindingMalus(PathType.WATER, -1.0F);
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
this.setPathfindingMalus(PathType.FIRE_IN_NEIGHBOR, 0.0F);
|
|
@@ -41,19 +42,55 @@ public class Blaze extends Monster {
|
|
this.xpReward = 10;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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 - Ridables
|
|
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 - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -118,6 +155,13 @@ public class Blaze extends Monster {
|
|
|
|
@Override
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
+ // Purpur start - Ridables
|
|
+ if (getRider() != null && this.isControllable()) {
|
|
+ Vec3 mot = getDeltaMovement();
|
|
+ setDeltaMovement(mot.x(), getVerticalMot() > 0 ? 0.07D : -0.07D, mot.z());
|
|
+ return;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
this.nextHeightOffsetChangeTick--;
|
|
if (this.nextHeightOffsetChangeTick <= 0) {
|
|
this.nextHeightOffsetChangeTick = 100;
|
|
diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java
|
|
index 4811c0607acbdf0e8f74327542560b96c84f728b..e5f7d276c083cdb78d2f420c03be1b08115d5597 100644
|
|
--- a/net/minecraft/world/entity/monster/Creeper.java
|
|
+++ b/net/minecraft/world/entity/monster/Creeper.java
|
|
@@ -57,21 +57,98 @@ public class Creeper extends Monster {
|
|
public boolean droppedSkulls;
|
|
public @Nullable Entity entityIgniter; // CraftBukkit
|
|
private boolean exploding = false; // Purpur - Config to make Creepers explode on death
|
|
+ // Purpur start - Ridables
|
|
+ private int spacebarCharge = 0;
|
|
+ private int prevSpacebarCharge = 0;
|
|
+ private int powerToggleDelay = 0;
|
|
+ // Purpur end - Ridables
|
|
|
|
public Creeper(final EntityType<? extends Creeper> type, final Level level) {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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(ServerLevel world) {
|
|
+ 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(world);
|
|
+ }
|
|
+
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
|
|
}
|
|
@@ -314,6 +391,7 @@ public class Creeper extends Monster {
|
|
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(DATA_IS_IGNITED, event.isIgnited());
|
|
+ if (!event.isIgnited()) setSwellDir(-1); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/ElderGuardian.java b/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
index ed994bae12ccf0500fb01ca84d40177b067b9ac2..b86f600b1101fe1fc9f7cac5cc47c3f048e0f885 100644
|
|
--- a/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
+++ b/net/minecraft/world/entity/monster/ElderGuardian.java
|
|
@@ -31,6 +31,18 @@ public class ElderGuardian extends Guardian {
|
|
}
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.elderGuardianRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.elderGuardianControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 8.0).add(Attributes.MAX_HEALTH, 80.0);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java
|
|
index 5b9733f1227f049ca3e00dc437fc3bc455271229..8b958dbdec8e68690525d345bd2f1038b1466ef9 100644
|
|
--- a/net/minecraft/world/entity/monster/EnderMan.java
|
|
+++ b/net/minecraft/world/entity/monster/EnderMan.java
|
|
@@ -89,9 +89,27 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
this.setPathfindingMalus(PathType.WATER, -1.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this));
|
|
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false));
|
|
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F));
|
|
@@ -99,6 +117,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 - Ridables
|
|
this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt));
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, 10, true, false, (entityliving, ignored) -> entityliving.level().purpurConfig.endermanAggroEndermites && entityliving instanceof Endermite endermite && (!entityliving.level().purpurConfig.endermanAggroEndermitesOnlyIfPlayerSpawned || endermite.isPlayerSpawned()))); // Purpur
|
|
@@ -263,7 +282,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
|
|
@Override
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
- if (level.isBrightOutside() && this.tickCount >= this.targetChangeTime + 600) {
|
|
+ if ((getRider() == null || !this.isControllable()) && level.isBrightOutside() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - Ridables - no random teleporting
|
|
float br = this.getLightLevelDependentMagicValue();
|
|
if (br > 0.5F && level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (br - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent
|
|
this.setTarget(null);
|
|
@@ -373,6 +392,7 @@ public class EnderMan extends Monster implements NeutralMob {
|
|
public boolean hurtServer(final ServerLevel level, final DamageSource source, final float damage) {
|
|
if (this.isInvulnerableTo(level, source)) {
|
|
return false;
|
|
+ } else if (getRider() != null && this.isControllable()) { return super.hurtServer(level, source, damage); // Purpur - no teleporting on damage
|
|
} else if (org.purpurmc.purpur.PurpurConfig.endermanShortHeight && source.is(net.minecraft.world.damagesource.DamageTypes.IN_WALL)) { return false; } // Purpur - no suffocation damage if short height - Short enderman height
|
|
|
|
AbstractThrownPotion thrownPotion = source.getDirectEntity() instanceof AbstractThrownPotion potion ? potion : null;
|
|
diff --git a/net/minecraft/world/entity/monster/Endermite.java b/net/minecraft/world/entity/monster/Endermite.java
|
|
index c5957be3e49710ac7d03cf5f1362d8745889fc16..8405358d2221d76bc0949047fcc6f17fdfc99dfc 100644
|
|
--- a/net/minecraft/world/entity/monster/Endermite.java
|
|
+++ b/net/minecraft/world/entity/monster/Endermite.java
|
|
@@ -47,14 +47,33 @@ public class Endermite extends Monster {
|
|
}
|
|
// Purpur end - Add back player spawned endermite API
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false));
|
|
this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/Ghast.java b/net/minecraft/world/entity/monster/Ghast.java
|
|
index f5b023651d6c3b21d3925856b5f851d879237381..0d40b789dc426c42aca47c01b4db57fb2b282f0d 100644
|
|
--- a/net/minecraft/world/entity/monster/Ghast.java
|
|
+++ b/net/minecraft/world/entity/monster/Ghast.java
|
|
@@ -53,11 +53,35 @@ public class Ghast extends Mob implements Enemy {
|
|
this.moveControl = new Ghast.GhastMoveControl(this, false, () -> false);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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 - Ridables
|
|
this.targetSelector
|
|
.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (target, level) -> Math.abs(target.getY() - this.getY()) <= 4.0));
|
|
}
|
|
@@ -102,6 +126,15 @@ public class Ghast extends Mob implements Enemy {
|
|
@Override
|
|
public void travel(final Vec3 input) {
|
|
this.travelFlying(input, 0.02F);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -237,7 +270,7 @@ public class Ghast extends Mob implements Enemy {
|
|
}
|
|
}
|
|
|
|
- public static class GhastMoveControl extends MoveControl {
|
|
+ public static class GhastMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur - Ridables
|
|
private final Mob ghast;
|
|
private int floatDuration;
|
|
private final boolean careful;
|
|
@@ -251,7 +284,7 @@ public class Ghast extends Mob implements Enemy {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (this.shouldBeStopped.getAsBoolean()) {
|
|
this.operation = MoveControl.Operation.WAIT;
|
|
this.ghast.stopInPlace();
|
|
diff --git a/net/minecraft/world/entity/monster/Giant.java b/net/minecraft/world/entity/monster/Giant.java
|
|
index 5f8074c93d2ad3d163bb416b16711d82edd7dacc..1b7a75a2be45928093382fa2f2da079ffc5d190d 100644
|
|
--- a/net/minecraft/world/entity/monster/Giant.java
|
|
+++ b/net/minecraft/world/entity/monster/Giant.java
|
|
@@ -12,6 +12,29 @@ public class Giant extends Monster {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes()
|
|
.add(Attributes.MAX_HEALTH, 100.0)
|
|
diff --git a/net/minecraft/world/entity/monster/Guardian.java b/net/minecraft/world/entity/monster/Guardian.java
|
|
index 45f972568e2b0aa16ca19f02dff7a790c694985f..6ad546f033919c6f0ba1091222a7af0f365fabb0 100644
|
|
--- a/net/minecraft/world/entity/monster/Guardian.java
|
|
+++ b/net/minecraft/world/entity/monster/Guardian.java
|
|
@@ -65,14 +65,35 @@ public class Guardian extends Monster {
|
|
this.xpReward = 10;
|
|
this.setPathfindingMalus(PathType.WATER, 0.0F);
|
|
this.moveControl = new Guardian.GuardianMoveControl(this);
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
this.clientSideTailAnimation = this.random.nextFloat();
|
|
this.clientSideTailAnimationO = this.clientSideTailAnimation;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.guardianRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.guardianControllable;
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
MoveTowardsRestrictionGoal goal = new MoveTowardsRestrictionGoal(this, 1.0);
|
|
this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80);
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field
|
|
this.goalSelector.addGoal(5, goal);
|
|
this.goalSelector.addGoal(7, this.randomStrollGoal);
|
|
@@ -81,6 +102,7 @@ public class Guardian extends Monster {
|
|
this.goalSelector.addGoal(9, new RandomLookAroundGoal(this));
|
|
this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
|
goal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this)));
|
|
}
|
|
|
|
@@ -344,7 +366,7 @@ public class Guardian extends Monster {
|
|
|
|
@Override
|
|
protected void travelInWater(final Vec3 input, final double baseGravity, final boolean isFalling, final double oldY) {
|
|
- this.moveRelative(0.1F, input);
|
|
+ this.moveRelative(getRider() != null && this.isControllable() ? getSpeed() : 0.1F, input); // Purpur - Ridables
|
|
this.move(MoverType.SELF, this.getDeltaMovement());
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
|
|
if (!this.isMoving() && this.getTarget() == null) {
|
|
@@ -449,7 +471,7 @@ public class Guardian extends Monster {
|
|
}
|
|
}
|
|
|
|
- private static class GuardianMoveControl extends MoveControl {
|
|
+ private static class GuardianMoveControl extends org.purpurmc.purpur.controller.WaterMoveControllerWASD { // Purpur - Ridables
|
|
private final Guardian guardian;
|
|
|
|
public GuardianMoveControl(final Guardian guardian) {
|
|
@@ -457,8 +479,17 @@ public class Guardian extends Monster {
|
|
this.guardian = guardian;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
@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 - Ridables
|
|
+
|
|
+ @Override
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) {
|
|
Vec3 delta = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ());
|
|
double length = delta.length();
|
|
@@ -468,7 +499,7 @@ public class Guardian extends Monster {
|
|
float yRotD = (float)(Mth.atan2(delta.z, delta.x) * 180.0F / (float)Math.PI) - 90.0F;
|
|
this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), yRotD, 90.0F));
|
|
this.guardian.yBodyRot = this.guardian.getYRot();
|
|
- float targetSpeed = (float)(this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float targetSpeed = (float)(this.getSpeedModifier() * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - Ridables
|
|
float newSpeed = Mth.lerp(0.125F, this.guardian.getSpeed(), targetSpeed);
|
|
this.guardian.setSpeed(newSpeed);
|
|
double push = Math.sin((this.guardian.tickCount + this.guardian.getId()) * 0.5) * 0.05;
|
|
diff --git a/net/minecraft/world/entity/monster/MagmaCube.java b/net/minecraft/world/entity/monster/MagmaCube.java
|
|
index f6021d3e41bcf7c65c708f9937bafafecea34ce3..600da11f46673177a0ff1f56c93a60d94df40025 100644
|
|
--- a/net/minecraft/world/entity/monster/MagmaCube.java
|
|
+++ b/net/minecraft/world/entity/monster/MagmaCube.java
|
|
@@ -24,6 +24,28 @@ public class MagmaCube extends Slime {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F);
|
|
}
|
|
@@ -76,6 +98,7 @@ public class MagmaCube extends Slime {
|
|
float sizeJumpBoostPower = this.getSize() * 0.1F;
|
|
this.setDeltaMovement(movement.x, this.getJumpPower() + sizeJumpBoostPower, movement.z);
|
|
this.needsSync = true;
|
|
+ this.actualJump = false; // Purpur - Ridables
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
|
|
index c3b6aab3eabb4b7efef17979a28246143d71e896..961a874d3eeee40d4c45ae511412ac0167ae54ac 100644
|
|
--- a/net/minecraft/world/entity/monster/Phantom.java
|
|
+++ b/net/minecraft/world/entity/monster/Phantom.java
|
|
@@ -61,6 +61,52 @@ public class Phantom extends Mob implements Enemy {
|
|
this.lookControl = new Phantom.PhantomLookControl(this);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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;
|
|
+ }
|
|
+
|
|
+ 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.projectile.PhantomFlames flames = new org.purpurmc.purpur.entity.projectile.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 - Ridables
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0;
|
|
@@ -73,9 +119,11 @@ public class Phantom extends Mob implements Enemy {
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal());
|
|
}
|
|
|
|
@@ -91,6 +139,7 @@ public class Phantom extends Mob implements Enemy {
|
|
|
|
private void updatePhantomSizeInfo() {
|
|
this.refreshDimensions();
|
|
+ if (level().purpurConfig.phantomFlamesOnSwoop && attackPhase == AttackPhase.SWOOP) shoot(); // Purpur - Ridables - Phantom flames on swoop
|
|
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(6 + this.getPhantomSize());
|
|
}
|
|
|
|
@@ -159,6 +208,15 @@ public class Phantom extends Mob implements Enemy {
|
|
@Override
|
|
public void travel(final Vec3 input) {
|
|
this.travelFlying(input, 0.2F);
|
|
+ // Purpur start - Ridables
|
|
+ if (this.getRider() != null && this.isControllable() && !this.onGround) {
|
|
+ float speed = (float) this.getAttributeValue(Attributes.FLYING_SPEED);
|
|
+ this.setSpeed(speed);
|
|
+ Vec3 mot = this.getDeltaMovement();
|
|
+ this.move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed));
|
|
+ this.setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -400,25 +458,42 @@ public class Phantom extends Mob implements Enemy {
|
|
}
|
|
}
|
|
|
|
- private static class PhantomLookControl extends LookControl {
|
|
+ private static class PhantomLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables
|
|
public PhantomLookControl(final Mob mob) {
|
|
super(mob);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ public void purpurTick(Player rider) {
|
|
+ setYawPitch(rider.getYRot(), -rider.xRotO * 0.75F);
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
}
|
|
}
|
|
|
|
- private class PhantomMoveControl extends MoveControl {
|
|
+ private class PhantomMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur - Ridables
|
|
private float speed = 0.1F;
|
|
|
|
public PhantomMoveControl(final Mob mob) {
|
|
super(mob);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (Phantom.this.horizontalCollision) {
|
|
Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F);
|
|
this.speed = 0.1F;
|
|
diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java
|
|
index c88545ac6fc99e5d055126ef39f799f9caef257b..1d02a5a037cb50844419ef41227be2427cdff4ca 100644
|
|
--- a/net/minecraft/world/entity/monster/Ravager.java
|
|
+++ b/net/minecraft/world/entity/monster/Ravager.java
|
|
@@ -70,15 +70,40 @@ public class Ravager extends Raider {
|
|
this.setPathfindingMalus(PathType.LEAVES, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
if (level().purpurConfig.ravagerAvoidRabbits) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.AvoidEntityGoal<>(this, net.minecraft.world.entity.animal.rabbit.Rabbit.class, 6.0F, 1.0D, 1.2D)); // Purpur - option to make ravagers afraid of rabbits
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(2, new HurtByTargetGoal(this, Raider.class).setAlertOthers());
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (target, level) -> !target.isBaby()));
|
|
@@ -135,7 +160,7 @@ public class Ravager extends Raider {
|
|
@Override
|
|
public void aiStep() {
|
|
super.aiStep();
|
|
- if (this.isAlive()) {
|
|
+ if (this.isAlive() && (getRider() == null || !this.isControllable())) { // Purpur - Ridables
|
|
if (this.isImmobile()) {
|
|
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0);
|
|
} else {
|
|
diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java
|
|
index 1f7a8b12a37b42fa38cb7136cd9ef5b3bab45d6b..746dfa496dc6cde62ab3c890aa6fbdbe68086ea9 100644
|
|
--- a/net/minecraft/world/entity/monster/Shulker.java
|
|
+++ b/net/minecraft/world/entity/monster/Shulker.java
|
|
@@ -109,12 +109,31 @@ public class Shulker extends AbstractGolem implements Enemy {
|
|
}
|
|
// Purpur end - Shulker change color with dye
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, this.getClass()).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this));
|
|
this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this));
|
|
@@ -709,7 +728,7 @@ public class Shulker extends AbstractGolem implements Enemy {
|
|
}
|
|
}
|
|
|
|
- private class ShulkerLookControl extends LookControl {
|
|
+ private class ShulkerLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables
|
|
public ShulkerLookControl(final Mob mob) {
|
|
super(mob);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/Silverfish.java b/net/minecraft/world/entity/monster/Silverfish.java
|
|
index 95896f9276f3d4afa8141f2beed06974240a1318..4bda4d98e94f906cd86eafd412dd393b534ff8df 100644
|
|
--- a/net/minecraft/world/entity/monster/Silverfish.java
|
|
+++ b/net/minecraft/world/entity/monster/Silverfish.java
|
|
@@ -38,14 +38,33 @@ public class Silverfish extends Monster {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
|
this.goalSelector.addGoal(3, this.friendsGoal);
|
|
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false));
|
|
this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers());
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/Slime.java b/net/minecraft/world/entity/monster/Slime.java
|
|
index 04f0c15a891c86ab42fe5aa719cb1357f68dd0f6..47c6dfee0254c4ccd62ed4ff584a78234284a815 100644
|
|
--- a/net/minecraft/world/entity/monster/Slime.java
|
|
+++ b/net/minecraft/world/entity/monster/Slime.java
|
|
@@ -60,6 +60,7 @@ public class Slime extends Mob implements Enemy {
|
|
public float oSquish;
|
|
private boolean wasOnGround = false;
|
|
private boolean canWander = true; // Paper - Slime pathfinder events
|
|
+ protected boolean actualJump; // Purpur - Ridables
|
|
|
|
public Slime(final EntityType<? extends Slime> type, final Level level) {
|
|
super(type, level);
|
|
@@ -67,12 +68,48 @@ public class Slime extends Mob implements Enemy {
|
|
this.moveControl = new Slime.SlimeMoveControl(this);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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 - Ridables
|
|
this.targetSelector
|
|
.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (target, level) -> Math.abs(target.getY() - this.getY()) <= 4.0));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
|
|
@@ -356,6 +393,7 @@ public class Slime extends Mob implements Enemy {
|
|
Vec3 movement = this.getDeltaMovement();
|
|
this.setDeltaMovement(movement.x, this.getJumpPower(), movement.z);
|
|
this.needsSync = true;
|
|
+ this.actualJump = false; // Purpur - Ridables
|
|
}
|
|
|
|
@Override
|
|
@@ -519,7 +557,7 @@ public class Slime extends Mob implements Enemy {
|
|
}
|
|
}
|
|
|
|
- private static class SlimeMoveControl extends MoveControl {
|
|
+ private static class SlimeMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
private float yRot;
|
|
private int jumpDelay;
|
|
private final Slime slime;
|
|
@@ -537,21 +575,33 @@ public class Slime extends Mob implements Enemy {
|
|
}
|
|
|
|
public void setWantedMovement(final double speedModifier) {
|
|
- this.speedModifier = speedModifier;
|
|
+ this.setSpeedModifier(speedModifier); // Purpur - Ridables
|
|
this.operation = MoveControl.Operation.MOVE_TO;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
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 - Ridables
|
|
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 - Ridables
|
|
if (this.jumpDelay-- <= 0) {
|
|
this.jumpDelay = this.slime.getJumpDelay();
|
|
if (this.isAggressive) {
|
|
@@ -568,7 +618,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 - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java
|
|
index 9bf12a67f7175ae7c7dadee84a5ab0de5cae43e8..039b83311bee193038968bf44c0bcbc98c5579df 100644
|
|
--- a/net/minecraft/world/entity/monster/Strider.java
|
|
+++ b/net/minecraft/world/entity/monster/Strider.java
|
|
@@ -93,6 +93,23 @@ public class Strider extends Animal implements ItemSteerable {
|
|
this.setPathfindingMalus(PathType.FIRE, 0.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static boolean checkStriderSpawnRules(
|
|
final EntityType<Strider> ignoredType,
|
|
final LevelAccessor level,
|
|
@@ -143,6 +160,7 @@ public class Strider extends Animal implements ItemSteerable {
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.65));
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
|
this.temptGoal = new TemptGoal(this, 1.4, i -> i.is(ItemTags.STRIDER_TEMPT_ITEMS), false);
|
|
this.goalSelector.addGoal(3, this.temptGoal);
|
|
@@ -422,7 +440,7 @@ public class Strider extends Animal implements ItemSteerable {
|
|
InteractionResult interactionResult = super.mobInteract(player, hand);
|
|
if (!interactionResult.consumesAction()) {
|
|
ItemStack itemStack = player.getItemInHand(hand);
|
|
- return this.isEquippableInSlot(itemStack, EquipmentSlot.SADDLE) ? itemStack.interactLivingEntity(player, this, hand) : InteractionResult.PASS;
|
|
+ return this.isEquippableInSlot(itemStack, EquipmentSlot.SADDLE) ? itemStack.interactLivingEntity(player, this, hand) : tryRide(player, hand); // Purpur - Ridables
|
|
}
|
|
|
|
if (hasFood && !this.isSilent()) {
|
|
diff --git a/net/minecraft/world/entity/monster/Vex.java b/net/minecraft/world/entity/monster/Vex.java
|
|
index e23aa0c86cd4070628f29b51eb4f804bb63a4f27..0621c1a46c392b8fcf5235f7483d0d8a0ac598ed 100644
|
|
--- a/net/minecraft/world/entity/monster/Vex.java
|
|
+++ b/net/minecraft/world/entity/monster/Vex.java
|
|
@@ -58,6 +58,50 @@ public class Vex extends Monster implements TraceableEntity {
|
|
this.xpReward = 3;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed));
|
|
+ setDeltaMovement(mot.scale(0.9D));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean causeFallDamage(double fallDistance, float damageMultiplier, DamageSource damageSource) {
|
|
+ return false; // no fall damage please
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public boolean isFlapping() {
|
|
return this.tickCount % TICKS_PER_FLAP == 0;
|
|
@@ -70,7 +114,7 @@ public class Vex extends Monster implements TraceableEntity {
|
|
|
|
@Override
|
|
public void tick() {
|
|
- this.noPhysics = true;
|
|
+ this.noPhysics = getRider() == null || !this.isControllable(); // Purpur - Ridables
|
|
super.tick();
|
|
this.noPhysics = false;
|
|
this.setNoGravity(true);
|
|
@@ -84,17 +128,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 - Ridables
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, 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.0).add(Attributes.ATTACK_DAMAGE, 4.0);
|
|
+ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0).add(Attributes.ATTACK_DAMAGE, 4.0).add(Attributes.FLYING_SPEED, 0.6D); // Purpur;
|
|
}
|
|
|
|
@Override
|
|
@@ -293,13 +339,13 @@ public class Vex extends Monster implements TraceableEntity {
|
|
}
|
|
}
|
|
|
|
- private class VexMoveControl extends MoveControl {
|
|
+ private class VexMoveControl extends org.purpurmc.purpur.controller.FlyingMoveControllerWASD { // Purpur - Ridables
|
|
public VexMoveControl(final Vex vex) {
|
|
super(vex);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (this.operation == MoveControl.Operation.MOVE_TO) {
|
|
Vec3 delta = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ());
|
|
double deltaLength = delta.length();
|
|
@@ -307,7 +353,7 @@ public class Vex extends Monster implements TraceableEntity {
|
|
this.operation = MoveControl.Operation.WAIT;
|
|
Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5));
|
|
} else {
|
|
- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(delta.scale(this.speedModifier * 0.05 / deltaLength)));
|
|
+ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(delta.scale(this.getSpeedModifier() * 0.05 / deltaLength))); // Purpur - Ridables
|
|
if (Vex.this.getTarget() == null) {
|
|
Vec3 movement = Vex.this.getDeltaMovement();
|
|
Vex.this.setYRot(-((float)Mth.atan2(movement.x, movement.z)) * Mth.RAD_TO_DEG);
|
|
diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java
|
|
index 205b55db821ab81883c23c194cdb12cd57061fb9..7551dcf0bd8d0ff6deffb298211788d5ff91d93b 100644
|
|
--- a/net/minecraft/world/entity/monster/Witch.java
|
|
+++ b/net/minecraft/world/entity/monster/Witch.java
|
|
@@ -57,6 +57,23 @@ public class Witch extends Raider implements RangedAttackMob {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
super.registerGoals();
|
|
@@ -65,10 +82,12 @@ public class Witch extends Raider implements RangedAttackMob {
|
|
);
|
|
this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, null);
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0, 60, 10.0F));
|
|
this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class));
|
|
this.targetSelector.addGoal(2, this.healRaidersGoal);
|
|
this.targetSelector.addGoal(3, this.attackPlayersGoal);
|
|
diff --git a/net/minecraft/world/entity/monster/Zoglin.java b/net/minecraft/world/entity/monster/Zoglin.java
|
|
index 95e5773fe060bdc42847fdf56801eb4fe1494c56..1a5e3a38671602e097e1e7f00d8f80e46b1596a0 100644
|
|
--- a/net/minecraft/world/entity/monster/Zoglin.java
|
|
+++ b/net/minecraft/world/entity/monster/Zoglin.java
|
|
@@ -76,6 +76,23 @@ public class Zoglin extends Monster implements HoglinBase {
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected Brain<Zoglin> makeBrain(final Brain.Packed packedBrain) {
|
|
return BRAIN_PROVIDER.makeBrain(this, packedBrain);
|
|
@@ -227,6 +244,7 @@ public class Zoglin extends Monster implements HoglinBase {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("zoglinBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
this.updateActivity();
|
|
diff --git a/net/minecraft/world/entity/monster/breeze/Breeze.java b/net/minecraft/world/entity/monster/breeze/Breeze.java
|
|
index a58ad6176864c299725f5d51b3c239259f3b9c20..ec4d124b6a714d6b57d006ba70d838a35e62df75 100644
|
|
--- a/net/minecraft/world/entity/monster/breeze/Breeze.java
|
|
+++ b/net/minecraft/world/entity/monster/breeze/Breeze.java
|
|
@@ -233,6 +233,7 @@ public class Breeze extends Monster {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("breezeBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.popPush("breezeActivityUpdate");
|
|
BreezeAi.updateActivity(this);
|
|
diff --git a/net/minecraft/world/entity/monster/creaking/Creaking.java b/net/minecraft/world/entity/monster/creaking/Creaking.java
|
|
index 7e4910d8492dae511db604e52fe5dfa6373c76ee..fdbf9b64871c5cdb7ed9fa56c669bd77d1a19ac2 100644
|
|
--- a/net/minecraft/world/entity/monster/creaking/Creaking.java
|
|
+++ b/net/minecraft/world/entity/monster/creaking/Creaking.java
|
|
@@ -106,6 +106,29 @@ public class Creaking extends Monster {
|
|
return this.getHomePos() != null;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean isRidable() {
|
|
+ return level().purpurConfig.creakingRidable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean dismountsUnderwater() {
|
|
+ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.creakingRidableInWater;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isControllable() {
|
|
+ return level().purpurConfig.creakingControllable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected BodyRotationControl createBodyControl() {
|
|
return new Creaking.CreakingBodyRotationControl(this);
|
|
@@ -548,28 +571,28 @@ public class Creaking extends Monster {
|
|
}
|
|
}
|
|
|
|
- private class CreakingLookControl extends LookControl {
|
|
+ private class CreakingLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur - Ridables {
|
|
public CreakingLookControl(final Creaking creaking) {
|
|
super(creaking);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (Creaking.this.canMove()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
|
|
- private class CreakingMoveControl extends MoveControl {
|
|
+ private class CreakingMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
public CreakingMoveControl(final Creaking creaking) {
|
|
super(creaking);
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
if (Creaking.this.canMove()) {
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
index e3f59999c9592af213b21afb43bcaddb94fd8279..7ba62badc9b832bdedbec5984421abfee242fa16 100644
|
|
--- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
+++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
|
@@ -73,6 +73,23 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@VisibleForTesting
|
|
public void setTimeInOverworld(final int timeInOverworld) {
|
|
this.timeInOverworld = timeInOverworld;
|
|
@@ -136,6 +153,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("hoglinBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
HoglinAi.updateActivity(this);
|
|
diff --git a/net/minecraft/world/entity/monster/illager/Evoker.java b/net/minecraft/world/entity/monster/illager/Evoker.java
|
|
index 442940e8bbcd45271e71d91ecae9adbb0ef6fae2..2d8654f1b16ee3177466dc21aff7c2bdbce310a7 100644
|
|
--- a/net/minecraft/world/entity/monster/illager/Evoker.java
|
|
+++ b/net/minecraft/world/entity/monster/illager/Evoker.java
|
|
@@ -49,10 +49,28 @@ public class Evoker extends SpellcasterIllager {
|
|
this.xpReward = 10;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal());
|
|
this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6, 1.0));
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 0.6, 1.0));
|
|
@@ -62,6 +80,7 @@ public class Evoker extends SpellcasterIllager {
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, 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/net/minecraft/world/entity/monster/illager/Illusioner.java b/net/minecraft/world/entity/monster/illager/Illusioner.java
|
|
index f4b93c3dd12d762f280c7b52af5d3b5f58cb9cef..9ea4745eb0d72c25ac5b89a6bfa5ba2846740f07 100644
|
|
--- a/net/minecraft/world/entity/monster/illager/Illusioner.java
|
|
+++ b/net/minecraft/world/entity/monster/illager/Illusioner.java
|
|
@@ -59,10 +59,28 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob {
|
|
}
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal());
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal());
|
|
@@ -71,6 +89,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob {
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, 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/net/minecraft/world/entity/monster/illager/Pillager.java b/net/minecraft/world/entity/monster/illager/Pillager.java
|
|
index 0385a6d602d80cb0f19b8ec4c982641c2f7e9f23..510a1d4e1e44bda60ee05f0799a8930403f3eb7e 100644
|
|
--- a/net/minecraft/world/entity/monster/illager/Pillager.java
|
|
+++ b/net/minecraft/world/entity/monster/illager/Pillager.java
|
|
@@ -65,16 +65,35 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(2, new Raider.HoldGroundAttackGoal(this, 10.0F));
|
|
this.goalSelector.addGoal(3, new RangedCrossbowAttackGoal<>(this, 1.0, 8.0F));
|
|
this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6));
|
|
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 - Ridables
|
|
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, false));
|
|
diff --git a/net/minecraft/world/entity/monster/illager/Vindicator.java b/net/minecraft/world/entity/monster/illager/Vindicator.java
|
|
index 4404765ba6b971f5525d3fba73a57d17d5f16dec..c3164a33fd8010e1920eead11c482641f17b3a65 100644
|
|
--- a/net/minecraft/world/entity/monster/illager/Vindicator.java
|
|
+++ b/net/minecraft/world/entity/monster/illager/Vindicator.java
|
|
@@ -57,15 +57,34 @@ public class Vindicator extends AbstractIllager {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@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 - Ridables
|
|
this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(2, new Vindicator.VindicatorBreakDoorGoal(this));
|
|
this.goalSelector.addGoal(3, new AbstractIllager.RaiderOpenDoorGoal(this));
|
|
this.goalSelector.addGoal(4, new Raider.HoldGroundAttackGoal(this, 10.0F));
|
|
this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, false));
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
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/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
index a6623851235d8c6fa6fe7519b5d04674ecd31eb5..f617f3cbd41e9b60faf1489dd32972c6a2467fe1 100644
|
|
--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
|
@@ -108,6 +108,23 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
|
this.xpReward = 5;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void addAdditionalSaveData(final ValueOutput output) {
|
|
super.addAdditionalSaveData(output);
|
|
@@ -287,6 +304,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("piglinBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
PiglinAi.updateActivity(this);
|
|
diff --git a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
index ca543d886dee48a03175d0c96051d4f956d33a9d..75fea76d60b76a81646aa3ae4defa6cc5385d78c 100644
|
|
--- a/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
+++ b/net/minecraft/world/entity/monster/piglin/PiglinBrute.java
|
|
@@ -50,6 +50,23 @@ public class PiglinBrute extends AbstractPiglin {
|
|
this.xpReward = 20;
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static AttributeSupplier.Builder createAttributes() {
|
|
return Monster.createMonsterAttributes()
|
|
.add(Attributes.MAX_HEALTH, 50.0)
|
|
@@ -96,6 +113,7 @@ public class PiglinBrute extends AbstractPiglin {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("piglinBruteBrain");
|
|
+ if (getRider() == null || this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
PiglinBruteAi.updateActivity(this);
|
|
diff --git a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
|
|
index 297d7ce0e5e38471f22dd61123ccf0348e85b9bf..695dca87fc3ef633290f9abe1089e7a6a0e7feb9 100644
|
|
--- a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
|
|
+++ b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
|
|
@@ -75,12 +75,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 - Ridables
|
|
this.goalSelector.addGoal(2, new RestrictSunGoal(this));
|
|
this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0));
|
|
this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0, 1.2));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
|
|
diff --git a/net/minecraft/world/entity/monster/skeleton/Bogged.java b/net/minecraft/world/entity/monster/skeleton/Bogged.java
|
|
index f157729acf531c08543d800c824b462dc4e080f0..87b03adc6b8c18e489b3bcdc04d155719ab59e98 100644
|
|
--- a/net/minecraft/world/entity/monster/skeleton/Bogged.java
|
|
+++ b/net/minecraft/world/entity/monster/skeleton/Bogged.java
|
|
@@ -41,6 +41,23 @@ public class Bogged extends AbstractSkeleton implements Shearable {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/monster/skeleton/Skeleton.java b/net/minecraft/world/entity/monster/skeleton/Skeleton.java
|
|
index 96da8225680bdc7c6b2c337a931858e383f329e3..06bae8a804bc7ac47dc21c915f386ca1dd07cd7f 100644
|
|
--- a/net/minecraft/world/entity/monster/skeleton/Skeleton.java
|
|
+++ b/net/minecraft/world/entity/monster/skeleton/Skeleton.java
|
|
@@ -26,6 +26,23 @@ public class Skeleton extends AbstractSkeleton {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/monster/skeleton/Stray.java b/net/minecraft/world/entity/monster/skeleton/Stray.java
|
|
index dd5db995d603cc9c8a263255a16dedb766244499..1d706fe3bca726a4e606232039beeadedf75b499 100644
|
|
--- a/net/minecraft/world/entity/monster/skeleton/Stray.java
|
|
+++ b/net/minecraft/world/entity/monster/skeleton/Stray.java
|
|
@@ -23,6 +23,23 @@ public class Stray extends AbstractSkeleton {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
public static boolean checkStraySpawnRules(
|
|
final EntityType<Stray> type, final ServerLevelAccessor level, final EntitySpawnReason spawnReason, final BlockPos pos, final RandomSource random
|
|
) {
|
|
diff --git a/net/minecraft/world/entity/monster/skeleton/WitherSkeleton.java b/net/minecraft/world/entity/monster/skeleton/WitherSkeleton.java
|
|
index de05a15d4609bb76c57101b8c5a3a3600833fd2d..3651c21dc87a76ad4aa268a2de6686016b589e6c 100644
|
|
--- a/net/minecraft/world/entity/monster/skeleton/WitherSkeleton.java
|
|
+++ b/net/minecraft/world/entity/monster/skeleton/WitherSkeleton.java
|
|
@@ -34,6 +34,23 @@ public class WitherSkeleton extends AbstractSkeleton {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true));
|
|
diff --git a/net/minecraft/world/entity/monster/spider/CaveSpider.java b/net/minecraft/world/entity/monster/spider/CaveSpider.java
|
|
index fe82f97689305de64caa52ef648308431f4aebb1..59265f8286a32a1fe7de1986df78b441861e9367 100644
|
|
--- a/net/minecraft/world/entity/monster/spider/CaveSpider.java
|
|
+++ b/net/minecraft/world/entity/monster/spider/CaveSpider.java
|
|
@@ -26,6 +26,23 @@ public class CaveSpider extends Spider {
|
|
return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public boolean doHurtTarget(final ServerLevel level, final Entity target) {
|
|
if (super.doHurtTarget(level, target)) {
|
|
diff --git a/net/minecraft/world/entity/monster/spider/Spider.java b/net/minecraft/world/entity/monster/spider/Spider.java
|
|
index 1507f340b16fd95985bfe49870e923c626833d18..546561f6b9960de22d84468a317c65f3cf406b29 100644
|
|
--- a/net/minecraft/world/entity/monster/spider/Spider.java
|
|
+++ b/net/minecraft/world/entity/monster/spider/Spider.java
|
|
@@ -52,15 +52,34 @@ public class Spider extends Monster {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
+ this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Armadillo.class, 6.0F, 1.0, 1.2, entity -> !((Armadillo)entity).isScared()));
|
|
this.goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4F));
|
|
this.goalSelector.addGoal(4, new Spider.SpiderAttackGoal(this));
|
|
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8));
|
|
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 - Ridables
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
|
this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class));
|
|
this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class));
|
|
diff --git a/net/minecraft/world/entity/monster/warden/Warden.java b/net/minecraft/world/entity/monster/warden/Warden.java
|
|
index 72332ef3956b0cc1550221dfa6179ea0a6ecc87a..4af25b2afa2cb8a2fec84d9281bd386d1517a644 100644
|
|
--- a/net/minecraft/world/entity/monster/warden/Warden.java
|
|
+++ b/net/minecraft/world/entity/monster/warden/Warden.java
|
|
@@ -132,8 +132,32 @@ public class Warden extends Monster implements VibrationSystem {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
this.setPathfindingMalus(PathType.FIRE, 0.0F);
|
|
this.setPathfindingMalus(PathType.FIRE_IN_NEIGHBOR, 0.0F);
|
|
+ this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this, 0.5F); // Purpur - Ridables
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
public Packet<ClientGamePacketListener> getAddEntityPacket(final ServerEntity serverEntity) {
|
|
return new ClientboundAddEntityPacket(this, serverEntity, this.hasPose(Pose.EMERGING) ? 1 : 0);
|
|
@@ -288,6 +312,7 @@ public class Warden extends Monster implements VibrationSystem {
|
|
protected void customServerAiStep(final ServerLevel level) {
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("wardenBrain");
|
|
+ if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider
|
|
this.getBrain().tick(level, this);
|
|
profiler.pop();
|
|
super.customServerAiStep(level);
|
|
@@ -390,6 +415,7 @@ public class Warden extends Monster implements VibrationSystem {
|
|
|
|
@Contract("null->false")
|
|
public boolean canTargetEntity(final @Nullable Entity entity) {
|
|
+ if (getRider() != null && isControllable()) return false; // Purpur - Ridables
|
|
return entity instanceof LivingEntity livingEntity
|
|
&& this.level() == entity.level()
|
|
&& EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity)
|
|
diff --git a/net/minecraft/world/entity/monster/zombie/Drowned.java b/net/minecraft/world/entity/monster/zombie/Drowned.java
|
|
index 78cb0e6d7161aaf2da9bc0ef90bc5946e98c8129..643cf630000cd389ff7ae073a1850f2ae3f4a458 100644
|
|
--- a/net/minecraft/world/entity/monster/zombie/Drowned.java
|
|
+++ b/net/minecraft/world/entity/monster/zombie/Drowned.java
|
|
@@ -81,6 +81,23 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
return Zombie.createAttributes().add(Attributes.STEP_HEIGHT, 1.0);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected PathNavigation createNavigation(final Level level) {
|
|
return new AmphibiousPathNavigation(this, level);
|
|
@@ -447,7 +464,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
}
|
|
}
|
|
|
|
- private static class DrownedMoveControl extends MoveControl {
|
|
+ private static class DrownedMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur - Ridables
|
|
private final Drowned drowned;
|
|
|
|
public DrownedMoveControl(final Drowned drowned) {
|
|
@@ -456,7 +473,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
}
|
|
|
|
@Override
|
|
- public void tick() {
|
|
+ public void vanillaTick() { // Purpur - Ridables
|
|
LivingEntity target = this.drowned.getTarget();
|
|
if (this.drowned.wantsToSwim() && this.drowned.isInWater()) {
|
|
if (target != null && target.getY() > this.drowned.getY() || this.drowned.searchingForLand) {
|
|
@@ -476,7 +493,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
float yRotD = (float)(Mth.atan2(zd, xd) * 180.0F / (float)Math.PI) - 90.0F;
|
|
this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), yRotD, 90.0F));
|
|
this.drowned.yBodyRot = this.drowned.getYRot();
|
|
- float targetSpeed = (float)(this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
|
+ float targetSpeed = (float)(this.getSpeedModifier() * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - Ridables
|
|
float newSpeed = Mth.lerp(0.125F, this.drowned.getSpeed(), targetSpeed);
|
|
this.drowned.setSpeed(newSpeed);
|
|
this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(newSpeed * xd * 0.005, newSpeed * yd * 0.1, newSpeed * zd * 0.005));
|
|
@@ -485,7 +502,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
|
this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0));
|
|
}
|
|
|
|
- super.tick();
|
|
+ super.vanillaTick(); // Purpur - Ridables
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/monster/zombie/Husk.java b/net/minecraft/world/entity/monster/zombie/Husk.java
|
|
index 4e5f6cf6c8ffc965fd3e6b3069998d2b39e4e779..dfb43d27865674f4f13050682eda38afe2731f00 100644
|
|
--- a/net/minecraft/world/entity/monster/zombie/Husk.java
|
|
+++ b/net/minecraft/world/entity/monster/zombie/Husk.java
|
|
@@ -37,6 +37,23 @@ public class Husk extends Zombie {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public boolean isSunSensitive() {
|
|
return false;
|
|
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
|
index 6f5bdf9657a8b30d8b9390e02e1660eba31b096a..5d86cfd5c5d679368ddebf1afd7e32702b6e34a9 100644
|
|
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
|
|
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
|
@@ -112,11 +112,30 @@ public class Zombie extends Monster {
|
|
this(EntityType.ZOMBIE, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
|
if (this.level().paperConfig().entities.behavior.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0, 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 - Ridables
|
|
this.addBehaviourGoals();
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
|
|
index 591df33e1f0c8d49633180c2a10555072e4304e3..b3735610f347cb6275314dc7cd3dab56e26db85a 100644
|
|
--- a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
|
|
+++ b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
|
|
@@ -85,6 +85,23 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
|
|
super(type, level);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
diff --git a/net/minecraft/world/entity/monster/zombie/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/zombie/ZombifiedPiglin.java
|
|
index 2d294595b2d9e4daaf221482514329126d59f077..eb3ec4314603f61a041740d5b5e52165dac6ebc6 100644
|
|
--- a/net/minecraft/world/entity/monster/zombie/ZombifiedPiglin.java
|
|
+++ b/net/minecraft/world/entity/monster/zombie/ZombifiedPiglin.java
|
|
@@ -68,6 +68,23 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
|
|
this.setPathfindingMalus(PathType.LAVA, 8.0F);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void addBehaviourGoals() {
|
|
this.goalSelector.addGoal(1, new SpearUseGoal<>(this, 1.0, 1.0, 10.0F, 2.0F));
|
|
diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java
|
|
index 18e4071adb53edf1e511893dc2a21d955ba55900..627461178e2ab4f59699e04b16d8d0f337a0daba 100644
|
|
--- a/net/minecraft/world/entity/npc/villager/Villager.java
|
|
+++ b/net/minecraft/world/entity/npc/villager/Villager.java
|
|
@@ -252,6 +252,28 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
|
}
|
|
// Purpur end - Lobotomize stuck villagers
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
public Brain<Villager> getBrain() {
|
|
return (Brain<Villager>) super.getBrain();
|
|
@@ -332,7 +354,7 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
|
} else {
|
|
this.isLobotomized = false;
|
|
}
|
|
- if (!inactive) {
|
|
+ if (!inactive && (getRider() == null || !this.isControllable())) { // Purpur - Ridables
|
|
this.getBrain().tick(level, this); // Paper - EAR 2
|
|
}
|
|
else if (this.isLobotomized && shouldRestock(level)) restock();
|
|
@@ -394,7 +416,7 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
|
|
|
if (this.isBaby()) {
|
|
this.setUnhappy();
|
|
- return InteractionResult.SUCCESS;
|
|
+ return tryRide(player, hand, InteractionResult.SUCCESS); // Purpur - Ridables
|
|
}
|
|
|
|
if (!this.level().isClientSide()) {
|
|
@@ -408,9 +430,11 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
|
}
|
|
|
|
if (noOffers) {
|
|
- return InteractionResult.CONSUME;
|
|
+ return tryRide(player, hand, InteractionResult.CONSUME); // Purpur - Ridables
|
|
}
|
|
|
|
+ if (level().purpurConfig.villagerRidable && itemStack.isEmpty()) return tryRide(player, hand); // Purpur - Ridables
|
|
+
|
|
if (this.level().purpurConfig.villagerAllowTrading) // Purpur - Add config for villager trading
|
|
this.startTrading(player);
|
|
}
|
|
diff --git a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
|
index f99d5379a83dc9aabe8c8fef52bb2b0cccc40e19..4c35ca3877b88b13a1919d0625e5055b4554057f 100644
|
|
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
|
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
|
@@ -67,6 +67,23 @@ public class WanderingTrader extends AbstractVillager implements Consumable.Over
|
|
}
|
|
// Purpur end - Allow leashing villagers
|
|
|
|
+ // Purpur - start - Ridables
|
|
+ @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 - Ridables
|
|
+
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(0, new FloatGoal(this));
|
|
@@ -124,8 +141,9 @@ public class WanderingTrader extends AbstractVillager implements Consumable.Over
|
|
|
|
if (!this.level().isClientSide()) {
|
|
if (this.getOffers().isEmpty()) {
|
|
- return InteractionResult.CONSUME;
|
|
+ return tryRide(player, hand, InteractionResult.CONSUME); // Purpur - Ridables
|
|
}
|
|
+ if (level().purpurConfig.wanderingTraderRidable && itemStack.isEmpty()) return tryRide(player, hand); // Purpur - Ridables
|
|
|
|
if (this.level().purpurConfig.wanderingTraderAllowTrading) { // Purpur - Add config for villager trading
|
|
this.setTradingPlayer(player);
|
|
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
|
index 7c4ae5904081da7b0e4c135c243f2d9cebb161d9..3b0a0525cdca3ea5b91834e04b42696a7cedde10 100644
|
|
--- a/net/minecraft/world/entity/player/Player.java
|
|
+++ b/net/minecraft/world/entity/player/Player.java
|
|
@@ -193,6 +193,19 @@ public abstract class Player extends Avatar implements ContainerUser {
|
|
}
|
|
// CraftBukkit end
|
|
|
|
+ // Purpur start - Ridables
|
|
+ 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 - Ridables
|
|
+
|
|
public Player(final Level level, final GameProfile gameProfile) {
|
|
super(EntityType.PLAYER, level);
|
|
this.setUUID(gameProfile.id());
|
|
diff --git a/net/minecraft/world/entity/projectile/LlamaSpit.java b/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
index aeec4864cc80d4cc470464a01b7cae9b85e6bf9e..83ea958fd688f25d5fa7b1a1718d9932e901fee1 100644
|
|
--- a/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
+++ b/net/minecraft/world/entity/projectile/LlamaSpit.java
|
|
@@ -33,6 +33,12 @@ public class LlamaSpit extends Projectile {
|
|
);
|
|
}
|
|
|
|
+ // Purpur start - Ridables
|
|
+ public void projectileTick() {
|
|
+ super.tick();
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected double getDefaultGravity() {
|
|
return 0.06;
|
|
diff --git a/net/minecraft/world/entity/projectile/hurtingprojectile/WitherSkull.java b/net/minecraft/world/entity/projectile/hurtingprojectile/WitherSkull.java
|
|
index 92ef3b07a79b9a274675f9db54444a8083b15cf5..d713721f92717df7d184d790ff14e6b87ba832de 100644
|
|
--- a/net/minecraft/world/entity/projectile/hurtingprojectile/WitherSkull.java
|
|
+++ b/net/minecraft/world/entity/projectile/hurtingprojectile/WitherSkull.java
|
|
@@ -110,6 +110,14 @@ public class WitherSkull extends AbstractHurtingProjectile {
|
|
}
|
|
// Purpur end - Add canSaveToDisk to Entity
|
|
|
|
+ // Purpur start - Ridables
|
|
+ @Override
|
|
+ public boolean canHitEntity(Entity target) {
|
|
+ // do not hit rider
|
|
+ return target != this.getRider() && super.canHitEntity(target);
|
|
+ }
|
|
+ // Purpur end - Ridables
|
|
+
|
|
@Override
|
|
protected void defineSynchedData(final SynchedEntityData.Builder entityData) {
|
|
entityData.define(DATA_DANGEROUS, false);
|