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" + } } }