Created
September 22, 2024 08:10
-
-
Save Densamisten/46e46cb5888b2f955c5282bf2b998785 to your computer and use it in GitHub Desktop.
works sometimes
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.text.Text; | |
import org.lwjgl.glfw.GLFW; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.Stack; | |
public class AllyshipEditor extends Screen { | |
private EditBoxWidget editBoxWidget; | |
private final String filePath; | |
private static final int MAX_UNDO_STACK_SIZE = 100; | |
private final Stack<String> undoStack = new Stack<>(); // Stack to hold previous text states | |
private final Stack<String> redoStack = new Stack<>(); // Stack to hold redo states | |
private final 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 using the updated method | |
String fileContents = readFileContents(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); | |
} | |
if (isValidJson(modifiedText)) { | |
saveFile(modifiedText); // Save the file when the JSON is valid | |
} else { | |
showInvalidJsonToast(); // Show the toast if JSON is invalid | |
} | |
}) | |
.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()) { | |
// Push the current state to the undo stack before changing text | |
String currentState = editBoxWidget.getText(); | |
if (currentState != null) { | |
pushUndoState(currentState); | |
} | |
// Get the state to redo | |
String redoState = redoStack.pop(); | |
// Set the redo state as the current text | |
editBoxWidget.setText(redoState); | |
} | |
} | |
// Undo functionality | |
private void undoText() { | |
if (!undoStack.isEmpty()) { | |
// Push the current state to the redo stack before changing text | |
String currentState = editBoxWidget.getText(); | |
if (currentState != null) { | |
redoStack.push(currentState); | |
} | |
// Get the last state from the undo stack | |
String previousState = undoStack.pop(); | |
// Set the previous state as the current text | |
editBoxWidget.setText(previousState); | |
} | |
} | |
@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 action | |
if (isUndoKeyPressed()) { | |
undoText(); | |
} | |
// Handle redo action | |
if (isRedoKeyPressed()) { | |
redoText(); | |
} | |
// Beautify JSON content only if it's valid and if the text has actually changed | |
try { | |
String currentText = editBoxWidget.getText(); | |
if (isValidJson(currentText)) { | |
String beautifiedJson = gson.toJson(gson.fromJson(currentText, Object.class)); | |
if (!currentText.equals(beautifiedJson)) { | |
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 after pressing save | |
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; | |
} | |
// Updated function to read the file contents with standard Java | |
private String readFileContents(String path) { | |
try { | |
// Read all bytes from the file and convert them to a string | |
return new String(Files.readAllBytes(Paths.get(path))); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return null; // Return null if an error occurs | |
} | |
} | |
// Save the file only if JSON is valid | |
private void saveFile(String content) { | |
try (FileWriter writer = new FileWriter(filePath)) { | |
writer.write(content); // Save the content | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
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; | |
} | |
// Updated method to push the current state onto the undo stack | |
private void pushUndoState(String newState) { | |
// Avoid pushing null states and ensure that state has actually changed | |
if (newState == null || (!undoStack.isEmpty() && undoStack.peek().equals(newState))) { | |
return; | |
} | |
// Ensure the undo stack does not exceed the max size | |
if (undoStack.size() >= MAX_UNDO_STACK_SIZE) { | |
undoStack.removeFirst(); // Remove the oldest state to prevent overflow | |
} | |
// Push the new state onto the undo stack | |
undoStack.push(newState); | |
}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment