IMPORTED KeyPreset FROM EASINGS BRANCH

This commit is contained in:
bigguy345 committed 2025-12-19 12:14:36 +02:00
1 parent ebd005c2df
commit cd00fcf013
3 files changed
+746

No files matched your search

@@ -0,0 +1,419 @@
package noppes.npcs.client.gui.util.key;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.util.ResourceLocation;
import noppes.npcs.client.gui.util.GuiUtil;
import noppes.npcs.client.key.KeyPreset;
import noppes.npcs.client.key.KeyPresetManager;
import noppes.npcs.client.util.Color;
import noppes.npcs.util.ValueUtil;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import java.util.LinkedList;
import java.util.List;
public class OverlayKeyPresetViewer {
public static final ResourceLocation TEXTURE = new ResourceLocation("customnpcs:textures/gui/keypreset_highres.png");
public int startX, startY, endX, endY, width, height;
public int mouseX, mouseY;
public boolean showOverlay;
public int elementSpacing = 5, yStartSpacing = 5;
public float scale = 0.75f;
public Scrollable scroll = new Scrollable();
public KeyPresetManager manager;
public OverlayButton viewButton = new OverlayButton();
public LinkedList<PresetElement> list = new LinkedList<>();
private final FontRenderer font = Minecraft.getMinecraft().fontRenderer;
public OverlayKeyPresetViewer(KeyPresetManager manager) {
this.manager = manager;
manager.keys.forEach((key) -> {
PresetElement element = new PresetElement(key);
list.add(element);
});
}
public void initGui(int startX, int startY, int endX, int endY) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
this.width = endX - startX;
this.height = endY - startY;
scroll.init();
}
public void draw(int mouseX, int mouseY, int wheel) {
this.mouseX = mouseX;
this.mouseY = mouseY;
boolean aboveButton = viewButton.isMouseAbove(mouseX, mouseY);
boolean aboveOverlay = isMouseAbove(mouseX, mouseY);
if (aboveButton)
showOverlay = true;
if (showOverlay) {
drawOverlay(wheel);
if (!aboveOverlay && !aboveButton)
showOverlay = false;
}
viewButton.drawButton();
}
public void drawOverlay(int wheel) {
scroll.update(wheel);
GL11.glEnable(GL11.GL_SCISSOR_TEST);
GuiUtil.drawGradientRect(startX, startY, endX, endY, 0x88000000, 0x88303030);
if (scroll.maxScroll > 0)
scroll.drawBar();
GuiUtil.setScissorClip(startX, startY, scroll.maxScroll > 0 ? width - scroll.barWidth : width, height);
GL11.glPushMatrix();
GL11.glTranslatef((startX + 2), startY + yStartSpacing - scroll.scrollY, 0);
for (int i = 0, height = 0; i < list.size(); i++) {
PresetElement element = list.get(i);
GL11.glPushMatrix();
GL11.glScalef(scale, scale, 1);
GL11.glTranslatef(0, Math.round(height / scale), 0);
element.drawDescription();
GL11.glPopMatrix();
element.drawBox(height);
height += element.getHeight();
}
GL11.glPopMatrix();
GL11.glDisable(GL11.GL_SCISSOR_TEST);
}
public void keyTyped(char c, int i) {
if (!showOverlay)
return;
list.forEach((element) -> {
if (element.isEditing)
element.keyTyped(i);
});
}
public void mouseClicked(int mouseX, int mouseY, int button) {
if (!showOverlay)
return;
list.forEach((element) -> {
if (!element.isMouseAboveBox(mouseX, mouseY)) {
if (element.isEditing)
element.cancelEdit();
} else
element.boxClicked(button);
if (element.isMouseAboveReset(mouseX, mouseY) && !element.key.isDefault()) {
element.key.defaultState.writeTo(element.key.currentState);
manager.save();
}
});
}
public boolean isMouseAbove(int mouseX, int mouseY) {
if (scroll.isMouseDragging)
return true;
return mouseX >= startX && mouseX < endX && mouseY >= startY && mouseY < endY;
}
public int getWidth() {
return (int) (width / scale);
}
public class Scrollable {
private float scrollY, targetScrollY, maxScroll;
private int totalHeight, scrollbarHeight, barWidth = 2;
private float heightFactor, scrollFactor;
private boolean isMouseDragging;
private int startDragY;
public Scrollable() {
}
public void init() {
totalHeight = 0;
for (PresetElement element : list)
totalHeight += element.getHeight();
totalHeight -= yStartSpacing;
scroll.maxScroll = Math.max(0, totalHeight - height);
heightFactor = height / totalHeight;
scrollbarHeight = Math.max((int) (height * heightFactor), 20);
scrollFactor = (height - yStartSpacing - scrollbarHeight) / maxScroll;
}
public void update(int wheel) {
if (wheel != 0 && isMouseAbove(mouseX, mouseY))
targetScrollY = ValueUtil.clamp(targetScrollY - wheel / 15, 0, maxScroll);
if (Mouse.isButtonDown(0)) {
if (!isMouseDragging && isMouseAboveBar(mouseX, mouseY)) {
isMouseDragging = true;
startDragY = (int) (mouseY - scrollY * scrollFactor);
}
} else
isMouseDragging = false;
if (isMouseDragging)
scrollY = targetScrollY = ValueUtil.clamp((mouseY - startDragY) / scrollFactor, 0, maxScroll);
if (scrollY != targetScrollY) {
scrollY = ValueUtil.lerp(scrollY, targetScrollY, 0.1f);
if (Math.abs(scrollY - targetScrollY) < 0.001) // Snap to exact target value
scrollY = targetScrollY;
}
scrollY = ValueUtil.clamp(scrollY, 0, maxScroll);
}
public void drawBar() {
GL11.glPushMatrix();
GL11.glTranslatef(endX - barWidth - 2, startY + yStartSpacing + scrollY * scrollFactor, 0);
GuiUtil.drawRectD(0, 0, barWidth, scrollbarHeight, (isMouseAboveBar(mouseX, mouseY) || isMouseDragging) ? 0xffbababa : 0xff767676);
GL11.glPopMatrix();
}
public boolean isMouseAboveBar(int mouseX, int mouseY) {
int barX = endX - barWidth - 2;
int barY = (int) (startY + yStartSpacing + scrollY * scrollFactor);
return mouseX >= barX && mouseX < barX + barWidth && mouseY >= barY && mouseY < barY + scrollbarHeight;
}
}
public class PresetElement {
public KeyPreset key;
public boolean isEditing;
public float boxScreenX, boxScreenY;
public KeyPreset.KeyState newState = new KeyPreset.KeyState();
public PresetElement(KeyPreset key) {
this.key = key;
}
public void drawDescription() {
String name = String.format("> %s", key.name);
font.drawString(name, 0, 0, 0xffffff);
if (!key.shouldConflict)
font.drawString("(Conflict-free)", font.getStringWidth(name) + 5, 0, 0xface40);
String description = String.format("- %s", key.description);
font.drawSplitString(description, 9, font.FONT_HEIGHT, getMaxStringWidth() - 9, 0x888888);
}
public void drawBox(int offsetY) {
////////////////////////////////////////////
////////////////////////////////////////////
//Box texture
Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
GL11.glPushMatrix();
GL11.glColor4f(1, 1, 1, 1);
float boxScaleX = 1.75f;
float boxWidth = 32 * boxScaleX;
boxScreenX = getMaxStringWidth() * scale + 8; //remove scaling from maxStringWidth
GL11.glScalef(boxScaleX, 1, 0);
if (isEditing)
new Color(0x4772b3, 1).glColor();
else if (isMouseAboveBox(mouseX, mouseY))
new Color(0x656565, 1).glColor();
else
new Color(0x545454, 1).glColor();
GuiUtil.drawTexturedModalRect(boxScreenX / boxScaleX, boxScreenY = offsetY - 5, 32, 20, 0, 492);
GL11.glPopMatrix();
//Reset box
boolean isDefault = key.isDefault();
float resetWidth = 10;
float resetScreenX = boxScreenX + boxWidth + 2;
if (isMouseAboveReset(mouseX, mouseY) && !isDefault)
new Color(0x656565, 1).glColor();
else
new Color(0x545454, 1).glColor();
GuiUtil.drawTexturedModalRect(resetScreenX, boxScreenY, 10, 20, 33, 492);
////////////////////////////////////////////
////////////////////////////////////////////
//Key name
String name = getBoxKeyName();
float nameWidth = font.getStringWidth(name);
float nameScale = scale;
float nameBoxRatio = nameWidth * scale / boxWidth;
GL11.glPushMatrix();
if (nameBoxRatio > 0.9) {
nameScale /= nameWidth / boxWidth / 1.2f;
GL11.glTranslatef(0, nameBoxRatio * 0.5f, 0);
}
float nameX = boxScreenX + boxWidth / 2 - (nameWidth / 2 * nameScale);
float nameY = offsetY + 11.5f - (font.FONT_HEIGHT / 2);
GL11.glScalef(nameScale, nameScale, 1);
GL11.glTranslatef(nameX / nameScale, nameY / nameScale, 1);
font.drawStringWithShadow(name, 0, 0, conflicts() ? 0xff5555 : 0xffffffff);
GL11.glPopMatrix();
//Reset letter
char letter = 'X';
float letterX = resetScreenX + (resetWidth / 2) - (font.getCharWidth(letter) / 2 * scale) + 0.25f;
GL11.glPushMatrix();
GL11.glScalef(scale, scale, 1);
GL11.glTranslatef(letterX / scale, nameY / scale, 1);
font.drawStringWithShadow(String.valueOf(letter), 0, 0, isDefault ? 0xff8a8a8a : 0xffffffff);
GL11.glPopMatrix();
////////////////////////////////////////////
////////////////////////////////////////////
}
public void boxClicked(int button) {
if (isEditing)
setKey(-100 + button);
else if (button == 0)
isEditing = true;
}
public void keyTyped(int typedKey) {
if (typedKey == 1) {
setKey(0);
return;
}
newState.setState(newState.keyCode, KeyPreset.isCtrlKeyDown(), KeyPreset.isAltKeyDown(), KeyPreset.isShiftKeyDown());
if (KeyPreset.isNotCtrlAltShift(typedKey))
setKey(typedKey);
}
public void setKey(int keyCode) {
if (keyCode == 0)
newState.clear();
newState.keyCode = keyCode;
newState.writeTo(key.currentState);
cancelEdit();
manager.save();
}
public void cancelEdit() {
newState.clear();
isEditing = false;
}
public boolean conflicts() {
return list.stream().anyMatch(element -> key.shouldConflict && element.key.shouldConflict && element.key != this.key && element.key.equals(this.key));
}
public String getBoxKeyName() {
if (isEditing) {
String modifiers = "";
if (KeyPreset.isCtrlKeyDown())
modifiers += "CTRL ";
if (KeyPreset.isAltKeyDown())
modifiers += "ALT ";
if (KeyPreset.isShiftKeyDown())
modifiers += "SHIFT ";
return !modifiers.isEmpty() ? modifiers : "Press a key";
}
return key.currentState.getName();
}
public boolean isMouseAboveBox(int mouseX, int mouseY) {
mouseX -= startX + 2;
mouseY -= startY + 5 - scroll.scrollY;
float boxScaleX = 1.75f;
float screenY = boxScreenY + 10;
return mouseX >= boxScreenX && mouseX < boxScreenX + 32 * boxScaleX && mouseY >= screenY && mouseY < screenY + 10;
}
public boolean isMouseAboveReset(int mouseX, int mouseY) {
mouseX -= startX + 2;
mouseY -= startY + 5 - scroll.scrollY;
float boxScaleX = 1.75f;
float resetWidth = 10, boxWidth = 32 * boxScaleX;
float screenX = boxScreenX + boxWidth + 2;
float screenY = boxScreenY + 10;
return mouseX >= screenX && mouseX < screenX + resetWidth && mouseY >= screenY && mouseY < screenY + 10;
}
public int getHeight() {
List<String> wrappedDescription = font.listFormattedStringToWidth(String.format("- %s", key.description), getMaxStringWidth());
int nameHeight = font.FONT_HEIGHT;
int translations = font.FONT_HEIGHT;
int descriptionHeight = wrappedDescription.size() * (font.FONT_HEIGHT);
return Math.round((nameHeight + descriptionHeight + translations) * scale) + elementSpacing;
}
public int getMaxStringWidth() {
return (int) (getWidth() * 2.5f / 4);
}
}
public class OverlayButton {
public int startX, startY, endX, width, height;
public int textureWidth = 252, textureHeight = 109;
public float scale = 0.25f;
public OverlayButton() {
}
public void initGui(int endX, int startY) {
this.endX = endX;
this.startY = startY;
startX = (int) (endX - textureWidth * scale / 2);
}
public void drawButton() {
Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
double screenX = startX / scale, screenY = startY / scale;
int oldMinFilter = GL11.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glPushMatrix();
float color = 0.55f;
GL11.glColor4f(color, color, color, 1);
GL11.glScalef(scale, scale, 1);
GuiUtil.drawTexturedModalRect(screenX, screenY, textureWidth, textureHeight, 0, 0);
GL11.glPopMatrix();
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, oldMinFilter);
}
public boolean isMouseAbove(int mouseX, int mouseY) {
return mouseX >= startX && mouseX < startX + textureWidth * scale / 2 && mouseY >= startY - 4 && mouseY < startY + textureHeight * scale / 2;
}
}
}
@@ -0,0 +1,250 @@
package noppes.npcs.client.key;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.nbt.NBTTagCompound;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import java.util.function.Consumer;
public class KeyPreset {
/**
* @field SINGLE_PRESS => on releasing before 5 ticks press time
* @field PRESS_RELEASE => on pressing and releasing
*/
/** Press types for key events. */
public enum PressType { PRESS, HOLD, RELEASE, SINGLE_PRESS, PRESS_RELEASE }
public KeyState defaultState = new KeyState();
public KeyState currentState = new KeyState();
public String name, description;
public boolean shouldConflict = true;
public Consumer<PressType> task;
public int pressTime;
public boolean isDown;
public KeyPreset(String name) {
this.name = name;
}
public KeyPreset setDefaultState(int keyCode, boolean hasCtrl, boolean hasAlt, boolean hasShift) {
defaultState.setState(keyCode, hasCtrl, hasAlt, hasShift);
currentState.setState(keyCode, hasCtrl, hasAlt, hasShift);
return this;
}
public KeyPreset setDescription(String description) {
this.description = description;
return this;
}
public KeyPreset setTask(Consumer<PressType> task) {
this.task = task;
return this;
}
public KeyPreset shouldConflict(boolean shouldConflict) {
this.shouldConflict = shouldConflict;
return this;
}
public void tick() {
int keyCode = keyCode();
if (keyCode == -1 || keyCode == 0)
return;
boolean isDown = isMouseKey() ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode);
isDown = isDown && (hasCtrl() ? isCtrlKeyDown() : true) && (hasAlt() ? isAltKeyDown() : true) && (hasShift() ? isShiftKeyDown() : true);
setDown(isDown);
}
public void setDown(boolean down) {
if (down && !isDown)
onAction(PressType.PRESS, PressType.PRESS_RELEASE);
if (!down && isDown) {
if (pressTime <= 5)
onAction(PressType.SINGLE_PRESS);
onAction(PressType.RELEASE, PressType.PRESS_RELEASE);
pressTime = 0;
}
if (isDown || down) //to fire in both press & release
onAction(PressType.HOLD);
if (isDown)
pressTime++;
this.isDown = down;
}
public KeyPreset onAction(PressType... pressTypes) {
if (task != null) {
for (PressType pressType : pressTypes)
this.task.accept(pressType);
}
return this;
}
public boolean isDefault() {
return currentState.equals(defaultState);
}
public boolean isMouseKey() {
return keyCode() < -1;
}
public int keyCode() {
return currentState.keyCode;
}
public boolean hasCtrl() {
return currentState.hasCtrl;
}
public boolean hasAlt() {
return currentState.hasAlt;
}
public boolean hasShift() {
return currentState.hasShift;
}
public String getKeyName() {
return currentState.getName();
}
public void clear() {
currentState.clear();
}
//call on the last key added, to load saved presets
public KeyPreset markDone(KeyPresetManager manager) {
manager.load();
return this;
}
public void writeToNbt(NBTTagCompound c) {
c.setTag(name, currentState.writeToNbt());
}
public void readFromNbt(NBTTagCompound compound) {
currentState.readFromNbt(compound.getCompoundTag(name));
}
public boolean equals(Object preset) {
if (preset == this)
return true;
if (preset instanceof KeyPreset) {
KeyPreset key = (KeyPreset) preset;
return key.currentState.equals(currentState);
}
return false;
}
public static class KeyState {
public int keyCode = -1;
public boolean hasCtrl, hasAlt, hasShift;
public void setState(int keyCode, boolean hasCtrl, boolean hasAlt, boolean hasShift) {
this.keyCode = keyCode;
this.hasCtrl = hasCtrl;
this.hasAlt = hasAlt;
this.hasShift = hasShift;
}
public void readFrom(KeyState state) {
keyCode = state.keyCode;
hasCtrl = state.hasCtrl;
hasShift = state.hasShift;
hasAlt = state.hasAlt;
}
public void writeTo(KeyState state) {
state.setState(keyCode, hasCtrl, hasAlt, hasShift);
}
public boolean hasState() {
return keyCode != -1;
}
public void clear() {
this.keyCode = -1;
hasCtrl = hasAlt = hasShift = false;
}
public boolean equals(Object preset) {
if (preset == this)
return true;
if (preset instanceof KeyState) {
KeyState state = (KeyState) preset;
return state.keyCode == keyCode && state.hasCtrl == hasCtrl && state.hasAlt == hasAlt && state.hasShift == hasShift;
}
return false;
}
public NBTTagCompound writeToNbt() {
NBTTagCompound compound = new NBTTagCompound();
compound.setInteger("keyCode", keyCode);
compound.setBoolean("hasCtrl", hasCtrl);
compound.setBoolean("hasShift", hasShift);
compound.setBoolean("hasAlt", hasAlt);
return compound;
}
public void readFromNbt(NBTTagCompound compound) {
this.keyCode = compound.getInteger("keyCode");
this.hasCtrl = compound.getBoolean("hasCtrl");
this.hasShift = compound.getBoolean("hasShift");
this.hasAlt = compound.getBoolean("hasAlt");
}
public String getName() {
int code = keyCode;
String name = "";
if (code == LEFT_MOUSE)
name = "Left Mouse";
else if (code == RIGHT_MOUSE)
name = "Right Mouse";
else if (code == MIDDLE_MOUSE)
name = "Middle Mouse";
else {
name = code == -1 ? "" : GameSettings.getKeyDisplayString(code);
if (name.contains("Button"))
name = name.replace("Button", "Mouse");
}
return (hasCtrl ? "CTRL " : "") + (hasAlt ? "ALT " : "") + (hasShift ? "SHIFT " : "") + name;
}
}
public static final int LEFT_MOUSE = -100, RIGHT_MOUSE = -99, MIDDLE_MOUSE = -98, MOUSE_4 = -97, MOUSE_5 = -96;
public static boolean isCtrlKeyDown() {
return Minecraft.isRunningOnMac ? Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220) : Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157);
}
public static boolean isAltKeyDown() {
return Keyboard.isKeyDown(56) || Keyboard.isKeyDown(184);
}
public static boolean isShiftKeyDown() {
return Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54);
}
public static boolean isNotCtrlAltShift(int key) {
return key != 219 && key != 220 && key != 29 && key != 157 && key != 42 && key != 54 && key != 56 && key != 184;
}
}
@@ -0,0 +1,77 @@
package noppes.npcs.client.key;
import net.minecraft.nbt.NBTTagCompound;
import noppes.npcs.CustomNpcs;
import noppes.npcs.LogWriter;
import noppes.npcs.util.NBTJsonUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class KeyPresetManager {
public List<KeyPreset> keys = new ArrayList<>();
public String fileName;
public KeyPresetManager(String fileName) {
this.fileName = fileName;
}
public KeyPreset add(String name) {
KeyPreset preset = new KeyPreset(name);
keys.add(preset);
return preset;
}
public void tick() {
for (KeyPreset key : keys)
key.tick();
}
public void load() {
try {
File dir = getDir();
File file = new File(dir, fileName + ".json");
if (!file.exists())
return;
NBTTagCompound compound = NBTJsonUtil.LoadFile(file);
for (KeyPreset key : keys)
key.readFromNbt(compound);
} catch (Exception e) {
LogWriter.except(e);
}
}
public void save() {
try {
File dir = getDir();
String filename = fileName + ".json";
File newFile = new File(dir, filename + "_new");
File originalFile = new File(dir, filename);
NBTTagCompound compound = new NBTTagCompound();
for (KeyPreset key : keys)
key.writeToNbt(compound);
NBTJsonUtil.SaveFile(newFile, compound);
if (originalFile.exists())
originalFile.delete();
newFile.renameTo(originalFile);
} catch (Exception e) {
LogWriter.except(e);
}
}
public File getDir() {
File dir = new File(CustomNpcs.Dir, "keypresets");
if (!dir.exists())
dir.mkdir();
return dir;
}
}