Make controllable inner classes static

This commit is contained in:
fullwall 2024-08-19 15:40:40 +08:00
parent 6bfb2a0dd7
commit 44c697180f

View File

@ -1,6 +1,7 @@
package net.citizensnpcs.trait;
import java.util.List;
import java.util.function.Function;
import org.bukkit.Location;
import org.bukkit.entity.EnderDragon;
@ -32,7 +33,7 @@ import net.citizensnpcs.util.Util;
*/
@TraitName("controllable")
public class Controllable extends Trait implements Toggleable {
private MovementController controller = new GroundController();
private MovementController controller;
@Persist
private BuiltInControls controls;
@Persist
@ -44,42 +45,10 @@ public class Controllable extends Trait implements Toggleable {
super("controllable");
}
private void enterOrLeaveVehicle(Player player) {
List<Entity> passengers = NMS.getPassengers(player);
if (passengers.size() > 0) {
if (passengers.contains(player)) {
player.leaveVehicle();
}
return;
}
if (!player.hasPermission("citizens.npc.controllable." + Util.prettyEnum(npc.getEntity().getType()))
|| !player.hasPermission("citizens.npc.controllable")
|| ownerRequired && !npc.getOrAddTrait(Owner.class).isOwnedBy(player))
return;
NMS.mount(npc.getEntity(), player);
}
public boolean isEnabled() {
return enabled;
}
private void loadController() {
if (controls != null) {
controller = controls.create(this);
return;
}
if (!(npc.getEntity() instanceof LivingEntity) && !(npc.getEntity() instanceof Vehicle)) {
controller = new LookAirController();
return;
}
if (Util.isAlwaysFlyable(npc.getEntity().getType())) {
controller = new PlayerInputAirController();
} else {
controller = new GroundController();
}
}
/**
* Attempts to mount the {@link Player} onto the {@link NPC}.
*
@ -100,7 +69,7 @@ public class Controllable extends Trait implements Toggleable {
}
if (found)
return false;
enterOrLeaveVehicle(toMount);
enterOrLeaveVehicle(npc, toMount);
return true;
}
@ -139,7 +108,19 @@ public class Controllable extends Trait implements Toggleable {
@Override
public void onSpawn() {
loadController();
if (controls != null) {
controller = controls.factory.apply(npc);
return;
}
if (!(npc.getEntity() instanceof LivingEntity) && !(npc.getEntity() instanceof Vehicle)) {
controller = new LookAirController(npc);
return;
}
if (Util.isAlwaysFlyable(npc.getEntity().getType())) {
controller = new PlayerInputAirController(npc);
} else {
controller = new GroundController(npc);
}
}
@Override
@ -161,24 +142,6 @@ public class Controllable extends Trait implements Toggleable {
return enabled;
}
private void setMountedYaw(Entity entity) {
if (entity instanceof EnderDragon || !Setting.USE_BOAT_CONTROLS.asBoolean())
return; // EnderDragon handles this separately
Location loc = entity.getLocation();
Vector vel = entity.getVelocity();
if (vel.lengthSquared() == 0)
return;
double tX = loc.getX() + vel.getX();
double tZ = loc.getZ() + vel.getZ();
if (loc.getZ() > tZ) {
loc.setYaw((float) -Math.toDegrees(Math.atan((loc.getX() - tX) / (loc.getZ() - tZ))) + 180F);
} else if (loc.getZ() < tZ) {
loc.setYaw((float) -Math.toDegrees(Math.atan((loc.getX() - tX) / (loc.getZ() - tZ))));
}
NMS.look(entity, loc.getYaw(), loc.getPitch());
}
/**
* Sets whether the {@link Player} attempting to mount the {@link NPC} must actually own the {@link NPC} to mount
* it.
@ -198,7 +161,223 @@ public class Controllable extends Trait implements Toggleable {
return enabled;
}
private double updateHorizontalSpeed(Entity handle, Entity passenger, double speed, float speedMod,
public enum BuiltInControls {
AIR(PlayerInputAirController::new),
GROUND(GroundController::new),
GROUND_JUMPLESS(JumplessGroundController::new),
LOOK_AIR(LookAirController::new);
private final Function<NPC, MovementController> factory;
private BuiltInControls(Function<NPC, MovementController> factory) {
this.factory = factory;
}
}
public static class GroundController implements MovementController {
private int jumpTicks = 0;
private final NPC npc;
private double speed = 0.07D;
public GroundController(NPC npc) {
this.npc = npc;
}
@Override
public void leftClick(PlayerInteractEvent event) {
}
@Override
public void rightClick(PlayerInteractEvent event) {
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(npc, event.getClicker());
}
@Override
public void run(Player rider) {
boolean onGround = NMS.isOnGround(npc.getEntity());
float impulse = npc.getNavigator().getDefaultParameters()
.modifiedSpeed(onGround ? GROUND_SPEED : AIR_SPEED);
if (!Util.isHorse(npc.getEntity().getType())) {
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, impulse,
Setting.MAX_CONTROLLABLE_GROUND_SPEED.asDouble());
}
if (onGround && jumpTicks <= 0 && NMS.shouldJump(rider)) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(JUMP_VELOCITY));
jumpTicks = 10;
}
jumpTicks--;
setMountedYaw(npc.getEntity());
}
private static final float AIR_SPEED = 0.5F;
private static final float GROUND_SPEED = 0.5F;
private static final float JUMP_VELOCITY = 0.5F;
}
public static class JumplessGroundController implements MovementController {
private final NPC npc;
private double speed = 0.07D;
public JumplessGroundController(NPC npc) {
this.npc = npc;
}
@Override
public void leftClick(PlayerInteractEvent event) {
}
@Override
public void rightClick(PlayerInteractEvent event) {
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(npc, event.getClicker());
}
@Override
public void run(Player rider) {
boolean onGround = NMS.isOnGround(npc.getEntity());
float impulse = npc.getNavigator().getDefaultParameters()
.modifiedSpeed(onGround ? GROUND_SPEED : AIR_SPEED);
if (!Util.isHorse(npc.getEntity().getType())) {
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, impulse,
Setting.MAX_CONTROLLABLE_GROUND_SPEED.asDouble());
}
setMountedYaw(npc.getEntity());
}
private static final float AIR_SPEED = 0.5F;
private static final float GROUND_SPEED = 0.5F;
}
public static class LookAirController implements MovementController {
private final NPC npc;
private boolean paused = false;
public LookAirController(NPC npc) {
this.npc = npc;
}
@Override
public void leftClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(npc, event.getClicker());
}
@Override
public void run(Player rider) {
if (paused) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.001));
return;
}
Vector dir = rider.getEyeLocation().getDirection();
dir.multiply(npc.getNavigator().getDefaultParameters().speedModifier());
npc.getEntity().setVelocity(dir);
setMountedYaw(npc.getEntity());
}
}
public static interface MovementController {
void leftClick(PlayerInteractEvent event);
void rightClick(PlayerInteractEvent event);
void rightClickEntity(NPCRightClickEvent event);
void run(Player rider);
}
public static class PlayerInputAirController implements MovementController {
private final NPC npc;
private boolean paused = false;
private double speed;
public PlayerInputAirController(NPC npc) {
this.npc = npc;
}
@Override
public void leftClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClick(PlayerInteractEvent event) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(-0.25F));
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(npc, event.getClicker());
}
@Override
public void run(Player rider) {
if (paused) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.001F));
return;
}
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, 1F,
Setting.MAX_CONTROLLABLE_FLIGHT_SPEED.asDouble());
boolean shouldJump = NMS.shouldJump(rider);
if (shouldJump) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.25F));
}
npc.getEntity().setVelocity(npc.getEntity().getVelocity().multiply(new Vector(1, 0.98, 1)));
setMountedYaw(npc.getEntity());
}
}
private static void enterOrLeaveVehicle(NPC npc, Player player) {
List<Entity> passengers = NMS.getPassengers(player);
if (passengers.size() > 0) {
if (passengers.contains(player)) {
player.leaveVehicle();
}
return;
}
if (!player.hasPermission("citizens.npc.controllable." + Util.prettyEnum(npc.getEntity().getType()))
|| !player.hasPermission("citizens.npc.controllable")
|| npc.getOrAddTrait(Controllable.class).ownerRequired
&& !npc.getOrAddTrait(Owner.class).isOwnedBy(player))
return;
NMS.mount(npc.getEntity(), player);
}
private static void setMountedYaw(Entity entity) {
if (entity instanceof EnderDragon || !Setting.USE_BOAT_CONTROLS.asBoolean())
return; // EnderDragon handles this separately
Location loc = entity.getLocation();
Vector vel = entity.getVelocity();
if (vel.lengthSquared() == 0)
return;
double tX = loc.getX() + vel.getX();
double tZ = loc.getZ() + vel.getZ();
if (loc.getZ() > tZ) {
loc.setYaw((float) -Math.toDegrees(Math.atan((loc.getX() - tX) / (loc.getZ() - tZ))) + 180F);
} else if (loc.getZ() < tZ) {
loc.setYaw((float) -Math.toDegrees(Math.atan((loc.getX() - tX) / (loc.getZ() - tZ))));
}
NMS.look(entity, loc.getYaw(), loc.getPitch());
}
private static double updateHorizontalSpeed(Entity handle, Entity passenger, double speed, float speedMod,
double maxSpeed) {
Vector vel = handle.getVelocity();
double oldSpeed = Math.sqrt(vel.getX() * vel.getX() + vel.getZ() * vel.getZ());
@ -231,181 +410,4 @@ public class Controllable extends Trait implements Toggleable {
return (float) Math.max(0, speed - speed / 50.0D);
}
}
public enum BuiltInControls {
AIR {
@Override
MovementController create(Controllable trait) {
return trait.new PlayerInputAirController();
}
},
GROUND {
@Override
MovementController create(Controllable trait) {
return trait.new GroundController();
}
},
GROUND_JUMPLESS {
@Override
MovementController create(Controllable trait) {
return trait.new JumplessGroundController();
}
},
LOOK_AIR {
@Override
MovementController create(Controllable trait) {
return trait.new LookAirController();
}
};
abstract MovementController create(Controllable trait);
}
public class GroundController implements MovementController {
private int jumpTicks = 0;
private double speed = 0.07D;
@Override
public void leftClick(PlayerInteractEvent event) {
}
@Override
public void rightClick(PlayerInteractEvent event) {
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(event.getClicker());
}
@Override
public void run(Player rider) {
boolean onGround = NMS.isOnGround(npc.getEntity());
float impulse = npc.getNavigator().getDefaultParameters()
.modifiedSpeed(onGround ? GROUND_SPEED : AIR_SPEED);
if (!Util.isHorse(npc.getEntity().getType())) {
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, impulse,
Setting.MAX_CONTROLLABLE_GROUND_SPEED.asDouble());
}
if (onGround && jumpTicks <= 0 && NMS.shouldJump(rider)) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(JUMP_VELOCITY));
jumpTicks = 10;
}
jumpTicks--;
setMountedYaw(npc.getEntity());
}
private static final float AIR_SPEED = 0.5F;
private static final float GROUND_SPEED = 0.5F;
private static final float JUMP_VELOCITY = 0.5F;
}
public class JumplessGroundController implements MovementController {
private double speed = 0.07D;
@Override
public void leftClick(PlayerInteractEvent event) {
}
@Override
public void rightClick(PlayerInteractEvent event) {
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(event.getClicker());
}
@Override
public void run(Player rider) {
boolean onGround = NMS.isOnGround(npc.getEntity());
float impulse = npc.getNavigator().getDefaultParameters()
.modifiedSpeed(onGround ? GROUND_SPEED : AIR_SPEED);
if (!Util.isHorse(npc.getEntity().getType())) {
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, impulse,
Setting.MAX_CONTROLLABLE_GROUND_SPEED.asDouble());
}
setMountedYaw(npc.getEntity());
}
private static final float AIR_SPEED = 0.5F;
private static final float GROUND_SPEED = 0.5F;
}
public class LookAirController implements MovementController {
private boolean paused = false;
@Override
public void leftClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(event.getClicker());
}
@Override
public void run(Player rider) {
if (paused) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.001));
return;
}
Vector dir = rider.getEyeLocation().getDirection();
dir.multiply(npc.getNavigator().getDefaultParameters().speedModifier());
npc.getEntity().setVelocity(dir);
setMountedYaw(npc.getEntity());
}
}
public static interface MovementController {
void leftClick(PlayerInteractEvent event);
void rightClick(PlayerInteractEvent event);
void rightClickEntity(NPCRightClickEvent event);
void run(Player rider);
}
public class PlayerInputAirController implements MovementController {
private boolean paused = false;
private double speed;
@Override
public void leftClick(PlayerInteractEvent event) {
paused = !paused;
}
@Override
public void rightClick(PlayerInteractEvent event) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(-0.25F));
}
@Override
public void rightClickEntity(NPCRightClickEvent event) {
enterOrLeaveVehicle(event.getClicker());
}
@Override
public void run(Player rider) {
if (paused) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.001F));
return;
}
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, 1F,
Setting.MAX_CONTROLLABLE_FLIGHT_SPEED.asDouble());
boolean shouldJump = NMS.shouldJump(rider);
if (shouldJump) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.25F));
}
npc.getEntity().setVelocity(npc.getEntity().getVelocity().multiply(new Vector(1, 0.98, 1)));
setMountedYaw(npc.getEntity());
}
}
}