diff --git a/FeatureManager b/FeatureManager index 5af4aff..dcc1e0c 160000 --- a/FeatureManager +++ b/FeatureManager @@ -1 +1 @@ -Subproject commit 5af4aff86ab3e3a362346bb91076d2bdb0206ca7 +Subproject commit dcc1e0c9cdd25fdbb1605314002b031543ecee30 diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java new file mode 100644 index 0000000..a8a6926 --- /dev/null +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java @@ -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"; +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java index 50800e8..55d2c91 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java @@ -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 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 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 perm(String node) { + return source -> { + try { + return PermissionAPI.hasPermission(source.asPlayer(), node); + } catch (Throwable t) { + return source.hasPermissionLevel(2); + } + }; + } + private static BiomeProvider getBiomeProvider(CommandContext context) { return (BiomeProvider) context.getSource().getWorld().getChunkProvider().getChunkGenerator().getBiomeProvider(); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java index 0dfc4a5..ab2a4b3 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java @@ -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 { public static Biome getBiome(CommandContext context, String name) { return context.getArgument(name, Biome.class); } + + public static class Serializer implements IArgumentSerializer { + + @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) { + + } + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java index 9a06b1c..0fd01d1 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java @@ -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 { - private final List terrains = Terrain.getRegistered(); + private final List terrains; + + public TerrainArgType() { + this(Terrain.getRegistered()); + } + + public TerrainArgType(List terrains) { + this.terrains = terrains; + } @Override public Terrain parse(StringReader reader) throws CommandSyntaxException { @@ -76,4 +87,22 @@ public class TerrainArgType implements ArgumentType { new StringTextComponent(String.format(message, args)) ); } + + public static class Serializer implements IArgumentSerializer { + + @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) { + + } + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java b/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java index cbe327b..4c1d082 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java @@ -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> 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 e : getJigsawRegistry().entrySet()) { + JsonArray array = new JsonArray(); + List 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 getJigsawRegistry() { + try { + for (Field field : JigsawPatternRegistry.class.getDeclaredFields()) { + if (field.getType() == Map.class) { + field.setAccessible(true); + Object value = field.get(JigsawManager.REGISTRY); + return (Map) value; + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + return Collections.emptyMap(); + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java index d8a4a9b..7836573 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java @@ -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()) { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java b/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java index b1582c5..e0a8278 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java @@ -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); } }