From ee093397d307f2ca4743c1eea70ad866a4e9e741 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 4 Jan 2021 00:21:49 -0700 Subject: [PATCH] begin work on janky pregenerator --- .gitignore | 1 + .../items/state/BufferedStateManipulator.java | 27 +++++ .../world/generation/TerraChunkGenerator.java | 2 +- .../generation/MasterChunkGenerator.java | 2 +- platforms/region/build.gradle.kts | 26 ++++ .../java/com/dfsek/terra/RegionGenerator.java | 18 +++ .../com/dfsek/terra/StandalonePlugin.java | 111 ++++++++++++++++++ .../java/com/dfsek/terra/platform/Data.java | 71 +++++++++++ .../dfsek/terra/platform/DirectChunkData.java | 41 +++++++ .../com/dfsek/terra/platform/DirectWorld.java | 88 ++++++++++++++ .../com/dfsek/terra/platform/GenWrapper.java | 67 +++++++++++ .../com/dfsek/terra/platform/RawBiome.java | 16 +++ .../com/dfsek/terra/platform/RawTree.java | 25 ++++ .../dfsek/terra/platform/RawWorldHandle.java | 45 +++++++ .../com/dfsek/terra/region/Generator.java | 87 ++++++++++++++ .../com/dfsek/terra/region/RegionWriter.java | 5 + settings.gradle.kts | 2 +- 17 files changed, 631 insertions(+), 3 deletions(-) create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/state/BufferedStateManipulator.java create mode 100644 platforms/region/build.gradle.kts create mode 100644 platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/Data.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/region/Generator.java create mode 100644 platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java diff --git a/.gitignore b/.gitignore index 2acf9e5c9..ab2a28212 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,4 @@ build /lang/ /packs/ /config.yml +/region/ diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/state/BufferedStateManipulator.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/state/BufferedStateManipulator.java new file mode 100644 index 000000000..ec8f72c41 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/state/BufferedStateManipulator.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.api.structures.structure.buffer.items.state; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; + +@SuppressWarnings("unchecked") +public abstract class BufferedStateManipulator implements BufferedItem { + private final TerraPlugin main; + + protected BufferedStateManipulator(TerraPlugin main) { + this.main = main; + } + + @Override + public void paste(Location origin) { + BlockState state = origin.getBlock().getState(); + try { + apply((T) state); + } catch(ClassCastException e) { + main.getLogger().warning("Could not find expected BlockState at " + origin + "; found " + origin.getBlock().getBlockData().getAsString()); + } + } + + public abstract void apply(T state); +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java index 85d2cea78..5273916a1 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Random; public interface TerraChunkGenerator { - ChunkGenerator.ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, ChunkGenerator.ChunkData original); + ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, ChunkGenerator.ChunkData original); void generateBiomes(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome); diff --git a/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java b/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java index 0abb1a2d1..ed049ebe6 100644 --- a/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/generation/MasterChunkGenerator.java @@ -86,7 +86,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator { @Override @SuppressWarnings({"try"}) - public ChunkGenerator.ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, ChunkGenerator.ChunkData chunk) { + public ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkGenerator.ChunkData chunk) { TerraWorld tw = main.getWorld(world); com.dfsek.terra.api.world.biome.BiomeGrid grid = tw.getGrid(); try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) { diff --git a/platforms/region/build.gradle.kts b/platforms/region/build.gradle.kts new file mode 100644 index 000000000..3d467c794 --- /dev/null +++ b/platforms/region/build.gradle.kts @@ -0,0 +1,26 @@ +import com.dfsek.terra.configureCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + `java-library` +} + +configureCommon() + +group = "com.dfsek.terra" + +repositories { + mavenCentral() + maven { url = uri("https://jitpack.io/") } +} + +dependencies { + "shadedApi"(project(":common")) + "shadedImplementation"("com.github.Querz:NBT:5.2") // Standalone NBT API + "shadedImplementation"("org.yaml:snakeyaml:1.27") + "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") +} + +tasks.named("shadowJar") { + relocate("net.querz", "com.dfsek.terra.libs.nbt") +} \ No newline at end of file diff --git a/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java b/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java new file mode 100644 index 000000000..52ceb47f6 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java @@ -0,0 +1,18 @@ +package com.dfsek.terra; + +import com.dfsek.terra.region.Generator; + +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; + +public class RegionGenerator { + public static void main(String[] args) throws IOException { + long seed; + if(args.length == 1) seed = Long.parseLong(args[0]); + else seed = ThreadLocalRandom.current().nextLong(); + + Generator generator = new Generator(seed); + + generator.generate(); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java new file mode 100644 index 000000000..741c34674 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java @@ -0,0 +1,111 @@ +package com.dfsek.terra; + +import com.dfsek.tectonic.loading.TypeRegistry; +import com.dfsek.terra.api.GenericLoaders; +import com.dfsek.terra.api.lang.Language; +import com.dfsek.terra.api.platform.TerraPlugin; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.ItemHandle; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Biome; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.config.base.PluginConfig; +import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.platform.RawBiome; +import com.dfsek.terra.platform.RawWorldHandle; +import com.dfsek.terra.registry.ConfigRegistry; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; + +public class StandalonePlugin implements TerraPlugin { + private final ConfigRegistry registry = new ConfigRegistry(); + private final PluginConfig config = new PluginConfig(); + private final RawWorldHandle worldHandle = new RawWorldHandle(); + + @Override + public WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public TerraWorld getWorld(World world) { + return new TerraWorld(world, registry.get("DEFAULT"), this); + } + + @Override + public Logger getLogger() { + return Logger.getLogger("Terra"); + } + + @Override + public PluginConfig getTerraConfig() { + return config; + } + + @Override + public File getDataFolder() { + return new File("."); + } + + @Override + public boolean isDebug() { + return true; + } + + @Override + public Language getLanguage() { + try { + return new Language(new File(getDataFolder(), "lang/en_us.yml")); + } catch(IOException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public ConfigRegistry getRegistry() { + return registry; + } + + @Override + public void reload() { + throw new UnsupportedOperationException(); + } + + @Override + public ItemHandle getItemHandle() { + return null; + } + + @Override + public void saveDefaultConfig() { + + } + + @Override + public String platformName() { + return "Standalone"; + } + + @Override + public void register(TypeRegistry registry) { + registry + .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) + .registerLoader(Biome.class, (t, o, l) -> new RawBiome(o.toString())) + .registerLoader(MaterialData.class, (t, o, l) -> worldHandle.createMaterialData((String) o)); + new GenericLoaders(this).register(registry); + } + + public void load() { + LangUtil.load("en_us", this); + registry.loadAll(this); + config.load(this); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java new file mode 100644 index 000000000..705ff12ad --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java @@ -0,0 +1,71 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import net.querz.nbt.tag.CompoundTag; + +public class Data implements BlockData, MaterialData { + private final CompoundTag data; + private final String noProp; + + public Data(String data) { + this.data = new CompoundTag(); + if(data.contains("[")) noProp = data.substring(0, data.indexOf('[')); // Strip properties for now TODO: actually do properties lol + else noProp = data; + this.data.putString("Name", noProp); + } + + @Override + public MaterialData getMaterial() { + return this; + } + + @Override + public boolean matches(MaterialData materialData) { + return ((Data) materialData).noProp.equals(noProp); + } + + @Override + public boolean matches(BlockData other) { + return ((Data) other).noProp.equals(noProp); + } + + @Override + public boolean isSolid() { + return !isAir(); //TODO: actual implementation + } + + @Override + public boolean isAir() { + return noProp.equals("minecraft:air"); + } + + @Override + public double getMaxDurability() { + return 0; + } + + @Override + public BlockData createBlockData() { + return this; + } + + @Override + public BlockData clone() { + try { + return (BlockData) super.clone(); + } catch(CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public String getAsString() { + return noProp; + } + + @Override + public CompoundTag getHandle() { + return data; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java new file mode 100644 index 000000000..a0c694680 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java @@ -0,0 +1,41 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import net.querz.mca.Chunk; +import net.querz.nbt.tag.CompoundTag; +import org.jetbrains.annotations.NotNull; + +public class DirectChunkData implements ChunkGenerator.ChunkData { + private final Chunk delegate; + private final int offX; + private final int offZ; + + public DirectChunkData(Chunk delegate, int offX, int offZ) { + this.delegate = delegate; + this.offX = offX; + this.offZ = offZ; + } + + @Override + public Object getHandle() { + return delegate; + } + + @Override + public int getMaxHeight() { + return 255; + } + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { + delegate.setBlockStateAt(x, y, z, ((Data) blockData).getHandle(), false); + } + + @Override + public @NotNull BlockData getBlockData(int x, int y, int z) { + CompoundTag tag = delegate.getBlockStateAt(x, y, z); + if(tag == null) return new Data("minecraft:air"); + return new Data(tag.getString("Name")); + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java new file mode 100644 index 000000000..71bc47b6d --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java @@ -0,0 +1,88 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.entity.Entity; +import com.dfsek.terra.api.platform.world.entity.EntityType; + +import java.io.File; +import java.util.UUID; + +public class DirectWorld implements World { + private final long seed; + private final GenWrapper generator; + + public DirectWorld(long seed, GenWrapper generator) { + this.seed = seed; + this.generator = generator; + } + + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return 255; + } + + @Override + public ChunkGenerator getGenerator() { + return generator; + } + + @Override + public String getName() { + return null; + } + + @Override + public UUID getUID() { + return null; + } + + @Override + public boolean isChunkGenerated(int x, int z) { + return false; + } + + @Override + public Chunk getChunkAt(int x, int z) { + return null; + } + + @Override + public File getWorldFolder() { + return null; + } + + @Override + public Block getBlockAt(int x, int y, int z) { + return null; + } + + @Override + public Block getBlockAt(Location l) { + return null; + } + + @Override + public boolean generateTree(Location l, Tree vanillaTreeType) { + return false; + } + + @Override + public Entity spawnEntity(Location location, EntityType entityType) { + return null; + } + + @Override + public Object getHandle() { + return generator; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java new file mode 100644 index 000000000..9b68bc4a2 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java @@ -0,0 +1,67 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.generator.BlockPopulator; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.platform.world.BiomeGrid; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.generation.MasterChunkGenerator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class GenWrapper implements ChunkGenerator { + private final MasterChunkGenerator generator; + + public GenWrapper(MasterChunkGenerator generator) { + this.generator = generator; + } + + @Override + public Object getHandle() { + return generator; + } + + @Override + public boolean isParallelCapable() { + return true; + } + + @Override + public boolean shouldGenerateCaves() { + return true; + } + + @Override + public boolean shouldGenerateDecorations() { + return true; + } + + @Override + public boolean shouldGenerateMobs() { + return true; + } + + @Override + public boolean shouldGenerateStructures() { + return true; + } + + @Override + public ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { + throw new UnsupportedOperationException(); // gen is directly handled by Generator + } + + @Override + public List getDefaultPopulators(World world) { + return Collections.emptyList(); + } + + @Override + public @Nullable TerraChunkGenerator getTerraGenerator() { + return generator; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java new file mode 100644 index 000000000..d9082aa4c --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.world.Biome; + +public class RawBiome implements Biome { + private final String id; + + public RawBiome(String id) { + this.id = id; + } + + @Override + public Object getHandle() { + return id; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java new file mode 100644 index 000000000..b1ced73b6 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.world.Tree; + +import java.util.Random; +import java.util.Set; + +public class RawTree implements Tree { // TODO: implement + @Override + public Object getHandle() { + return null; + } + + @Override + public boolean plant(Location l, Random r) { + return false; + } + + @Override + public Set getSpawnable() { + return null; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java new file mode 100644 index 000000000..c88ef66a7 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.platform; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.MaterialData; +import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.platform.world.entity.EntityType; + +public class RawWorldHandle implements WorldHandle { + @Override + public void setBlockData(Block block, BlockData data, boolean physics) { + + } + + @Override + public BlockData getBlockData(Block block) { + return null; + } + + @Override + public MaterialData getType(Block block) { + return null; + } + + @Override + public BlockData createBlockData(String data) { + return new Data(data); + } + + @Override + public MaterialData createMaterialData(String data) { + return new Data(data); + } + + @Override + public Tree getTree(String id) { + return new RawTree(); + } + + @Override + public EntityType getEntity(String id) { + return null; + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java new file mode 100644 index 000000000..f7415c15e --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java @@ -0,0 +1,87 @@ +package com.dfsek.terra.region; + +import com.dfsek.terra.StandalonePlugin; +import com.dfsek.terra.api.platform.generator.ChunkGenerator; +import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.generation.MasterChunkGenerator; +import com.dfsek.terra.generation.math.SamplerCache; +import com.dfsek.terra.platform.DirectChunkData; +import com.dfsek.terra.platform.DirectWorld; +import com.dfsek.terra.platform.GenWrapper; +import net.querz.mca.Chunk; +import net.querz.mca.MCAFile; +import net.querz.mca.MCAUtil; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Generator { + private final Map files = new HashMap<>(); + + private final long seed; + + public Generator(long seed) { + this.seed = seed; + } + + public void generate() throws IOException { + + int rad = 50; + + StandalonePlugin plugin = new StandalonePlugin(); + plugin.load(); + + + MasterChunkGenerator generator = new MasterChunkGenerator(plugin.getRegistry().get("DEFAULT"), plugin, new SamplerCache(plugin)); + GenWrapper wrapper = new GenWrapper(generator); + + int count = 0; + + List times = new GlueList<>(); + + for(int cx = -rad; cx <= rad; cx++) { + for(int cz = -rad; cz <= rad; cz++) { + long start = System.nanoTime(); + + long key = (((long) MCAUtil.chunkToRegion(cx)) << 32) | (MCAUtil.chunkToRegion(cz) & 0xffffffffL); + + int finalCx = cx; + int finalCz = cz; + MCAFile file = files.computeIfAbsent(key, k -> new MCAFile(MCAUtil.chunkToRegion(finalCx), MCAUtil.chunkToRegion(finalCz))); + + Chunk chunk = Chunk.newChunk(); + + ChunkGenerator.ChunkData chunkData = new DirectChunkData(chunk, cx, cz); + generator.generateChunkData(new DirectWorld(seed, wrapper), null, cx, cz, chunkData); + + file.setChunk(cx, cz, chunk); + + long end = System.nanoTime() - start; + count++; + times.add((double) end / 1000000); + + if(count % 200 == 0) { + double total = 0; + for(double d : times) total += d; + double avg = total / count; + + double pct = ((double) count / (rad * rad * 2 * 2)) * 100D; + + plugin.getLogger().info("Generated " + count + " chunks. " + (1 / avg) * 1000 + "cps; " + pct + "%"); + } + } + } + + for(Map.Entry entry : files.entrySet()) { + entry.getValue().cleanupPalettesAndBlockStates(); + int x = (int) (entry.getKey() >> 32); + int z = (int) (long) entry.getKey(); + File file = new File("region", MCAUtil.createNameFromRegionLocation(x, z)); + file.getParentFile().mkdirs(); + MCAUtil.write(entry.getValue(), file); + } + } +} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java b/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java new file mode 100644 index 000000000..7ae434669 --- /dev/null +++ b/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.region; + +public class RegionWriter { + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 61c60a585..682f7912b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,7 +11,7 @@ rootProject.name = "Terra" include("common") include("platforms:bukkit") include("platforms:fabric") - +include("platforms:region") pluginManagement { repositories {