Use Minecraft's no gravity logic and enable it for all default flying NPCs

This commit is contained in:
fullwall 2020-03-02 14:51:54 +08:00
parent bd95e7d364
commit 496a4cbb3b
13 changed files with 120 additions and 72 deletions

View File

@ -41,6 +41,7 @@ import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.ai.CitizensNavigator;
import net.citizensnpcs.npc.skin.SkinnableEntity;
import net.citizensnpcs.trait.CurrentLocation;
import net.citizensnpcs.trait.Gravity;
import net.citizensnpcs.trait.ScoreboardTrait;
import net.citizensnpcs.util.ChunkCoord;
import net.citizensnpcs.util.Messages;
@ -302,6 +303,8 @@ public class CitizensNPC extends AbstractNPC {
}
}
updateFlyableState();
return true;
}
@ -400,7 +403,12 @@ public class CitizensNPC extends AbstractNPC {
if (type == null)
return;
if (Util.isAlwaysFlyable(type)) {
data().setPersistent(NPC.FLYABLE_METADATA, true);
if (!data().has(NPC.FLYABLE_METADATA)) {
data().setPersistent(NPC.FLYABLE_METADATA, true);
}
if (!hasTrait(Gravity.class)) {
getTrait(Gravity.class).setEnabled(true);
}
}
}

View File

@ -1,13 +1,12 @@
package net.citizensnpcs.trait;
import org.bukkit.util.Vector;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.util.NMS;
/**
* Enable/disable gravity. Without gravity the y velocity of the NPC is always set to <code>0</code>
* Enable/disable Minecraft's gravity.
*/
@TraitName("gravity")
public class Gravity extends Trait implements Toggleable {
@ -36,11 +35,11 @@ public class Gravity extends Trait implements Toggleable {
public void run() {
if (!npc.isSpawned())
return;
if (!enabled || npc.getNavigator().isNavigating())
return;
Vector vector = npc.getEntity().getVelocity();
vector.setY(Math.max(0, vector.getY()));
npc.getEntity().setVelocity(vector);
NMS.setNoGravity(npc.getEntity(), enabled);
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override

View File

@ -382,6 +382,10 @@ public class NMS {
BRIDGE.setNavigationTarget(handle, target, speed);
}
public static void setNoGravity(Entity entity, boolean enabled) {
BRIDGE.setNoGravity(entity, enabled);
}
public static void setPandaSitting(Entity entity, boolean sitting) {
BRIDGE.setPandaSitting(entity, sitting);
}

View File

@ -126,6 +126,8 @@ public interface NMSBridge {
public void setNavigationTarget(Entity handle, Entity target, float speed);
public void setNoGravity(Entity entity, boolean enabled);
public void setPandaSitting(Entity entity, boolean sitting);
public void setPeekShulker(Entity entity, int peek);

View File

@ -882,6 +882,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}

View File

@ -940,6 +940,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}

View File

@ -953,6 +953,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}

View File

@ -988,6 +988,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}

View File

@ -1037,6 +1037,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}

View File

