pocket command

This commit is contained in:
SD 2021-03-31 16:37:19 +05:30
parent c826c5adb0
commit dfb405761e
10 changed files with 217 additions and 52 deletions

View file

@ -57,6 +57,14 @@ repositories {
name = 'TerraformersMC'
url = 'https://maven.terraformersmc.com/'
}
maven {
name = "Libs"
url = "./libs"
metadataSources {
artifact()
}
}
}
def includeCompile(group, artifact, version) {
@ -137,6 +145,8 @@ dependencies {
}
modCompileOnly "me.shedaniel.cloth.api:cloth-datagen-api-v1:2.0.0"
modRuntime "me.shedaniel.cloth.api:cloth-datagen-api-v1:2.0.0"
modCompileOnly "worldedit:worldedit:7.2.3"
modRuntime "worldedit:worldedit:7.2.3"
datagenImplementation sourceSets.main.output
datagenImplementation sourceSets.main.compileClasspath

Binary file not shown.

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>worldedit</groupId>
<artifactId>worldedit</artifactId>
<version>7.2.3</version>
</project>

View file

@ -100,6 +100,7 @@ public final class ModConfig implements ConfigData {
@Tooltip public int fallbackWeight = 5;
@Tooltip @EnumHandler(option = BUTTON) public ExtendedResourcePackActivationType classicPocketsResourcePackActivationType = ExtendedResourcePackActivationType.DEFAULT_ENABLED;
@Tooltip @EnumHandler(option = BUTTON) public ExtendedResourcePackActivationType defaultPocketsResourcePackActivationType = ExtendedResourcePackActivationType.DEFAULT_ENABLED;
@Tooltip public boolean asyncWorldEditPocketLoading = true;
}
public static class World {

View file

@ -6,8 +6,8 @@ public final class ModCommands {
public static void init() {
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
DimTeleportCommand.register(dispatcher);
SchematicCommand.register(dispatcher);
SchematicCommand.register(dispatcher);
PocketCommand.register(dispatcher);
PocketCommand.register(dispatcher);
});
}
}

View file

@ -0,0 +1,120 @@
package org.dimdev.dimdoors.command;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import com.google.common.collect.HashBiMap;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader;
import com.sk89q.worldedit.fabric.FabricAdapter;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.session.ClipboardHolder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.api.util.BlockPlacementType;
import org.dimdev.dimdoors.command.arguments.EnumArgumentType;
import org.dimdev.dimdoors.command.arguments.PocketTemplateArgumentType;
import org.dimdev.dimdoors.pockets.PocketLoader;
import org.dimdev.dimdoors.pockets.PocketTemplate;
import org.dimdev.dimdoors.util.schematic.Schematic;
import org.dimdev.dimdoors.util.schematic.SchematicPlacer;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.fabricmc.loader.api.FabricLoader;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
public class PocketCommand {
private static final Logger LOGGER = LogManager.getLogger();
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(
literal("pocket")
.requires(source -> source.hasPermissionLevel(2))
.then(
literal("schematic")
.then(
literal("place")
.then(
argument("pocket_template", new PocketTemplateArgumentType())
.executes(ctx -> place(ctx.getSource().getPlayer(), PocketTemplateArgumentType.getValue(ctx, "pocket_template"), BlockPlacementType.SECTION_NO_UPDATE))
.then(
argument("placement_type", new EnumArgumentType<>(BlockPlacementType.class))
.executes(ctx -> place(ctx.getSource().getPlayer(), PocketTemplateArgumentType.getValue(ctx, "pocket_template"), ctx.getArgument("placement_type", BlockPlacementType.class)))
)
)
)
.then(
literal("load")
.requires(source -> FabricLoader.getInstance().isModLoaded("worldedit"))
.then(
argument("pocket_template", new PocketTemplateArgumentType())
.executes(ctx -> load(ctx.getSource(), PocketTemplateArgumentType.getValue(ctx, "pocket_template")))
)
)
)
);
}
private static int load(ServerCommandSource source, PocketTemplate template) throws CommandSyntaxException {
ServerPlayerEntity player = source.getPlayer();
boolean async = DimensionalDoorsInitializer.getConfig().getPocketsConfig().asyncWorldEditPocketLoading;
Consumer<Text> messageSender = async ? t -> source.getMinecraftServer().execute(() -> {
source.sendFeedback(t, true);
}) : t -> source.sendFeedback(t, true);
Runnable task = () -> {
CompoundTag tag = Schematic.toTag(template.getSchematic());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
NbtIo.writeCompressed(tag, stream);
} catch (IOException e) {
throw new RuntimeException(e); // Can't happen, the stream is a ByteArrayOutputStream
}
Clipboard clipboard;
try {
clipboard = new SpongeSchematicReader(new NBTInputStream(new ByteArrayInputStream(stream.toByteArray()))).read();
} catch (IOException e) {
throw new RuntimeException(e); // Can't happen, the stream is a ByteArrayInputStream
}
WorldEdit.getInstance().getSessionManager().get(FabricAdapter.adaptPlayer(player)).setClipboard(new ClipboardHolder(clipboard));
messageSender.accept(new TranslatableText("commands.pocket.loadedSchem", HashBiMap.create(PocketLoader.getInstance().getTemplates()).inverse().get(template).reduce(String::concat).get()));
};
if (async) {
CompletableFuture.runAsync(task);
} else {
task.run();
}
return Command.SINGLE_SUCCESS;
}
private static int place(ServerPlayerEntity source, PocketTemplate template, BlockPlacementType blockPlacementType) throws CommandSyntaxException {
SchematicPlacer.place(
template.getSchematic(),
source.getServerWorld(),
source.getBlockPos(),
blockPlacementType
);
String id = HashBiMap.create(PocketLoader.getInstance().getTemplates()).inverse().get(template).reduce(String::concat).get();
source.getCommandSource().sendFeedback(new TranslatableText("commands.pocket.placedSchem", id, "" + source.getBlockPos().getX() + ", " + source.getBlockPos().getY() + ", " + source.getBlockPos().getZ(), source.world.getRegistryKey().getValue().toString()), true);
return Command.SINGLE_SUCCESS;
}
}

