Refactored /place
-Command
This commit is contained in:
parent
0485f040b9
commit
28af68b906
8 changed files with 505 additions and 211 deletions
|
@ -16,6 +16,7 @@ import org.betterx.bclib.api.v3.tag.BCLBlockTags;
|
|||
import org.betterx.bclib.blocks.signs.BaseHangingSignBlock;
|
||||
import org.betterx.bclib.blocks.signs.BaseSignBlock;
|
||||
import org.betterx.bclib.commands.CommandRegistry;
|
||||
import org.betterx.bclib.commands.arguments.BCLibArguments;
|
||||
import org.betterx.bclib.complexmaterials.BCLWoodTypeWrapper;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.config.PathConfig;
|
||||
|
@ -67,6 +68,7 @@ public class BCLib implements ModInitializer {
|
|||
@Override
|
||||
public void onInitialize() {
|
||||
WorldsTogether.onInitialize();
|
||||
BCLibArguments.register();
|
||||
PresetsRegistry.register();
|
||||
LevelGenEvents.register();
|
||||
BlockPredicates.ensureStaticInitialization();
|
||||
|
|
|
@ -41,7 +41,7 @@ public class CommandRegistry {
|
|||
LiteralArgumentBuilder<CommandSourceStack> bnContext = Commands.literal("bclib")
|
||||
.requires(source -> source.hasPermission(Commands.LEVEL_OWNERS));
|
||||
|
||||
bnContext = Place.register(bnContext, commandBuildContext);
|
||||
bnContext = PlaceCommand.register(bnContext, commandBuildContext);
|
||||
bnContext = PrintInfo.register(bnContext);
|
||||
bnContext = DumpDatapack.register(bnContext);
|
||||
|
||||
|
|
|
@ -2,20 +2,25 @@ package org.betterx.bclib.commands;
|
|||
|
||||
import de.ambertation.wunderlib.math.Float3;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructureNBT;
|
||||
import org.betterx.bclib.commands.arguments.Float3ArgumentType;
|
||||
import org.betterx.bclib.commands.arguments.PlacementDirections;
|
||||
import org.betterx.bclib.commands.arguments.TemplatePlacementArgument;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
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 com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.ResourceLocationArgument;
|
||||
import net.minecraft.commands.arguments.blocks.BlockInput;
|
||||
import net.minecraft.commands.arguments.blocks.BlockStateArgument;
|
||||
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
|
||||
import net.minecraft.commands.arguments.coordinates.Coordinates;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
|
@ -33,230 +38,145 @@ import net.minecraft.world.level.block.state.properties.AttachFace;
|
|||
import net.minecraft.world.level.block.state.properties.StructureMode;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class PlaceNBT {
|
||||
protected <T extends ArgumentBuilder<CommandSourceStack, T>> T execute(
|
||||
T builder,
|
||||
BlockPos searchDir, boolean border, boolean commandBlock
|
||||
) {
|
||||
return builder.executes(commandContext -> placeNBT(
|
||||
commandContext.getSource(),
|
||||
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
||||
StringArgumentType.getString(commandContext, "path"),
|
||||
searchDir, border ? BlockStateArgument.getBlock(commandContext, "block") : null, commandBlock
|
||||
));
|
||||
}
|
||||
class PlaceCommandBuilder {
|
||||
public static final String PATH = "path";
|
||||
public static final String NBT = "nbt";
|
||||
public static final String EMPTY = "empty";
|
||||
public static final String PLACEMENT = "placement";
|
||||
public static final String POS = "pos";
|
||||
public static final String SPAN = "span";
|
||||
public static final String BORDER = "border";
|
||||
|
||||
protected <T extends ArgumentBuilder<CommandSourceStack, T>> T buildPosArgument(
|
||||
CommandBuildContext commandBuildContext,
|
||||
T builder,
|
||||
BlockPos searchDir
|
||||
public void register(
|
||||
CommandBuildContext ctx,
|
||||
LiteralArgumentBuilder<CommandSourceStack> command
|
||||
) {
|
||||
final var posBuilder = Commands.argument(
|
||||
"pos",
|
||||
final Supplier<RequiredArgumentBuilder<CommandSourceStack, ResourceLocation>> path = () -> Commands.argument(
|
||||
PATH,
|
||||
ResourceLocationArgument.id()
|
||||
);
|
||||
final Supplier<RequiredArgumentBuilder<CommandSourceStack, PlacementDirections>> placement = () -> Commands.argument(
|
||||
PLACEMENT,
|
||||
TemplatePlacementArgument.templatePlacement()
|
||||
);
|
||||
final Supplier<RequiredArgumentBuilder<CommandSourceStack, Coordinates>> pos = () -> Commands.argument(
|
||||
POS,
|
||||
BlockPosArgument.blockPos()
|
||||
);
|
||||
|
||||
final var posOnly = addPosOnly(searchDir, posBuilder);
|
||||
final var all = addPosWithAttributes(commandBuildContext, searchDir, posBuilder);
|
||||
|
||||
return builder.then(posOnly).then(all);
|
||||
}
|
||||
|
||||
protected <P extends ArgumentBuilder<CommandSourceStack, P>> P addPosWithAttributes(
|
||||
CommandBuildContext commandBuildContext,
|
||||
BlockPos searchDir,
|
||||
P posBuilder
|
||||
) {
|
||||
return posBuilder
|
||||
.then(execute(Commands.literal("structureblock"), searchDir, false, true))
|
||||
.then(Commands.literal("border")
|
||||
.then(execute(
|
||||
Commands.argument("block", BlockStateArgument.block(commandBuildContext)),
|
||||
searchDir,
|
||||
true,
|
||||
false
|
||||
).then(execute(Commands.literal("structureblock"), searchDir, true, true))
|
||||
final var nbtTree = Commands.literal(NBT).then(
|
||||
path.get().then(
|
||||
placement.get().then(
|
||||
addOptionalsAndExecute(
|
||||
ctx,
|
||||
pos.get(),
|
||||
PlaceCommandBuilder::placeNBT
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected <P extends ArgumentBuilder<CommandSourceStack, P>> P addPosOnly(
|
||||
BlockPos searchDir,
|
||||
P posBuilder
|
||||
) {
|
||||
return execute(posBuilder, searchDir, false, false);
|
||||
}
|
||||
|
||||
public void register(
|
||||
CommandBuildContext commandBuildContext,
|
||||
Map<String, Float3> directions,
|
||||
LiteralArgumentBuilder<CommandSourceStack> command
|
||||
) {
|
||||
|
||||
final LiteralArgumentBuilder<CommandSourceStack> nbtBuilder = Commands
|
||||
.literal("nbt")
|
||||
.then(Commands
|
||||
.argument("path", StringArgumentType.string())
|
||||
.then(buildPosArgument(commandBuildContext, Commands.literal("at"), null))
|
||||
.then(buildFindCommand(commandBuildContext, directions))
|
||||
final var emptyTree = Commands.literal(EMPTY).then(
|
||||
path.get().then(
|
||||
placement.get().then(
|
||||
pos.get().then(
|
||||
addOptionalsAndExecute(
|
||||
ctx,
|
||||
Commands.argument(SPAN, Float3ArgumentType.int3(0, 64)),
|
||||
PlaceCommandBuilder::placeEmpty
|
||||
)
|
||||
// .then(Commands.literal("test")
|
||||
// .then(Commands.argument("block", BlockStateArgument.block(commandBuildContext))
|
||||
// .executes(commandContext -> placeNBT(
|
||||
// commandContext.getSource(),
|
||||
// new BlockPos(100, 10, 0),
|
||||
// "betternether:altar_01",
|
||||
// Float3.NORTH.toBlockPos(),
|
||||
// BlockStateArgument.getBlock(commandContext, "block"),
|
||||
// true
|
||||
// )))
|
||||
// )
|
||||
;
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
command.then(nbtBuilder);
|
||||
command
|
||||
.then(nbtTree)
|
||||
.then(emptyTree);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected LiteralArgumentBuilder<CommandSourceStack> buildFindCommand(
|
||||
private <T> RequiredArgumentBuilder<CommandSourceStack, T> addOptionalsAndExecute(
|
||||
CommandBuildContext commandBuildContext,
|
||||
Map<String, Float3> directions
|
||||
RequiredArgumentBuilder<CommandSourceStack, T> root,
|
||||
Executor runner
|
||||
) {
|
||||
final LiteralArgumentBuilder<CommandSourceStack> executeFindFree = Commands.literal("find");
|
||||
for (var dir : directions.entrySet()) {
|
||||
executeFindFree.then(buildPosArgument(
|
||||
commandBuildContext,
|
||||
Commands.literal(dir.getKey()),
|
||||
dir.getValue().toBlockPos()
|
||||
));
|
||||
}
|
||||
return executeFindFree;
|
||||
final Supplier<LiteralArgumentBuilder<CommandSourceStack>> addControllers = () -> Commands.literal("controller");
|
||||
final Supplier<RequiredArgumentBuilder<CommandSourceStack, BlockInput>> addBorder = () -> Commands.argument(
|
||||
BORDER,
|
||||
BlockStateArgument.block(commandBuildContext)
|
||||
);
|
||||
|
||||
return root
|
||||
.executes(c -> runner.exec(c, false, false))
|
||||
.then(addBorder.get()
|
||||
.executes(c -> runner.exec(c, true, false))
|
||||
.then(addControllers.get()
|
||||
.executes(c -> runner.exec(c, true, true)))
|
||||
)
|
||||
.then(addControllers.get().executes(c -> runner.exec(c, false, true)));
|
||||
}
|
||||
|
||||
static int placeNBT(
|
||||
CommandSourceStack stack,
|
||||
BlockPos pos,
|
||||
String location,
|
||||
BlockPos searchDir,
|
||||
BlockInput blockInput,
|
||||
boolean structureBlock
|
||||
) {
|
||||
StructureNBT structureNBT = StructureNBT.create(new ResourceLocation(location));
|
||||
return Place.placeBlocks(
|
||||
stack,
|
||||
pos,
|
||||
searchDir,
|
||||
interface Executor {
|
||||
int exec(
|
||||
CommandContext<CommandSourceStack> ctx,
|
||||
boolean border,
|
||||
boolean controlBlocks
|
||||
) throws CommandSyntaxException;
|
||||
}
|
||||
|
||||
protected static int placeNBT(
|
||||
CommandContext<CommandSourceStack> ctx,
|
||||
boolean border,
|
||||
boolean controlBlocks
|
||||
) throws CommandSyntaxException {
|
||||
final ResourceLocation id = ResourceLocationArgument.getId(ctx, PATH);
|
||||
final PlacementDirections searchDir = TemplatePlacementArgument.getPlacement(ctx, PLACEMENT);
|
||||
final BlockInput blockInput = border ? BlockStateArgument.getBlock(ctx, BORDER) : null;
|
||||
final StructureNBT structureNBT = StructureNBT.create(id);
|
||||
|
||||
return PlaceCommand.placeBlocks(
|
||||
ctx.getSource(),
|
||||
BlockPosArgument.getLoadedBlockPos(ctx, POS),
|
||||
searchDir.getOffset(),
|
||||
blockInput,
|
||||
structureBlock,
|
||||
controlBlocks,
|
||||
structureNBT.location,
|
||||
(p) -> structureNBT.getBoundingBox(p, Rotation.NONE, Mirror.NONE),
|
||||
(level, p) -> structureNBT.generateAt(level, p, Rotation.NONE, Mirror.NONE)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PlaceEmpty extends PlaceNBT {
|
||||
@Override
|
||||
protected <T extends ArgumentBuilder<CommandSourceStack, T>> T execute(
|
||||
T builder,
|
||||
BlockPos searchDir, boolean border, boolean commandBlock
|
||||
) {
|
||||
return builder.executes(commandContext -> placeEmpty(
|
||||
commandContext.getSource(),
|
||||
BlockPosArgument.getLoadedBlockPos(commandContext, "pos"),
|
||||
new BlockPos(
|
||||
IntegerArgumentType.getInteger(commandContext, "spanX"),
|
||||
IntegerArgumentType.getInteger(commandContext, "spanY"),
|
||||
IntegerArgumentType.getInteger(commandContext, "spanZ")
|
||||
),
|
||||
StringArgumentType.getString(commandContext, "path"),
|
||||
searchDir, border ? BlockStateArgument.getBlock(commandContext, "block") : null, commandBlock
|
||||
));
|
||||
}
|
||||
protected static int placeEmpty(
|
||||
CommandContext<CommandSourceStack> ctx,
|
||||
boolean border,
|
||||
boolean controlBlocks
|
||||
) throws CommandSyntaxException {
|
||||
final ResourceLocation id = ResourceLocationArgument.getId(ctx, PATH);
|
||||
final PlacementDirections searchDir = TemplatePlacementArgument.getPlacement(ctx, PLACEMENT);
|
||||
final BlockInput blockInput = border ? BlockStateArgument.getBlock(ctx, BORDER) : null;
|
||||
final BlockPos span = Float3ArgumentType.getFloat3(ctx, SPAN).toBlockPos();
|
||||
|
||||
@Override
|
||||
protected <T extends ArgumentBuilder<CommandSourceStack, T>> T buildPosArgument(
|
||||
CommandBuildContext commandBuildContext,
|
||||
T builder,
|
||||
BlockPos searchDir
|
||||
) {
|
||||
final var spanX = Commands.argument(
|
||||
"spanX",
|
||||
IntegerArgumentType.integer(0, 64)
|
||||
);
|
||||
final var spanY = Commands.argument(
|
||||
"spanY",
|
||||
IntegerArgumentType.integer(0, 64)
|
||||
);
|
||||
final var spanZ = Commands.argument(
|
||||
"spanZ",
|
||||
IntegerArgumentType.integer(0, 64)
|
||||
);
|
||||
final var posBuilder = Commands.argument(
|
||||
"pos",
|
||||
BlockPosArgument.blockPos()
|
||||
);
|
||||
|
||||
final var posOnly = addPosOnly(searchDir, spanZ);
|
||||
final var all = addPosWithAttributes(commandBuildContext, searchDir, spanZ);
|
||||
|
||||
return builder.then(posBuilder.then(spanX.then(spanY.then(posOnly).then(all))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(
|
||||
CommandBuildContext commandBuildContext,
|
||||
Map<String, Float3> directions,
|
||||
LiteralArgumentBuilder<CommandSourceStack> command
|
||||
) {
|
||||
|
||||
final LiteralArgumentBuilder<CommandSourceStack> nbtBuilder = Commands
|
||||
.literal("empty")
|
||||
.then(Commands
|
||||
.argument("path", StringArgumentType.string())
|
||||
.then(buildPosArgument(commandBuildContext, Commands.literal("at"), null))
|
||||
.then(buildFindCommand(commandBuildContext, directions))
|
||||
);
|
||||
|
||||
|
||||
command.then(nbtBuilder);
|
||||
}
|
||||
|
||||
private static int placeEmpty(
|
||||
CommandSourceStack stack,
|
||||
BlockPos start,
|
||||
BlockPos span,
|
||||
String location,
|
||||
BlockPos searchDir,
|
||||
BlockInput blockInput,
|
||||
boolean structureBlock
|
||||
) {
|
||||
return Place.placeBlocks(
|
||||
stack,
|
||||
start,
|
||||
searchDir,
|
||||
return PlaceCommand.placeBlocks(
|
||||
ctx.getSource(),
|
||||
BlockPosArgument.getLoadedBlockPos(ctx, POS),
|
||||
searchDir == null || searchDir.dir == Float3.ZERO ? null : searchDir.dir.toBlockPos(),
|
||||
blockInput,
|
||||
structureBlock,
|
||||
new ResourceLocation(location),
|
||||
controlBlocks,
|
||||
id,
|
||||
(p) -> BoundingBox.fromCorners(p, p.offset(span)),
|
||||
(level, p) -> {
|
||||
var box = BoundingBox.fromCorners(p, p.offset(span));
|
||||
Place.fillStructureVoid(level, box);
|
||||
PlaceCommand.fillStructureVoid(level, box);
|
||||
if (blockInput != null) {
|
||||
Place.fill(
|
||||
PlaceCommand.fill(
|
||||
level,
|
||||
new BoundingBox(
|
||||
box.minX(),
|
||||
box.minY() - 1,
|
||||
box.minZ(),
|
||||
box.maxX(),
|
||||
box.minY() - 1,
|
||||
box.maxZ()
|
||||
box.minX(), box.minY() - 1, box.minZ(),
|
||||
box.maxX(), box.minY() - 1, box.maxZ()
|
||||
),
|
||||
blockInput.getState()
|
||||
);
|
||||
|
@ -266,29 +186,19 @@ class PlaceEmpty extends PlaceNBT {
|
|||
}
|
||||
}
|
||||
|
||||
public class Place {
|
||||
public Place() {
|
||||
public class PlaceCommand {
|
||||
public PlaceCommand() {
|
||||
}
|
||||
|
||||
public static LiteralArgumentBuilder<CommandSourceStack> register(
|
||||
LiteralArgumentBuilder<CommandSourceStack> bnContext,
|
||||
CommandBuildContext commandBuildContext
|
||||
) {
|
||||
final Map<String, Float3> directions = Map.of(
|
||||
"northOf", Float3.NORTH,
|
||||
"southOf", Float3.SOUTH,
|
||||
"eastOf", Float3.EAST,
|
||||
"westOf", Float3.WEST,
|
||||
"above", Float3.UP,
|
||||
"below", Float3.DOWN
|
||||
);
|
||||
|
||||
final var command = Commands
|
||||
.literal("place")
|
||||
.requires(commandSourceStack -> commandSourceStack.hasPermission(2));
|
||||
|
||||
new PlaceNBT().register(commandBuildContext, directions, command);
|
||||
new PlaceEmpty().register(commandBuildContext, directions, command);
|
||||
new PlaceCommandBuilder().register(commandBuildContext, command);
|
||||
|
||||
return bnContext.then(command);
|
||||
}
|
||||
|
@ -378,7 +288,7 @@ public class Place {
|
|||
stack.getLevel().setBlock(structureBlockPos, state, BlocksHelper.SET_OBSERV);
|
||||
if (stack.getLevel().getBlockEntity(structureBlockPos) instanceof StructureBlockEntity entity) {
|
||||
entity.setIgnoreEntities(false);
|
||||
entity.setShowAir(true);
|
||||
entity.setShowAir(false);
|
||||
entity.setMirror(Mirror.NONE);
|
||||
entity.setRotation(Rotation.NONE);
|
||||
entity.setShowBoundingBox(true);
|
||||
|
@ -462,5 +372,15 @@ public class Place {
|
|||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/bclib place nbt "betternether:city/city_building_01" find northOf 0 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/city_center_04" find northOf 32 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/city_enchanter_02" find northOf 32 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/city_library_03" find northOf 64 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/city_park_02" find northOf 64 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/city_tower_04" find northOf 96 -59 0 border glass structureblock
|
||||
/bclib place nbt "betternether:city/road_end_02" find northOf 96 -59 0 border glass structureblock
|
||||
*/
|
|
@ -0,0 +1,23 @@
|
|||
package org.betterx.bclib.commands.arguments;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
|
||||
|
||||
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
|
||||
|
||||
public class BCLibArguments {
|
||||
public static void register() {
|
||||
ArgumentTypeRegistry.registerArgumentType(
|
||||
BCLib.makeID("template_placement"),
|
||||
TemplatePlacementArgument.class,
|
||||
SingletonArgumentInfo.contextFree(TemplatePlacementArgument::templatePlacement)
|
||||
);
|
||||
|
||||
ArgumentTypeRegistry.registerArgumentType(
|
||||
BCLib.makeID("float3"),
|
||||
Float3ArgumentType.class,
|
||||
new Float3ArgumentInfo()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package org.betterx.bclib.commands.arguments;
|
||||
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class Float3ArgumentInfo implements ArgumentTypeInfo<Float3ArgumentType, Float3ArgumentInfo.Template> {
|
||||
private static byte MIN_FLAG = 1 << 1;
|
||||
private static byte MAX_FLAG = 1 << 2;
|
||||
private static byte IS_INT_FLAG = 1 << 0;
|
||||
|
||||
private static byte createNumberFlags(boolean isInt, boolean hasMin, boolean hasMax) {
|
||||
byte flagByte = 0;
|
||||
if (isInt) flagByte |= IS_INT_FLAG;
|
||||
if (hasMin) flagByte |= MIN_FLAG;
|
||||
if (hasMax) flagByte |= MAX_FLAG;
|
||||
|
||||
return flagByte;
|
||||
}
|
||||
|
||||
private static boolean numberHasMin(byte flag) {
|
||||
return (flag & MIN_FLAG) != 0;
|
||||
}
|
||||
|
||||
private static boolean numberHasMax(byte flag) {
|
||||
return (flag & MAX_FLAG) != 0;
|
||||
}
|
||||
|
||||
private static boolean numberIsInt(byte flag) {
|
||||
return (flag & IS_INT_FLAG) != 0;
|
||||
}
|
||||
|
||||
public void serializeToNetwork(
|
||||
Float3ArgumentInfo.Template template,
|
||||
FriendlyByteBuf friendlyByteBuf
|
||||
) {
|
||||
final boolean hasMin = template.min != -Double.MAX_VALUE;
|
||||
final boolean hasMax = template.max != Double.MAX_VALUE;
|
||||
friendlyByteBuf.writeByte(createNumberFlags(template.asInt, hasMin, hasMax));
|
||||
if (hasMin) friendlyByteBuf.writeDouble(template.min);
|
||||
if (hasMax) friendlyByteBuf.writeDouble(template.max);
|
||||
}
|
||||
|
||||
public Float3ArgumentInfo.Template deserializeFromNetwork(
|
||||
FriendlyByteBuf friendlyByteBuf
|
||||
) {
|
||||
byte flag = friendlyByteBuf.readByte();
|
||||
boolean asInt = numberIsInt(flag);
|
||||
double min = numberHasMin(flag) ? friendlyByteBuf.readDouble() : -Double.MAX_VALUE;
|
||||
double max = numberHasMax(flag) ? friendlyByteBuf.readDouble() : Double.MAX_VALUE;
|
||||
return new Float3ArgumentInfo.Template(asInt, min, max);
|
||||
}
|
||||
|
||||
public void serializeToJson(Float3ArgumentInfo.Template template, JsonObject jsonObject) {
|
||||
if (!template.asInt) {
|
||||
jsonObject.addProperty("asInt", template.asInt);
|
||||
}
|
||||
if (template.min != -Double.MAX_VALUE) {
|
||||
jsonObject.addProperty("min", template.min);
|
||||
}
|
||||
if (template.max != Double.MAX_VALUE) {
|
||||
jsonObject.addProperty("max", template.max);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Float3ArgumentInfo.Template unpack(Float3ArgumentType type) {
|
||||
return new Float3ArgumentInfo.Template(type.isInt(), type.getMinimum(), type.getMaximum());
|
||||
}
|
||||
|
||||
public final class Template implements ArgumentTypeInfo.Template<Float3ArgumentType> {
|
||||
final double min;
|
||||
final double max;
|
||||
final boolean asInt;
|
||||
|
||||
Template(boolean asInt, double min, double max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.asInt = asInt;
|
||||
|
||||
}
|
||||
|
||||
public Float3ArgumentType instantiate(CommandBuildContext commandBuildContext) {
|
||||
return this.asInt
|
||||
? Float3ArgumentType.int3((int) this.min, (int) this.max)
|
||||
: Float3ArgumentType.float3(this.min, this.max);
|
||||
}
|
||||
|
||||
public ArgumentTypeInfo<Float3ArgumentType, ?> type() {
|
||||
return Float3ArgumentInfo.this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
package org.betterx.bclib.commands.arguments;
|
||||
|
||||
import de.ambertation.wunderlib.math.Float3;
|
||||
|
||||
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.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
|
||||
import net.minecraft.commands.arguments.coordinates.WorldCoordinate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class Float3ArgumentType implements ArgumentType<Float3> {
|
||||
private static final Collection<String> EXAMPLES = List.of("0 0 0");
|
||||
|
||||
private final double minimum;
|
||||
private final double maximum;
|
||||
private final boolean asInt;
|
||||
|
||||
Float3ArgumentType(int minimum, int maximum) {
|
||||
this(true, minimum, maximum);
|
||||
}
|
||||
|
||||
Float3ArgumentType(double minimum, double maximum) {
|
||||
this(false, minimum, maximum);
|
||||
}
|
||||
|
||||
Float3ArgumentType(boolean asInt, double minimum, double maximum) {
|
||||
this.asInt = asInt;
|
||||
this.minimum = minimum;
|
||||
this.maximum = maximum;
|
||||
}
|
||||
|
||||
public double getMinimum() {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
public double getMaximum() {
|
||||
return maximum;
|
||||
}
|
||||
|
||||
public boolean isInt() {
|
||||
return asInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float3 parse(StringReader reader) throws CommandSyntaxException {
|
||||
int i = reader.getCursor();
|
||||
double x = asInt ? parseInt(reader) : parseDouble(reader);
|
||||
if (!reader.canRead() || reader.peek() != ' ') {
|
||||
reader.setCursor(i);
|
||||
throw Vec3Argument.ERROR_NOT_COMPLETE.createWithContext(reader);
|
||||
}
|
||||
reader.skip();
|
||||
double y = asInt ? parseInt(reader) : parseDouble(reader);
|
||||
if (!reader.canRead() || reader.peek() != ' ') {
|
||||
reader.setCursor(i);
|
||||
throw Vec3Argument.ERROR_NOT_COMPLETE.createWithContext(reader);
|
||||
}
|
||||
reader.skip();
|
||||
double z = asInt ? parseInt(reader) : parseDouble(reader);
|
||||
return Float3.of(x, y, z);
|
||||
}
|
||||
|
||||
private double parseDouble(StringReader reader) throws CommandSyntaxException {
|
||||
if (!reader.canRead()) {
|
||||
throw WorldCoordinate.ERROR_EXPECTED_DOUBLE.createWithContext(reader);
|
||||
} else {
|
||||
final int start = reader.getCursor();
|
||||
double result = reader.canRead() && reader.peek() != ' ' ? reader.readDouble() : 0.0;
|
||||
|
||||
if (result < minimum) {
|
||||
reader.setCursor(start);
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.doubleTooLow()
|
||||
.createWithContext(reader, result, minimum);
|
||||
}
|
||||
if (result > maximum) {
|
||||
reader.setCursor(start);
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.doubleTooHigh()
|
||||
.createWithContext(reader, result, maximum);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private double parseInt(StringReader reader) throws CommandSyntaxException {
|
||||
if (!reader.canRead()) {
|
||||
throw WorldCoordinate.ERROR_EXPECTED_DOUBLE.createWithContext(reader);
|
||||
} else {
|
||||
final int start = reader.getCursor();
|
||||
int result = reader.canRead() && reader.peek() != ' ' ? reader.readInt() : 0;
|
||||
|
||||
if (result < minimum) {
|
||||
reader.setCursor(start);
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooLow()
|
||||
.createWithContext(reader, result, minimum);
|
||||
}
|
||||
if (result > maximum) {
|
||||
reader.setCursor(start);
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooHigh()
|
||||
.createWithContext(reader, result, maximum);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Float3ArgumentType int3() {
|
||||
return new Float3ArgumentType(-Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Float3ArgumentType int3(int min) {
|
||||
return new Float3ArgumentType(min, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Float3ArgumentType int3(int min, int max) {
|
||||
return new Float3ArgumentType(min, max);
|
||||
}
|
||||
|
||||
public static Float3ArgumentType float3() {
|
||||
return new Float3ArgumentType(-Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Float3ArgumentType float3(double min) {
|
||||
return new Float3ArgumentType(min, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Float3ArgumentType float3(double min, double max) {
|
||||
return new Float3ArgumentType(min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||
final String remaining = builder.getRemaining();
|
||||
return SharedSuggestionProvider.suggestCoordinates(
|
||||
remaining,
|
||||
List.of(new SharedSuggestionProvider.TextCoordinates("8", "8", "8")),
|
||||
builder,
|
||||
Commands.createValidator(this::parse)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getExamples() {
|
||||
return EXAMPLES;
|
||||
}
|
||||
|
||||
public static Float3 getFloat3(CommandContext<CommandSourceStack> commandContext, String string) {
|
||||
return commandContext.getArgument(string, Float3.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Float3ArgumentType)) return false;
|
||||
Float3ArgumentType that = (Float3ArgumentType) o;
|
||||
return Double.compare(that.minimum, minimum) == 0 && Double.compare(
|
||||
that.maximum,
|
||||
maximum
|
||||
) == 0 && asInt == that.asInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(minimum, maximum, asInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (asInt) {
|
||||
if (minimum == -Double.MAX_VALUE && maximum == Double.MAX_VALUE) {
|
||||
return "int3()";
|
||||
} else if (maximum == Double.MAX_VALUE) {
|
||||
return "int3(" + (int) minimum + ")";
|
||||
} else {
|
||||
return "int3(" + (int) minimum + ", " + (int) maximum + ")";
|
||||
}
|
||||
} else {
|
||||
if (minimum == -Double.MAX_VALUE && maximum == Double.MAX_VALUE) {
|
||||
return "float3()";
|
||||
} else if (maximum == Double.MAX_VALUE) {
|
||||
return "float3(" + (int) minimum + ")";
|
||||
} else {
|
||||
return "float3(" + (int) minimum + ", " + (int) maximum + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.betterx.bclib.commands.arguments;
|
||||
|
||||
import de.ambertation.wunderlib.math.Float3;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
|
||||
public enum PlacementDirections implements StringRepresentable {
|
||||
NORTH_OF("northOf", Float3.NORTH),
|
||||
EAST_OF("eastOf", Float3.EAST),
|
||||
SOUTH_OF("southOf", Float3.SOUTH),
|
||||
WEST_OF("westOf", Float3.WEST),
|
||||
ABOVE("above", Float3.UP),
|
||||
BELOW("below", Float3.DOWN),
|
||||
AT("at", null);
|
||||
|
||||
public static final Codec<PlacementDirections> CODEC = StringRepresentable.fromEnum(PlacementDirections::values);
|
||||
|
||||
private final String name;
|
||||
public final Float3 dir;
|
||||
|
||||
PlacementDirections(String name, Float3 dir) {
|
||||
this.name = name;
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
public BlockPos getOffset() {
|
||||
return dir == null || dir == Float3.ZERO ? null : dir.toBlockPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.betterx.bclib.commands.arguments;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.StringRepresentableArgument;
|
||||
|
||||
public class TemplatePlacementArgument
|
||||
extends StringRepresentableArgument<PlacementDirections> {
|
||||
private TemplatePlacementArgument() {
|
||||
super(PlacementDirections.CODEC, PlacementDirections::values);
|
||||
}
|
||||
|
||||
public static TemplatePlacementArgument templatePlacement() {
|
||||
return new TemplatePlacementArgument();
|
||||
}
|
||||
|
||||
public static PlacementDirections getPlacement(CommandContext<CommandSourceStack> commandContext, String string) {
|
||||
return commandContext.getArgument(string, PlacementDirections.class);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue