diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingScreen.java index 875ca66..a24723f 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingScreen.java @@ -5,8 +5,12 @@ import io.github.techstreet.dfscript.screen.widget.CItem; import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; +import io.github.techstreet.dfscript.script.options.ScriptOption; import io.github.techstreet.dfscript.script.options.ScriptOptionEnum; import io.github.techstreet.dfscript.util.chat.ChatUtil; + +import java.util.ArrayList; + public class ScriptAddSettingScreen extends CScreen { private static final int size; @@ -29,7 +33,7 @@ public ScriptAddSettingScreen(Script script, int pos) { if(option.getExtraTypes() == 0) { citem.setClickListener((a) -> { try { - script.addOption(pos, new ScriptNamedOption(option.getOptionType().getConstructor().newInstance(), script.getUnnamedOption())); + script.addOption(pos, new ScriptNamedOption(ScriptOption.instantiate(option, new ArrayList<>()), script.getUnnamedOption())); } catch (Exception e) { ChatUtil.error(String.valueOf(e.getCause())); } diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingSubtypeScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingSubtypeScreen.java index b1f0ef8..05a6c0c 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingSubtypeScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddSettingSubtypeScreen.java @@ -6,6 +6,7 @@ import io.github.techstreet.dfscript.screen.widget.CTexturedButton; import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; +import io.github.techstreet.dfscript.script.options.ScriptOption; import io.github.techstreet.dfscript.script.options.ScriptOptionEnum; import io.github.techstreet.dfscript.util.chat.ChatUtil; import net.minecraft.client.gui.DrawableHelper; @@ -118,10 +119,7 @@ public void render(MatrixStack stack, int mouseX, int mouseY, float tickDelta) { if(noNull) { CTexturedButton button = new CTexturedButton(width - 10, 3, 8, 8, DFScript.MOD_ID + ":on_button.png", () -> { try { - Class[] argTypes = new Class[option.getExtraTypes()]; - Arrays.fill(argTypes, ScriptOptionEnum.class); - - script.addOption(pos, new ScriptNamedOption(option.getOptionType().getConstructor(argTypes).newInstance(subtypes.toArray()), script.getUnnamedOption())); + script.addOption(pos, new ScriptNamedOption(ScriptOption.instantiate(option, subtypes), script.getUnnamedOption())); } catch (Exception e) { ChatUtil.error(String.valueOf(e.getCause())); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptBoolOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptBoolOption.java index 962bce6..18a1660 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptBoolOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptBoolOption.java @@ -32,9 +32,6 @@ public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) return ScriptActionArgument.ScriptActionArgumentType.TEXT.convertableTo(arg); } - @Override - public String getName() { return "Boolean"; } - @Override public int create(CScrollPanel panel, int x, int y, int width) { CTexturedButton button = new CTexturedButton(x, y, 8, 8, getTexture(), null, 0, 0, 1, 0.5f, 0, 0.5f); @@ -51,11 +48,6 @@ private String getTexture() { return DFScript.MOD_ID + (value ? ":on_button.png" : ":off_button.png"); } - @Override - public Item getIcon() { - return Items.LEVER; - } - @Override public JsonElement getJsonElement() { return new JsonPrimitive(value); diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDictionaryOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDictionaryOption.java new file mode 100644 index 0000000..db52aa4 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDictionaryOption.java @@ -0,0 +1,177 @@ +package io.github.techstreet.dfscript.script.options; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.script.ScriptSettingsScreen; +import io.github.techstreet.dfscript.screen.widget.CButton; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument; +import io.github.techstreet.dfscript.script.util.ScriptOptionSubtypeMismatchException; +import io.github.techstreet.dfscript.script.values.ScriptDictionaryValue; +import io.github.techstreet.dfscript.script.values.ScriptListValue; +import io.github.techstreet.dfscript.script.values.ScriptValue; +import io.github.techstreet.dfscript.util.chat.ChatUtil; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.sound.SoundEvents; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +public class ScriptDictionaryOption implements ScriptOption { + + List value = new ArrayList<>(); + ScriptOptionEnum[] valueTypes; + + public ScriptDictionaryOption(JsonElement value, ScriptOptionEnum type1, ScriptOptionEnum type2) throws ScriptOptionSubtypeMismatchException { + valueTypes = new ScriptOptionEnum[]{type1,type2}; + + if(!value.isJsonArray()) + { + DFScript.LOGGER.error("Not a JSON Array!"); + } + + for(JsonElement e : value.getAsJsonArray()) + { + this.value.add((ScriptDualOption) ScriptOption.fromJson(e, ScriptOptionEnum.DUAL, + List.of(type1, type2) + )); + } + + checkValidity(); + } + + public ScriptDictionaryOption(ScriptOptionEnum type1, ScriptOptionEnum type2) throws ScriptOptionSubtypeMismatchException { + valueTypes = new ScriptOptionEnum[]{type1,type2}; + + checkValidity(); + } + + private void checkValidity() throws ScriptOptionSubtypeMismatchException { + for(int i = 0; i < 2; i++) + { + if(valueTypes[i].getExtraTypes() != 0) + { + throw new ScriptOptionSubtypeMismatchException("Incorrect amount of extra types"); + } + } + + for(ScriptDualOption o : value) + { + for(int i = 0; i < 2; i++) { + if (valueTypes[i] != o.getSubtypes().get(i)) { + throw new ScriptOptionSubtypeMismatchException("Incorrect type of an item"); + } + } + } + } + + @Override + public ScriptValue getValue() { + HashMap result = new HashMap<>(); + + for(ScriptOption o : value) + { + List s = o.getValue().asList(); + + result.put(s.get(0).asText(),s.get(1)); + } + + return new ScriptDictionaryValue(result); + } + + @Override + public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) { + return ScriptActionArgument.ScriptActionArgumentType.DICTIONARY.convertableTo(arg); + } + + @Override + public int create(CScrollPanel panel, int x, int y, int width) { + int i = 0; + for(ScriptOption o : value) { + int y1 = y; + y = o.create(panel,x+5,y,width-5); + int finalI = i; + panel.add(new CButton(5, y1, 115, y-y1, "",() -> {}) { + @Override + public void render(MatrixStack stack, int mouseX, int mouseY, float tickDelta) { + Rectangle b = getBounds(); + if (b.contains(mouseX, mouseY)) { + DrawableHelper.fill(stack, b.x, b.y, b.x + b.width, b.y + b.height, 0x33000000); + } + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (getBounds().contains(x, y)) { + if (button != 0) { + DFScript.MC.getSoundManager().play(PositionedSoundInstance.ambient(SoundEvents.UI_BUTTON_CLICK, 1f,1f)); + if (DFScript.MC.currentScreen instanceof ScriptSettingsScreen s) { + CButton insertBefore = new CButton((int) x, (int) y, 50, 8, "Insert Item Before", () -> { + try { + value.add(finalI, (ScriptDualOption) ScriptOption.instantiate(ScriptOptionEnum.DUAL, List.of(valueTypes[0],valueTypes[1]))); + } catch (Exception e) { + ChatUtil.error(String.valueOf(e.getCause())); + } + s.reloadMenu(); + }); + CButton insertAfter = new CButton((int) x, (int) y + 8, 50, 8, "Insert Item After", () -> { + try { + value.add(finalI + 1, (ScriptDualOption) ScriptOption.instantiate(ScriptOptionEnum.DUAL, List.of(valueTypes[0],valueTypes[1]))); + } catch (Exception e) { + ChatUtil.error(String.valueOf(e.getCause())); + } + s.reloadMenu(); + }); + CButton delete = new CButton((int) x, (int) y + 16, 50, 8, "Delete Item", () -> { + value.remove(finalI); + s.reloadMenu(); + }); + s.newContextMenu(new CButton[]{insertBefore, insertAfter, delete}); + } + return true; + } + } + return false; + } + }); + i++; + } + + CButton button = new CButton(x+5, y, width-5, 8, "Add Item", ()->{ + try { + value.add((ScriptDualOption) ScriptOption.instantiate(ScriptOptionEnum.DUAL, List.of(valueTypes[0],valueTypes[1]))); + } catch (Exception e) { + ChatUtil.error(String.valueOf(e.getCause())); + } + + if(DFScript.MC.currentScreen instanceof ScriptSettingsScreen s) { + s.reloadMenu(); + } + }); + + panel.add(button); + + return y+10; + } + + @Override + public JsonElement getJsonElement() { + JsonArray array = new JsonArray(value.size()); + for (ScriptOption o : value) { + array.add(o.getJsonElement()); + } + + return array; + } + + @Override + public List getSubtypes() { + return Arrays.stream(valueTypes).toList(); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDualOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDualOption.java new file mode 100644 index 0000000..747e713 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptDualOption.java @@ -0,0 +1,115 @@ +package io.github.techstreet.dfscript.script.options; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.script.ScriptSettingsScreen; +import io.github.techstreet.dfscript.screen.widget.CButton; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument; +import io.github.techstreet.dfscript.script.util.ScriptOptionSubtypeMismatchException; +import io.github.techstreet.dfscript.script.values.ScriptListValue; +import io.github.techstreet.dfscript.script.values.ScriptValue; +import io.github.techstreet.dfscript.util.chat.ChatUtil; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.sound.SoundEvents; + +import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ScriptDualOption implements ScriptOption { + + ScriptOption[] values; + ScriptOptionEnum[] valueTypes; + + public ScriptDualOption(JsonElement value, ScriptOptionEnum type1, ScriptOptionEnum type2) throws ScriptOptionSubtypeMismatchException { + valueTypes = new ScriptOptionEnum[]{type1,type2}; + + values = new ScriptOption[] + { + ScriptOption.fromJson(value.getAsJsonObject().get("first"), type1, new ArrayList<>()), + ScriptOption.fromJson(value.getAsJsonObject().get("second"), type2, new ArrayList<>()) + }; + + checkValidity(); + } + + public ScriptDualOption(ScriptOptionEnum type1, ScriptOptionEnum type2) throws ScriptOptionSubtypeMismatchException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + values = new ScriptOption[]{ + ScriptOption.instantiate(type1, new ArrayList<>()), + ScriptOption.instantiate(type2, new ArrayList<>()) + }; + valueTypes = new ScriptOptionEnum[]{type1,type2}; + + checkValidity(); + } + + private void checkValidity() throws ScriptOptionSubtypeMismatchException { + for(int i = 0; i < 2; i++) { + if (valueTypes[i].getExtraTypes() != 0) { + throw new ScriptOptionSubtypeMismatchException("Incorrect amount of extra types"); + } + + if(!values[i].getClass().equals(valueTypes[i].getOptionType())) { + throw new ScriptOptionSubtypeMismatchException("Incorrect type of a value"); + } + } + } + + @Override + public ScriptValue getValue() { + List result = new ArrayList<>(); + + for(ScriptOption o : values) + { + result.add(o.getValue()); + } + + return new ScriptListValue(result); + } + + @Override + public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) { + return ScriptActionArgument.ScriptActionArgumentType.LIST.convertableTo(arg); + } + + @Override + public int create(CScrollPanel panel, int x, int y, int width) { + + int endY = y; + + for(int i = 0; i < 2; i++) + { + int curY = values[i].create(panel, x, y, width/2-1); + if(curY > endY) + { + endY = curY; + } + + x += width/2+1; + } + + return endY; + } + + @Override + public JsonElement getJsonElement() { + JsonObject obj = new JsonObject(); + + obj.add("first", values[0].getJsonElement()); + obj.add("second", values[1].getJsonElement()); + + return obj; + } + + @Override + public List getSubtypes() { + return Arrays.stream(valueTypes).toList(); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptFloatOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptFloatOption.java index 55ec960..6e9c916 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptFloatOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptFloatOption.java @@ -30,8 +30,6 @@ public ScriptValue getValue() { public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) { return ScriptActionArgument.ScriptActionArgumentType.NUMBER.convertableTo(arg); } - @Override - public String getName() { return "Floating-Point Value"; } @Override public int create(CScrollPanel panel, int x, int y, int width) { @@ -50,11 +48,6 @@ public int create(CScrollPanel panel, int x, int y, int width) { return y + 12; } - @Override - public Item getIcon() { - return Items.SLIME_BLOCK; - } - @Override public JsonElement getJsonElement() { return new JsonPrimitive(value); diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptIntOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptIntOption.java index 3e18f35..7c9bde3 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptIntOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptIntOption.java @@ -30,8 +30,6 @@ public ScriptValue getValue() { public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) { return ScriptActionArgument.ScriptActionArgumentType.NUMBER.convertableTo(arg); } - @Override - public String getName() { return "Integer"; } @Override public int create(CScrollPanel panel, int x, int y, int width) { @@ -50,11 +48,6 @@ public int create(CScrollPanel panel, int x, int y, int width) { return y + 12; } - @Override - public Item getIcon() { - return Items.SLIME_BALL; - } - @Override public JsonElement getJsonElement() { return new JsonPrimitive(value); diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptKeyOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptKeyOption.java index 98e9154..008f918 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptKeyOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptKeyOption.java @@ -37,9 +37,6 @@ public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) return ScriptActionArgument.ScriptActionArgumentType.NUMBER.convertableTo(arg); } - @Override - public String getName() { return "Key"; } - @Override public int create(CScrollPanel panel, int x, int y, int width) { CKeyField field = new CKeyField(x, y, width, 10, true, value); @@ -51,11 +48,6 @@ public int create(CScrollPanel panel, int x, int y, int width) { return y + 12; } - @Override - public Item getIcon() { - return Items.STONE_BUTTON; - } - @Override public JsonElement getJsonElement() { if(value == null) { diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptListOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptListOption.java index 8341547..918ac00 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptListOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptListOption.java @@ -86,9 +86,6 @@ public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) return ScriptActionArgument.ScriptActionArgumentType.LIST.convertableTo(arg); } - @Override - public String getName() { return "List<"+valueType.getName()+">"; } - @Override public int create(CScrollPanel panel, int x, int y, int width) { int i = 0; @@ -159,11 +156,6 @@ public boolean mouseClicked(double x, double y, int button) { return y+10; } - @Override - public Item getIcon() { - return Items.LEVER; - } - @Override public JsonElement getJsonElement() { JsonArray array = new JsonArray(value.size()); diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptNamedOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptNamedOption.java index 01199dc..faf429f 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptNamedOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptNamedOption.java @@ -46,7 +46,7 @@ public void setName(String text) { } public ItemStack getIcon() { - return new ItemStack(option.getIcon()).setCustomName(Text.literal(getName()).fillStyle(Style.EMPTY.withItalic(false))); + return option.getType().getIcon().setCustomName(Text.literal(getFullName()).fillStyle(Style.EMPTY.withItalic(false))); } public static class Serializer implements JsonSerializer, JsonDeserializer { diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOption.java index d3a6366..6e2e248 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOption.java @@ -9,19 +9,30 @@ import io.github.techstreet.dfscript.script.values.ScriptValue; import net.minecraft.item.Item; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public interface ScriptOption { ScriptValue getValue(); boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg); - String getName(); + default String getName() { + String result = getType().getName(); - int create(CScrollPanel panel, int x, int y, int width); // the return value = new y + if(getSubtypes().size() > 0) + { + result += "<" + String.join(", ", getSubtypes().stream().map(ScriptOptionEnum::getName).toList()) + ">"; + } - Item getIcon(); + return result; + } + + int create(CScrollPanel panel, int x, int y, int width); // the return value = new y default ScriptOptionEnum getType() { return ScriptOptionEnum.fromClass(getClass()); @@ -104,4 +115,13 @@ static ScriptOption fromJson(JsonElement value, ScriptOptionEnum type, List subtypes) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + if(subtypes.size() == 0) return type.getOptionType().getConstructor().newInstance(); + + Class[] argTypes = new Class[type.getExtraTypes()]; + Arrays.fill(argTypes, ScriptOptionEnum.class); + + return type.getOptionType().getConstructor(argTypes).newInstance(subtypes.toArray()); + } } diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOptionEnum.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOptionEnum.java index 5de2055..a558133 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOptionEnum.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptOptionEnum.java @@ -17,7 +17,9 @@ public enum ScriptOptionEnum { FLOAT("Floating-Point", "A single option, must be an int or a float.", Items.SLIME_BLOCK, ScriptFloatOption.class), KEY("Key", "A single option, acts as a key bind.", Items.STONE_BUTTON, ScriptKeyOption.class), BOOL("Boolean", "A true/false option. Returns either \"true\" or \"false\".", Items.LEVER, ScriptBoolOption.class), - LIST("List", "A list of values, can contain a single type", Items.CHEST, ScriptListOption.class, 1); + DUAL("Dual", "Two values, two types", Items.HOPPER, ScriptDualOption.class, 2), + LIST("List", "A list of values, can contain a single type", Items.CHEST, ScriptListOption.class, 1), + DICTIONARY("Dictionary", "A dictionary of values, two types", Items.CHEST_MINECART, ScriptDictionaryOption.class, 2); String name; String description; diff --git a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptTextOption.java b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptTextOption.java index ef2290b..8ea08d1 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/options/ScriptTextOption.java +++ b/src/main/java/io/github/techstreet/dfscript/script/options/ScriptTextOption.java @@ -31,9 +31,6 @@ public boolean convertableTo(ScriptActionArgument.ScriptActionArgumentType arg) return ScriptActionArgument.ScriptActionArgumentType.TEXT.convertableTo(arg); } - @Override - public String getName() { return "Text"; } - @Override public int create(CScrollPanel panel, int x, int y, int width) { CTextField field = new CTextField(value, x, y, width, 10, true); @@ -43,11 +40,6 @@ public int create(CScrollPanel panel, int x, int y, int width) { return y + 12; } - @Override - public Item getIcon() { - return Items.BOOK; - } - @Override public JsonElement getJsonElement() { return new JsonPrimitive(value);