Merge branch 'dev' into janino-scripts

This commit is contained in:
bigguy345 committed 2026-01-10 00:19:14 +02:00
commit fb0332e5cf
53 files changed
+3017 -376

No files matched your search

@@ -60,6 +60,7 @@ import kamkeel.npcs.network.packets.player.MailActionPacket;
import kamkeel.npcs.network.packets.player.SaveBookPacket;
import kamkeel.npcs.network.packets.player.SaveSignPacket;
import kamkeel.npcs.network.packets.player.ScreenSizePacket;
import kamkeel.npcs.network.packets.player.SpecialKeyStatePacket;
import kamkeel.npcs.network.packets.player.TransportPacket;
import kamkeel.npcs.network.packets.player.customgui.CustomGuiButtonPacket;
import kamkeel.npcs.network.packets.player.customgui.CustomGuiClosePacket;
@@ -568,6 +569,7 @@ public class PacketHandler {
PLAYER_PACKET.registerPacket(new InputDevicePacket());
PLAYER_PACKET.registerPacket(new ScreenSizePacket());
PLAYER_PACKET.registerPacket(new SpecialKeyStatePacket());
PLAYER_PACKET.registerPacket(new SyncRevisionInfoPacket());
@@ -14,6 +14,7 @@ public enum EnumPlayerPacket {
CompanionAction,
GetRole,
InputDevice,
SpecialKeyState,
ScreenSize,
MagicCycles,
@@ -0,0 +1,60 @@
package kamkeel.npcs.network.packets.player;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import kamkeel.npcs.network.AbstractPacket;
import kamkeel.npcs.network.PacketChannel;
import kamkeel.npcs.network.PacketClient;
import kamkeel.npcs.network.PacketHandler;
import kamkeel.npcs.network.enums.EnumPlayerPacket;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import noppes.npcs.controllers.PlayerDataController;
import noppes.npcs.controllers.data.PlayerData;
import java.io.IOException;
public final class SpecialKeyStatePacket extends AbstractPacket {
private boolean pressed;
public SpecialKeyStatePacket() {
}
private SpecialKeyStatePacket(boolean pressed) {
this.pressed = pressed;
}
public static void send(boolean pressed) {
PacketClient.sendClient(new SpecialKeyStatePacket(pressed));
}
@Override
public Enum getType() {
return EnumPlayerPacket.SpecialKeyState;
}
@Override
public PacketChannel getChannel() {
return PacketHandler.PLAYER_PACKET;
}
@Override
@SideOnly(Side.CLIENT)
public void sendData(ByteBuf out) throws IOException {
out.writeBoolean(pressed);
}
@Override
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
boolean keyDown = in.readBoolean();
if (!(player instanceof EntityPlayerMP)) {
return;
}
PlayerData data = PlayerDataController.Instance.getPlayerData((EntityPlayerMP) player);
if (data != null) {
data.setSpecialKeyDown(keyDown);
}
}
}
@@ -92,7 +92,7 @@ public final class LinkedItemScriptPacket extends AbstractPacket {
} else {
data.saveScript(in);
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
LogWriter.script(String.format("[%s] (Player) %s SAVED EFFECT %s [%s]", "LINKED ITEM SCRIPTS", player.getCommandSenderName(), linkedItem.getName()));
LogWriter.script(String.format("[%s] (Player) %s SAVED LINKED ITEM [%s]", "LINKED ITEM SCRIPTS", player.getCommandSenderName(), linkedItem.getName()));
}
}
}
+1 -1
View File
@@ -101,7 +101,7 @@ import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.10.2")
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.10.3")
public class CustomNpcs {
@SidedProxy(clientSide = "noppes.npcs.client.ClientProxy", serverSide = "noppes.npcs.CommonProxy")
@@ -123,8 +123,12 @@ public class NoppesUtilPlayer {
}
public static void teleportPlayer(EntityPlayerMP player, double posX, double posY, double posZ, int dimension) {
// Dismount from NPC mount before teleportation to prevent mount desync
if (player.ridingEntity instanceof EntityNPCInterface) {
player.mountEntity(null);
}
if (player.dimension != dimension) {
int dim = player.dimension;
MinecraftServer server = MinecraftServer.getServer();
WorldServer wor = server.worldServerForDimension(dimension);
if (wor == null) {
@@ -144,8 +148,12 @@ public class NoppesUtilPlayer {
}
public static void teleportPlayer(EntityPlayerMP player, double posX, double posY, double posZ, float yaw, float pitch, int dimension) {
// Dismount from NPC mount before teleportation to prevent mount desync
if (player.ridingEntity instanceof EntityNPCInterface) {
player.mountEntity(null);
}
if (player.dimension != dimension) {
int dim = player.dimension;
MinecraftServer server = MinecraftServer.getServer();
WorldServer wor = server.worldServerForDimension(dimension);
if (wor == null) {
@@ -44,6 +44,7 @@ import net.minecraftforge.event.world.BlockEvent;
import noppes.npcs.api.IWorld;
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.api.item.IItemCustomizable;
import noppes.npcs.api.item.IItemStack;
import noppes.npcs.config.ConfigMain;
import noppes.npcs.config.ConfigScript;
import noppes.npcs.constants.EnumQuestType;
@@ -60,6 +61,8 @@ import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.items.ItemNpcTool;
import noppes.npcs.quests.QuestItem;
import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.item.ScriptCustomizableItem;
import noppes.npcs.scripted.item.ScriptItemStack;
import static noppes.npcs.config.ConfigMain.TrackedQuestUpdateFrequency;
@@ -545,6 +548,18 @@ public class ScriptPlayerEventHandler {
}
if (event.source.getEntity() instanceof EntityPlayerMP) {
EntityPlayerMP playerMP = (EntityPlayerMP) event.source.getEntity();
if(playerMP.getHeldItem() != null) {
IItemStack itemStack = NpcAPI.Instance().getIItemStack(playerMP.getHeldItem());
if (itemStack instanceof ScriptCustomizableItem) {
ScriptCustomizableItem sci = (ScriptCustomizableItem) itemStack;
int attackSpeed = sci.getAttackSpeed();
if (event.entityLiving.hurtResistantTime <= event.entityLiving.maxHurtResistantTime - attackSpeed) {
event.entityLiving.hurtResistantTime = 0;
}
}
}
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) event.source.getEntity());
float attackAmount = event.ammount;
if (ConfigMain.AttributesEnabled && !DBCAddon.IsAvailable())
@@ -173,19 +173,6 @@ public class ServerEventsHandler {
@SubscribeEvent
public void invoke(LivingHurtEvent event) {
if(event.source.getEntity() instanceof EntityPlayerMP && event.entity instanceof EntityLivingBase ){
EntityPlayerMP ep = (EntityPlayerMP) event.source.getEntity();
if(ep.getHeldItem() != null && ep.getHeldItem().getItem() instanceof ItemLinked){
int time = ep.getHeldItem().stackTagCompound.getCompoundTag("ItemData").getCompoundTag("LinkedData").getInteger("AttackSpeed");
event.entity.hurtResistantTime = time;
((EntityLivingBase) event.entity).hurtTime = time;
}
}
if (!(event.entityLiving instanceof EntityPlayer))
return;
@@ -433,6 +420,8 @@ public class ServerEventsHandler {
return;
String name = EntityList.getEntityString(entity);
if (entity instanceof EntityPlayer)
name = "Player";
QuestKill quest = (QuestKill) data.quest.questInterface;
if (data.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.Leader && !party.getLeaderUUID().equals(player.getUniqueID()))
return;
@@ -10,6 +10,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.WorldServer;
import noppes.npcs.controllers.ScriptController;
import noppes.npcs.controllers.data.PlayerData;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.controllers.data.action.ActionManager;
public class ServerTickHandler {
@@ -65,6 +66,11 @@ public class ServerTickHandler {
@SubscribeEvent
public void playerLogout(PlayerEvent.PlayerLoggedOutEvent event) {
// Dismount player from NPC mount before logout to prevent orphaned mount state
if (event.player.ridingEntity instanceof EntityNPCInterface) {
event.player.mountEntity(null);
}
PlayerData playerData = PlayerData.get(event.player);
if (playerData != null) {
playerData.onLogout();
@@ -0,0 +1,63 @@
package noppes.npcs.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.util.MathHelper;
import noppes.npcs.entity.EntityNPCInterface;
public class EntityAILeapAtTargetNpc extends EntityAIBase {
private final EntityNPCInterface npc;
private EntityLivingBase leapTarget;
private final float leapMotionY;
public EntityAILeapAtTargetNpc(EntityNPCInterface npc, float leapMotionY) {
this.npc = npc;
this.leapMotionY = leapMotionY;
this.setMutexBits(5);
}
@Override
public boolean shouldExecute() {
this.leapTarget = this.npc.getAttackTarget();
if (this.leapTarget == null) {
return false;
}
double distanceSq = this.npc.getDistanceSqToEntity(this.leapTarget);
if (distanceSq < 4.0D || distanceSq > 16.0D) {
return false;
}
if (!this.npc.onGround) {
return false;
}
return this.npc.getRNG().nextInt(5) == 0;
}
@Override
public boolean continueExecuting() {
boolean airborne = !this.npc.onGround;
if (!airborne) {
this.npc.setNpcJumpingState(false);
}
return airborne;
}
@Override
public void startExecuting() {
double d0 = this.leapTarget.posX - this.npc.posX;
double d1 = this.leapTarget.posZ - this.npc.posZ;
float f = MathHelper.sqrt_double(d0 * d0 + d1 * d1);
if ((double) f >= 1.0E-4D) {
this.npc.motionX += d0 / (double) f * 0.5D * 0.8D + this.npc.motionX * 0.2D;
this.npc.motionZ += d1 / (double) f * 0.5D * 0.8D + this.npc.motionZ * 0.2D;
}
this.npc.motionY = this.leapMotionY;
this.npc.setNpcJumpingState(true);
}
@Override
public void resetTask() {
this.npc.setNpcJumpingState(false);
}
}
@@ -30,7 +30,11 @@ public class EntityAIPounceTarget extends EntityAIBase {
@Override
public boolean continueExecuting() {
return !this.npc.onGround;
boolean airborne = !this.npc.onGround;
if (!airborne) {
this.npc.setNpcJumpingState(false);
}
return airborne;
}
@Override
@@ -47,6 +51,12 @@ public class EntityAIPounceTarget extends EntityAIBase {
this.npc.motionX *= this.leapSpeed;
this.npc.motionZ *= this.leapSpeed;
this.npc.motionY *= this.leapSpeed;
this.npc.setNpcJumpingState(true);
}
@Override
public void resetTask() {
this.npc.setNpcJumpingState(false);
}
public float getAngleForXYZ(double varX, double varY, double varZ, double horiDist) {
@@ -223,6 +223,7 @@ import java.util.Random;
public class ClientProxy extends CommonProxy {
public static KeyBinding NPCButton;
public static KeyBinding SpecialKey;
public static final Random RAND = new Random();
public static FontContainer Font;
@@ -289,8 +290,10 @@ public class ClientProxy extends CommonProxy {
Minecraft mc = Minecraft.getMinecraft();
NPCButton = new KeyBinding("NPC Inventory", Keyboard.KEY_N, "key.categories.customnpc");
SpecialKey = new KeyBinding("key.customnpcs.special", Keyboard.KEY_C, "key.categories.customnpc");
ClientRegistry.registerKeyBinding(NPCButton);
ClientRegistry.registerKeyBinding(SpecialKey);
new PresetController(CustomNpcs.Dir);
@@ -8,6 +8,7 @@ import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import kamkeel.npcs.network.PacketClient;
import kamkeel.npcs.network.packets.player.CheckPlayerValue;
import kamkeel.npcs.network.packets.player.InputDevicePacket;
import kamkeel.npcs.network.packets.player.SpecialKeyStatePacket;
import kamkeel.npcs.network.packets.player.ScreenSizePacket;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
@@ -23,9 +24,12 @@ import noppes.npcs.client.gui.hud.EnumHudComponent;
import noppes.npcs.client.gui.hud.HudComponent;
import noppes.npcs.client.gui.player.inventory.GuiCNPCInventory;
import noppes.npcs.client.renderer.RenderNPCInterface;
import noppes.npcs.constants.EnumRoleType;
import noppes.npcs.constants.MarkType;
import noppes.npcs.controllers.data.MarkData;
import noppes.npcs.controllers.data.PlayerData;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.roles.RoleMount;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import tconstruct.client.tabs.InventoryTabCustomNpc;
@@ -42,6 +46,7 @@ public class ClientTickHandler {
private int buttonPressed = -1;
private long buttonTime = 0L;
private final int[] ignoreKeys = new int[]{157, 29, 54, 42, 184, 56, 220, 219};
private boolean lastSpecialKeyDown = false;
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onClientTick(TickEvent.ClientTickEvent event) {
@@ -52,6 +57,30 @@ public class ClientTickHandler {
}
this.prevWorld = mc.theWorld;
}
if (event.phase == Phase.START) {
EntityPlayer player = mc.thePlayer;
if (player != null) {
boolean specialKeyDown = ClientProxy.SpecialKey != null && Keyboard.isKeyDown(ClientProxy.SpecialKey.getKeyCode());
if (specialKeyDown != lastSpecialKeyDown) {
PlayerData data = CustomNpcs.proxy.getPlayerData(player);
if (data != null) {
data.setSpecialKeyDown(specialKeyDown);
}
SpecialKeyStatePacket.send(specialKeyDown);
lastSpecialKeyDown = specialKeyDown;
}
if (player.ridingEntity instanceof EntityNPCInterface) {
EntityNPCInterface mount = (EntityNPCInterface) player.ridingEntity;
if (mount.advanced.role == EnumRoleType.Mount && mount.roleInterface instanceof RoleMount) {
RoleMount role = (RoleMount) mount.roleInterface;
if (!role.isSprintAllowed() && player.isSprinting()) {
player.setSprinting(false);
}
}
}
}
}
if (event.phase == Phase.END) {
if (mc.thePlayer != null && mc.theWorld != null && !mc.isGamePaused() && ClientEventHandler.hasOverlays(mc.thePlayer)) {
renderCNPCPlayer.itemRenderer.updateEquippedItem();
@@ -66,6 +66,8 @@ public class MusicController {
this.playingSound.stopSound();
this.sounds.remove(this.playingSound.sound);
this.playingSound = null;
this.entity = null;
this.playDelay = 20; // Prevent immediate restart when music is stopped
} else if (soundHandler != null) {
try {
soundHandler.stopSounds();
@@ -193,4 +195,26 @@ public class MusicController {
}
this.sounds.clear();
}
/**
* Stops a specific sound by its resource key.
* This is used to stop dialog sounds without affecting Bard music.
* @param soundKey The sound resource key to stop
*/
public void stopSound(String soundKey) {
if (soundKey == null || soundKey.isEmpty()) {
return;
}
ScriptClientSound sound = this.sounds.remove(soundKey);
if (sound != null) {
SoundHandler soundHandler = Minecraft.getMinecraft().getSoundHandler();
if (soundHandler != null) {
try {
soundHandler.stopSound(sound);
} catch (Exception ignored) {
}
}
sound.stopSound();
}
}
}
@@ -706,10 +706,8 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
if (!questCatSearch.equals(newText)) {
questCatSearch = newText;
if (questCatScroll != null) {
if (selectedQuestCategory.isEmpty())
questCatScroll.setList(new ArrayList<>());
else
questCatScroll.setList(filterList(questCatData, questCatSearch));
questCatScroll.setList(filterList(questCatData, questCatSearch));
questCatScroll.resetScroll();
}
}
}
@@ -718,12 +716,14 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!questFinishedSearch.equals(newText)) {
questFinishedSearch = newText;
if (questFinishedScroll != null)
if (questFinishedScroll != null) {
questFinishedScroll.setList(
selectedQuestCategory.isEmpty() ?
new ArrayList<>() :
filterAndTrimListByCategory(questFinishedData, selectedQuestCategory, questFinishedSearch)
);
questFinishedScroll.resetScroll();
}
}
}
tf = getTextField(activeFieldId);
@@ -731,12 +731,14 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!questActiveSearch.equals(newText)) {
questActiveSearch = newText;
if (questActiveScroll != null)
if (questActiveScroll != null) {
questActiveScroll.setList(
selectedQuestCategory.isEmpty() ?
new ArrayList<>() :
filterAndTrimListByCategory(questActiveData, selectedQuestCategory, questActiveSearch)
);
questActiveScroll.resetScroll();
}
}
}
}
@@ -747,8 +749,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!questFinishedSearch.equals(newText)) {
questFinishedSearch = newText;
if (questFinishedScroll != null)
if (questFinishedScroll != null) {
questFinishedScroll.setList(filterList(questFinishedData, questFinishedSearch));
questFinishedScroll.resetScroll();
}
}
}
tf = getTextField(activeFieldId);
@@ -756,8 +760,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!questActiveSearch.equals(newText)) {
questActiveSearch = newText;
if (questActiveScroll != null)
if (questActiveScroll != null) {
questActiveScroll.setList(filterList(questActiveData, questActiveSearch));
questActiveScroll.resetScroll();
}
}
}
}
@@ -768,12 +774,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!dialogCatSearch.equals(newText)) {
dialogCatSearch = newText;
if (dialogCatScroll != null)
dialogCatScroll.setList(
selectedDialogCategory.isEmpty() ?
new ArrayList<>() :
filterList(dialogCatData, dialogCatSearch)
);
if (dialogCatScroll != null) {
dialogCatScroll.setList(filterList(dialogCatData, dialogCatSearch));
dialogCatScroll.resetScroll();
}
}
}
tf = getTextField(readFieldId);
@@ -781,12 +785,14 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!dialogReadSearch.equals(newText)) {
dialogReadSearch = newText;
if (dialogReadScroll != null)
if (dialogReadScroll != null) {
dialogReadScroll.setList(
selectedDialogCategory.isEmpty() ?
new ArrayList<>() :
filterAndTrimListByCategory(dialogReadData, selectedDialogCategory, dialogReadSearch)
);
dialogReadScroll.resetScroll();
}
}
}
}
@@ -797,8 +803,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!dialogCompactSearch.equals(newText)) {
dialogCompactSearch = newText;
if (dialogCompactScroll != null)
if (dialogCompactScroll != null) {
dialogCompactScroll.setList(filterList(dialogReadData, dialogCompactSearch));
dialogCompactScroll.resetScroll();
}
}
}
}
@@ -809,12 +817,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!transCatSearch.equals(newText)) {
transCatSearch = newText;
if (transCatScroll != null)
transCatScroll.setList(
selectedTransCategory.isEmpty() ?
new ArrayList<>() :
filterList(transCatData, transCatSearch)
);
if (transCatScroll != null) {
transCatScroll.setList(filterList(transCatData, transCatSearch));
transCatScroll.resetScroll();
}
}
}
tf = getTextField(locFieldId);
@@ -822,12 +828,14 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!transLocSearch.equals(newText)) {
transLocSearch = newText;
if (transLocScroll != null)
if (transLocScroll != null) {
transLocScroll.setList(
selectedTransCategory.isEmpty() ?
new ArrayList<>() :
filterAndTrimListByCategory(transLocData, selectedTransCategory, transLocSearch)
);
transLocScroll.resetScroll();
}
}
}
}
@@ -838,8 +846,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!transCompactSearch.equals(newText)) {
transCompactSearch = newText;
if (transCompactScroll != null)
if (transCompactScroll != null) {
transCompactScroll.setList(filterList(transLocData, transCompactSearch));
transCompactScroll.resetScroll();
}
}
}
}
@@ -850,8 +860,10 @@ public class SubGuiPlayerData extends SubGuiInterface implements IPlayerDataInfo
String newText = tf.getText().toLowerCase();
if (!singleSearch.equals(newText)) {
singleSearch = newText;
if (singleScroll != null)
if (singleScroll != null) {
singleScroll.setList(filterList(currentTab == 13 ? bankData : factionData, singleSearch));
singleScroll.resetScroll();
}
}
}
}
@@ -262,6 +262,7 @@ public class GuiNpcNaturalSpawns extends GuiNPCInterface2 implements IGuiData, I
public void setSelected(String selected) {
}
@Override
public void closeSubGui(SubGuiInterface gui) {
super.closeSubGui(gui);
if (gui instanceof GuiNpcMobSpawnerSelector && this.spawnEntryScroll.hasSelected()) {
@@ -270,6 +271,9 @@ public class GuiNpcNaturalSpawns extends GuiNPCInterface2 implements IGuiData, I
this.spawn.spawnCompounds.put(selected, selector.getCompound());
initGui();
}
if (gui instanceof SubGuiNpcBiomes || gui instanceof SubGuiNpcDimensions || gui instanceof SubGuiSpawningOptions) {
save();
}
}
@Override
@@ -125,12 +125,6 @@ public class SubGuiLinkedItem extends SubGuiInterface implements ITextfieldListe
y += spacing;
// Attack Speed Field (integers only)
//addLabel(new GuiNpcLabel(13,"Attack Speed",x,y + 5, CustomNpcResourceListener.DefaultTextColor));
//y += spacing;
// TEXTURE field
addLabel(new GuiNpcLabel(3, "display.texture", x, y + 5, CustomNpcResourceListener.DefaultTextColor));
addTextField(new GuiNpcTextField(2, this, x + 60, y, 200, 20, linkedItem.display.texture));
@@ -75,6 +75,12 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose {
*/
private boolean sentClosePacket = false;
/**
* Tracks the dialog sound that was played, so we can stop only this sound
* on close without affecting Bard music or other sounds.
*/
private String dialogSound = null;
public GuiDialogInteract(EntityNPCInterface npc, Dialog dialog) {
super(npc);
this.dialog = dialog;
@@ -671,8 +677,13 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose {
this.options = new ArrayList<Integer>();
if (dialog.sound != null && !dialog.sound.isEmpty()) {
// Stop any previous dialog sound before playing new one
if (this.dialogSound != null) {
MusicController.Instance.stopSound(this.dialogSound);
}
MusicController.Instance.stopMusic();
MusicController.Instance.playSound(dialog.sound, (float) npc.posX, (float) npc.posY, (float) npc.posZ);
this.dialogSound = dialog.sound;
}
if (!dialog.showPreviousBlocks) {
@@ -707,7 +718,11 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose {
super.close();
if (parent != null)
NoppesUtil.openGUI(player, parent);
MusicController.Instance.stopAllSounds();
// Only stop the dialog sound, not Bard music or other sounds
if (this.dialogSound != null) {
MusicController.Instance.stopSound(this.dialogSound);
this.dialogSound = null;
}
}
@Override
@@ -63,6 +63,12 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos
*/
private boolean sentClosePacket = false;
/**
* Tracks the dialog sound that was played, so we can stop only this sound
* on close without affecting Bard music or other sounds.
*/
private String dialogSound = null;
public GuiModernDialogInteract(EntityNPCInterface npc, Dialog dialog) {
super(npc);
this.dialog = dialog;
@@ -380,8 +386,13 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos
this.options = new ArrayList<Integer>();
if (dialog.sound != null && !dialog.sound.isEmpty()) {
// Stop any previous dialog sound before playing new one
if (this.dialogSound != null) {
MusicController.Instance.stopSound(this.dialogSound);
}
MusicController.Instance.stopMusic();
MusicController.Instance.playSound(dialog.sound, (float) npc.posX, (float) npc.posY, (float) npc.posZ);
this.dialogSound = dialog.sound;
}
if (!dialog.showPreviousBlocks) {
@@ -440,6 +451,11 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos
}
closed();
}
// Only stop the dialog sound, not Bard music or other sounds
if (this.dialogSound != null) {
MusicController.Instance.stopSound(this.dialogSound);
this.dialogSound = null;
}
super.onGuiClosed();
}
}
@@ -4,7 +4,6 @@ import kamkeel.npcs.network.PacketClient;
import kamkeel.npcs.network.packets.request.role.RoleSavePacket;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
import noppes.npcs.client.gui.util.GuiNPCInterface2;
import noppes.npcs.client.gui.util.GuiNpcButton;
import noppes.npcs.client.gui.util.GuiNpcLabel;
@@ -13,8 +12,6 @@ import noppes.npcs.client.gui.util.ITextfieldListener;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.roles.RoleMount;
import java.util.Locale;
public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener {
private final RoleMount role;
@@ -32,55 +29,82 @@ public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener
return;
}
int y = guiTop + 6;
addOffsetRow(0, "role.mount.offsetx", role.getOffsetX(), y);
y += 24;
addOffsetRow(1, "role.mount.offsety", role.getOffsetY(), y);
y += 24;
addOffsetRow(2, "role.mount.offsetz", role.getOffsetZ(), y);
y += 24;
addJumpRow(3, "role.mount.jumpheight", role.getJumpStrength(), y);
y += 24;
int leftLabelX = guiLeft + 4;
int leftFieldX = guiLeft + 116;
int leftY = guiTop + 6;
addLabel(new GuiNpcLabel(5, "role.mount.sprint", guiLeft + 4, y + 5));
addButton(new GuiNpcButton(5, guiLeft + 140, y, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isSprintAllowed() ? 1 : 0));
leftY = addOffsetRow(0, 10, "role.mount.offsetx", role.getOffsetX(), leftLabelX, leftFieldX, leftY);
leftY = addOffsetRow(1, 11, "role.mount.offsety", role.getOffsetY(), leftLabelX, leftFieldX, leftY);
leftY = addOffsetRow(2, 12, "role.mount.offsetz", role.getOffsetZ(), leftLabelX, leftFieldX, leftY);
leftY = addJumpRow(3, 13, "role.mount.jumpheight", role.getJumpStrength(), leftLabelX, leftFieldX, leftY);
addButton(new GuiNpcButton(4, guiLeft + 4, y + 30, 80, 20, "role.mount.reset"));
addLabel(new GuiNpcLabel(4, "role.mount.sprint", leftLabelX, leftY + 5));
addButton(new GuiNpcButton(101, leftFieldX, leftY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isSprintAllowed() ? 1 : 0));
leftY += 24;
GuiNpcLabel speedLabel = new GuiNpcLabel(6, "", guiLeft + 4, y + 56);
speedLabel.label = StatCollector.translateToLocalFormatted("role.mount.walkspeed", npc.ais.getWalkingSpeed());
addLabel(speedLabel);
int rightLabelX = guiLeft + 214;
int rightFieldX = guiLeft + 320;
int rightY = guiTop + 6;
addLabel(new GuiNpcLabel(20, "role.mount.fly", rightLabelX, rightY + 5));
addButton(new GuiNpcButton(102, rightFieldX, rightY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isFlyingMountEnabled() ? 1 : 0));
rightY += 24;
if (role.isFlyingMountEnabled()) {
addLabel(new GuiNpcLabel(21, "role.mount.hover", rightLabelX, rightY + 5));
addButton(new GuiNpcButton(103, rightFieldX, rightY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isHoverModeEnabled() ? 1 : 0));
rightY += 24;
rightY = addSpeedRow(22, 14, "role.mount.ascendspeed", role.getFlyingAscendSpeed(), rightLabelX, rightFieldX, rightY, 0.1F, 3.0F, 0.60F);
rightY = addSpeedRow(23, 15, "role.mount.descendspeed", role.getFlyingDescendSpeed(), rightLabelX, rightFieldX, rightY, 0.05F, 3.0F, 0.35F);
}
}
private void addOffsetRow(int id, String translationKey, float value, int y) {
addLabel(new GuiNpcLabel(id, translationKey, guiLeft + 4, y + 5));
GuiNpcTextField field = new GuiNpcTextField(id, this, guiLeft + 140, y, 80, 20, format(value));
private int addOffsetRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y) {
addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5));
GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value));
field.floatsOnly = true;
field.setMinMaxDefaultFloat(-5.0F, 5.0F, 0.0F);
addTextField(field);
return y + 24;
}
private void addJumpRow(int id, String translationKey, float value, int y) {
addLabel(new GuiNpcLabel(id, translationKey, guiLeft + 4, y + 5));
GuiNpcTextField field = new GuiNpcTextField(id, this, guiLeft + 140, y, 80, 20, format(value));
private int addJumpRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y) {
addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5));
GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value));
field.floatsOnly = true;
field.setMinMaxDefaultFloat(0.1F, 15.0F, 1.0F);
addTextField(field);
return y + 24;
}
private int addSpeedRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y, float min, float max, float defaultValue) {
addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5));
GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value));
field.floatsOnly = true;
field.setMinMaxDefaultFloat(min, max, defaultValue);
addTextField(field);
return y + 24;
}
private String format(float value) {
return String.format(Locale.ROOT, "%.2f", value);
return String.format(java.util.Locale.ROOT, "%.2f", value);
}
@Override
public void buttonEvent(GuiButton guibutton) {
if (role == null)
return;
if (guibutton.id == 4) {
role.resetOffsets();
initGui();
} else if (guibutton.id == 5 && guibutton instanceof GuiNpcButton) {
role.setSprintAllowed(((GuiNpcButton) guibutton).getValue() == 1);
if (guibutton instanceof GuiNpcButton) {
GuiNpcButton button = (GuiNpcButton) guibutton;
if (guibutton.id == 101) {
role.setSprintAllowed(button.getValue() == 1);
} else if (guibutton.id == 102) {
role.setFlyingMountEnabled(button.getValue() == 1);
initGui();
} else if (guibutton.id == 103) {
role.setHoverModeEnabled(button.getValue() == 1);
}
}
}
@@ -90,32 +114,42 @@ public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener
return;
float value = textfield.isFloat() ? textfield.getFloat() : 0.0F;
switch (textfield.id) {
case 0:
case 10:
role.setOffsetX(value);
break;
case 1:
case 11:
role.setOffsetY(value);
break;
case 2:
case 12:
role.setOffsetZ(value);
break;
case 3:
case 13:
role.setJumpStrength(value);
break;
case 14:
role.setFlyingAscendSpeed(value);
break;
case 15:
role.setFlyingDescendSpeed(value);
break;
}
textfield.setText(format(valueForField(textfield.id)));
}
private float valueForField(int id) {
switch (id) {
case 0:
case 10:
return role.getOffsetX();
case 1:
case 11:
return role.getOffsetY();
case 2:
case 12:
return role.getOffsetZ();
case 3:
case 13:
return role.getJumpStrength();
case 14:
return role.getFlyingAscendSpeed();
case 15:
return role.getFlyingDescendSpeed();
default:
return 0.0F;
}
@@ -136,10 +136,14 @@ public class PlayerQuestController {
return player.worldObj.getTotalWorldTime() - questTime >= 24000;
} else if (quest.repeat == EnumQuestRepeat.MCWEEKLY) {
return player.worldObj.getTotalWorldTime() - questTime >= 168000;
} else if (quest.repeat == EnumQuestRepeat.MCCUSTOM) {
return player.worldObj.getTotalWorldTime() - questTime >= quest.customCooldown;
} else if (quest.repeat == EnumQuestRepeat.RLDAILY) {
return System.currentTimeMillis() - questTime >= 86400000;
} else if (quest.repeat == EnumQuestRepeat.RLWEEKLY) {
return System.currentTimeMillis() - questTime >= 604800000;
} else if (quest.repeat == EnumQuestRepeat.RLCUSTOM) {
return System.currentTimeMillis() - questTime >= quest.customCooldown;
}
return false;
}
@@ -12,7 +12,10 @@ import noppes.npcs.constants.EnumAnimationPart;
import noppes.npcs.controllers.AnimationController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class Animation implements IAnimation {
public AnimationData parent; //Client-sided only
@@ -34,6 +37,12 @@ public class Animation implements IAnimation {
//Client-sided
public boolean paused;
protected final Map<String, Object> dataStore = new HashMap<>();
public Consumer<IAnimation> onAnimationStart;
public BiConsumer<Integer, IAnimation> onAnimationFrame;
public Consumer<IAnimation> onAnimationEnd;
public Animation() {
}
@@ -175,6 +184,18 @@ public class Animation implements IAnimation {
return time;
}
@Override
public boolean hasData(String key) {return dataStore.containsKey(key);}
@Override
public Object getData(String key) {return dataStore.get(key);}
@Override
public IAnimation setData(String key, Object v) {dataStore.put(key, v);return this;}
@Override
public IAnimation removeData(String key) {dataStore.remove(key);return this;}
public void readFromNBT(NBTTagCompound compound) {
if (compound.hasKey("ID")) {
id = compound.getInteger("ID");
@@ -254,8 +275,10 @@ public class Animation implements IAnimation {
if (this.currentFrame() != null) {
EventHooks.onAnimationFrameEntered(this, this.currentFrame());
fireFrameTask(this.currentFrame);
} else {
EventHooks.onAnimationEnded(this);
fireEndTask();
}
if (nextFrame != null) {
@@ -294,4 +317,61 @@ public class Animation implements IAnimation {
}
}
}
@Override
public IAnimation onStart(Consumer<IAnimation> task) {
this.onAnimationStart = task;
return this;
}
@Override
public IAnimation onFrame(BiConsumer<Integer, IAnimation> task) {
this.onAnimationFrame = task;
return this;
}
@Override
public IAnimation onEnd(Consumer<IAnimation> task) {
this.onAnimationEnd = task;
return this;
}
protected void fireStartTask() {
if (this.onAnimationStart != null) {
this.onAnimationStart.accept(this);
}
}
protected void fireFrameTask(int frame) {
if (this.onAnimationFrame != null) {
this.onAnimationFrame.accept(frame, this);
}
}
protected void fireEndTask() {
if (this.onAnimationEnd != null) {
this.onAnimationEnd.accept(this);
}
}
/**
* Only called on setAnimation, to transfer tasks from
* this global instance stored in AnimationController
* to the new local instance on entity's AnimationData,
* and clear them from the global instance.
*/
public void moveFromGlobalToLocal(Animation animation) {
this.onAnimationStart = animation.onAnimationStart;
this.onAnimationFrame = animation.onAnimationFrame;
this.onAnimationEnd = animation.onAnimationEnd;
animation.onAnimationEnd = null;
animation.onAnimationFrame = null;
animation.onAnimationStart = null;
this.dataStore.putAll(animation.dataStore);
animation.dataStore.clear();
}
}
@@ -98,15 +98,18 @@ public class AnimationData implements IAnimationData {
this.isClientAnimating = this.allowAnimation && this.animation != null;
if (prevIsClientAnimating && (!this.isClientAnimating || this.animation != this.currentClientAnimation)) {
EventHooks.onAnimationEnded(this.currentClientAnimation);
this.currentClientAnimation.fireEndTask();
}
if (this.isClientAnimating) {
this.currentClientAnimation = this.animation;
}
if (this.animation != null && this.allowAnimation) {
this.animation.fireStartTask();
if (EventHooks.onAnimationStarted(this.animation))
return;
EventHooks.onAnimationFrameEntered(this.animation, this.animation.currentFrame());
this.animation.fireFrameTask(this.animation.currentFrame);
}
List<EntityPlayer> entities = sendingEntity.worldObj.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(
@@ -269,6 +272,7 @@ public class AnimationData implements IAnimationData {
newAnim.currentFrame = 0;
newAnim.currentFrameTime = 0;
newAnim.parent = this;
newAnim.moveFromGlobalToLocal((Animation) animation);
}
@@ -29,7 +29,7 @@ public class LinkedItem implements ILinkedItem {
public boolean isNormalItem = false;
public boolean isTool = false;
public int digSpeed = 1;
public int attackSpeed = 20;
public int attackSpeed = 10;
public int armorType = -2; //-2: Fits in no armor slot, -1: Fits in all slots, 0 - 3: Fits in Head -> Boots slot respectively
public int enchantability;
@@ -59,7 +59,8 @@ public class LinkedItem implements ILinkedItem {
compound.setBoolean("IsTool", this.isTool);
compound.setBoolean("IsNormalItem", this.isNormalItem);
compound.setInteger("DigSpeed", this.digSpeed);
compound.setInteger("AttackSpeed",this.attackSpeed);
compound.setInteger("AttackSpeed", this.attackSpeed);
compound.setInteger("ArmorType", this.armorType);
compound.setInteger("Enchantability", this.enchantability);
@@ -89,7 +90,7 @@ public class LinkedItem implements ILinkedItem {
this.isTool = compound.getBoolean("IsTool");
this.isNormalItem = compound.getBoolean("IsNormalItem");
this.digSpeed = compound.getInteger("DigSpeed");
this.attackSpeed = compound.getInteger("AttackSpeed");
this.setAttackSpeed(compound.getInteger("AttackSpeed"));
this.armorType = compound.getInteger("ArmorType");
this.enchantability = compound.getInteger("Enchantability");
@@ -241,6 +242,19 @@ public class LinkedItem implements ILinkedItem {
this.enchantability = enchantability;
}
@Override
public int getAttackSpeed() {
return attackSpeed;
}
@Override
public void setAttackSpeed(int time) {
if(time <= 0) {
time = 10;
}
this.attackSpeed = time;
}
public LinkedItem clone() {
NBTTagCompound nbt = this.writeToNBT(true);
LinkedItem clone = new LinkedItem(this.name);
@@ -254,10 +268,4 @@ public class LinkedItem implements ILinkedItem {
setScriptHandler(data = new LinkedItemScript());
return data;
}
@Override
public int getAttackSpeed() {return attackSpeed;}
@Override
public void setAttackSpeed(int time) {this.attackSpeed = time;}
}
@@ -84,6 +84,7 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData {
public ScreenSize screenSize = new ScreenSize(-1, -1);
public int profileSlot = 0;
private boolean specialKeyDown = false;
public void onLogin() {
// Continue playing animation for self when re-logging
@@ -267,6 +268,14 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData {
return this.isGUIOpen;
}
public boolean isSpecialKeyDown() {
return specialKeyDown;
}
public void setSpecialKeyDown(boolean specialKeyDown) {
this.specialKeyDown = specialKeyDown;
}
public ScreenSize getScreenSize() {
return screenSize;
}
@@ -45,6 +45,7 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
if (handleMountedMovement(p_70612_1_, p_70612_2_))
return;
if (!this.canFly() || this.hurtTime != 0 || !this.canBreathe()) {
setNpcFlyingState(false);
super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
return;
}
@@ -66,11 +67,13 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
if (!this.getNavigator().noPath() && this.motionY > 0) {
this.motionY = 0;
} else {
setNpcFlyingState(false);
super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
return;
}
}
this.flyLimitAllow = true;
setNpcFlyingState(true);
double d3 = this.motionY;
super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
@@ -81,7 +84,6 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
}
this.updateLimbSwing();
this.velocityChanged = true;
}
public void updateLimbSwing() {
@@ -97,12 +99,15 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
}
@Override
protected void doMountedMovement(float strafe, float forward, float moveSpeed) {
public void performMountedMovement(float strafe, float forward, float moveSpeed) {
if (!this.canFly() || this.hurtTime != 0 || !this.canBreathe()) {
super.doMountedMovement(strafe, forward, moveSpeed);
setNpcFlyingState(false);
super.performMountedMovement(strafe, forward, moveSpeed);
return;
}
boolean flightModeActive = isMountFlightModeActive();
boolean aboveLimit = false;
double heightOffGround = this.posY - this.worldObj.getTopSolidOrLiquidBlock((int) this.posX, (int) this.posZ);
if (heightOffGround < 0) {
@@ -120,14 +125,21 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
if (!this.getNavigator().noPath() && this.motionY > 0) {
this.motionY = 0;
} else {
super.doMountedMovement(strafe, forward, moveSpeed);
setNpcFlyingState(false);
super.performMountedMovement(strafe, forward, moveSpeed);
return;
}
}
this.flyLimitAllow = true;
setNpcFlyingState(true);
if (flightModeActive) {
super.performMountedMovement(strafe, forward, moveSpeed);
return;
}
double d3 = this.motionY;
super.doMountedMovement(strafe, forward, moveSpeed);
super.performMountedMovement(strafe, forward, moveSpeed);
this.motionY = d3;
if (this.getNavigator().noPath()) {
@@ -135,6 +147,5 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
}
this.updateLimbSwing();
this.velocityChanged = true;
}
}
@@ -32,7 +32,6 @@ import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILeapAtTarget;
import net.minecraft.entity.ai.EntityAIOpenDoor;
import net.minecraft.entity.ai.EntityAIRestrictSun;
import net.minecraft.entity.ai.EntityAISwimming;
@@ -101,6 +100,7 @@ import noppes.npcs.ai.EntityAIMoveIndoors;
import noppes.npcs.ai.EntityAIMovingPath;
import noppes.npcs.ai.EntityAIOrbitTarget;
import noppes.npcs.ai.EntityAIPanic;
import noppes.npcs.ai.EntityAILeapAtTargetNpc;
import noppes.npcs.ai.EntityAIPounceTarget;
import noppes.npcs.ai.EntityAIRangedAttack;
import noppes.npcs.ai.EntityAIReturn;
@@ -159,7 +159,9 @@ import noppes.npcs.roles.RoleInterface;
import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.entity.ScriptNpc;
import noppes.npcs.scripted.event.NpcEvent;
import noppes.npcs.scripted.item.ScriptCustomizableItem;
import noppes.npcs.util.GameProfileAlt;
import noppes.npcs.util.NPCMountUtil;
import java.io.IOException;
import java.util.ArrayList;
@@ -211,7 +213,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
public ResourceLocation textureLocation = null;
private Entity lastRider;
private final NPCMountUtil.MountState mountState = new NPCMountUtil.MountState();
private static final int NPC_STATE_FLAG_FLYING = 1;
private static final int NPC_STATE_FLAG_JUMPING = 1 << 1;
public EnumAnimation currentAnimation = EnumAnimation.NONE;
@@ -282,6 +286,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
this.dataWatcher.addObject(14, Integer.valueOf(0)); // Animation
this.dataWatcher.addObject(15, Integer.valueOf(0)); // isWalking
this.dataWatcher.addObject(16, ""); // Role
this.dataWatcher.addObject(17, Byte.valueOf((byte) 0)); // Mount state flags
}
protected boolean isAIEnabled() {
@@ -634,6 +639,22 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
reset();
}
// Check for custom weapon attack speed - bypass immunity if enough time has passed
Entity sourceEntity = damagesource.getEntity();
if (sourceEntity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) sourceEntity;
ItemStack heldItem = player.getHeldItem();
if (heldItem != null) {
IItemStack itemStack = NpcAPI.Instance().getIItemStack(heldItem);
if (itemStack instanceof ScriptCustomizableItem) {
int attackSpeed = ((ScriptCustomizableItem) itemStack).getAttackSpeed();
if (this.hurtResistantTime <= this.maxHurtResistantTime - attackSpeed) {
this.hurtResistantTime = 0;
}
}
}
}
if ((float) this.hurtResistantTime > (float) this.maxHurtResistantTime / 2.0F && i <= this.lastDamage)
return false;
@@ -967,7 +988,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
*/
public void setLeapTask() {
if (this.ais.leapType == 1)
this.tasks.addTask(this.taskCount++, aiLeap = new EntityAILeapAtTarget(this, 0.4F));
this.tasks.addTask(this.taskCount++, aiLeap = new EntityAILeapAtTargetNpc(this, 0.4F));
if (this.ais.leapType == 2)
this.tasks.addTask(this.taskCount++, aiLeap = new EntityAIPounceTarget(this));
}
@@ -1486,13 +1507,14 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
delete();
} else {
if (this.riddenByEntity != null) {
stabilizeDismountedRider(this.riddenByEntity);
NPCMountUtil.stabilizeDismountedRider(this.riddenByEntity);
this.riddenByEntity.mountEntity(null);
haltMountedMotion();
NPCMountUtil.haltMountedMotion(this, mountState);
}
if (this.ridingEntity != null)
this.mountEntity(null);
lastRider = null;
mountState.lastRider = null;
NPCMountUtil.resetMountedFlightState(this, mountState);
setHealth(-1);
setSprinting(false);
getNavigator().clearPathEntity();
@@ -1623,7 +1645,32 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
}
public boolean isFlying() {
return isWalking() && !onGround;
return isNpcFlying();
}
public boolean isNpcFlying() {
return (dataWatcher.getWatchableObjectByte(17) & NPC_STATE_FLAG_FLYING) != 0;
}
public boolean isNpcJumping() {
return (dataWatcher.getWatchableObjectByte(17) & NPC_STATE_FLAG_JUMPING) != 0;
}
private void setNpcStateFlag(int mask, boolean value) {
byte current = dataWatcher.getWatchableObjectByte(17);
byte updated = value ? (byte) (current | mask) : (byte) (current & ~mask);
if (current != updated) {
dataWatcher.updateObject(17, updated);
}
}
public void setNpcFlyingState(boolean flying) {
setNpcStateFlag(NPC_STATE_FLAG_FLYING, flying);
}
public void setNpcJumpingState(boolean jumping) {
setNpcStateFlag(NPC_STATE_FLAG_JUMPING, jumping);
this.isJumping = jumping;
}
public void setBoolFlag(boolean bo, int id) {
@@ -1872,9 +1919,12 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
}
@Override
protected void fall(float par1) {
protected void fall(float distance) {
if (NPCMountUtil.isFlyingMountWithFlightEnabled(this)) {
return;
}
if (!this.stats.noFallDamage)
super.fall(par1);
super.fall(distance);
}
@Override
@@ -2089,64 +2139,47 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
}
protected boolean handleMountedMovement(float strafe, float forward) {
if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount))
return false;
if (riddenByEntity != null && !(riddenByEntity instanceof EntityPlayer)) {
riddenByEntity.mountEntity(null);
return false;
}
if (!(riddenByEntity instanceof EntityPlayer))
return false;
RoleMount mount = (RoleMount) roleInterface;
EntityPlayer rider = (EntityPlayer) riddenByEntity;
this.prevRotationYaw = this.rotationYaw = rider.rotationYaw;
this.rotationPitch = rider.rotationPitch * 0.5F;
this.setRotation(this.rotationYaw, this.rotationPitch);
this.renderYawOffset = this.rotationYaw;
this.rotationYawHead = this.rotationYaw;
float controlledStrafe = rider.moveStrafing * 0.5F;
float controlledForward = rider.moveForward;
if (controlledForward <= 0.0F) {
controlledForward *= 0.25F;
}
float moveSpeed = Math.max(0.1F, getSpeed());
boolean riderSprinting = rider.isSprinting() && mount.isSprintAllowed();
if (riderSprinting) {
moveSpeed *= 1.2F;
}
if (!mount.isSprintAllowed() && rider.isSprinting()) {
rider.setSprinting(false);
}
this.setSprinting(riderSprinting);
this.stepHeight = 1.0F;
this.jumpMovementFactor = moveSpeed * 0.1F;
this.getNavigator().clearPathEntity();
this.setAttackTarget(null);
this.setRevengeTarget(null);
this.fallDistance = 0.0F;
rider.fallDistance = 0.0F;
applyMountedVerticalMotion(rider, moveSpeed, controlledForward);
doMountedMovement(controlledStrafe, controlledForward, moveSpeed);
return true;
return NPCMountUtil.handleMountedMovement(this, mountState, strafe, forward);
}
protected void doMountedMovement(float strafe, float forward, float moveSpeed) {
public void performMountedMovement(float strafe, float forward, float moveSpeed) {
this.moveStrafing = strafe;
this.moveForward = forward;
boolean flightMode = isMountFlightModeActive();
double prevMotionY = this.motionY;
// Server-side only physics (like vanilla horse)
if (!worldObj.isRemote) {
this.jumpMovementFactor = getMountedAirStrafeFactor(moveSpeed, flightMode);
this.setAIMoveSpeed(moveSpeed);
super.moveEntityWithHeading(strafe, forward);
if (flightMode) {
this.motionY = prevMotionY;
this.isAirBorne = true;
}
}
// Both sides do animation (like vanilla horse)
updateMountedLimbSwing();
}
protected boolean isMountFlightModeActive() {
return NPCMountUtil.isMountInFlightMode(mountState);
}
private float getMountedAirStrafeFactor(float moveSpeed, boolean flightMode) {
if (moveSpeed <= 0.0F) {
return 0.0F;
}
if (!flightMode) {
return moveSpeed * 0.1F;
}
return moveSpeed * 0.5F;
}
private void updateMountedLimbSwing() {
this.prevLimbSwingAmount = this.limbSwingAmount;
double deltaX = this.posX - this.prevPosX;
double deltaZ = this.posZ - this.prevPosZ;
@@ -2162,46 +2195,6 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
this.limbSwing += this.limbSwingAmount;
}
protected void applyMountedVerticalMotion(EntityLivingBase rider, float moveSpeed, float forward) {
if (!(roleInterface instanceof RoleMount)) {
return;
}
RoleMount mount = (RoleMount) roleInterface;
double jumpFactor = MathHelper.clamp_double(mount.getJumpStrength(), 0.1D, 3.0D);
if (canFly()) {
double verticalBase = Math.max(0.1D, moveSpeed * 0.6D);
double vertical = MathHelper.clamp_double(verticalBase * jumpFactor, 0.05D, 2.0D);
if (rider.isJumping) {
this.motionY = Math.min(this.motionY + vertical, vertical);
this.isAirBorne = true;
this.velocityChanged = true;
} else {
float pitch = rider.rotationPitch;
if (pitch < -10F) {
this.motionY = vertical;
} else if (pitch > 10F) {
this.motionY = -vertical;
} else if (!this.onGround) {
this.motionY *= 0.6D;
}
}
} else if (rider.isJumping && this.onGround) {
double baseVelocity = MathHelper.clamp_double(0.4D + moveSpeed * 1.5D, 0.2D, 1.2D);
double jumpVelocity = MathHelper.clamp_double(baseVelocity * jumpFactor, 0.2D, 2.0D);
this.motionY = jumpVelocity;
this.isAirBorne = true;
this.velocityChanged = true;
if (forward > 0.0F) {
float yawRadians = this.rotationYaw * (float) Math.PI / 180.0F;
double boost = 0.4D * forward;
this.motionX += -MathHelper.sin(yawRadians) * boost;
this.motionZ += MathHelper.cos(yawRadians) * boost;
}
ForgeHooks.onLivingJump(this);
}
}
@Override
public boolean allowLeashing() {
return false;
@@ -2240,71 +2233,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
}
private void handleMountRiderState() {
if (worldObj.isRemote) {
if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount)) {
lastRider = null;
}
return;
}
if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount)) {
lastRider = null;
return;
}
Entity currentRider = this.riddenByEntity;
if (currentRider != null && !(currentRider instanceof EntityPlayer)) {
Entity dismount = currentRider;
dismount.mountEntity(null);
stabilizeDismountedRider(dismount);
haltMountedMotion();
currentRider = null;
}
if (currentRider != lastRider) {
if (lastRider != null) {
stabilizeDismountedRider(lastRider);
haltMountedMotion();
}
lastRider = currentRider;
}
}
private 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 void haltMountedMotion() {
this.motionX = 0.0D;
this.motionY = 0.0D;
this.motionZ = 0.0D;
this.velocityChanged = true;
this.isAirBorne = false;
this.setSprinting(false);
this.moveForward = 0.0F;
this.moveStrafing = 0.0F;
this.setAIMoveSpeed(0.0F);
this.limbSwingAmount = 0.0F;
this.limbSwing = 0.0F;
this.getNavigator().clearPathEntity();
NPCMountUtil.handleMountRiderState(this, mountState);
}
// Model Types: 0: Steve 64x32, 1: Steve 64x64, 2: Alex 64x64
@@ -94,6 +94,7 @@ public class EntityNpcDragon extends EntityNPCInterface {
field_40172_ax += f1 * 0.5F;
}
super.onLivingUpdate();
this.isFlying = isNpcFlying();
}
// public float ticks = 0.0f;
@@ -35,4 +35,10 @@ public class EntityNpcPony extends EntityNPCInterface {
super.onUpdate();
}
@Override
public void onLivingUpdate() {
super.onLivingUpdate();
this.isFlying = isNpcFlying();
}
}
+59 -4
View File
@@ -10,12 +10,13 @@ public class RoleMount extends RoleInterface {
private float offsetX;
private float offsetY;
private float offsetZ;
private static final float MIN_JUMP_STRENGTH = 0.1F;
private static final float MAX_JUMP_STRENGTH = 3.0F;
private boolean storedReturnToStart;
private float jumpStrength = 1.0F;
private boolean allowSprint = true;
private boolean flyingMountEnabled = false;
private boolean hoverMode = false;
private float flyingAscendSpeed = 0.60F;
private float flyingDescendSpeed = 0.35F;
public RoleMount(EntityNPCInterface npc) {
super(npc);
@@ -31,6 +32,10 @@ public class RoleMount extends RoleInterface {
compound.setBoolean("MountReturnFlag", storedReturnToStart);
compound.setFloat("MountJumpStrength", jumpStrength);
compound.setBoolean("MountAllowSprint", allowSprint);
compound.setBoolean("MountAllowFlying", flyingMountEnabled);
compound.setBoolean("MountHoverMode", hoverMode);
compound.setFloat("MountFlyingAscendSpeed", flyingAscendSpeed);
compound.setFloat("MountFlyingDescendSpeed", flyingDescendSpeed);
return compound;
}
@@ -50,6 +55,20 @@ public class RoleMount extends RoleInterface {
jumpStrength = 1.0F;
}
allowSprint = !compound.hasKey("MountAllowSprint") || compound.getBoolean("MountAllowSprint");
flyingMountEnabled = compound.hasKey("MountAllowFlying") && compound.getBoolean("MountAllowFlying");
hoverMode = compound.hasKey("MountHoverMode") && compound.getBoolean("MountHoverMode");
if (compound.hasKey("MountFlyingAscendSpeed")) {
setFlyingAscendSpeed(compound.getFloat("MountFlyingAscendSpeed"));
} else {
flyingAscendSpeed = 0.60F;
}
if (compound.hasKey("MountFlyingDescendSpeed")) {
setFlyingDescendSpeed(compound.getFloat("MountFlyingDescendSpeed"));
} else if (compound.hasKey("MountFlyingFallSpeed")) {
setFlyingDescendSpeed(compound.getFloat("MountFlyingFallSpeed"));
} else {
flyingDescendSpeed = 0.35F;
}
npc.ais.returnToStart = false;
}
@@ -106,7 +125,7 @@ public class RoleMount extends RoleInterface {
}
public void setJumpStrength(float value) {
this.jumpStrength = ValueUtil.clamp(value, MIN_JUMP_STRENGTH, MAX_JUMP_STRENGTH);
this.jumpStrength = ValueUtil.clamp(value, 0.1F, 3.0F);
}
public float getJumpStrength() {
@@ -121,6 +140,38 @@ public class RoleMount extends RoleInterface {
return allowSprint;
}
public void setFlyingMountEnabled(boolean enabled) {
this.flyingMountEnabled = enabled;
}
public boolean isFlyingMountEnabled() {
return flyingMountEnabled;
}
public void setHoverModeEnabled(boolean enabled) {
this.hoverMode = enabled;
}
public boolean isHoverModeEnabled() {
return hoverMode;
}
public void setFlyingAscendSpeed(float value) {
this.flyingAscendSpeed = ValueUtil.clamp(value, 0.1F, 3.0F);
}
public float getFlyingAscendSpeed() {
return flyingAscendSpeed;
}
public void setFlyingDescendSpeed(float value) {
this.flyingDescendSpeed = ValueUtil.clamp(value, 0.05F, 3.0F);
}
public float getFlyingDescendSpeed() {
return flyingDescendSpeed;
}
public void setReturnToStartPreference(boolean value) {
this.storedReturnToStart = value;
npc.ais.returnToStart = false;
@@ -141,6 +192,10 @@ public class RoleMount extends RoleInterface {
}
public void onDisable() {
// Dismount any rider when mount role is disabled
if (npc.riddenByEntity != null) {
npc.riddenByEntity.mountEntity(null);
}
npc.ais.returnToStart = storedReturnToStart;
}
@@ -36,6 +36,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus
public int digSpeed = 1;
public int armorType = -2; //-2: Fits in no armor slot, -1: Fits in all slots, 0 - 4: Fits in Head -> Boots slot respectively
public int enchantability;
public int attackSpeed = 10;
public long lastInited = -1;
@@ -228,6 +229,18 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus
return this.enchantability;
}
public int getAttackSpeed() {
return this.attackSpeed;
}
public void setAttackSpeed(int speed) {
if(speed <= 0) {
speed = 10;
}
this.attackSpeed = speed;
saveItemData();
}
public void setEnchantability(int enchantability) {
this.enchantability = enchantability;
saveItemData();
@@ -270,6 +283,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus
compound.setInteger("DigSpeed", this.digSpeed);
compound.setInteger("ArmorType", this.armorType);
compound.setInteger("Enchantability", this.enchantability);
compound.setInteger("AttackSpeed", this.attackSpeed);
compound.setInteger("MaxItemUseDuration", this.maxItemUseDuration);
compound.setInteger("ItemUseAction", this.itemUseAction);
@@ -286,6 +300,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus
this.digSpeed = compound.getInteger("DigSpeed");
this.armorType = compound.getInteger("ArmorType");
this.enchantability = compound.getInteger("Enchantability");
setAttackSpeed(compound.getInteger("AttackSpeed"));
this.maxItemUseDuration = compound.getInteger("MaxItemUseDuration");
this.itemUseAction = compound.getInteger("ItemUseAction");
@@ -30,6 +30,7 @@ public abstract class ScriptCustomizableItem extends ScriptItemStack implements
public abstract int getEnchantability();
public abstract int getAttackSpeed();
public String getTexture() {
return this.itemDisplay.texture == null ? "" : this.itemDisplay.texture;
@@ -102,6 +102,11 @@ public class ScriptLinkedItem extends ScriptCustomizableItem implements IItemLin
return this.linkedItem.enchantability;
}
@Override
public int getAttackSpeed() {
return this.linkedItem.attackSpeed;
}
@Override
public String getTexture() {
return this.itemDisplay.texture == null ? this.linkedItem.display.texture : this.itemDisplay.texture;
@@ -0,0 +1,336 @@
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;
return;
}
if (jumpPressed && npc.onGround) {
npc.motionY = jumpFactor;
npc.setNpcJumpingState(true);
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote) {
net.minecraftforge.common.ForgeHooks.onLivingJump(npc);
}
return;
}
if (!npc.onGround) {
npc.motionY = Math.max(npc.motionY, -descendSpeed);
npc.setNpcFlyingState(!npc.isInWater());
} else {
npc.setNpcFlyingState(false);
}
return;
}
if (npc.onGround) {
if (rider.isJumping) {
npc.motionY = jumpFactor;
npc.setNpcJumpingState(true);
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
if (!npc.worldObj.isRemote) {
net.minecraftforge.common.ForgeHooks.onLivingJump(npc);
}
}
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;
// Validate rider is alive and valid - dismount dead/invalid riders
if (currentRider != null && !currentRider.isEntityAlive()) {
currentRider.mountEntity(null);
stabilizeDismountedRider(currentRider);
haltMountedMotion(npc, state);
applyUnriddenFlightDescent(npc, state, mount);
currentRider = null;
}
// Only allow EntityPlayer as riders
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) {
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;
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;
}
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;
}
npc.motionY = -descendSpeed;
npc.isAirBorne = true;
npc.fallDistance = 0.0F;
npc.setNpcFlyingState(true);
npc.setNpcJumpingState(false);
}
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;
}
}
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();
}
}