Merge pull request #328 from PolyhedralDev/dev/architectury

Use Architectury to share mixins and mod code not dependent on mod loader
This commit is contained in:
dfsek
2022-06-25 13:34:10 -07:00
committed by GitHub
86 changed files with 1290 additions and 904 deletions

View File

@@ -34,6 +34,7 @@ fun Project.configureDependencies() {
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/" )
}
dependencies {

View File

@@ -28,6 +28,22 @@ object Versions {
const val minotaur = "1.1.0"
}
object Mod {
const val minecraft = "1.19"
const val yarn = "$minecraft+build.1"
const val fabricLoader = "0.14.2"
const val architecuryLoom = "0.12.0-SNAPSHOT"
const val architectutyPlugin = "3.4-SNAPSHOT"
}
object Forge {
const val minecraft = "1.19"
const val forge = "$minecraft-41.0.38"
const val yarn = "$minecraft+build.1"
const val architecuryLoom = "0.12.0-SNAPSHOT"
}
object Bukkit {
const val paper = "1.18.2-R0.1-SNAPSHOT"
const val paperLib = "1.0.5"

View File

@@ -1,6 +1,7 @@
dependencies {
api("ca.solo-studios", "strata", Versions.Libraries.strata)
api("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud)
api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic)

View File

@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -145,6 +146,11 @@ public final class Pair<L, R> {
}
}
public Pair<L, R> apply(BiConsumer<L, R> consumer) {
consumer.accept(this.left, this.right);
return this;
}
@Override
public String toString() {
return String.format("{%s,%s}", left, right);

View File

@@ -2,6 +2,8 @@ dependencies {
api(project(":common:api"))
api(project(":common:implementation:bootstrap-addon-loader"))
testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
implementation("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
implementation("org.apache.commons", "commons-text", Versions.Libraries.Internal.apacheText)

View File

@@ -111,8 +111,12 @@ public abstract class AbstractPlatform implements Platform {
logger.info("Loading config.yml");
File configFile = new File(getDataFolder(), "config.yml");
if(!configFile.exists()) {
logger.info("Writing new config.yml...");
FileUtils.copyInputStreamToFile(stream, configFile);
logger.info("Dumping config.yml...");
if(stream == null) {
logger.warn("Could not find config.yml in JAR");
} else {
FileUtils.copyInputStreamToFile(stream, configFile);
}
}
} catch(IOException e) {
logger.error("Error loading config.yml resource from jar", e);

View File

@@ -1,20 +1,9 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import java.net.URL
import java.nio.channels.Channels
import java.nio.file.Files
import java.nio.file.StandardCopyOption
plugins {
id("xyz.jpenilla.run-paper") version "1.0.6"
}
val testDir = "target/server"
val testMem = "3G"
val paperBuild = 350
val paperURL = "https://papermc.io/api/v2/projects/paper/versions/%version%/builds/$paperBuild/downloads/paper-%version%-$paperBuild.jar"
val purpurURL = "https://api.purpurmc.org/v2/purpur/%version%/latest/download"
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
@@ -26,174 +15,27 @@ dependencies {
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
}
val throttleCoreCount = 0
val jvmFlags = mutableListOf(
"-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", /*"-javaagent:paperclip.jar"*/
)
if(throttleCoreCount > 0) {
jvmFlags.add("-XX:ActiveProcessorCount=$throttleCoreCount")
}
fun downloadPaperclip(url: String, dir: String) {
val clip = URL(url.replace("%version%", Versions.Bukkit.minecraft))
val clipReadableByteChannel = Channels.newChannel(clip.openStream())
val clipFile = file("$testDir/$dir/paperclip.jar")
val clipOutputStream = clipFile.outputStream()
val clipFileChannel = clipOutputStream.channel
clipFileChannel.transferFrom(clipReadableByteChannel, 0, Long.MAX_VALUE)
}
fun copyTerra(dir: String) {
file("$testDir/$dir").walk().forEach {
if (it.name.startsWith("Terra-bukkit") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s)
}
copy {
from("$buildDir/libs/Terra-bukkit-$version-shaded.jar")
into("$testDir/$dir/plugins/")
}
}
fun installServer(dir: String) {
// clean
file("$testDir/$dir").deleteRecursively()
file("$testDir/$dir/plugins").mkdirs()
// Cloning test setup.
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
// Copying plugins
Files.move(
file("WorldGenTestServer/plugins").toPath(),
file("$testDir/$dir/plugins").toPath(),
StandardCopyOption.REPLACE_EXISTING
)
// Copying config
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
file("$testDir/$dir/server.properties").writeText(serverText)
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
file("$testDir/$dir/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
println("By proceeding, you are agreeing to the Minecraft EULA: https://account.mojang.com/documents/minecraft_eula")
file("$testDir/$dir/eula.txt").writeText("eula=true")
// clean up
file("WorldGenTestServer").deleteRecursively()
}
fun deleteFolder(folder: File) {
if (folder.exists()) folder.deleteRecursively()
}
fun deleteFile(file: File) {
if (file.exists()) file.delete()
}
tasks.create("cleanWorlds") {
group = "bukkit"
doFirst {
deleteFolder(file("$testDir/paper/world"))
deleteFolder(file("$testDir/paper/world_nether"))
deleteFolder(file("$testDir/paper/world_the_end"))
deleteFolder(file("$testDir/purpur/world"))
deleteFolder(file("$testDir/purpur/world_nether"))
deleteFolder(file("$testDir/purpur/world_the_end"))
}
}
tasks.create("updatePaper") {
group = "bukkit"
doFirst {
deleteFile(file("$testDir/paper/paperclip.jar"))
downloadPaperclip(paperURL, "paper")
}
}
tasks.create("updatePurpur") {
group = "bukkit"
doFirst {
deleteFile(file("$testDir/paper/paperclip.jar"))
downloadPaperclip(purpurURL, "purpur")
}
}
tasks.create("installPaper") {
group = "bukkit"
dependsOn("shadowJar")
doFirst {
installServer("paper")
// Downloading latest paper jar.
downloadPaperclip(paperURL, "paper")
}
}
tasks.create("installPurpur") {
group = "bukkit"
dependsOn("shadowJar")
doFirst {
installServer("purpur")
// Downloading latest paper jar.
downloadPaperclip(purpurURL, "purpur")
}
}
task<JavaExec>(name = "runPaper") {
group = "bukkit"
standardInput = System.`in`
dependsOn("shadowJar")
// Copy Terra into dir
doFirst {
copyTerra("paper")
tasks {
shadowJar {
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("com.google.common", "com.dfsek.terra.lib.google.common")
relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j")
exclude("org/slf4j/**")
exclude("org/checkerframework/**")
exclude("org/jetbrains/annotations/**")
exclude("org/intellij/**")
exclude("com/google/errorprone/**")
exclude("com/google/j2objc/**")
exclude("javax/**")
}
mainClass.set("io.papermc.paperclip.Paperclip")
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
args = listOf("nogui")
workingDir = file("$testDir/paper")
classpath = files("$testDir/paper/paperclip.jar")
}
task<JavaExec>(name = "runPurpur") {
group = "bukkit"
standardInput = System.`in`
dependsOn("shadowJar")
// Copy Terra into dir
doFirst {
copyTerra("purpur")
runServer {
minecraftVersion("1.19")
dependsOn(shadowJar)
pluginJars(shadowJar.get().archiveFile)
}
mainClass.set("io.papermc.paperclip.Paperclip")
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
workingDir = file("$testDir/purpur")
classpath = files("$testDir/purpur/paperclip.jar")
}
tasks.named<ShadowJar>("shadowJar") {
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("com.google.common", "com.dfsek.terra.lib.google.common")
relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j")
exclude("org/slf4j/**")
exclude("org/checkerframework/**")
exclude("org/jetbrains/annotations/**")
exclude("org/intellij/**")
exclude("com/google/errorprone/**")
exclude("com/google/j2objc/**")
exclude("javax/**")
}
addonDir(project.file("./target/server/paper/plugins/Terra/addons"), tasks.named("runPaper").get())
addonDir(project.file("./target/server/purpur/plugins/Terra/addons"), tasks.named("runPurpur").get())
addonDir(project.file("./target/server/paper/plugins/Terra/addons"), tasks.named("runServer").get())

View File

@@ -1,13 +1,15 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.modrinth.minotaur.TaskModrinthUpload
import net.fabricmc.loom.task.RemapJarTask
plugins {
id("fabric-loom") version Versions.Fabric.loom
id("com.modrinth.minotaur") version Versions.Fabric.minotaur
id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower
}
configurations {
val common by creating
compileClasspath.get().extendsFrom(common)
runtimeClasspath.get().extendsFrom(common)
}
dependencies {
shadedApi(project(":common:implementation:base"))
@@ -15,6 +17,9 @@ dependencies {
"annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}")
"annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}")
"common"(project(path = ":platforms:mixin-common", configuration = "namedElements")) { isTransitive = false }
shaded(project(path = ":platforms:mixin-common", configuration = "transformProductionFabric")) { isTransitive = false }
minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}")
mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2")
@@ -33,49 +38,22 @@ dependencies {
loom {
accessWidenerPath.set(file("src/main/resources/terra.accesswidener"))
mixin {
defaultRefmapName.set("terra-refmap.json")
defaultRefmapName.set("terra-fabric-refmap.json")
}
}
addonDir(project.file("./run/config/Terra/addons"), tasks.named("runClient").get())
addonDir(project.file("./run/config/Terra/addons"), tasks.named("runServer").get())
tasks.withType<JavaCompile>().configureEach {
options.release.set(17)
}
tasks.getByName<ShadowJar>("shadowJar") {
exclude("org/slf4j/**")
tasks {
compileJava {
options.release.set(17)
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)
archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar")
}
}
val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
dependsOn("installAddons")
group = "fabric"
val shadowJar = tasks.getByName<ShadowJar>("shadowJar")
dependsOn(shadowJar)
inputFile.set(shadowJar.archiveFile)
archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar"))
addNestedDependencies.set(true)
}
tasks.named("assemble").configure {
dependsOn("remapShadedJar")
}
tasks.withType<Jar> {
finalizedBy(remapped)
}
tasks.register<TaskModrinthUpload>("publishModrinth") {
dependsOn("remapShadedJar")
group = "fabric"
token = System.getenv("MODRINTH_SECRET")
projectId = "FIlZB9L0"
versionNumber = "${project.version}-fabric"
uploadFile = remapped.get().archiveFile.get().asFile
releaseType = "beta"
addGameVersion(Versions.Fabric.minecraft)
addLoader("fabric")
}

View File

@@ -24,15 +24,19 @@ import cloud.commandframework.fabric.FabricServerCommandManager;
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.fabric.util.BiomeUtil;
import com.dfsek.terra.mod.CommonPlatform;
import net.fabricmc.api.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 net.minecraft.world.gen.WorldPresets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dfsek.terra.fabric.data.Codecs;
import com.dfsek.terra.mod.data.Codecs;
public class FabricEntryPoint implements ModInitializer {
@@ -46,10 +50,17 @@ public class FabricEntryPoint implements ModInitializer {
}
public static void register() { // register the things
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER);
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() {
logger.info("Initializing Terra Fabric mod...");

View File

@@ -20,17 +20,23 @@ package com.dfsek.terra.fabric;
import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.fabric.util.BiomeUtil;
import com.dfsek.terra.mod.CommonPlatform;
import com.dfsek.terra.mod.ModPlatform;
import com.dfsek.terra.mod.generation.TerraBiomeSource;
import com.dfsek.terra.mod.util.PresetUtil;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.MinecraftVersion;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.biome.Biome.Precipitation;
import net.minecraft.world.biome.BiomeEffects.GrassColorModifier;
import net.minecraft.world.dimension.DimensionOptions;
import net.minecraft.world.gen.WorldPreset;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,28 +45,28 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiConsumer;
import com.dfsek.terra.AbstractPlatform;
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.api.world.biome.PlatformBiome;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.util.ProtoPlatformBiome;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import com.dfsek.terra.mod.handle.MinecraftItemHandle;
import com.dfsek.terra.mod.handle.MinecraftWorldHandle;
public class PlatformImpl extends AbstractPlatform {
public class PlatformImpl extends ModPlatform {
private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class);
private final ItemHandle itemHandle = new FabricItemHandle();
private final WorldHandle worldHandle = new FabricWorldHandle();
private final ItemHandle itemHandle = new MinecraftItemHandle();
private final WorldHandle worldHandle = new MinecraftWorldHandle();
private final Lazy<File> dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"));
private MinecraftServer server;
public PlatformImpl() {
CommonPlatform.initialize(this);
load();
}
@@ -68,6 +74,7 @@ public class PlatformImpl extends AbstractPlatform {
this.server = server;
}
@Override
public MinecraftServer getServer() {
return server;
}
@@ -86,7 +93,7 @@ public class PlatformImpl extends AbstractPlatform {
}).join();
BiomeUtil.registerBiomes();
server.getWorlds().forEach(world -> {
if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) {
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);
@@ -101,7 +108,7 @@ public class PlatformImpl extends AbstractPlatform {
protected Iterable<BaseAddon> platformAddon() {
List<BaseAddon> addons = new ArrayList<>();
addons.add(new FabricAddon(this));
super.platformAddon().forEach(addons::add);
String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget();
try {
@@ -150,27 +157,4 @@ public class PlatformImpl extends AbstractPlatform {
public @NotNull ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
.registerLoader(Identifier.class, (type, o, loader, depthTracker) -> {
Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null)
throw new LoadException("Invalid identifier: " + o, depthTracker);
return identifier;
})
.registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT)));
}
private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException {
Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure.
return new ProtoPlatformBiome(identifier);
}
}

View File

@@ -1,15 +0,0 @@
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.chunk.Chunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(ChunkRegion.class)
public interface ChunkRegionAccessor {
@Accessor("chunks")
List<Chunk> getChunks();
}

View File

@@ -1,10 +1,9 @@
package com.dfsek.terra.fabric.mixin.lifecycle;
import com.dfsek.terra.fabric.util.SeedHack;
import com.dfsek.terra.mod.util.SeedHack;
import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.source.util.MultiNoiseUtil;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import net.minecraft.world.gen.noise.NoiseConfig;

View File

@@ -17,8 +17,6 @@
package com.dfsek.terra.fabric.mixin.lifecycle.client;
import com.dfsek.terra.fabric.util.LifecycleUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.RunArgs;
import org.spongepowered.asm.mixin.Mixin;
@@ -26,9 +24,7 @@ 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.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.util.BiomeUtil;
@Mixin(MinecraftClient.class)
@@ -40,6 +36,6 @@ public class MinecraftClientMixin {
// sorta arbitrary position, after mod init, before window opens
shift = At.Shift.BEFORE))
public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) {
LifecycleUtil.initialize();
FabricEntryPoint.initialize();
}
}

View File

@@ -17,16 +17,12 @@
package com.dfsek.terra.fabric.mixin.lifecycle.server;
import com.dfsek.terra.fabric.util.BiomeUtil;
import com.dfsek.terra.fabric.util.LifecycleUtil;
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;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.fabric.FabricEntryPoint;
@@ -39,6 +35,6 @@ public class ServerMainMixin {
// after registry manager creation
)
private static void injectConstructor(String[] args, CallbackInfo ci) {
LifecycleUtil.initialize();
FabricEntryPoint.initialize();
}
}

View File

@@ -3,18 +3,15 @@ package com.dfsek.terra.fabric.util;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.VanillaBiomeProperties;
import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.mod.config.ProtoPlatformBiome;
import com.dfsek.terra.mod.util.MinecraftUtil;
import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.biome.Biome.Builder;
import net.minecraft.world.biome.BiomeEffects;
import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,25 +21,17 @@ import java.util.*;
public final class BiomeUtil {
private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class);
private static final Map<Identifier, List<Identifier>>
TERRA_BIOME_MAP = new HashMap<>();
private BiomeUtil() {
}
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
return pack.getID()
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
}
public static void registerBiomes() {
logger.info("Registering biomes...");
FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes.
pack.getCheckedRegistry(Biome.class)
.forEach((id, biome) -> registerBiome(biome, pack, id));
});
registerFlora(BuiltinRegistries.BIOME);
MinecraftUtil.registerFlora(BuiltinRegistries.BIOME);
logger.info("Terra biomes registered.");
}
@@ -61,108 +50,23 @@ public final class BiomeUtil {
if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) {
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla);
} else {
net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, registry.get(vanilla));
net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, registry.get(vanilla));
Identifier identifier = new Identifier("terra", createBiomeID(pack, id));
Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id));
if(registry.containsId(identifier)) {
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(FabricUtil.getEntry(registry, identifier)
.orElseThrow()
.getKey()
.orElseThrow());
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier)
.orElseThrow()
.getKey()
.orElseThrow());
} else {
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry,
registerKey(identifier).getValue(),
MinecraftUtil.registerKey(identifier).getValue(),
minecraftBiome).getKey().orElseThrow());
}
TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier);
MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier);
}
}
public static void registerFlora(Registry<net.minecraft.world.biome.Biome> biomes) {
logger.info("Injecting flora into Terra biomes...");
TERRA_BIOME_MAP
.forEach((vb, terraBiomes) ->
biomes.getOrEmpty(vb)
.ifPresentOrElse(vanilla -> terraBiomes
.forEach(tb -> biomes.getOrEmpty(tb)
.ifPresentOrElse(
terra -> {
List<ConfiguredFeature<?, ?>> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures());
logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures);
((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures);
},
() -> logger.error(
"No such biome: {}",
tb))),
() -> logger.error("No vanilla biome: {}", vb)));
}
public static Map<Identifier, List<Identifier>> getTerraBiomeMap() {
return Map.copyOf(TERRA_BIOME_MAP);
}
private static RegistryKey<net.minecraft.world.biome.Biome> registerKey(Identifier identifier) {
return RegistryKey.of(Registry.BIOME_KEY, identifier);
}
public static net.minecraft.world.biome.Biome createBiome(Biome biome, net.minecraft.world.biome.Biome vanilla) {
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
BiomeEffects.Builder effects = new BiomeEffects.Builder();
net.minecraft.world.biome.Biome.Builder builder = new Builder();
if(biome.getContext().has(VanillaBiomeProperties.class)) {
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()))
.grassColorModifier(
Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier()));
if(vanillaBiomeProperties.getGrassColor() == null) {
vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor);
} else {
effects.grassColor(vanillaBiomeProperties.getGrassColor());
}
if(vanillaBiomeProperties.getFoliageColor() == null) {
vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor);
} else {
effects.foliageColor(vanillaBiomeProperties.getFoliageColor());
}
builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation()));
} else {
effects.waterColor(vanilla.getWaterColor())
.waterFogColor(vanilla.getWaterFogColor())
.fogColor(vanilla.getFogColor())
.skyColor(vanilla.getSkyColor());
vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor);
vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor);
builder.precipitation(vanilla.getPrecipitation());
}
vanilla.getLoopSound().ifPresent(effects::loopSound);
vanilla.getAdditionsSound().ifPresent(effects::additionsSound);
vanilla.getMoodSound().ifPresent(effects::moodSound);
vanilla.getMusic().ifPresent(effects::music);
vanilla.getParticleConfig().ifPresent(effects::particleConfig);
return builder
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(effects.build())
.spawnSettings(vanilla.getSpawnSettings())
.generationSettings(generationSettings.build())
.build();
}
}

View File

@@ -1,185 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.util;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.WallShape;
import net.minecraft.block.enums.WireConnection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.HeightLimitView;
import com.dfsek.terra.api.block.state.properties.enums.Axis;
import com.dfsek.terra.api.block.state.properties.enums.Half;
import com.dfsek.terra.api.block.state.properties.enums.RailShape;
import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection;
import com.dfsek.terra.api.block.state.properties.enums.WallHeight;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.info.WorldProperties;
public final class FabricAdapter {
public static BlockPos adapt(Vector3 v) {
return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ());
}
public static Vector3 adapt(BlockPos pos) {
return Vector3.of(pos.getX(), pos.getY(), pos.getZ());
}
public static Direction adapt(com.dfsek.terra.api.block.state.properties.enums.Direction direction) {
return switch(direction) {
case SOUTH -> Direction.SOUTH;
case NORTH -> Direction.NORTH;
case WEST -> Direction.WEST;
case EAST -> Direction.EAST;
case UP -> Direction.UP;
case DOWN -> Direction.DOWN;
};
}
public static WorldProperties adapt(HeightLimitView height, long seed) {
return new WorldProperties() {
@Override
public long getSeed() {
return seed;
}
@Override
public int getMaxHeight() {
return height.getTopY();
}
@Override
public int getMinHeight() {
return height.getBottomY();
}
@Override
public Object getHandle() {
return height;
}
};
}
public static com.dfsek.terra.api.block.state.properties.enums.Direction adapt(Direction direction) {
return switch(direction) {
case SOUTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.SOUTH;
case NORTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.NORTH;
case WEST -> com.dfsek.terra.api.block.state.properties.enums.Direction.WEST;
case EAST -> com.dfsek.terra.api.block.state.properties.enums.Direction.EAST;
case UP -> com.dfsek.terra.api.block.state.properties.enums.Direction.UP;
case DOWN -> com.dfsek.terra.api.block.state.properties.enums.Direction.DOWN;
};
}
public static WallHeight adapt(WallShape shape) {
return switch(shape) {
case LOW -> WallHeight.LOW;
case NONE -> WallHeight.NONE;
case TALL -> WallHeight.TALL;
};
}
public static WallShape adapt(WallHeight shape) {
return switch(shape) {
case LOW -> WallShape.LOW;
case NONE -> WallShape.NONE;
case TALL -> WallShape.TALL;
};
}
public static RedstoneConnection adapt(WireConnection connection) {
return switch(connection) {
case NONE -> RedstoneConnection.NONE;
case UP -> RedstoneConnection.UP;
case SIDE -> RedstoneConnection.SIDE;
};
}
public static WireConnection adapt(RedstoneConnection connection) {
return switch(connection) {
case NONE -> WireConnection.NONE;
case UP -> WireConnection.UP;
case SIDE -> WireConnection.SIDE;
};
}
public static Half adapt(BlockHalf half) {
return switch(half) {
case BOTTOM -> Half.BOTTOM;
case TOP -> Half.TOP;
};
}
public static BlockHalf adapt(Half half) {
return switch(half) {
case TOP -> BlockHalf.TOP;
case BOTTOM -> BlockHalf.BOTTOM;
default -> throw new IllegalStateException();
};
}
public static RailShape adapt(net.minecraft.block.enums.RailShape railShape) {
return switch(railShape) {
case EAST_WEST -> RailShape.EAST_WEST;
case NORTH_EAST -> RailShape.NORTH_EAST;
case NORTH_WEST -> RailShape.NORTH_WEST;
case SOUTH_EAST -> RailShape.SOUTH_EAST;
case SOUTH_WEST -> RailShape.SOUTH_WEST;
case NORTH_SOUTH -> RailShape.NORTH_SOUTH;
case ASCENDING_EAST -> RailShape.ASCENDING_EAST;
case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH;
case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH;
case ASCENDING_WEST -> RailShape.ASCENDING_WEST;
};
}
public static net.minecraft.block.enums.RailShape adapt(RailShape railShape) {
return switch(railShape) {
case EAST_WEST -> net.minecraft.block.enums.RailShape.EAST_WEST;
case NORTH_EAST -> net.minecraft.block.enums.RailShape.NORTH_EAST;
case NORTH_WEST -> net.minecraft.block.enums.RailShape.NORTH_WEST;
case SOUTH_EAST -> net.minecraft.block.enums.RailShape.SOUTH_EAST;
case SOUTH_WEST -> net.minecraft.block.enums.RailShape.SOUTH_WEST;
case NORTH_SOUTH -> net.minecraft.block.enums.RailShape.NORTH_SOUTH;
case ASCENDING_EAST -> net.minecraft.block.enums.RailShape.ASCENDING_EAST;
case ASCENDING_NORTH -> net.minecraft.block.enums.RailShape.ASCENDING_NORTH;
case ASCENDING_SOUTH -> net.minecraft.block.enums.RailShape.ASCENDING_SOUTH;
case ASCENDING_WEST -> net.minecraft.block.enums.RailShape.ASCENDING_WEST;
};
}
public static Axis adapt(Direction.Axis axis) {
return switch(axis) {
case X -> Axis.X;
case Y -> Axis.Y;
case Z -> Axis.Z;
};
}
public static Direction.Axis adapt(Axis axis) {
return switch(axis) {
case Z -> Direction.Axis.Z;
case Y -> Direction.Axis.Y;
case X -> Direction.Axis.X;
};
}
}

