mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
Add in-game calculator
This commit is contained in:
parent
081df1c8fe
commit
fd940b59c8
@ -1,5 +1,7 @@
|
||||
package com.hbm.handler;
|
||||
|
||||
import com.hbm.inventory.gui.GUICalculator;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import com.hbm.extprop.HbmPlayerProps;
|
||||
@ -16,6 +18,7 @@ public class HbmKeybinds {
|
||||
|
||||
public static final String category = "hbm.key";
|
||||
|
||||
public static KeyBinding calculatorKey = new KeyBinding(category + ".calculator", Keyboard.KEY_N, category);
|
||||
public static KeyBinding jetpackKey = new KeyBinding(category + ".toggleBack", Keyboard.KEY_C, category);
|
||||
public static KeyBinding hudKey = new KeyBinding(category + ".toggleHUD", Keyboard.KEY_V, category);
|
||||
public static KeyBinding reloadKey = new KeyBinding(category + ".reload", Keyboard.KEY_R, category);
|
||||
@ -25,12 +28,13 @@ public class HbmKeybinds {
|
||||
public static KeyBinding craneLeftKey = new KeyBinding(category + ".craneMoveLeft", Keyboard.KEY_LEFT, category);
|
||||
public static KeyBinding craneRightKey = new KeyBinding(category + ".craneMoveRight", Keyboard.KEY_RIGHT, category);
|
||||
public static KeyBinding craneLoadKey = new KeyBinding(category + ".craneLoad", Keyboard.KEY_RETURN, category);
|
||||
|
||||
|
||||
public static void register() {
|
||||
ClientRegistry.registerKeyBinding(calculatorKey);
|
||||
ClientRegistry.registerKeyBinding(jetpackKey);
|
||||
ClientRegistry.registerKeyBinding(hudKey);
|
||||
ClientRegistry.registerKeyBinding(reloadKey);
|
||||
|
||||
|
||||
ClientRegistry.registerKeyBinding(craneUpKey);
|
||||
ClientRegistry.registerKeyBinding(craneDownKey);
|
||||
ClientRegistry.registerKeyBinding(craneLeftKey);
|
||||
@ -40,6 +44,9 @@ public class HbmKeybinds {
|
||||
|
||||
@SubscribeEvent
|
||||
public void keyEvent(KeyInputEvent event) {
|
||||
if (calculatorKey.getIsKeyPressed()) { // handle the calculator client-side only
|
||||
FMLCommonHandler.instance().showGuiScreen(new GUICalculator());
|
||||
}
|
||||
|
||||
HbmPlayerProps props = HbmPlayerProps.getData(MainRegistry.proxy.me());
|
||||
|
||||
|
||||
237
src/main/java/com/hbm/inventory/gui/GUICalculator.java
Normal file
237
src/main/java/com/hbm/inventory/gui/GUICalculator.java
Normal file
@ -0,0 +1,237 @@
|
||||
package com.hbm.inventory.gui;
|
||||
|
||||
import com.hbm.lib.RefStrings;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
|
||||
public class GUICalculator extends GuiScreen {
|
||||
private static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID, "textures/gui/calculator.png");
|
||||
private int xSize = 220;
|
||||
private int ySize = 50;
|
||||
private GuiTextField inputField;
|
||||
|
||||
private String latestResult = "?";
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
int x = (width - xSize) / 2;
|
||||
int y = (height - ySize) / 2;
|
||||
inputField = new GuiTextField(fontRendererObj, x + 5, y + 5, 210, 13);
|
||||
inputField.setTextColor(-1);
|
||||
inputField.setCanLoseFocus(false);
|
||||
inputField.setFocused(true);
|
||||
inputField.setMaxStringLength(1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char p_73869_1_, int p_73869_2_) {
|
||||
if (!inputField.textboxKeyTyped(p_73869_1_, p_73869_2_))
|
||||
super.keyTyped(p_73869_1_, p_73869_2_);
|
||||
|
||||
if (p_73869_1_ == 13 || p_73869_1_ == 10) { // when pressing enter (CR or LF)
|
||||
try {
|
||||
double result = Double.parseDouble(latestResult);
|
||||
String plainStringRepresentation = (new BigDecimal(result)).toPlainString();
|
||||
GuiScreen.setClipboardString(plainStringRepresentation);
|
||||
inputField.setText(plainStringRepresentation);
|
||||
inputField.setCursorPositionEnd();
|
||||
inputField.setSelectionPos(0);
|
||||
} catch (Exception ignored) {}
|
||||
return;
|
||||
}
|
||||
|
||||
String input = inputField.getText().replaceAll("[^\\d+\\-*/^.()\\sA-Za-z]+", "");
|
||||
|
||||
if (input.isEmpty()) {
|
||||
latestResult = "?";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
latestResult = Double.toString(evaluateExpression(input));
|
||||
} catch (Exception e) { latestResult = e.toString(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
|
||||
GL11.glColor4f(1F, 1F, 1F, 1F);
|
||||
mc.getTextureManager().bindTexture(texture);
|
||||
int x = (width - xSize) / 2;
|
||||
int y = (height - ySize) / 2;
|
||||
|
||||
drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
|
||||
|
||||
inputField.drawTextBox();
|
||||
fontRendererObj.drawString("=" + latestResult, x + 5, y + 30, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mathematically evaluates user-inputted strings<br>
|
||||
* It is recommended to catch all exceptions when using this
|
||||
*/
|
||||
public static double evaluateExpression(String input) {
|
||||
if (input.contains("^")) input = preEvaluatePower(input);
|
||||
|
||||
char[] tokens = input.toCharArray();
|
||||
Stack<Double> values = new Stack<>();
|
||||
Stack<String> operators = new Stack<>();
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i] == ' ') continue;
|
||||
|
||||
if (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.' || (tokens[i] == '-' && (i == 0 || "+-*/^(".contains(String.valueOf(tokens[i - 1]))))) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (tokens[i] == '-') {
|
||||
buffer.append('-'); // for negative numbers
|
||||
i++;
|
||||
}
|
||||
while (i < tokens.length && (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.')) buffer.append(tokens[i++]);
|
||||
values.push(Double.parseDouble(buffer.toString()));
|
||||
i--;
|
||||
} else if (tokens[i] == '(') operators.push(Character.toString(tokens[i]));
|
||||
else if (tokens[i] == ')') {
|
||||
while (!operators.isEmpty() && operators.peek().charAt(0) != '(')
|
||||
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
|
||||
operators.pop();
|
||||
if (!operators.isEmpty() && operators.peek().length() > 1)
|
||||
values.push(evaluateFunction(operators.pop(), values.pop()));
|
||||
} else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/' || tokens[i] == '^') {
|
||||
while (!operators.isEmpty() && hasPrecedence(String.valueOf(tokens[i]), operators.peek()))
|
||||
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
|
||||
operators.push(Character.toString(tokens[i]));
|
||||
} else if (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z') {
|
||||
StringBuilder charBuffer = new StringBuilder();
|
||||
while (i < tokens.length && (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z'))
|
||||
charBuffer.append(tokens[i++]);
|
||||
String string = charBuffer.toString();
|
||||
if (string.equalsIgnoreCase("pi")) values.push(Math.PI);
|
||||
else if (string.equalsIgnoreCase("e")) values.push(Math.E);
|
||||
else operators.push(string.toLowerCase(Locale.ROOT));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// if the expression is correctly formatted, no function is remaining
|
||||
while (!operators.empty()) values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
|
||||
|
||||
return values.pop();
|
||||
}
|
||||
|
||||
private static double evaluateOperator(char operator, double x, double y) {
|
||||
switch (operator) {
|
||||
case '+': return y + x;
|
||||
case '-': return y - x;
|
||||
case '*': return y * x;
|
||||
case '/': return y / x;
|
||||
|
||||
case '^': return Math.pow(y, x); // should not happen here, but oh well
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static double evaluateFunction(String function, double x) {
|
||||
switch (function) {
|
||||
case "sqrt": return Math.sqrt(x);
|
||||
|
||||
case "sin": return Math.sin(x);
|
||||
case "cos": return Math.cos(x);
|
||||
case "tan": return Math.tan(x);
|
||||
case "asin": return Math.asin(x);
|
||||
case "acos": return Math.acos(x);
|
||||
case "atan": return Math.atan(x);
|
||||
|
||||
case "log": return Math.log10(x);
|
||||
case "ln": return Math.log(x);
|
||||
|
||||
case "ceil": return Math.ceil(x);
|
||||
case "floor": return Math.floor(x);
|
||||
case "round": return Math.round(x);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns whether {@code second} has precedence over {@code first} */
|
||||
private static boolean hasPrecedence(String first, String second) {
|
||||
if (second.length() > 1) return false;
|
||||
|
||||
char firstChar = first.charAt(0);
|
||||
char secondChar = second.charAt(0);
|
||||
|
||||
if (secondChar == '(' || secondChar == ')') return false;
|
||||
else return (firstChar != '*' && firstChar != '/' && firstChar != '^') || (secondChar != '+' && secondChar != '-');
|
||||
}
|
||||
|
||||
/** Returns the input with all powers evaluated */
|
||||
private static String preEvaluatePower(String input) {
|
||||
do {
|
||||
int powerOperatorIndex = input.lastIndexOf('^');
|
||||
|
||||
// find base
|
||||
boolean previousTokenIsParentheses = input.charAt(powerOperatorIndex - 1) == ')';
|
||||
int parenthesesDepth = previousTokenIsParentheses ? 1 : 0;
|
||||
int baseExpressionStart = previousTokenIsParentheses ? powerOperatorIndex - 2 : powerOperatorIndex - 1;
|
||||
baseLoop:
|
||||
for (; baseExpressionStart >= 0; baseExpressionStart--) { // search backwards
|
||||
switch (input.charAt(baseExpressionStart)) {
|
||||
case ')':
|
||||
if (previousTokenIsParentheses) parenthesesDepth++;
|
||||
else break baseLoop;
|
||||
break;
|
||||
case '(':
|
||||
if (previousTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
|
||||
else break baseLoop;
|
||||
break;
|
||||
case '+': case '-': case '*': case '/': case '^':
|
||||
if (parenthesesDepth == 0) break baseLoop;
|
||||
}
|
||||
}
|
||||
baseExpressionStart++; // go one token forward again
|
||||
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
|
||||
|
||||
// find exponent
|
||||
boolean nextTokenIsParentheses = input.charAt(powerOperatorIndex + 1) == '(';
|
||||
parenthesesDepth = nextTokenIsParentheses ? 1 : 0;
|
||||
int exponentExpressionEnd = nextTokenIsParentheses ? powerOperatorIndex + 2 : powerOperatorIndex + 1;
|
||||
exponentLoop:
|
||||
for (; exponentExpressionEnd < input.length(); exponentExpressionEnd++) {
|
||||
switch (input.charAt(exponentExpressionEnd)) {
|
||||
case '(':
|
||||
if (nextTokenIsParentheses) parenthesesDepth++;
|
||||
else break exponentLoop;
|
||||
break;
|
||||
case ')':
|
||||
if (nextTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
|
||||
else break exponentLoop;
|
||||
break;
|
||||
case '+': case '-': case '*': case '/': case '^':
|
||||
if (parenthesesDepth == 0) break exponentLoop;
|
||||
}
|
||||
}
|
||||
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
|
||||
|
||||
double base = evaluateExpression(input.substring(baseExpressionStart, powerOperatorIndex));
|
||||
double exponent = evaluateExpression(input.substring(powerOperatorIndex + 1, exponentExpressionEnd));
|
||||
double result = Math.pow(base, exponent);
|
||||
// use big decimal to avoid scientific notation messing with the calculation
|
||||
input = input.substring(0, baseExpressionStart) + (new BigDecimal(result)).toPlainString() + input.substring(exponentExpressionEnd);
|
||||
} while (input.contains("^"));
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
@ -438,6 +438,7 @@ hazard.particleFine=Feinstaub
|
||||
hazard.sand=Augenreizstoffe
|
||||
|
||||
hbm.key=NTM Hotkeys
|
||||
hbm.key.calculator=Taschenrechner
|
||||
hbm.key.craneLoad=Kran laden/entladen
|
||||
hbm.key.craneMoveDown=Kran rückwärts
|
||||
hbm.key.craneMoveLeft=Kran nach links
|
||||
|
||||
@ -575,6 +575,7 @@ hazard.particleFine=Particulates
|
||||
hazard.sand=Eye Irritants
|
||||
|
||||
hbm.key=NTM Hotkeys
|
||||
hbm.key.calculator=Calculator
|
||||
hbm.key.craneLoad=Load/Unload Crane
|
||||
hbm.key.craneMoveDown=Move Crane Backward
|
||||
hbm.key.craneMoveLeft=Move Crane Left
|
||||
|
||||
BIN
src/main/resources/assets/hbm/textures/gui/calculator.png
Normal file
BIN
src/main/resources/assets/hbm/textures/gui/calculator.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 566 B |
Loading…
x
Reference in New Issue
Block a user