- use forge permission system for commands

- set sapling listener to lowest priority for Nature's Aura compat
- tweak feature debugger and catch any exceptions thrown during debugging
This commit is contained in:
dags- 2020-04-30 11:56:20 +01:00
parent c9b55cacad
commit e3ca04e78b
8 changed files with 155 additions and 8 deletions

@ -1 +1 @@
Subproject commit 5af4aff86ab3e3a362346bb91076d2bdb0206ca7
Subproject commit dcc1e0c9cdd25fdbb1605314002b031543ecee30

View File

@ -0,0 +1,10 @@
package com.terraforged.mod.command;
public class Permissions {
public static final String QUERY = "terraforged.command.terra.query";
public static final String DEBUG = "terraforged.command.terra.debug";
public static final String DATA = "terraforged.command.terra.data";
public static final String DEFAULTS = "terraforged.command.terra.defaults";
public static final String LOCATE = "terraforged.command.terra.locate";
}

View File

@ -49,7 +49,6 @@ import com.terraforged.mod.data.DataGen;
import com.terraforged.mod.settings.SettingsHelper;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.command.arguments.ArgumentSerializer;
import net.minecraft.command.arguments.ArgumentTypes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
@ -70,18 +69,21 @@ import net.minecraft.world.gen.ChunkGenerator;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.server.permission.DefaultPermissionLevel;
import net.minecraftforge.server.permission.PermissionAPI;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.function.Supplier;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
public class TerraCommand {
public static void init() {
ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new ArgumentSerializer<>(BiomeArgType::new));
ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new ArgumentSerializer<>(TerrainArgType::new));
ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new BiomeArgType.Serializer());
ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new TerrainArgType.Serializer());
}
@SubscribeEvent
@ -92,22 +94,31 @@ public class TerraCommand {
public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(command());
PermissionAPI.registerNode(Permissions.QUERY, DefaultPermissionLevel.OP, "Allows use of the query command");
PermissionAPI.registerNode(Permissions.DATA, DefaultPermissionLevel.OP, "Allows use of the data command");
PermissionAPI.registerNode(Permissions.DEFAULTS, DefaultPermissionLevel.OP, "Allows use of the defaults command");
PermissionAPI.registerNode(Permissions.DEBUG, DefaultPermissionLevel.OP, "Allows use of the debug command");
PermissionAPI.registerNode(Permissions.LOCATE, DefaultPermissionLevel.OP, "Allows use of the locate command");
}
private static LiteralArgumentBuilder<CommandSource> command() {
return Commands.literal("terra")
.requires(source -> source.hasPermissionLevel(2))
.then(Commands.literal("query")
.requires(perm(Permissions.QUERY))
.executes(TerraCommand::query))
.then(Commands.literal("data")
.requires(perm(Permissions.DATA))
.then(Commands.literal("dump")
.executes(TerraCommand::dump)))
.then(Commands.literal("defaults")
.requires(perm(Permissions.DEFAULTS))
.then(Commands.literal("set")
.executes(TerraCommand::setDefaults)))
.then(Commands.literal("debug")
.requires(perm(Permissions.DEBUG))
.executes(TerraCommand::debugBiome))
.then(Commands.literal("locate")
.requires(perm(Permissions.LOCATE))
.then(Commands.argument("biome", BiomeArgType.biome())
.executes(TerraCommand::findBiome)
.then(Commands.argument("terrain", TerrainArgType.terrain())
@ -283,6 +294,16 @@ public class TerraCommand {
return find;
}
private static Predicate<CommandSource> perm(String node) {
return source -> {
try {
return PermissionAPI.hasPermission(source.asPlayer(), node);
} catch (Throwable t) {
return source.hasPermissionLevel(2);
}
};
}
private static BiomeProvider getBiomeProvider(CommandContext<CommandSource> context) {
return (BiomeProvider) context.getSource().getWorld().getChunkProvider().getChunkGenerator().getBiomeProvider();
}

View File

@ -25,6 +25,7 @@
package com.terraforged.mod.command.arg;
import com.google.gson.JsonObject;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
@ -33,6 +34,8 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.command.ISuggestionProvider;
import net.minecraft.command.arguments.IArgumentSerializer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.StringTextComponent;
@ -69,4 +72,22 @@ public class BiomeArgType implements ArgumentType<Biome> {
public static <S> Biome getBiome(CommandContext<S> context, String name) {
return context.getArgument(name, Biome.class);
}
public static class Serializer implements IArgumentSerializer<BiomeArgType> {
@Override
public void write(BiomeArgType type, PacketBuffer buffer) {
}
@Override
public BiomeArgType read(PacketBuffer buffer) {
return new BiomeArgType();
}
@Override
public void write(BiomeArgType type, JsonObject json) {
}
}
}

View File

@ -25,6 +25,7 @@
package com.terraforged.mod.command.arg;
import com.google.gson.JsonObject;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
@ -34,6 +35,8 @@ import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.terraforged.core.world.terrain.Terrain;
import net.minecraft.command.ISuggestionProvider;
import net.minecraft.command.arguments.IArgumentSerializer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.text.StringTextComponent;
import java.util.List;
@ -42,7 +45,15 @@ import java.util.stream.Collectors;
public class TerrainArgType implements ArgumentType<Terrain> {
private final List<Terrain> terrains = Terrain.getRegistered();
private final List<Terrain> terrains;
public TerrainArgType() {
this(Terrain.getRegistered());
}
public TerrainArgType(List<Terrain> terrains) {
this.terrains = terrains;
}
@Override
public Terrain parse(StringReader reader) throws CommandSyntaxException {
@ -76,4 +87,22 @@ public class TerrainArgType implements ArgumentType<Terrain> {
new StringTextComponent(String.format(message, args))
);
}
public static class Serializer implements IArgumentSerializer<TerrainArgType> {
@Override
public void write(TerrainArgType type, PacketBuffer buffer) {
}
@Override
public TerrainArgType read(PacketBuffer buffer) {
return new TerrainArgType();
}
@Override
public void write(TerrainArgType type, JsonObject json) {
}
}
}

View File

@ -30,12 +30,24 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.JsonOps;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.jigsaw.JigsawManager;
import net.minecraft.world.gen.feature.jigsaw.JigsawPattern;
import net.minecraft.world.gen.feature.jigsaw.JigsawPatternRegistry;
import net.minecraft.world.gen.feature.jigsaw.JigsawPiece;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraftforge.registries.ForgeRegistries;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class WorldGenFeatures extends DataGen {
@ -43,7 +55,9 @@ public class WorldGenFeatures extends DataGen {
if (dataDir.exists() || dataDir.mkdirs()) {
for (Biome biome : ForgeRegistries.BIOMES) {
genBiomeFeatures(dataDir, biome);
genBiomeStructures(dataDir, biome);
}
genBiomeJigsaws(dataDir);
}
}
@ -65,4 +79,55 @@ public class WorldGenFeatures extends DataGen {
write(root, writer);
});
}
private static void genBiomeStructures(File dir, Biome biome) {
write(new File(dir, getJsonPath("structures", biome.getRegistryName())), writer -> {
JsonObject root = new JsonObject();
for (Map.Entry<String, Structure<?>> e : Structure.STRUCTURES.entrySet()) {
JsonArray array = new JsonArray();
IFeatureConfig config = biome.getStructureConfig(e.getValue());
if (config == null) {
continue;
}
JsonElement element = config.serialize(JsonOps.INSTANCE).getValue();
JsonObject object = new JsonObject();
object.addProperty("structure", e.getValue().getRegistryName() + "");
object.add("config", element);
array.add(object);
}
write(root, writer);
});
}
private static void genBiomeJigsaws(File dir) {
Random random = new Random();
write(new File(dir, "jigsaws.json"), writer -> {
JsonObject root = new JsonObject();
for (Map.Entry<ResourceLocation, JigsawPattern> e : getJigsawRegistry().entrySet()) {
JsonArray array = new JsonArray();
List<JigsawPiece> pieces = e.getValue().getShuffledPieces(random);
for (JigsawPiece piece : pieces) {
JsonElement element = piece.serialize(JsonOps.INSTANCE).getValue();
array.add(element);
}
root.add(e.getKey().toString(), array);
}
write(root, writer);
});
}
private static Map<ResourceLocation, JigsawPattern> getJigsawRegistry() {
try {
for (Field field : JigsawPatternRegistry.class.getDeclaredFields()) {
if (field.getType() == Map.class) {
field.setAccessible(true);
Object value = field.get(JigsawManager.REGISTRY);
return (Map<ResourceLocation, JigsawPattern>) value;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return Collections.emptyMap();
}
}

View File

@ -39,6 +39,7 @@ import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.event.world.SaplingGrowTreeEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -54,7 +55,7 @@ public class SaplingListener {
{new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(0, 0, 1)},
};
@SubscribeEvent
@SubscribeEvent(priority = EventPriority.LOWEST)
public static void onTreeGrow(SaplingGrowTreeEvent event) {
// ignore if client
if (event.getWorld().isRemote()) {

View File

@ -53,6 +53,6 @@ public class StructurePage extends BasePage {
@Override
public void init(OverlayScreen parent) {
Column left = getColumn(0);
addElements(left.left, left.top, left, structureSettings, false, left.scrollPane::addButton, this::update);
addElements(left.left, left.top, left, structureSettings, true, left.scrollPane::addButton, this::update);
}
}