diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 21036749f..d6fbe2a8f 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -15,7 +15,9 @@ buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
- maven { url = uri("https://repo.codemc.org/repository/maven-public") }
+ maven("https://repo.codemc.org/repository/maven-public") {
+ name = "CodeMC"
+ }
maven("https://papermc.io/repo/repository/maven-public/") {
name = "PaperMC"
}
diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt
index a507eb96c..55f6f18b6 100644
--- a/buildSrc/src/main/kotlin/DependencyConfig.kt
+++ b/buildSrc/src/main/kotlin/DependencyConfig.kt
@@ -30,11 +30,21 @@ fun Project.configureDependencies() {
repositories {
mavenCentral()
gradlePluginPortal()
- maven("https://maven.fabricmc.net/")
- maven("https://repo.codemc.org/repository/maven-public")
- maven("https://repo.codemc.io/repository/nms/")
- maven("https://papermc.io/repo/repository/maven-public/")
- maven ( "https://files.minecraftforge.net/maven/" )
+ maven("https://maven.fabricmc.net/") {
+ name = "FabricMC"
+ }
+ maven("https://repo.codemc.org/repository/maven-public") {
+ name = "CodeMC"
+ }
+ maven("https://papermc.io/repo/repository/maven-public/") {
+ name = "PaperMC"
+ }
+ maven ( "https://files.minecraftforge.net/maven/" ) {
+ name = "Forge"
+ }
+ maven ("https://maven.quiltmc.org/repository/release/") {
+ name = "Quilt"
+ }
}
dependencies {
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 78517707c..d5a77a8c4 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -25,6 +25,12 @@ object Versions {
const val minotaur = "1.1.0"
}
+ object Quilt {
+ const val quiltLoader = "0.17.0"
+ const val loom = "0.12.+"
+ const val fabricApi = "2.0.0-alpha.2+0.55.3-1.19"
+ }
+
object Mod {
const val minecraft = "1.19"
const val yarn = "$minecraft+build.1"
diff --git a/gradle.properties b/gradle.properties
index 62df22f83..35e42e00d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,11 @@
-# Magic options for more perf
+# Project information
+terra.description=A modern voxel world generation modding platform
+terra.source=https://github.com/PolyhedralDev/Terra
+terra.issues=https://github.com/PolyhedralDev/Terra/issues
+terra.wiki=https://github.com/PolyhedralDev/Terra/wiki
+terra.license=MIT
+
+# Gradle options
org.gradle.jvmargs=-Xmx3072M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.vfs.watch=true
kapt.use.worker.api=true
@@ -6,11 +13,3 @@ kapt.include.compile.classpath=false
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.warning.mode=all
-#org.gradle.logging.level=info
-#org.gradle.configureondemand=true
-# Project information
-terra.description=A modern voxel world generation modding platform
-terra.source=https://github.com/PolyhedralDev/Terra
-terra.issues=https://github.com/PolyhedralDev/Terra/issues
-terra.wiki=https://github.com/PolyhedralDev/Terra/wiki
-terra.license=GNU General Public License, version 3.0
\ No newline at end of file
diff --git a/platforms/mixin-common/build.gradle.kts b/platforms/mixin-common/build.gradle.kts
index 8646e8b39..47b720ca2 100644
--- a/platforms/mixin-common/build.gradle.kts
+++ b/platforms/mixin-common/build.gradle.kts
@@ -22,7 +22,7 @@ dependencies {
}
architectury {
- common("fabric", "forge")
+ common("fabric", "forge", "quilt")
minecraft = Versions.Mod.minecraft
}
diff --git a/platforms/quilt/build.gradle.kts b/platforms/quilt/build.gradle.kts
new file mode 100644
index 000000000..5bfcf8099
--- /dev/null
+++ b/platforms/quilt/build.gradle.kts
@@ -0,0 +1,60 @@
+plugins {
+ id("org.quiltmc.loom") version Versions.Quilt.loom
+ id("architectury-plugin") version Versions.Mod.architectutyPlugin
+}
+
+
+configurations {
+ val common by creating
+ compileClasspath.get().extendsFrom(common)
+ runtimeClasspath.get().extendsFrom(common)
+}
+
+dependencies {
+ shadedApi(project(":common:implementation:base"))
+
+ "common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false }
+ shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionQuilt")) { isTransitive = false }
+
+ minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}")
+ mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2")
+
+ modImplementation("org.quiltmc:quilt-loader:${Versions.Quilt.quiltLoader}")
+
+ modApi("org.quiltmc.quilted-fabric-api:quilted-fabric-api:${Versions.Quilt.fabricApi}")
+
+ setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base", "fabric-command-api-v2", "fabric-networking-api-v1").forEach { apiModule ->
+ val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI)
+ modImplementation(module)
+ include(module)
+ }
+
+ modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)
+ include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)
+}
+
+loom {
+ accessWidenerPath.set(project(":platforms:mixin-common").file("terra.accesswidener"))
+
+ mixin {
+ defaultRefmapName.set("terra.quilt.refmap.json")
+ }
+}
+
+
+addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get())
+
+tasks {
+ compileJava {
+ options.release.set(17)
+ }
+
+ remapJar {
+ inputFile.set(shadowJar.get().archiveFile)
+ archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar")
+ }
+
+ processResources {
+ from(project(":platforms:mixin-common").file("terra.accesswidener"))
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java
new file mode 100644
index 000000000..958e61080
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/PlatformImpl.java
@@ -0,0 +1,151 @@
+/*
+ * This file is part of Terra.
+ *
+ * Terra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Terra is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Terra. If not, see .
+ */
+
+package com.dfsek.terra.quilt;
+
+import ca.solostudios.strata.Versions;
+import ca.solostudios.strata.parser.tokenizer.ParseException;
+import ca.solostudios.strata.version.Version;
+import net.minecraft.MinecraftVersion;
+import net.minecraft.server.MinecraftServer;
+import org.jetbrains.annotations.NotNull;
+import org.quiltmc.loader.api.QuiltLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.dfsek.terra.addon.EphemeralAddon;
+import com.dfsek.terra.api.addon.BaseAddon;
+import com.dfsek.terra.api.handle.ItemHandle;
+import com.dfsek.terra.api.handle.WorldHandle;
+import com.dfsek.terra.api.util.generic.Lazy;
+import com.dfsek.terra.mod.CommonPlatform;
+import com.dfsek.terra.mod.ModPlatform;
+import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
+import com.dfsek.terra.mod.handle.MinecraftItemHandle;
+import com.dfsek.terra.mod.handle.MinecraftWorldHandle;
+import com.dfsek.terra.quilt.util.BiomeUtil;
+
+
+public class PlatformImpl extends ModPlatform {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class);
+ private final ItemHandle itemHandle = new MinecraftItemHandle();
+ private final WorldHandle worldHandle = new MinecraftWorldHandle();
+ private final Lazy dataFolder = Lazy.lazy(() -> new File(QuiltLoader.getConfigDir().toFile(), "Terra"));
+ private MinecraftServer server;
+
+ public PlatformImpl() {
+ CommonPlatform.initialize(this);
+ load();
+ }
+
+ public void setServer(MinecraftServer server) {
+ this.server = server;
+ }
+
+ @Override
+ public MinecraftServer getServer() {
+ return server;
+ }
+
+ @Override
+ public boolean reload() {
+ getTerraConfig().load(this);
+ getRawConfigRegistry().clear();
+ boolean succeed = getRawConfigRegistry().loadAll(this);
+
+
+ if(server != null) {
+ server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> {
+ LOGGER.warn("Failed to execute reload", throwable);
+ return null;
+ }).join();
+ BiomeUtil.registerBiomes();
+ server.getWorlds().forEach(world -> {
+ if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) {
+ getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> {
+ chunkGeneratorWrapper.setPack(pack);
+ LOGGER.info("Replaced pack in chunk generator for world {}", world);
+ });
+ }
+ });
+ }
+ return succeed;
+ }
+
+ @Override
+ protected Iterable platformAddon() {
+ List addons = new ArrayList<>();
+
+ super.platformAddon().forEach(addons::add);
+
+ String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget();
+ try {
+ addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft"));
+ } catch(ParseException e) {
+ try {
+ addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft"));
+ } catch(ParseException ex) {
+ LOGGER.warn("Failed to parse Minecraft version", e);
+ }
+ }
+
+ QuiltLoader.getAllMods().forEach(mod -> {
+ String id = mod.metadata().id();
+ if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return;
+ try {
+ Version version = Versions.parseVersion(mod.metadata().version().raw());
+ addons.add(new EphemeralAddon(version, "quilt:" + id));
+ } catch(ParseException e) {
+ LOGGER.warn(
+ "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " +
+ "it.",
+ id, mod.metadata().version().raw());
+ }
+ });
+
+ return addons;
+ }
+
+ @Override
+ public @NotNull String platformName() {
+ return "Quilt";
+ }
+
+ @Override
+ public @NotNull WorldHandle getWorldHandle() {
+ return worldHandle;
+ }
+
+ @Override
+ public @NotNull File getDataFolder() {
+ return dataFolder.value();
+ }
+
+ @Override
+ public @NotNull ItemHandle getItemHandle() {
+ return itemHandle;
+ }
+
+ @Override
+ public BaseAddon getPlatformAddon() {
+ return new QuiltAddon(this);
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java
new file mode 100644
index 000000000..6a34eab74
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltAddon.java
@@ -0,0 +1,16 @@
+package com.dfsek.terra.quilt;
+
+import com.dfsek.terra.mod.MinecraftAddon;
+import com.dfsek.terra.mod.ModPlatform;
+
+public class QuiltAddon extends MinecraftAddon {
+
+ public QuiltAddon(ModPlatform modPlatform) {
+ super(modPlatform);
+ }
+
+ @Override
+ public String getID() {
+ return "terra-quilt";
+ }
+}
\ No newline at end of file
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java
new file mode 100644
index 000000000..20adb8e3b
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/QuiltEntryPoint.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of Terra.
+ *
+ * Terra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Terra is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Terra. If not, see .
+ */
+
+package com.dfsek.terra.quilt;
+
+import cloud.commandframework.execution.CommandExecutionCoordinator;
+import cloud.commandframework.fabric.FabricServerCommandManager;
+import org.quiltmc.loader.api.ModContainer;
+import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;
+import net.minecraft.server.command.ServerCommandSource;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.registry.BuiltinRegistries;
+import net.minecraft.util.registry.Registry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.dfsek.terra.api.command.CommandSender;
+import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
+import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
+import com.dfsek.terra.quilt.util.BiomeUtil;
+import com.dfsek.terra.mod.CommonPlatform;
+import com.dfsek.terra.mod.data.Codecs;
+
+
+public class QuiltEntryPoint implements ModInitializer {
+ private static final Logger logger = LoggerFactory.getLogger(QuiltEntryPoint.class);
+
+ private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl();
+
+
+ public static PlatformImpl getPlatform() {
+ return TERRA_PLUGIN;
+ }
+
+ public static void register() { // register the things
+ Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER);
+ Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE);
+ }
+
+ public static void initialize() {
+ getPlatform().getEventManager().callEvent(
+ new PlatformInitializationEvent());
+ BiomeUtil.registerBiomes();
+ CommonPlatform.get().registerWorldTypes((id, preset) -> BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, id, preset));
+ }
+
+ @Override
+ public void onInitialize(ModContainer container) {
+ logger.info("Initializing Terra Quilt mod...");
+
+ FabricServerCommandManager manager = new FabricServerCommandManager<>(
+ CommandExecutionCoordinator.simpleCoordinator(),
+ serverCommandSource -> (CommandSender) serverCommandSource,
+ commandSender -> (ServerCommandSource) commandSender
+ );
+
+
+ manager.brigadierManager().setNativeNumberSuggestions(false);
+
+ TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager));
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java
new file mode 100644
index 000000000..53277b18c
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/MinecraftServerMixin.java
@@ -0,0 +1,32 @@
+package com.dfsek.terra.quilt.mixin.lifecycle;
+
+import com.mojang.datafixers.DataFixer;
+import net.minecraft.resource.ResourcePackManager;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.SaveLoader;
+import net.minecraft.server.WorldGenerationProgressListenerFactory;
+import net.minecraft.util.ApiServices;
+import net.minecraft.world.level.storage.LevelStorage;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.net.Proxy;
+
+import com.dfsek.terra.quilt.QuiltEntryPoint;
+
+
+@Mixin(MinecraftServer.class)
+public class MinecraftServerMixin {
+ @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" +
+ "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" +
+ "Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" +
+ "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V",
+ at = @At("RETURN"))
+ private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager,
+ SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices,
+ WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) {
+ QuiltEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this);
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java
new file mode 100644
index 000000000..6b863cca0
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/NoiseConfigMixin.java
@@ -0,0 +1,31 @@
+package com.dfsek.terra.quilt.mixin.lifecycle;
+
+import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
+import net.minecraft.util.registry.Registry;
+import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
+import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
+import net.minecraft.world.gen.noise.NoiseConfig;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.dfsek.terra.mod.util.SeedHack;
+
+
+/**
+ * Hack to map noise sampler to seeds
+ */
+@Mixin(NoiseConfig.class)
+public class NoiseConfigMixin {
+ @Shadow
+ @Final
+ private MultiNoiseSampler multiNoiseSampler;
+
+ @Inject(method = "(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL"))
+ private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry noiseRegistry, long seed, CallbackInfo ci) {
+ SeedHack.register(multiNoiseSampler, seed);
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java
new file mode 100644
index 000000000..55d649d44
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/RegistryMixin.java
@@ -0,0 +1,19 @@
+package com.dfsek.terra.quilt.mixin.lifecycle;
+
+
+import com.dfsek.terra.quilt.QuiltEntryPoint;
+import net.minecraft.util.registry.Registry;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+
+// Register Terra things to the builtin registries.
+@Mixin(Registry.class)
+public class RegistryMixin {
+ @Inject(method = "", at = @At("RETURN"))
+ private static void registerTerraGenerators(CallbackInfo ci) {
+ QuiltEntryPoint.register();
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java
new file mode 100644
index 000000000..6556ba806
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/client/MinecraftClientMixin.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of Terra.
+ *
+ * Terra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Terra is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Terra. If not, see .
+ */
+
+package com.dfsek.terra.quilt.mixin.lifecycle.client;
+
+import com.dfsek.terra.quilt.QuiltEntryPoint;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.RunArgs;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+
+@Mixin(MinecraftClient.class)
+public class MinecraftClientMixin {
+ @Inject(method = "", at = @At(value = "INVOKE",
+ target = "Lnet/minecraft/client/util/WindowProvider;createWindow" +
+ "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" +
+ "Lnet/minecraft/client/util/Window;",
+ // sorta arbitrary position, after mod init, before window opens
+ shift = At.Shift.BEFORE))
+ public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) {
+ QuiltEntryPoint.initialize();
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java
new file mode 100644
index 000000000..23f9f63d2
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * This file is part of Terra.
+ *
+ * Terra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Terra is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Terra. If not, see .
+ */
+
+/**
+ * Mixins that inject behavior into the client/server lifecycle.
+ */
+
+package com.dfsek.terra.quilt.mixin.lifecycle;
\ No newline at end of file
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java
new file mode 100644
index 000000000..577e2cfe2
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/mixin/lifecycle/server/ServerMainMixin.java
@@ -0,0 +1,39 @@
+/*
+ * This file is part of Terra.
+ *
+ * Terra is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Terra is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Terra. If not, see .
+ */
+
+package com.dfsek.terra.quilt.mixin.lifecycle.server;
+
+import com.dfsek.terra.quilt.QuiltEntryPoint;
+import net.minecraft.server.Main;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+
+@Mixin(Main.class)
+public class ServerMainMixin {
+ @Inject(method = "main([Ljava/lang/String;)V",
+ at = @At(value = "INVOKE",
+ target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" +
+ "[Lnet/minecraft/resource/ResourcePackProvider;)V")
+ // after registry manager creation
+ )
+ private static void injectConstructor(String[] args, CallbackInfo ci) {
+ QuiltEntryPoint.initialize();
+ }
+}
diff --git a/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java
new file mode 100644
index 000000000..e26d08938
--- /dev/null
+++ b/platforms/quilt/src/main/java/com/dfsek/terra/quilt/util/BiomeUtil.java
@@ -0,0 +1,71 @@
+package com.dfsek.terra.quilt.util;
+
+import com.dfsek.terra.quilt.QuiltEntryPoint;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.registry.BuiltinRegistries;
+import net.minecraft.util.registry.Registry;
+import net.minecraft.util.registry.RegistryKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+import com.dfsek.terra.api.config.ConfigPack;
+import com.dfsek.terra.api.world.biome.Biome;
+import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions;
+import com.dfsek.terra.mod.config.ProtoPlatformBiome;
+import com.dfsek.terra.mod.util.MinecraftUtil;
+
+
+public final class BiomeUtil {
+ private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class);
+
+ private BiomeUtil() {
+
+ }
+
+ public static void registerBiomes() {
+ logger.info("Registering biomes...");
+ QuiltEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes.
+ pack.getCheckedRegistry(Biome.class)
+ .forEach((id, biome) -> registerBiome(biome, pack, id));
+ });
+ MinecraftUtil.registerFlora(BuiltinRegistries.BIOME);
+ logger.info("Terra biomes registered.");
+ }
+
+ /**
+ * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate.
+ *
+ * @param biome The Terra BiomeBuilder.
+ * @param pack The ConfigPack this biome belongs to.
+ */
+ private static void registerBiome(Biome biome, ConfigPack pack,
+ com.dfsek.terra.api.registry.key.RegistryKey id) {
+ Registry registry = BuiltinRegistries.BIOME;
+ RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry);
+
+
+ if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) {
+ ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla);
+ } else {
+ net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla));
+
+ Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id));
+
+ if(registry.containsId(identifier)) {
+ ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier)
+ .orElseThrow()
+ .getKey()
+ .orElseThrow());
+ } else {
+ ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry,
+ MinecraftUtil.registerKey(identifier).getValue(),
+ minecraftBiome).getKey().orElseThrow());
+ }
+
+ MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier);
+ }
+ }
+
+}
diff --git a/platforms/quilt/src/main/resources/assets/terra/icon.png b/platforms/quilt/src/main/resources/assets/terra/icon.png
new file mode 100644
index 000000000..a8f458866
Binary files /dev/null and b/platforms/quilt/src/main/resources/assets/terra/icon.png differ
diff --git a/platforms/quilt/src/main/resources/assets/terra/lang/en_us.json b/platforms/quilt/src/main/resources/assets/terra/lang/en_us.json
new file mode 100644
index 000000000..116199214
--- /dev/null
+++ b/platforms/quilt/src/main/resources/assets/terra/lang/en_us.json
@@ -0,0 +1,4 @@
+{
+ "generator.terra": "Terra"
+}
+
diff --git a/platforms/quilt/src/main/resources/quilt.mod.json b/platforms/quilt/src/main/resources/quilt.mod.json
new file mode 100644
index 000000000..6dac98fb9
--- /dev/null
+++ b/platforms/quilt/src/main/resources/quilt.mod.json
@@ -0,0 +1,52 @@
+{
+ "schema_version": 1,
+ "quilt_loader": {
+ "group": "com.dfsek",
+ "id": "terra",
+ "version": "@VERSION@",
+ "metadata": {
+ "name": "Terra",
+ "description": "@DESCRIPTION@",
+ "authors": [
+ "dfsek"
+ ],
+ "contact": {
+ "homepage": "@WIKI@",
+ "sources": "@SOURCE@",
+ "issues": "@ISSUES@"
+ },
+ "license": "@LICENSE@",
+ "icon": "assets/terra/icon.png"
+ },
+ "environment": "*",
+ "intermediate_mappings": "net.fabricmc:intermediary",
+ "entrypoints": {
+ "init": [
+ "com.dfsek.terra.quilt.QuiltEntryPoint"
+ ]
+ },
+ "depends": [
+ {
+ "id": "quilt_loader",
+ "version": ">=0.17.0"
+ },
+ {
+ "id": "java",
+ "version": ">=17"
+ },
+ {
+ "id": "minecraft",
+ "version": "1.19.x"
+ },
+ {
+ "id": "quilted_fabric_api",
+ "versions": ">=2.0.0-"
+ }
+ ]
+ },
+ "mixin": [
+ "terra.quilt.mixins.json",
+ "terra.common.mixins.json"
+ ],
+ "accessWidener": "terra.accesswidener"
+}
\ No newline at end of file
diff --git a/platforms/quilt/src/main/resources/terra.quilt.mixins.json b/platforms/quilt/src/main/resources/terra.quilt.mixins.json
new file mode 100644
index 000000000..ca92e0bf1
--- /dev/null
+++ b/platforms/quilt/src/main/resources/terra.quilt.mixins.json
@@ -0,0 +1,20 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "package": "com.dfsek.terra.quilt.mixin",
+ "compatibilityLevel": "JAVA_17",
+ "mixins": [
+ "lifecycle.MinecraftServerMixin",
+ "lifecycle.NoiseConfigMixin",
+ "lifecycle.RegistryMixin"
+ ],
+ "client": [
+ "lifecycle.client.MinecraftClientMixin"
+ ],
+ "server": [
+ "lifecycle.server.ServerMainMixin"
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index a8a8b3644..7a1cdc8a0 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -28,11 +28,14 @@ pluginManagement {
maven("https://maven.fabricmc.net") {
name = "Fabric Maven"
}
- maven ( "https://maven.architectury.dev/" ) {
+ maven("https://maven.architectury.dev/") {
name = "Architectury Maven"
}
- maven ( "https://files.minecraftforge.net/maven/" ) {
+ maven("https://files.minecraftforge.net/maven/") {
name = "Forge Maven"
}
+ maven("https://maven.quiltmc.org/repository/release/") {
+ name = "Quilt"
+ }
}
}