View file

@ -1,45 +0,0 @@
package org.dimdev.dimdoors.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.command.arguments.PocketTemplateArgumentType;
import org.dimdev.dimdoors.pockets.PocketTemplate;
import org.dimdev.dimdoors.api.util.BlockPlacementType;
import org.dimdev.dimdoors.util.schematic.SchematicPlacer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
public class SchematicCommand {
private static final Logger LOGGER = LogManager.getLogger();
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(literal("schematic") // TODO: better command name
.then(argument("pocket_template", new PocketTemplateArgumentType())
.executes(SchematicCommand::place)
)
);
}
private static int place(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException {
ServerPlayerEntity player = ctx.getSource().getPlayer();
PocketTemplate template = PocketTemplateArgumentType.getValue(ctx, "pocket_template");
SchematicPlacer.place(
template.getSchematic(),
ctx.getSource().getWorld(),
ctx.getSource().getPlayer().getBlockPos(),
BlockPlacementType.SECTION_NO_UPDATE // TODO: placement type argument
);
// TODO
//LOGGER.info(String.format("Placed schematic %s from namespace %s at %s in world %s", id, ns, player.getBlockPos(), player.getServerWorld().getRegistryKey().getValue()));
return 1;
}
}

View file

@ -0,0 +1,54 @@
package org.dimdev.dimdoors.command.arguments;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
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.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.command.CommandSource;
import net.minecraft.text.TranslatableText;
public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
public static final DynamicCommandExceptionType UNKNOWN_VALUE = new DynamicCommandExceptionType(str -> new TranslatableText("commands.generic.unknownValue", str));
private final Map<String, T> values;
private final Set<String> valueList;
public EnumArgumentType(Class<T> enumClass) {
values = new HashMap<>();
for (T enumConstant : enumClass.getEnumConstants()) {
values.put(enumConstant.name().toLowerCase(), enumConstant);
}
valueList = values.keySet();
}
@Override
public T parse(StringReader reader) throws CommandSyntaxException {
String str = reader.readString();
return Optional.ofNullable(str)
.map(values::get)
.orElseThrow(() -> UNKNOWN_VALUE.create(str));
}
@Override
public Collection<String> getExamples() {
return valueList;
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(valueList, builder);
}
}

View file

@ -4,9 +4,11 @@ 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.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.command.CommandSource;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier;
import org.dimdev.dimdoors.api.util.Path;
import org.dimdev.dimdoors.api.util.SimpleTree;
@ -16,17 +18,20 @@ import org.dimdev.dimdoors.pockets.PocketTemplate;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class PocketTemplateArgumentType implements ArgumentType<PocketTemplate> {
public static final DynamicCommandExceptionType UNKNOWN_POCKET_TEMPLATE = new DynamicCommandExceptionType(s -> new TranslatableText("commands.pocket.unknownPocketTemplate", s));
@Override
public PocketTemplate parse(StringReader reader) throws CommandSyntaxException {
Path<String> value = Path.stringPath(Objects.requireNonNull(reader.readString()));
String strValue = reader.readString();
Path<String> value = Path.stringPath(strValue);
if (!getPocketTemplates().containsKey(value)) {
// TODO: throw
throw UNKNOWN_POCKET_TEMPLATE.create(value.toString());
}
return getPocketTemplates().get(value);
}
@ -38,7 +43,14 @@ public class PocketTemplateArgumentType implements ArgumentType<PocketTemplate>
@Override
public Collection<String> getExamples() {
return getPocketTemplates().keySet().parallelStream().map(path -> path.reduce(String::concat)).map(id -> "\"" + id + "\"").collect(Collectors.toCollection(TreeSet::new));
return getPocketTemplates()
.keySet()
.parallelStream()
.map(path -> path.reduce(String::concat))
.filter(Optional::isPresent)
.map(Optional::get)
.map(id -> "\"" + id + "\"")
.collect(Collectors.toCollection(TreeSet::new));
}
private SimpleTree<String, PocketTemplate> getPocketTemplates() {

View file

@ -118,7 +118,7 @@
"fluid.dimdoors.eternal_fabric": "Eternal Fabric",
"entity.dimdoors.monolith": "",
"entity.dimdoors.monolith": "Monolith",
"commands.dimteleport.usage": "/dimteleport <dimension> <x> <y> <z> [yaw] [pitch]",
"commands.fabricconvert.usage": "/fabricconvert",
@ -130,6 +130,10 @@
"commands.dimdoors.saveschem.success": "Pocket %s has been successfully saved",
"commands.generic.dimdoors.not_in_pocket_dim": "You must be in a pocket dimension to use this command.",
"commands.generic.dimdoors.not_in_pocket": "You must be in a pocket to use this command.",
"commands.generic.unknownValue": "Unknown value '%s'",
"commands.pocket.unknownPocketTemplate": "Unknown Pocket Template '%s'",
"commands.pocket.placedSchem": "Placed schematic %s at %s in world %s",
"commands.pocket.loadedSchem": "Loaded schematic %s to clipboard. Paste it using //paste",
"rifts.unlinked1": "This rift doesn't lead anywhere",
"rifts.unlinked2": "This rift has closed",
@ -183,7 +187,8 @@
"text.autoconfig.dimdoors.option.pockets.classicPocketsResourcePackActivationType": "Classic Resource Pack Activation Type",
"text.autoconfig.dimdoors.option.pockets.classicPocketsResourcePackActivationType@Tooltip": "Default - Disabled but can be enabled, Default Enabled - Enabled but can be disabled, Always Enabled - Can not be disabled",
"text.autoconfig.dimdoors.option.pockets.defaultPocketsResourcePackActivationType": "Default Resource Pack Activation Type",
"text.autoconfig.dimdoors.option.pockets.defaultPocketsResourcePackActivationType@Tooltip": "Default - Disabled but can be enabled, Default Enabled - Enabled but can be disabled, Always Enabled - Can not be disabled.",
"text.autoconfig.dimdoors.option.pockets.asyncWorldEditPocketLoading": "Async WorldEdit Pocket Loading",
"text.autoconfig.dimdoors.option.pockets.asyncWorldEditPocketLoading@Tooltip": "Sets loading pockets to your WorldEdit clipboard asynchronous or synchronous. Only affects when WorldEdit is installed.",
"dimdoors.pocket.dyeAlreadyAbsorbed": "The pocket is already that color, so the rift didn't absorb the dye.",
"dimdoors.pocket.pocketHasBeenDyed": "The pocket has been dyed %s.",
"dimdoors.pocket.remainingNeededDyes": "The pocket has %s/%s of the dyes needed to be colored %s.",