mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 21:17:32 +00:00
Merge branch 'dev' into syntax-highlighter-unified
This commit is contained in:
commit
f4fdde4a0b
21 files changed
+269
-65
No files matched your search
@@ -184,6 +184,14 @@ public class SyncController {
|
||||
DBCAddon.instance.syncPlayer(player);
|
||||
syncPlayerData(player, false);
|
||||
PartyInfoPacket.sendPartyData(player);
|
||||
|
||||
// Sync skin overlays after full handshake to ensure the client is ready.
|
||||
// Overlays are not part of getSyncNBTFull(), and packets sent during
|
||||
// PlayerLoggedInEvent can arrive before the client entity exists.
|
||||
PlayerData data = PlayerData.get(player);
|
||||
if (data != null) {
|
||||
data.skinOverlays.updateClient();
|
||||
}
|
||||
}
|
||||
|
||||
private static EnumMap<EnumSyncType, Integer> getServerRevisionSnapshot() {
|
||||
|
||||
@@ -741,6 +741,13 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
|
||||
double px = ent.posX + dirX * probe;
|
||||
double py = ent.posY + dirY * probe;
|
||||
double pz = ent.posZ + dirZ * probe;
|
||||
// Never probe below the entity's feet — a downward probe always detects the
|
||||
// block the entity is already standing/hovering above (false positive).
|
||||
// MC's own collision system prevents entities from falling through floors,
|
||||
// so the downward check is redundant. Upward probes (ceiling detection) still work.
|
||||
if (py < ent.posY) {
|
||||
py = ent.posY;
|
||||
}
|
||||
AxisAlignedBB box = AxisAlignedBB.getBoundingBox(
|
||||
px - halfW, py, pz - halfW,
|
||||
px + halfW, py + ent.height, pz + halfW
|
||||
|
||||
@@ -124,7 +124,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-prerelease2")
|
||||
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-prerelease3")
|
||||
public class CustomNpcs {
|
||||
|
||||
@SidedProxy(clientSide = "noppes.npcs.client.ClientProxy", serverSide = "noppes.npcs.CommonProxy")
|
||||
|
||||
@@ -199,7 +199,7 @@ public class GuiNpcMobSpawnerFullscreen extends GuiDirectory implements IGuiData
|
||||
navScroll.setSelected(getNavSelection());
|
||||
navScroll.scrollY = Math.min(savedNavScroll, Math.max(0, navScroll.maxScrollY));
|
||||
|
||||
// Phase 2: color nav items orange (selectable) or red (current location, not selectable)
|
||||
// Phase 2: color nav items orange (selectable) or red (current location)
|
||||
if (movePhase == 2) {
|
||||
String currentNav = getNavSelection();
|
||||
for (String name : navNames) {
|
||||
|
||||
@@ -88,12 +88,15 @@ public class SubGuiAbilityVariantSelect extends SubGuiInterface implements ICust
|
||||
scroll.setSize(190, 155);
|
||||
|
||||
// Mark blank separators and group headers as non-interactive colored entries
|
||||
scroll.nonInteractive.add("");
|
||||
scroll.colors.put("", 0x000000);
|
||||
if (lastGroup != null) {
|
||||
for (int i = 0; i < variants.size(); i++) {
|
||||
String group = variants.get(i).getGroup();
|
||||
if (group != null)
|
||||
if (group != null) {
|
||||
scroll.nonInteractive.add(group);
|
||||
scroll.colors.put(group, 0xFFFF00); // Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,24 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
|
||||
@Override
|
||||
protected void onCloneItem() {
|
||||
// Abilities don't support cloning through this mechanism
|
||||
if (currentIsBuiltIn) return;
|
||||
if (isChainedMode() && selectedChain != null) {
|
||||
ChainedAbility clone = new ChainedAbility();
|
||||
clone.readNBT(selectedChain.writeNBT(false));
|
||||
String cloneName = selectedChain.getName() + "_copy";
|
||||
clone.setName(cloneName);
|
||||
PacketClient.sendClient(new ChainedAbilitySavePacket(clone.writeNBT(false)));
|
||||
if (selectedCatId >= 0) requestItemsInCategory(selectedCatId);
|
||||
} else if (selectedAbility != null) {
|
||||
Ability clone = AbilityController.Instance.fromNBT(selectedAbility.writeNBT(false));
|
||||
if (clone != null) {
|
||||
clone.setId(UUID.randomUUID().toString());
|
||||
String cloneName = selectedAbility.getName() + "_copy";
|
||||
clone.setName(cloneName);
|
||||
PacketClient.sendClient(new CustomAbilitySavePacket(clone.writeNBT(false)));
|
||||
if (selectedCatId >= 0 && isCustomMode()) requestItemsInCategory(selectedCatId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -672,10 +689,10 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
|
||||
if (!isPlaying || isPaused) {
|
||||
String statusKey = isPaused ? "animation.paused" : "animation.stopped";
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(91, "", btnX + 65, playY, 11, 20, animTexture, 18, 71));
|
||||
} else {
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(92, "", btnX + 65, playY, 14, 20, animTexture, 0, 71));
|
||||
}
|
||||
if (isActive) {
|
||||
@@ -683,13 +700,19 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
}
|
||||
}
|
||||
|
||||
// Edit + Remove at bottom
|
||||
int editY = contentY + contentH - btnH * 2 - gap;
|
||||
GuiNpcButton editBtn = new GuiNpcButton(51, rightX, editY, rightPanelW, btnH, "gui.edit");
|
||||
// Edit + Copy on one row, Remove below
|
||||
int btnY = contentY + contentH - btnH * 2 - gap;
|
||||
int halfW = (rightPanelW - gap) / 2;
|
||||
|
||||
GuiNpcButton editBtn = new GuiNpcButton(51, rightX, btnY, halfW, btnH, "gui.edit");
|
||||
editBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
addButton(editBtn);
|
||||
|
||||
int removeY = editY + btnH + gap;
|
||||
GuiNpcButton cloneBtn = new GuiNpcButton(52, rightX + halfW + gap, btnY, halfW, btnH, "gui.copy");
|
||||
cloneBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
addButton(cloneBtn);
|
||||
|
||||
int removeY = btnY + btnH + gap;
|
||||
GuiNpcButton removeBtn = new GuiNpcButton(53, rightX, removeY, rightPanelW, btnH, "gui.remove");
|
||||
removeBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
removeBtn.setTextColor(0xFF5555);
|
||||
@@ -718,6 +741,8 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
* Matches GuiAbilityInterface's rendering pipeline.
|
||||
*/
|
||||
private void drawAbilityPreview(float partialTicks) {
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
// Set NPC facing direction
|
||||
npc.prevRenderYawOffset = npc.renderYawOffset = NPC_FACING_YAW;
|
||||
npc.prevRotationYaw = npc.rotationYaw = NPC_FACING_YAW;
|
||||
@@ -822,14 +847,17 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
GL11.glTranslatef(0.0F, entity.yOffset, 1F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(entity, 0.0, 0.0, 0.0, 0.0F, 1.0F);
|
||||
} catch (Exception ignored) {}
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
|
||||
entity.prevRenderYawOffset = entity.renderYawOffset = f2;
|
||||
entity.prevRotationYaw = entity.rotationYaw = f3;
|
||||
entity.rotationPitch = f4;
|
||||
entity.prevRotationYawHead = entity.rotationYawHead = f7;
|
||||
GL11.glPopMatrix();
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
@@ -837,7 +865,6 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
private void renderPreviewEntities(float partialTicks) {
|
||||
@@ -959,32 +986,32 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
if (isChainedMode() && selectedChain != null) {
|
||||
fontRendererObj.drawString(selectedChain.getDisplayName(), x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
fontRendererObj.drawString("Entries: " + selectedChain.getEntries().size(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.entries") + ": " + selectedChain.getEntries().size(), x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Cooldown: " + selectedChain.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.cooldown") + ": " + selectedChain.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
UserType ut = selectedChain.getAllowedBy();
|
||||
fontRendererObj.drawString("Allowed: " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.allowed") + ": " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
} else if (selectedAbility != null) {
|
||||
fontRendererObj.drawString(selectedAbility.getDisplayName(), x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
String typeId = selectedAbility.getTypeId();
|
||||
String typeName = StatCollector.translateToLocal(typeId);
|
||||
fontRendererObj.drawString("Type: " + typeName, x, y, 0xFFAE0D, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.type") + ": " + typeName, x, y, 0xFFAE0D, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Cooldown: " + selectedAbility.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.cooldown") + ": " + selectedAbility.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Windup: " + selectedAbility.getWindUpTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.windup") + ": " + selectedAbility.getWindUpTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
UserType ut = selectedAbility.getAllowedBy();
|
||||
fontRendererObj.drawString("Allowed: " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.allowed") + ": " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
if (selectedAbility.hasDamage()) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Damage: " + selectedAbility.getDisplayDamage(), x, y, 0xFF5555, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.damage") + ": " + selectedAbility.getDisplayDamage(), x, y, 0xFF5555, false);
|
||||
}
|
||||
if (currentIsBuiltIn) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("(Built-in)", x, y, 0x55FF55, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.builtin.tag"), x, y, 0x55FF55, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.NoppesUtil;
|
||||
import noppes.npcs.client.gui.util.GuiCustomScroll;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
@@ -34,6 +35,7 @@ import noppes.npcs.controllers.data.AnimationData;
|
||||
import noppes.npcs.controllers.data.Category;
|
||||
import noppes.npcs.controllers.data.Frame;
|
||||
import noppes.npcs.controllers.data.FramePart;
|
||||
import noppes.npcs.client.ClientEventHandler;
|
||||
import noppes.npcs.entity.EntityCustomNpc;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -263,10 +265,13 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
@Override
|
||||
protected void initRightPanel(int startY) {
|
||||
// Calculate layout: playback row + edit/copy + remove rows
|
||||
// Calculate layout: playback rows + edit/copy + remove rows
|
||||
int bottomRows = 2; // edit+copy, remove
|
||||
boolean hasPlayback = animation != null && !animation.frames.isEmpty() && hasSelectedItem();
|
||||
if (hasPlayback) bottomRows++; // playback row
|
||||
if (hasPlayback) {
|
||||
bottomRows++; // playback controls row
|
||||
if (playingAnimation) bottomRows++; // frame info row
|
||||
}
|
||||
int bottomH = bottomRows * (btnH + gap) + 14;
|
||||
|
||||
previewX = rightX;
|
||||
@@ -283,15 +288,17 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
if (!playingAnimation || (data.animation != null && data.animation.paused)) {
|
||||
String statusKey = (data.animation != null && data.animation.paused) ? "animation.paused" : "animation.stopped";
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(91, "", btnX + 65, playY, 11, 20, animTexture, 18, 71));
|
||||
} else {
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(94, "", btnX + 60, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(92, "", btnX + 65, playY, 14, 20, animTexture, 0, 71));
|
||||
}
|
||||
if (playingAnimation) {
|
||||
addButton(new GuiTexturedButton(93, "", btnX + 85, playY, 14, 20, animTexture, 33, 71));
|
||||
// Frame info on its own line below playback controls
|
||||
int frameInfoY = playY + btnH + gap;
|
||||
addLabel(new GuiNpcLabel(94, "", btnX, frameInfoY + 5, 0xFFFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,15 +479,18 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
GL11.glTranslatef(0.0F, entity.yOffset, 1F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(entity, 0.0, 0.0, 0.0, 0.0F, 1.0F);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
|
||||
entity.prevRenderYawOffset = entity.renderYawOffset = f2;
|
||||
entity.prevRotationYaw = entity.rotationYaw = f3;
|
||||
entity.rotationPitch = f4;
|
||||
entity.prevRotationYawHead = entity.rotationYawHead = f7;
|
||||
GL11.glPopMatrix();
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
@@ -488,7 +498,6 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -498,15 +507,15 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
fontRendererObj.drawString(animation.name, x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
fontRendererObj.drawString("Frames: " + animation.frames.size(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("animation.frames") + ": " + animation.frames.size(), x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Speed: " + animation.speed, x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("stats.speed") + ": " + animation.speed, x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
String loopStr = animation.loop == 0 ? "None" : animation.loop == 1 ? "Loop" : "Mirror";
|
||||
fontRendererObj.drawString("Loop: " + loopStr, x, y, 0xB5B5B5, false);
|
||||
String loopStr = animation.loop == 0 ? StatCollector.translateToLocal("gui.none") : animation.loop == 1 ? StatCollector.translateToLocal("animation.loop") : StatCollector.translateToLocal("animation.mirror");
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("animation.loop") + ": " + loopStr, x, y, 0xB5B5B5, false);
|
||||
if (currentIsBuiltIn) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("(Built-in)", x, y, 0x55FF55, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.builtin.tag"), x, y, 0x55FF55, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.client.CustomNpcResourceListener;
|
||||
import noppes.npcs.client.gui.SubGuiEffectGeneral;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
@@ -180,7 +179,7 @@ public class GuiEffectDirectory extends GuiDirectoryCategorized {
|
||||
if (effect == null || effect.id == -1) return;
|
||||
|
||||
String drawString = effect.getMenuName();
|
||||
fontRendererObj.drawString(drawString, x, y, CustomNpcResourceListener.DefaultTextColor, true);
|
||||
fontRendererObj.drawString(drawString, x, y, 0xFFFFFF, true);
|
||||
|
||||
y += 14;
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.name") + ": " + effect.name, x, y, 0xFFFFFF, false);
|
||||
|
||||
@@ -17,7 +17,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.client.CustomNpcResourceListener;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import noppes.npcs.client.gui.item.SubGuiLinkedItem;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
@@ -215,7 +214,7 @@ public class GuiLinkedItemDirectory extends GuiDirectoryCategorized {
|
||||
protected void drawItemDetails(int x, int y, int w) {
|
||||
if (linkedItem == null || linkedItem.id < 0) return;
|
||||
|
||||
fontRendererObj.drawString(linkedItem.name, x, y, CustomNpcResourceListener.DefaultTextColor, true);
|
||||
fontRendererObj.drawString(linkedItem.name, x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
|
||||
int labelColor = 0xffae0d;
|
||||
|
||||
@@ -19,6 +19,7 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
public static final ResourceLocation resource = new ResourceLocation("customnpcs", "textures/gui/misc.png");
|
||||
public List<String> list;
|
||||
public final HashMap<String, Integer> colors = new HashMap<>();
|
||||
public final HashSet<String> nonInteractive = new HashSet<>();
|
||||
|
||||
public int id;
|
||||
public int guiLeft = 0;
|
||||
@@ -217,21 +218,25 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
} else
|
||||
text = displayString;
|
||||
|
||||
// Entries with a custom color are non-interactive (headers/separators)
|
||||
// Non-interactive entries (headers/separators) — colored, no hover/selection
|
||||
Integer customColor = colors.get(rawEntry);
|
||||
if (customColor != null) {
|
||||
if (nonInteractive.contains(rawEntry)) {
|
||||
if (!text.isEmpty())
|
||||
fontRendererObj.drawString(text, j, k, customColor);
|
||||
fontRendererObj.drawString(text, j, k, customColor != null ? customColor : 0xffffff);
|
||||
} else if ((multipleSelection && selectedList.contains(text)) || (!multipleSelection && selected == i)) {
|
||||
drawVerticalLine(j - 2, k - 4, k + 10, 0xffffffff);
|
||||
drawVerticalLine(j + xSize - 18 + xOffset, k - 4, k + 10, 0xffffffff);
|
||||
drawHorizontalLine(j - 2, j + xSize - 18 + xOffset, k - 3, 0xffffffff);
|
||||
drawHorizontalLine(j - 2, j + xSize - 18 + xOffset, k + 10, 0xffffffff);
|
||||
fontRendererObj.drawString(text, j, k, 0xffffff);
|
||||
int selColor = customColor != null ? customColor : 0xffffff;
|
||||
fontRendererObj.drawString(text, j, k, selColor);
|
||||
} else if (i == hover) {
|
||||
fontRendererObj.drawString(text, j, k, 0x00ff00);
|
||||
} else
|
||||
fontRendererObj.drawString(text, j, k, 0xffffff);
|
||||
int hoverColor = customColor != null ? customColor : 0x00ff00;
|
||||
fontRendererObj.drawString(text, j, k, hoverColor);
|
||||
} else {
|
||||
int defaultColor = customColor != null ? customColor : 0xffffff;
|
||||
fontRendererObj.drawString(text, j, k, defaultColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +257,8 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip non-interactive entries (colored headers/separators)
|
||||
if (colors.containsKey(list.get(j1))) {
|
||||
// Skip non-interactive entries (headers/separators)
|
||||
if (nonInteractive.contains(list.get(j1))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
// ========== New Item Category ==========
|
||||
protected int pendingNewItemCatId = -1;
|
||||
|
||||
// ========== Pending Move Destination ==========
|
||||
private int pendingMoveDestCatId = -1;
|
||||
private String pendingMoveDestName = "";
|
||||
|
||||
// ========== Category Data Loaded ==========
|
||||
private boolean itemDataLoaded = false;
|
||||
|
||||
@@ -184,7 +188,7 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
x += topBtnW + 2;
|
||||
|
||||
// MOVE
|
||||
String moveLabel = movePhase > 0 ? "Moving" : "Move";
|
||||
String moveLabel = movePhase > 0 ? "gui.moving" : "gui.move";
|
||||
GuiNpcButton moveBtn = new GuiNpcButton(54, x, topBtnY, topBtnW, btnH, moveLabel);
|
||||
moveBtn.enabled = selectedCatId >= 0 && !leftCollapsed && hasCategories();
|
||||
addButton(moveBtn);
|
||||
@@ -192,8 +196,9 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
// Confirm (only during move phase 1)
|
||||
if (movePhase == 1) {
|
||||
GuiNpcButton confirmBtn = new GuiNpcButton(55, x, topBtnY, topBtnW, btnH, "Confirm");
|
||||
GuiNpcButton confirmBtn = new GuiNpcButton(55, x, topBtnY, topBtnW, btnH, "gui.confirm");
|
||||
confirmBtn.enabled = !moveSelection.isEmpty();
|
||||
confirmBtn.setTextColor(0x55FFFF);
|
||||
addButton(confirmBtn);
|
||||
x += topBtnW + 2;
|
||||
}
|
||||
@@ -230,9 +235,18 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
catScroll.setSelected(prevCatName);
|
||||
catScroll.scrollY = Math.max(0, Math.min(savedCatScrollY, catScroll.maxScrollY));
|
||||
|
||||
// Phase 2: ensure scroll is clickable for destination selection
|
||||
// Phase 1: categories locked (not clickable)
|
||||
if (movePhase == 1) {
|
||||
catScroll.setSelectable(false);
|
||||
}
|
||||
// Phase 2: color nav items orange (selectable) or red (current/source category)
|
||||
if (movePhase == 2) {
|
||||
catScroll.setSelectable(true);
|
||||
for (String name : navNames) {
|
||||
catScroll.colors.put(name, name.equals(prevCatName) ? 0xFF5555 : 0xFFAA00);
|
||||
}
|
||||
} else if (movePhase == 0) {
|
||||
catScroll.setSelectable(true);
|
||||
}
|
||||
|
||||
addScroll(catScroll);
|
||||
@@ -391,19 +405,19 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
// Draw ID (skip if -1, e.g. abilities use names not IDs)
|
||||
if (hasSelectedItem() && getSelectedItemId() >= 0) {
|
||||
String idStr = "ID: " + getSelectedItemId();
|
||||
int idY = contentY + contentH - btnH - 14;
|
||||
String idStr = StatCollector.translateToLocal("gui.id") + ": " + getSelectedItemId();
|
||||
int idY = contentY + contentH - btnH * 2 - gap - 12;
|
||||
fontRendererObj.drawString(idStr, previewX + 4, idY, 0xFFFFFF, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Move phase overlay text
|
||||
if (movePhase == 1) {
|
||||
String text = "Select Items to Move (max " + MAX_MOVE_ITEMS + ")";
|
||||
String text = String.format(StatCollector.translateToLocal("gui.move.selectItems"), MAX_MOVE_ITEMS);
|
||||
int textW = fontRendererObj.getStringWidth(text);
|
||||
fontRendererObj.drawStringWithShadow(text, width / 2 - textW / 2, height - pad - 10, 0x55FF55);
|
||||
} else if (movePhase == 2) {
|
||||
String text = "Select Destination Category";
|
||||
String text = StatCollector.translateToLocal("gui.move.selectCategory");
|
||||
int textW = fontRendererObj.getStringWidth(text);
|
||||
fontRendererObj.drawStringWithShadow(text, width / 2 - textW / 2, height - pad - 10, 0xFF5555);
|
||||
}
|
||||
@@ -592,15 +606,20 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) {
|
||||
// Category scroll
|
||||
if (guiCustomScroll.id == 2) {
|
||||
// Block category clicks during move phase 1 (selecting items)
|
||||
if (movePhase == 1) return;
|
||||
|
||||
String selected = catScroll.getSelected();
|
||||
if (selected == null) return;
|
||||
|
||||
// Move phase 2: destination selected
|
||||
// Move phase 2: destination selected — show confirmation
|
||||
if (movePhase == 2) {
|
||||
if (!selected.equals(prevCatName)) {
|
||||
Integer destCatId = catData.get(selected);
|
||||
if (destCatId != null) {
|
||||
executeMoveItems(destCatId);
|
||||
pendingMoveDestCatId = destCatId;
|
||||
pendingMoveDestName = selected;
|
||||
setSubGui(new SubGuiCategoryMoveConfirm(moveSelection.size(), selected));
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -761,6 +780,16 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subgui instanceof SubGuiCategoryMoveConfirm) {
|
||||
SubGuiCategoryMoveConfirm confirm = (SubGuiCategoryMoveConfirm) subgui;
|
||||
if (confirm.confirmed && !moveSelection.isEmpty() && pendingMoveDestCatId >= 0) {
|
||||
executeMoveItems(pendingMoveDestCatId);
|
||||
} else {
|
||||
// Cancelled — stay in phase 2
|
||||
}
|
||||
pendingMoveDestCatId = -1;
|
||||
pendingMoveDestName = "";
|
||||
}
|
||||
onSubGuiClosed(subgui);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
@@ -166,8 +167,13 @@ public class GuiNpcButton extends GuiButton {
|
||||
}
|
||||
}
|
||||
}
|
||||
// First, draw the button normally using the superclass method.
|
||||
super.drawButton(mc, mouseX, mouseY);
|
||||
// Wide buttons (>396px) break the vanilla 200px button texture.
|
||||
// Draw them with a three-patch approach instead.
|
||||
if (this.width > 396) {
|
||||
drawWideButton(mc, mouseX, mouseY);
|
||||
} else {
|
||||
super.drawButton(mc, mouseX, mouseY);
|
||||
}
|
||||
// Restore original display string
|
||||
this.displayString = original;
|
||||
// Then, if an icon texture is set, draw it.
|
||||
@@ -175,17 +181,58 @@ public class GuiNpcButton extends GuiButton {
|
||||
mc.getTextureManager().bindTexture(iconTexture);
|
||||
GL11.glPushMatrix();
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
// Calculate the icon position so that it's centered in the button.
|
||||
// (Assumes the button's (xPosition,yPosition) is its top left.)
|
||||
int iconX = this.xPosition + (this.width - iconWidth) / 2;
|
||||
int iconY = this.yPosition + (this.height - iconHeight) / 2;
|
||||
// Draw the texture; we assume texture coordinates start at (0,0) with the desired size.
|
||||
this.drawTexturedModalRect(iconX, iconY, iconPosX, iconPosY, iconWidth, iconHeight);
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a button wider than the vanilla 200px texture allows.
|
||||
* Uses three-patch rendering: left cap, tiled center, right cap.
|
||||
*/
|
||||
private void drawWideButton(Minecraft mc, int mouseX, int mouseY) {
|
||||
FontRenderer fontrenderer = mc.fontRenderer;
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition
|
||||
&& mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height;
|
||||
int k = this.getHoverState(this.field_146123_n);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
int texY = 46 + k * 20;
|
||||
int cap = 100;
|
||||
|
||||
// Left cap (first 100px of texture)
|
||||
this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, texY, cap, this.height);
|
||||
// Right cap (last 100px of texture)
|
||||
this.drawTexturedModalRect(this.xPosition + this.width - cap, this.yPosition, 200 - cap, texY, cap, this.height);
|
||||
// Tile the center column to fill the gap
|
||||
int gapStart = this.xPosition + cap;
|
||||
int gapEnd = this.xPosition + this.width - cap;
|
||||
for (int x = gapStart; x < gapEnd; x += 2) {
|
||||
int drawW = Math.min(2, gapEnd - x);
|
||||
this.drawTexturedModalRect(x, this.yPosition, 99, texY, drawW, this.height);
|
||||
}
|
||||
|
||||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
|
||||
int l = 14737632;
|
||||
if (packedFGColour != 0) {
|
||||
l = packedFGColour;
|
||||
} else if (!this.enabled) {
|
||||
l = 10526880;
|
||||
} else if (this.field_146123_n) {
|
||||
l = 16777120;
|
||||
}
|
||||
this.drawCenteredString(fontrenderer, this.displayString,
|
||||
this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, l);
|
||||
}
|
||||
|
||||
public void drawHover(int i, int j, boolean hasSubGui) {
|
||||
if (hasSubGui || !visible || hoverableText.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package noppes.npcs.client.gui.util;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
public class SubGuiCategoryMoveConfirm extends SubGuiInterface {
|
||||
public boolean confirmed = false;
|
||||
|
||||
private final int count;
|
||||
public final String destCategoryName;
|
||||
|
||||
public SubGuiCategoryMoveConfirm(int count, String destCategoryName) {
|
||||
this.count = count;
|
||||
this.destCategoryName = destCategoryName;
|
||||
xSize = 220;
|
||||
ySize = 90;
|
||||
closeOnEsc = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
String line1 = String.format(StatCollector.translateToLocal("gui.move.confirmLine"), count);
|
||||
addLabel(new GuiNpcLabel(0, line1, guiLeft + 10, guiTop + 10, 0xFFFFFF));
|
||||
|
||||
String dest = StatCollector.translateToLocal("gui.category") + ": \"" + destCategoryName + "\"";
|
||||
addLabel(new GuiNpcLabel(1, " " + dest, guiLeft + 10, guiTop + 25, 0xFFFFFF));
|
||||
|
||||
addButton(new GuiNpcButton(0, guiLeft + 10, guiTop + 55, 95, 20, "gui.yes"));
|
||||
addButton(new GuiNpcButton(1, guiLeft + 115, guiTop + 55, 95, 20, "gui.cancel"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
if (guibutton.id == 0) {
|
||||
confirmed = true;
|
||||
close();
|
||||
}
|
||||
if (guibutton.id == 1) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,8 @@ public class EntityCustomNpc extends EntityNPCFlying {
|
||||
worldObj.MAX_ENTITY_RADIUS = newWidth / 2;
|
||||
}
|
||||
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,9 @@ public class EntityNPCGolem extends EntityNPCInterface {
|
||||
newWidth = 1.4f;
|
||||
newHeight = 2.5f;
|
||||
}
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1285,8 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
World.MAX_ENTITY_RADIUS = newWidth / 2;
|
||||
}
|
||||
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,9 @@ public class EntityNpcDragon extends EntityNPCInterface {
|
||||
// }
|
||||
@Override
|
||||
public void updateHitbox() {
|
||||
setSize(1.8f, 1.4f);
|
||||
this.width = 1.8f;
|
||||
this.height = 1.4f;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ public class EntityNpcSlime extends EntityNPCInterface {
|
||||
|
||||
@Override
|
||||
public void updateHitbox() {
|
||||
setSize(0.8f, 0.8f);
|
||||
this.width = 0.8f;
|
||||
this.height = 0.8f;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,9 @@ public class EntityNPCEnderman extends EntityNpcEnderchibi {
|
||||
newHeight = (newHeight / 5f) * display.modelSize;
|
||||
newWidth = Math.max(newWidth, 0.00001f);
|
||||
newHeight = Math.max(newHeight, 0.00001f);
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user