View File

@@ -1,61 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.util;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.world.WorldAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.entity.Container;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.Sign;
public final class FabricUtil {
private FabricUtil() {
}
public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) {
net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos);
if(entity instanceof SignBlockEntity) {
return (Sign) entity;
} else if(entity instanceof MobSpawnerBlockEntity) {
return (MobSpawner) entity;
} else if(entity instanceof LootableContainerBlockEntity) {
return (Container) entity;
}
return null;
}
public static <T> Optional<RegistryEntry<T>> getEntry(Registry<T> registry, Identifier identifier) {
return registry.getOrEmpty(identifier)
.flatMap(registry::getKey)
.map(registry::getOrCreateEntry);
}
}

View File

@@ -21,7 +21,7 @@
]
},
"mixins": [
"terra.mixins.json"
"terra.fabric.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.2",

View File

@@ -0,0 +1,21 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.dfsek.terra.fabric.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"lifecycle.MinecraftServerMixin",
"lifecycle.NoiseConfigMixin",
"lifecycle.RegistryMixin"
],
"client": [
"lifecycle.client.MinecraftClientMixin"
],
"server": [
"lifecycle.server.ServerMainMixin"
],
"injectors": {
"defaultRequire": 1
},
"refmap": "terra-fabric-refmap.json"
}

View File

