diff --git a/src/main/java/io/github/techstreet/dfscript/screen/ContextMenuButton.java b/src/main/java/io/github/techstreet/dfscript/screen/ContextMenuButton.java new file mode 100644 index 0000000..2720d3d --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/screen/ContextMenuButton.java @@ -0,0 +1,41 @@ +package io.github.techstreet.dfscript.screen; + +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.script.ScriptEditScreen; + +public class ContextMenuButton { + String name; + Runnable onClick; + + boolean reloadOnClick; + + public ContextMenuButton(String name, Runnable onClick) { + this.name = name; + this.onClick = onClick; + this.reloadOnClick = true; + } + + public ContextMenuButton(String name, Runnable onClick, boolean reloadOnClick) { + this.name = name; + this.onClick = onClick; + this.reloadOnClick = reloadOnClick; + } + + public Runnable getOnClick() { + if(reloadOnClick) { + return () -> { + onClick.run(); + if(DFScript.MC.currentScreen instanceof ScriptEditScreen editScreen) + { + editScreen.reload(); + } + }; + } + + return onClick; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddActionScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddActionScreen.java deleted file mode 100644 index dba89ce..0000000 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddActionScreen.java +++ /dev/null @@ -1,105 +0,0 @@ -package io.github.techstreet.dfscript.screen.script; - -import io.github.techstreet.dfscript.DFScript; -import io.github.techstreet.dfscript.screen.CScreen; -import io.github.techstreet.dfscript.screen.widget.CItem; -import io.github.techstreet.dfscript.script.Script; -import io.github.techstreet.dfscript.script.action.ScriptAction; -import io.github.techstreet.dfscript.script.action.ScriptActionCategory; -import io.github.techstreet.dfscript.script.action.ScriptActionCategoryExtra; -import io.github.techstreet.dfscript.script.action.ScriptActionType; -import io.github.techstreet.dfscript.script.event.ScriptEvent; -import io.github.techstreet.dfscript.script.event.ScriptEventType; -import java.util.ArrayList; -import java.util.List; - -public class ScriptAddActionScreen extends CScreen { - - private final Script script; - private final int insertIndex; - - public ScriptAddActionScreen(Script script, int insertIndex, ScriptActionCategory category) { - super(size(category), size(category)); - int size = size(category); - this.script = script; - this.insertIndex = insertIndex; - - int x = 3; - int y = 3; - - if (category == null) { - for (ScriptEventType type : ScriptEventType.values()) { - CItem item = new CItem(x, y, type.getIcon()); - item.setClickListener((btn) -> { - ScriptEvent event = new ScriptEvent(type); - script.getParts().add(insertIndex, event); - DFScript.MC.setScreen(new ScriptEditScreen(script)); - }); - widgets.add(item); - x += 10; - if (x >= size - 10) { - x = 3; - y += 10; - } - } - } - - if (category != null) - { - for(ScriptActionCategoryExtra extra : category.getExtras()) { - CItem item = new CItem(x, y, extra.getIcon()); - item.setClickListener((btn) -> { - script.getParts().add(insertIndex, extra.getPart()); - DFScript.MC.setScreen(new ScriptEditScreen(script)); - }); - widgets.add(item); - x += 10; - if (x >= size-10) { - x = 3; - y += 10; - } - } - } - - for (ScriptActionType type : ScriptActionType.values()) { - if (type.getCategory() != category) continue; - if (type.isDeprecated()) continue; - - CItem item = new CItem(x, y, type.getIcon()); - item.setClickListener((btn) -> { - ScriptAction action = new ScriptAction(type, new ArrayList<>()); - script.getParts().add(insertIndex, action); - if (action.getType().hasChildren()) { - script.getParts().add(insertIndex + 1, new ScriptAction(ScriptActionType.CLOSE_BRACKET, List.of())); - } - DFScript.MC.setScreen(new ScriptEditScreen(script)); - }); - widgets.add(item); - x += 10; - if (x >= size-10) { - x = 3; - y += 10; - } - } - } - - private static int size(ScriptActionCategory category) { - int amount = 0; - if (category == null) { - amount = ScriptEventType.values().length; - } else { - amount += category.getExtras().size(); - for (ScriptActionType type : ScriptActionType.values()) { - if (type.getCategory() == category) { - amount++; - } - } - } - return (int) (Math.ceil(Math.sqrt(amount))*10)+4; - } - - @Override - public void close() { - DFScript.MC.setScreen(new ScriptActionCategoryScreen(script, insertIndex)); - } -} diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddArgumentScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddArgumentScreen.java index cc2941d..9d4babd 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddArgumentScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddArgumentScreen.java @@ -5,6 +5,8 @@ import io.github.techstreet.dfscript.screen.widget.CItem; import io.github.techstreet.dfscript.screen.widget.CTextField; import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptParametrizedPart; +import io.github.techstreet.dfscript.script.ScriptPart; import io.github.techstreet.dfscript.script.action.ScriptAction; import io.github.techstreet.dfscript.script.argument.ScriptNumberArgument; import io.github.techstreet.dfscript.script.argument.ScriptTextArgument; @@ -17,9 +19,9 @@ public class ScriptAddArgumentScreen extends CScreen { private final Script script; - private final ScriptAction action; + private final ScriptParametrizedPart action; - public ScriptAddArgumentScreen(Script script, ScriptAction action, int index) { + public ScriptAddArgumentScreen(Script script, ScriptParametrizedPart action, int index) { super(100, 50); this.script = script; this.action = action; @@ -57,14 +59,14 @@ public ScriptAddArgumentScreen(Script script, ScriptAction action, int index) { addText.setClickListener((btn) -> { action.getArguments().add(index, new ScriptTextArgument(input.getText())); - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); }); addNumber.setClickListener((btn) -> { try { double number = Double.parseDouble(input.getText()); action.getArguments().add(index, new ScriptNumberArgument(number)); - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); } catch (Exception err) { input.textColor = 0xFF3333; } @@ -72,7 +74,7 @@ public ScriptAddArgumentScreen(Script script, ScriptAction action, int index) { addVariable.setClickListener((btn) -> { action.getArguments().add(index, new ScriptVariableArgument(input.getText())); - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); }); addClientValue.setClickListener((btn) -> { @@ -93,6 +95,6 @@ public ScriptAddArgumentScreen(Script script, ScriptAction action, int index) { @Override public void close() { - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); } } diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddClientValueScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddClientValueScreen.java index a202d84..fe6484b 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddClientValueScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddClientValueScreen.java @@ -4,17 +4,19 @@ import io.github.techstreet.dfscript.screen.CScreen; import io.github.techstreet.dfscript.screen.widget.CItem; import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptParametrizedPart; +import io.github.techstreet.dfscript.script.ScriptPart; import io.github.techstreet.dfscript.script.action.ScriptAction; import io.github.techstreet.dfscript.script.argument.ScriptClientValueArgument; public class ScriptAddClientValueScreen extends CScreen { private final Script script; - private final ScriptAction action; + private final ScriptParametrizedPart action; private final int insertIndex; private static final int WIDTH = 55; - public ScriptAddClientValueScreen(ScriptAction action, Script script, int insertIndex) { + public ScriptAddClientValueScreen(ScriptParametrizedPart action, Script script, int insertIndex) { super(WIDTH, 52); this.script = script; this.action = action; @@ -26,7 +28,7 @@ public ScriptAddClientValueScreen(ScriptAction action, Script script, int insert CItem item = new CItem(x, y, arg.getIcon()); item.setClickListener((btn) -> { action.getArguments().add(insertIndex, arg); - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); }); widgets.add(item); x += 10; diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddConfigValueScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddConfigValueScreen.java index 89422cf..11a6072 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddConfigValueScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddConfigValueScreen.java @@ -5,20 +5,21 @@ import io.github.techstreet.dfscript.screen.widget.CItem; import io.github.techstreet.dfscript.screen.widget.CScrollPanel; import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptParametrizedPart; +import io.github.techstreet.dfscript.script.ScriptPart; import io.github.techstreet.dfscript.script.action.ScriptAction; -import io.github.techstreet.dfscript.script.argument.ScriptClientValueArgument; import io.github.techstreet.dfscript.script.argument.ScriptConfigArgument; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; public class ScriptAddConfigValueScreen extends CScreen { private final Script script; - private final ScriptAction action; + private final ScriptParametrizedPart action; private final int insertIndex; private static int WIDTH = 200; private static int HEIGHT = 94; - public ScriptAddConfigValueScreen(ScriptAction action, Script script, int insertIndex) { + public ScriptAddConfigValueScreen(ScriptParametrizedPart action, Script script, int insertIndex) { super(WIDTH, HEIGHT); this.script = script; this.action = action; @@ -32,7 +33,7 @@ public ScriptAddConfigValueScreen(ScriptAction action, Script script, int insert CItem item = new CItem(x, y, arg.getIcon()); item.setClickListener((btn) -> { this.action.getArguments().add(insertIndex, new ScriptConfigArgument(arg.getName(), this.script)); - DFScript.MC.setScreen(new ScriptEditActionScreen(this.action, this.script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(this.action, this.script)); }); panel.add(item); x += 10; diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddHeaderScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddHeaderScreen.java new file mode 100644 index 0000000..9203514 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddHeaderScreen.java @@ -0,0 +1,64 @@ +package io.github.techstreet.dfscript.screen.script; + +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.CScreen; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.action.ScriptAction; +import io.github.techstreet.dfscript.script.action.ScriptActionCategory; +import io.github.techstreet.dfscript.script.action.ScriptActionCategoryExtra; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.event.ScriptEvent; +import io.github.techstreet.dfscript.script.event.ScriptEventType; +import io.github.techstreet.dfscript.script.event.ScriptHeaderCategory; + +import java.util.ArrayList; +import java.util.List; + +public class ScriptAddHeaderScreen extends CScreen { + + private final Script script; + private final int insertIndex; + + public ScriptAddHeaderScreen(Script script, int insertIndex, ScriptHeaderCategory category) { + super(size(category), size(category)); + int size = size(category); + this.script = script; + this.insertIndex = insertIndex; + + int x = 3; + int y = 3; + + for (ScriptEventType type : ScriptEventType.values()) { + //if (type.getCategory() != category) continue; + + CItem item = new CItem(x, y, type.getIcon()); + item.setClickListener((btn) -> { + ScriptEvent event = new ScriptEvent(type); + script.getHeaders().add(insertIndex, event); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size-10) { + x = 3; + y += 10; + } + } + } + + private static int size(ScriptHeaderCategory category) { + int amount = 0; + for (ScriptEventType type : ScriptEventType.values()) { + //if (type.getCategory() != category) continue; + + amount++; + } + return (int) (Math.ceil(Math.sqrt(amount))*10)+4; + } + + @Override + public void close() { + DFScript.MC.setScreen(new ScriptHeaderCategoryScreen(script, insertIndex)); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddPartScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddPartScreen.java new file mode 100644 index 0000000..5db88fc --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptAddPartScreen.java @@ -0,0 +1,150 @@ +package io.github.techstreet.dfscript.screen.script; + +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.CScreen; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptSnippet; +import io.github.techstreet.dfscript.script.action.*; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.conditions.ScriptBuiltinCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptConditionType; +import io.github.techstreet.dfscript.script.event.ScriptEventType; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetitionType; + +import java.util.ArrayList; + +public class ScriptAddPartScreen extends CScreen { + + private final Script script; + + private final ScriptSnippet snippet; + private final int insertIndex; + + public ScriptAddPartScreen(Script script, ScriptSnippet snippet, int insertIndex, ScriptActionCategory category) { + super(size(category), size(category)); + int size = size(category); + this.script = script; + this.insertIndex = insertIndex; + this.snippet = snippet; + + int x = 3; + int y = 3; + + /*if (category == null) { + for (ScriptEventType type : ScriptEventType.values()) { + CItem item = new CItem(x, y, type.getIcon()); + item.setClickListener((btn) -> { + ScriptEvent event = new ScriptEvent(type); + script.getParts().add(insertIndex, event); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size - 10) { + x = 3; + y += 10; + } + } + }*/ + + if (category != null) + { + for(ScriptActionCategoryExtra extra : category.getExtras()) { + CItem item = new CItem(x, y, extra.getIcon()); + item.setClickListener((btn) -> { + snippet.add(insertIndex, extra.getPart()); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size-10) { + x = 3; + y += 10; + } + } + } + + for (ScriptActionType type : ScriptActionType.values()) { + if (type.getCategory() != category) continue; + if (type.isDeprecated()) continue; + + CItem item = new CItem(x, y, type.getIcon()); + item.setClickListener((btn) -> { + ScriptAction action = new ScriptBuiltinAction(type, new ArrayList<>()); + snippet.add(insertIndex, action); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size-10) { + x = 3; + y += 10; + } + } + + for (ScriptConditionType type : ScriptConditionType.values()) { + if (type.getCategory() != category) continue; + if (type.isDeprecated()) continue; + + CItem item = new CItem(x, y, type.getIcon()); + item.setClickListener((btn) -> { + ScriptBranch action = new ScriptBranch(new ArrayList<>(), new ScriptBuiltinCondition(type)); + snippet.add(insertIndex, action); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size-10) { + x = 3; + y += 10; + } + } + + for (ScriptRepetitionType type : ScriptRepetitionType.values()) { + if (type.getCategory() != category) continue; + if (type.isDeprecated()) continue; + + CItem item = new CItem(x, y, type.getIcon()); + item.setClickListener((btn) -> { + ScriptBuiltinRepetition action = new ScriptBuiltinRepetition(new ArrayList<>(), type); + snippet.add(insertIndex, action); + DFScript.MC.setScreen(new ScriptEditScreen(script)); + }); + widgets.add(item); + x += 10; + if (x >= size-10) { + x = 3; + y += 10; + } + } + } + + private static int size(ScriptActionCategory category) { + int amount = 0; + amount += category.getExtras().size(); + for (ScriptActionType type : ScriptActionType.values()) { + if (type.getCategory() == category) { + amount++; + } + } + for (ScriptConditionType type : ScriptConditionType.values()) { + if (type.getCategory() == category) { + amount++; + } + } + for (ScriptRepetitionType type : ScriptRepetitionType.values()) { + if (type.getCategory() == category) { + amount++; + } + } + return (int) (Math.ceil(Math.sqrt(amount))*10)+4; + } + + @Override + public void close() { + DFScript.MC.setScreen(new ScriptPartCategoryScreen(script, snippet, insertIndex)); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditActionScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditPartScreen.java similarity index 95% rename from src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditActionScreen.java rename to src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditPartScreen.java index 2edb3cf..b2366b3 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditActionScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditPartScreen.java @@ -7,7 +7,8 @@ import io.github.techstreet.dfscript.screen.widget.CText; import io.github.techstreet.dfscript.screen.widget.CWidget; import io.github.techstreet.dfscript.script.Script; -import io.github.techstreet.dfscript.script.action.ScriptAction; +import io.github.techstreet.dfscript.script.ScriptParametrizedPart; +import io.github.techstreet.dfscript.script.ScriptPart; import io.github.techstreet.dfscript.script.argument.*; import java.awt.Rectangle; @@ -23,12 +24,12 @@ import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; -public class ScriptEditActionScreen extends CScreen { +public class ScriptEditPartScreen extends CScreen { private final Script script; private final List contextMenu = new ArrayList<>(); - public ScriptEditActionScreen(ScriptAction action, Script script) { + public ScriptEditPartScreen(ScriptParametrizedPart action, Script script) { super(90, 100); this.script = script; @@ -91,7 +92,7 @@ public boolean mouseClicked(double x, double y, int button) { }); CButton delete = new CButton((int) x, (int) y + 16, 40, 8, "Delete", () -> { action.getArguments().remove(currentIndex); - DFScript.MC.setScreen(new ScriptEditActionScreen(action, script)); + DFScript.MC.setScreen(new ScriptEditPartScreen(action, script)); }); DFScript.MC.send(() -> { widgets.add(insertBefore); diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditScreen.java index 4687d76..bfde1c8 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditScreen.java @@ -2,6 +2,7 @@ import io.github.techstreet.dfscript.DFScript; import io.github.techstreet.dfscript.screen.CScreen; +import io.github.techstreet.dfscript.screen.ContextMenuButton; import io.github.techstreet.dfscript.screen.widget.*; import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.ScriptComment; @@ -13,6 +14,9 @@ import java.awt.Rectangle; import java.util.ArrayList; import java.util.List; + +import io.github.techstreet.dfscript.script.event.ScriptHeader; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.math.MatrixStack; @@ -31,14 +35,16 @@ public class ScriptEditScreen extends CScreen { private final Script script; private static int scroll = 0; - private final static int width = 125; - private final CScrollPanel panel; + public final static int width = 125; + private CScrollPanel panel; private final List contextMenu = new ArrayList<>(); public ScriptEditScreen(Script script) { super(width, 100); this.script = script; - panel = new CScrollPanel(0, 3, 120, 94); + + reload(); + /*panel = new CScrollPanel(0, 3, 120, 94); //CTextField description = new CTextField(script.getDescription(), 3, 3, 115, 20, true); //description.setChangedListener(() -> script.setDescription(description.getText())); @@ -252,6 +258,90 @@ public boolean mouseClicked(double x, double y, int button) { }); panel.add(add); + panel.setScroll(scroll);*/ + } + + public void reload() + { + clearContextMenu(); + widgets.clear(); + + if(panel != null) + { + scroll = panel.getScroll(); + } + + panel = new CScrollPanel(0, 3, 120, 94); + widgets.add(panel); + + int y = 0; + int index = 0; + + CText name = new CText(5,y+2,Text.literal(script.getName()),0,1,false,false); + panel.add(name); + + CButton settings = new CTexturedButton(120-8, y, 8, 8, DFScript.MOD_ID + ":settings.png", () -> { + DFScript.MC.setScreen(new ScriptSettingsScreen(this.script, true)); + }, 0, 0, 1, 0.5f, 0, 0.5f); + panel.add(settings); + + y += 10; + + for(ScriptHeader header : script.getHeaders()) { + int origY = y; + y = header.create(panel, y, index, script); + int currentIndex = index; + panel.add(new CButton(5, origY-1, 115, 10, "",() -> {}) { + @Override + public void render(MatrixStack stack, int mouseX, int mouseY, float tickDelta) { + Rectangle b = getBounds(); + + if (b.contains(mouseX, mouseY)) { + int color = 0x33000000; + + DrawableHelper.fill(stack, b.x, b.y, b.x + b.width, b.y + b.height, color); + } + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (getBounds().contains(x, y)) { + DFScript.MC.getSoundManager().play(PositionedSoundInstance.ambient(SoundEvents.UI_BUTTON_CLICK, 1f,1f)); + + if (button != 0) { + CButton insertBefore = new CButton((int) x, (int) y, 40, 8, "Insert Before", () -> { + DFScript.MC.setScreen(new ScriptHeaderCategoryScreen(script, currentIndex)); + }); + CButton insertAfter = new CButton((int) x, (int) y+8, 40, 8, "Insert After", () -> { + DFScript.MC.setScreen(new ScriptHeaderCategoryScreen(script, currentIndex + 1)); + }); + CButton delete = new CButton((int) x, (int) y+16, 40, 8, "Delete", () -> { + script.getHeaders().remove(currentIndex); + reload(); + }); + DFScript.MC.send(() -> { + panel.add(insertBefore); + panel.add(insertAfter); + panel.add(delete); + contextMenu.add(insertBefore); + contextMenu.add(insertAfter); + contextMenu.add(delete); + }); + } + return true; + } + return false; + } + }); + index++; + } + + CButton add = new CButton(37, y, 46, 8, "Add Header", () -> { + DFScript.MC.setScreen(new ScriptHeaderCategoryScreen(script, script.getHeaders().size())); + }); + + panel.add(add); + panel.setScroll(scroll); } @@ -294,4 +384,27 @@ private void clearContextMenu() { } contextMenu.clear(); } + + public void contextMenu(int x, int y, List contextMenuButtons) { + clearContextMenu(); + + int maxWidth = 0; + + for(ContextMenuButton w : contextMenuButtons) + { + TextRenderer t = DFScript.MC.textRenderer; + int width = t.getWidth(w.getName())/2 + 4; + + if(width > maxWidth) maxWidth = width; + } + + for(ContextMenuButton w : contextMenuButtons) + { + CButton button = new CButton(x, y, maxWidth, 8, w.getName(), w.getOnClick()); + y += 8; + + panel.add(button); + contextMenu.add(button); + } + } } diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditSettingScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditSettingScreen.java index 1fa358f..a2c4c6a 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditSettingScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptEditSettingScreen.java @@ -27,7 +27,7 @@ public ScriptEditSettingScreen(Script script, ScriptNamedOption o) { if(script.optionExists(input.getText())) { input.textColor = 0xFF3333; } else { - script.replaceOption(option.getName(), input.getText()); + //script.replaceOption(option.getName(), input.getText()); option.setName(input.getText()); close(); } diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptActionCategoryScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptHeaderCategoryScreen.java similarity index 60% rename from src/main/java/io/github/techstreet/dfscript/screen/script/ScriptActionCategoryScreen.java rename to src/main/java/io/github/techstreet/dfscript/screen/script/ScriptHeaderCategoryScreen.java index cdcd562..4a21648 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptActionCategoryScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptHeaderCategoryScreen.java @@ -5,43 +5,34 @@ import io.github.techstreet.dfscript.screen.widget.CItem; import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.action.ScriptActionCategory; +import io.github.techstreet.dfscript.script.event.ScriptHeaderCategory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.text.Style; import net.minecraft.text.Text; -public class ScriptActionCategoryScreen extends CScreen { +public class ScriptHeaderCategoryScreen extends CScreen { private static final int size; static { - size = (int) (Math.ceil(Math.sqrt(ScriptActionCategory.values().length + 1)) * 10)+4; + size = (int) (Math.ceil(Math.sqrt(ScriptHeaderCategory.values().length)) * 10)+4; } private final Script script; - public ScriptActionCategoryScreen(Script script, int insertIndex) { + public ScriptHeaderCategoryScreen(Script script, int insertIndex) { super(size, size); this.script = script; - ItemStack eventsItem = new ItemStack(Items.DIAMOND); - eventsItem.setCustomName(Text.literal("Events").fillStyle(Style.EMPTY.withItalic(false))); - int x = 3; int y = 3; - CItem item = new CItem(x, y, eventsItem); - widgets.add(item); - - item.setClickListener(btn -> DFScript.MC.setScreen(new ScriptAddActionScreen(script, insertIndex, null))); - - x += 10; - - for (ScriptActionCategory category : ScriptActionCategory.values()) { + for (ScriptHeaderCategory category : ScriptHeaderCategory.values()) { CItem actionItem = new CItem(x, y, category.getIcon()); widgets.add(actionItem); - actionItem.setClickListener(btn -> DFScript.MC.setScreen(new ScriptAddActionScreen(script, insertIndex, category))); + actionItem.setClickListener(btn -> DFScript.MC.setScreen(new ScriptAddHeaderScreen(script, insertIndex, category))); x += 10; if (x >= size - 10) { diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptPartCategoryScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptPartCategoryScreen.java new file mode 100644 index 0000000..6ad6b20 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptPartCategoryScreen.java @@ -0,0 +1,45 @@ +package io.github.techstreet.dfscript.screen.script; + +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.CScreen; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptSnippet; +import io.github.techstreet.dfscript.script.action.ScriptActionCategory; + +public class ScriptPartCategoryScreen extends CScreen { + + private static final int size; + + static { + size = (int) (Math.ceil(Math.sqrt(ScriptActionCategory.values().length)) * 10)+4; + } + + private final Script script; + + public ScriptPartCategoryScreen(Script script, ScriptSnippet snippet, int insertIndex) { + super(size, size); + this.script = script; + + int x = 3; + int y = 3; + + for (ScriptActionCategory category : ScriptActionCategory.values()) { + CItem actionItem = new CItem(x, y, category.getIcon()); + widgets.add(actionItem); + + actionItem.setClickListener(btn -> DFScript.MC.setScreen(new ScriptAddPartScreen(script, snippet, insertIndex, category))); + + x += 10; + if (x >= size - 10) { + x = 3; + y += 10; + } + } + } + + @Override + public void close() { + DFScript.MC.setScreen(new ScriptEditScreen(script)); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptSettingsScreen.java b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptSettingsScreen.java index 827aaa2..fe229fa 100644 --- a/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptSettingsScreen.java +++ b/src/main/java/io/github/techstreet/dfscript/screen/script/ScriptSettingsScreen.java @@ -102,7 +102,7 @@ public boolean mouseClicked(double x, double y, int button) { DFScript.MC.setScreen(new ScriptAddSettingScreen(script, finalIndex + 1)); }); CButton delete = new CButton((int) x, (int) y+16, 40, 8, "Delete", () -> { - script.removeOption(script.getOptions().get(finalIndex).getName()); + //script.removeOption(script.getOptions().get(finalIndex).getName()); script.getOptions().remove(finalIndex); scroll = panel.getScroll(); DFScript.MC.setScreen(new ScriptSettingsScreen(script, true)); diff --git a/src/main/java/io/github/techstreet/dfscript/script/Script.java b/src/main/java/io/github/techstreet/dfscript/script/Script.java index 21f5c8d..57589a4 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/Script.java +++ b/src/main/java/io/github/techstreet/dfscript/script/Script.java @@ -12,14 +12,25 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptAction; import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; import io.github.techstreet.dfscript.script.argument.ScriptArgument; import io.github.techstreet.dfscript.script.argument.ScriptUnknownArgument; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.conditions.ScriptBuiltinCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptConditionType; +import io.github.techstreet.dfscript.script.event.ScriptEmptyHeader; +import io.github.techstreet.dfscript.script.event.ScriptEventType; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; import io.github.techstreet.dfscript.script.event.ScriptEvent; +import io.github.techstreet.dfscript.script.event.ScriptHeader; import io.github.techstreet.dfscript.script.execution.ScriptContext; import io.github.techstreet.dfscript.script.execution.ScriptPosStack; import io.github.techstreet.dfscript.script.execution.ScriptScopeVariables; import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetitionType; import io.github.techstreet.dfscript.script.values.ScriptUnknownValue; import io.github.techstreet.dfscript.script.values.ScriptValue; import io.github.techstreet.dfscript.util.chat.ChatType; @@ -34,14 +45,16 @@ import org.apache.logging.log4j.Logger; public class Script { - public static int scriptVersion = 4; + public static int scriptVersion = 5; private String name; private String owner; private String description = "N/A"; private int version = 0; private String server; - private final List parts; + // private final List parts; + + private final List headers; private final List options; private final Logger LOGGER; @@ -49,11 +62,11 @@ public class Script { private File file; private boolean disabled; - public Script(String name, String owner, String server, List parts, boolean disabled, int version) { + public Script(String name, String owner, String server, List headers, boolean disabled, int version) { this.name = name; this.owner = owner; this.server = server; - this.parts = parts; + this.headers = headers; this.disabled = disabled; this.version = version; this.options = new ArrayList<>(); @@ -71,11 +84,13 @@ public void setFile(File file) { public void invoke(Event event) { int pos = 0; - for (ScriptPart part : parts) { + for (ScriptHeader part : headers) { if (part instanceof ScriptEvent se) { if (se.getType().getCodeutilitiesEvent().equals(event.getClass())) { try { - this.execute(new ScriptTask(new ScriptPosStack(pos+1), event,this)); + ScriptTask task = new ScriptTask(event,this); + se.run(task); + task.run(); } catch (Exception err) { ChatUtil.sendMessage("Error while invoking event " + se.getType().getName() + " in script " + name + ": " + err.getMessage(), ChatType.FAIL); LOGGER.error("Error while invoking event " + se.getType().getName(), err); @@ -87,7 +102,7 @@ public void invoke(Event event) { } } - public void execute(ScriptTask task) { + /*public void execute(ScriptTask task) { if (disabled) { // don't run the code if it's disabled obviously return; } @@ -201,9 +216,10 @@ private boolean endScope(ScriptTask task) { } return false; - } - public List getParts() { - return parts; + } */ + + public List getHeaders() { + return headers; } public String getName() { @@ -259,15 +275,20 @@ public ScriptContext getContext() { } public void replaceAction(ScriptActionType oldAction, ScriptActionType newAction) { - for(int i = 0; i < parts.size(); i++) - { - if(parts.get(i) instanceof ScriptAction) - { - if(((ScriptAction) parts.get(i)).getType() == oldAction) - { - parts.set(i, ((ScriptAction) parts.get(i)).setType(newAction)); - } - } + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.replaceAction(oldAction, newAction)); + } + } + + public void replaceCondition(ScriptConditionType oldCondition, ScriptConditionType newCondition) { + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.replaceCondition(oldCondition, newCondition)); + } + } + + public void replaceRepetition(ScriptRepetitionType oldRepetition, ScriptRepetitionType newRepetition) { + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.replaceRepetition(oldRepetition, newRepetition)); } } @@ -319,26 +340,20 @@ public ScriptNamedOption getNamedOption(String option) { } private void updateScriptReferences() { - for(ScriptPart part : getParts()) { - if(part instanceof ScriptAction a) { - a.updateScriptReferences(this); - } + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.updateScriptReferences(this)); } } public void replaceOption(String oldOption, String newOption) { - for(ScriptPart part : getParts()) { - if(part instanceof ScriptAction a) { - a.updateConfigArguments(oldOption, newOption); - } + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.replaceOption(oldOption, newOption)); } } public void removeOption(String option) { - for(ScriptPart part : getParts()) { - if(part instanceof ScriptAction a) { - a.removeConfigArguments(option); - } + for(ScriptHeader header : headers) { + header.forEach((snippet) -> snippet.removeOption(option)); } } @@ -357,18 +372,26 @@ public Script deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon String description = "N/A"; if (object.get("description") != null) description = object.get("description").getAsString(); - List parts = new ArrayList<>(); - for (JsonElement element : object.get("actions").getAsJsonArray()) { - ScriptPart part = context.deserialize(element, ScriptPart.class); - parts.add(part); + List headers = new ArrayList<>(); + + if(object.has("actions")) { + JsonArray parts = object.get("actions").getAsJsonArray(); + legacyDeserialize(headers, parts, context); + } + else { + for (JsonElement element : object.get("headers").getAsJsonArray()) { + ScriptHeader header = context.deserialize(element, ScriptHeader.class); + headers.add(header); + } } + boolean disabled = object.has("disabled") && object.get("disabled").getAsBoolean(); int version = 0; if (object.get("version") != null) version = object.get("version").getAsInt(); - Script script = new Script(name, owner, serverId, parts, disabled, version); + Script script = new Script(name, owner, serverId, headers, disabled, version); script.setDescription(description); if (object.get("config") != null) for (JsonElement element : object.get("config").getAsJsonArray()) { @@ -390,7 +413,7 @@ public JsonElement serialize(Script src, Type typeOfSrc, JsonSerializationContex object.addProperty("description", src.description); JsonArray array = new JsonArray(); - for (ScriptPart part : src.getParts()) { + for (ScriptHeader part : src.getHeaders()) { array.add(context.serialize(part)); } @@ -399,11 +422,123 @@ public JsonElement serialize(Script src, Type typeOfSrc, JsonSerializationContex config.add(context.serialize(option)); } - object.add("actions", array); + object.add("headers", array); object.add("config", config); object.addProperty("disabled", src.disabled); object.addProperty("version", src.version); return object; } + + public static void legacyDeserialize(List headers, JsonArray parts, JsonDeserializationContext context) { + int pos = 0; + + while(pos < parts.size()) { + ScriptHeader header; + + JsonObject obj = parts.get(pos).getAsJsonObject(); + String type = obj.get("type").getAsString(); + + DFScript.LOGGER.info(pos); + DFScript.LOGGER.info(obj); + + if(Objects.equals(type, "event")) { + header = new ScriptEvent(ScriptEventType.valueOf(obj.get("event").getAsString())); + pos++; + } + else { + header = new ScriptEmptyHeader(); + } + + ScriptSnippet snippet = new ScriptSnippet(); + pos = legacyDeserializeActions(pos, parts, snippet, context); + + if(snippet.size() > 0) { + header.container().setSnippet(0, snippet); + headers.add(header); + } + } + } + + private static int legacyDeserializeActions(int pos, JsonArray parts, ScriptSnippet snippet, JsonDeserializationContext context) { + boolean parity = false; + + while(pos < parts.size()) { + JsonObject obj = parts.get(pos).getAsJsonObject(); + String type = obj.get("type").getAsString(); + boolean breakOut = false; + switch(type) { + case "event" -> { + breakOut = true; + } + case "comment" -> { + parity = false; + ScriptComment comment = new ScriptComment(obj.get("comment").getAsString()); + snippet.add(comment); + } + case "action" -> { + String action = obj.get("action").getAsString(); + + switch(action) { + case "CLOSE_BRACKET" -> { + breakOut = true; + } + case "ELSE" -> { + ScriptPart latestPart = snippet.get(snippet.size()-1); + + ScriptSnippet elseSnippet = new ScriptSnippet(); + + pos = legacyDeserializeActions(pos+1, parts, elseSnippet, context); + + if(latestPart instanceof ScriptBranch b) { + if(!b.hasElse()) b.setHasElse(); + b.container().getSnippet(parity ? 0 : 1).addAll(elseSnippet); + parity = !parity; + } + else { + ScriptCondition condition = new ScriptBuiltinCondition(ScriptConditionType.TRUE).invert(); + ScriptBranch b = new ScriptBranch(new ArrayList<>(), condition); + snippet.add(b); + } + } + default -> { + parity = false; + + List args = new ArrayList<>(); + for (JsonElement arg : obj.get("arguments").getAsJsonArray()) { + args.add(context.deserialize(arg, ScriptArgument.class)); + } + + try { + ScriptActionType innerType = ScriptActionType.valueOf(action); + + snippet.add(new ScriptBuiltinAction(innerType, args)); + } + catch(IllegalArgumentException e) { + ScriptSnippet innerSnippet = new ScriptSnippet(); + pos = legacyDeserializeActions(pos+1, parts, innerSnippet, context); + + try { + ScriptRepetitionType innerType = ScriptRepetitionType.valueOf(action); + ScriptBuiltinRepetition part = new ScriptBuiltinRepetition(args, innerType); + part.container().setSnippet(0, innerSnippet); + snippet.add(part); + } + catch(IllegalArgumentException e2) { + ScriptConditionType innerType = ScriptConditionType.valueOf(action); + ScriptBranch part = new ScriptBranch(args, new ScriptBuiltinCondition(innerType)); + part.container().setSnippet(0, innerSnippet); + snippet.add(part); + } + } + } + } + } + } + if(breakOut) break; + pos++; + } + + return pos; + } } } diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptComment.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptComment.java index 2b4f8ce..621c61e 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/ScriptComment.java +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptComment.java @@ -4,22 +4,22 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.github.techstreet.dfscript.event.system.Event; -import io.github.techstreet.dfscript.script.action.ScriptActionType; -import io.github.techstreet.dfscript.script.argument.ScriptArgument; -import io.github.techstreet.dfscript.script.argument.ScriptConfigArgument; -import io.github.techstreet.dfscript.script.execution.ScriptActionContext; -import io.github.techstreet.dfscript.script.execution.ScriptContext; -import io.github.techstreet.dfscript.script.execution.ScriptScopeVariables; +import io.github.techstreet.dfscript.screen.script.ScriptEditScreen; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CTextField; import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderDynamicElement; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.Style; +import net.minecraft.text.Text; import java.lang.reflect.Type; -import java.util.HashMap; import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -public class ScriptComment implements ScriptPart { +public class ScriptComment extends ScriptPart { private String comment; @@ -38,8 +38,26 @@ public String getComment() { } @Override - public ScriptGroup getGroup() { - return ScriptGroup.COMMENT; + public void run(ScriptTask task) { + + } + + @Override + public void create(ScriptPartRender render, Script script) { + render.addElement(new ScriptPartRenderDynamicElement((args) -> { + int y = args.y(); + int indent = args.indent(); + CScrollPanel panel = args.panel(); + + panel.add(new CItem(5+indent*5, y, new ItemStack(Items.MAP).setCustomName(Text.literal("Comment").setStyle(Style.EMPTY.withItalic(false))))); + + CTextField cTextField = new CTextField(getComment(),15+indent*5, y-1, ScriptEditScreen.width-(15+indent*5)-5, 10, true); + + cTextField.setChangedListener(() -> setComment(cTextField.getText())); + + panel.add(cTextField); + return y+10; + })); } public static class Serializer implements JsonSerializer { diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptContainer.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptContainer.java new file mode 100644 index 0000000..6454a4d --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptContainer.java @@ -0,0 +1,51 @@ +package io.github.techstreet.dfscript.script; + +import com.google.gson.JsonElement; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderSnippetElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +public class ScriptContainer { + List snippets; + + public ScriptContainer(int snippetCount) { + snippets = new ArrayList<>(); + for(int i = 0; i < snippetCount; i++) { + snippets.add(new ScriptSnippet()); + } + } + + public void runSnippet(ScriptTask task, int snippetIndex, ScriptScopeParent parent) + { + snippets.get(snippetIndex).run(task, parent); + } + + public ScriptPartRenderSnippetElement createSnippet(int snippetIndex) { + return new ScriptPartRenderSnippetElement(snippets.get(snippetIndex)); + } + + public void forEach(Consumer consumer) { + for(ScriptSnippet snippet : snippets) { + consumer.accept(snippet); + } + } + + public int createSnippet(int snippetIndex, CScrollPanel panel, int y, int indent, Script script) { + return snippets.get(snippetIndex).create(panel, y, indent, script); + } + + public void setSnippet(int snippetIndex, ScriptSnippet snippet) { + snippets.set(snippetIndex, snippet); + } + + public ScriptSnippet getSnippet(int snippetIndex) { + return snippets.get(snippetIndex); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptManager.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptManager.java index dd94672..b6f5326 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/ScriptManager.java +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptManager.java @@ -9,10 +9,18 @@ import io.github.techstreet.dfscript.loader.Loadable; import io.github.techstreet.dfscript.screen.script.ScriptAddScreen; import io.github.techstreet.dfscript.script.action.ScriptAction; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; import io.github.techstreet.dfscript.script.argument.*; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.conditions.ScriptBuiltinCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptCondition; +import io.github.techstreet.dfscript.script.event.ScriptEmptyHeader; import io.github.techstreet.dfscript.script.event.ScriptEvent; +import io.github.techstreet.dfscript.script.event.ScriptHeader; import io.github.techstreet.dfscript.script.event.ScriptStartUpEvent; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetition; import io.github.techstreet.dfscript.util.FileUtil; import io.github.techstreet.dfscript.util.chat.ChatType; import io.github.techstreet.dfscript.util.chat.ChatUtil; @@ -44,9 +52,16 @@ public class ScriptManager implements Loadable { .registerTypeAdapter(ScriptClientValueArgument.class, new ScriptClientValueArgument.Serializer()) .registerTypeAdapter(ScriptConfigArgument.class, new ScriptConfigArgument.Serializer()) .registerTypeAdapter(ScriptNamedOption.class, new ScriptNamedOption.Serializer()) - .registerTypeAdapter(ScriptAction.class, new ScriptAction.Serializer()) + .registerTypeAdapter(ScriptBuiltinAction.class, new ScriptBuiltinAction.Serializer()) + .registerTypeAdapter(ScriptBuiltinCondition.class, new ScriptBuiltinCondition.Serializer()) + .registerTypeAdapter(ScriptCondition.class, new ScriptCondition.Serializer()) + .registerTypeAdapter(ScriptBuiltinRepetition.class, new ScriptBuiltinRepetition.Serializer()) + .registerTypeAdapter(ScriptBranch.class, new ScriptBranch.Serializer()) .registerTypeAdapter(ScriptEvent.class, new ScriptEvent.Serializer()) .registerTypeAdapter(ScriptComment.class, new ScriptComment.Serializer()) + .registerTypeAdapter(ScriptSnippet.class, new ScriptSnippet.Serializer()) + .registerTypeAdapter(ScriptHeader.class, new ScriptHeader.Serializer()) + .registerTypeAdapter(ScriptEmptyHeader.class, new ScriptEmptyHeader.Serializer()) .create(); public ScriptManager() { diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptMigrator.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptMigrator.java index 5c2075b..792e6d7 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/ScriptMigrator.java +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptMigrator.java @@ -30,6 +30,10 @@ public static void migrate(Script script) { script.setVersion(4); } + if (script.getVersion() == 4) { + script.setVersion(5); + } + if (previousVer != script.getVersion()) { ScriptManager.LOGGER.info("Migrated script '" + script.getName() + "' from version " + previousVer + " to version " + script.getVersion() + "!"); ScriptManager.getInstance().saveScript(script); diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptParametrizedPart.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptParametrizedPart.java new file mode 100644 index 0000000..806cd6c --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptParametrizedPart.java @@ -0,0 +1,63 @@ +package io.github.techstreet.dfscript.script; + +import com.google.gson.*; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.argument.ScriptConfigArgument; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public abstract class ScriptParametrizedPart extends ScriptPart implements ScriptRunnable { + + List arguments; + + public ScriptParametrizedPart(List arguments) { + this.arguments = arguments; + } + //ScriptGroup getGroup(); + + public List getArguments() { + return arguments; + } + + public void updateScriptReferences(Script script) { + for(ScriptArgument arg : getArguments()) { + if (arg instanceof ScriptConfigArgument carg) { + carg.setScript(script); + } + } + } + + public void updateConfigArguments(String oldOption, String newOption) { + for(ScriptArgument arg : getArguments()) { + if (arg instanceof ScriptConfigArgument carg) { + if(carg.getName() == oldOption) + { + carg.setOption(newOption); + } + } + } + } + + public void removeConfigArguments(String option) { + int index = 0; + + List argList = getArguments(); + + while(index < argList.size()) { + if (argList.get(index) instanceof ScriptConfigArgument carg) { + if(Objects.equals(carg.getName(), option)) + { + argList.remove(index); + continue; + } + } + index++; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptPart.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptPart.java index 07fecd8..13208fe 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/ScriptPart.java +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptPart.java @@ -5,20 +5,33 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import io.github.techstreet.dfscript.script.action.ScriptAction; +import io.github.techstreet.dfscript.screen.ContextMenuButton; import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; import io.github.techstreet.dfscript.script.argument.ScriptArgument; -import io.github.techstreet.dfscript.script.event.ScriptEvent; -import io.github.techstreet.dfscript.script.event.ScriptEventType; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.conditions.ScriptCondition; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetitionType; + import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; -public interface ScriptPart { +public abstract class ScriptPart implements ScriptRunnable { + + public abstract void create(ScriptPartRender render, Script script); - ScriptGroup getGroup(); + public boolean isDeprecated() { + return false; + } + + public List getContextMenu() { + return new ArrayList<>(); + } - class Serializer implements JsonDeserializer { + public static class Serializer implements JsonDeserializer { @Override public ScriptPart deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { @@ -31,11 +44,35 @@ public ScriptPart deserialize(JsonElement json, Type typeOfT, JsonDeserializatio for (JsonElement arg : obj.get("arguments").getAsJsonArray()) { args.add(context.deserialize(arg, ScriptArgument.class)); } - return new ScriptAction(ScriptActionType.valueOf(action), args); + return new ScriptBuiltinAction(ScriptActionType.valueOf(action), args); } - case "event" -> { - String event = obj.get("event").getAsString(); - return new ScriptEvent(ScriptEventType.valueOf(event)); + case "branch" -> { + boolean hasElse = obj.get("hasElse").getAsBoolean(); + List args = new ArrayList<>(); + for (JsonElement arg : obj.get("arguments").getAsJsonArray()) { + args.add(context.deserialize(arg, ScriptArgument.class)); + } + ScriptCondition condition = context.deserialize(obj.get("condition"), ScriptCondition.class); + + ScriptBranch part = new ScriptBranch(args, condition); + if(hasElse) part.setHasElse(); + + part.container().setSnippet(0, context.deserialize(obj.getAsJsonObject("true"), ScriptSnippet.class)); + part.container().setSnippet(1, context.deserialize(obj.getAsJsonObject("false"), ScriptSnippet.class)); + + return part; + } + case "repetition" -> { + String action = obj.get("repetition").getAsString(); + List args = new ArrayList<>(); + for (JsonElement arg : obj.get("arguments").getAsJsonArray()) { + args.add(context.deserialize(arg, ScriptArgument.class)); + } + ScriptBuiltinRepetition part = new ScriptBuiltinRepetition(args, ScriptRepetitionType.valueOf(action)); + + part.container().setSnippet(0, context.deserialize(obj.getAsJsonObject("snippet"), ScriptSnippet.class)); + + return part; } case "comment" -> { String comment = obj.get("comment").getAsString(); diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptRunnable.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptRunnable.java new file mode 100644 index 0000000..409ed44 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptRunnable.java @@ -0,0 +1,7 @@ +package io.github.techstreet.dfscript.script; + +import io.github.techstreet.dfscript.script.execution.ScriptTask; + +public interface ScriptRunnable { + void run(ScriptTask task); +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptScopeParent.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptScopeParent.java new file mode 100644 index 0000000..7a7ebad --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptScopeParent.java @@ -0,0 +1,10 @@ +package io.github.techstreet.dfscript.script; + +import io.github.techstreet.dfscript.script.action.ScriptActionType; + +import java.util.function.Consumer; + +public interface ScriptScopeParent { + void forEach(Consumer consumer); + ScriptContainer container(); +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/ScriptSnippet.java b/src/main/java/io/github/techstreet/dfscript/script/ScriptSnippet.java new file mode 100644 index 0000000..746eef2 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/ScriptSnippet.java @@ -0,0 +1,234 @@ +package io.github.techstreet.dfscript.script; + +import com.google.gson.*; +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.screen.ContextMenuButton; +import io.github.techstreet.dfscript.screen.script.ScriptEditPartScreen; +import io.github.techstreet.dfscript.screen.script.ScriptEditScreen; +import io.github.techstreet.dfscript.screen.script.ScriptPartCategoryScreen; +import io.github.techstreet.dfscript.screen.widget.CButton; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CWidget; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.conditions.ScriptBuiltinCondition; +import io.github.techstreet.dfscript.script.conditions.ScriptConditionType; +import io.github.techstreet.dfscript.script.event.ScriptEvent; +import io.github.techstreet.dfscript.script.event.ScriptEventType; +import io.github.techstreet.dfscript.script.event.ScriptHeader; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetitionType; +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 javax.naming.Context; +import java.awt.*; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +public class ScriptSnippet extends ArrayList { + ScriptSnippet() { + + } + + public void run(ScriptTask task, ScriptScopeParent parent) + { + task.stack().push(this, parent); + } + + public int create(CScrollPanel panel, int y, int indent, Script script) { + int index = 0; + ScriptSnippet thisSnippet = this; + for(ScriptPart part : this) { + ScriptPartRender render = new ScriptPartRender(); + part.create(render, script); + y = render.create(panel, y, indent, script); + int currentIndex = index; + for (var buttonPos : render.getButtonPositions()) { + panel.add(new CButton(5, buttonPos.getY() - 1, 115, buttonPos.height(), "", () -> { + }) { + @Override + public void render(MatrixStack stack, int mouseX, int mouseY, float tickDelta) { + Rectangle b = getBounds(); + int color = 0; + boolean drawFill = false; + if (b.contains(mouseX, mouseY)) { + drawFill = true; + color = 0x33000000; + + if (part.isDeprecated()) { + color = 0x80FF0000; + } + + + } else { + if (part.isDeprecated()) { + drawFill = true; + color = 0x33FF0000; + } + } + + if(drawFill) { + for(var renderButtonPos : render.getButtonPositions()) { + DrawableHelper.fill(stack, b.x, renderButtonPos.y()-1, b.x + b.width, renderButtonPos.y()-1 + renderButtonPos.height(), color); + } + } + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (getBounds().contains(x, y)) { + DFScript.MC.getSoundManager().play(PositionedSoundInstance.ambient(SoundEvents.UI_BUTTON_CLICK, 1f, 1f)); + + if (button == 0) { + if(part instanceof ScriptParametrizedPart parametrizedPart) + DFScript.MC.setScreen(new ScriptEditPartScreen(parametrizedPart, script)); + if(part instanceof ScriptComment) + return false; + } else { + List contextMenu = new ArrayList<>(); + contextMenu.add(new ContextMenuButton("Insert Before", () -> { + DFScript.MC.setScreen(new ScriptPartCategoryScreen(script, thisSnippet, currentIndex)); + }, false)); + contextMenu.add(new ContextMenuButton("Insert After", () -> { + DFScript.MC.setScreen(new ScriptPartCategoryScreen(script, thisSnippet, currentIndex + 1)); + }, false)); + contextMenu.add(new ContextMenuButton("Delete", () -> { + thisSnippet.remove(currentIndex); + })); + contextMenu.addAll(part.getContextMenu()); + DFScript.MC.send(() -> { + if(DFScript.MC.currentScreen instanceof ScriptEditScreen editScreen) + { + editScreen.contextMenu((int) x, (int) y, contextMenu); + } + }); + } + return true; + } + return false; + } + }); + } + index++; + } + + ScriptPartRender.createIndent(panel, indent, y, 8); + CButton add = new CButton((ScriptEditScreen.width-30)/2, y, 30, 8, "Add Part", () -> { + DFScript.MC.setScreen(new ScriptPartCategoryScreen(script, thisSnippet, thisSnippet.size())); + }); + + panel.add(add); + + return y+10; + } + + public void replaceAction(ScriptActionType oldAction, ScriptActionType newAction) { + for(ScriptPart part : this) { + if(part instanceof ScriptBuiltinAction a) { + if(a.getType() == oldAction) { + a.setType(newAction); + } + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.replaceAction(oldAction, newAction)); + } + } + } + + public void replaceCondition(ScriptConditionType oldCondition, ScriptConditionType newCondition) { + for(ScriptPart part : this) { + if(part instanceof ScriptBranch b) { + if(b.getCondition() instanceof ScriptBuiltinCondition c) { + if(c.getType() == oldCondition) { + c.setType(newCondition); + } + } + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.replaceCondition(oldCondition, newCondition)); + } + } + } + + public void replaceRepetition(ScriptRepetitionType oldRepetition, ScriptRepetitionType newRepetition) { + for(ScriptPart part : this) { + if(part instanceof ScriptBuiltinRepetition r) { + if(r.getType() == oldRepetition) { + r.setType(newRepetition); + } + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.replaceRepetition(oldRepetition, newRepetition)); + } + } + } + + public void updateScriptReferences(Script script) { + for(ScriptPart part : this) { + if(part instanceof ScriptParametrizedPart p) { + p.updateScriptReferences(script); + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.updateScriptReferences(script)); + } + } + } + + public void replaceOption(String oldOption, String newOption) { + for(ScriptPart part : this) { + if(part instanceof ScriptParametrizedPart p) { + p.updateConfigArguments(oldOption, newOption); + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.replaceOption(oldOption, newOption)); + } + } + } + + public void removeOption(String option) { + for(ScriptPart part : this) { + if(part instanceof ScriptParametrizedPart p) { + p.removeConfigArguments(option); + } + if(part instanceof ScriptScopeParent p) { + p.forEach((snippet) -> snippet.removeOption(option)); + } + } + } + + public static class Serializer implements JsonSerializer, JsonDeserializer { + + @Override + public ScriptSnippet deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject obj = json.getAsJsonObject(); + ScriptSnippet snippet = new ScriptSnippet(); + + for(JsonElement element : obj.getAsJsonArray("parts")) { + snippet.add(context.deserialize(element, ScriptPart.class)); + } + + return snippet; + } + + @Override + public JsonElement serialize(ScriptSnippet src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + JsonArray parts = new JsonArray(); + + for (ScriptPart part : src) { + parts.add(context.serialize(part)); + } + + obj.add("parts", parts); + return obj; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptAction.java b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptAction.java index 6f9d0a7..65eb589 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptAction.java +++ b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptAction.java @@ -4,105 +4,32 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.github.techstreet.dfscript.event.system.Event; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; import io.github.techstreet.dfscript.script.Script; -import io.github.techstreet.dfscript.script.ScriptGroup; -import io.github.techstreet.dfscript.script.ScriptPart; +import io.github.techstreet.dfscript.script.ScriptParametrizedPart; import io.github.techstreet.dfscript.script.argument.ScriptArgument; -import io.github.techstreet.dfscript.script.argument.ScriptConfigArgument; -import io.github.techstreet.dfscript.script.execution.ScriptActionContext; -import io.github.techstreet.dfscript.script.execution.ScriptContext; -import io.github.techstreet.dfscript.script.execution.ScriptScopeVariables; import io.github.techstreet.dfscript.script.execution.ScriptTask; -import io.github.techstreet.dfscript.script.options.ScriptNamedOption; -import io.github.techstreet.dfscript.util.chat.ChatUtil; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; import java.lang.reflect.Type; -import java.util.HashMap; import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -public class ScriptAction implements ScriptPart { +public class ScriptAction extends ScriptParametrizedPart { - private ScriptActionType type; - private final List arguments; - - public ScriptAction(ScriptActionType type, List arguments) { - this.type = type; - this.arguments = arguments; - } - - public ScriptAction setType(ScriptActionType newType) { - type = newType; - - return this; - } - - public void invoke(Event event, ScriptContext context, Consumer inner, ScriptTask task, Script script) { - type.run(new ScriptActionContext( - context, arguments, event, inner, task, new HashMap<>(), script - )); - } - - public ScriptActionType getType() { - return type; - } - - public List getArguments() { - return arguments; + public ScriptAction(List arguments) { + super(arguments); } @Override - public ScriptGroup getGroup() { - return getType().getGroup(); - } - - public void updateScriptReferences(Script script) { - for(ScriptArgument arg : getArguments()) { - if (arg instanceof ScriptConfigArgument carg) { - carg.setScript(script); - } - } - } + public void run(ScriptTask task) { - public void updateConfigArguments(String oldOption, String newOption) { - for(ScriptArgument arg : getArguments()) { - if (arg instanceof ScriptConfigArgument carg) { - if(carg.getName() == oldOption) - { - carg.setOption(newOption); - } - } - } } - public void removeConfigArguments(String option) { - int index = 0; - - List argList = getArguments(); - - while(index < argList.size()) { - if (argList.get(index) instanceof ScriptConfigArgument carg) { - if(Objects.equals(carg.getName(), option)) - { - argList.remove(index); - continue; - } - } - index++; - } + @Override + public boolean isDeprecated() { + return false; } - public static class Serializer implements JsonSerializer { - - @Override - public JsonElement serialize(ScriptAction src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject obj = new JsonObject(); - obj.addProperty("type", "action"); - obj.addProperty("action", src.getType().name()); - obj.add("arguments", context.serialize(src.getArguments())); - return obj; - } - } + @Override + public void create(ScriptPartRender render, Script script) {} } \ No newline at end of file diff --git a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionArgumentList.java b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionArgumentList.java new file mode 100644 index 0000000..ff1d392 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionArgumentList.java @@ -0,0 +1,75 @@ +package io.github.techstreet.dfscript.script.action; + +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; + +import java.util.ArrayList; +import java.util.List; + +public class ScriptActionArgumentList extends ArrayList { + public ScriptActionArgumentList(ScriptActionArgumentList current) { + this.addAll(current); + } + + public ScriptActionArgumentList() { + + } + + private void generatePossibilities(List possibilities, ScriptActionArgumentList current, int pos) { + if (pos >= size()) { + possibilities.add(new ScriptActionArgumentList(current)); + return; + } + + ScriptActionArgument arg = get(pos); + if (arg.optional()) { + generatePossibilities(possibilities, new ScriptActionArgumentList(current), pos + 1); + } + current.add(arg); + generatePossibilities(possibilities, current, pos + 1); + } + + public List generatePossibilities() { + List possibilities = new ArrayList<>(); + + generatePossibilities(possibilities, new ScriptActionArgumentList(), 0); + + return possibilities; + } + + public void getArgMap(ScriptActionContext ctx) { + List possibilities = generatePossibilities(); + + search: + for (List possibility : possibilities) { + int pos = 0; + ctx.argMap().clear(); + for (ScriptActionArgument arg : possibility) { + List args = new ArrayList<>(); + if (pos >= ctx.arguments().size()) { + continue search; + } + if (ctx.arguments().get(pos).convertableTo(arg.type())) { + args.add(ctx.arguments().get(pos)); + pos++; + } + if (arg.plural()) { + while (pos < ctx.arguments().size()) { + if (ctx.arguments().get(pos).convertableTo(arg.type())) { + args.add(ctx.arguments().get(pos)); + pos++; + } else { + break; + } + } + } + ctx.setArg(arg.name(), args); + } + if (pos == ctx.arguments().size()) { + return; + } + } + ctx.argMap().clear(); + throw new IllegalArgumentException(); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionCategory.java b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionCategory.java index dd80c44..84915f3 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionCategory.java +++ b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionCategory.java @@ -25,6 +25,8 @@ public enum ScriptActionCategory { DICTIONARIES("Dictionaries", Items.ENDER_CHEST), MENUS("Menus", Items.PAINTING), + + CONTROL("Control", Items.COAL) ; private final ItemStack icon; diff --git a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionType.java b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionType.java index 07c2f8a..da3d843 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionType.java +++ b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptActionType.java @@ -20,6 +20,7 @@ import io.github.techstreet.dfscript.script.menu.ScriptMenuText; import io.github.techstreet.dfscript.script.menu.ScriptMenuTextField; import io.github.techstreet.dfscript.script.menu.ScriptWidget; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetition; import io.github.techstreet.dfscript.script.util.ScriptValueItem; import io.github.techstreet.dfscript.script.util.ScriptValueJson; import io.github.techstreet.dfscript.script.values.*; @@ -119,59 +120,13 @@ public enum ScriptActionType { } })), - REPEAT_MULTIPLE(builder -> builder.name("RepeatMultiple") - .description("Repeats a specified amount of times.") - .icon(Items.REDSTONE) - .category(ScriptActionCategory.NUMBERS) - .arg("Times", ScriptActionArgumentType.NUMBER) - .arg("Current", ScriptActionArgumentType.VARIABLE, b -> b.optional(true)) - .hasChildren(true) - .group(ScriptGroup.REPETITION) - .action(ctx -> { - ctx.scheduleInner( - null, - context -> { - if(!context.hasScopeVariable("Counter")) { - context.setScopeVariable("Counter", 0); - } - - int counter = (Integer)context.getScopeVariable("Counter")+1; - - if(counter <= context.value("Times").asNumber()) { - context.setScopeVariable("Counter", counter); - if (context.argMap().containsKey("Current")) { - context.context().setVariable(context.variable("Current").name(), new ScriptNumberValue(counter)); - } - context.setLastIfResult(true); - } - } - ); - - /*if (ctx.argMap().containsKey("Current")) { - ctx.context().setVariable(ctx.variable("Current").name(), new ScriptNumberValue(1)); - } - for (int i = (int) ctx.value("Times").asNumber(); i > 0; i--) { - int current = i+1; - ctx.scheduleInner(() -> { - if (ctx.argMap().containsKey("Current")) { - ctx.context().setVariable(ctx.variable("Current").name(), new ScriptNumberValue(current)); - } - }); - }*/ - })), - - CLOSE_BRACKET(builder -> builder.name("CloseBracket") - .description("Closes the current code block.") - .icon(Items.PISTON) - .category(ScriptActionCategory.MISC)), - SET_VARIABLE(builder -> builder.name("SetVariable") .description("Sets a variable to a value.") .icon(Items.IRON_INGOT) .category(ScriptActionCategory.VARIABLES) .arg("Variable", ScriptActionArgumentType.VARIABLE) .arg("Value", ScriptActionArgumentType.ANY) - .action(ctx -> ctx.context().setVariable( + .action(ctx -> ctx.task().context().setVariable( ctx.variable("Variable").name(), ctx.value("Value") ))), @@ -187,7 +142,7 @@ public enum ScriptActionType { for (ScriptValue val : ctx.pluralValue("Amount")) { value += val.asNumber(); } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Variable").name(), new ScriptNumberValue(value) ); @@ -204,7 +159,7 @@ public enum ScriptActionType { for (ScriptValue val : ctx.pluralValue("Amount")) { value -= val.asNumber(); } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Variable").name(), new ScriptNumberValue(value) ); @@ -221,7 +176,7 @@ public enum ScriptActionType { for (ScriptValue arg : ctx.pluralValue("Texts")) { sb.append(arg.asText()); } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptTextValue(sb.toString()) ); @@ -238,7 +193,7 @@ public enum ScriptActionType { for (ScriptValue val : ctx.pluralValue("Numbers")) { value += val.asNumber(); } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(value) ); @@ -260,7 +215,7 @@ public enum ScriptActionType { value -= val.asNumber(); } } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(value) ); @@ -277,7 +232,7 @@ public enum ScriptActionType { for (ScriptValue val : ctx.pluralValue("Numbers")) { value *= val.asNumber(); } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(value) ); @@ -299,7 +254,7 @@ public enum ScriptActionType { value /= val.asNumber(); } } - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(value) ); @@ -315,142 +270,18 @@ public enum ScriptActionType { .action(ctx -> { double dividend = ctx.value("Dividend").asNumber(); double divisor = ctx.value("Divisor").asNumber(); - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(dividend % divisor) ); })), - IF_EQUALS(builder -> builder.name("If Equals") - .description("Checks if one value is equal to another.") - .icon(Items.IRON_INGOT) - .category(ScriptActionCategory.VARIABLES) - .arg("Value", ScriptActionArgumentType.ANY) - .arg("Other", ScriptActionArgumentType.ANY) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (ctx.value("Value").valueEquals(ctx.value("Other"))) { - ctx.setLastIfResult(true); - } - })), - - IF_NOT_EQUALS(builder -> builder.name("If Not Equals") - .description("Checks if one value is not equal to another.") - .icon(Items.BARRIER) - .category(ScriptActionCategory.VARIABLES) - .arg("Value", ScriptActionArgumentType.ANY) - .arg("Other", ScriptActionArgumentType.ANY) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (!ctx.value("Value").valueEquals(ctx.value("Other"))) { - ctx.setLastIfResult(true); - } - })), - - IF_GREATER(builder -> builder.name("If Greater") - .description("Checks if one number is greater than another.") - .icon(Items.BRICK) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Other", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (ctx.value("Value").asNumber() > ctx.value("Other").asNumber()) { - ctx.setLastIfResult(true); - } - })), - - IF_GREATER_EQUALS(builder -> builder.name("If Greater Equals") - .description("Checks if one number is greater than or equal to another.") - .icon(Items.BRICKS) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Other", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (ctx.value("Value").asNumber() >= ctx.value("Other").asNumber()) { - ctx.setLastIfResult(true); - } - })), - - IF_LESS(builder -> builder.name("If Less") - .description("Checks if one number is less than another.") - .icon(Items.NETHER_BRICK) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Other", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (ctx.value("Value").asNumber() < ctx.value("Other").asNumber()) { - ctx.setLastIfResult(true); - } - })), - - IF_LESS_EQUALS(builder -> builder.name("If Less Equals") - .description("Checks if one number is less than or equal to another.") - .icon(Items.NETHER_BRICKS) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Other", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (ctx.value("Value").asNumber() <= ctx.value("Other").asNumber()) { - ctx.setLastIfResult(true); - } - })), - - IF_WITHIN_RANGE(builder -> builder.name("If Number Within Range") - .description("Checks if a number is between\n2 different numbers (inclusive).") - .icon(Items.CHEST) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Minimum", ScriptActionArgumentType.NUMBER) - .arg("Maximum", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - double value = ctx.value("Value").asNumber(); - - if (value >= ctx.value("Minimum").asNumber()) { - if (value <= ctx.value("Maximum").asNumber()) { - ctx.setLastIfResult(true); - } - } - })), - - IF_NOT_WITHIN_RANGE(builder -> builder.name("If Number Not Within Range") - .description("Checks if a number isn't between\n2 different numbers (inclusive).") - .icon(Items.TRAPPED_CHEST) - .category(ScriptActionCategory.NUMBERS) - .arg("Value", ScriptActionArgumentType.NUMBER) - .arg("Minimum", ScriptActionArgumentType.NUMBER) - .arg("Maximum", ScriptActionArgumentType.NUMBER) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - double value = ctx.value("Value").asNumber(); - - if (value >= ctx.value("Minimum").asNumber()) { - if (value <= ctx.value("Maximum").asNumber()) { - return; - } - } - - ctx.setLastIfResult(true); - })), - CANCEL_EVENT(builder -> builder.name("Cancel Event") .description("Cancels the event.") .icon(Items.BARRIER) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .action(ctx -> { - if (ctx.event() instanceof CancellableEvent ce) { + if (ctx.task().event() instanceof CancellableEvent ce) { ce.setCancelled(true); } })), @@ -458,9 +289,9 @@ public enum ScriptActionType { UNCANCEL_EVENT(builder -> builder.name("Uncancel Event") .description("Uncancels the event.") .icon(Items.STRUCTURE_VOID) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .action(ctx -> { - if (ctx.event() instanceof CancellableEvent ce) { + if (ctx.task().event() instanceof CancellableEvent ce) { ce.setCancelled(false); } })), @@ -476,10 +307,10 @@ public enum ScriptActionType { ArrayList values = new ArrayList<>(); if (ctx.argMap().containsKey("Values")) { for (ScriptArgument v : ctx.argMap().get("Values")) { - values.add(v.getValue(ctx.event(), ctx.context())); + values.add(v.getValue(ctx.task())); } } - ctx.context().setVariable(ctx.variable("Variable").name(), new ScriptListValue(values)); + ctx.task().context().setVariable(ctx.variable("Variable").name(), new ScriptListValue(values)); })), APPEND_VALUE(builder -> builder.name("Append Value") @@ -491,9 +322,9 @@ public enum ScriptActionType { .action(ctx -> { List list = ctx.value("List").asList(); for (ScriptArgument v : ctx.argMap().get("Values")) { - list.add(v.getValue(ctx.event(), ctx.context())); + list.add(v.getValue(ctx.task())); } - ctx.context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); + ctx.task().context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); })), APPEND_LIST_VALUES(builder -> builder.name("Append List Values") @@ -509,7 +340,7 @@ public enum ScriptActionType { receiver.addAll(donor); - ctx.context().setVariable(ctx.variable("Receiving List").name(), new ScriptListValue(receiver)); + ctx.task().context().setVariable(ctx.variable("Receiving List").name(), new ScriptListValue(receiver)); })), GET_LIST_VALUE(builder -> builder.name("Get List Value") @@ -524,9 +355,9 @@ public enum ScriptActionType { // force index consistent with diamondfire indexes int index = (int) ctx.value("Index").asNumber() - 1; if (index < 0 || index >= list.size()) { - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); } else { - ctx.context().setVariable(ctx.variable("Result").name(), list.get(index)); + ctx.task().context().setVariable(ctx.variable("Result").name(), list.get(index)); } })), @@ -547,7 +378,7 @@ public enum ScriptActionType { break; } } - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(index)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(index)); })), SET_LIST_VALUE(builder -> builder.name("Set List Value") @@ -565,7 +396,7 @@ public enum ScriptActionType { return; } list.set(index, ctx.value("Value")); - ctx.context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); + ctx.task().context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); })), REMOVE_LIST_AT_INDEX_VALUE(builder -> builder.name("Remove List Value") @@ -582,7 +413,7 @@ public enum ScriptActionType { return; } list.remove(index); - ctx.context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); + ctx.task().context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); })), REMOVE_LIST_VALUE(builder -> builder.name("Remove List Value") @@ -596,7 +427,7 @@ public enum ScriptActionType { list.removeIf(value -> value.valueEquals(ctx.value("Value"))); - ctx.context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); + ctx.task().context().setVariable(ctx.variable("List").name(), new ScriptListValue(list)); })), LIST_LENGTH(builder -> builder.name("List Length") @@ -606,143 +437,17 @@ public enum ScriptActionType { .arg("Result", ScriptActionArgumentType.VARIABLE) .arg("List", ScriptActionArgumentType.LIST) .action(ctx -> { - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(ctx.value("List").asList().size())); - })), - - IF_LIST_CONTAINS(builder -> builder.name("If List Contains") - .description("Checks if a list contains a value.") - .icon(Items.BOOKSHELF) - .category(ScriptActionCategory.LISTS) - .arg("List", ScriptActionArgumentType.LIST) - .arg("Value", ScriptActionArgumentType.ANY) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - List list = ctx.value("List").asList(); - if (list.stream().anyMatch(value -> value.valueEquals(ctx.value("Value")))) { - ctx.setLastIfResult(true); - } - })), - - IF_TEXT_CONTAINS(builder -> builder.name("If Text Contains") - .description("Checks if a text contains a value.") - .icon(Items.NAME_TAG) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Subtext", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String subtext = ctx.value("Subtext").asText(); - if (text.contains(subtext)) { - ctx.setLastIfResult(true); - } - })), - - IF_MATCHES_REGEX(builder -> builder.name("If Matches Regex") - .description("Checks if a text matches a regex.") - .icon(Items.ANVIL) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Regex", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String regex = ctx.value("Regex").asText(); - if (text.matches(regex)) { - ctx.setLastIfResult(true); - } - })), - - IF_STARTS_WITH(builder -> builder.name("If Starts With") - .description("Checks if a text starts with an other.") - .icon(Items.FEATHER) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Subtext", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String subtext = ctx.value("Subtext").asText(); - if (text.startsWith(subtext)) { - ctx.setLastIfResult(true); - } - })), - - IF_LIST_DOESNT_CONTAIN(builder -> builder.name("If List Doesnt Contain") - .description("Checks if a list doesnt contain a value.") - .icon(Items.BOOKSHELF) - .category(ScriptActionCategory.LISTS) - .arg("List", ScriptActionArgumentType.LIST) - .arg("Value", ScriptActionArgumentType.ANY) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - List list = ctx.value("List").asList(); - if (list.stream().noneMatch(value -> value.valueEquals(ctx.value("Value")))) { - ctx.setLastIfResult(true); - } - })), - - IF_TEXT_DOESNT_CONTAIN(builder -> builder.name("If Text Doesnt Contain") - .description("Checks if a text doesnt contain a value.") - .icon(Items.NAME_TAG) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Subtext", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String subtext = ctx.value("Subtext").asText(); - if (!text.contains(subtext)) { - ctx.setLastIfResult(true); - } - })), - - IF_DOESNT_START_WITH(builder -> builder.name("If Doesnt Start With") - .description("Checks if a text doesnt start with an other.") - .icon(Items.FEATHER) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Subtext", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String subtext = ctx.value("Subtext").asText(); - if (!text.startsWith(subtext)) { - ctx.setLastIfResult(true); - } - })), - - IF_DOESNT_MATCH_REGEX(builder -> builder.name("If Doesnt Match Regex") - .description("Checks if a text doesnt match a regex.") - .icon(Items.ANVIL) - .category(ScriptActionCategory.TEXTS) - .arg("Text", ScriptActionArgumentType.TEXT) - .arg("Regex", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String text = ctx.value("Text").asText(); - String regex = ctx.value("Regex").asText(); - if (!text.matches(regex)) { - ctx.setLastIfResult(true); - } + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(ctx.value("List").asList().size())); })), WAIT(builder -> builder.name("Wait") .description("Waits for a given amount of time.") .icon(Items.CLOCK) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .arg("Ticks", ScriptActionArgumentType.NUMBER) .action(ctx -> { int n = 0; - while(!(ctx.task().stack().peekOriginal(n) < 0)) { + /*while(!(ctx.task().stack().peekOriginal(n) < 0)) { int pos = ctx.task().stack().peekOriginal(n); n++; if(pos >= 0 && ctx.script().getParts().get(pos).getGroup() == ScriptGroup.REPETITION) { @@ -751,6 +456,12 @@ public enum ScriptActionType { ctx.task().stack().peekElement(n).setVariable("LagslayerCounter", 0); } } + }*/ + + for(int i = 0; i < ctx.task().stack().size(); i++) { + if(ctx.task().stack().peek(i).getParent() instanceof ScriptRepetition) { + ctx.task().stack().peek(i).setVariable("Lagslayer Count", 0); + } } ctx.task().stop();//Stop the current thread @@ -781,7 +492,7 @@ public enum ScriptActionType { } } - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptDictionaryValue(dict)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptDictionaryValue(dict)); })), PARSE_JSON(builder -> builder.name("Parse from JSON") @@ -799,7 +510,7 @@ public enum ScriptActionType { catch (JsonParseException e) {dict = new ScriptUnknownValue();} - ctx.context().setVariable(ctx.variable("Result").name(), dict); + ctx.task().context().setVariable(ctx.variable("Result").name(), dict); })), GET_DICT_VALUE(builder -> builder.name("Get Dictionary Value") @@ -813,9 +524,9 @@ public enum ScriptActionType { HashMap dict = ctx.value("Dictionary").asDictionary(); String key = ctx.value("Key").asText(); if (dict.containsKey(key)) { - ctx.context().setVariable(ctx.variable("Result").name(), dict.get(key)); + ctx.task().context().setVariable(ctx.variable("Result").name(), dict.get(key)); } else { - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); } })), @@ -830,7 +541,7 @@ public enum ScriptActionType { HashMap dict = ctx.value("Dictionary").asDictionary(); String key = ctx.value("Key").asText(); dict.put(key, ctx.value("Value")); - ctx.context().setVariable(ctx.variable("Dictionary").name(), new ScriptDictionaryValue(dict)); + ctx.task().context().setVariable(ctx.variable("Dictionary").name(), new ScriptDictionaryValue(dict)); })), GET_DICT_SIZE(builder -> builder.name("Get Dictionary Size") @@ -841,7 +552,7 @@ public enum ScriptActionType { .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) .action(ctx -> { HashMap dict = ctx.value("Dictionary").asDictionary(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(dict.size())); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(dict.size())); })), GET_DICT_KEYS(builder -> builder.name("Get Dictionary Keys") @@ -852,42 +563,10 @@ public enum ScriptActionType { .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) .action(ctx -> { HashMap dict = ctx.value("Dictionary").asDictionary(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptListValue(dict.keySet().stream().map(x -> (ScriptValue) new ScriptTextValue(x)).toList())); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptListValue(dict.keySet().stream().map(x -> (ScriptValue) new ScriptTextValue(x)).toList())); }) ), - IF_DICT_KEY_EXISTS(builder -> builder.name("If Dictionary Key Exists") - .description("Checks if a key exists in a dictionary.") - .icon(Items.NAME_TAG) - .category(ScriptActionCategory.DICTIONARIES) - .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) - .arg("Key", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - HashMap dict = ctx.value("Dictionary").asDictionary(); - String key = ctx.value("Key").asText(); - if (dict.containsKey(key)) { - ctx.setLastIfResult(true); - } - })), - - IF_DICT_KEY_DOESNT_EXIST(builder -> builder.name("If Dictionary Key Doesnt Exist") - .description("Checks if a key doesnt exist in a dictionary.") - .icon(Items.NAME_TAG) - .category(ScriptActionCategory.DICTIONARIES) - .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) - .arg("Key", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - HashMap dict = ctx.value("Dictionary").asDictionary(); - String key = ctx.value("Key").asText(); - if (!dict.containsKey(key)) { - ctx.setLastIfResult(true); - } - })), - REMOVE_DICT_ENTRY(builder -> builder.name("Remove Dictionary Entry") .description("Removes a key from a dictionary.") .icon(Items.TNT_MINECART) @@ -898,87 +577,7 @@ public enum ScriptActionType { HashMap dict = ctx.value("Dictionary").asDictionary(); String key = ctx.value("Key").asText(); dict.remove(key); - ctx.context().setVariable(ctx.variable("Dictionary").name(), new ScriptDictionaryValue(dict)); - })), - - - FOR_EACH_IN_LIST(builder -> builder.name("For Each In List") - .description("Iterates over a list.") - .icon(Items.BOOKSHELF) - .category(ScriptActionCategory.LISTS) - .arg("Variable", ScriptActionArgumentType.VARIABLE) - .arg("List", ScriptActionArgumentType.LIST) - .hasChildren(true) - .group(ScriptGroup.REPETITION) - .action(ctx -> { - ctx.scheduleInner( - null, - context -> { - if(!context.hasScopeVariable("Counter")) { - context.setScopeVariable("Counter", 0); - } - - int counter = (Integer)context.getScopeVariable("Counter")+1; - List list = context.value("List").asList(); - - if(counter <= list.size()) { - context.setScopeVariable("Counter", counter); - context.context().setVariable(context.variable("Variable").name(), list.get(counter-1)); - context.setLastIfResult(true); - } - } - ); - - /*List list = ctx.value("List").asList(); - if (!list.isEmpty()) { - ctx.context().setVariable(ctx.variable("Variable").name(), list.get(0)); - } - Lists.reverse(list); - for (ScriptValue item : list) { - ctx.scheduleInner(() -> { - ctx.context().setVariable(ctx.variable("Variable").name(), item); - }); - }*/ - })), - - DICT_FOR_EACH(builder -> builder.name("For Each In Dictionary") - .description("Iterates over a dictionary.") - .icon(Items.BOOKSHELF) - .category(ScriptActionCategory.DICTIONARIES) - .arg("Key", ScriptActionArgumentType.VARIABLE) - .arg("Value", ScriptActionArgumentType.VARIABLE) - .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) - .hasChildren(true) - .group(ScriptGroup.REPETITION) - .action(ctx -> { - ctx.scheduleInner( - null, - context -> { - HashMap dict = context.value("Dictionary").asDictionary(); - - if(!context.hasScopeVariable("Iterator")) { - context.setScopeVariable("Iterator", dict.entrySet().iterator()); - } - - Iterator> iterator = (Iterator>) context.getScopeVariable("Iterator"); - - if(iterator.hasNext()) { - Map.Entry entry = iterator.next(); - context.setScopeVariable("Iterator", iterator); - context.context().setVariable(context.variable("Key").name(), new ScriptTextValue(entry.getKey())); - context.context().setVariable(context.variable("Value").name(), entry.getValue()); - context.setLastIfResult(true); - } - } - ); - - /*HashMap dict = ctx.value("Dictionary").asDictionary(); - for (Map.Entry entry : dict.entrySet()) { - ctx.scheduleInner(() -> { - ctx.context().setVariable(ctx.variable("Key").name(), new ScriptTextValue(entry.getKey())); - ctx.context().setVariable(ctx.variable("Value").name(), entry.getValue()); - }); - }*/ + ctx.task().context().setVariable(ctx.variable("Dictionary").name(), new ScriptDictionaryValue(dict)); })), ROUND_NUM(builder -> builder.name("Round Number") @@ -989,7 +588,7 @@ public enum ScriptActionType { .arg("Number", ScriptActionArgumentType.NUMBER) .action(ctx -> { double number = ctx.value("Number").asNumber(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.round(number))); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.round(number))); })), FLOOR_NUM(builder -> builder.name("Floor Number") @@ -1000,7 +599,7 @@ public enum ScriptActionType { .arg("Number", ScriptActionArgumentType.NUMBER) .action(ctx -> { double number = ctx.value("Number").asNumber(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.floor(number))); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.floor(number))); })), CEIL_NUM(builder -> builder.name("Ceil Number") @@ -1011,7 +610,7 @@ public enum ScriptActionType { .arg("Number", ScriptActionArgumentType.NUMBER) .action(ctx -> { double number = ctx.value("Number").asNumber(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.ceil(number))); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Math.ceil(number))); })), REGISTER_CMD(builder -> builder.name("Register Command") @@ -1056,30 +655,6 @@ public enum ScriptActionType { } })), - IF_GUI_OPEN(builder -> builder.name("If GUI Open") - .description("Executes if a gui is open.") - .icon(Items.BOOK) - .hasChildren(true) - .category(ScriptActionCategory.MISC) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (io.github.techstreet.dfscript.DFScript.MC.currentScreen != null) { - ctx.setLastIfResult(true); - } - })), - - IF_GUI_CLOSED(builder -> builder.name("If GUI Not Open") - .description("Executes if no gui is open.") - .icon(Items.BOOK) - .hasChildren(true) - .category(ScriptActionCategory.MISC) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - if (io.github.techstreet.dfscript.DFScript.MC.currentScreen == null) { - ctx.setLastIfResult(true); - } - })), - COPY_TEXT(builder -> builder.name("Copy Text") .description("Copies the text to the clipboard.") .icon(Items.PAPER) @@ -1105,7 +680,7 @@ public enum ScriptActionType { split.add(new ScriptTextValue(s)); } - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptListValue(split)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptListValue(split)); })), REGEX_SPLIT_TEXT(builder -> builder.name("Split Text by Regex") @@ -1124,13 +699,13 @@ public enum ScriptActionType { split.add(new ScriptTextValue(s)); } - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptListValue(split)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptListValue(split)); })), STOP(builder -> builder.name("Stop Codeline") .description("Stops the current codeline.") .icon(Items.BARRIER) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .action(ctx -> { ctx.task().stop(); })), @@ -1138,33 +713,28 @@ public enum ScriptActionType { SKIP_ITERATION(builder -> builder.name("Skip Iteration") .description("Skips the current iteration of the latest loop.") .icon(Items.ENDER_PEARL) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .action(ctx -> { - int n = 0; - while(!(ctx.task().stack().peekOriginal(n) < 0)) { - int pos = ctx.task().stack().peekOriginal(n); - n++; - ctx.context().forceEndScope(); - if(pos < 0 || ctx.script().getParts().get(pos).getGroup() == ScriptGroup.REPETITION) { + while(ctx.task().stack().size() > 0) { + if(ctx.task().stack().peek().getParent() instanceof ScriptRepetition) { + ctx.task().stack().peek().skip(); break; } + ctx.task().stack().pop(); } })), STOP_REPETITION(builder -> builder.name("Stop Repetition") .description("Stops the latest loop.") .icon(Items.PRISMARINE_SHARD) - .category(ScriptActionCategory.MISC) + .category(ScriptActionCategory.CONTROL) .action(ctx -> { - ctx.context().breakLoop(); - int n = 0; - while(!(ctx.task().stack().peekOriginal(n) < 0)) { - int pos = ctx.task().stack().peekOriginal(n); - n++; - ctx.context().forceEndScope(); - if(pos < 0 || ctx.script().getParts().get(pos).getGroup() == ScriptGroup.REPETITION) { + while(ctx.task().stack().size() > 0) { + if(ctx.task().stack().peek().getParent() instanceof ScriptRepetition) { + ctx.task().stack().pop(); break; } + ctx.task().stack().pop(); } })), @@ -1295,7 +865,7 @@ public enum ScriptActionType { .map(ScriptValue::asText) .collect(Collectors.joining(separator)); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), TEXT_INDEX_OF(builder -> builder.name("Index Of Text") @@ -1307,7 +877,7 @@ public enum ScriptActionType { .arg("Subtext",ScriptActionArgumentType.TEXT) .action(ctx -> { int result = ctx.value("Text").asText().indexOf(ctx.value("Subtext").asText()) + 1; - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(result)); })), TEXT_SUBTEXT(builder -> builder.name("Get Subtext") @@ -1323,7 +893,7 @@ public enum ScriptActionType { int start = (int)ctx.value("First Index").asNumber()-1; int end = (int)ctx.value("Last Index").asNumber(); String result = text.substring(start, end); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), TEXT_SUBTEXT_V1(builder -> builder.name("Get Subtext OLD") @@ -1340,7 +910,7 @@ public enum ScriptActionType { int start = (int)ctx.value("First Index").asNumber()+1; int end = (int)ctx.value("Last Index").asNumber(); String result = text.substring(start, end); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), TEXT_LENGTH(builder -> builder.name("Get Text Length") @@ -1351,7 +921,7 @@ public enum ScriptActionType { .arg("Text",ScriptActionArgumentType.TEXT) .action(ctx -> { String text = ctx.value("Text").asText(); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(text.length())); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(text.length())); })), READ_FILE(builder -> builder.name("Read File") @@ -1364,13 +934,13 @@ public enum ScriptActionType { String filename = ctx.value("Filename").asText(); if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { - Path f = FileUtil.folder("Scripts").resolve(ctx.script().getFile().getName()+"-files").resolve(filename); + Path f = FileUtil.folder("Scripts").resolve(ctx.task().context().script().getFile().getName()+"-files").resolve(filename); if (Files.exists(f)) { try { String content = FileUtil.readFile(f); JsonElement json = JsonParser.parseString(content); ScriptValue value = ScriptValueJson.fromJson(json); - ctx.context().setVariable(ctx.variable("Result").name(), value); + ctx.task().context().setVariable(ctx.variable("Result").name(), value); } catch (IOException e) { e.printStackTrace(); ChatUtil.error("Internal error while reading file."); @@ -1392,7 +962,7 @@ public enum ScriptActionType { ScriptValue value = ctx.value("Content"); if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { - Path f = FileUtil.folder("Scripts").resolve(ctx.script().getFile().getName()+"-files").resolve(filename); + Path f = FileUtil.folder("Scripts").resolve(ctx.task().context().script().getFile().getName()+"-files").resolve(filename); try { f.toFile().getParentFile().mkdirs(); FileUtil.writeFile(f, ScriptValueJson.toJson(value).toString()); @@ -1405,44 +975,6 @@ public enum ScriptActionType { } })), - IF_FILE_EXISTS(builder -> builder.name("If File Exists") - .description("Executes if the specified file exists.") - .icon(Items.BOOK) - .category(ScriptActionCategory.MISC) - .arg("Filename", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String filename = ctx.value("Filename").asText(); - if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { - Path f = FileUtil.folder("Scripts").resolve(ctx.script().getFile().getName()+"-files").resolve(filename); - if (Files.exists(f)) { - ctx.setLastIfResult(true); - } - } else { - ChatUtil.error("Illegal filename: " + filename); - } - })), - - IF_FILE_DOESNT_EXIST(builder -> builder.name("If File Doesnt Exist") - .description("Executes if the specified file doesnt exist.") - .icon(Items.BOOK) - .category(ScriptActionCategory.MISC) - .arg("Filename", ScriptActionArgumentType.TEXT) - .hasChildren(true) - .group(ScriptGroup.CONDITION) - .action(ctx -> { - String filename = ctx.value("Filename").asText(); - if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { - Path f = FileUtil.folder("Scripts").resolve(ctx.script().getFile().getName()+"-files").resolve(filename); - if (!Files.exists(f)) { - ctx.setLastIfResult(true); - } - } else { - ChatUtil.error("Illegal filename: " + filename); - } - })), - PARSE_NUMBER(builder -> builder.name("Parse Number") .description("Parses a number from a text.") .icon(Items.ANVIL) @@ -1452,9 +984,9 @@ public enum ScriptActionType { .action(ctx -> { String text = ctx.value("Text").asText(); try { - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Double.parseDouble(text))); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(Double.parseDouble(text))); } catch (NumberFormatException e) { - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptUnknownValue()); } })), @@ -1503,7 +1035,7 @@ public enum ScriptActionType { int x = (int) ctx.value("X").asNumber(); int y = (int) ctx.value("Y").asNumber(); - if (ctx.event() instanceof HudRenderEvent event) { + if (ctx.task().event() instanceof HudRenderEvent event) { Text t = ComponentUtil.fromString(ComponentUtil.andsToSectionSigns(text)); io.github.techstreet.dfscript.DFScript.MC.textRenderer.drawWithShadow(event.stack(),t,x,y, 0xFFFFFF); } @@ -1519,7 +1051,7 @@ public enum ScriptActionType { String text = ctx.value("Text").asText(); Text t = ComponentUtil.fromString(ComponentUtil.andsToSectionSigns(text)); int width = DFScript.MC.textRenderer.getWidth(t); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(width)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptNumberValue(width)); })), OPEN_MENU(builder -> builder.name("Open Menu") @@ -1532,7 +1064,7 @@ public enum ScriptActionType { int width = (int) ctx.value("Width").asNumber(); int height = (int) ctx.value("Height").asNumber(); - io.github.techstreet.dfscript.DFScript.MC.setScreen(new ScriptMenu(width,height,ctx.script())); + io.github.techstreet.dfscript.DFScript.MC.setScreen(new ScriptMenu(width,height,ctx.task().context().script())); })), ADD_MENU_BUTTON(builder -> builder.name("Add Menu Button") @@ -1554,8 +1086,8 @@ public enum ScriptActionType { String identifier = ctx.value("Identifier").asText(); if (DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { - menu.widgets.add(new ScriptMenuButton(x,y,width,height,text,identifier,ctx.script())); + if (menu.ownedBy(ctx.task().context().script())) { + menu.widgets.add(new ScriptMenuButton(x,y,width,height,text,identifier,ctx.task().context().script())); } else { ChatUtil.error("Unable to add button to menu! (Not owned by script)"); } @@ -1579,7 +1111,7 @@ public enum ScriptActionType { String identifier = ctx.value("Identifier").asText(); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { menu.widgets.add(new ScriptMenuItem(x,y,item,identifier)); } else { ChatUtil.error("Unable to add item to menu! (Not owned by script)"); @@ -1605,7 +1137,7 @@ public enum ScriptActionType { Text text = ComponentUtil.fromString(ComponentUtil.andsToSectionSigns(rawText)); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { menu.widgets.add(new ScriptMenuText(x,y,text,0x333333, 1, false, false,identifier)); } else { ChatUtil.error("Unable to add text to menu! (Not owned by script)"); @@ -1632,7 +1164,7 @@ public enum ScriptActionType { String identifier = ctx.value("Identifier").asText(); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { menu.widgets.add(new ScriptMenuTextField("",x,y,width,height,true,identifier)); } else { ChatUtil.error("Unable to add text field to menu! (Not owned by script)"); @@ -1650,7 +1182,7 @@ public enum ScriptActionType { .action(ctx -> { String identifier = ctx.value("Identifier").asText(); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { menu.removeChild(identifier); } else { ChatUtil.error("Unable to remove element from menu! (Not owned by script)"); @@ -1669,11 +1201,11 @@ public enum ScriptActionType { .action(ctx -> { String identifier = ctx.value("Identifier").asText(); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { ScriptWidget w = menu.getWidget(identifier); if (w instanceof ScriptMenuTextField field) { - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptTextValue(field.getText()) ); @@ -1698,7 +1230,7 @@ public enum ScriptActionType { String identifier = ctx.value("Identifier").asText(); if (io.github.techstreet.dfscript.DFScript.MC.currentScreen instanceof ScriptMenu menu) { - if (menu.ownedBy(ctx.script())) { + if (menu.ownedBy(ctx.task().context().script())) { ScriptWidget w = menu.getWidget(identifier); if (w instanceof ScriptMenuTextField field) { field.setText(ctx.value("Value").asText()); @@ -1725,7 +1257,7 @@ public enum ScriptActionType { int max = (int) ctx.value("Max").asNumber(); Random random = new Random(); int result = random.nextInt(max + 1 - min) + min; - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(result) ); @@ -1742,7 +1274,7 @@ public enum ScriptActionType { double min = ctx.value("Min").asNumber(); double max = ctx.value("Max").asNumber(); double result = Math.random() * (max - min) + min; - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(result) ); @@ -1760,31 +1292,12 @@ public enum ScriptActionType { double min = ctx.value("Min").asNumber(); double max = ctx.value("Max").asNumber(); double result = Math.random() * (max - min) + min; - ctx.context().setVariable( + ctx.task().context().setVariable( ctx.variable("Result").name(), new ScriptNumberValue(result) ); })), - REPEAT_FOREVER(builder -> builder.name("RepeatForever") - .description("Repeats for eternity.\nMake sure to have a Stop Repetition, Stop Codeline or Wait somewhere in the code!\nThere's a lagslayer for the repetition actions.\nIt activates after 100000 iterations with no Wait.") - .icon(Items.GOLD_INGOT) - .category(ScriptActionCategory.MISC) - .hasChildren(true) - .group(ScriptGroup.REPETITION) - .action(ctx -> { - ctx.scheduleInner(null, context -> context.setLastIfResult(true)); - })), - ELSE(builder -> builder.name("Else") - .description("Executes if the last IF condition failed.\nAnd ELSE also works as a valid IF condition for ELSE.") - .icon(Items.END_STONE) - .category(ScriptActionCategory.MISC) - .group(ScriptGroup.CONDITION) - .hasChildren(true) - .action(ctx -> { - ctx.setLastIfResult(!ctx.lastIfResult()); - })), - SORT_LIST(builder -> builder.name("Sort List") .description("Sorts a list in ascending order.") .icon(Items.REPEATING_COMMAND_BLOCK) @@ -1805,7 +1318,7 @@ public enum ScriptActionType { list.sort(new ScriptValueComparator()); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptListValue(list)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptListValue(list)); })), REPLACE_TEXT(builder -> builder.name("Replace Text") @@ -1821,7 +1334,7 @@ public enum ScriptActionType { result = result.replace(ctx.value("Text part to replace").asText(), ctx.value("Replacement").asText()); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), REGEX_REPLACE_TEXT(builder -> builder.name("Replace Text using Regex") @@ -1837,7 +1350,7 @@ public enum ScriptActionType { result = result.replaceAll(ctx.value("Regex").asText(), ctx.value("Replacement").asText()); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), REMOVE_TEXT(builder -> builder.name("Remove Text") @@ -1856,7 +1369,7 @@ public enum ScriptActionType { result = result.replace(textsToRemove.get(i).asText(), ""); } - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), STRIP_COLOR(builder -> builder.name("Strip Color from Text") @@ -1877,7 +1390,7 @@ public enum ScriptActionType { result = result.replaceAll("&x(&[0-9a-fA-F]){6}", ""); result = result.replaceAll("&[0-9a-fA-FlonmkrLONMKR]", ""); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })), REPEAT_TEXT(builder -> builder.name("Repeat Text") @@ -1888,16 +1401,12 @@ public enum ScriptActionType { .arg("Times to repeat", ScriptActionArgumentType.NUMBER) .category(ScriptActionCategory.TEXTS) .action(ctx -> { - String result = ""; String input = ctx.value("Text to repeat").asText(); int times = (int) ctx.value("Times to repeat").asNumber(); - for(int i = 0; i < times; i++) - { - result += input; - } + String result = input.repeat(Math.max(0, times)); - ctx.context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); + ctx.task().context().setVariable(ctx.variable("Result").name(), new ScriptTextValue(result)); })); private Consumer action = (ctx) -> { diff --git a/src/main/java/io/github/techstreet/dfscript/script/action/ScriptBuiltinAction.java b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptBuiltinAction.java new file mode 100644 index 0000000..a0f415e --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/action/ScriptBuiltinAction.java @@ -0,0 +1,68 @@ +package io.github.techstreet.dfscript.script.action; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderIconElement; +import net.minecraft.text.Text; + +import java.lang.reflect.Type; +import java.util.List; + +public class ScriptBuiltinAction extends ScriptAction { + + private ScriptActionType type; + + public ScriptBuiltinAction(ScriptActionType type, List arguments) { + super(arguments); + this.type = type; + } + + public ScriptBuiltinAction setType(ScriptActionType newType) { + type = newType; + + return this; + } + + @Override + public void run(ScriptTask task) { + type.run(new ScriptActionContext(task, getArguments())); + } + + public ScriptActionType getType() { + return type; + } + + @Override + public boolean isDeprecated() { + return type.isDeprecated(); + } + + @Override + public void create(ScriptPartRender render, Script script) { + render.addElement(new ScriptPartRenderIconElement(getType().getName(), getType().getIcon())); + + super.create(render, script); + } + + public static class Serializer implements JsonSerializer { + + @Override + public JsonElement serialize(ScriptBuiltinAction src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "action"); + obj.addProperty("action", src.getType().name()); + obj.add("arguments", context.serialize(src.getArguments())); + return obj; + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptArgument.java index 328ca9b..5101e99 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptArgument.java @@ -8,12 +8,13 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.values.ScriptValue; import java.lang.reflect.Type; public interface ScriptArgument { - ScriptValue getValue(Event event, ScriptContext context); + ScriptValue getValue(ScriptTask task); boolean convertableTo(ScriptActionArgumentType type); diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptClientValueArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptClientValueArgument.java index c86e57f..79950b0 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptClientValueArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptClientValueArgument.java @@ -12,6 +12,7 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.menu.ScriptMenuClickButtonEvent; import io.github.techstreet.dfscript.script.util.ScriptValueItem; import io.github.techstreet.dfscript.script.values.ScriptListValue; @@ -23,6 +24,8 @@ import java.util.ArrayList; import java.util.List; import java.util.function.BiFunction; +import java.util.function.Function; + import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -34,51 +37,51 @@ public enum ScriptClientValueArgument implements ScriptArgument { - EVENT_KEY("KeyPressed","The key code of the key pressed. (KeyPressEvent)", Items.STONE_BUTTON, ScriptActionArgumentType.NUMBER, (event, context) -> { - if (event instanceof KeyPressEvent e) { + EVENT_KEY("KeyPressed","The key code of the key pressed. (KeyPressEvent)", Items.STONE_BUTTON, ScriptActionArgumentType.NUMBER, (task) -> { + if (task.event() instanceof KeyPressEvent e) { return new ScriptNumberValue(e.getKey().getCode()); } else { throw new IllegalStateException("Event is not a KeyPressEvent"); } }), - EVENT_KEY_ACTION("KeyAction","The code of the key action performed. (KeyPressEvent)", Items.OAK_BUTTON, ScriptActionArgumentType.NUMBER, (event,context) -> { - if (event instanceof KeyPressEvent e) { + EVENT_KEY_ACTION("KeyAction","The code of the key action performed. (KeyPressEvent)", Items.OAK_BUTTON, ScriptActionArgumentType.NUMBER, (task) -> { + if (task.event() instanceof KeyPressEvent e) { return new ScriptNumberValue(e.getAction()); } else { throw new IllegalStateException("Event is not a KeyPressEvent"); } }), - EVENT_MESSAGE("ReceivedMessage","The message received. (ReceiveChatEvent)", Items.WRITTEN_BOOK, ScriptActionArgumentType.TEXT, (event,context) -> { - if (event instanceof ReceiveChatEvent e) { + EVENT_MESSAGE("ReceivedMessage","The message received. (ReceiveChatEvent)", Items.WRITTEN_BOOK, ScriptActionArgumentType.TEXT, (task) -> { + if (task.event() instanceof ReceiveChatEvent e) { return new ScriptTextValue(ComponentUtil.sectionSignsToAnds(ComponentUtil.toFormattedString(e.getMessage()))); } else { throw new IllegalStateException("Event is not a ReceiveChatEvent"); } }), - ENTERED_MESSAGE("EnteredMessage","The message entered. (SendChatEvent)", Items.WRITABLE_BOOK, ScriptActionArgumentType.TEXT, (event,context) -> { - if (event instanceof SendChatEvent e) { + ENTERED_MESSAGE("EnteredMessage","The message entered. (SendChatEvent)", Items.WRITABLE_BOOK, ScriptActionArgumentType.TEXT, (task) -> { + if (task.event() instanceof SendChatEvent e) { return new ScriptTextValue(e.getMessage()); } else { throw new IllegalStateException("Event is not a SendChatEvent"); } }), - TIMESTAMP("Timestamp","The current timestamp in milliseconds.", Items.CLOCK, ScriptActionArgumentType.NUMBER, (event,context) -> new ScriptNumberValue(System.currentTimeMillis())), + TIMESTAMP("Timestamp","The current timestamp in milliseconds.", Items.CLOCK, ScriptActionArgumentType.NUMBER, (task) -> new ScriptNumberValue(System.currentTimeMillis())), - CLIPBOARD("Clipboard", "The current text on the clipboard", Items.PAPER, ScriptActionArgumentType.TEXT, (event,context) -> new ScriptTextValue(DFScript.MC.keyboard.getClipboard())), + CLIPBOARD("Clipboard", "The current text on the clipboard", Items.PAPER, ScriptActionArgumentType.TEXT, (task) -> new ScriptTextValue(DFScript.MC.keyboard.getClipboard())), MAIN_HAND_ITEM("MainHandItem","The item in the players main hand.", Items.STONE_BUTTON, ScriptActionArgumentType.DICTIONARY, - (event,context) -> ScriptValueItem.valueFromItem(DFScript.MC.player.getMainHandStack()) + (task) -> ScriptValueItem.valueFromItem(DFScript.MC.player.getMainHandStack()) ), OFF_HAND_ITEM("OffHandItem","The item in the players off hand.", Items.OAK_BUTTON, ScriptActionArgumentType.DICTIONARY, - (event,context) -> ScriptValueItem.valueFromItem(DFScript.MC.player.getOffHandStack()) + (task) -> ScriptValueItem.valueFromItem(DFScript.MC.player.getOffHandStack()) ), - FULL_INVENTORY("FullInventory","The entire inventory items of the player.", Items.OAK_PLANKS, ScriptActionArgumentType.LIST, (event,context) -> { + FULL_INVENTORY("FullInventory","The entire inventory items of the player.", Items.OAK_PLANKS, ScriptActionArgumentType.LIST, (task) -> { List list = new ArrayList<>(); for (int i = 0; i < DFScript.MC.player.getInventory().size(); i++) { list.add(ScriptValueItem.valueFromItem(DFScript.MC.player.getInventory().getStack(i))); @@ -86,7 +89,7 @@ public enum ScriptClientValueArgument implements ScriptArgument { return new ScriptListValue(list); }), - MAIN_INVENTORY("MainInventory", "The main inventory items of the player.", Items.BIRCH_PLANKS, ScriptActionArgumentType.LIST, (event, context) -> { + MAIN_INVENTORY("MainInventory", "The main inventory items of the player.", Items.BIRCH_PLANKS, ScriptActionArgumentType.LIST, (task) -> { List list = new ArrayList<>(); for (ItemStack item : DFScript.MC.player.getInventory().main) { list.add(ScriptValueItem.valueFromItem(item)); @@ -94,7 +97,7 @@ public enum ScriptClientValueArgument implements ScriptArgument { return new ScriptListValue(list); }), - ARMOR("Armor", "The armor items of the player.", Items.IRON_CHESTPLATE, ScriptActionArgumentType.LIST, (event, context) -> { + ARMOR("Armor", "The armor items of the player.", Items.IRON_CHESTPLATE, ScriptActionArgumentType.LIST, (task) -> { List list = new ArrayList<>(); for (ItemStack item : DFScript.MC.player.getInventory().armor) { list.add(ScriptValueItem.valueFromItem(item)); @@ -102,7 +105,7 @@ public enum ScriptClientValueArgument implements ScriptArgument { return new ScriptListValue(list); }), - HOTBAR_ITEMS("Hotbar Items", "The hotbar items of the player.", Items.IRON_AXE, ScriptActionArgumentType.LIST, (event, context) -> { + HOTBAR_ITEMS("Hotbar Items", "The hotbar items of the player.", Items.IRON_AXE, ScriptActionArgumentType.LIST, (task) -> { List list = new ArrayList<>(); for (int i = 0; i < 9; i++) { list.add(ScriptValueItem.valueFromItem(DFScript.MC.player.getInventory().getStack(i))); @@ -111,23 +114,23 @@ public enum ScriptClientValueArgument implements ScriptArgument { }), SELECTED_SLOT("Selected Slot", "The selected hotbar slot.", Items.LIME_DYE, ScriptActionArgumentType.NUMBER, - (event, context) -> new ScriptNumberValue(DFScript.MC.player.getInventory().selectedSlot) + (task) -> new ScriptNumberValue(DFScript.MC.player.getInventory().selectedSlot) ), GAME_MODE("Game Mode", "The gamemode the player is in.", Items.BEDROCK, ScriptActionArgumentType.TEXT, - (event, context) -> new ScriptTextValue(DFScript.MC.interactionManager.getCurrentGameMode().getName()) + (task) -> new ScriptTextValue(DFScript.MC.interactionManager.getCurrentGameMode().getName()) ), WINDOW_WIDTH("Window Width", "The width of the current window.", Items.STICK, ScriptActionArgumentType.NUMBER, - (event, context) -> new ScriptNumberValue(DFScript.MC.getWindow().getScaledWidth()) + (task) -> new ScriptNumberValue(DFScript.MC.getWindow().getScaledWidth()) ), WINDOW_HEIGHT("Window Height", "The height of the current window.", Items.STICK, ScriptActionArgumentType.NUMBER, - (event, context) -> new ScriptNumberValue(DFScript.MC.getWindow().getScaledHeight()) + (task) -> new ScriptNumberValue(DFScript.MC.getWindow().getScaledHeight()) ), - MENU_ELEMENT_IDENTIFIER("Menu Element Identifier", "The identifier of the menu element that triggered the event.", Items.NAME_TAG, ScriptActionArgumentType.TEXT,(event, scriptContext) -> { - if (event instanceof ScriptMenuClickButtonEvent e) { + MENU_ELEMENT_IDENTIFIER("Menu Element Identifier", "The identifier of the menu element that triggered the event.", Items.NAME_TAG, ScriptActionArgumentType.TEXT,(task) -> { + if (task.event() instanceof ScriptMenuClickButtonEvent e) { return new ScriptTextValue(e.identifier()); } else { throw new IllegalStateException("The event is not a menu click event."); @@ -135,29 +138,29 @@ public enum ScriptClientValueArgument implements ScriptArgument { }), PLAYER_UUID("Player UUID", "The UUID of the player.", Items.PLAYER_HEAD, ScriptActionArgumentType.TEXT, - (event, context) -> new ScriptTextValue(DFScript.PLAYER_UUID)), + (task) -> new ScriptTextValue(DFScript.PLAYER_UUID)), PLAYER_NAME("Player Name", "The name of the player.", Items.PLAYER_HEAD, ScriptActionArgumentType.TEXT, - (event, context) -> new ScriptTextValue(DFScript.PLAYER_NAME)), + (task) -> new ScriptTextValue(DFScript.PLAYER_NAME)), - EVENT_SOUND("ReceivedSound", "The ID of the sound. (OnReceiveSound)", Items.NAUTILUS_SHELL, ScriptActionArgumentType.TEXT, (event, context) -> { - if(event instanceof RecieveSoundEvent e) { + EVENT_SOUND("ReceivedSound", "The ID of the sound. (OnReceiveSound)", Items.NAUTILUS_SHELL, ScriptActionArgumentType.TEXT, (task) -> { + if(task.event() instanceof RecieveSoundEvent e) { return new ScriptTextValue(e.getSoundId().toString().replaceAll("^minecraft:", "")); } else { throw new IllegalStateException("The event is not a receive sound event."); } }), - EVENT_VOLUME("ReceivedSoundVolume", "The volume of the sound received. (OnReceiveSound)", Items.NOTE_BLOCK, ScriptActionArgumentType.NUMBER, (event, context) -> { - if(event instanceof RecieveSoundEvent e) { + EVENT_VOLUME("ReceivedSoundVolume", "The volume of the sound received. (OnReceiveSound)", Items.NOTE_BLOCK, ScriptActionArgumentType.NUMBER, (task) -> { + if(task.event() instanceof RecieveSoundEvent e) { return new ScriptNumberValue(e.getVolume()); } else { throw new IllegalStateException("The event is not a receive sound event."); } }), - EVENT_PITCH("ReceivedSoundPitch", "The pitch of the sound received. (OnReceiveSound)", Items.JUKEBOX, ScriptActionArgumentType.NUMBER, (event, context) -> { - if(event instanceof RecieveSoundEvent e) { + EVENT_PITCH("ReceivedSoundPitch", "The pitch of the sound received. (OnReceiveSound)", Items.JUKEBOX, ScriptActionArgumentType.NUMBER, (task) -> { + if(task.event() instanceof RecieveSoundEvent e) { return new ScriptNumberValue(e.getPitch()); } else { throw new IllegalStateException("The event is not a receive sound event."); @@ -166,10 +169,10 @@ public enum ScriptClientValueArgument implements ScriptArgument { private final String name; private final ItemStack icon; - private final BiFunction consumer; + private final Function consumer; private final ScriptActionArgumentType type; - ScriptClientValueArgument(String name, String description, Item type, ScriptActionArgumentType varType, BiFunction consumer) { + ScriptClientValueArgument(String name, String description, Item type, ScriptActionArgumentType varType, Function consumer) { this.name = name; this.icon = new ItemStack(type); icon.setCustomName(Text.literal(name) @@ -195,8 +198,8 @@ public ItemStack getIcon() { } @Override - public ScriptValue getValue(Event event, ScriptContext context) { - return consumer.apply(event, context); + public ScriptValue getValue(ScriptTask task) { + return consumer.apply(task); } @Override diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptConfigArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptConfigArgument.java index 9779eb9..11480eb 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptConfigArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptConfigArgument.java @@ -8,6 +8,7 @@ import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.action.ScriptActionArgument; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.options.ScriptNamedOption; import io.github.techstreet.dfscript.script.values.ScriptValue; @@ -25,7 +26,7 @@ public ScriptConfigArgument(String option, Script script) { } @Override - public ScriptValue getValue(Event event, ScriptContext context) { + public ScriptValue getValue(ScriptTask task) { return script.getOption(option); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptNumberArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptNumberArgument.java index 1df772f..fe72ecb 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptNumberArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptNumberArgument.java @@ -7,6 +7,7 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.values.ScriptNumberValue; import io.github.techstreet.dfscript.script.values.ScriptValue; import java.lang.reflect.Type; @@ -14,7 +15,7 @@ public record ScriptNumberArgument(double value) implements ScriptArgument { @Override - public ScriptValue getValue(Event event, ScriptContext context) { + public ScriptValue getValue(ScriptTask task) { return new ScriptNumberValue(value); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptTextArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptTextArgument.java index dbde9bb..c59d209 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptTextArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptTextArgument.java @@ -7,6 +7,7 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.values.ScriptTextValue; import io.github.techstreet.dfscript.script.values.ScriptValue; import java.lang.reflect.Type; @@ -14,7 +15,7 @@ public record ScriptTextArgument(String value) implements ScriptArgument { @Override - public ScriptValue getValue(Event event, ScriptContext context) { + public ScriptValue getValue(ScriptTask task) { return new ScriptTextValue(value); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptUnknownArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptUnknownArgument.java index ed1004e..05a9d27 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptUnknownArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptUnknownArgument.java @@ -3,12 +3,13 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.values.ScriptUnknownValue; import io.github.techstreet.dfscript.script.values.ScriptValue; public record ScriptUnknownArgument() implements ScriptArgument { @Override - public ScriptValue getValue(Event event, ScriptContext context) { + public ScriptValue getValue(ScriptTask task) { return new ScriptUnknownValue(); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptVariableArgument.java b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptVariableArgument.java index e755bb0..513b162 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptVariableArgument.java +++ b/src/main/java/io/github/techstreet/dfscript/script/argument/ScriptVariableArgument.java @@ -7,14 +7,15 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; import io.github.techstreet.dfscript.script.execution.ScriptContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; import io.github.techstreet.dfscript.script.values.ScriptValue; import java.lang.reflect.Type; -public record ScriptVariableArgument(String name) implements ScriptArgument{ +public record ScriptVariableArgument(String name) implements ScriptArgument { @Override - public ScriptValue getValue(Event event, ScriptContext context) { - return context.getVariable(name); + public ScriptValue getValue(ScriptTask task) { + return task.context().getVariable(name); } diff --git a/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBranch.java b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBranch.java new file mode 100644 index 0000000..d57c6d3 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBranch.java @@ -0,0 +1,143 @@ +package io.github.techstreet.dfscript.script.conditions; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.techstreet.dfscript.screen.ContextMenuButton; +import io.github.techstreet.dfscript.script.*; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderIconElement; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class ScriptBranch extends ScriptParametrizedPart implements ScriptScopeParent { + + public static String closeBracketName = "Close Bracket"; + public static ItemStack closeBracketIcon = new ItemStack(Items.PISTON); + static String elseName = "Else"; + static ItemStack elseIcon = new ItemStack(Items.END_STONE); + + static { + closeBracketIcon.setCustomName(Text.literal(closeBracketName) + .fillStyle(Style.EMPTY + .withColor(Formatting.WHITE) + .withItalic(false))); + + NbtList lore = new NbtList(); + + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("Closes the current code block.").setStyle(Style.EMPTY.withColor(Formatting.GRAY).withItalic(false))))); + + closeBracketIcon.getSubNbt("display") + .put("Lore", lore); + + elseIcon.setCustomName(Text.literal(closeBracketName) + .fillStyle(Style.EMPTY + .withColor(Formatting.WHITE) + .withItalic(false))); + + lore = new NbtList(); + + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("Executes if the last IF condition failed.").setStyle(Style.EMPTY.withColor(Formatting.GRAY).withItalic(false))))); + + elseIcon.getSubNbt("display") + .put("Lore", lore); + } + boolean hasElse = false; + + ScriptCondition condition; + ScriptContainer container; + + public ScriptBranch(List arguments, ScriptCondition condition) { + super(arguments); + this.condition = condition; + container = new ScriptContainer(2); + } + + @Override + public void create(ScriptPartRender render, Script script) { + condition.create(render, script); + + render.addElement(container.createSnippet(0)); + + render.addElement(new ScriptPartRenderIconElement(closeBracketName, closeBracketIcon)); + + if(hasElse) + { + render.addElement(new ScriptPartRenderIconElement(elseName, elseIcon)); + + render.addElement(container.createSnippet(1)); + + render.addElement(new ScriptPartRenderIconElement(closeBracketName, closeBracketIcon)); + } + } + + public ScriptBranch setHasElse() { + hasElse = !hasElse; + return this; + } + + public boolean hasElse() { + return hasElse; + } + + @Override + public void run(ScriptTask task) { + ScriptActionContext actionCtx = new ScriptActionContext(task, getArguments()); + boolean result = condition.run(actionCtx); + + if(!result && !hasElse) return; + + container.runSnippet(task, result ? 0 : 1, this); + } + + public ScriptCondition getCondition() { + return condition; + } + + @Override + public void forEach(Consumer consumer) { + container.forEach(consumer); + } + + @Override + public ScriptContainer container() { + return container; + } + + @Override + public List getContextMenu() { + List extra = new ArrayList<>(); + extra.add(new ContextMenuButton("Invert", () -> condition.invert())); + extra.add(new ContextMenuButton(!hasElse ? "Add Else Statement" : "Remove Else Statement", this::setHasElse)); + return extra; + } + + public static class Serializer implements JsonSerializer { + + @Override + public JsonElement serialize(ScriptBranch src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "branch"); + obj.add("condition", context.serialize(src.condition)); + obj.add("arguments", context.serialize(src.getArguments())); + obj.addProperty("hasElse", src.hasElse); + obj.add("true", context.serialize(src.container().getSnippet(0))); + obj.add("false", context.serialize(src.container().getSnippet(1))); + return obj; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBuiltinCondition.java b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBuiltinCondition.java new file mode 100644 index 0000000..bfc6950 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptBuiltinCondition.java @@ -0,0 +1,64 @@ +package io.github.techstreet.dfscript.script.conditions; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptContainer; +import io.github.techstreet.dfscript.script.ScriptPart; +import io.github.techstreet.dfscript.script.action.ScriptAction; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderIconElement; +import net.minecraft.text.Text; + +import java.lang.reflect.Type; +import java.util.List; + +public class ScriptBuiltinCondition extends ScriptCondition { + ScriptConditionType type; + + public ScriptBuiltinCondition(ScriptConditionType type) { + this.type = type; + } + + @Override + public void create(ScriptPartRender render, Script script) { + render.addElement(new ScriptPartRenderIconElement((isInverted() ? "Unless " : "If ") + getType().getName(), getType().getIcon())); + + super.create(render, script); + } + + @Override + public boolean run(ScriptActionContext ctx) { + return type.run(ctx) != isInverted(); + } + + public ScriptBuiltinCondition setType(ScriptConditionType newType) { + type = newType; + + return this; + } + + public ScriptConditionType getType() { + return type; + } + + public static class Serializer implements JsonSerializer { + + @Override + public JsonElement serialize(ScriptBuiltinCondition src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "condition"); + obj.addProperty("inverted", src.isInverted()); + obj.addProperty("condition", src.getType().name()); + return obj; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptCondition.java b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptCondition.java new file mode 100644 index 0000000..103befb --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptCondition.java @@ -0,0 +1,65 @@ +package io.github.techstreet.dfscript.script.conditions; + +import com.google.gson.*; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.*; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.repetitions.ScriptBuiltinRepetition; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetitionType; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +public abstract class ScriptCondition { + boolean inverted = false; + + public void create(ScriptPartRender render, Script script) { + + } + + public ScriptCondition invert() { + inverted = !inverted; + return this; + } + + public boolean isInverted() { + return inverted; + } + + public boolean run(ScriptActionContext ctx) { + return false; + } + + public static class Serializer implements JsonDeserializer { + + @Override + public ScriptCondition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject obj = json.getAsJsonObject(); + boolean inverted = obj.get("inverted").getAsBoolean(); + String type = obj.get("type").getAsString(); + ScriptCondition condition; + switch (type) { + case "condition" -> condition = new ScriptBuiltinCondition(ScriptConditionType.valueOf(obj.get("condition").getAsString())); + default -> throw new JsonParseException("Unknown script condition type: " + type); + } + if(inverted) condition.invert(); + return condition; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptConditionType.java b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptConditionType.java new file mode 100644 index 0000000..12affd0 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/conditions/ScriptConditionType.java @@ -0,0 +1,472 @@ +package io.github.techstreet.dfscript.script.conditions; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.event.HudRenderEvent; +import io.github.techstreet.dfscript.event.system.CancellableEvent; +import io.github.techstreet.dfscript.script.ScriptGroup; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; +import io.github.techstreet.dfscript.script.action.ScriptActionArgumentList; +import io.github.techstreet.dfscript.script.action.ScriptActionCategory; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.menu.*; +import io.github.techstreet.dfscript.script.util.ScriptValueItem; +import io.github.techstreet.dfscript.script.util.ScriptValueJson; +import io.github.techstreet.dfscript.script.values.*; +import io.github.techstreet.dfscript.util.*; +import io.github.techstreet.dfscript.util.chat.ChatUtil; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.sound.SoundManager; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; +import net.minecraft.sound.SoundEvent; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.world.GameMode; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public enum ScriptConditionType { + + IF_EQUALS(builder -> builder.name("Equals") + .description("Checks if one value is equal to another.") + .icon(Items.IRON_INGOT) + .category(ScriptActionCategory.VARIABLES) + .arg("Value", ScriptActionArgumentType.ANY) + .arg("Other", ScriptActionArgumentType.ANY) + .action(ctx -> ctx.value("Value").valueEquals(ctx.value("Other")))), + + IF_NOT_EQUALS(builder -> builder.name("Not Equals") + .description("Checks if one value is not equal to another.") + .icon(Items.BARRIER) + .category(ScriptActionCategory.VARIABLES) + .arg("Value", ScriptActionArgumentType.ANY) + .arg("Other", ScriptActionArgumentType.ANY) + .deprecate(IF_EQUALS) + .action(ctx -> !ctx.value("Value").valueEquals(ctx.value("Other")))), + + IF_GREATER(builder -> builder.name("Greater") + .description("Checks if one number is greater than another.") + .icon(Items.BRICK) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Other", ScriptActionArgumentType.NUMBER) + .action(ctx -> ctx.value("Value").asNumber() > ctx.value("Other").asNumber())), + + IF_GREATER_EQUALS(builder -> builder.name("Greater Equals") + .description("Checks if one number is greater than or equal to another.") + .icon(Items.BRICKS) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Other", ScriptActionArgumentType.NUMBER) + .action(ctx -> ctx.value("Value").asNumber() >= ctx.value("Other").asNumber())), + + IF_LESS(builder -> builder.name("Less") + .description("Checks if one number is less than another.") + .icon(Items.NETHER_BRICK) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Other", ScriptActionArgumentType.NUMBER) + .action(ctx -> ctx.value("Value").asNumber() < ctx.value("Other").asNumber())), + + IF_LESS_EQUALS(builder -> builder.name("If Less Equals") + .description("Checks if one number is less than or equal to another.") + .icon(Items.NETHER_BRICKS) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Other", ScriptActionArgumentType.NUMBER) + .action(ctx -> ctx.value("Value").asNumber() <= ctx.value("Other").asNumber())), + + IF_WITHIN_RANGE(builder -> builder.name("Number Within Range") + .description("Checks if a number is between\n2 different numbers (inclusive).") + .icon(Items.CHEST) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Minimum", ScriptActionArgumentType.NUMBER) + .arg("Maximum", ScriptActionArgumentType.NUMBER) + .action(ctx -> { + double value = ctx.value("Value").asNumber(); + + if (value >= ctx.value("Minimum").asNumber()) { + if (value <= ctx.value("Maximum").asNumber()) { + return true; + } + } + return false; + })), + + IF_NOT_WITHIN_RANGE(builder -> builder.name("Number Not Within Range") + .description("Checks if a number isn't between\n2 different numbers (inclusive).") + .icon(Items.TRAPPED_CHEST) + .category(ScriptActionCategory.NUMBERS) + .arg("Value", ScriptActionArgumentType.NUMBER) + .arg("Minimum", ScriptActionArgumentType.NUMBER) + .arg("Maximum", ScriptActionArgumentType.NUMBER) + .deprecate(IF_WITHIN_RANGE) + .action(ctx -> { + double value = ctx.value("Value").asNumber(); + + if (value >= ctx.value("Minimum").asNumber()) { + if (value <= ctx.value("Maximum").asNumber()) { + return false; + } + } + + return true; + })), + + IF_LIST_CONTAINS(builder -> builder.name("List Contains") + .description("Checks if a list contains a value.") + .icon(Items.BOOKSHELF) + .category(ScriptActionCategory.LISTS) + .arg("List", ScriptActionArgumentType.LIST) + .arg("Value", ScriptActionArgumentType.ANY) + .action(ctx -> { + List list = ctx.value("List").asList(); + return list.stream().anyMatch(value -> value.valueEquals(ctx.value("Value"))); + })), + + IF_TEXT_CONTAINS(builder -> builder.name("Text Contains") + .description("Checks if a text contains a value.") + .icon(Items.NAME_TAG) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Subtext", ScriptActionArgumentType.TEXT) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String subtext = ctx.value("Subtext").asText(); + return text.contains(subtext); + })), + + IF_MATCHES_REGEX(builder -> builder.name("Matches Regex") + .description("Checks if a text matches a regex.") + .icon(Items.ANVIL) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Regex", ScriptActionArgumentType.TEXT) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String regex = ctx.value("Regex").asText(); + return text.matches(regex); + })), + + IF_STARTS_WITH(builder -> builder.name("Starts With") + .description("Checks if a text starts with an other.") + .icon(Items.FEATHER) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Subtext", ScriptActionArgumentType.TEXT) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String subtext = ctx.value("Subtext").asText(); + return text.startsWith(subtext); + })), + + IF_LIST_DOESNT_CONTAIN(builder -> builder.name("List Doesnt Contain") + .description("Checks if a list doesnt contain a value.") + .icon(Items.BOOKSHELF) + .category(ScriptActionCategory.LISTS) + .arg("List", ScriptActionArgumentType.LIST) + .arg("Value", ScriptActionArgumentType.ANY) + .deprecate(IF_LIST_CONTAINS) + .action(ctx -> { + List list = ctx.value("List").asList(); + return list.stream().noneMatch(value -> value.valueEquals(ctx.value("Value"))); + })), + + IF_TEXT_DOESNT_CONTAIN(builder -> builder.name("Text Doesnt Contain") + .description("Checks if a text doesnt contain a value.") + .icon(Items.NAME_TAG) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Subtext", ScriptActionArgumentType.TEXT) + .deprecate(IF_TEXT_CONTAINS) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String subtext = ctx.value("Subtext").asText(); + return !text.contains(subtext); + })), + + IF_DOESNT_START_WITH(builder -> builder.name("Doesnt Start With") + .description("Checks if a text doesnt start with an other.") + .icon(Items.FEATHER) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Subtext", ScriptActionArgumentType.TEXT) + .deprecate(IF_STARTS_WITH) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String subtext = ctx.value("Subtext").asText(); + return !text.startsWith(subtext); + })), + + IF_DOESNT_MATCH_REGEX(builder -> builder.name("Doesnt Match Regex") + .description("Checks if a text doesnt match a regex.") + .icon(Items.ANVIL) + .category(ScriptActionCategory.TEXTS) + .arg("Text", ScriptActionArgumentType.TEXT) + .arg("Regex", ScriptActionArgumentType.TEXT) + .deprecate(IF_MATCHES_REGEX) + .action(ctx -> { + String text = ctx.value("Text").asText(); + String regex = ctx.value("Regex").asText(); + return !text.matches(regex); + })), + + IF_DICT_KEY_EXISTS(builder -> builder.name("Dictionary Key Exists") + .description("Checks if a key exists in a dictionary.") + .icon(Items.NAME_TAG) + .category(ScriptActionCategory.DICTIONARIES) + .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) + .arg("Key", ScriptActionArgumentType.TEXT) + .action(ctx -> { + HashMap dict = ctx.value("Dictionary").asDictionary(); + String key = ctx.value("Key").asText(); + return dict.containsKey(key); + })), + + IF_DICT_KEY_DOESNT_EXIST(builder -> builder.name("Dictionary Key Doesnt Exist") + .description("Checks if a key doesnt exist in a dictionary.") + .icon(Items.NAME_TAG) + .category(ScriptActionCategory.DICTIONARIES) + .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) + .arg("Key", ScriptActionArgumentType.TEXT) + .deprecate(IF_DICT_KEY_EXISTS) + .action(ctx -> { + HashMap dict = ctx.value("Dictionary").asDictionary(); + String key = ctx.value("Key").asText(); + return !dict.containsKey(key); + })), + + IF_GUI_OPEN(builder -> builder.name("GUI Open") + .description("Executes if a gui is open.") + .icon(Items.BOOK) + .category(ScriptActionCategory.MISC) + .action(ctx -> { + return DFScript.MC.currentScreen != null; + })), + + IF_GUI_CLOSED(builder -> builder.name("GUI Not Open") + .description("Executes if no gui is open.") + .icon(Items.BOOK) + .deprecate(IF_GUI_OPEN) + .category(ScriptActionCategory.MISC) + .action(ctx -> { + return DFScript.MC.currentScreen == null; + })), + + IF_FILE_EXISTS(builder -> builder.name("File Exists") + .description("Executes if the specified file exists.") + .icon(Items.BOOK) + .category(ScriptActionCategory.MISC) + .arg("Filename", ScriptActionArgumentType.TEXT) + .action(ctx -> { + String filename = ctx.value("Filename").asText(); + if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { + Path f = FileUtil.folder("Scripts").resolve(ctx.task().context().script().getFile().getName()+"-files").resolve(filename); + if (Files.exists(f)) { + return true; + } + } else { + ChatUtil.error("Illegal filename: " + filename); + } + return false; + })), + + IF_FILE_DOESNT_EXIST(builder -> builder.name("File Doesnt Exist") + .description("Executes if the specified file doesnt exist.") + .icon(Items.BOOK) + .category(ScriptActionCategory.MISC) + .arg("Filename", ScriptActionArgumentType.TEXT) + .deprecate(IF_FILE_EXISTS) + .action(ctx -> { + String filename = ctx.value("Filename").asText(); + if (filename.matches("^[a-zA-Z\\d_\\-\\. ]+$")) { + Path f = FileUtil.folder("Scripts").resolve(ctx.task().context().script().getFile().getName()+"-files").resolve(filename); + if (!Files.exists(f)) { + return true; + } + } else { + ChatUtil.error("Illegal filename: " + filename); + } + return false; + })), + + TRUE(builder -> builder.name("True") + .description("Always executes.\nLiterally the only reason for this is so the\nlegacy deserializer code doesn't have to discard ELSEs\nthat aren't tied to a CONDITION...") + .icon(Items.LIME_WOOL) + .category(null) + .action(ctx -> true)); + + private Function action = (ctx) -> false; + + private boolean glow = false; + private Item icon = Items.STONE; + private String name = "Unnamed Condition"; + private boolean hasChildren = false; + private ScriptActionCategory category = ScriptActionCategory.MISC; + private List description = new ArrayList(); + private ScriptGroup group = ScriptGroup.ACTION; + + private ScriptConditionType deprecated = null; //if deprecated == null, the action is not deprecated + private final ScriptActionArgumentList arguments = new ScriptActionArgumentList(); + ScriptConditionType(Consumer builder) { + description.add("No description provided."); + builder.accept(this); + } + public ItemStack getIcon() { + ItemStack item = new ItemStack(icon); + + item.setCustomName(Text.literal(name) + .fillStyle(Style.EMPTY + .withColor(Formatting.WHITE) + .withItalic(false))); + + NbtList lore = new NbtList(); + + if(isDeprecated()) + { + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("This action is deprecated!") + .fillStyle(Style.EMPTY + .withColor(Formatting.RED) + .withItalic(false))))); + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("Use '" + deprecated.getName() + "'") + .fillStyle(Style.EMPTY + .withColor(Formatting.RED) + .withItalic(false))))); + } + + for (String descriptionLine: description) { + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal(descriptionLine) + .fillStyle(Style.EMPTY + .withColor(Formatting.GRAY) + .withItalic(false))))); + } + + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("")))); + + for (ScriptActionArgument arg : arguments) { + lore.add(NbtString.of(Text.Serializer.toJson(arg.text()))); + } + + item.getSubNbt("display") + .put("Lore", lore); + + if(glow) + { + item.addEnchantment(Enchantments.UNBREAKING, 1); + item.addHideFlag(ItemStack.TooltipSection.ENCHANTMENTS); + } + + return item; + } + public String getName() { + return name; + } + + public boolean isDeprecated() { + return deprecated != null; + } + + public boolean hasChildren() { + return hasChildren; + } + + public ScriptActionCategory getCategory() { + return category; + } + + private ScriptConditionType action(Function action) { + this.action = action; + return this; + } + + private ScriptConditionType icon(Item icon, boolean glow) { + this.icon = icon; + this.glow = glow; + return this; + } + + private ScriptConditionType icon(Item icon) { + icon(icon, false); + return this; + } + + private ScriptConditionType name(String name) { + this.name = name; + return this; + } + + private ScriptConditionType hasChildren(boolean hasChildren) { + this.hasChildren = hasChildren; + return this; + } + + private ScriptConditionType category(ScriptActionCategory category) { + this.category = category; + return this; + } + + private ScriptConditionType description(String description) { + this.description.clear(); + this.description.addAll(Arrays.asList(description.split("\n", -1))); + return this; + } + + public ScriptConditionType arg(String name, ScriptActionArgumentType type, Consumer builder) { + ScriptActionArgument arg = new ScriptActionArgument(name, type); + builder.accept(arg); + arguments.add(arg); + return this; + } + + public ScriptConditionType arg(String name, ScriptActionArgumentType type) { + return arg(name, type, (arg) -> { + }); + } + + public ScriptConditionType deprecate(ScriptConditionType newScriptConditionType) { + deprecated = newScriptConditionType; + + return this; + } + + public boolean run(ScriptActionContext ctx) { + try + { + arguments.getArgMap(ctx); + return action.apply(ctx); + } + catch(IllegalArgumentException e) + { + ChatUtil.error("Invalid arguments for " + name + "."); + return false; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEmptyHeader.java b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEmptyHeader.java new file mode 100644 index 0000000..8da7fd1 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEmptyHeader.java @@ -0,0 +1,59 @@ +package io.github.techstreet.dfscript.script.event; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; + +import java.awt.*; +import java.lang.reflect.Type; + +public class ScriptEmptyHeader extends ScriptHeader { + + static String emptyName; + static ItemStack emptyIcon; + + static { + emptyName = "Empty..."; + + emptyIcon = new ItemStack(Items.LIGHT_GRAY_DYE); + emptyIcon.setCustomName(Text.literal(emptyName).setStyle(Style.EMPTY.withItalic(false).withColor(Formatting.WHITE))); + + NbtList lore = new NbtList(); + + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("Literally can never be triggered...").setStyle(Style.EMPTY.withColor(Formatting.GRAY).withItalic(false))))); + + emptyIcon.getSubNbt("display") + .put("Lore", lore); + } + + public static class Serializer implements JsonSerializer { + + @Override + public JsonElement serialize(ScriptEmptyHeader src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "empty"); + obj.add("snippet", context.serialize(src.container().getSnippet(0))); + return obj; + } + } + + public int create(CScrollPanel panel, int y, int index, Script script) { + panel.add(new CItem(5, y, emptyIcon)); + panel.add(new CText(15, y + 2, Text.literal(emptyName))); + + return super.create(panel, y, index, script); + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEvent.java b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEvent.java index ec93ac9..310ef48 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEvent.java +++ b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptEvent.java @@ -1,14 +1,18 @@ package io.github.techstreet.dfscript.script.event; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; +import com.google.gson.*; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; import io.github.techstreet.dfscript.script.ScriptGroup; import io.github.techstreet.dfscript.script.ScriptPart; +import io.github.techstreet.dfscript.script.ScriptSnippet; +import net.minecraft.text.Text; + import java.lang.reflect.Type; -public class ScriptEvent implements ScriptPart { +public class ScriptEvent extends ScriptHeader { private final ScriptEventType type; @@ -20,11 +24,6 @@ public ScriptEventType getType() { return type; } - @Override - public ScriptGroup getGroup() { - return ScriptGroup.EVENT; - } - public static class Serializer implements JsonSerializer { @Override @@ -32,8 +31,15 @@ public JsonElement serialize(ScriptEvent src, Type typeOfSrc, JsonSerializationC JsonObject obj = new JsonObject(); obj.addProperty("type", "event"); obj.addProperty("event", src.getType().name()); + obj.add("snippet", context.serialize(src.container().getSnippet(0))); return obj; } } + public int create(CScrollPanel panel, int y, int index, Script script) { + panel.add(new CItem(5, y, getType().getIcon())); + panel.add(new CText(15, y + 2, Text.literal(getType().getName()))); + + return super.create(panel, y, index, script); + } } diff --git a/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeader.java b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeader.java new file mode 100644 index 0000000..b002033 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeader.java @@ -0,0 +1,67 @@ +package io.github.techstreet.dfscript.script.event; + +import com.google.gson.*; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.*; +import io.github.techstreet.dfscript.script.action.ScriptActionType; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptTask; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public abstract class ScriptHeader implements ScriptRunnable, ScriptScopeParent { + + ScriptContainer container; + ScriptHeader() + { + container = new ScriptContainer(1); + } + + @Override + public void run(ScriptTask task) + { + container.runSnippet(task, 0, this); + } + + public int create(CScrollPanel panel, int y, int index, Script script) { + y += 10; + return container.createSnippet(0, panel, y, 1, script); + } + + @Override + public void forEach(Consumer consumer) { + container.forEach(consumer); + } + + @Override + public ScriptContainer container() { + return container; + } + + public static class Serializer implements JsonDeserializer { + + @Override + public ScriptHeader deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject obj = json.getAsJsonObject(); + String type = obj.get("type").getAsString(); + ScriptHeader header; + switch (type) { + case "empty" -> { + header = new ScriptEmptyHeader(); + } + case "event" -> { + String event = obj.get("event").getAsString(); + header = new ScriptEvent(ScriptEventType.valueOf(event)); + } + default -> throw new JsonParseException("Unknown script header type: " + type); + } + header.container().setSnippet(0, context.deserialize(obj.getAsJsonObject("snippet"), ScriptSnippet.class)); + + return header; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeaderCategory.java b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeaderCategory.java new file mode 100644 index 0000000..9e58d2e --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/event/ScriptHeaderCategory.java @@ -0,0 +1,29 @@ +package io.github.techstreet.dfscript.script.event; + +import io.github.techstreet.dfscript.script.ScriptComment; +import io.github.techstreet.dfscript.script.action.ScriptActionCategoryExtra; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.Style; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.List; + +public enum ScriptHeaderCategory { + + EVENTS("Events", Items.DIAMOND) + ; + + private final ItemStack icon; + + ScriptHeaderCategory(String name, Item icon) { + this.icon = new ItemStack(icon); + this.icon.setCustomName(Text.literal(name).fillStyle(Style.EMPTY.withItalic(false))); + } + + public ItemStack getIcon() { + return icon; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptActionContext.java b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptActionContext.java index 95bf707..8f54e8d 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptActionContext.java +++ b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptActionContext.java @@ -7,10 +7,20 @@ import io.github.techstreet.dfscript.script.values.ScriptValue; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Collectors; -public record ScriptActionContext(ScriptContext context, List arguments, Event event, Consumer inner, ScriptTask task, HashMap> argMap, Script script) { +public final class ScriptActionContext { + private final ScriptTask task; + private final List arguments; + private final HashMap> argMap; + + public ScriptActionContext(ScriptTask task, List arguments) { + this.task = task; + this.arguments = arguments; + this.argMap = new HashMap<>(); + } public void setArg(String name, List args) { argMap.put(name, args); @@ -25,18 +35,18 @@ public ScriptArgument arg(String name) { } public ScriptValue value(String name) { - return arg(name).getValue(event,context); + return arg(name).getValue(task); } public List pluralValue(String name) { - return pluralArg(name).stream().map(arg -> arg.getValue(event,context)).collect(Collectors.toList()); + return pluralArg(name).stream().map(arg -> arg.getValue(task)).collect(Collectors.toList()); } public ScriptVariableArgument variable(String name) { return (ScriptVariableArgument) arg(name); } - public void scheduleInner(Runnable runnable) { + /*public void scheduleInner(Runnable runnable) { inner.accept(new ScriptScopeVariables(runnable, null, this)); } @@ -60,17 +70,53 @@ public void setLastIfResult(boolean a, int n) { } public void setLastIfResult(boolean a) { setLastIfResult(a, 0); - } + }*/ public void setScopeVariable(String name, Object object) { - task().stack().peekElement(0).setVariable(name, object); + task().stack().peek(0).setVariable(name, object); } public Object getScopeVariable(String name) { - return task().stack().peekElement(0).getVariable(name); + return task().stack().peek(0).getVariable(name); } public boolean hasScopeVariable(String name) { - return task().stack().peekElement(0).hasVariable(name); + return task().stack().peek(0).hasVariable(name); + } + + public ScriptTask task() { + return task; + } + + public List arguments() { + return arguments; + } + + public HashMap> argMap() { + return argMap; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (ScriptActionContext) obj; + return Objects.equals(this.task, that.task) && + Objects.equals(this.arguments, that.arguments) && + Objects.equals(this.argMap, that.argMap); + } + + @Override + public int hashCode() { + return Objects.hash(task, arguments, argMap); + } + + @Override + public String toString() { + return "ScriptActionContext[" + + "task=" + task + ", " + + "arguments=" + arguments + ", " + + "argMap=" + argMap + ']'; } + } diff --git a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStack.java b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStack.java index 896d053..7b6765d 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStack.java +++ b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStack.java @@ -1,18 +1,18 @@ package io.github.techstreet.dfscript.script.execution; +import io.github.techstreet.dfscript.script.ScriptScopeParent; +import io.github.techstreet.dfscript.script.ScriptSnippet; + import java.util.ArrayList; import java.util.List; public class ScriptPosStack { private final List data = new ArrayList<>(); - public ScriptPosStack(int initial) { - push(initial); - } - public void push(int value, ScriptScopeVariables variables) { - data.add(new ScriptPosStackElement(value, variables)); + public ScriptPosStack() { + } - public void push(int value) { - data.add(new ScriptPosStackElement(value)); + public void push(ScriptSnippet snippet, ScriptScopeParent parent) { + data.add(new ScriptPosStackElement(snippet, parent)); } public void pop() { @@ -21,40 +21,11 @@ public void pop() { return; } ScriptPosStackElement element = data.remove(data.size() - 1); - element.runPreTask(); - } - - public int peek() { - return peek(0); - } - - public int peekOriginal() { - return peekOriginal(0); } - public ScriptPosStackElement peekElement() { return peekElement(0); } - - public int peek(int n) - { - ScriptPosStackElement element = peekElement(n); - if(element == null) - { - return -1; - } - return element.getPos(); - } - - public int peekOriginal(int n) - { - ScriptPosStackElement element = peekElement(n); - if(element == null) - { - return -1; - } - return element.getOriginalPos(); - } + public ScriptPosStackElement peek() { return peek(0); } - public ScriptPosStackElement peekElement(int n) { + public ScriptPosStackElement peek(int n) { if(!(data.size() - 1 - n >= 0)) { return null; @@ -74,7 +45,7 @@ public void clear() { } public void increase() { - ScriptPosStackElement element = peekElement(); + ScriptPosStackElement element = peek(); data.set(data.size() - 1, element.setPos(element.getPos()+1)); } } diff --git a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStackElement.java b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStackElement.java index 53fe267..6ec4f2c 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStackElement.java +++ b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptPosStackElement.java @@ -1,50 +1,28 @@ package io.github.techstreet.dfscript.script.execution; +import io.github.techstreet.dfscript.script.ScriptScopeParent; +import io.github.techstreet.dfscript.script.ScriptSnippet; +import io.github.techstreet.dfscript.script.repetitions.ScriptRepetition; +import io.github.techstreet.dfscript.util.chat.ChatUtil; + import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; public class ScriptPosStackElement { - private int pos; - private int originalPos; - private Runnable preTask = null; - private Consumer condition = null; - - private ScriptActionContext defaultCtx = null; + private int pos = 0; + private final ScriptSnippet snippet; + private final ScriptScopeParent parent; private Map scopeVariables = new HashMap<>(); - public ScriptPosStackElement(int initial) { - originalPos = initial; - setPos(originalPos); - } - public ScriptPosStackElement(int initial, Runnable preTask) { - originalPos = initial; - setPos(originalPos); - this.preTask = preTask; - } - public ScriptPosStackElement(int initial, Runnable preTask, Consumer condition) { - originalPos = initial; - setPos(originalPos); - this.preTask = preTask; - this.condition = condition; - } - - public ScriptPosStackElement(int initial, ScriptScopeVariables variables) { - originalPos = initial; - setPos(originalPos); - - if(variables == null) - { - this.preTask = null; - this.condition = null; - this.defaultCtx = null; - return; + public ScriptPosStackElement(ScriptSnippet snippet, ScriptScopeParent parent) { + this.snippet = snippet; + this.parent = parent; + setPos(0); + if(parent instanceof ScriptRepetition) { + setPos(this.snippet.size()); } - - this.preTask = variables.preTask; - this.condition = variables.condition; - this.defaultCtx = variables.ctx; } public ScriptPosStackElement setPos(int pos) { this.pos = pos; @@ -53,27 +31,38 @@ public ScriptPosStackElement setPos(int pos) { public int getPos() { return pos; } - public int getOriginalPos() { - return originalPos; - } - public void runPreTask() { - if (preTask != null) { - preTask.run(); - } + + public ScriptScopeParent getParent() { + return parent; } - public boolean checkCondition() { - if(condition == null) - { - return false; + + public boolean executeOnce(ScriptTask task) { + if(pos >= snippet.size()) { + if (!(parent instanceof ScriptRepetition r)) { + return true; + } + if(!hasVariable("Lagslayer Count")) { + setVariable("Lagslayer Count", 0); + } + + setVariable("Lagslayer Count", (Integer)getVariable("Lagslayer Count")+1); + + if((Integer)getVariable("Lagslayer Count") > 100000) { + ChatUtil.error("Lagslayer triggered in script: " + task.context().script().getName()); + task.stop(); + return true; + } + + if (!r.checkCondition(task)) { + return true; + } + pos = 0; } - defaultCtx.setLastIfResult(false); + snippet.get(pos).run(task); - condition.accept(defaultCtx); - return defaultCtx.lastIfResult(); - } - public boolean hasCondition() { - return condition != null; + pos++; + return false; } public Object getVariable(String name) { @@ -87,4 +76,8 @@ public void setVariable(String name, Object value) { public boolean hasVariable(String name) { return scopeVariables.containsKey(name); } + + public void skip() { + setPos(snippet.size()); + } } \ No newline at end of file diff --git a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptTask.java b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptTask.java index c107784..2becdad 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptTask.java +++ b/src/main/java/io/github/techstreet/dfscript/script/execution/ScriptTask.java @@ -2,28 +2,45 @@ import io.github.techstreet.dfscript.event.system.Event; import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.util.chat.ChatUtil; public class ScriptTask { private final ScriptPosStack stack; private final Event event; private boolean running; - private final Script script; + private final ScriptContext context; public ScriptTask(ScriptPosStack stack, Event event, Script script) { this.stack = stack; this.event = event; - this.script = script; + this.context = script.getContext(); running = true; } + public ScriptTask(Event event, Script script) { + this(new ScriptPosStack(), event, script); + } + + public ScriptContext context() { + return context; + } + public void stop() { running = false; } public void run() { running = true; - script.execute(this); + while(true) { + if(!running) break; + if(stack.size() <= 0) break; + + if(stack.peek().executeOnce(this)) { + stack.pop(); + } + } + //script.execute(this); } public ScriptPosStack stack() { @@ -37,12 +54,4 @@ public Event event() { public boolean isRunning() { return running; } - public void schedule(int posCopy, ScriptScopeVariables scriptScopeVariables) { - stack.push(posCopy, scriptScopeVariables); - - if(stack.peekElement().hasCondition() && !stack.peekElement().checkCondition()) { - stack.pop(); - return; - } - } } diff --git a/src/main/java/io/github/techstreet/dfscript/script/menu/ScriptMenuButton.java b/src/main/java/io/github/techstreet/dfscript/script/menu/ScriptMenuButton.java index 7eff42d..4e883fe 100644 --- a/src/main/java/io/github/techstreet/dfscript/script/menu/ScriptMenuButton.java +++ b/src/main/java/io/github/techstreet/dfscript/script/menu/ScriptMenuButton.java @@ -25,7 +25,7 @@ public String getIdentifier() { public boolean mouseClicked(double x, double y, int button) { if (getBounds().contains(x,y)) { DFScript.MC.getSoundManager().play(PositionedSoundInstance.ambient(SoundEvents.UI_BUTTON_CLICK, 1f,1f)); - script.invoke(new ScriptMenuClickButtonEvent(identifier)); + //script.invoke(new ScriptMenuClickButtonEvent(identifier)); return true; } return false; diff --git a/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRender.java b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRender.java new file mode 100644 index 0000000..b76ad04 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRender.java @@ -0,0 +1,76 @@ +package io.github.techstreet.dfscript.script.render; + +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.screen.widget.CWidget; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptSnippet; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class ScriptPartRender { + List elements = new ArrayList<>(); + List buttonPos = new ArrayList<>(); + + public ScriptPartRender() { + + } + + public ScriptPartRender addElement(ScriptPartRenderElement element) { + elements.add(element); + return this; + } + + public List getButtonPositions() { + return buttonPos; + } + + public int create(CScrollPanel panel, int y, int indent, Script script) { + buttonPos.clear(); + for (ScriptPartRenderElement element : elements) { + int origY = y; + y = element.render(panel, y, indent, script); + if(element.canGenerateButton()) { + createIndent(panel, indent, origY, y - origY - 2); + buttonPos.add(new ScriptButtonPos(origY, y - origY)); + } + } + return y; + } + + public static void createIndent(CScrollPanel panel, int indent, int y, int height) + { + for (int i = 0; i < indent; i ++) { + int xpos = 8 + i*5; + int ypos = y; + panel.add(new CWidget() { + @Override + public void render(MatrixStack stack, int mouseX, int mouseY, float tickDelta) { + DrawableHelper.fill(stack, xpos, ypos, xpos + 1, ypos + height, 0xFF333333); + } + + @Override + public Rectangle getBounds() { + return new Rectangle(0, 0, 0, 0); + } + }); + } + } + + public record ScriptButtonPos(int y, int height) { + public int getY() { + return y; + } + + public int getHeight() { + return height; + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderDynamicElement.java b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderDynamicElement.java new file mode 100644 index 0000000..00a3005 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderDynamicElement.java @@ -0,0 +1,42 @@ +package io.github.techstreet.dfscript.script.render; + +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.util.function.Consumer; +import java.util.function.Function; + +public class ScriptPartRenderDynamicElement implements ScriptPartRenderElement { + private Function onRender; + + public ScriptPartRenderDynamicElement(Function onRender) { + this.onRender = onRender; + } + + @Override + public int render(CScrollPanel panel, int y, int indent, Script script) { + return onRender.apply(new ScriptPartRenderArgs(panel, y, indent, script)); + } + + public record ScriptPartRenderArgs(CScrollPanel panel, int y, int indent, Script script) { + public int y() { + return y; + } + + public int indent() { + return indent; + } + + public CScrollPanel panel() { + return panel; + } + + public Script script() { + return script; + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderElement.java b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderElement.java new file mode 100644 index 0000000..a436b07 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderElement.java @@ -0,0 +1,12 @@ +package io.github.techstreet.dfscript.script.render; + +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.Script; + +public interface ScriptPartRenderElement { + int render(CScrollPanel panel, int y, int indent, Script script); + + default boolean canGenerateButton() { + return true; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderIconElement.java b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderIconElement.java new file mode 100644 index 0000000..46d4f5b --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderIconElement.java @@ -0,0 +1,26 @@ +package io.github.techstreet.dfscript.script.render; + +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +public class ScriptPartRenderIconElement implements ScriptPartRenderElement { + private String name; + private ItemStack icon; + + public ScriptPartRenderIconElement(String name, ItemStack icon) { + this.name = name; + this.icon = icon; + } + + @Override + public int render(CScrollPanel panel, int y, int indent, Script script) { + panel.add(new CItem(5 + indent * 5, y, icon)); + panel.add(new CText(15 + indent * 5, y + 2, Text.literal(name))); + + return y + 10; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderSnippetElement.java b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderSnippetElement.java new file mode 100644 index 0000000..c00c937 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/render/ScriptPartRenderSnippetElement.java @@ -0,0 +1,23 @@ +package io.github.techstreet.dfscript.script.render; + +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.ScriptSnippet; + +public class ScriptPartRenderSnippetElement implements ScriptPartRenderElement { + ScriptSnippet snippet; + + public ScriptPartRenderSnippetElement(ScriptSnippet snippet) { + this.snippet = snippet; + } + + @Override + public int render(CScrollPanel panel, int y, int indent, Script script) { + return snippet.create(panel, y, indent + 1, script); + } + + @Override + public boolean canGenerateButton() { + return false; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptBuiltinRepetition.java b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptBuiltinRepetition.java new file mode 100644 index 0000000..be9b6ab --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptBuiltinRepetition.java @@ -0,0 +1,71 @@ +package io.github.techstreet.dfscript.script.repetitions; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.Script; +import io.github.techstreet.dfscript.script.action.ScriptBuiltinAction; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderIconElement; +import net.minecraft.text.Text; + +import java.lang.reflect.Type; +import java.util.List; + +public class ScriptBuiltinRepetition extends ScriptRepetition { + + private ScriptRepetitionType type; + + public ScriptBuiltinRepetition(List arguments, ScriptRepetitionType type) { + super(arguments); + this.type = type; + } + + @Override + public void create(ScriptPartRender render, Script script) { + render.addElement(new ScriptPartRenderIconElement(getType().getName(), getType().getIcon())); + + super.create(render, script); + } + + public ScriptBuiltinRepetition setType(ScriptRepetitionType newType) { + type = newType; + + return this; + } + + public ScriptRepetitionType getType() { + return type; + } + + @Override + public boolean isDeprecated() { + return type.isDeprecated(); + } + + @Override + public boolean checkCondition(ScriptTask task) { + ScriptActionContext ctx = new ScriptActionContext(task, getArguments()); + return type.run(ctx); + } + + public static class Serializer implements JsonSerializer { + + @Override + public JsonElement serialize(ScriptBuiltinRepetition src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty("type", "repetition"); + obj.addProperty("repetition", src.getType().name()); + obj.add("arguments", context.serialize(src.getArguments())); + obj.add("snippet", context.serialize(src.container().getSnippet(0))); + return obj; + } + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetition.java b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetition.java new file mode 100644 index 0000000..c26ea55 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetition.java @@ -0,0 +1,55 @@ +package io.github.techstreet.dfscript.script.repetitions; + +import io.github.techstreet.dfscript.screen.widget.CItem; +import io.github.techstreet.dfscript.screen.widget.CScrollPanel; +import io.github.techstreet.dfscript.screen.widget.CText; +import io.github.techstreet.dfscript.script.*; +import io.github.techstreet.dfscript.script.argument.ScriptArgument; +import io.github.techstreet.dfscript.script.conditions.ScriptBranch; +import io.github.techstreet.dfscript.script.execution.ScriptTask; +import io.github.techstreet.dfscript.script.render.ScriptPartRender; +import io.github.techstreet.dfscript.script.render.ScriptPartRenderIconElement; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.List; +import java.util.function.Consumer; + +public abstract class ScriptRepetition extends ScriptParametrizedPart implements ScriptScopeParent { + + ScriptContainer container; + + public ScriptRepetition(List arguments) { + super(arguments); + container = new ScriptContainer(1); + } + + @Override + public void create(ScriptPartRender render, Script script) { + render.addElement(container.createSnippet(0)); + + render.addElement(new ScriptPartRenderIconElement(ScriptBranch.closeBracketName, ScriptBranch.closeBracketIcon)); + } + + public abstract boolean checkCondition(ScriptTask task); + + @Override + public final void run(ScriptTask task) { + container.runSnippet(task, 0, this); + } + + @Override + public void forEach(Consumer consumer) { + container.forEach(consumer); + } + + @Override + public ScriptContainer container() { + return container; + } +} diff --git a/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetitionType.java b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetitionType.java new file mode 100644 index 0000000..e0f9a19 --- /dev/null +++ b/src/main/java/io/github/techstreet/dfscript/script/repetitions/ScriptRepetitionType.java @@ -0,0 +1,254 @@ +package io.github.techstreet.dfscript.script.repetitions; + +import io.github.techstreet.dfscript.DFScript; +import io.github.techstreet.dfscript.script.ScriptGroup; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument; +import io.github.techstreet.dfscript.script.action.ScriptActionArgument.ScriptActionArgumentType; +import io.github.techstreet.dfscript.script.action.ScriptActionArgumentList; +import io.github.techstreet.dfscript.script.action.ScriptActionCategory; +import io.github.techstreet.dfscript.script.execution.ScriptActionContext; +import io.github.techstreet.dfscript.script.values.ScriptNumberValue; +import io.github.techstreet.dfscript.script.values.ScriptTextValue; +import io.github.techstreet.dfscript.script.values.ScriptValue; +import io.github.techstreet.dfscript.util.FileUtil; +import io.github.techstreet.dfscript.util.chat.ChatUtil; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; + +public enum ScriptRepetitionType { + + REPEAT_MULTIPLE(builder -> builder.name("RepeatMultiple") + .description("Repeats a specified amount of times.") + .icon(Items.REDSTONE) + .category(ScriptActionCategory.NUMBERS) + .arg("Times", ScriptActionArgumentType.NUMBER) + .arg("Current", ScriptActionArgumentType.VARIABLE, b -> b.optional(true)) + .action(ctx -> { + if(!ctx.hasScopeVariable("Counter")) { + ctx.setScopeVariable("Counter", 0); + } + + int counter = (Integer)ctx.getScopeVariable("Counter")+1; + + if(counter <= ctx.value("Times").asNumber()) { + ctx.setScopeVariable("Counter", counter); + if (ctx.argMap().containsKey("Current")) { + ctx.task().context().setVariable(ctx.variable("Current").name(), new ScriptNumberValue(counter)); + } + return true; + } + return false; + })), + + FOR_EACH_IN_LIST(builder -> builder.name("For Each In List") + .description("Iterates over a list.") + .icon(Items.BOOKSHELF) + .category(ScriptActionCategory.LISTS) + .arg("Variable", ScriptActionArgumentType.VARIABLE) + .arg("List", ScriptActionArgumentType.LIST) + .action(ctx -> { + if(!ctx.hasScopeVariable("Counter")) { + ctx.setScopeVariable("Counter", 0); + } + + int counter = (Integer)ctx.getScopeVariable("Counter")+1; + List list = ctx.value("List").asList(); + + if(counter <= list.size()) { + ctx.setScopeVariable("Counter", counter); + ctx.task().context().setVariable(ctx.variable("Variable").name(), list.get(counter-1)); + return true; + } + return false; + })), + + DICT_FOR_EACH(builder -> builder.name("For Each In Dictionary") + .description("Iterates over a dictionary.") + .icon(Items.BOOKSHELF) + .category(ScriptActionCategory.DICTIONARIES) + .arg("Key", ScriptActionArgumentType.VARIABLE) + .arg("Value", ScriptActionArgumentType.VARIABLE) + .arg("Dictionary", ScriptActionArgumentType.DICTIONARY) + .action(ctx -> { + HashMap dict = ctx.value("Dictionary").asDictionary(); + + if(!ctx.hasScopeVariable("Iterator")) { + ctx.setScopeVariable("Iterator", dict.entrySet().iterator()); + } + + Iterator> iterator = (Iterator>) ctx.getScopeVariable("Iterator"); + + if(iterator.hasNext()) { + Map.Entry entry = iterator.next(); + ctx.setScopeVariable("Iterator", iterator); + ctx.task().context().setVariable(ctx.variable("Key").name(), new ScriptTextValue(entry.getKey())); + ctx.task().context().setVariable(ctx.variable("Value").name(), entry.getValue()); + return true; + } + return false; + })), + + REPEAT_FOREVER(builder -> builder.name("RepeatForever") + .description("Repeats for eternity.\nMake sure to have a Stop Repetition, Stop Codeline or Wait somewhere in the code!\nThere's a lagslayer for the repetition actions.\nIt activates after 100000 iterations with no Wait.") + .icon(Items.GOLD_INGOT) + .category(ScriptActionCategory.MISC) + .action(ctx -> true)); + + private Function action = (ctx) -> false; + + private boolean glow = false; + private Item icon = Items.STONE; + private String name = "Unnamed Action"; + private boolean hasChildren = false; + private ScriptActionCategory category = ScriptActionCategory.MISC; + private List description = new ArrayList(); + + private ScriptRepetitionType deprecated = null; //if deprecated == null, the action is not deprecated + private final ScriptActionArgumentList arguments = new ScriptActionArgumentList(); + ScriptRepetitionType(Consumer builder) { + description.add("No description provided."); + builder.accept(this); + } + public ItemStack getIcon() { + ItemStack item = new ItemStack(icon); + + item.setCustomName(Text.literal(name) + .fillStyle(Style.EMPTY + .withColor(Formatting.WHITE) + .withItalic(false))); + + NbtList lore = new NbtList(); + + if(isDeprecated()) + { + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("This action is deprecated!") + .fillStyle(Style.EMPTY + .withColor(Formatting.RED) + .withItalic(false))))); + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("Use '" + deprecated.getName() + "'") + .fillStyle(Style.EMPTY + .withColor(Formatting.RED) + .withItalic(false))))); + } + + for (String descriptionLine: description) { + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal(descriptionLine) + .fillStyle(Style.EMPTY + .withColor(Formatting.GRAY) + .withItalic(false))))); + } + + lore.add(NbtString.of(Text.Serializer.toJson(Text.literal("")))); + + for (ScriptActionArgument arg : arguments) { + lore.add(NbtString.of(Text.Serializer.toJson(arg.text()))); + } + + item.getSubNbt("display") + .put("Lore", lore); + + if(glow) + { + item.addEnchantment(Enchantments.UNBREAKING, 1); + item.addHideFlag(ItemStack.TooltipSection.ENCHANTMENTS); + } + + return item; + } + public String getName() { + return name; + } + + public boolean isDeprecated() { + return deprecated != null; + } + + public boolean hasChildren() { + return hasChildren; + } + + public ScriptActionCategory getCategory() { + return category; + } + + private ScriptRepetitionType action(Function action) { + this.action = action; + return this; + } + + private ScriptRepetitionType icon(Item icon, boolean glow) { + this.icon = icon; + this.glow = glow; + return this; + } + + private ScriptRepetitionType icon(Item icon) { + icon(icon, false); + return this; + } + + private ScriptRepetitionType name(String name) { + this.name = name; + return this; + } + + private ScriptRepetitionType hasChildren(boolean hasChildren) { + this.hasChildren = hasChildren; + return this; + } + + private ScriptRepetitionType category(ScriptActionCategory category) { + this.category = category; + return this; + } + + private ScriptRepetitionType description(String description) { + this.description.clear(); + this.description.addAll(Arrays.asList(description.split("\n", -1))); + return this; + } + + public ScriptRepetitionType arg(String name, ScriptActionArgumentType type, Consumer builder) { + ScriptActionArgument arg = new ScriptActionArgument(name, type); + builder.accept(arg); + arguments.add(arg); + return this; + } + + public ScriptRepetitionType arg(String name, ScriptActionArgumentType type) { + return arg(name, type, (arg) -> { + }); + } + + public ScriptRepetitionType deprecate(ScriptRepetitionType newScriptRepetitionType) { + deprecated = newScriptRepetitionType; + + return this; + } + + public boolean run(ScriptActionContext ctx) { + try + { + arguments.getArgMap(ctx); + return action.apply(ctx); + } + catch(IllegalArgumentException e) + { + ChatUtil.error("Invalid arguments for " + name + "."); + return false; + } + } +}