From: Irtimaled Date: Thu, 14 May 2020 03:44:06 +0000 (-0700) Subject: Add support for custom line X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=fe6313739c4de9129dd2304a0b3bb512a22e95f8;p=BoundingBoxOutlineReloaded.git Add support for custom line --- diff --git a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java index 6dedcf3..2bf9a96 100644 --- a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java +++ b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java @@ -49,6 +49,7 @@ public class ClientRenderer { registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer()); registerRenderer(BoundingBoxConduit.class, new ConduitRenderer()); registerRenderer(BoundingBoxSpawnableBlocks.class, new SpawnableBlocksRenderer()); + registerRenderer(BoundingBoxLine.class, new LineRenderer()); registerProvider(new SlimeChunkProvider()); registerProvider(new WorldSpawnProvider()); @@ -60,6 +61,7 @@ public class ClientRenderer { registerProvider(new MobSpawnerProvider()); registerProvider(new ConduitProvider()); registerProvider(new SpawnableBlocksProvider()); + registerProvider(new CustomLineProvider()); } public static void registerProvider(IBoundingBoxProvider provider) { diff --git a/src/main/java/com/irtimaled/bbor/client/commands/CustomCommand.java b/src/main/java/com/irtimaled/bbor/client/commands/CustomCommand.java index 184a860..2cd9af9 100644 --- a/src/main/java/com/irtimaled/bbor/client/commands/CustomCommand.java +++ b/src/main/java/com/irtimaled/bbor/client/commands/CustomCommand.java @@ -2,6 +2,7 @@ package com.irtimaled.bbor.client.commands; import com.irtimaled.bbor.client.providers.CustomBeaconProvider; import com.irtimaled.bbor.client.providers.CustomBoxProvider; +import com.irtimaled.bbor.client.providers.CustomLineProvider; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.command.Commands; @@ -11,15 +12,18 @@ public class CustomCommand { private static final String COMMAND = "bbor:custom"; private static final String BOX = "box"; private static final String BEACON = "beacon"; + private static final String LINE = "line"; public static void register(CommandDispatcher commandDispatcher) { LiteralArgumentBuilder command = Commands.literal(COMMAND) .then(BoxCommandBuilder.build(BOX)) .then(BeaconCommandBuilder.build(BEACON)) + .then(LineCommandBuilder.build(LINE)) .then(Commands.literal(ArgumentNames.CLEAR) .executes(context -> { CustomBoxProvider.clear(); CustomBeaconProvider.clear(); + CustomLineProvider.clear(); CommandHelper.feedback(context, "bbor.commands.custom.cleared.all"); return 0; diff --git a/src/main/java/com/irtimaled/bbor/client/commands/LineCommandBuilder.java b/src/main/java/com/irtimaled/bbor/client/commands/LineCommandBuilder.java new file mode 100644 index 0000000..048b2aa --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/commands/LineCommandBuilder.java @@ -0,0 +1,55 @@ +package com.irtimaled.bbor.client.commands; + +import com.irtimaled.bbor.client.providers.CustomLineProvider; +import com.irtimaled.bbor.common.models.Point; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; + +class LineCommandBuilder { + private static final String WIDTH = "width"; + + static LiteralArgumentBuilder build(String command) { + return Commands.literal(command) + .then(Commands.literal(ArgumentNames.ADD) + .then(Commands.argument(ArgumentNames.FROM, Arguments.point()) + .then(Commands.argument(ArgumentNames.TO, Arguments.point()) + .executes(LineCommandBuilder::addLine) + .then(Commands.argument(WIDTH, Arguments.doubleArg()) + .executes(LineCommandBuilder::addLine))))) + .then(Commands.literal(ArgumentNames.CLEAR) + .executes(context -> { + CustomLineProvider.clear(); + + CommandHelper.feedback(context, "bbor.commands.line.cleared.all"); + return 0; + }) + .then(Commands.argument(ArgumentNames.FROM, Arguments.coords()) + .then(Commands.argument(ArgumentNames.TO, Arguments.coords()) + .executes(context -> { + Point from = Arguments.getPoint(context, ArgumentNames.FROM).snapXZ(0.5d); + Point to = Arguments.getPoint(context, ArgumentNames.TO).snapXZ(0.5d); + boolean removed = CustomLineProvider.remove(from, to); + + String format = removed ? "bbor.commands.line.cleared" : "bbor.commands.line.notFound"; + CommandHelper.feedback(context, format, + from.getX(), from.getY(), from.getZ(), + to.getX(), to.getY(), to.getZ()); + return 0; + })))); + } + + private static int addLine(CommandContext context) throws CommandSyntaxException { + Point from = Arguments.getPoint(context, ArgumentNames.FROM).snapXZ(0.5d); + Point to = Arguments.getPoint(context, ArgumentNames.TO).snapXZ(0.5d); + Double width = Arguments.getDouble(context, WIDTH); + CustomLineProvider.add(from, to, width); + + CommandHelper.feedback(context, "bbor.commands.line.added", + from.getX(), from.getY(), from.getZ(), + to.getX(), to.getY(), to.getZ()); + return 0; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxLine.java b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxLine.java new file mode 100644 index 0000000..b8b02bd --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxLine.java @@ -0,0 +1,96 @@ +package com.irtimaled.bbor.client.models; + +import com.irtimaled.bbor.common.BoundingBoxType; +import com.irtimaled.bbor.common.TypeHelper; +import com.irtimaled.bbor.common.models.AbstractBoundingBox; +import com.irtimaled.bbor.common.models.Point; + +public class BoundingBoxLine extends AbstractBoundingBox { + private final Point minPoint; + private final Point maxPoint; + private final Double width; + private final Point[] corners; + + protected BoundingBoxLine(Point minPoint, Point maxPoint, double width, BoundingBoxType type, Point... corners) { + super(type); + this.minPoint = minPoint; + this.maxPoint = maxPoint; + this.width = width; + this.corners = corners; + } + + public static BoundingBoxLine from(Point minPoint, Point maxPoint, Double width, BoundingBoxType type) { + if (width == 0) return new BoundingBoxLine(minPoint, maxPoint, width, type); + + double halfWidth = width / 2.0d; + + double dx = maxPoint.getX() - minPoint.getX(); + double dz = maxPoint.getZ() - minPoint.getZ(); + + double dxm = dx == 0 ? 0 : dx / Math.abs(dx); + double dzm = dz == 0 ? 0 : dz / Math.abs(dz); + + double xc, zc; + if (dxm == 0 || dzm == 0) { + xc = Math.abs(dzm) * halfWidth; + zc = Math.abs(dxm) * halfWidth; + } else { + double h = Math.sqrt(dx * dx + dz * dz); + double theta = Math.acos((dz * dz + h * h - dx * dx) / (2 * dz * h)); + zc = halfWidth * Math.sin(theta); + xc = Math.sqrt(halfWidth * halfWidth - zc * zc) * dxm * dzm; + } + + return new BoundingBoxLine(minPoint, maxPoint, width, type, + new Point(minPoint.getX() + xc, minPoint.getY(), minPoint.getZ() - zc), + new Point(minPoint.getX() - xc, minPoint.getY(), minPoint.getZ() + zc), + new Point(maxPoint.getX() - xc, maxPoint.getY(), maxPoint.getZ() + zc), + new Point(maxPoint.getX() + xc, maxPoint.getY(), maxPoint.getZ() - zc)); + } + + @Override + public int hashCode() { + return TypeHelper.combineHashCodes(minPoint.hashCode(), maxPoint.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + BoundingBoxLine other = (BoundingBoxLine) obj; + return minPoint.equals(other.minPoint) && maxPoint.equals(other.maxPoint); + } + + public Point getMinPoint() { + return minPoint; + } + + public Point getMaxPoint() { + return maxPoint; + } + + public double getWidth() { + return width; + } + + public Point[] getCorners() { + return corners; + } + + @Override + public Boolean intersectsBounds(int minX, int minZ, int maxX, int maxZ) { + boolean minXWithinBounds = isBetween(minPoint.getX(), minX, maxX); + boolean maxXWithinBounds = isBetween(maxPoint.getX(), minX, maxX); + boolean minZWithinBounds = isBetween(minPoint.getZ(), minZ, maxZ); + boolean maxZWithinBounds = isBetween(maxPoint.getZ(), minZ, maxZ); + + return (minXWithinBounds && minZWithinBounds) || + (maxXWithinBounds && maxZWithinBounds) || + (minXWithinBounds && maxZWithinBounds) || + (maxXWithinBounds && minZWithinBounds); + } + + private boolean isBetween(double val, int min, int max) { + return val >= min && val <= max; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/providers/CustomLineProvider.java b/src/main/java/com/irtimaled/bbor/client/providers/CustomLineProvider.java new file mode 100644 index 0000000..6c50944 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/providers/CustomLineProvider.java @@ -0,0 +1,43 @@ +package com.irtimaled.bbor.client.providers; + +import com.irtimaled.bbor.client.Player; +import com.irtimaled.bbor.client.models.BoundingBoxLine; +import com.irtimaled.bbor.common.BoundingBoxType; +import com.irtimaled.bbor.common.models.Point; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class CustomLineProvider implements IBoundingBoxProvider { + private static final Map> dimensionCache = new HashMap<>(); + + private static int getHashKey(Point minPoint, Point maxPoint) { + return (31 + minPoint.hashCode()) * 31 + maxPoint.hashCode(); + } + + private static Map getCache(int dimensionId) { + return dimensionCache.computeIfAbsent(dimensionId, i -> new ConcurrentHashMap<>()); + } + + public static void add(Point minPoint, Point maxPoint, Double width) { + int dimensionId = Player.getDimensionId(); + int cacheKey = getHashKey(minPoint, maxPoint); + BoundingBoxLine line = BoundingBoxLine.from(minPoint, maxPoint, width, BoundingBoxType.Custom); + getCache(dimensionId).put(cacheKey, line); + } + + public static boolean remove(Point min, Point max) { + int dimensionId = Player.getDimensionId(); + int cacheKey = getHashKey(min, max); + return getCache(dimensionId).remove(cacheKey) != null; + } + + public static void clear() { + dimensionCache.values().forEach(Map::clear); + } + + public Iterable get(int dimensionId) { + return getCache(dimensionId).values(); + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/LineRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/LineRenderer.java new file mode 100644 index 0000000..148bcc4 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/renderers/LineRenderer.java @@ -0,0 +1,45 @@ +package com.irtimaled.bbor.client.renderers; + +import com.irtimaled.bbor.client.config.ConfigManager; +import com.irtimaled.bbor.client.models.BoundingBoxLine; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.Arrays; + +public class LineRenderer extends AbstractRenderer { + @Override + public void render(BoundingBoxLine boundingBox) { + Color color = boundingBox.getColor(); + + if (boundingBox.getWidth() == 0) { + OffsetPoint startPoint = new OffsetPoint(boundingBox.getMinPoint()).offset(0, 0.001f, 0); + OffsetPoint endPoint = new OffsetPoint(boundingBox.getMaxPoint()).offset(0, 0.001f, 0); + renderLine(startPoint, endPoint, color); + return; + } + + OffsetPoint[] cornerPoints = Arrays.stream(boundingBox.getCorners()). + map(point -> new OffsetPoint(point).offset(0,0.001f, 0)). + toArray(OffsetPoint[]::new); + + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); + Renderer.startQuads() + .setColor(color) + .addPoints(cornerPoints) + .render(); + + if(!ConfigManager.fill.get()) return; + + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); + GL11.glEnable(GL11.GL_BLEND); + Renderer.startQuads() + .setColor(color) + .setAlpha(30) + .addPoints(cornerPoints) + .render(); + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE); + GL11.glPolygonOffset(-1.f, -1.f); + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java index fe8564e..b6ea2c7 100644 --- a/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java +++ b/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java @@ -64,6 +64,14 @@ public class Renderer { return addPoint(point.getX(), point.getY(), point.getZ()); } + public Renderer addPoints(OffsetPoint[] points) { + Renderer renderer = this; + for (OffsetPoint point : points) { + renderer = renderer.addPoint(point); + } + return renderer; + } + Renderer addPoint(double x, double y, double z) { pos(x, y, z); color(); diff --git a/src/main/resources/assets/bbor/lang/en_us.json b/src/main/resources/assets/bbor/lang/en_us.json index 7ff6045..70930d3 100644 --- a/src/main/resources/assets/bbor/lang/en_us.json +++ b/src/main/resources/assets/bbor/lang/en_us.json @@ -77,6 +77,11 @@ "bbor.commands.box.cleared": "Box cleared with start [x=%d, y=%d, z=%d] and end [x=%d, y=%d, z=%d]", "bbor.commands.box.notFound": "No box found with start [x=%d, y=%d, z=%d] and end [x=%d, y=%d, z=%d]", + "bbor.commands.line.added": "Line added with start [x=%d, y=%d, z=%d] and end [x=%d, y=%d, z=%d]", + "bbor.commands.line.cleared": "All lines cleared", + "bbor.commands.line.cleared.all": "Line cleared with start [x=%d, y=%d, z=%d] and end [x=%d, y=%d, z=%d]", + "bbor.commands.line.notFound": "No line found with start [x=%d, y=%d, z=%d] and end [x=%d, y=%d, z=%d]", + "bbor.commands.spawningSphere.set": "Spawning sphere set", "bbor.commands.spawningSphere.notSet": "No spawning sphere set", "bbor.commands.spawningSphere.cleared": "Spawning sphere cleared",