@@ -1,53 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.dfsek.terra.fabric.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"access.ChunkRegionAccessor",
"access.MobSpawnerLogicAccessor",
"access.StateAccessor",
"access.StructureAccessorAccessor",
"fix.BeeMoveGoalsUnsynchronizedRandomAccessFix",
"fix.NetherFossilOptimization",
"implementations.compat.GenerationSettingsFloraFeaturesMixin",
"implementations.terra.BiomeMixin",
"implementations.terra.HandleImplementationMixin",
"implementations.terra.block.BlockMixin",
"implementations.terra.block.entity.BlockEntityMixin",
"implementations.terra.block.entity.LootableContainerBlockEntityMixin",
"implementations.terra.block.entity.MobSpawnerBlockEntityMixin",
"implementations.terra.block.entity.SignBlockEntityMixin",
"implementations.terra.block.state.BlockStateMixin",
"implementations.terra.block.state.PropertyMixin",
"implementations.terra.chunk.ChunkRegionMixin",
"implementations.terra.chunk.WorldChunkMixin",
"implementations.terra.chunk.data.ProtoChunkMixin",
"implementations.terra.entity.EntityMixin",
"implementations.terra.entity.EntityTypeMixin",
"implementations.terra.entity.PlayerEntityMixin",
"implementations.terra.entity.ServerCommandSourceMixin",
"implementations.terra.inventory.LockableContainerBlockEntityMixin",
"implementations.terra.inventory.item.ItemMixin",
"implementations.terra.inventory.item.ItemStackMixin",
"implementations.terra.inventory.meta.EnchantmentMixin",
"implementations.terra.inventory.meta.ItemStackDamageableMixin",
"implementations.terra.inventory.meta.ItemStackMetaMixin",
"implementations.terra.world.ChunkRegionMixin",
"implementations.terra.world.ServerWorldMixin",
"lifecycle.DataPackContentsMixin",
"lifecycle.MinecraftServerMixin",
"lifecycle.NoiseConfigMixin",
"lifecycle.RegistryMixin"
],
"client": [
"lifecycle.client.MinecraftClientMixin"
],
"server": [
"lifecycle.server.ServerMainMixin"
],
"injectors": {
"defaultRequire": 1
},
"refmap": "terra-refmap.json"
}

View File

@@ -0,0 +1,67 @@
plugins {
id("dev.architectury.loom") version Versions.Forge.architecuryLoom
id("architectury-plugin") version Versions.Mod.architectutyPlugin
id("io.github.juuxel.loom-quiltflower") version Versions.Fabric.loomQuiltflower
}
architectury {
platformSetupLoomIde()
forge()
}
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 = "transformProductionForge")) { isTransitive = false }
"developmentForge"(project(":platforms:mixin-common", configuration = "namedElements")) {
isTransitive = false
}
forge(group = "net.minecraftforge", name = "forge", version = Versions.Forge.forge)
minecraft("com.mojang:minecraft:${Versions.Forge.minecraft}")
mappings("net.fabricmc:yarn:${Versions.Forge.yarn}:v2")
}
loom {
mixin {
defaultRefmapName.set("terra-forge-refmap.json")
}
forge {
mixinConfig("terra.common.mixins.json")
mixinConfig("terra.forge.mixins.json")
}
}
tasks {
jar {
manifest {
attributes(
mapOf(
"Implementation-Title" to rootProject.name,
"Implementation-Version" to project.version,
)
)
}
}
shadowJar {
exclude("fabric.mod.json")
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)
archiveFileName.set("${rootProject.name.capitalize()}-${project.version}.jar")
}
}

View File

@@ -0,0 +1 @@
loom.platform=forge

View File

@@ -0,0 +1,108 @@
package com.dfsek.terra.forge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.JarFile;
import java.util.stream.Stream;
/**
* Forge is really wacky and screws with class resolution in the addon loader. Loading every single Terra class *manually* on startup
* fixes it. If you know of a better way to fix this, PLEASE let us know.
*/
public final class AwfulForgeHacks {
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulForgeHacks.class);
/**
* Forge tampers with code source to make the *normal* way of getting the current JAR file useless, so this awful hack is
* needed.
*
* <code>
* Class.class.getProtectionDomain()
* .getCodeSource()
* .getLocation()
* .toURI()
* .getPath()
* </code>
*/
public static JarFile getTerraJar() throws IOException {
LOGGER.info("Scanning for Terra JAR...");
return Files.walk(Path.of("./", "mods"), 1, FileVisitOption.FOLLOW_LINKS)
.filter(it -> it.getFileName().toString().endsWith(".jar"))
.peek(path -> LOGGER.info("Found mod: {}", path))
.map(Path::toFile)
.flatMap(path -> {
try {
return Stream.of(new JarFile(path));
} catch(IOException e) {
LOGGER.error("Malformed mod JAR: {}: {}", path, e);
return Stream.of();
}
})
.filter(jar -> jar
.stream()
.anyMatch(entry -> entry
.getName()
.equals(ForgeEntryPoint.class.getName().replace('.', '/') + ".class")))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Could not find Terra JAR"));
}
public static void loadAllTerraClasses() {
try(JarFile jar = getTerraJar()) {
jar.stream()
.forEach(jarEntry -> {
if(jarEntry.getName().startsWith("com/dfsek/terra/forge/mixin")
|| jarEntry.getName().startsWith("com/dfsek/terra/mod/mixin")) {
return;
}
if(jarEntry.getName().endsWith(".class")) {
String name = jarEntry.getName().replace('/', '.');
name = name.substring(0, name.length() - 6);
try {
Class.forName(name);
} catch(ClassNotFoundException | NoClassDefFoundError e) {
LOGGER.warn("Failed to load class {}: {}", name, e);
}
}
});
} catch(IOException e) {
throw new IllegalStateException("Could not load all Terra classes", e);
}
}
public enum RegistryStep {
BLOCK,
BIOME,
WORLD_TYPE,
DONE;
}
public static class RegistrySanityCheck {
private final AtomicReference<RegistryStep> step = new AtomicReference<>(RegistryStep.BLOCK);
public <T> void progress(RegistryStep expected, Runnable action) {
step.getAndUpdate(s -> {
if(s != expected) {
LOGGER.error("Registry sanity check failed, expected to find {}, found {}", expected, step);
}
action.run();
RegistryStep[] registrySteps = RegistryStep.values();
if(s.ordinal() < registrySteps.length - 1) {
return registrySteps[s.ordinal() + 1];
}
return s;
});
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.forge;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.forge.util.BiomeUtil;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries.Keys;
import net.minecraftforge.registries.RegisterEvent;
import net.minecraftforge.registries.RegisterEvent.RegisterHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dfsek.terra.forge.AwfulForgeHacks.RegistrySanityCheck;
import com.dfsek.terra.forge.AwfulForgeHacks.RegistryStep;
import com.dfsek.terra.mod.data.Codecs;
@Mod("terra")
@EventBusSubscriber(bus = Bus.MOD)
public class ForgeEntryPoint {
private final RegistrySanityCheck sanityCheck = new RegistrySanityCheck();
static {
AwfulForgeHacks.loadAllTerraClasses();
TERRA_PLUGIN = new PlatformImpl();
}
public static final String MODID = "terra";
private static final Logger logger = LoggerFactory.getLogger(ForgeEntryPoint.class);
private static final PlatformImpl TERRA_PLUGIN;
public static PlatformImpl getPlatform() {
return TERRA_PLUGIN;
}
public ForgeEntryPoint() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.register(this);
}
public static void initialize(RegisterHelper<Biome> helper) {
getPlatform().getEventManager().callEvent(
new PlatformInitializationEvent());
BiomeUtil.registerBiomes(helper);
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void registerBiomes(RegisterEvent event) {
event.register(Keys.BLOCKS, helper -> sanityCheck.progress(RegistryStep.BLOCK, () -> logger.debug("Block registration detected.")));
event.register(Keys.BIOMES, helper -> sanityCheck.progress(RegistryStep.BIOME, () -> initialize(helper)));
event.register(Registry.WORLD_PRESET_KEY, helper -> sanityCheck.progress(RegistryStep.WORLD_TYPE, () -> TERRA_PLUGIN.registerWorldTypes(helper::register)));
event.register(Registry.CHUNK_GENERATOR_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER));
event.register(Registry.BIOME_SOURCE_KEY, helper -> helper.register(new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE));
}
}

View File

@@ -0,0 +1,141 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.forge;
import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version;
import com.dfsek.terra.mod.util.PresetUtil;
import net.minecraft.MinecraftVersion;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.world.gen.WorldPreset;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
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;
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<File> dataFolder = Lazy.lazy(() -> new File("./config/Terra"));
public PlatformImpl() {
CommonPlatform.initialize(this);
load();
}
@Override
public MinecraftServer getServer() {
return ServerLifecycleHooks.getCurrentServer();
}
@Override
public boolean reload() {
getTerraConfig().load(this);
getRawConfigRegistry().clear();
boolean succeed = getRawConfigRegistry().loadAll(this);
MinecraftServer server = getServer();
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<BaseAddon> platformAddon() {
List<BaseAddon> 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);
}
}
FMLLoader.getLoadingModList().getMods().forEach(mod -> {
String id = mod.getModId();
if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return;
Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(), mod.getVersion().getIncrementalVersion());
addons.add(new EphemeralAddon(version, "forge:" + id));
});
return addons;
}
@Override
public @NotNull String platformName() {
return "Forge";
}
@Override
public @NotNull WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public @NotNull File getDataFolder() {
return dataFolder.value();
}
@Override
public @NotNull ItemHandle getItemHandle() {
return itemHandle;
}
}

