From 82030a65348c975c4dab7cd9f7c050fe6b4a2133 Mon Sep 17 00:00:00 2001 From: fullwall Date: Sat, 25 Mar 2023 23:22:46 +0800 Subject: [PATCH] Implement pitchable look control --- .../citizensnpcs/commands/NPCCommands.java | 29 +++++++++++------ .../main/java/net/citizensnpcs/util/NMS.java | 1 - .../v1_14_R1/entity/MobEntityController.java | 6 ++++ .../nms/v1_14_R1/util/NMSImpl.java | 12 +++++++ .../v1_14_R1/util/PitchableLookControl.java | 32 +++++++++++++++++++ .../v1_15_R1/entity/MobEntityController.java | 6 ++++ .../nms/v1_15_R1/util/NMSImpl.java | 12 +++++++ .../v1_15_R1/util/PitchableLookControl.java | 32 +++++++++++++++++++ .../v1_16_R3/entity/MobEntityController.java | 6 ++++ .../nms/v1_16_R3/util/NMSImpl.java | 12 ++++++- .../v1_16_R3/util/PitchableLookControl.java | 32 +++++++++++++++++++ .../v1_17_R1/entity/MobEntityController.java | 6 ++++ .../nms/v1_17_R1/util/NMSImpl.java | 12 +++++++ .../v1_17_R1/util/PitchableLookControl.java | 32 +++++++++++++++++++ .../v1_18_R2/entity/MobEntityController.java | 6 ++++ .../nms/v1_18_R2/util/NMSImpl.java | 11 +++++++ .../v1_18_R2/util/PitchableLookControl.java | 32 +++++++++++++++++++ .../v1_19_R3/entity/MobEntityController.java | 6 ++++ .../v1_19_R3/entity/VillagerController.java | 3 ++ .../nms/v1_19_R3/util/NMSImpl.java | 10 ++++++ .../v1_19_R3/util/PitchableLookControl.java | 32 +++++++++++++++++++ 21 files changed, 319 insertions(+), 11 deletions(-) create mode 100644 v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/PitchableLookControl.java create mode 100644 v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/PitchableLookControl.java create mode 100644 v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/PitchableLookControl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PitchableLookControl.java create mode 100644 v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PitchableLookControl.java create mode 100644 v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/PitchableLookControl.java diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index 53abdfa4b..1e5a9d025 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -684,6 +684,7 @@ public class NPCCommands { if (args.hasFlag('t') || temporaryTicks != null) { registry = temporaryRegistry; } + if (item != null) { ItemStack stack = new ItemStack(Material.STONE, 1); try { @@ -1345,6 +1346,7 @@ public class NPCCommands { max = 1, flags = "t", permission = "citizens.npc.leashable") + @Requirements(selected = true, ownership = true, excludedTypes = { EntityType.PLAYER }) public void leashable(CommandContext args, CommandSender sender, NPC npc) { boolean vulnerable = !npc.data().get(NPC.Metadata.LEASH_PROTECTED, true); if (args.hasFlag('t')) { @@ -1535,12 +1537,9 @@ public class NPCCommands { permission = "citizens.npc.metadata") @Requirements(selected = true, ownership = true) public void metadata(CommandContext args, CommandSender sender, NPC npc, - @Arg(value = 1, completions = { "set", "get", "remove" }) String command) throws CommandException { + @Arg(value = 1, completions = { "set", "get", "remove" }) String command, @Arg(2) NPC.Metadata enumKey) + throws CommandException { String key = args.getString(2); - try { - key = NPC.Metadata.valueOf(key.toUpperCase()).getKey(); - } catch (IllegalArgumentException e) { - } if (command.equals("set")) { if (args.argsLength() != 4) @@ -1560,21 +1559,33 @@ public class NPCCommands { } if (args.hasFlag('t')) { - npc.data().set(key, metadata); + if (enumKey != null) { + npc.data().set(enumKey, metadata); + } else { + npc.data().set(key, metadata); + } } else { - npc.data().setPersistent(key, metadata); + if (enumKey != null) { + npc.data().set(enumKey, metadata); + } else { + npc.data().setPersistent(key, metadata); + } } Messaging.sendTr(sender, Messages.METADATA_SET, key, args.getString(3)); } else if (command.equals("get")) { if (args.argsLength() != 3) { throw new CommandException(); } - sender.sendMessage(npc.data().get(key, "null")); + sender.sendMessage(enumKey != null ? npc.data().get(enumKey, "null") : npc.data().get(key, "null")); } else if (command.equals("remove")) { if (args.argsLength() != 3) { throw new CommandException(); } - npc.data().remove(key); + if (enumKey != null) { + npc.data().remove(enumKey); + } else { + npc.data().remove(key); + } Messaging.sendTr(sender, Messages.METADATA_UNSET, key, npc.getName()); } else { throw new CommandUsageException(); diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 109f1bc52..3ac7cc298 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -775,7 +775,6 @@ public class NMS { private static Object UNSAFE; private static MethodHandle UNSAFE_FIELD_OFFSET; private static MethodHandle UNSAFE_PUT_OBJECT; - private static MethodHandle UNSAFE_STATIC_FIELD_OFFSET; static { diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/MobEntityController.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/MobEntityController.java index 7b552509a..c5daa9db9 100644 --- a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/MobEntityController.java +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/entity/MobEntityController.java @@ -13,9 +13,11 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_14_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_14_R1.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.util.NMS; +import net.minecraft.server.v1_14_R1.ControllerLook; import net.minecraft.server.v1_14_R1.EntityInsentient; import net.minecraft.server.v1_14_R1.EntityTypes; import net.minecraft.server.v1_14_R1.World; @@ -35,6 +37,10 @@ public abstract class MobEntityController extends AbstractEntityController { ((CraftWorld) at.getWorld()).getHandle(), npc); if (entity instanceof EntityInsentient) { NMSImpl.clearGoals(((EntityInsentient) entity).goalSelector, ((EntityInsentient) entity).targetSelector); + EntityInsentient mob = (EntityInsentient) entity; + if (mob.getControllerLook().getClass() == ControllerLook.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } entity.setPositionRotation(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); if (npc != null) { diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java index 305aa8495..1cc359ab7 100644 --- a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/NMSImpl.java @@ -243,6 +243,7 @@ import net.minecraft.server.v1_14_R1.ContainerAccess; import net.minecraft.server.v1_14_R1.ContainerAnvil; import net.minecraft.server.v1_14_R1.Containers; import net.minecraft.server.v1_14_R1.ControllerJump; +import net.minecraft.server.v1_14_R1.ControllerLook; import net.minecraft.server.v1_14_R1.ControllerMove; import net.minecraft.server.v1_14_R1.DamageSource; import net.minecraft.server.v1_14_R1.DataWatcherObject; @@ -2110,6 +2111,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(EntityInsentient mob, ControllerLook control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(EntityFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2169,6 +2178,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ADVANCEMENT_PLAYER_FIELD = NMS.getFinalSetter(EntityPlayer.class, "advancementDataPlayer"); + private static final Set BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, EntityType.SLIME, EntityType.DOLPHIN, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.GHAST, EntityType.SHULKER, @@ -2201,6 +2211,8 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ISCLIMBING_METHOD = NMS.getMethodHandle(EntityLiving.class, "f", true, Vec3D.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(EntityLiving.class, "jumping"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class, + ControllerLook.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h"); diff --git a/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/PitchableLookControl.java b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/PitchableLookControl.java new file mode 100644 index 000000000..d36ba5203 --- /dev/null +++ b/v1_14_R1/src/main/java/net/citizensnpcs/nms/v1_14_R1/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_14_R1.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.server.v1_14_R1.ControllerLook; +import net.minecraft.server.v1_14_R1.EntityInsentient; + +public class PitchableLookControl extends ControllerLook { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(EntityInsentient var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean b() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/MobEntityController.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/MobEntityController.java index 0655845a3..872d01002 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/MobEntityController.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/MobEntityController.java @@ -13,9 +13,11 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_15_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_15_R1.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.util.NMS; +import net.minecraft.server.v1_15_R1.ControllerLook; import net.minecraft.server.v1_15_R1.EntityInsentient; import net.minecraft.server.v1_15_R1.EntityTypes; import net.minecraft.server.v1_15_R1.World; @@ -36,6 +38,10 @@ public abstract class MobEntityController extends AbstractEntityController { if (entity instanceof EntityInsentient) { NMSImpl.clearGoals(npc, ((EntityInsentient) entity).goalSelector, ((EntityInsentient) entity).targetSelector); + EntityInsentient mob = (EntityInsentient) entity; + if (mob.getControllerLook().getClass() == ControllerLook.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } entity.setPositionRotation(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); if (npc != null) { diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java index c1d89fa07..dcbb72799 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/NMSImpl.java @@ -245,6 +245,7 @@ import net.minecraft.server.v1_15_R1.ContainerAccess; import net.minecraft.server.v1_15_R1.ContainerAnvil; import net.minecraft.server.v1_15_R1.Containers; import net.minecraft.server.v1_15_R1.ControllerJump; +import net.minecraft.server.v1_15_R1.ControllerLook; import net.minecraft.server.v1_15_R1.ControllerMove; import net.minecraft.server.v1_15_R1.ControllerMoveFlying; import net.minecraft.server.v1_15_R1.DamageSource; @@ -2175,6 +2176,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(EntityInsentient mob, ControllerLook control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(EntityFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2254,6 +2263,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ADVANCEMENT_PLAYER_FIELD = NMS.getFinalSetter(EntityPlayer.class, "advancementDataPlayer"); + private static final Set 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, @@ -2288,6 +2298,8 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ISCLIMBING_METHOD = NMS.getMethodHandle(EntityLiving.class, "f", true, Vec3D.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(EntityLiving.class, "jumping"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class, + ControllerLook.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h"); diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/PitchableLookControl.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/PitchableLookControl.java new file mode 100644 index 000000000..bebe3bed6 --- /dev/null +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_15_R1.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.server.v1_15_R1.ControllerLook; +import net.minecraft.server.v1_15_R1.EntityInsentient; + +public class PitchableLookControl extends ControllerLook { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(EntityInsentient var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean b() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/MobEntityController.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/MobEntityController.java index 99e8b6063..b8b29bb42 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/MobEntityController.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/MobEntityController.java @@ -13,9 +13,11 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_16_R3.util.NMSImpl; +import net.citizensnpcs.nms.v1_16_R3.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.util.NMS; +import net.minecraft.server.v1_16_R3.ControllerLook; import net.minecraft.server.v1_16_R3.EntityInsentient; import net.minecraft.server.v1_16_R3.EntityTypes; import net.minecraft.server.v1_16_R3.World; @@ -36,6 +38,10 @@ public abstract class MobEntityController extends AbstractEntityController { if (entity instanceof EntityInsentient) { NMSImpl.clearGoals(npc, ((EntityInsentient) entity).goalSelector, ((EntityInsentient) entity).targetSelector); + EntityInsentient mob = (EntityInsentient) entity; + if (mob.getControllerLook().getClass() == ControllerLook.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } entity.setPositionRotation(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); if (npc != null) { diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java index 78d6aca71..09709eb75 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/NMSImpl.java @@ -256,6 +256,7 @@ import net.minecraft.server.v1_16_R3.ContainerAccess; import net.minecraft.server.v1_16_R3.ContainerAnvil; import net.minecraft.server.v1_16_R3.Containers; import net.minecraft.server.v1_16_R3.ControllerJump; +import net.minecraft.server.v1_16_R3.ControllerLook; import net.minecraft.server.v1_16_R3.ControllerMove; import net.minecraft.server.v1_16_R3.ControllerMoveFlying; import net.minecraft.server.v1_16_R3.DamageSource; @@ -2188,6 +2189,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(EntityInsentient mob, ControllerLook control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(EntityFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2280,7 +2289,6 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ATTRIBUTE_MAP = NMS.getGetter(AttributeMapBase.class, "d"); private static final MethodHandle ATTRIBUTE_PROVIDER_MAP = NMS.getGetter(AttributeProvider.class, "a"); - private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFinalSetter(AttributeProvider.class, "a"); private static final Set BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE, EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, @@ -2315,6 +2323,8 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getMethodHandle(Entity.class, "getHeadHeight", true, EntityPose.class, EntitySize.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(EntityLiving.class, "jumping"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(EntityInsentient.class, + ControllerLook.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(ControllerMove.class, "h"); diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/PitchableLookControl.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/PitchableLookControl.java new file mode 100644 index 000000000..c0b054629 --- /dev/null +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_16_R3.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.server.v1_16_R3.ControllerLook; +import net.minecraft.server.v1_16_R3.EntityInsentient; + +public class PitchableLookControl extends ControllerLook { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(EntityInsentient var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean b() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java index 833ad4a5d..01a9614c8 100644 --- a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java @@ -12,10 +12,12 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; import net.minecraft.world.level.Level; public abstract class MobEntityController extends AbstractEntityController { @@ -35,6 +37,10 @@ public abstract class MobEntityController extends AbstractEntityController { if (npc != null) { if (entity instanceof Mob) { NMSImpl.clearGoals(npc, ((Mob) entity).goalSelector, ((Mob) entity).targetSelector); + Mob mob = (Mob) entity; + if (mob.getLookControl().getClass() == LookControl.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } // entity.onGround isn't updated right away - we approximate here so // that things like pathfinding still work *immediately* after spawn. diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java index f49e1aa44..3aed06806 100644 --- a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java @@ -285,6 +285,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeMap; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.control.LookControl; import net.minecraft.world.entity.ai.control.MoveControl; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.ai.navigation.PathNavigation; @@ -2184,6 +2185,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(Mob mob, LookControl control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(AbstractFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2271,10 +2280,12 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ATTRIBUTE_SUPPLIER = NMS.getFirstGetter(AttributeMap.class, AttributeSupplier.class); + private static final Set 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_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, @@ -2299,6 +2310,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class, EntityDimensions.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(LivingEntity.class, "bn"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(Mob.class, LookControl.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(MoveControl.class, "k"); diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PitchableLookControl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PitchableLookControl.java new file mode 100644 index 000000000..af5da7ffb --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; + +public class PitchableLookControl extends LookControl { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(Mob var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean resetXRotOnTick() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/MobEntityController.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/MobEntityController.java index 13cf33cda..c43cff436 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/MobEntityController.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/MobEntityController.java @@ -12,10 +12,12 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_18_R2.util.NMSImpl; +import net.citizensnpcs.nms.v1_18_R2.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; import net.minecraft.world.level.Level; public abstract class MobEntityController extends AbstractEntityController { @@ -33,6 +35,10 @@ public abstract class MobEntityController extends AbstractEntityController { npc); if (entity instanceof Mob) { NMSImpl.clearGoals(npc, ((Mob) entity).goalSelector, ((Mob) entity).targetSelector); + Mob mob = (Mob) entity; + if (mob.getLookControl().getClass() == LookControl.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } entity.absMoveTo(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); if (npc != null) { diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java index 445665a2e..0abc97f13 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/NMSImpl.java @@ -286,6 +286,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeMap; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.control.LookControl; import net.minecraft.world.entity.ai.control.MoveControl; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.ai.navigation.PathNavigation; @@ -2197,6 +2198,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(Mob mob, LookControl control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(AbstractFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2311,6 +2320,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle ATTRIBUTE_SUPPLIER = NMS.getFirstGetter(AttributeMap.class, AttributeSupplier.class); + private static final Set 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, @@ -2344,6 +2354,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class, EntityDimensions.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(LivingEntity.class, "bn"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(Mob.class, LookControl.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_MOVING = NMS.getSetter(MoveControl.class, "k"); diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PitchableLookControl.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PitchableLookControl.java new file mode 100644 index 000000000..f62d4f001 --- /dev/null +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_18_R2.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; + +public class PitchableLookControl extends LookControl { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(Mob var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean resetXRotOnTick() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/MobEntityController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/MobEntityController.java index 74fe46507..301d04c79 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/MobEntityController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/MobEntityController.java @@ -12,10 +12,12 @@ import org.bukkit.entity.Entity; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.nms.v1_19_R3.util.NMSImpl; +import net.citizensnpcs.nms.v1_19_R3.util.PitchableLookControl; import net.citizensnpcs.npc.AbstractEntityController; import net.citizensnpcs.trait.ScoreboardTrait; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; import net.minecraft.world.level.Level; public abstract class MobEntityController extends AbstractEntityController { @@ -33,6 +35,10 @@ public abstract class MobEntityController extends AbstractEntityController { npc); if (entity instanceof Mob) { NMSImpl.clearGoals(npc, ((Mob) entity).goalSelector, ((Mob) entity).targetSelector); + Mob mob = (Mob) entity; + if (mob.getLookControl().getClass() == LookControl.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } } entity.absMoveTo(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); if (npc != null) { diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/VillagerController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/VillagerController.java index 36cfa6d0e..3727b4871 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/VillagerController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/VillagerController.java @@ -103,6 +103,9 @@ public class VillagerController extends MobEntityController { super.customServerAiStep(); if (npc != null) { npc.update(); + if (npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, true)) { + NMS.setPitch(getBukkitEntity(), 0); + } } } diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java index 25a39ccf1..85acb4f66 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java @@ -308,6 +308,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeSupplier; 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.LookControl; import net.minecraft.world.entity.ai.control.MoveControl; import net.minecraft.world.entity.ai.goal.GoalSelector; import net.minecraft.world.entity.ai.navigation.PathNavigation; @@ -2335,6 +2336,14 @@ public class NMSImpl implements NMSBridge { } } + public static void setLookControl(Mob mob, LookControl control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } catch (Throwable e) { + e.printStackTrace(); + } + } + public static void setNotInSchool(AbstractFish entity) { try { if (ENTITY_FISH_NUM_IN_SCHOOL != null) { @@ -2479,6 +2488,7 @@ public class NMSImpl implements NMSBridge { private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class, EntityDimensions.class); private static final MethodHandle JUMP_FIELD = NMS.getGetter(LivingEntity.class, "bi"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(Mob.class, LookControl.class); private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, "makeRequest", true, URL.class, Object.class, Class.class); private static MethodHandle MOVE_CONTROLLER_OPERATION = NMS.getSetter(MoveControl.class, "k"); diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/PitchableLookControl.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/PitchableLookControl.java new file mode 100644 index 000000000..0f8d24385 --- /dev/null +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/PitchableLookControl.java @@ -0,0 +1,32 @@ +package net.citizensnpcs.nms.v1_19_R3.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; + +public class PitchableLookControl extends LookControl { + private boolean explicit = true; + private final Supplier resetOnTick; + + public PitchableLookControl(Mob var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, explicit); + } else { + resetOnTick = () -> explicit; + } + } + + @Override + public boolean resetXRotOnTick() { + return resetOnTick.get(); + } + + public void setResetXRotOnTick(boolean val) { + explicit = val; + } +} \ No newline at end of file