Created
September 11, 2024 11:05
-
-
Save Densamisten/5119199a2f068e5a27067d1fd20bc29a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package exonihility.client.gui; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import com.google.gson.JsonElement; | |
import com.google.gson.JsonSyntaxException; | |
import exonihility.client.util.toasts.impl.builder.BasicToastBuilder; | |
import net.minecraft.client.MinecraftClient; | |
import net.minecraft.client.gui.DrawContext; | |
import net.minecraft.client.gui.screen.Screen; | |
import net.minecraft.client.gui.tooltip.Tooltip; | |
import net.minecraft.client.gui.widget.ButtonWidget; | |
import net.minecraft.client.gui.widget.EditBoxWidget; | |
import net.minecraft.client.toast.SystemToast; | |
import net.minecraft.text.Text; | |
import org.lwjgl.glfw.GLFW; | |
import org.unix4j.Unix4j; | |
import java.io.File; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.util.Stack; | |
public class AllyshipEditor extends Screen { | |
private EditBoxWidget editBoxWidget; | |
private String filePath; | |
private static final int MAX_UNDO_STACK_SIZE = 100; | |
private Stack<String> undoStack = new Stack<>(); // Stack to hold previous text states | |
private Stack<String> redoStack = new Stack<>(); // Stack to hold redo states | |
private Gson gson = new GsonBuilder().setPrettyPrinting().create(); // Gson with pretty-print enabled | |
public AllyshipEditor(String filePath) { | |
super(Text.literal("In-Game Text Editor")); | |
this.filePath = filePath; | |
} | |
@Override | |
public void init() { | |
super.init(); | |
// Create a larger EditBoxWidget for text input | |
int editorWidth = this.width - 40; | |
int editorHeight = this.height - 100; | |
editBoxWidget = new EditBoxWidget(this.textRenderer, 20, 20, editorWidth, editorHeight, Text.literal("Type here..."), Text.literal("...")); | |
editBoxWidget.setFocused(true); | |
// Load file contents into the editor | |
String fileContents = readFileWithUnix4j(filePath); | |
editBoxWidget.setText(fileContents != null ? fileContents : "Failed to load file"); | |
this.addSelectableChild(editBoxWidget); | |
// Notify all plugins that the editor is being opened | |
AllyshipEditorPluginRegistry.getPlugins().forEach(plugin -> plugin.onEditorOpen(this)); | |
// Notify all plugins to add custom UI elements | |
AllyshipEditorPluginRegistry.getPlugins().forEach(plugin -> plugin.addCustomUI(this)); | |
// Push initial state to undo stack | |
pushUndoState(editBoxWidget.getText()); | |
// Save button with JSON validation check | |
ButtonWidget saveButton = ButtonWidget.builder(Text.literal("Save Changes"), button -> { | |
String modifiedText = editBoxWidget.getText(); | |
for (AllyshipEditorPlugin plugin : AllyshipEditorPluginRegistry.getPlugins()) { | |
modifiedText = plugin.onSave(modifiedText); | |
} | |
saveFile(modifiedText); // Save file when button is clicked | |
}) | |
.dimensions(20, this.height - 40, 100, 20) | |
.tooltip(Tooltip.of(Text.literal("Saves changes to file"))) | |
.build(); | |
addDrawableChild(saveButton); | |
} | |
// Detect Ctrl+Y for redo | |
private boolean isRedoKeyPressed() { | |
boolean ctrlPressed = GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_LEFT_CONTROL) == GLFW.GLFW_PRESS || | |
GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_RIGHT_CONTROL) == GLFW.GLFW_PRESS; | |
boolean yPressed = GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_Y) == GLFW.GLFW_PRESS; | |
return ctrlPressed && yPressed; | |
} | |
// Redo functionality | |
private void redoText() { | |
if (!redoStack.isEmpty()) { | |
String redoState = redoStack.pop(); | |
undoStack.push(editBoxWidget.getText()); | |
editBoxWidget.setText(redoState); | |
} | |
} | |
// Undo functionality | |
private void undoText() { | |
if (!undoStack.isEmpty()) { | |
redoStack.push(editBoxWidget.getText()); | |
undoStack.pop(); | |
if (!undoStack.isEmpty()) { | |
String previousState = undoStack.peek(); | |
editBoxWidget.setText(previousState); | |
} else { | |
editBoxWidget.setText(""); | |
} | |
} | |
} | |
@Override | |
public void render(DrawContext context, int mouseX, int mouseY, float delta) { | |
this.renderBackground(context, mouseX, mouseY, delta); | |
super.render(context, mouseX, mouseY, delta); | |
if (editBoxWidget != null) { | |
editBoxWidget.render(context, mouseX, mouseY, delta); | |
} | |
// Call the onRender method for all registered plugins | |
AllyshipEditorPluginRegistry.getPlugins().forEach(plugin -> plugin.onRender(this, context)); | |
} | |
@Override | |
public void tick() { | |
super.tick(); | |
// Handle undo/redo actions | |
if (isUndoKeyPressed()) { | |
undoText(); | |
} | |
if (isRedoKeyPressed()) { | |
redoText(); | |
} | |
// Beautify JSON content only if it's valid | |
try { | |
String currentText = editBoxWidget.getText(); | |
if (isValidJson(currentText)) { | |
String beautifiedJson = gson.toJson(gson.fromJson(currentText, Object.class)); | |
editBoxWidget.setText(beautifiedJson); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
private boolean isValidJson(String json) { | |
try { | |
gson.fromJson(json, JsonElement.class); // Parse JSON | |
return true; | |
} catch (JsonSyntaxException e) { | |
return false; | |
} | |
} | |
// Show a toast notification when invalid JSON is detected | |
private void showInvalidJsonToast() { | |
new BasicToastBuilder() | |
.title("Malformed JSON Error") | |
.description("Invalid JSON!") // Show a fixed error message | |
.build() | |
.show(); | |
} | |
public String getEditBoxText() { | |
return editBoxWidget.getText(); | |
} | |
@Override | |
public boolean shouldPause() { | |
return false; | |
} | |
// Function to read the file contents using Unix4J cat | |
private String readFileWithUnix4j(String path) { | |
try { | |
File file = new File(path); | |
return Unix4j.cat(file).toStringResult(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
// Save the file only if JSON is valid | |
private void saveFile(String content) { | |
if (isValidJson(content)) { | |
try (FileWriter writer = new FileWriter(filePath)) { | |
writer.write(content); // Save the content | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} else { | |
showInvalidJsonToast(); // Show toast when JSON is malformed | |
} | |
} | |
private boolean undoKeyHeld = false; | |
// Detect Ctrl+Z for undo | |
private boolean isUndoKeyPressed() { | |
boolean ctrlPressed = GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_LEFT_CONTROL) == GLFW.GLFW_PRESS || | |
GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_RIGHT_CONTROL) == GLFW.GLFW_PRESS; | |
boolean zPressed = GLFW.glfwGetKey(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_Z) == GLFW.GLFW_PRESS; | |
if (ctrlPressed && zPressed && !undoKeyHeld) { | |
undoKeyHeld = true; | |
return true; | |
} | |
if (!ctrlPressed || !zPressed) { | |
undoKeyHeld = false; | |
} | |
return false; | |
} | |
private void pushUndoState(String newState) { | |
if (undoStack.size() >= MAX_UNDO_STACK_SIZE) { | |
undoStack.remove(0); // Remove the oldest state to prevent overflow | |
} | |
undoStack.push(newState); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment