Fix flying move controllers not respecting the no gravity setting

This commit is contained in:
fullwall 2022-02-19 14:20:02 +08:00
parent aacff7b45a
commit 2981f7e855
5 changed files with 124 additions and 4 deletions

13
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,13 @@
Setup
=====
Clone the CitizensAPI and Citizens2 repositories.
Citizens2 uses Maven subprojects for backwards compatibility with old Minecraft versions.
Contributing
============
Citizens welcomes open source contributions. Make sure you sign the CLA when making a pull request.
Building
========
Make sure you have installed all prerequisite Spigot versions using `java BuildTools.jar --rev <1.12.2|1.13.2|1.14.4|1.15.2...>`.
Build the Citizens JAR by running `maven install` in the main directory; the output JAR will be located at `dist/target/Citizens-xxx.jar`.

View File

@ -211,6 +211,7 @@ import net.minecraft.server.v1_15_R1.BossBattleServer;
import net.minecraft.server.v1_15_R1.ChunkProviderServer;
import net.minecraft.server.v1_15_R1.ControllerJump;
import net.minecraft.server.v1_15_R1.ControllerMove;
import net.minecraft.server.v1_15_R1.ControllerMoveFlying;
import net.minecraft.server.v1_15_R1.CrashReport;
import net.minecraft.server.v1_15_R1.CrashReportSystemDetails;
import net.minecraft.server.v1_15_R1.DamageSource;
@ -1159,7 +1160,27 @@ public class NMSImpl implements NMSBridge {
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
Entity handle = getHandle(entity);
handle.setNoGravity(enabled);
if (!(handle instanceof EntityInsentient) || !(entity instanceof NPCHolder))
return;
EntityInsentient mob = (EntityInsentient) handle;
NPC npc = ((NPCHolder) entity).getNPC();
if (!(mob.getControllerMove() instanceof ControllerMoveFlying) || npc.data().has("flying-nogravity-float"))
return;
try {
if (enabled) {
boolean old = (boolean) FLYING_MOVECONTROL_FLOAT_GETTER.invoke(mob.getControllerMove());
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getControllerMove(), true);
npc.data().set("flying-nogravity-float", old);
} else {
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getControllerMove(),
npc.data().get("flying-nogravity-float"));
npc.data().remove("flying-nogravity-float");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
@ -1914,8 +1935,10 @@ public class NMSImpl implements NMSBridge {
private static final MethodHandle BEHAVIOR_MAP = NMS.getGetter(BehaviorController.class, "c");
private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity");
private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(PlayerChunkMap.class, "a",
true, EntityPlayer.class, boolean.class);
private static final Map<Class<?>, EntityTypes<?>> CITIZENS_ENTITY_TYPES = Maps.newHashMap();
private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle");
private static final float DEFAULT_SPEED = 1F;
@ -1928,6 +1951,10 @@ public class NMSImpl implements NMSBridge {
private static CustomEntityRegistry ENTITY_REGISTRY;
private static final MethodHandle ENTITY_SETPOSE = NMS.getMethodHandle(Entity.class, "setPose", false,
EntityPose.class);
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_GETTER = NMS.getFirstGetter(ControllerMoveFlying.class,
boolean.class);
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_SETTER = NMS.getFirstSetter(ControllerMoveFlying.class,
boolean.class);
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
private static final MethodHandle GOAL_SET_FIELD = NMS.getGetter(PathfinderGoalSelector.class, "d");
private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "headHeight");

View File

@ -216,6 +216,7 @@ import net.minecraft.server.v1_16_R3.BossBattleServer;
import net.minecraft.server.v1_16_R3.ChunkProviderServer;
import net.minecraft.server.v1_16_R3.ControllerJump;
import net.minecraft.server.v1_16_R3.ControllerMove;
import net.minecraft.server.v1_16_R3.ControllerMoveFlying;
import net.minecraft.server.v1_16_R3.CrashReport;
import net.minecraft.server.v1_16_R3.CrashReportSystemDetails;
import net.minecraft.server.v1_16_R3.DamageSource;
@ -1191,7 +1192,27 @@ public class NMSImpl implements NMSBridge {
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
Entity handle = getHandle(entity);
handle.setNoGravity(enabled);
if (!(handle instanceof EntityInsentient) || !(entity instanceof NPCHolder))
return;
EntityInsentient mob = (EntityInsentient) handle;
NPC npc = ((NPCHolder) entity).getNPC();
if (!(mob.getControllerMove() instanceof ControllerMoveFlying) || npc.data().has("flying-nogravity-float"))
return;
try {
if (enabled) {
boolean old = (boolean) FLYING_MOVECONTROL_FLOAT_GETTER.invoke(mob.getControllerMove());
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getControllerMove(), true);
npc.data().set("flying-nogravity-float", old);
} else {
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getControllerMove(),
npc.data().get("flying-nogravity-float"));
npc.data().remove("flying-nogravity-float");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
@ -1890,8 +1911,10 @@ public class NMSImpl implements NMSBridge {
private static final MethodHandle BEHAVIOR_MAP = NMS.getGetter(BehaviorController.class, "e");
private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity");
private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(PlayerChunkMap.class, "a",
true, EntityPlayer.class, boolean.class);
private static final Map<Class<?>, EntityTypes<?>> CITIZENS_ENTITY_TYPES = Maps.newHashMap();
private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle");
private static MethodHandle CRAFTSOUND_GETSOUND = NMS.getMethodHandle(CraftSound.class, "getSound", false,
@ -1905,6 +1928,10 @@ public class NMSImpl implements NMSBridge {
private static CustomEntityRegistry ENTITY_REGISTRY;
private static final MethodHandle FISHING_HOOK_HOOKED = NMS.getGetter(EntityFishingHook.class, "hooked");
private static final MethodHandle FISHING_HOOK_HOOKED_SETTER = NMS.getSetter(EntityFishingHook.class, "hooked");
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_GETTER = NMS.getFirstGetter(ControllerMoveFlying.class,
boolean.class);
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_SETTER = NMS.getFirstSetter(ControllerMoveFlying.class,
boolean.class);
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
private static final MethodHandle GOAL_SET_FIELD = NMS.getGetter(PathfinderGoalSelector.class, "d");
private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "headHeight");

View File

@ -245,6 +245,7 @@ import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.control.FlyingMoveControl;
import net.minecraft.world.entity.ai.control.JumpControl;
import net.minecraft.world.entity.ai.control.MoveControl;
import net.minecraft.world.entity.ai.goal.GoalSelector;
@ -1184,7 +1185,26 @@ public class NMSImpl implements NMSBridge {
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
Entity handle = getHandle(entity);
handle.setNoGravity(enabled);
if (!(handle instanceof Mob) || !(entity instanceof NPCHolder))
return;
Mob mob = (Mob) handle;
NPC npc = ((NPCHolder) entity).getNPC();
if (!(mob.getMoveControl() instanceof FlyingMoveControl) || npc.data().has("flying-nogravity-float"))
return;
try {
if (enabled) {
boolean old = (boolean) FLYING_MOVECONTROL_FLOAT_GETTER.invoke(mob.getMoveControl());
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), true);
npc.data().set("flying-nogravity-float", old);
} else {
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), npc.data().get("flying-nogravity-float"));
npc.data().remove("flying-nogravity-float");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
@ -1885,7 +1905,9 @@ public class NMSImpl implements NMSBridge {
EntityType.SHULKER, EntityType.PHANTOM);
private static final MethodHandle BEHAVIOR_MAP = NMS.getGetter(Brain.class, "f");
private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity");
private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(ChunkMap.class, "a", true,
ServerPlayer.class, boolean.class);
private static final Map<Class<?>, net.minecraft.world.entity.EntityType<?>> CITIZENS_ENTITY_TYPES = Maps
@ -1899,6 +1921,10 @@ public class NMSImpl implements NMSBridge {
private static CustomEntityRegistry ENTITY_REGISTRY;
private static MethodHandle ENTITY_REGISTRY_SETTER;
private static final MethodHandle FISHING_HOOK_LIFE = NMS.getSetter(FishingHook.class, "ap");
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_GETTER = NMS.getFirstGetter(FlyingMoveControl.class,
boolean.class);
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_SETTER = NMS.getFirstSetter(FlyingMoveControl.class,
boolean.class);
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "aX");
private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class,

View File

@ -247,6 +247,7 @@ import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.Brain;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.control.FlyingMoveControl;
import net.minecraft.world.entity.ai.control.JumpControl;
import net.minecraft.world.entity.ai.control.MoveControl;
import net.minecraft.world.entity.ai.goal.GoalSelector;
@ -283,6 +284,7 @@ import net.minecraft.world.scores.PlayerTeam;
@SuppressWarnings("unchecked")
public class NMSImpl implements NMSBridge {
public NMSImpl() {
loadEntityTypes();
}
@ -1188,7 +1190,26 @@ public class NMSImpl implements NMSBridge {
@Override
public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) {
getHandle(entity).setNoGravity(enabled);
Entity handle = getHandle(entity);
handle.setNoGravity(enabled);
if (!(handle instanceof Mob) || !(entity instanceof NPCHolder))
return;
Mob mob = (Mob) handle;
NPC npc = ((NPCHolder) entity).getNPC();
if (!(mob.getMoveControl() instanceof FlyingMoveControl) || npc.data().has("flying-nogravity-float"))
return;
try {
if (enabled) {
boolean old = (boolean) FLYING_MOVECONTROL_FLOAT_GETTER.invoke(mob.getMoveControl());
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), true);
npc.data().set("flying-nogravity-float", old);
} else {
FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), npc.data().get("flying-nogravity-float"));
npc.data().remove("flying-nogravity-float");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
@ -1910,10 +1931,12 @@ public class NMSImpl implements NMSBridge {
}
private static final MethodHandle ADVANCEMENTS_PLAYER_FIELD = NMS.getFinalSetter(ServerPlayer.class, "cs");
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE,
EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT,
EntityType.SLIME, EntityType.DOLPHIN, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.GHAST,
EntityType.SHULKER, EntityType.PHANTOM);
private static final MethodHandle BEHAVIOR_TREE_MAP = NMS.getGetter(Brain.class, "f");
private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity");
private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(ChunkMap.class, "a", true,
@ -1932,6 +1955,10 @@ public class NMSImpl implements NMSBridge {
private static final MethodHandle FIND_DIMENSION_ENTRY_POINT = NMS.getFirstMethodHandleWithReturnType(Entity.class,
true, PortalInfo.class, ServerLevel.class);
private static final MethodHandle FISHING_HOOK_LIFE = NMS.getSetter(FishingHook.class, "aq");
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_GETTER = NMS.getFirstGetter(FlyingMoveControl.class,
boolean.class);
private static final MethodHandle FLYING_MOVECONTROL_FLOAT_SETTER = NMS.getFirstSetter(FlyingMoveControl.class,
boolean.class);
private static final Location FROM_LOCATION = new Location(null, 0, 0, 0);
private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "aZ");
private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class,