diff --git a/src/main/java/noppes/npcs/client/CustomNpcResourceListener.java b/src/main/java/noppes/npcs/client/CustomNpcResourceListener.java
index 14bb52e71..c856cbea3 100644
--- a/src/main/java/noppes/npcs/client/CustomNpcResourceListener.java
+++ b/src/main/java/noppes/npcs/client/CustomNpcResourceListener.java
@@ -10,12 +10,12 @@ import net.minecraft.util.StatCollector;
import noppes.npcs.CustomNpcs;
import noppes.npcs.LogWriter;
import noppes.npcs.client.gui.util.script.interpreter.js_parser.JSTypeRegistry;
+import noppes.npcs.client.gui.util.script.interpreter.token.ScriptColorScheme;
import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.InputStream;
+import java.io.*;
public class CustomNpcResourceListener implements
IResourceManagerReloadListener {
@@ -30,8 +30,14 @@ public class CustomNpcResourceListener implements
SimpleReloadableResourceManager simplemanager = (SimpleReloadableResourceManager) var1;
FolderResourcePack pack = new FolderResourcePack(CustomNpcs.Dir);
+ LogWriter.info("[ResourceListener] Adding FolderResourcePack: " + CustomNpcs.Dir.getAbsolutePath());
+ File schemeInFolder = new File(CustomNpcs.Dir, "assets/customnpcs/colorscheme/script_editor_scheme.json");
+ LogWriter.info("[ResourceListener] Colorscheme in customnpcs folder: " + schemeInFolder.exists()
+ + " (" + schemeInFolder.getAbsolutePath() + ")");
simplemanager.reloadResourcePack(pack);
+ ScriptColorScheme.reloadColorScheme(var1);
+
// Reload scripting .d.ts files
JSTypeRegistry registry = JSTypeRegistry.getInstance();
registry.clear();
diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java
index d98eae47d..dac50d743 100644
--- a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java
+++ b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java
@@ -19,6 +19,7 @@ import noppes.npcs.client.gui.util.script.interpreter.field.FieldAccessInfo;
import noppes.npcs.client.gui.util.script.interpreter.method.MethodCallInfo;
import noppes.npcs.client.gui.util.script.interpreter.method.MethodInfo;
import noppes.npcs.client.gui.util.script.interpreter.token.Token;
+import noppes.npcs.client.gui.util.script.interpreter.token.ScriptColorScheme;
import noppes.npcs.client.gui.util.script.interpreter.token.TokenType;
import noppes.npcs.client.gui.util.script.interpreter.hover.GutterIconRenderer;
import noppes.npcs.client.gui.util.script.interpreter.hover.HoverState;
@@ -597,18 +598,18 @@ public class GuiScriptTextArea extends GuiNpcTextField {
// Draw outer border around entire area
int offset = fullscreen() ? 2 : 1;
drawRect(x - offset, y - offset - searchBar.getTotalHeight(), x + width + offset, y + height + offset,
- 0xffa0a0a0);
+ ScriptColorScheme.getBackgroundStyle().getBorderColor());
int searchHeight = searchBar.getTotalHeight();
// Draw line number gutter background
int viewportX = x + LINE_NUMBER_GUTTER_WIDTH;
- drawRect(x, y, x + LINE_NUMBER_GUTTER_WIDTH, y + height, 0xff000000);
+ drawRect(x, y, x + LINE_NUMBER_GUTTER_WIDTH, y + height, ScriptColorScheme.getBackgroundStyle().getGutterColor());
// Draw text viewport background (starts after gutter)
- drawRect(x + LINE_NUMBER_GUTTER_WIDTH, y, x + width, y + height, 0xff000000);
+ drawRect(x + LINE_NUMBER_GUTTER_WIDTH, y, x + width, y + height, ScriptColorScheme.getBackgroundStyle().getBackgroundColor());
// Draw separator line between gutter and text area
- drawRect(x + LINE_NUMBER_GUTTER_WIDTH-1, y, x + LINE_NUMBER_GUTTER_WIDTH, y + height, 0xff3c3f41);
+ drawRect(x + LINE_NUMBER_GUTTER_WIDTH-1, y, x + LINE_NUMBER_GUTTER_WIDTH, y + height, ScriptColorScheme.getBackgroundStyle().getGutterSeparatorColor());
// Enable scissor test to clip drawing to the TEXT viewport rectangle (excludes gutter)
GL11.glEnable(GL11.GL_SCISSOR_TEST);
@@ -833,13 +834,13 @@ public class GuiScriptTextArea extends GuiNpcTextField {
int lineNumX = x + LINE_NUMBER_GUTTER_WIDTH - lineNumWidth - 5 - GutterIconRenderer.ICON_GUTTER_WIDTH; // right-align before icon space
int lineNumY = posY + 1;
// Highlight current line number
- int lineNumColor = 0xFF606366;
+ int lineNumColor = ScriptColorScheme.getBackgroundStyle().getLineNumberColor();
if (active && isEnabled()) {
for (int li = 0; li < list.size(); li++) {
LineData ld = list.get(li);
if (selection.getCursorPosition() >= ld.start && selection.getCursorPosition() < ld.end || (li == list.size() - 1 && selection.getCursorPosition() == text.length())) {
if (li == i) {
- lineNumColor = 0xFFb9c7d6;
+ lineNumColor = ScriptColorScheme.getBackgroundStyle().getLineNumberActiveColor();
break;
}
}
@@ -1078,7 +1079,7 @@ public class GuiScriptTextArea extends GuiNpcTextField {
double linesCount = (double) effLines;
int posY = (int) (y + 1f * scroll.getScrollPos() / linesCount * (height - 4)) + 1;
- drawRect(posX, posY, posX + 5, posY + sbSize + 2, 0xFFe0e0e0);
+ drawRect(posX, posY, posX + 5, posY + sbSize + 2, ScriptColorScheme.getBackgroundStyle().getScrollbarColor());
}
if (parent != null)
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java
index 28dea5e08..983018edd 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java
@@ -333,7 +333,7 @@ public class ScriptLine {
// Get the width of everything before this segment
String prefix = fullText.substring(0, seg.startPos);
int prefixWidth = ClientProxy.Font.width(prefix);
- int color = (seg.color & 0xFF000000) == 0 ? (0xFF000000 | seg.color) : seg.color;
+ int color = seg.color;
// Draw this segment at the correct position
ClientProxy.Font.drawString(seg.text, x + prefixWidth, y, color);
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/GutterIconRenderer.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/GutterIconRenderer.java
index 3c5087533..69014acc9 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/GutterIconRenderer.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/GutterIconRenderer.java
@@ -282,7 +282,7 @@ public class GutterIconRenderer {
int currentY = y + PADDING;
for (TextSegment segment : segments) {
- ClientProxy.Font.drawString(segment.text, currentX, currentY, 0xFF000000 | segment.color);
+ ClientProxy.Font.drawString(segment.text, currentX, currentY, segment.color);
currentX += ClientProxy.Font.width(segment.text);
}
}
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverRenderer.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverRenderer.java
index f3215b1a9..aed5d4391 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverRenderer.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverRenderer.java
@@ -437,7 +437,7 @@ public class TokenHoverRenderer {
for (TokenHoverInfo.TextSegment segment : segments) {
String text = segment.text;
- int color = 0xFF000000 | segment.color;
+ int color = segment.color;
// Split segment into words for wrapping
String[] words = text.split("(?<=\\s)|(?=\\s)"); // Keep whitespace as separate tokens
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/ScriptColorScheme.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/ScriptColorScheme.java
new file mode 100644
index 000000000..c8f377645
--- /dev/null
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/ScriptColorScheme.java
@@ -0,0 +1,295 @@
+package noppes.npcs.client.gui.util.script.interpreter.token;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import net.minecraft.client.resources.IResource;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.util.ResourceLocation;
+import noppes.npcs.LogWriter;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * Manages reloadable style overrides (color, priority, bold, italic) for {@link TokenType},
+ * plus editor background/gutter/scrollbar colors via {@link BackgroundStyleEntry}.
+ *
+ * Loaded from {@code assets/customnpcs/colorscheme/script_editor_scheme.json} on resource reload.
+ * Styles are cached in a flat array indexed by {@link TokenType#ordinal()} for zero-cost lookups.
+ */
+public final class ScriptColorScheme {
+
+ // Volatile array reference swapped atomically — all tokens update at once
+ static volatile StyleEntry[] styles = buildDefaults();
+
+ // Background/gutter/scrollbar colors — volatile for same atomic-swap pattern
+ private static volatile BackgroundStyleEntry background = BackgroundStyleEntry.DEFAULT;
+
+ private ScriptColorScheme() {}
+
+ /** Returns the current background style (never null). */
+ public static BackgroundStyleEntry getBackgroundStyle() {
+ return background;
+ }
+
+ /**
+ * Reload the color scheme from the resource pack's JSON file.
+ * Uses {@code getAllResources()} to find the highest-priority version
+ * (the last entry in the list, which is the latest resource pack override).
+ * Falls back to defaults if the file is missing or malformed.
+ */
+ public static void reloadColorScheme(IResourceManager resourceManager) {
+ ResourceLocation loc = new ResourceLocation("customnpcs", "colorscheme/script_editor_scheme.json");
+ try {
+ List allResources = resourceManager.getAllResources(loc);
+
+ if (allResources.isEmpty()) {
+ LogWriter.info("[ColorScheme] No script_editor_scheme.json found in any resource pack, using defaults");
+ resetToDefaults();
+ return;
+ }
+
+ int count = allResources.size();
+ LogWriter.info("[ColorScheme] Found " + count + " script_editor_scheme.json resource(s):");
+ for (int i = 0; i < count; i++) {
+ IResource res = allResources.get(i);
+ String preview = peekResourceContent(res);
+ LogWriter.info("[ColorScheme] [" + i + "] id=@" + Integer.toHexString(System.identityHashCode(res))
+ + " preview: " + preview);
+ }
+ LogWriter.info("[ColorScheme] Using highest-priority resource (last in list, index " + (count - 1) + ")");
+
+ // Re-fetch the resource list to get a fresh InputStream for the last entry,
+ // because peekResourceContent consumed the original streams.
+ List freshResources = resourceManager.getAllResources(loc);
+ IResource bestResource = freshResources.get(freshResources.size() - 1);
+
+ try (InputStream is = bestResource.getInputStream();
+ InputStreamReader reader = new InputStreamReader(is, "UTF-8")) {
+ loadFromJson(reader);
+ LogWriter.info("[ColorScheme] Loaded script_editor_scheme.json successfully");
+ logLoadedSample();
+ }
+ } catch (FileNotFoundException e) {
+ LogWriter.info("[ColorScheme] No script_editor_scheme.json found, using defaults");
+ resetToDefaults();
+ } catch (Exception e) {
+ LogWriter.error("[ColorScheme] Failed to load script_editor_scheme.json: " + e.getMessage());
+ resetToDefaults();
+ }
+ }
+
+ private static String peekResourceContent(IResource res) {
+ try (InputStream peekIs = res.getInputStream()) {
+ byte[] buf = new byte[120];
+ int read = peekIs.read(buf);
+ if (read > 0) {
+ return new String(buf, 0, read, "UTF-8").replaceAll("\\s+", " ").trim();
+ }
+ } catch (Exception ignored) {}
+ return "";
+ }
+
+ private static void logLoadedSample() {
+ StyleEntry[] current = styles;
+ TokenType[] samples = { TokenType.COMMENT, TokenType.KEYWORD, TokenType.STRING, TokenType.METHOD_CALL, TokenType.DEFAULT };
+ for (TokenType tt : samples) {
+ StyleEntry e = current[tt.ordinal()];
+ LogWriter.info("[ColorScheme] " + tt.name() + " -> color=#" + String.format("%08X", e.hexColor)
+ + ", priority=" + e.priority + ", bold=" + e.bold + ", italic=" + e.italic);
+ }
+
+ BackgroundStyleEntry bg = background;
+ LogWriter.info("[ColorScheme] background -> bg=#" + String.format("%08X", bg.getBackgroundColor())
+ + ", gutter=#" + String.format("%08X", bg.getGutterColor()));
+ }
+
+ /**
+ * Parse a color scheme JSON and install it as the active scheme.
+ * Expected format: {@code { "TOKEN_NAME": { "color": "#RRGGBB", "priority": int, "bold": bool, "italic": bool }, ... }}
+ * Missing properties per token fall back to the enum default. Parse errors are logged per-token.
+ */
+ public static void loadFromJson(Reader reader) {
+ try {
+ JsonParser parser = new JsonParser();
+ JsonElement root = parser.parse(reader);
+ if (!root.isJsonObject()) {
+ LogWriter.error("[ColorScheme] script_editor_scheme.json root is not a JSON object, using defaults");
+ return;
+ }
+
+ JsonObject obj = root.getAsJsonObject();
+
+ background = parseBackground(obj);
+
+ TokenType[] all = TokenType.values();
+ StyleEntry[] next = new StyleEntry[all.length];
+ for (TokenType tt : all) {
+ next[tt.ordinal()] = parseEntry(obj, tt);
+ }
+ styles = next;
+ } catch (Exception e) {
+ LogWriter.error("[ColorScheme] Failed to parse script_editor_scheme.json, using defaults: " + e.getMessage());
+ }
+ }
+
+ public static void resetToDefaults() {
+ styles = buildDefaults();
+ background = BackgroundStyleEntry.DEFAULT;
+ }
+
+ private static StyleEntry parseEntry(JsonObject root, TokenType tt) {
+ if (!root.has(tt.name())) {
+ return defaultEntry(tt);
+ }
+ try {
+ JsonElement elem = root.get(tt.name());
+ if (!elem.isJsonObject()) {
+ LogWriter.error("[ColorScheme] Entry for " + tt.name() + " is not an object, skipping");
+ return defaultEntry(tt);
+ }
+ JsonObject entry = elem.getAsJsonObject();
+
+ int defaultColor = tt.getDefaultHexColor();
+ if ((defaultColor & 0xFF000000) == 0) {
+ defaultColor |= 0xFF000000;
+ }
+
+ int color = entry.has("color")
+ ? parseColor(entry.get("color"), defaultColor, tt.name())
+ : defaultColor;
+ int priority = entry.has("priority") ? entry.get("priority").getAsInt() : tt.getDefaultPriority();
+ boolean bold = entry.has("bold") ? entry.get("bold").getAsBoolean() : tt.getDefaultBold();
+ boolean italic = entry.has("italic") ? entry.get("italic").getAsBoolean() : tt.getDefaultItalic();
+
+ return new StyleEntry(color, priority, bold, italic);
+ } catch (Exception e) {
+ LogWriter.error("[ColorScheme] Error parsing token " + tt.name() + ", using defaults: " + e.getMessage());
+ return defaultEntry(tt);
+ }
+ }
+
+ private static StyleEntry defaultEntry(TokenType tt) {
+ int color = tt.getDefaultHexColor();
+ if ((color & 0xFF000000) == 0) {
+ color |= 0xFF000000;
+ }
+ return new StyleEntry(color, tt.getDefaultPriority(), tt.getDefaultBold(), tt.getDefaultItalic());
+ }
+
+ private static BackgroundStyleEntry parseBackground(JsonObject root) {
+ if (!root.has("background")) {
+ return BackgroundStyleEntry.DEFAULT;
+ }
+ try {
+ JsonElement elem = root.get("background");
+ if (!elem.isJsonObject()) {
+ LogWriter.error("[ColorScheme] 'background' is not an object, using defaults");
+ return BackgroundStyleEntry.DEFAULT;
+ }
+ JsonObject bg = elem.getAsJsonObject();
+ BackgroundStyleEntry d = BackgroundStyleEntry.DEFAULT;
+
+ int backgroundColor = bg.has("backgroundColor") ? parseColor(bg.get("backgroundColor"), d.getBackgroundColor(), "background.backgroundColor") : d.getBackgroundColor();
+ int gutterColor = bg.has("gutterColor") ? parseColor(bg.get("gutterColor"), d.getGutterColor(), "background.gutterColor") : d.getGutterColor();
+ int gutterSeparatorColor = bg.has("gutterSeparatorColor") ? parseColor(bg.get("gutterSeparatorColor"), d.getGutterSeparatorColor(), "background.gutterSeparatorColor") : d.getGutterSeparatorColor();
+ int lineNumberColor = bg.has("lineNumberColor") ? parseColor(bg.get("lineNumberColor"), d.getLineNumberColor(), "background.lineNumberColor") : d.getLineNumberColor();
+ int lineNumberActiveColor = bg.has("lineNumberActiveColor") ? parseColor(bg.get("lineNumberActiveColor"), d.getLineNumberActiveColor(), "background.lineNumberActiveColor") : d.getLineNumberActiveColor();
+ int scrollbarColor = bg.has("scrollbarColor") ? parseColor(bg.get("scrollbarColor"), d.getScrollbarColor(), "background.scrollbarColor") : d.getScrollbarColor();
+ int borderColor = bg.has("borderColor") ? parseColor(bg.get("borderColor"), d.getBorderColor(), "background.borderColor") : d.getBorderColor();
+
+ return new BackgroundStyleEntry(backgroundColor, gutterColor, gutterSeparatorColor,
+ lineNumberColor, lineNumberActiveColor, scrollbarColor, borderColor);
+ } catch (Exception e) {
+ LogWriter.error("[ColorScheme] Error parsing 'background', using defaults: " + e.getMessage());
+ return BackgroundStyleEntry.DEFAULT;
+ }
+ }
+
+ private static StyleEntry[] buildDefaults() {
+ TokenType[] all = TokenType.values();
+ StyleEntry[] defaults = new StyleEntry[all.length];
+ for (TokenType tt : all) {
+ defaults[tt.ordinal()] = defaultEntry(tt);
+ }
+ return defaults;
+ }
+
+ private static int parseColor(JsonElement element, int fallback, String tokenName) {
+ try {
+ if (element.isJsonPrimitive()) {
+ if (element.getAsJsonPrimitive().isString()) {
+ String s = element.getAsString().trim();
+ if (s.startsWith("#")) {
+ s = s.substring(1);
+ }
+ int color = (int) Long.parseLong(s, 16);
+ if (s.length() <= 6) {
+ color |= 0xFF000000;
+ }
+ return color;
+ } else if (element.getAsJsonPrimitive().isNumber()) {
+ return element.getAsInt();
+ }
+ }
+ } catch (NumberFormatException e) {
+ LogWriter.error("[ColorScheme] Invalid color for " + tokenName + ": " + element + ", using default");
+ }
+ return fallback;
+ }
+
+ static final class StyleEntry {
+ final int hexColor;
+ final int priority;
+ final boolean bold;
+ final boolean italic;
+
+ StyleEntry(int hexColor, int priority, boolean bold, boolean italic) {
+ this.hexColor = hexColor;
+ this.priority = priority;
+ this.bold = bold;
+ this.italic = italic;
+ }
+ }
+
+ public static final class BackgroundStyleEntry {
+ static final BackgroundStyleEntry DEFAULT = new BackgroundStyleEntry(
+ 0xff000000, // backgroundColor (text viewport)
+ 0xff000000, // gutterColor (line-number gutter)
+ 0xff3c3f41, // gutterSeparatorColor
+ 0xFF606366, // lineNumberColor (inactive)
+ 0xFFb9c7d6, // lineNumberActiveColor (current line)
+ 0xFFe0e0e0, // scrollbarColor
+ 0xffa0a0a0 // borderColor (outer border)
+ );
+
+ private final int backgroundColor;
+ private final int gutterColor;
+ private final int gutterSeparatorColor;
+ private final int lineNumberColor;
+ private final int lineNumberActiveColor;
+ private final int scrollbarColor;
+ private final int borderColor;
+
+ BackgroundStyleEntry(int backgroundColor, int gutterColor, int gutterSeparatorColor,
+ int lineNumberColor, int lineNumberActiveColor,
+ int scrollbarColor, int borderColor) {
+ this.backgroundColor = backgroundColor;
+ this.gutterColor = gutterColor;
+ this.gutterSeparatorColor = gutterSeparatorColor;
+ this.lineNumberColor = lineNumberColor;
+ this.lineNumberActiveColor = lineNumberActiveColor;
+ this.scrollbarColor = scrollbarColor;
+ this.borderColor = borderColor;
+ }
+
+ public int getBackgroundColor() { return backgroundColor; }
+ public int getGutterColor() { return gutterColor; }
+ public int getGutterSeparatorColor() { return gutterSeparatorColor; }
+ public int getLineNumberColor() { return lineNumberColor; }
+ public int getLineNumberActiveColor() { return lineNumberActiveColor; }
+ public int getScrollbarColor() { return scrollbarColor; }
+ public int getBorderColor() { return borderColor; }
+ }
+}
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java
index 9306a3c67..e3f5c6470 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/token/TokenType.java
@@ -6,81 +6,100 @@ import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
* Defines all token types for syntax highlighting with hex colors and priorities.
* Priority determines which token type wins when marks overlap.
* Higher priority = wins conflicts.
+ *
+ * Style properties (color, priority, bold, italic) can be overridden at runtime
+ * via {@link ScriptColorScheme}. The enum constructor values serve as compile-time defaults.
*/
public enum TokenType {
// Comments and strings have highest priority - they override everything inside them
- COMMENT(0x777777, 140),
- STRING(0xCC8855, 130),
+ COMMENT(0xFF777777, 140),
+ STRING(0xFFCC8855, 130),
// JSDoc elements - lower priority but will fill gaps left by fragmented comment marking
- JSDOC_TAG(0xCC9933, 125), // @param, @type, @return etc. (gold/orange)
- JSDOC_TYPE(0x00AAAA, 124), // {TypeName} in JSDoc (aqua like types)
+ JSDOC_TAG(0xFFCC9933, 125), // @param, @type, @return etc. (gold/orange)
+ JSDOC_TYPE(0xFF00AAAA, 124), // {TypeName} in JSDoc (aqua like types)
- UNUSED_IMPORT(0x666666, 119), // unused import statements (gray)
+ UNUSED_IMPORT(0xFF666666, 119), // unused import statements (gray)
// Keywords and modifiers
- CLASS_KEYWORD(0xFF5555, 115), // 'class', 'interface', 'enum' keywords
- IMPORT_KEYWORD(0xFFAA00, 110), // 'import' keyword
- KEYWORD(0xFF5555, 100), // control flow: if, else, for, while, etc.
- MODIFIER(0xFFAA00, 90), // public, private, static, final, etc.
+ CLASS_KEYWORD(0xFFFF5555, 115), // 'class', 'interface', 'enum' keywords
+ IMPORT_KEYWORD(0xFFFFAA00, 110), // 'import' keyword
+ KEYWORD(0xFFFF5555, 100), // control flow: if, else, for, while, etc.
+ MODIFIER(0xFFFFAA00, 90), // public, private, static, final, etc.
// Type declarations and references
- INTERFACE_DECL(0x55FFFF, 85), // interface names (aqua)
- ENUM_DECL(0xFF55FF, 85), // enum names (magenta)
- ENUM_CONSTANT(0x55FFFF, 84, true, false), // enum constant values (blue, bold+italic) - like IntelliJ
- CLASS_DECL(0x00AAAA, 85), // class names in declarations
- IMPORTED_CLASS(0x00AAAA, 75), // imported class usages
- GENERIC_TYPE_PARAM(0x00FA9A, 76), // generic type parameters like T, E, K, V (light green)
- TYPE_DECL(0x00AAAA, 70), // package paths, type references
+ INTERFACE_DECL(0xFF55FFFF, 85), // interface names (aqua)
+ ENUM_DECL(0xFFFF55FF, 85), // enum names (magenta)
+ ENUM_CONSTANT(0xFF55FFFF, 84, true, false), // enum constant values (blue, bold+italic) - like IntelliJ
+ CLASS_DECL(0xFF00AAAA, 85), // class names in declarations
+ IMPORTED_CLASS(0xFF00AAAA, 75), // imported class usages
+ GENERIC_TYPE_PARAM(0xFF00FA9A, 76), // generic type parameters like T, E, K, V (light green)
+ TYPE_DECL(0xFF00AAAA, 70), // package paths, type references
// Methods
- METHOD_DECL(0x00AA00, 60), // method declarations (green)
- METHOD_CALL(0x55FF55, 50), // method calls (bright green)
+ METHOD_DECL(0xFF00AA00, 60), // method declarations (green)
+ METHOD_CALL(0xFF55FF55, 50), // method calls (bright green)
// Variables and fields
- UNDEFINED_VAR(0xAA0000, 20), // unresolved variables (dark red) - high priority
- PARAMETER(0x5555FF, 36), // method parameters (blue)
- GLOBAL_FIELD(0x55FFFF, 35), // class-level fields (aqua)
- LOCAL_FIELD(0xFFFF55, 25), // local variables (yellow)
- STATIC_FINAL_FIELD(0xFF55FF, 36, false, true), // static final fields (magenta, italic)
+ UNDEFINED_VAR(0xFFAA0000, 20), // unresolved variables (dark red) - high priority
+ PARAMETER(0xFF5555FF, 36), // method parameters (blue)
+ GLOBAL_FIELD(0xFF55FFFF, 35), // class-level fields (aqua)
+ LOCAL_FIELD(0xFFFFFF55, 25), // local variables (yellow)
+ STATIC_FINAL_FIELD(0xFFFF55FF, 36, false, true), // static final fields (magenta, italic)
// Literals
- LITERAL(0x777777, 40), // numeric and boolean literals
+ LITERAL(0xFF777777, 40), // numeric and boolean literals
// Default
- VARIABLE(0xFFFFFF, 30), // generic variables
- DEFAULT(0xFFFFFF, 0); // default text color (white)
+ VARIABLE(0xFFFFFFFF, 30), // generic variables
+ DEFAULT(0xFFFFFFFF, 0); // default text color (white)
- private final int hexColor;
- private final int priority;
- private final boolean bold;
- private final boolean italic;
+ private final int defaultHexColor;
+ private final int defaultPriority;
+ private final boolean defaultBold;
+ private final boolean defaultItalic;
TokenType(int hexColor, int priority) {
this(hexColor, priority, false, false);
}
TokenType(int hexColor, int priority, boolean bold, boolean italic) {
- this.hexColor = hexColor;
- this.priority = priority;
- this.bold = bold;
- this.italic = italic;
+ this.defaultHexColor = hexColor;
+ this.defaultPriority = priority;
+ this.defaultBold = bold;
+ this.defaultItalic = italic;
}
public int getHexColor() {
- return hexColor;
+ return ScriptColorScheme.styles[ordinal()].hexColor;
}
public int getPriority() {
- return priority;
+ return ScriptColorScheme.styles[ordinal()].priority;
}
public boolean isBold() {
- return bold;
+ return ScriptColorScheme.styles[ordinal()].bold;
}
public boolean isItalic() {
- return italic;
+ return ScriptColorScheme.styles[ordinal()].italic;
+ }
+
+ int getDefaultHexColor() {
+ return defaultHexColor;
+ }
+
+ int getDefaultPriority() {
+ return defaultPriority;
+ }
+
+ boolean getDefaultBold() {
+ return defaultBold;
+ }
+
+ boolean getDefaultItalic() {
+ return defaultItalic;
}
public static TokenType getByType(TypeInfo typeInfo) {
diff --git a/src/main/resources/assets/customnpcs/colorscheme/script_editor_scheme.json b/src/main/resources/assets/customnpcs/colorscheme/script_editor_scheme.json
new file mode 100644
index 000000000..86dd81927
--- /dev/null
+++ b/src/main/resources/assets/customnpcs/colorscheme/script_editor_scheme.json
@@ -0,0 +1,167 @@
+{
+ "background": {
+ "backgroundColor": "#FF000000",
+ "gutterColor": "#FF000000",
+ "gutterSeparatorColor": "#FF3C3F41",
+ "lineNumberColor": "#FF606366",
+ "lineNumberActiveColor": "#FFB9C7D6",
+ "scrollbarColor": "#FFE0E0E0",
+ "borderColor": "#FFA0A0A0"
+ },
+ "COMMENT": {
+ "color": "#FF777777",
+ "priority": 140,
+ "bold": false,
+ "italic": false
+ },
+ "STRING": {
+ "color": "#FFCC8855",
+ "priority": 130,
+ "bold": false,
+ "italic": false
+ },
+ "JSDOC_TAG": {
+ "color": "#FFCC9933",
+ "priority": 125,
+ "bold": false,
+ "italic": false
+ },
+ "JSDOC_TYPE": {
+ "color": "#FF00AAAA",
+ "priority": 124,
+ "bold": false,
+ "italic": false
+ },
+ "UNUSED_IMPORT": {
+ "color": "#FF666666",
+ "priority": 119,
+ "bold": false,
+ "italic": false
+ },
+ "CLASS_KEYWORD": {
+ "color": "#FFFF5555",
+ "priority": 115,
+ "bold": false,
+ "italic": false
+ },
+ "IMPORT_KEYWORD": {
+ "color": "#FFFFAA00",
+ "priority": 110,
+ "bold": false,
+ "italic": false
+ },
+ "KEYWORD": {
+ "color": "#FFFF5555",
+ "priority": 100,
+ "bold": false,
+ "italic": false
+ },
+ "MODIFIER": {
+ "color": "#FFFFAA00",
+ "priority": 90,
+ "bold": false,
+ "italic": false
+ },
+ "INTERFACE_DECL": {
+ "color": "#FF55FFFF",
+ "priority": 85,
+ "bold": false,
+ "italic": false
+ },
+ "ENUM_DECL": {
+ "color": "#FFFF55FF",
+ "priority": 85,
+ "bold": false,
+ "italic": false
+ },
+ "ENUM_CONSTANT": {
+ "color": "#FF55FFFF",
+ "priority": 84,
+ "bold": true,
+ "italic": false
+ },
+ "CLASS_DECL": {
+ "color": "#FF00AAAA",
+ "priority": 85,
+ "bold": false,
+ "italic": false
+ },
+ "IMPORTED_CLASS": {
+ "color": "#FF00AAAA",
+ "priority": 75,
+ "bold": false,
+ "italic": false
+ },
+ "GENERIC_TYPE_PARAM": {
+ "color": "#FF00FA9A",
+ "priority": 76,
+ "bold": false,
+ "italic": false
+ },
+ "TYPE_DECL": {
+ "color": "#FF00AAAA",
+ "priority": 70,
+ "bold": false,
+ "italic": false
+ },
+ "METHOD_DECL": {
+ "color": "#FF00AA00",
+ "priority": 60,
+ "bold": false,
+ "italic": false
+ },
+ "METHOD_CALL": {
+ "color": "#FF55FF55",
+ "priority": 50,
+ "bold": false,
+ "italic": false
+ },
+ "UNDEFINED_VAR": {
+ "color": "#FFAA0000",
+ "priority": 20,
+ "bold": false,
+ "italic": false
+ },
+ "PARAMETER": {
+ "color": "#FF5555FF",
+ "priority": 36,
+ "bold": false,
+ "italic": false
+ },
+ "GLOBAL_FIELD": {
+ "color": "#FF55FFFF",
+ "priority": 35,
+ "bold": false,
+ "italic": false
+ },
+ "LOCAL_FIELD": {
+ "color": "#FFFFFF55",
+ "priority": 25,
+ "bold": false,
+ "italic": false
+ },
+ "STATIC_FINAL_FIELD": {
+ "color": "#FFFF55FF",
+ "priority": 36,
+ "bold": false,
+ "italic": true
+ },
+ "LITERAL": {
+ "color": "#FF777777",
+ "priority": 40,
+ "bold": false,
+ "italic": false
+ },
+ "VARIABLE": {
+ "color": "#FFFFFFFF",
+ "priority": 30,
+ "bold": false,
+ "italic": false
+ },
+ "DEFAULT": {
+ "color": "#FFFFFFFF",
+ "priority": 0,
+ "bold": false,
+ "italic": false
+ }
+}