View File

@@ -0,0 +1,36 @@
package com.dfsek.terra.forge.mixin.lifecycle;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube;
import net.minecraft.world.gen.densityfunction.DensityFunction;
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.Redirect;
import java.util.List;
import com.dfsek.terra.mod.util.SeedHack;
/**
* Hack to map noise sampler to seeds
*/
@Mixin(NoiseConfig.class)
public class NoiseConfigMixin {
@Shadow
@Final
private long legacyWorldSeed;
@Redirect(method = "<init>(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At(value = "NEW", target = "(Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Lnet/minecraft/world/gen/densityfunction/DensityFunction;Ljava/util/List;)Lnet/minecraft/world/biome/source/util/MultiNoiseUtil$MultiNoiseSampler;"))
private MultiNoiseSampler t(DensityFunction densityFunction, DensityFunction densityFunction2, DensityFunction densityFunction3,
DensityFunction densityFunction4, DensityFunction densityFunction5, DensityFunction densityFunction6,
List<NoiseHypercube> list) {
MultiNoiseSampler sampler = new MultiNoiseSampler(densityFunction, densityFunction2, densityFunction3, densityFunction4,
densityFunction5, densityFunction6, list);
SeedHack.register(sampler, legacyWorldSeed);
return sampler;
}
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
/**
* Mixins that inject behavior into the client/server lifecycle.
*/
package com.dfsek.terra.forge.mixin.lifecycle;

View File

@@ -0,0 +1,68 @@
package com.dfsek.terra.forge.util;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.RegistryKey;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent.RegisterHelper;
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.forge.ForgeEntryPoint;
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(RegisterHelper<net.minecraft.world.biome.Biome> helper) {
logger.info("Registering biomes...");
ForgeEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes.
pack.getCheckedRegistry(Biome.class)
.forEach((id, biome) -> registerBiome(biome, pack, id, helper));
});
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, RegisterHelper<net.minecraft.world.biome.Biome> helper) {
RegistryKey<net.minecraft.world.biome.Biome> vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(BuiltinRegistries.BIOME);
if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) {
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla);
} else {
net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, ForgeRegistries.BIOMES.getDelegateOrThrow(vanilla).value());
Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id));
if(ForgeRegistries.BIOMES.containsKey(identifier)) {
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow());
} else {
helper.register(MinecraftUtil.registerKey(identifier).getValue(), minecraftBiome);
((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(ForgeRegistries.BIOMES.getHolder(identifier).orElseThrow().getKey().orElseThrow());
}
MinecraftUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier);
}
}
}

View File

@@ -0,0 +1,24 @@
modLoader = "javafml"
loaderVersion = "[41,)"
license = "GNU General Public License, v3.0"
issueTrackerURL="https://github.com/PolyhedralDev/Terra/issues"
[[mods]]
modId = "terra"
version = "@VERSION@"
displayName = "Terra"
description = "@DESCRIPTION@"
[[dependencies.terra]]
modId = "forge"
mandatory = true
versionRange = "[41,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.terra]]
modId = "minecraft"
mandatory = true
versionRange = "[1.19,)"
ordering = "NONE"
side = "BOTH"

View File

@@ -0,0 +1,6 @@
{
"pack": {
"description": "Terra Resources",
"pack_format": 9
}
}

View File

@@ -0,0 +1,17 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.dfsek.terra.forge.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"lifecycle.NoiseConfigMixin"
],
"client": [
],
"server": [
],
"injectors": {
"defaultRequire": 1
},
"refmap": "terra-forge-refmap.json"
}

View File

@@ -0,0 +1,4 @@
# mixin-common
This project contains mixins shared between Forge & Fabric, as
well as glue code.

View File

@@ -0,0 +1,24 @@
plugins {
id("dev.architectury.loom") version Versions.Mod.architecuryLoom
id("architectury-plugin") version Versions.Mod.architectutyPlugin
}
loom {
mixin {
defaultRefmapName.set("terra-common-refmap.json")
}
}
dependencies {
shadedApi(project(":common:implementation:base"))
modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}")
minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}")
mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2")
}
architectury {
common("fabric", "forge")
minecraft = Versions.Mod.minecraft
}

View File

@@ -0,0 +1,24 @@
package com.dfsek.terra.mod;
import java.util.concurrent.atomic.AtomicReference;
public final class CommonPlatform {
private static final AtomicReference<ModPlatform> platform = new AtomicReference<>();
public static ModPlatform get() {
ModPlatform modPlatform = platform.get();
if(modPlatform == null) {
throw new IllegalStateException("Platform is not yet initialised!");
}
return modPlatform;
}
public static void initialize(ModPlatform modPlatform) {
if(!platform.compareAndSet(null, modPlatform)) {
throw new IllegalStateException("Platform has already been initialized to " + platform.get());
}
}
}

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric;
package com.dfsek.terra.mod;
import ca.solostudios.strata.Versions;
import ca.solostudios.strata.version.Version;
@@ -28,44 +28,44 @@ import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.VanillaBiomeProperties;
import com.dfsek.terra.mod.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.mod.config.VanillaBiomeProperties;
public final class FabricAddon implements BaseAddon {
public final class MinecraftAddon implements BaseAddon {
private static final Version VERSION = Versions.getVersion(1, 0, 0);
private static final Logger logger = LoggerFactory.getLogger(FabricAddon.class);
private final PlatformImpl terraFabricPlugin;
private static final Logger logger = LoggerFactory.getLogger(MinecraftAddon.class);
private final ModPlatform modPlatform;
public FabricAddon(PlatformImpl terraFabricPlugin) {
this.terraFabricPlugin = terraFabricPlugin;
public MinecraftAddon(ModPlatform modPlatform) {
this.modPlatform = modPlatform;
}
@Override
public void initialize() {
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions())))
.global();
modPlatform.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions())))
.global();
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPostLoadEvent.class)
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions())))
.priority(100)
.global();
modPlatform.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPostLoadEvent.class)
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions())))
.priority(100)
.global();
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigurationLoadEvent.class)
.then(event -> {
modPlatform.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigurationLoadEvent.class)
.then(event -> {
if(event.is(Biome.class)) {
event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties()));
}
})
.global();
.global();
}
@Override

View File

