Implement pitchable look control

This commit is contained in:
fullwall 2023-03-25 23:22:46 +08:00
parent 4a55753409
commit 82030a6534
21 changed files with 319 additions and 11 deletions

View File

@ -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();

View File

@ -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 {

View File

@ -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) {

View File

@ -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<EntityType> 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");

View File

@ -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<Boolean> 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;
}
}

View File

@ -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) {

View File

@ -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<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,
@ -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");

View File

@ -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<Boolean> 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;
}
}

View File

@ -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) {

View File

@ -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<EntityType> 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");

View File

@ -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<Boolean> 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;
}
}

View File

@ -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.

View File

@ -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<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_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");

View File

@ -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<Boolean> 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;
}
}

View File

@ -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) {

View File

@ -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<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,
@ -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");

View File

@ -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<Boolean> 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;
}
}

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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");

View File

@ -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<Boolean> 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;
}
}