@ -1,7 +1,5 @@
package net.citizensnpcs.nms.v1_15_R1.entity;
import net.minecraft.server.v1_15_R1.Vec3D;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_15_R1.CraftServer;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftBat;
@ -63,6 +61,13 @@ public class BatController extends MobEntityController {
}
}
@Override
public void checkDespawn() {
if (npc == null) {
super.checkDespawn();
}
}
@Override
public void collide(net.minecraft.server.v1_15_R1.Entity entity) {
// this method is called by both the entities involved - cancelling
@ -73,26 +78,11 @@ public class BatController extends MobEntityController {
}
}
@Override
protected SoundEffect getSoundDeath() {
return NMSImpl.getSoundEffect(npc, super.getSoundDeath(), NPC.DEATH_SOUND_METADATA);
}
@Override
protected SoundEffect getSoundHurt(DamageSource damagesource) {
return NMSImpl.getSoundEffect(npc, super.getSoundHurt(damagesource), NPC.HURT_SOUND_METADATA);
}
@Override
public boolean d(NBTTagCompound save) {
return npc == null ? super.d(save) : false;
}
@Override
public SoundEffect getSoundAmbient() {
return NMSImpl.getSoundEffect(npc, super.getSoundAmbient(), NPC.AMBIENT_SOUND_METADATA);
}
@Override
public void enderTeleportTo(double d0, double d1, double d2) {
if (npc == null) {
@ -106,6 +96,34 @@ public class BatController extends MobEntityController {
}
}
@Override
public CraftEntity getBukkitEntity() {
if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) {
NMSImpl.setBukkitEntity(this, new BatNPC(this));
}
return super.getBukkitEntity();
}
@Override
public NPC getNPC() {
return npc;
}
@Override
public SoundEffect getSoundAmbient() {
return NMSImpl.getSoundEffect(npc, super.getSoundAmbient(), NPC.AMBIENT_SOUND_METADATA);
}
@Override
protected SoundEffect getSoundDeath() {
return NMSImpl.getSoundEffect(npc, super.getSoundDeath(), NPC.DEATH_SOUND_METADATA);
}
@Override
protected SoundEffect getSoundHurt(DamageSource damagesource) {
return NMSImpl.getSoundEffect(npc, super.getSoundHurt(damagesource), NPC.HURT_SOUND_METADATA);
}
@Override
public void h(double x, double y, double z) {
if (npc == null) {
@ -128,26 +146,6 @@ public class BatController extends MobEntityController {
// cancelled.
}
@Override
public CraftEntity getBukkitEntity() {
if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) {
NMSImpl.setBukkitEntity(this, new BatNPC(this));
}
return super.getBukkitEntity();
}
@Override
public NPC getNPC() {
return npc;
}
@Override
public void checkDespawn() {
if (npc == null) {
super.checkDespawn();
}
}
@Override
public boolean isLeashed() {
if (npc == null) {

View File

@ -95,28 +95,6 @@ public class BeeController extends MobEntityController {
}
}
@Override
public void h(double x, double y, double z) {
if (npc == null) {
super.h(x, y, z);
return;
}
if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
super.h(x, y, z);
return;
}
Vector vector = new Vector(x, y, z);
NPCPushEvent event = Util.callPushEvent(npc, vector);
if (!event.isCancelled()) {
vector = event.getCollisionVector();
super.h(vector.getX(), vector.getY(), vector.getZ());
}
// when another entity collides, this method is called to push the
// NPC so we prevent it from doing anything if the event is
// cancelled.
}
@Override
public CraftEntity getBukkitEntity() {
if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) {
@ -145,6 +123,28 @@ public class BeeController extends MobEntityController {
return NMSImpl.getSoundEffect(npc, super.getSoundHurt(damagesource), NPC.HURT_SOUND_METADATA);
}
@Override
public void h(double x, double y, double z) {
if (npc == null) {
super.h(x, y, z);
return;
}
if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0) {
if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true))
super.h(x, y, z);
return;
}
Vector vector = new Vector(x, y, z);
NPCPushEvent event = Util.callPushEvent(npc, vector);
if (!event.isCancelled()) {
vector = event.getCollisionVector();
super.h(vector.getX(), vector.getY(), vector.getZ());
}
// when another entity collides, this method is called to push the
// NPC so we prevent it from doing anything if the event is
// cancelled.
}
@Override
public boolean isLeashed() {
if (npc == null) {

View File

@ -1040,6 +1040,11 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
((EntityPanda) getHandle(entity)).r(sitting);
@ -1746,7 +1751,6 @@ public class NMSImpl implements NMSBridge {
private static final Random RANDOM = Util.getFastRandom();
private static final MethodHandle SIZE_FIELD_GETTER = NMS.getGetter(Entity.class, "size");
private static final MethodHandle SIZE_FIELD_SETTER = NMS.getSetter(Entity.class, "size");
private static Field SKULL_PROFILE_FIELD;
static {

View File

@ -819,6 +819,17 @@ public class NMSImpl implements NMSBridge {
NMSImpl.getNavigation(handle).a(NMSImpl.getHandle(target), speed);
}
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
if (!enabled)
return;
if (((NPCHolder) entity).getNPC().getNavigator().isNavigating())
return; // use legacy gravity behaviour
Vector vector = entity.getVelocity();
vector.setY(Math.max(0, vector.getY()));
entity.setVelocity(vector);
}
@Override
public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) {
}
@ -1327,11 +1338,8 @@ public class NMSImpl implements NMSBridge {
public static Field NETWORK_ADDRESS = NMS.getField(NetworkManager.class, "l");
public static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0);
private static Field PATHFINDING_RANGE = NMS.getField(NavigationAbstract.class, "a");
private static final Random RANDOM = Util.getFastRandom();
private static Field SKULL_PROFILE_FIELD;
private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c");
static {