@@ -0,0 +1,66 @@
package com.dfsek.terra.mod;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.AbstractPlatform;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.mod.config.ProtoPlatformBiome;
import com.dfsek.terra.mod.util.PresetUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.Precipitation;
import net.minecraft.world.biome.BiomeEffects.GrassColorModifier;
import net.minecraft.world.gen.WorldPreset;
import java.util.List;
import java.util.Locale;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public abstract class ModPlatform extends AbstractPlatform {
public abstract MinecraftServer getServer();
public void registerWorldTypes(BiConsumer<Identifier, WorldPreset> registerFunction) {
getRawConfigRegistry()
.forEach(pack -> PresetUtil.createDefault(pack).apply(registerFunction));
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
.registerLoader(Identifier.class, (type, o, loader, depthTracker) -> {
Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null)
throw new LoadException("Invalid identifier: " + o, depthTracker);
return identifier;
})
.registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT)));
}
private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException {
Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure.
return new ProtoPlatformBiome(identifier);
}
@Override
protected Iterable<BaseAddon> platformAddon() {
return List.of(new MinecraftAddon(this));
}
}

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.config;
package com.dfsek.terra.mod.config;
import com.dfsek.tectonic.api.config.template.ConfigTemplate;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.config;
package com.dfsek.terra.mod.config;
import com.dfsek.tectonic.api.config.template.ConfigTemplate;
import com.dfsek.tectonic.api.config.template.annotations.Default;
@@ -26,19 +26,19 @@ import com.dfsek.terra.api.properties.Properties;
@SuppressWarnings("FieldMayBeFinal")
public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties {
@Value("fabric.use-vanilla-biomes")
@Value("minecraft.use-vanilla-biomes")
@Default
private boolean vanillaBiomes = false;
@Value("fabric.beard.enable")
@Value("minecraft.beard.enable")
@Default
private boolean beard = true;
@Value("fabric.beard.threshold")
@Value("minecraft.beard.threshold")
@Default
private double beardThreshold = 0.5;
@Value("fabric.beard.air-threshold")
@Value("minecraft.beard.air-threshold")
@Default
private double airThreshold = -0.5;

View File

@@ -15,7 +15,9 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.util;
package com.dfsek.terra.mod.config;
import com.dfsek.terra.mod.util.MinecraftUtil;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
@@ -37,7 +39,7 @@ public class ProtoPlatformBiome implements PlatformBiome {
}
public RegistryKey<Biome> get(Registry<net.minecraft.world.biome.Biome> registry) {
return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow();
return MinecraftUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow();
}
@Override

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.config;
package com.dfsek.terra.mod.config;
import com.dfsek.tectonic.api.config.template.ConfigTemplate;
import com.dfsek.tectonic.api.config.template.annotations.Default;

View File

@@ -1,10 +1,7 @@
package com.dfsek.terra.fabric.data;
package com.dfsek.terra.mod.data;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import com.dfsek.terra.mod.generation.TerraBiomeSource;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -12,6 +9,10 @@ import net.minecraft.util.dynamic.RegistryOps;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.mod.CommonPlatform;
public final class Codecs {
public static final Codec<RegistryKey> TERRA_REGISTRY_KEY = RecordCodecBuilder
@@ -27,10 +28,10 @@ public final class Codecs {
.create(config -> config.group(TERRA_REGISTRY_KEY.fieldOf("pack")
.stable()
.forGetter(ConfigPack::getRegistryKey))
.apply(config, config.stable(id -> FabricEntryPoint.getPlatform()
.getConfigRegistry()
.get(id)
.orElseThrow(() -> new IllegalArgumentException(
.apply(config, config.stable(id -> CommonPlatform.get()
.getConfigRegistry()
.get(id)
.orElseThrow(() -> new IllegalArgumentException(
"No such config pack " +
id)))));
@@ -44,22 +45,22 @@ public final class Codecs {
.forGetter(TerraBiomeSource::getPack))
.apply(instance, instance.stable(TerraBiomeSource::new)));
public static final Codec<FabricChunkGeneratorWrapper> FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder
public static final Codec<MinecraftChunkGeneratorWrapper> MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder
.create(
instance -> instance.group(
RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY)
.fieldOf("structure_registry")
.stable()
.forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry),
.forGetter(MinecraftChunkGeneratorWrapper::getNoiseRegistry),
TERRA_BIOME_SOURCE.fieldOf("biome_source")
.stable()
.forGetter(FabricChunkGeneratorWrapper::getBiomeSource),
.forGetter(MinecraftChunkGeneratorWrapper::getBiomeSource),
CONFIG_PACK.fieldOf("pack")
.stable()
.forGetter(FabricChunkGeneratorWrapper::getPack),
.forGetter(MinecraftChunkGeneratorWrapper::getPack),
ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings")
.stable()
.forGetter(FabricChunkGeneratorWrapper::getSettings)
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
.forGetter(MinecraftChunkGeneratorWrapper::getSettings)
).apply(instance, instance.stable(MinecraftChunkGeneratorWrapper::new))
);
}

View File

@@ -15,7 +15,9 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.generation;
package com.dfsek.terra.mod.generation;
import com.dfsek.terra.mod.mixin.access.StructureAccessorAccessor;
import com.mojang.serialization.Codec;
import net.minecraft.block.BlockState;
@@ -61,14 +63,13 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.data.Codecs;
import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor;
import com.dfsek.terra.fabric.util.FabricAdapter;
import com.dfsek.terra.mod.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.mod.data.Codecs;
import com.dfsek.terra.mod.util.MinecraftAdapter;
public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper {
private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class);
public class MinecraftChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper {
private static final Logger logger = LoggerFactory.getLogger(MinecraftChunkGeneratorWrapper.class);
private final TerraBiomeSource biomeSource;
private final Registry<StructureSet> noiseRegistry;
@@ -76,8 +77,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
private ChunkGenerator delegate;
private ConfigPack pack;
public FabricChunkGeneratorWrapper(Registry<StructureSet> noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack,
RegistryEntry<ChunkGeneratorSettings> settingsSupplier) {
public MinecraftChunkGeneratorWrapper(Registry<StructureSet> noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack,
RegistryEntry<ChunkGeneratorSettings> settingsSupplier) {
super(noiseRegistry, Optional.empty(), biomeSource);
this.noiseRegistry = noiseRegistry;
this.pack = configPack;
@@ -94,7 +95,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
@Override
protected Codec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() {
return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER;
return Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER;
}
@Override
@@ -185,7 +186,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
@Override
public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) {
WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
WorldProperties properties = MinecraftAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
BiomeProvider biomeProvider = pack.getBiomeProvider();
int min = height.getBottomY();
for(int y = height.getTopY() - 1; y >= min; y--) {
@@ -199,7 +200,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
@Override
public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) {
BlockState[] array = new BlockState[height.getHeight()];
WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
WorldProperties properties = MinecraftAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
BiomeProvider biomeProvider = pack.getBiomeProvider();
for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) {
array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider);

View File

@@ -15,18 +15,16 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.generation;
package com.dfsek.terra.mod.generation;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.fabric.data.Codecs;
import com.dfsek.terra.fabric.util.ProtoPlatformBiome;
import com.dfsek.terra.mod.data.Codecs;
import com.dfsek.terra.mod.config.ProtoPlatformBiome;
import com.dfsek.terra.fabric.util.SeedHack;
import com.dfsek.terra.mod.util.SeedHack;
import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.world.biome.source.BiomeSource;
@@ -34,7 +32,6 @@ import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.stream.StreamSupport;

View File

@@ -15,9 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.handle;
import com.dfsek.terra.fabric.FabricEntryPoint;
package com.dfsek.terra.mod.handle;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -32,14 +30,16 @@ import java.util.stream.Collectors;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.mod.CommonPlatform;
public class FabricItemHandle implements ItemHandle {
public class MinecraftItemHandle implements ItemHandle {
@Override
public Item createItem(String data) {
try {
return (Item) new ItemStackArgumentType(new CommandRegistryAccess(FabricEntryPoint.getPlatform().getServer().getRegistryManager())).parse(new StringReader(data)).getItem();
return (Item) new ItemStackArgumentType(new CommandRegistryAccess(
CommonPlatform.get().getServer().getRegistryManager())).parse(new StringReader(data)).getItem();
} catch(CommandSyntaxException e) {
throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e);
}

View File

@@ -15,16 +15,12 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.handle;
package com.dfsek.terra.mod.handle;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.Blocks;
import net.minecraft.command.argument.BlockArgumentParser;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import org.jetbrains.annotations.NotNull;
@@ -33,7 +29,7 @@ import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.handle.WorldHandle;
public class FabricWorldHandle implements WorldHandle {
public class MinecraftWorldHandle implements WorldHandle {
private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState();

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.access;
package com.dfsek.terra.mod.mixin.access;
import net.minecraft.world.MobSpawnerEntry;
import net.minecraft.world.MobSpawnerLogic;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.access;
package com.dfsek.terra.mod.mixin.access;
import net.minecraft.state.State;
import net.minecraft.state.property.Property;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.access;
package com.dfsek.terra.mod.mixin.access;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.gen.StructureAccessor;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.mixin.fix;
package com.dfsek.terra.mod.mixin.fix;
import net.minecraft.entity.passive.BeeEntity.MoveToFlowerGoal;
import net.minecraft.entity.passive.BeeEntity.MoveToHiveGoal;
@@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.mod.CommonPlatform;
/**
@@ -22,6 +22,6 @@ import com.dfsek.terra.fabric.FabricEntryPoint;
public class BeeMoveGoalsUnsynchronizedRandomAccessFix {
@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;random:Lnet/minecraft/util/math/random/Random;"))
public Random redirectRandomAccess(World instance) {
return new CheckedRandom(FabricEntryPoint.getPlatform().getServer().getTicks()); // replace with new random seeded by tick time.
return new CheckedRandom(CommonPlatform.get().getServer().getTicks()); // replace with new random seeded by tick time.
}
}

View File

@@ -1,24 +1,11 @@
package com.dfsek.terra.fabric.mixin.fix;
package com.dfsek.terra.mod.mixin.fix;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.structure.NetherFossilGenerator;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.ChunkRandom;
import net.minecraft.world.EmptyBlockView;
import net.minecraft.world.gen.HeightContext;
import net.minecraft.world.gen.chunk.VerticalBlockSample;
import net.minecraft.world.gen.heightprovider.HeightProvider;
import net.minecraft.world.gen.structure.NetherFossilStructure;
import net.minecraft.world.gen.structure.Structure;
import net.minecraft.world.gen.structure.Structure.Context;
import net.minecraft.world.gen.structure.Structure.StructurePosition;
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.CallbackInfoReturnable;
@@ -35,7 +22,7 @@ import java.util.Optional;
public class NetherFossilOptimization {
@Inject(method = "getStructurePosition", at = @At("HEAD"), cancellable = true)
public void injectFossilPositions(Context context, CallbackInfoReturnable<Optional<StructurePosition>> cir) {
if(context.chunkGenerator() instanceof FabricChunkGeneratorWrapper) {
if(context.chunkGenerator() instanceof MinecraftChunkGeneratorWrapper) {
cir.setReturnValue(Optional.empty());
}
}

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.fabric.mixin.implementations.compat;
package com.dfsek.terra.mod.mixin.implementations.compat;
import com.dfsek.terra.fabric.mixin_ifaces.FloraFeatureHolder;
import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder;
import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.gen.feature.ConfiguredFeature;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra;
package com.dfsek.terra.mod.mixin.implementations.terra;
import net.minecraft.world.biome.Biome;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.mixin.implementations.terra;
package com.dfsek.terra.mod.mixin.implementations.terra;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.block;
package com.dfsek.terra.mod.mixin.implementations.terra.block;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.block.entity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.block.entity;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.block.entity;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
@@ -34,8 +34,8 @@ import org.spongepowered.asm.mixin.Shadow;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.SerialState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor;
import com.dfsek.terra.mod.CommonPlatform;
import com.dfsek.terra.mod.mixin.access.MobSpawnerLogicAccessor;
@Mixin(MobSpawnerBlockEntity.class)
@@ -116,7 +116,7 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity {
public void terra$applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type" -> terra$setSpawnedType(FabricEntryPoint.getPlatform().getWorldHandle().getEntity(v));
case "type" -> terra$setSpawnedType(CommonPlatform.get().getWorldHandle().getEntity(v));
case "delay" -> terra$setDelay(Integer.parseInt(v));
case "min_delay" -> terra$setMinSpawnDelay(Integer.parseInt(v));
case "max_delay" -> terra$setMaxSpawnDelay(Integer.parseInt(v));

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.block.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.block.entity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.text.Text;

View File

@@ -1,6 +1,8 @@
package com.dfsek.terra.fabric.mixin.implementations.terra.block.state;
package com.dfsek.terra.mod.mixin.implementations.terra.block.state;
import com.dfsek.terra.mod.mixin.access.StateAccessor;
import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.AbstractBlock.AbstractBlockState;
@@ -18,7 +20,6 @@ import java.util.stream.Collectors;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.state.properties.Property;
import com.dfsek.terra.fabric.mixin.access.StateAccessor;
@Mixin(AbstractBlockState.class)

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.mixin.implementations.terra.block.state;
package com.dfsek.terra.mod.mixin.implementations.terra.block.state;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.chunk;
package com.dfsek.terra.mod.mixin.implementations.terra.chunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.chunk;
package com.dfsek.terra.mod.mixin.implementations.terra.chunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.WorldChunk;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.chunk.data;
package com.dfsek.terra.mod.mixin.implementations.terra.chunk.data;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.entity;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
@@ -26,7 +26,7 @@ import org.spongepowered.asm.mixin.Shadow;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.fabric.util.FabricAdapter;
import com.dfsek.terra.mod.util.MinecraftAdapter;
@Mixin(Entity.class)
@@ -42,7 +42,7 @@ public abstract class EntityMixin {
public abstract void teleport(double destX, double destY, double destZ);
public Vector3 terra$position() {
return FabricAdapter.adapt(blockPos);
return MinecraftAdapter.adapt(blockPos);
}
public void terra$position(Vector3 location) {

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.entity;
import net.minecraft.entity.EntityType;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.entity;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.entity;
package com.dfsek.terra.mod.mixin.implementations.terra.entity;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.server.command.ServerCommandSource;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory;
import net.minecraft.block.entity.LockableContainerBlockEntity;
import net.minecraft.item.Items;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item;
import net.minecraft.item.Item;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.item;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.util.registry.Registry;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Implements;

View File

@@ -15,7 +15,7 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.inventory.meta;
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;

View File

@@ -20,4 +20,4 @@
* interfaces in Minecraft classes.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra;
package com.dfsek.terra.mod.mixin.implementations.terra;

View File

@@ -15,8 +15,9 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.world;
package com.dfsek.terra.mod.mixin.implementations.terra.world;
import com.dfsek.terra.mod.util.MinecraftUtil;
import net.minecraft.block.FluidBlock;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.math.BlockPos;
@@ -47,8 +48,7 @@ import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
@Mixin(ChunkRegion.class)
@@ -109,7 +109,7 @@ public abstract class ChunkRegionMixin {
}
public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) {
return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z));
return MinecraftUtil.createState((WorldAccess) this, new BlockPos(x, y, z));
}
public int terraWorld$getMinHeight() {
@@ -117,7 +117,7 @@ public abstract class ChunkRegionMixin {
}
public ChunkGenerator terraWorld$getGenerator() {
return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle();
return ((MinecraftChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle();
}
public BiomeProvider terraWorld$getBiomeProvider() {

View File

@@ -15,8 +15,9 @@
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.fabric.mixin.implementations.terra.world;
package com.dfsek.terra.mod.mixin.implementations.terra.world;
import com.dfsek.terra.mod.util.MinecraftUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
import org.spongepowered.asm.mixin.Implements;
@@ -33,9 +34,8 @@ import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import com.dfsek.terra.mod.generation.TerraBiomeSource;
@Mixin(net.minecraft.server.world.ServerWorld.class)
@@ -73,7 +73,7 @@ public abstract class ServerWorldMixin {
}
public BlockEntity terra$getBlockEntity(int x, int y, int z) {
return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z));
return MinecraftUtil.createState((WorldAccess) this, new BlockPos(x, y, z));
}
public int terra$getMinHeight() {
@@ -81,8 +81,8 @@ public abstract class ServerWorldMixin {
}
public ChunkGenerator terra$getGenerator() {
return ((FabricChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()
.getChunkGenerator()).getHandle();
return ((MinecraftChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()
.getChunkGenerator()).getHandle();
}
public BiomeProvider terra$getBiomeProvider() {
@@ -94,8 +94,8 @@ public abstract class ServerWorldMixin {
public ConfigPack terra$getPack() {
net.minecraft.world.gen.chunk.ChunkGenerator generator =
(((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator();
if(generator instanceof FabricChunkGeneratorWrapper fabricChunkGeneratorWrapper) {
return fabricChunkGeneratorWrapper.getPack();
if(generator instanceof MinecraftChunkGeneratorWrapper minecraftChunkGeneratorWrapper) {
return minecraftChunkGeneratorWrapper.getPack();
}
return null;
}

View File

@@ -1,7 +1,8 @@
package com.dfsek.terra.fabric.mixin.lifecycle;
package com.dfsek.terra.mod.mixin.lifecycle;
import com.dfsek.terra.mod.util.TagUtil;
import com.dfsek.terra.mod.util.MinecraftUtil;
import com.dfsek.terra.fabric.util.BiomeUtil;
import com.dfsek.terra.fabric.util.TagUtil;
import net.minecraft.server.DataPackContents;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
@@ -23,6 +24,6 @@ public class DataPackContentsMixin {
Registry<Biome> biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY);
TagUtil.registerBiomeTags(biomeRegistry);
BiomeUtil.registerFlora(biomeRegistry);
MinecraftUtil.registerFlora(biomeRegistry);
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.mixin_ifaces;
package com.dfsek.terra.mod.mixin_ifaces;
import net.minecraft.world.gen.feature.ConfiguredFeature;

View File

@@ -0,0 +1,56 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.mod.util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.HeightLimitView;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.info.WorldProperties;
public final class MinecraftAdapter {
public static Vector3 adapt(BlockPos pos) {
return Vector3.of(pos.getX(), pos.getY(), pos.getZ());
}
public static WorldProperties adapt(HeightLimitView height, long seed) {
return new WorldProperties() {
@Override
public long getSeed() {
return seed;
}
@Override
public int getMaxHeight() {
return height.getTopY();
}
@Override
public int getMinHeight() {
return height.getBottomY();
}
@Override
public Object getHandle() {
return height;
}
};
}
}

View File

@@ -0,0 +1,154 @@
package com.dfsek.terra.mod.util;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.entity.Container;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.Sign;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.mod.config.VanillaBiomeProperties;
import com.dfsek.terra.mod.mixin_ifaces.FloraFeatureHolder;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryEntry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.Builder;
import net.minecraft.world.biome.BiomeEffects;
import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public final class MinecraftUtil {
public static final Logger logger = LoggerFactory.getLogger(MinecraftUtil.class);
public static final Map<Identifier, List<Identifier>>
TERRA_BIOME_MAP = new HashMap<>();
private MinecraftUtil() {
}
public static <T> Optional<RegistryEntry<T>> getEntry(Registry<T> registry, Identifier identifier) {
return registry.getOrEmpty(identifier)
.flatMap(registry::getKey)
.map(registry::getOrCreateEntry);
}
public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) {
net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos);
if(entity instanceof SignBlockEntity) {
return (Sign) entity;
} else if(entity instanceof MobSpawnerBlockEntity) {
return (MobSpawner) entity;
} else if(entity instanceof LootableContainerBlockEntity) {
return (Container) entity;
}
return null;
}
public static void registerFlora(Registry<net.minecraft.world.biome.Biome> biomes) {
logger.info("Injecting flora into Terra biomes...");
TERRA_BIOME_MAP
.forEach((vb, terraBiomes) ->
biomes.getOrEmpty(vb)
.ifPresentOrElse(vanilla -> terraBiomes
.forEach(tb -> biomes.getOrEmpty(tb)
.ifPresentOrElse(
terra -> {
List<ConfiguredFeature<?, ?>> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures());
logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures);
((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures);
},
() -> logger.error(
"No such biome: {}",
tb))),
() -> logger.error("No vanilla biome: {}", vb)));
}
public static Map<Identifier, List<Identifier>> getTerraBiomeMap() {
return Map.copyOf(TERRA_BIOME_MAP);
}
public static RegistryKey<Biome> registerKey(Identifier identifier) {
return RegistryKey.of(Registry.BIOME_KEY, identifier);
}
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) {
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
BiomeEffects.Builder effects = new BiomeEffects.Builder();
Biome.Builder builder = new Builder();
if(biome.getContext().has(VanillaBiomeProperties.class)) {
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()))
.grassColorModifier(
Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier()));
if(vanillaBiomeProperties.getGrassColor() == null) {
vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor);
} else {
effects.grassColor(vanillaBiomeProperties.getGrassColor());
}
if(vanillaBiomeProperties.getFoliageColor() == null) {
vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor);
} else {
effects.foliageColor(vanillaBiomeProperties.getFoliageColor());
}
builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation()));
} else {
effects.waterColor(vanilla.getWaterColor())
.waterFogColor(vanilla.getWaterFogColor())
.fogColor(vanilla.getFogColor())
.skyColor(vanilla.getSkyColor());
vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor);
vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor);
builder.precipitation(vanilla.getPrecipitation());
}
vanilla.getLoopSound().ifPresent(effects::loopSound);
vanilla.getAdditionsSound().ifPresent(effects::additionsSound);
vanilla.getMoodSound().ifPresent(effects::moodSound);
vanilla.getMusic().ifPresent(effects::music);
vanilla.getParticleConfig().ifPresent(effects::particleConfig);
return builder
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(effects.build())
.spawnSettings(vanilla.getSpawnSettings())
.generationSettings(generationSettings.build())
.build();
}
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
return pack.getID()
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
}
}

View File

@@ -1,9 +1,10 @@
package com.dfsek.terra.fabric.util;
package com.dfsek.terra.mod.util;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import com.dfsek.terra.mod.generation.TerraBiomeSource;
import net.minecraft.structure.StructureSet;
import net.minecraft.util.Identifier;
@@ -30,24 +31,17 @@ import java.util.Locale;
import java.util.Map;
public class LifecycleUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.class);
public class PresetUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(PresetUtil.class);
private static final List<Identifier> PRESETS = new ArrayList<>();
public static void initialize() {
FabricEntryPoint.getPlatform().getEventManager().callEvent(
new PlatformInitializationEvent());
BiomeUtil.registerBiomes();
LOGGER.info("Registering Terra world types...");
public static Pair<Identifier, WorldPreset> createDefault(ConfigPack pack) {
Registry<DimensionType> dimensionTypeRegistry = BuiltinRegistries.DIMENSION_TYPE;
Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry = BuiltinRegistries.CHUNK_GENERATOR_SETTINGS;
Registry<StructureSet> structureSetRegistry = BuiltinRegistries.STRUCTURE_SET;
Registry<NoiseParameters> noiseParametersRegistry = BuiltinRegistries.NOISE_PARAMETERS;
Registry<Biome> biomeRegistry = BuiltinRegistries.BIOME;
RegistryEntry<DimensionType> theNetherDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_NETHER);
RegistryEntry<ChunkGeneratorSettings>
netherChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.NETHER);
@@ -64,34 +58,29 @@ public class LifecycleUtil {
new NoiseChunkGenerator(structureSetRegistry, noiseParametersRegistry,
new TheEndBiomeSource(biomeRegistry),
endChunkGeneratorSettings));
RegistryEntry<DimensionType> overworldDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.OVERWORLD);
RegistryEntry<ChunkGeneratorSettings> overworld = chunkGeneratorSettingsRegistry.getOrCreateEntry(ChunkGeneratorSettings.OVERWORLD);
FabricEntryPoint
.getPlatform()
.getRawConfigRegistry()
.forEach((id, pack) -> {
Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase(
Locale.ROOT));
PRESETS.add(generatorID);
TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack);
ChunkGenerator generator = new FabricChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld);
DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator);
WorldPreset preset = new WorldPreset(
Map.of(
DimensionOptions.OVERWORLD, dimensionOptions,
DimensionOptions.NETHER, netherDimensionOptions,
DimensionOptions.END, endDimensionOptions
)
);
BuiltinRegistries.add(BuiltinRegistries.WORLD_PRESET, generatorID, preset);
LOGGER.info("Registered world type \"{}\"", generatorID);
}
);
Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase(
Locale.ROOT));
PRESETS.add(generatorID);
TerraBiomeSource biomeSource = new TerraBiomeSource(biomeRegistry, pack);
ChunkGenerator generator = new MinecraftChunkGeneratorWrapper(structureSetRegistry, biomeSource, pack, overworld);
DimensionOptions dimensionOptions = new DimensionOptions(overworldDimensionType, generator);
WorldPreset preset = new WorldPreset(
Map.of(
DimensionOptions.OVERWORLD, dimensionOptions,
DimensionOptions.NETHER, netherDimensionOptions,
DimensionOptions.END, endDimensionOptions
)
);
LOGGER.info("Created world type \"{}\"", generatorID);
return Pair.of(generatorID, preset);
}
public static List<Identifier> getPresets() {

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.util;
package com.dfsek.terra.mod.util;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.util;
package com.dfsek.terra.mod.util;
import com.google.common.collect.ImmutableMap;
import net.minecraft.tag.TagKey;
@@ -36,9 +36,9 @@ public final class TagUtil {
logger.info("Doing preset tag garbage....");
Map<TagKey<WorldPreset>, List<RegistryEntry<WorldPreset>>> collect = tagsToMutableMap(registry);
LifecycleUtil
PresetUtil
.getPresets()
.forEach(id -> FabricUtil
.forEach(id -> MinecraftUtil
.getEntry(registry, id)
.ifPresentOrElse(
preset -> collect
@@ -54,14 +54,14 @@ public final class TagUtil {
logger.info("Doing biome tag garbage....");
Map<TagKey<Biome>, List<RegistryEntry<Biome>>> collect = tagsToMutableMap(registry);
BiomeUtil
MinecraftUtil
.getTerraBiomeMap()
.forEach((vb, terraBiomes) ->
FabricUtil
MinecraftUtil
.getEntry(registry, vb)
.ifPresentOrElse(
vanilla -> terraBiomes
.forEach(tb -> FabricUtil
.forEach(tb -> MinecraftUtil
.getEntry(registry, tb)
.ifPresentOrElse(
terra -> {

View File

@@ -0,0 +1,8 @@
{
"schemaVersion": 1,
"id": "terra-common",
"version": "1.0.0",
"mixins": [
"terra.common.mixins.json"
]
}

View File

@@ -0,0 +1,47 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.dfsek.terra.mod.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"access.MobSpawnerLogicAccessor",
"access.StateAccessor",
"access.StructureAccessorAccessor",
"fix.BeeMoveGoalsUnsynchronizedRandomAccessFix",
"fix.NetherFossilOptimization",
"implementations.compat.GenerationSettingsFloraFeaturesMixin",
"implementations.terra.BiomeMixin",
"implementations.terra.HandleImplementationMixin",
"implementations.terra.block.BlockMixin",
"implementations.terra.block.entity.BlockEntityMixin",
"implementations.terra.block.entity.LootableContainerBlockEntityMixin",
"implementations.terra.block.entity.MobSpawnerBlockEntityMixin",
"implementations.terra.block.entity.SignBlockEntityMixin",
"implementations.terra.block.state.BlockStateMixin",
"implementations.terra.block.state.PropertyMixin",
"implementations.terra.chunk.ChunkRegionMixin",
"implementations.terra.chunk.WorldChunkMixin",
"implementations.terra.chunk.data.ProtoChunkMixin",
"implementations.terra.entity.EntityMixin",
"implementations.terra.entity.EntityTypeMixin",
"implementations.terra.entity.PlayerEntityMixin",
"implementations.terra.entity.ServerCommandSourceMixin",
"implementations.terra.inventory.LockableContainerBlockEntityMixin",
"implementations.terra.inventory.item.ItemMixin",
"implementations.terra.inventory.item.ItemStackMixin",
"implementations.terra.inventory.meta.EnchantmentMixin",
"implementations.terra.inventory.meta.ItemStackDamageableMixin",
"implementations.terra.inventory.meta.ItemStackMetaMixin",
"implementations.terra.world.ChunkRegionMixin",
"implementations.terra.world.ServerWorldMixin",
"lifecycle.DataPackContentsMixin"
],
"client": [
],
"server": [
],
"injectors": {
"defaultRequire": 1
},
"refmap": "terra-common-refmap.json"
}

View File

@@ -24,9 +24,15 @@ include(":platforms:bukkit:common")
pluginManagement {
repositories {
maven("https://maven.fabricmc.net") {
name = "Fabric"
}
gradlePluginPortal()
maven("https://maven.fabricmc.net") {
name = "Fabric Maven"
}
maven ( "https://maven.architectury.dev/" ) {
name = "Architectury Maven"
}
maven ( "https://files.minecraftforge.net/maven/" ) {
name = "Forge Maven"
}
}
}