diff --git a/src/main/java/xyz/nucleoid/spleef/Spleef.java b/src/main/java/xyz/nucleoid/spleef/Spleef.java index 7aa284d..7bfd2e3 100644 --- a/src/main/java/xyz/nucleoid/spleef/Spleef.java +++ b/src/main/java/xyz/nucleoid/spleef/Spleef.java @@ -1,10 +1,16 @@ package xyz.nucleoid.spleef; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.minecraft.command.argument.ArgumentTypes; +import net.minecraft.command.argument.serialize.ConstantArgumentSerializer; import net.minecraft.util.Identifier; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import xyz.nucleoid.plasmid.game.GameType; +import xyz.nucleoid.spleef.command.MapShapeRendererArgumentType; +import xyz.nucleoid.spleef.command.RenderShapeCommand; import xyz.nucleoid.spleef.game.SpleefConfig; import xyz.nucleoid.spleef.game.SpleefWaiting; import xyz.nucleoid.spleef.game.map.shape.renderer.*; @@ -24,5 +30,10 @@ public void onInitialize() { MapShapeRenderer.REGISTRY.register(new Identifier(Spleef.ID, "circle"), CircleShapeRenderer.CODEC); MapShapeRenderer.REGISTRY.register(new Identifier(Spleef.ID, "square"), SquareShapeRenderer.CODEC); MapShapeRenderer.REGISTRY.register(new Identifier(Spleef.ID, "pattern"), PatternShapeRenderer.CODEC); + + ArgumentTypes.register("spleef:map_shape_renderer", MapShapeRendererArgumentType.class, new ConstantArgumentSerializer(MapShapeRendererArgumentType::mapShapeRenderer)); + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { + RenderShapeCommand.register(dispatcher); + }); } } diff --git a/src/main/java/xyz/nucleoid/spleef/command/MapShapeRendererArgumentType.java b/src/main/java/xyz/nucleoid/spleef/command/MapShapeRendererArgumentType.java new file mode 100644 index 0000000..3e8bbf2 --- /dev/null +++ b/src/main/java/xyz/nucleoid/spleef/command/MapShapeRendererArgumentType.java @@ -0,0 +1,48 @@ +package xyz.nucleoid.spleef.command; + +import java.util.Arrays; +import java.util.Collection; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DataResult.PartialResult; + +import net.minecraft.command.argument.NbtTagArgumentType; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import xyz.nucleoid.spleef.game.map.shape.renderer.MapShapeRenderer; + +public class MapShapeRendererArgumentType implements ArgumentType { + private static final Collection EXAMPLES = Arrays.asList("{type='spleef:circle',radius=16}"); + + public static MapShapeRendererArgumentType mapShapeRenderer() { + return new MapShapeRendererArgumentType(); + } + + public static MapShapeRenderer getMapShapeRenderer(CommandContext context, String name) { + return context.getArgument(name, MapShapeRenderer.class); + } + + @Override + public MapShapeRenderer parse(StringReader reader) throws CommandSyntaxException { + Tag tag = NbtTagArgumentType.nbtTag().parse(reader); + + DataResult result = MapShapeRenderer.REGISTRY_CODEC.codec().parse(NbtOps.INSTANCE, tag); + if (result.error().isPresent()) { + PartialResult partial = result.error().get(); + throw new SimpleCommandExceptionType(new LiteralText(partial.message())).create(); + } + return result.result().get(); + } + + @Override + public Collection getExamples() { + return EXAMPLES; + } +} diff --git a/src/main/java/xyz/nucleoid/spleef/command/RenderShapeCommand.java b/src/main/java/xyz/nucleoid/spleef/command/RenderShapeCommand.java new file mode 100644 index 0000000..ce225e1 --- /dev/null +++ b/src/main/java/xyz/nucleoid/spleef/command/RenderShapeCommand.java @@ -0,0 +1,51 @@ +package xyz.nucleoid.spleef.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; + +import net.minecraft.block.Blocks; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.gen.stateprovider.BlockStateProvider; +import net.minecraft.world.gen.stateprovider.SimpleBlockStateProvider; +import xyz.nucleoid.spleef.game.map.shape.ShapeCanvas; +import xyz.nucleoid.spleef.game.map.shape.ShapePlacer; +import xyz.nucleoid.spleef.game.map.shape.SpleefShape; +import xyz.nucleoid.spleef.game.map.shape.WorldShapePlacer; +import xyz.nucleoid.spleef.game.map.shape.renderer.MapShapeRenderer; + +public class RenderShapeCommand { + private static final BlockStateProvider FILL_PROVIDER = new SimpleBlockStateProvider(Blocks.WHITE_CONCRETE.getDefaultState()); + private static final BlockStateProvider OUTLINE_PROVIDER = new SimpleBlockStateProvider(Blocks.BLACK_CONCRETE.getDefaultState()); + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(CommandManager + .literal("rendershape") + .then(CommandManager.argument("shape", MapShapeRendererArgumentType.mapShapeRenderer()) + .executes(RenderShapeCommand::execute))); + } + + private static int execute(CommandContext context) { + + ShapeCanvas canvas = new ShapeCanvas(); + + MapShapeRenderer renderer = MapShapeRendererArgumentType.getMapShapeRenderer(context, "shape"); + renderer.renderTo(canvas); + + SpleefShape shape = canvas.render(); + + Vec3d pos = context.getSource().getPosition(); + int x = (int) pos.getX(); + int y = (int) pos.getY() - 1; + int z = (int) pos.getZ(); + + ShapePlacer fill = new WorldShapePlacer(x, z, context.getSource().getWorld(), FILL_PROVIDER); + fill.fill(shape, y, y); + + ShapePlacer outline = new WorldShapePlacer(x, z, context.getSource().getWorld(), OUTLINE_PROVIDER); + outline.outline(shape, y, y); + + return 1; + } +} diff --git a/src/main/java/xyz/nucleoid/spleef/game/map/SpleefMapGenerator.java b/src/main/java/xyz/nucleoid/spleef/game/map/SpleefMapGenerator.java index 2d673f6..d86ee5a 100644 --- a/src/main/java/xyz/nucleoid/spleef/game/map/SpleefMapGenerator.java +++ b/src/main/java/xyz/nucleoid/spleef/game/map/SpleefMapGenerator.java @@ -3,6 +3,7 @@ import net.minecraft.util.math.BlockPos; import xyz.nucleoid.plasmid.map.template.MapTemplate; import xyz.nucleoid.spleef.game.map.shape.SpleefShape; +import xyz.nucleoid.spleef.game.map.shape.MapShapePlacer; import xyz.nucleoid.spleef.game.map.shape.ShapeCanvas; import xyz.nucleoid.spleef.game.map.shape.ShapePlacer; @@ -36,10 +37,10 @@ public SpleefMap build() { private void buildFromShape(MapTemplate template, SpleefMap map, SpleefShape shape) { Random random = new Random(); - ShapePlacer floor = new ShapePlacer(template, this.config.floorProvider, random); - ShapePlacer walls = new ShapePlacer(template, this.config.wallProvider, random); - ShapePlacer lava = new ShapePlacer(template, this.config.lavaProvider, random); - ShapePlacer ceiling = new ShapePlacer(template, this.config.ceilingProvider, random); + MapShapePlacer floor = new MapShapePlacer(template, this.config.floorProvider, random); + ShapePlacer walls = new MapShapePlacer(template, this.config.wallProvider, random); + ShapePlacer lava = new MapShapePlacer(template, this.config.lavaProvider, random); + ShapePlacer ceiling = new MapShapePlacer(template, this.config.ceilingProvider, random); // base walls.fill(shape, 0, 0); diff --git a/src/main/java/xyz/nucleoid/spleef/game/map/shape/CustomOffsetShapePlacer.java b/src/main/java/xyz/nucleoid/spleef/game/map/shape/CustomOffsetShapePlacer.java new file mode 100644 index 0000000..6a995ba --- /dev/null +++ b/src/main/java/xyz/nucleoid/spleef/game/map/shape/CustomOffsetShapePlacer.java @@ -0,0 +1,27 @@ +package xyz.nucleoid.spleef.game.map.shape; + +import java.util.Random; + +import net.minecraft.world.gen.stateprovider.BlockStateProvider; + +public abstract class CustomOffsetShapePlacer extends ShapePlacer { + private final int offsetX; + private final int offsetZ; + + public CustomOffsetShapePlacer(int offsetX, int offsetZ, BlockStateProvider provider, Random random) { + super(provider, random); + + this.offsetX = offsetX; + this.offsetZ = offsetZ; + } + + @Override + public int getOffsetX() { + return this.offsetX; + } + + @Override + public int getOffsetZ() { + return this.offsetZ; + } +} diff --git a/src/main/java/xyz/nucleoid/spleef/game/map/shape/MapShapePlacer.java b/src/main/java/xyz/nucleoid/spleef/game/map/shape/MapShapePlacer.java new file mode 100644 index 0000000..f49a53a --- /dev/null +++ b/src/main/java/xyz/nucleoid/spleef/game/map/shape/MapShapePlacer.java @@ -0,0 +1,32 @@ +package xyz.nucleoid.spleef.game.map.shape; + +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.stateprovider.BlockStateProvider; +import xyz.nucleoid.plasmid.map.template.MapTemplate; + +import java.util.Random; +import java.util.Set; + +public final class MapShapePlacer extends ShapePlacer { + private final MapTemplate template; + private final Set usedStates = new ReferenceOpenHashSet<>(); + + public MapShapePlacer(MapTemplate template, BlockStateProvider provider, Random random) { + super(provider, random); + this.template = template; + } + + @Override + public void set(BlockPos pos) { + BlockState state = this.provider.getBlockState(this.random, pos); + this.usedStates.add(state); + + this.template.setBlockState(pos, state); + } + + public Set getUsedStates() { + return this.usedStates; + } +} diff --git a/src/main/java/xyz/nucleoid/spleef/game/map/shape/ShapePlacer.java b/src/main/java/xyz/nucleoid/spleef/game/map/shape/ShapePlacer.java index b245a6d..4ecc26f 100644 --- a/src/main/java/xyz/nucleoid/spleef/game/map/shape/ShapePlacer.java +++ b/src/main/java/xyz/nucleoid/spleef/game/map/shape/ShapePlacer.java @@ -1,25 +1,17 @@ package xyz.nucleoid.spleef.game.map.shape; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.stateprovider.BlockStateProvider; -import xyz.nucleoid.plasmid.map.template.MapTemplate; import java.util.Random; -import java.util.Set; -public final class ShapePlacer { - private final MapTemplate template; - private final BlockStateProvider provider; - private final Random random; - - private final Set usedStates = new ReferenceOpenHashSet<>(); +public abstract class ShapePlacer { + protected final BlockStateProvider provider; + protected final Random random; private final BlockPos.Mutable mutablePos = new BlockPos.Mutable(); - public ShapePlacer(MapTemplate template, BlockStateProvider provider, Random random) { - this.template = template; + public ShapePlacer(BlockStateProvider provider, Random random) { this.provider = provider; this.random = random; } @@ -33,21 +25,20 @@ public void outline(SpleefShape shape, int minY, int maxY) { } private void setStack(int minY, int maxY, int x, int z) { - this.mutablePos.set(x, 0, z); + this.mutablePos.set(x + this.getOffsetX(), 0, z + this.getOffsetZ()); for (int y = minY; y <= maxY; y++) { this.mutablePos.setY(y); this.set(this.mutablePos); } } - - private void set(BlockPos pos) { - BlockState state = this.provider.getBlockState(this.random, pos); - this.usedStates.add(state); - - this.template.setBlockState(pos, state); + + public int getOffsetX() { + return 0; } - public Set getUsedStates() { - return this.usedStates; + public int getOffsetZ() { + return 0; } + + public abstract void set(BlockPos pos); } diff --git a/src/main/java/xyz/nucleoid/spleef/game/map/shape/WorldShapePlacer.java b/src/main/java/xyz/nucleoid/spleef/game/map/shape/WorldShapePlacer.java new file mode 100644 index 0000000..e6caa9d --- /dev/null +++ b/src/main/java/xyz/nucleoid/spleef/game/map/shape/WorldShapePlacer.java @@ -0,0 +1,21 @@ +package xyz.nucleoid.spleef.game.map.shape; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.stateprovider.BlockStateProvider; + +public final class WorldShapePlacer extends CustomOffsetShapePlacer { + private final World world; + + public WorldShapePlacer(int offsetX, int offsetZ, World world, BlockStateProvider provider) { + super(offsetX, offsetZ, provider, world.getRandom()); + this.world = world; + } + + @Override + public void set(BlockPos pos) { + BlockState state = this.provider.getBlockState(this.random, pos); + this.world.setBlockState(pos, state); + } +}