Files
CustomNPC-Plus/src/main/java/noppes/npcs/util/NPCMountUtil.java
T

371 lines
13 KiB
Java
Raw Normal View History

package noppes.npcs.util;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.MathHelper;
import noppes.npcs.CustomNpcs;
import noppes.npcs.controllers.PlayerDataController;
import noppes.npcs.controllers.data.PlayerData;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.constants.EnumRoleType;
import noppes.npcs.roles.RoleMount;
public final class NPCMountUtil {
private static final int MOUNT_FLIGHT_TOGGLE_WINDOW = 7;
private NPCMountUtil() {
}
public static class MountState {
public Entity lastRider;
public boolean flightMode;
public boolean jumpPressed;
public int flightToggleTimer;
}
public static boolean handleMountedMovement(EntityNPCInterface npc, MountState state, float strafe, float forward) {
if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) {
resetMountedFlightState(npc, state);
return false;
}
if (npc.riddenByEntity != null && !(npc.riddenByEntity instanceof EntityPlayer)) {
npc.riddenByEntity.mountEntity(null);
return false;
}
if (!(npc.riddenByEntity instanceof EntityPlayer)) {
resetMountedFlightState(npc, state);
return false;
}
RoleMount mount = (RoleMount) npc.roleInterface;
EntityPlayer rider = (EntityPlayer) npc.riddenByEntity;
updateMountedFlightState(npc, state, mount, rider);
npc.prevRotationYaw = npc.rotationYaw = rider.rotationYaw;
npc.rotationPitch = rider.rotationPitch * 0.5F;
npc.setPositionAndRotation(npc.posX, npc.posY, npc.posZ, npc.rotationYaw, npc.rotationPitch);
npc.renderYawOffset = npc.rotationYaw;
npc.rotationYawHead = npc.rotationYaw;
float controlledStrafe = rider.moveStrafing;
float controlledForward = rider.moveForward;
if (controlledForward <= 0.0F) {
controlledForward *= 0.25F;
}
float moveSpeed = getMountMoveSpeed(npc);
boolean riderSprinting = rider.isSprinting() && mount.isSprintAllowed();
if (riderSprinting) {
moveSpeed *= 1.2F;
}
if (!mount.isSprintAllowed() && rider.isSprinting()) {
rider.setSprinting(false);
}
if (moveSpeed <= 0.0F) {
controlledStrafe = 0.0F;
controlledForward = 0.0F;
}
npc.setSprinting(riderSprinting);
npc.stepHeight = 1.0F;
npc.getNavigator().clearPathEntity();
npc.setAttackTarget(null);
npc.setRevengeTarget(null);
npc.fallDistance = 0.0F;
rider.fallDistance = 0.0F;
applyMountedVerticalMotion(npc, state, mount, rider, moveSpeed, controlledForward);
npc.performMountedMovement(controlledStrafe, controlledForward, moveSpeed);
return true;
}
private static float getMountMoveSpeed(EntityNPCInterface npc) {
return Math.max(0.0F, npc.getSpeed());
}
private static void applyMountedVerticalMotion(EntityNPCInterface npc, MountState state, RoleMount mount, EntityLivingBase rider, float moveSpeed, float forward) {
if (mount == null) {
return;
}
double jumpFactor = MathHelper.clamp_double(mount.getJumpStrength(), 0.1D, 3.0D);
boolean flyingEnabled = mount.isFlyingMountEnabled();
npc.setNpcJumpingState(false);
if (flyingEnabled) {
double ascendSpeed = MathHelper.clamp_double(mount.getFlyingAscendSpeed(), 0.1D, 3.0D);
double descendSpeed = MathHelper.clamp_double(mount.getFlyingDescendSpeed(), 0.05D, 3.0D);
boolean flightMode = isMountInFlightMode(state);
boolean jumpPressed = rider.isJumping;
boolean descendPressed = rider instanceof EntityPlayer && isSpecialKeyDown((EntityPlayer) rider);
if (flightMode) {
double previousMotionY = npc.motionY;
double newMotionY = 0.0D;
if (jumpPressed) {
newMotionY += ascendSpeed;
} else if (descendPressed) {
newMotionY -= descendSpeed;
}
newMotionY = MathHelper.clamp_double(newMotionY, -descendSpeed, ascendSpeed);
npc.motionY = newMotionY;
npc.setNpcFlyingState(true);
npc.setNpcJumpingState(jumpPressed);
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote && Math.abs(previousMotionY - newMotionY) > 1.0E-4D) {
npc.velocityChanged = true;
}
if (!npc.worldObj.isRemote && rider instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) rider;
if (!player.capabilities.isFlying) {
double playerPrevMotion = player.motionY;
player.motionY = npc.motionY;
if (Math.abs(playerPrevMotion - player.motionY) > 1.0E-4D) {
player.velocityChanged = true;
}
}
}
return;
}
if (jumpPressed && npc.onGround) {
double previousMotionY = npc.motionY;
npc.motionY = jumpFactor;
npc.setNpcJumpingState(true);
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote) {
if (Math.abs(previousMotionY - npc.motionY) > 1.0E-4D) {
npc.velocityChanged = true;
}
net.minecraftforge.common.ForgeHooks.onLivingJump(npc);
}
return;
}
if (!npc.onGround) {
double previousMotionY = npc.motionY;
double limitedMotionY = Math.max(npc.motionY, -descendSpeed);
if (Math.abs(previousMotionY - limitedMotionY) > 1.0E-4D) {
npc.motionY = limitedMotionY;
if (!npc.worldObj.isRemote) {
npc.velocityChanged = true;
}
} else {
npc.motionY = limitedMotionY;
}
npc.setNpcFlyingState(!npc.isInWater());
} else {
npc.setNpcFlyingState(false);
}
return;
}
if (npc.onGround) {
double previousMotionY = npc.motionY;
if (rider.isJumping) {
npc.motionY = jumpFactor;
npc.setNpcJumpingState(true);
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote) {
if (Math.abs(previousMotionY - npc.motionY) > 1.0E-4D) {
npc.velocityChanged = true;
}
net.minecraftforge.common.ForgeHooks.onLivingJump(npc);
}
} else {
npc.motionY = 0.0D;
}
return;
}
npc.setNpcFlyingState(false);
}
public static void handleMountRiderState(EntityNPCInterface npc, MountState state) {
if (npc.worldObj.isRemote) {
if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) {
state.lastRider = null;
}
return;
}
if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) {
state.lastRider = null;
return;
}
RoleMount mount = (RoleMount) npc.roleInterface;
Entity currentRider = npc.riddenByEntity;
if (currentRider != null && !(currentRider instanceof EntityPlayer)) {
Entity dismount = currentRider;
dismount.mountEntity(null);
stabilizeDismountedRider(dismount);
haltMountedMotion(npc, state);
applyUnriddenFlightDescent(npc, state, mount);
currentRider = null;
}
if (currentRider != state.lastRider) {
if (state.lastRider != null) {
stabilizeDismountedRider(state.lastRider);
}
if (currentRider == null) {
haltMountedMotion(npc, state);
applyUnriddenFlightDescent(npc, state, mount);
} else {
resetMountedFlightState(npc, state);
}
state.lastRider = currentRider;
} else if (currentRider == null) {
applyUnriddenFlightDescent(npc, state, mount);
}
}
public static boolean isFlyingMountWithFlightEnabled(EntityNPCInterface npc) {
return npc.advanced.role == EnumRoleType.Mount && npc.roleInterface instanceof RoleMount && ((RoleMount) npc.roleInterface).isFlyingMountEnabled();
}
public static void haltMountedMotion(EntityNPCInterface npc, MountState state) {
double prevMotionX = npc.motionX;
double prevMotionY = npc.motionY;
double prevMotionZ = npc.motionZ;
npc.motionX = 0.0D;
npc.motionY = 0.0D;
npc.motionZ = 0.0D;
npc.isAirBorne = false;
npc.setSprinting(false);
npc.moveForward = 0.0F;
npc.moveStrafing = 0.0F;
npc.setAIMoveSpeed(0.0F);
npc.limbSwingAmount = 0.0F;
npc.limbSwing = 0.0F;
npc.getNavigator().clearPathEntity();
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote && (Math.abs(prevMotionX) > 1.0E-4D || Math.abs(prevMotionY) > 1.0E-4D || Math.abs(prevMotionZ) > 1.0E-4D)) {
npc.velocityChanged = true;
}
resetMountedFlightState(npc, state);
}
public static void applyUnriddenFlightDescent(EntityNPCInterface npc, MountState state, RoleMount mount) {
if (mount == null || !mount.isFlyingMountEnabled()) {
npc.setNpcFlyingState(false);
npc.setNpcJumpingState(false);
return;
}
2025-11-07 22:44:22 -05:00
if (npc.canFly()) {
return;
}
if (npc.onGround) {
npc.motionY = 0.0D;
npc.setNpcFlyingState(false);
npc.setNpcJumpingState(false);
return;
}
double descendSpeed = MathHelper.clamp_double(mount.getFlyingDescendSpeed(), 0.05D, 3.0D);
if (descendSpeed <= 0.0D) {
npc.setNpcFlyingState(false);
npc.setNpcJumpingState(false);
return;
}
double desired = -descendSpeed;
double previousMotionY = npc.motionY;
npc.motionY = desired;
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
npc.setNpcFlyingState(true);
npc.setNpcJumpingState(false);
if (!npc.worldObj.isRemote && Math.abs(previousMotionY - desired) > 1.0E-4D) {
npc.velocityChanged = true;
}
}
public static void stabilizeDismountedRider(Entity rider) {
boolean wasOnGround = rider.onGround;
double previousMotionX = rider.motionX;
double previousMotionY = rider.motionY;
double previousMotionZ = rider.motionZ;
float previousFall = rider.fallDistance;
if (wasOnGround) {
rider.motionX = 0.0D;
rider.motionY = 0.0D;
rider.motionZ = 0.0D;
rider.fallDistance = 0.0F;
rider.onGround = true;
} else {
rider.motionX = previousMotionX;
rider.motionY = previousMotionY;
rider.motionZ = previousMotionZ;
rider.fallDistance = previousFall;
}
rider.velocityChanged = true;
}
private static void updateMountedFlightState(EntityNPCInterface npc, MountState state, RoleMount mount, EntityPlayer rider) {
if (mount == null || rider == null || !mount.isFlyingMountEnabled()) {
resetMountedFlightState(npc, state);
return;
}
if (npc.onGround) {
state.flightMode = false;
}
boolean jumpPressed = rider.isJumping;
if (jumpPressed && !state.jumpPressed) {
if (state.flightToggleTimer > 0) {
state.flightMode = !state.flightMode;
state.flightToggleTimer = 0;
} else {
state.flightToggleTimer = MOUNT_FLIGHT_TOGGLE_WINDOW;
}
}
if (state.flightToggleTimer > 0) {
state.flightToggleTimer--;
}
state.jumpPressed = jumpPressed;
}
public static boolean isMountInFlightMode(MountState state) {
return state.flightMode;
}
public static void resetMountedFlightState(EntityNPCInterface npc, MountState state) {
state.flightMode = false;
state.jumpPressed = false;
state.flightToggleTimer = 0;
npc.setNpcFlyingState(false);
npc.setNpcJumpingState(false);
}
private static boolean isSpecialKeyDown(EntityPlayer rider) {
if (rider == null) {
return false;
}
if (rider.worldObj.isRemote) {
PlayerData data = CustomNpcs.proxy.getPlayerData(rider);
return data != null && data.isSpecialKeyDown();
}
PlayerData data = PlayerDataController.Instance.getPlayerData(rider);
return data != null && data.isSpecialKeyDown();
}
}