diff options
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud')
59 files changed, 741 insertions, 291 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java new file mode 100644 index 00000000..1197ca2d --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java @@ -0,0 +1,166 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import me.xmrvizzy.skyblocker.SkyblockerMod; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline.AlignStage; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline.CollideStage; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PipelineStage; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PlaceStage; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline.StackStage; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EmptyWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EventWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.Identifier; + +public class ScreenBuilder { + + // layout pipeline + private ArrayList<PipelineStage> layoutPipeline = new ArrayList<>(); + + // all widget instances this builder knows + private ArrayList<Widget> instances = new ArrayList<>(); + // maps alias -> widget instance + private HashMap<String, Widget> objectMap = new HashMap<>(); + + /** + * Create a ScreenBuilder from a json. + */ + public ScreenBuilder(String jsonfile) throws IOException { + + Identifier ident = new Identifier(SkyblockerMod.NAMESPACE, "tabhud/" + jsonfile + ".json"); + BufferedReader reader = MinecraftClient.getInstance().getResourceManager().openAsReader(ident); + JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); + reader.close(); + + JsonArray widgets = json.getAsJsonArray("widgets"); + JsonArray layout = json.getAsJsonArray("layout"); + + for (JsonElement w : widgets) { + JsonObject widget = w.getAsJsonObject(); + String name = widget.get("name").getAsString(); + String alias = widget.get("alias").getAsString(); + + Widget wid = instanceFrom(name, widget); + objectMap.put(alias, wid); + instances.add(wid); + } + + for (JsonElement l : layout) { + layoutPipeline.add(createStage(l.getAsJsonObject())); + } + + } + + /** + * Try to find a class in the widget package that has the supplied name and + * call it's constructor. Manual work is required if the class has arguments. + */ + public Widget instanceFrom(String name, JsonObject widget) { + + // do widgets that require args the normal way + switch (name) { + case "EventWidget": + return new EventWidget(widget.get("inGarden").getAsBoolean()); + case "Widget": + // clown case sanity check. don't instantiate the superclass >:| + return new EmptyWidget(); + } + + // reflect something together for the "normal" ones. + // TODO don't get package list for every widget; do it once and cache. + // fine for now, as this would only shorten the load time anyways + + // find all packages that might contain widget classes + Package[] packs = Package.getPackages(); + + List<String> packnames = Arrays.stream(packs) + .map(pack -> pack.getName()) + .filter(s -> s.startsWith("me.xmrvizzy.skyblocker.skyblock.tabhud.widget")) + .toList(); + + // construct the full class name and try to load. + Class<?> clazz = null; + for (String pn : packnames) { + try { + clazz = Class.forName(pn + "." + name); + } catch (LinkageError | ClassNotFoundException ex) { + continue; + } + } + + // load failed. + if (clazz == null) { + return new EmptyWidget(); + } + + // return instance of that class. + try { + Constructor<?> ctor = clazz.getConstructor(); + return (Widget) ctor.newInstance(); + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException | SecurityException ex) { + return new EmptyWidget(); + } + } + + /** + * Create a PipelineStage from a json object. + */ + public PipelineStage createStage(JsonObject descr) { + + String op = descr.get("op").getAsString(); + + switch (op) { + case "place": + return new PlaceStage(this, descr); + case "stack": + return new StackStage(this, descr); + case "align": + return new AlignStage(this, descr); + case "collideAgainst": + return new CollideStage(this, descr); + } + return null; + } + + /** + * Lookup Widget instance from alias name + */ + public Widget getInstance(String name) { + return this.objectMap.get(name); + } + + /** + * Run the pipeline to build a Screen + */ + public void run(DrawContext context, int screenW, int screenH) { + // TODO for future: + // no need to update and run pipeline if PlayerListMgr wasn't updated. + + for (Widget w : instances) { + w.update(); + } + for (PipelineStage ps : layoutPipeline) { + ps.run(screenW, screenH); + } + for (Widget w : instances) { + w.render(context); + } + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java index 02b595d1..97969503 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java @@ -1,4 +1,4 @@ -package me.xmrvizzy.skyblocker.skyblock.tabhud.screens; +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder; import java.io.BufferedReader; import java.io.IOException; @@ -15,7 +15,6 @@ import com.google.gson.JsonParser; import me.xmrvizzy.skyblocker.SkyblockerMod; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; public class ScreenMaster { @@ -23,21 +22,24 @@ public class ScreenMaster { private static final Identifier ASSIGNMENT_JSON = new Identifier(SkyblockerMod.NAMESPACE, "tabhud/assignment.json"); private static final Logger LOGGER = LoggerFactory.getLogger("skyblocker"); - private static HashMap<String, ScreenBuilder> screenAMap = new HashMap<>(); + private static HashMap<String, ScreenBuilder> standardMap = new HashMap<>(); + // private static HashMap<String, ScreenBuilder> screenAMap = new HashMap<>(); // private static HashMap<String, ScreenBuilder> screenBMap = new HashMap<>(); - // private static HashMap<String, ScreenBuilder> screenCMap = new HashMap<>(); static { init(); } + /** + * Load the assignment json and construct the screen mapping + */ public static void init() { try (BufferedReader reader = MinecraftClient.getInstance().getResourceManager().openAsReader(ASSIGNMENT_JSON)) { JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); - JsonObject screenA = json.getAsJsonObject("screenA"); - for (Entry<String, JsonElement> entry : screenA.entrySet()) { - screenAMap.put(entry.getKey(), new ScreenBuilder(entry.getValue().getAsString())); + JsonObject standard = json.getAsJsonObject("standard"); + for (Entry<String, JsonElement> entry : standard.entrySet()) { + standardMap.put(entry.getKey(), new ScreenBuilder(entry.getValue().getAsString())); } } catch (IOException ioex) { @@ -46,13 +48,17 @@ public class ScreenMaster { } } - public static void render(DrawContext context, int w, int h, Text footer) { - screenAMap.get("default").run(context, w, h, footer); + /** + * Top level render method. + * Calls the appropriate ScreenBuilder with the screen's dimensions + */ + public static void render(DrawContext context, int w, int h) { + standardMap.get("default").run(context, w, h); } } /* - * + * * stackWidgetsH stackWidgetsW --> stack (direction?) horiz/vert (align?) center/top/bottom/left/right diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/AlignStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/AlignStage.java new file mode 100644 index 00000000..87638c33 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/AlignStage.java @@ -0,0 +1,53 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline; + +import java.util.ArrayList; + +import com.google.gson.JsonObject; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget; + +public class AlignStage extends PipelineStage { + + private String reference; + + public AlignStage(ScreenBuilder builder, JsonObject descr) { + this.reference = descr.get("reference").getAsString(); + this.primary = new ArrayList<Widget>(descr.getAsJsonArray("apply_to") + .asList() + .stream() + .map(x -> builder.getInstance(x.getAsString())) + .toList()); + } + + public void run(int screenW, int screenH) { + int wHalf, hHalf; + for (Widget wid : primary) { + switch (this.reference) { + case "horizontalCenter": + wid.setX((screenW - wid.getWidth()) / 2); + break; + case "verticalCenter": + wid.setY((screenH - wid.getHeight()) / 2); + break; + case "leftOfCenter": + wHalf = screenW / 2; + wid.setX(wHalf - 3 - wid.getWidth()); + break; + case "rightOfCenter": + wHalf = screenW / 2; + wid.setX(wHalf + 3); + break; + case "topOfCenter": + hHalf = screenH / 2; + wid.setY(hHalf - 3 - wid.getHeight()); + break; + case "botOfCenter": + hHalf = screenH / 2; + wid.setY(hHalf + 3); + break; + } + } + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/CollideStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/CollideStage.java new file mode 100644 index 00000000..8275e842 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/CollideStage.java @@ -0,0 +1,84 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline; + +import java.util.ArrayList; + +import com.google.gson.JsonObject; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget; + +public class CollideStage extends PipelineStage { + + private String direction; + + public CollideStage(ScreenBuilder builder, JsonObject descr) { + this.direction = descr.get("direction").getAsString(); + this.primary = new ArrayList<Widget>(descr.getAsJsonArray("widgets") + .asList() + .stream() + .map(x -> builder.getInstance(x.getAsString())) + .toList()); + this.secondary = new ArrayList<Widget>(descr.getAsJsonArray("colliders") + .asList() + .stream() + .map(x -> builder.getInstance(x.getAsString())) + .toList()); + } + + public void run(int screenW, int screenH) { + if (this.direction.equals("left")) { + primary.forEach(w -> collideAgainstL(screenW, w)); + } else if (this.direction.equals("right")) { + primary.forEach(w -> collideAgainstR(screenW, w)); + } + } + + public void collideAgainstL(int screenW, Widget w) { + int yMin = w.getY(); + int yMax = w.getY() + w.getHeight(); + + int xCor = screenW / 2; + + // assume others to be sorted top-bottom. + for (Widget other : secondary) { + if (other.getY() + other.getHeight() + 5 < yMin) { + // too high, next one + continue; + } + + if (other.getY() - 5 > yMax) { + // too low, next + continue; + } + + int xPos = other.getX() - 5 - w.getWidth(); + xCor = Math.min(xCor, xPos); + } + w.setX(xCor); + } + + public void collideAgainstR(int screenW, Widget w) { + int yMin = w.getY(); + int yMax = w.getY() + w.getHeight(); + + int xCor = screenW / 2; + + // assume others to be sorted top-bottom. + for (Widget other : secondary) { + if (other.getY() + other.getHeight() + 5 < yMin) { + // too high, next one + continue; + } + + if (other.getY() - 5 > yMax) { + // too low, next + continue; + } + + int xPos = other.getX() + other.getWidth() + 5; + xCor = Math.max(xCor, xPos); + } + w.setX(xCor); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/PipelineStage.java index d33078d8..e560058c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/PipelineStage.java @@ -1,4 +1,4 @@ -package me.xmrvizzy.skyblocker.skyblock.tabhud.screens; +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline; import java.util.ArrayList; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/PlaceStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/PlaceStage.java new file mode 100644 index 00000000..3ed89fda --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screenbuilder/pipeline/PlaceStage.java @@ -0,0 +1,31 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.pipeline; + +import java.util.ArrayList; + +import com.google.gson.JsonObject; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget; + +public class PlaceStage extends PipelineStage { + + private String where; + + public PlaceStage(ScreenBuilder builder, JsonObject descr) { + this.where = descr.get("where").getAsString(); + this.primary = new ArrayList<Widget>(descr.getAsJsonArray("apply_to") + .asList() + .stream() + .map(x -> builder.getInstance(x.getAsString())) + .limit(1) + .toList()); + } + + public void run(int screenW, int screenH) { + Widget wid = primary.get(0); + if (where.equals("center")) { + wid.setY((screenH - wid.getHeight()) / 2); + wid.setX((screenW - wid.getWidth()) / 2); + } + } +}
\ No newline at end of file |
