mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-01 23:47:50 +00:00
commit
0feae25be5
@ -1,8 +1,8 @@
|
||||
preRelease(true)
|
||||
|
||||
versionProjects(":common:api", version("6.0.1"))
|
||||
versionProjects(":common:implementation", version("6.0.1"))
|
||||
versionProjects(":platforms", version("6.0.1"))
|
||||
versionProjects(":common:api", version("6.1.0"))
|
||||
versionProjects(":common:implementation", version("6.1.0"))
|
||||
versionProjects(":platforms", version("6.1.0"))
|
||||
|
||||
|
||||
allprojects {
|
||||
|
@ -3,6 +3,15 @@ plugins {
|
||||
kotlin("jvm") version embeddedKotlinVersion
|
||||
}
|
||||
|
||||
buildscript {
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force("org.ow2.asm:asm:9.3") // TODO: remove when ShadowJar updates ASM version
|
||||
force("org.ow2.asm:asm-commons:9.3")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
@ -11,8 +20,8 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:+")
|
||||
implementation("org.ow2.asm:asm:9.2")
|
||||
implementation("org.ow2.asm:asm-tree:9.2")
|
||||
implementation("org.ow2.asm:asm:9.3")
|
||||
implementation("org.ow2.asm:asm-tree:9.3")
|
||||
implementation("com.dfsek.tectonic:common:4.2.0")
|
||||
implementation("org.yaml:snakeyaml:1.27")
|
||||
}
|
@ -3,7 +3,6 @@ import java.io.File
|
||||
import java.util.function.Predicate
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import kotlin.streams.asStream
|
||||
|
||||
@ -12,28 +11,33 @@ import kotlin.streams.asStream
|
||||
* Configures a directory where addons will be put.
|
||||
*/
|
||||
fun Project.addonDir(dir: File, task: Task) {
|
||||
task.dependsOn("compileAddons")
|
||||
task.doFirst {
|
||||
dir.parentFile.mkdirs()
|
||||
matchingAddons(dir) {
|
||||
it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon.
|
||||
}.forEach {
|
||||
println("Deleting old addon: " + it.absolutePath)
|
||||
it.delete()
|
||||
val moveAddons = tasks.register("moveAddons" + task.name) {
|
||||
dependsOn("compileAddons")
|
||||
doLast {
|
||||
dir.parentFile.mkdirs()
|
||||
matchingAddons(dir) {
|
||||
it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon.
|
||||
}.forEach {
|
||||
println("Deleting old addon: " + it.absolutePath)
|
||||
it.delete()
|
||||
}
|
||||
forSubProjects(":common:addons") {
|
||||
val jar = tasks.named("shadowJar").get() as ShadowJar
|
||||
|
||||
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
|
||||
val target = File(dir, boot + jar.archiveFileName.get())
|
||||
|
||||
val base = "${jar.archiveBaseName.get()}-${version}"
|
||||
|
||||
println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
|
||||
|
||||
jar.archiveFile.orNull?.asFile?.copyTo(target)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
forSubProjects(":common:addons") {
|
||||
val jar = tasks.named("shadowJar").get() as ShadowJar
|
||||
|
||||
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
|
||||
val target = File(dir, boot + jar.archiveFileName.get())
|
||||
|
||||
val base = "${jar.archiveBaseName.get()}-${version}"
|
||||
|
||||
println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
|
||||
|
||||
jar.archiveFile.orNull?.asFile?.copyTo(target)
|
||||
}
|
||||
}
|
||||
|
||||
task.dependsOn(moveAddons)
|
||||
}
|
||||
|
||||
fun matchingAddons(dir: File, matcher: Predicate<File>): Set<File> {
|
||||
|
@ -19,10 +19,12 @@ object Versions {
|
||||
|
||||
object Fabric {
|
||||
const val fabricLoader = "0.14.2"
|
||||
const val fabricAPI = "0.53.4+1.18.2"
|
||||
const val minecraft = "1.18.2"
|
||||
const val yarn = "$minecraft+build.3"
|
||||
const val fabricAPI = "0.55.1+1.19"
|
||||
const val minecraft = "1.19"
|
||||
const val yarn = "$minecraft+build.1"
|
||||
const val permissionsAPI = "0.1-SNAPSHOT"
|
||||
const val mixin = "0.11.2+mixin.0.8.5"
|
||||
const val loom = "0.11-SNAPSHOT"
|
||||
}
|
||||
|
||||
object Bukkit {
|
||||
|
@ -19,33 +19,6 @@ package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.tectonic.api.TypeRegistry;
|
||||
|
||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.addon.BootstrapAddonLoader;
|
||||
import com.dfsek.terra.addon.DependencySorter;
|
||||
import com.dfsek.terra.addon.EphemeralAddon;
|
||||
@ -64,6 +37,7 @@ import com.dfsek.terra.api.profiler.Profiler;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||
import com.dfsek.terra.api.util.mutable.MutableBoolean;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
import com.dfsek.terra.config.GenericLoaders;
|
||||
@ -75,6 +49,21 @@ import com.dfsek.terra.registry.LockedRegistryImpl;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Skeleton implementation of {@link Platform}
|
||||
@ -119,8 +108,10 @@ public abstract class AbstractPlatform implements Platform {
|
||||
logger.info("Initializing Terra...");
|
||||
|
||||
try(InputStream stream = getClass().getResourceAsStream("/config.yml")) {
|
||||
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);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
@ -222,6 +213,7 @@ public abstract class AbstractPlatform implements Platform {
|
||||
Path data = getDataFolder().toPath();
|
||||
|
||||
Path addonsPath = data.resolve("addons");
|
||||
Files.createDirectories(addonsPath);
|
||||
Set<Pair<Path, String>> paths = Files
|
||||
.walk(addonsPath)
|
||||
.map(path -> Pair.of(path, data.relativize(path).toString()))
|
||||
@ -249,7 +241,6 @@ public abstract class AbstractPlatform implements Platform {
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
|
||||
// Terra-aaa-aaa-1.2.3-BETA+1e6af8923d.jar
|
||||
String resourceYaml = IOUtils.toString(resourcesConfig, StandardCharsets.UTF_8);
|
||||
Map<String, List<String>> resources = new Yaml().load(resourceYaml);
|
||||
resources.forEach((dir, entries) -> entries.forEach(entry -> {
|
||||
@ -258,42 +249,44 @@ public abstract class AbstractPlatform implements Platform {
|
||||
if(resource.exists())
|
||||
return; // dont overwrite
|
||||
|
||||
paths
|
||||
.stream()
|
||||
.filter(Pair.testRight(resourcePath::startsWith))
|
||||
.forEach(Pair.consumeLeft(path -> {
|
||||
logger.info("Removing outdated resource {}, replacing with {}", path, resourcePath);
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
if(pathsNoMajor
|
||||
.stream()
|
||||
.anyMatch(resourcePath::startsWith) && // if any share name
|
||||
paths
|
||||
.stream()
|
||||
.map(Pair.unwrapRight())
|
||||
.noneMatch(resourcePath::startsWith)) { // but dont share major version
|
||||
logger.warn(
|
||||
"Addon {} has a new major version available. It will not be automatically updated; you will need to ensure " +
|
||||
"compatibility and update manually.",
|
||||
resourcePath);
|
||||
}
|
||||
|
||||
logger.info("Dumping resource {}...", resource.getAbsolutePath());
|
||||
try {
|
||||
try(InputStream is = getClass().getResourceAsStream("/" + resourcePath)) {
|
||||
if(is == null) {
|
||||
logger.error("Resource {} doesn't exist on the classpath!", resourcePath);
|
||||
return;
|
||||
}
|
||||
|
||||
paths
|
||||
.stream()
|
||||
.filter(Pair.testRight(resourcePath::startsWith))
|
||||
.forEach(Pair.consumeLeft(path -> {
|
||||
logger.info("Removing outdated resource {}, replacing with {}", path, resourcePath);
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
if(pathsNoMajor
|
||||
.stream()
|
||||
.anyMatch(resourcePath::startsWith) && // if any share name
|
||||
paths
|
||||
.stream()
|
||||
.map(Pair.unwrapRight())
|
||||
.noneMatch(resourcePath::startsWith)) { // but dont share major version
|
||||
logger.warn(
|
||||
"Addon {} has a new major version available. It will not be automatically updated; you will need to " +
|
||||
"ensure " +
|
||||
"compatibility and update manually.",
|
||||
resourcePath);
|
||||
}
|
||||
|
||||
logger.info("Dumping resource {}...", resource.getAbsolutePath());
|
||||
resource.getParentFile().mkdirs();
|
||||
resource.createNewFile();
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
logger.debug("Copying resource {}", resourcePath);
|
||||
try(InputStream is = getClass().getResourceAsStream("/" + resourcePath);
|
||||
OutputStream os = new FileOutputStream(resource)) {
|
||||
IOUtils.copy(is, os);
|
||||
try(OutputStream os = new FileOutputStream(resource)) {
|
||||
IOUtils.copy(is, os);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
@ -74,21 +74,24 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon<BootstrapBaseAdd
|
||||
}
|
||||
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
throw new AddonLoadException("Failed to load addon from path " + addonPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<BootstrapBaseAddon<?>> loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) {
|
||||
Path bootstrapFolder = addonsFolder.resolve("bootstrap");
|
||||
logger.debug("Loading bootstrap addons from {}", bootstrapFolder);
|
||||
|
||||
try(Stream<Path> bootstrapAddons = Files.walk(bootstrapFolder, 1, FileVisitOption.FOLLOW_LINKS)) {
|
||||
return bootstrapAddons.filter(path -> path.toFile().isFile())
|
||||
.filter(path -> path.toFile().canRead())
|
||||
.filter(path -> path.toString().endsWith(".jar"))
|
||||
.map(path -> loadAddon(path, parent))
|
||||
.collect(Collectors.toList());
|
||||
try {
|
||||
Path bootstrapFolder = addonsFolder.resolve("bootstrap");
|
||||
Files.createDirectories(bootstrapFolder);
|
||||
logger.debug("Loading bootstrap addons from {}", bootstrapFolder);
|
||||
|
||||
try(Stream<Path> bootstrapAddons = Files.walk(bootstrapFolder, 1, FileVisitOption.FOLLOW_LINKS)) {
|
||||
return bootstrapAddons.filter(path -> path.toFile().isFile())
|
||||
.filter(path -> path.toFile().canRead())
|
||||
.filter(path -> path.toString().endsWith(".jar"))
|
||||
.map(path -> loadAddon(path, parent))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import com.modrinth.minotaur.TaskModrinthUpload
|
||||
import net.fabricmc.loom.task.RemapJarTask
|
||||
|
||||
plugins {
|
||||
id("fabric-loom").version("0.11-SNAPSHOT")
|
||||
id("fabric-loom").version(Versions.Fabric.loom)
|
||||
id("com.modrinth.minotaur").version("1.1.0")
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ dependencies {
|
||||
|
||||
modImplementation("net.fabricmc:fabric-loader:${Versions.Fabric.fabricLoader}")
|
||||
|
||||
setOf("fabric-command-api-v1", "fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base").forEach { apiModule ->
|
||||
setOf("fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base").forEach { apiModule ->
|
||||
val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI)
|
||||
modImplementation(module)
|
||||
include(module)
|
||||
@ -24,8 +24,12 @@ dependencies {
|
||||
include(modImplementation("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI))
|
||||
include("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI)
|
||||
|
||||
include(modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud))
|
||||
include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)
|
||||
"compileOnly"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}")
|
||||
"annotationProcessor"("net.fabricmc:sponge-mixin:${Versions.Fabric.mixin}")
|
||||
"annotationProcessor"("net.fabricmc:fabric-loom:${Versions.Fabric.loom}")
|
||||
|
||||
//include(modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud))
|
||||
//include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)
|
||||
}
|
||||
|
||||
loom {
|
||||
|
@ -17,17 +17,13 @@
|
||||
|
||||
package com.dfsek.terra.fabric;
|
||||
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.gen.WorldPresets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandSender;
|
||||
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
|
||||
import com.dfsek.terra.fabric.data.Codecs;
|
||||
|
||||
|
||||
@ -49,7 +45,7 @@ public class FabricEntryPoint implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
logger.info("Initializing Terra Fabric mod...");
|
||||
|
||||
/*
|
||||
FabricServerCommandManager<CommandSender> manager = new FabricServerCommandManager<>(
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
serverCommandSource -> (CommandSender) serverCommandSource,
|
||||
@ -60,5 +56,7 @@ public class FabricEntryPoint implements ModInitializer {
|
||||
manager.brigadierManager().setNativeNumberSuggestions(false);
|
||||
|
||||
TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager));
|
||||
TODO: re-enable when Cloud updates
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ 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.Category;
|
||||
import net.minecraft.world.biome.Biome.Precipitation;
|
||||
import net.minecraft.world.biome.BiomeEffects.GrassColorModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -39,6 +38,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.dfsek.terra.AbstractPlatform;
|
||||
import com.dfsek.terra.addon.EphemeralAddon;
|
||||
@ -68,6 +68,10 @@ public class PlatformImpl extends AbstractPlatform {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public MinecraftServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reload() {
|
||||
getTerraConfig().load(this);
|
||||
@ -157,9 +161,10 @@ public class PlatformImpl extends AbstractPlatform {
|
||||
throw new LoadException("Invalid identifier: " + o, depthTracker);
|
||||
return identifier;
|
||||
})
|
||||
.registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.byName((String) o))
|
||||
.registerLoader(Category.class, (type, o, loader, depthTracker) -> Category.byName((String) o))
|
||||
.registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.byName((String) o));
|
||||
.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)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,10 @@ public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties {
|
||||
@Default
|
||||
private double beardThreshold = 0.5;
|
||||
|
||||
@Value("fabric.beard.air-threshold")
|
||||
@Default
|
||||
private double airThreshold = -0.5;
|
||||
|
||||
public boolean useVanillaBiomes() {
|
||||
return vanillaBiomes;
|
||||
}
|
||||
@ -49,4 +53,8 @@ public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties {
|
||||
public double getBeardThreshold() {
|
||||
return beardThreshold;
|
||||
}
|
||||
|
||||
public double getAirThreshold() {
|
||||
return airThreshold;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.dfsek.terra.fabric.config;
|
||||
import com.dfsek.tectonic.api.config.template.ConfigTemplate;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import net.minecraft.world.biome.Biome.Category;
|
||||
import net.minecraft.world.biome.Biome.Precipitation;
|
||||
import net.minecraft.world.biome.BiomeEffects.GrassColorModifier;
|
||||
|
||||
@ -43,10 +42,6 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties {
|
||||
@Default
|
||||
private Precipitation precipitation = null;
|
||||
|
||||
@Value("climate.category")
|
||||
@Default
|
||||
private Category category = null;
|
||||
|
||||
public Integer getFogColor() {
|
||||
return fogColor;
|
||||
}
|
||||
@ -71,10 +66,6 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties {
|
||||
return skyColor;
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public Precipitation getPrecipitation() {
|
||||
return precipitation;
|
||||
}
|
||||
|
@ -39,32 +39,27 @@ public final class Codecs {
|
||||
.fieldOf("biome_registry")
|
||||
.stable()
|
||||
.forGetter(TerraBiomeSource::getBiomeRegistry),
|
||||
Codec.LONG.fieldOf("seed")
|
||||
.stable()
|
||||
.forGetter(TerraBiomeSource::getSeed),
|
||||
CONFIG_PACK.fieldOf("pack")
|
||||
.stable()
|
||||
.forGetter(TerraBiomeSource::getPack))
|
||||
.apply(instance, instance.stable(TerraBiomeSource::new)));
|
||||
|
||||
public static final Codec<FabricChunkGeneratorWrapper> FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder.create(
|
||||
instance -> instance.group(
|
||||
RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY)
|
||||
.fieldOf("structure_registry")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry),
|
||||
TERRA_BIOME_SOURCE.fieldOf("biome_source")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getBiomeSource),
|
||||
Codec.LONG.fieldOf("seed")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getSeed),
|
||||
CONFIG_PACK.fieldOf("pack")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getPack),
|
||||
ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getSettings)
|
||||
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
|
||||
);
|
||||
public static final Codec<FabricChunkGeneratorWrapper> FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder
|
||||
.create(
|
||||
instance -> instance.group(
|
||||
RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY)
|
||||
.fieldOf("structure_registry")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry),
|
||||
TERRA_BIOME_SOURCE.fieldOf("biome_source")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getBiomeSource),
|
||||
CONFIG_PACK.fieldOf("pack")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getPack),
|
||||
ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings")
|
||||
.stable()
|
||||
.forGetter(FabricChunkGeneratorWrapper::getSettings)
|
||||
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
|
||||
);
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
package com.dfsek.terra.fabric.generation;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.structure.JigsawJunction;
|
||||
import net.minecraft.structure.PoolStructurePiece;
|
||||
import net.minecraft.structure.StructurePiece;
|
||||
import net.minecraft.structure.StructureStart;
|
||||
import net.minecraft.structure.pool.StructurePool.Projection;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.ChunkSectionPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.gen.StructureAccessor;
|
||||
import net.minecraft.world.gen.StructureWeightType;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
|
||||
// net.minecraft.world.gen.StructureWeightSampler
|
||||
public class BeardGenerator {
|
||||
private static final float[] STRUCTURE_WEIGHT_TABLE = Util.make(new float[13824], array -> {
|
||||
for(int i = 0; i < 24; ++i) {
|
||||
for(int j = 0; j < 24; ++j) {
|
||||
for(int k = 0; k < 24; ++k) {
|
||||
array[i * 24 * 24 + j * 24 + k] = (float) calculateStructureWeight(j - 12, k - 12, i - 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
private final ObjectList<StructurePiece> pieces;
|
||||
private final ObjectList<JigsawJunction> junctions;
|
||||
private final ObjectListIterator<StructurePiece> pieceIterator;
|
||||
private final ObjectListIterator<JigsawJunction> junctionIterator;
|
||||
private final Chunk chunk;
|
||||
private final int minY;
|
||||
private final int maxY;
|
||||
|
||||
private final double threshold;
|
||||
|
||||
public BeardGenerator(StructureAccessor structureAccessor, Chunk chunk, double threshold) {
|
||||
this.chunk = chunk;
|
||||
this.threshold = threshold;
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
int i = chunkPos.getStartX();
|
||||
int j = chunkPos.getStartZ();
|
||||
this.junctions = new ObjectArrayList<>(32);
|
||||
this.pieces = new ObjectArrayList<>(10);
|
||||
int minY = chunk.getBottomY();
|
||||
int maxY = chunk.getTopY();
|
||||
for(StructureStart start : structureAccessor.method_41035(ChunkSectionPos.from(chunk),
|
||||
configuredStructureFeature -> configuredStructureFeature.field_37144)) {
|
||||
for(StructurePiece structurePiece : start.getChildren()) {
|
||||
if(!structurePiece.intersectsChunk(chunkPos, 12)) continue;
|
||||
if(structurePiece instanceof PoolStructurePiece poolStructurePiece) {
|
||||
Projection projection = poolStructurePiece.getPoolElement().getProjection();
|
||||
if(projection == Projection.RIGID) {
|
||||
this.pieces.add(poolStructurePiece);
|
||||
}
|
||||
for(JigsawJunction jigsawJunction : poolStructurePiece.getJunctions()) {
|
||||
int k = jigsawJunction.getSourceX();
|
||||
int l = jigsawJunction.getSourceZ();
|
||||
if(k <= i - 12 || l <= j - 12 || k >= i + 15 + 12 || l >= j + 15 + 12) continue;
|
||||
maxY = Math.max(maxY, jigsawJunction.getSourceGroundY());
|
||||
minY = Math.min(minY, jigsawJunction.getSourceGroundY());
|
||||
this.junctions.add(jigsawJunction);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
maxY = Math.max(maxY, structurePiece.getCenter().getY());
|
||||
minY = Math.min(minY, structurePiece.getCenter().getY());
|
||||
this.pieces.add(structurePiece);
|
||||
}
|
||||
}
|
||||
this.pieceIterator = this.pieces.iterator();
|
||||
this.junctionIterator = this.junctions.iterator();
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
}
|
||||
|
||||
private static double getMagnitudeWeight(int x, int y, int z) {
|
||||
double d = MathHelper.magnitude(x, (double) y / 2.0, z);
|
||||
return MathHelper.clampedLerpFromProgress(d, 0.0, 6.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the structure weight from the array from the given position, or 0 if the position is out of bounds.
|
||||
*/
|
||||
private static double getStructureWeight(int x, int y, int z) {
|
||||
int xOffset = x + 12;
|
||||
int yOffset = y + 12;
|
||||
int zOffset = z + 12;
|
||||
if(xOffset < 0 || xOffset >= 24) {
|
||||
return 0.0;
|
||||
}
|
||||
if(yOffset < 0 || yOffset >= 24) {
|
||||
return 0.0;
|
||||
}
|
||||
if(zOffset < 0 || zOffset >= 24) {
|
||||
return 0.0;
|
||||
}
|
||||
return STRUCTURE_WEIGHT_TABLE[zOffset * 24 * 24 + xOffset * 24 + yOffset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the structure weight for the given position.
|
||||
* <p>The weight increases as x and z approach {@code (0, 0)}, and positive y values make the weight negative while negative y
|
||||
* values make the weight positive.
|
||||
*/
|
||||
private static double calculateStructureWeight(int x, int y, int z) {
|
||||
double horizontalDistanceSquared = x * x + z * z;
|
||||
double yOffset = y + 0.5;
|
||||
double verticalSquared = yOffset * yOffset;
|
||||
double naturalDistance = Math.pow(Math.E, -(verticalSquared / 16.0 + horizontalDistanceSquared / 16.0));
|
||||
double inverseSquareRootDistance = -yOffset * MathHelper.fastInverseSqrt(verticalSquared / 2.0 + horizontalDistanceSquared / 2.0) /
|
||||
2.0;
|
||||
return inverseSquareRootDistance * naturalDistance;
|
||||
}
|
||||
|
||||
public void generate(ChunkGenerator generator, WorldProperties worldProperties, BiomeProvider biomeProvider) {
|
||||
int xi = chunk.getPos().x << 4;
|
||||
int zi = chunk.getPos().z << 4;
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
int depth = 0;
|
||||
for(int y = maxY; y >= minY; y--) {
|
||||
if(calculateNoise(x + xi, y, z + zi) > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), (BlockState) generator
|
||||
.getPalette(x + xi, y, z + zi, worldProperties, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, worldProperties.getSeed()), false);
|
||||
depth++;
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double calculateNoise(int x, int y, int z) {
|
||||
double noise = 0.0;
|
||||
|
||||
while(this.pieceIterator.hasNext()) {
|
||||
StructurePiece structurePiece = this.pieceIterator.next();
|
||||
BlockBox blockBox = structurePiece.getBoundingBox();
|
||||
int structureX = Math.max(0, Math.max(blockBox.getMinX() - x, x - blockBox.getMaxX()));
|
||||
int structureY = y - (blockBox.getMinY() + (structurePiece instanceof PoolStructurePiece
|
||||
? ((PoolStructurePiece) structurePiece).getGroundLevelDelta()
|
||||
: 0));
|
||||
int structureZ = Math.max(0, Math.max(blockBox.getMinZ() - z, z - blockBox.getMaxZ()));
|
||||
StructureWeightType structureWeightType = structurePiece.getWeightType();
|
||||
if(structureWeightType == StructureWeightType.BURY) {
|
||||
noise += getMagnitudeWeight(structureX, structureY, structureZ);
|
||||
continue;
|
||||
}
|
||||
if(structureWeightType != StructureWeightType.BEARD) continue;
|
||||
|
||||
noise += getStructureWeight(structureX, structureY, structureZ) * 0.8;
|
||||
}
|
||||
this.pieceIterator.back(this.pieces.size());
|
||||
while(this.junctionIterator.hasNext()) {
|
||||
JigsawJunction structurePiece = this.junctionIterator.next();
|
||||
int structureX = x - structurePiece.getSourceX();
|
||||
int structureY = y - structurePiece.getSourceGroundY();
|
||||
int structureZ = z - structurePiece.getSourceZ();
|
||||
noise += getStructureWeight(structureX, structureY, structureZ) * 0.4;
|
||||
}
|
||||
this.junctionIterator.back(this.junctions.size());
|
||||
return noise;
|
||||
}
|
||||
}
|
@ -17,32 +17,34 @@
|
||||
|
||||
package com.dfsek.terra.fabric.generation;
|
||||
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.structure.StructureSet;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.random.CheckedRandom;
|
||||
import net.minecraft.util.math.random.ChunkRandom;
|
||||
import net.minecraft.util.math.random.RandomSeed;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.ChunkRegion;
|
||||
import net.minecraft.world.HeightLimitView;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.Heightmap.Type;
|
||||
import net.minecraft.world.SpawnHelper;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.source.BiomeAccess;
|
||||
import net.minecraft.world.biome.source.util.MultiNoiseUtil;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.GenerationStep.Carver;
|
||||
import net.minecraft.world.gen.StructureAccessor;
|
||||
import net.minecraft.world.gen.StructureWeightSampler;
|
||||
import net.minecraft.world.gen.chunk.Blender;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
import net.minecraft.world.gen.chunk.VerticalBlockSample;
|
||||
import net.minecraft.world.gen.random.AtomicSimpleRandom;
|
||||
import net.minecraft.world.gen.random.ChunkRandom;
|
||||
import net.minecraft.world.gen.random.RandomSeed;
|
||||
import net.minecraft.world.gen.densityfunction.DensityFunction.UnblendedNoisePos;
|
||||
import net.minecraft.world.gen.noise.NoiseConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -58,6 +60,7 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
||||
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;
|
||||
@ -67,16 +70,15 @@ import com.dfsek.terra.fabric.util.FabricAdapter;
|
||||
public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper {
|
||||
private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class);
|
||||
|
||||
private final long seed;
|
||||
private final TerraBiomeSource biomeSource;
|
||||
private final Registry<StructureSet> noiseRegistry;
|
||||
private final RegistryEntry<ChunkGeneratorSettings> settings;
|
||||
private ChunkGenerator delegate;
|
||||
private ConfigPack pack;
|
||||
|
||||
public FabricChunkGeneratorWrapper(Registry<StructureSet> noiseRegistry, TerraBiomeSource biomeSource, long seed, ConfigPack configPack,
|
||||
public FabricChunkGeneratorWrapper(Registry<StructureSet> noiseRegistry, TerraBiomeSource biomeSource, ConfigPack configPack,
|
||||
RegistryEntry<ChunkGeneratorSettings> settingsSupplier) {
|
||||
super(noiseRegistry, Optional.empty(), biomeSource, biomeSource, seed);
|
||||
super(noiseRegistry, Optional.empty(), biomeSource);
|
||||
this.noiseRegistry = noiseRegistry;
|
||||
this.pack = configPack;
|
||||
this.settings = settingsSupplier;
|
||||
@ -84,8 +86,6 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
logger.info("Loading world with config pack {}", pack.getID());
|
||||
this.biomeSource = biomeSource;
|
||||
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
public Registry<StructureSet> getNoiseRegistry() {
|
||||
@ -96,29 +96,21 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
protected Codec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() {
|
||||
return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.gen.chunk.ChunkGenerator withSeed(long seed) {
|
||||
return new FabricChunkGeneratorWrapper(noiseRegistry, (TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiNoiseUtil.MultiNoiseSampler getMultiNoiseSampler() {
|
||||
return MultiNoiseUtil.method_40443(); // zero
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(ChunkRegion region, StructureAccessor structures, Chunk chunk) {
|
||||
public void buildSurface(ChunkRegion region, StructureAccessor structures, NoiseConfig noiseConfig, Chunk chunk) {
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateEntities(ChunkRegion region) {
|
||||
ChunkPos chunkPos = region.getCenterPos();
|
||||
RegistryEntry<Biome> biome = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1));
|
||||
ChunkRandom chunkRandom = new ChunkRandom(new AtomicSimpleRandom(RandomSeed.getSeed()));
|
||||
chunkRandom.setPopulationSeed(region.getSeed(), chunkPos.getStartX(), chunkPos.getStartZ());
|
||||
SpawnHelper.populateEntities(region, biome, chunkPos, chunkRandom);
|
||||
if (!this.settings.value().mobGenerationDisabled()) {
|
||||
ChunkPos chunkPos = region.getCenterPos();
|
||||
RegistryEntry<Biome> registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1));
|
||||
ChunkRandom chunkRandom = new ChunkRandom(new CheckedRandom(RandomSeed.getSeed()));
|
||||
chunkRandom.setPopulationSeed(region.getSeed(), chunkPos.getStartX(), chunkPos.getStartZ());
|
||||
SpawnHelper.populateEntities(region, registryEntry, chunkPos, chunkRandom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,20 +118,49 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
return settings.value().generationShapeConfig().height();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Chunk> populateNoise(Executor executor, Blender arg, StructureAccessor structureAccessor, Chunk chunk) {
|
||||
public CompletableFuture<Chunk> populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig,
|
||||
StructureAccessor structureAccessor, Chunk chunk) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(world);
|
||||
delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z);
|
||||
|
||||
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
new BeardGenerator(structureAccessor, chunk, compatibilityOptions.getBeardThreshold()).generate(delegate, world,
|
||||
biomeProvider);
|
||||
beard(structureAccessor, chunk, world, biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return chunk;
|
||||
}, executor);
|
||||
}, Util.getMainWorkerExecutor());
|
||||
}
|
||||
|
||||
private void beard(StructureAccessor structureAccessor, Chunk chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
StructureWeightSampler structureWeightSampler = StructureWeightSampler.method_42695(structureAccessor, chunk.getPos());
|
||||
double threshold = compatibilityOptions.getBeardThreshold();
|
||||
double airThreshold = compatibilityOptions.getAirThreshold();
|
||||
int xi = chunk.getPos().x << 4;
|
||||
int zi = chunk.getPos().z << 4;
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
int depth = 0;
|
||||
for(int y = world.getMaxHeight(); y >= world.getMinHeight(); y--) {
|
||||
double noise = structureWeightSampler.sample(new UnblendedNoisePos(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), (BlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed()), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.getDefaultState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -162,10 +183,11 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
return settings.value().generationShapeConfig().minimumY();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView height) {
|
||||
public int getHeight(int x, int z, Type heightmap, HeightLimitView height, NoiseConfig noiseConfig) {
|
||||
int y = height.getTopY();
|
||||
WorldProperties properties = FabricAdapter.adapt(height, seed);
|
||||
WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
|
||||
while(y >= getMinimumY() && !heightmap.getBlockPredicate().test(
|
||||
(BlockState) delegate.getBlock(properties, x, y - 1, z, biomeProvider))) {
|
||||
@ -175,9 +197,9 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height) {
|
||||
public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height, NoiseConfig noiseConfig) {
|
||||
BlockState[] array = new BlockState[height.getHeight()];
|
||||
WorldProperties properties = FabricAdapter.adapt(height, seed);
|
||||
WorldProperties properties = FabricAdapter.adapt(height, noiseConfig.getLegacyWorldSeed());
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
|
||||
for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) {
|
||||
array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider);
|
||||
@ -186,7 +208,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDebugHudText(List<String> text, BlockPos pos) {
|
||||
public void getDebugHudText(List<String> text, NoiseConfig noiseConfig, BlockPos pos) {
|
||||
|
||||
}
|
||||
|
||||
@ -203,9 +225,9 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
}
|
||||
|
||||
@Override
|
||||
public void carve(ChunkRegion chunkRegion, long seed, BiomeAccess biomeAccess, StructureAccessor structureAccessor, Chunk chunk,
|
||||
GenerationStep.Carver generationStep) {
|
||||
|
||||
public void carve(ChunkRegion chunkRegion, long seed, NoiseConfig noiseConfig, BiomeAccess world, StructureAccessor structureAccessor,
|
||||
Chunk chunk, Carver carverStep) {
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -213,10 +235,6 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
public RegistryEntry<ChunkGeneratorSettings> getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
@ -22,7 +22,11 @@ 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.fabric.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;
|
||||
@ -30,6 +34,7 @@ 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;
|
||||
|
||||
|
||||
@ -37,17 +42,15 @@ public class TerraBiomeSource extends BiomeSource {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TerraBiomeSource.class);
|
||||
private final Registry<net.minecraft.world.biome.Biome> biomeRegistry;
|
||||
private final long seed;
|
||||
private ConfigPack pack;
|
||||
|
||||
public TerraBiomeSource(Registry<net.minecraft.world.biome.Biome> biomes, long seed, ConfigPack pack) {
|
||||
public TerraBiomeSource(Registry<net.minecraft.world.biome.Biome> biomes, ConfigPack pack) {
|
||||
super(StreamSupport
|
||||
.stream(pack.getBiomeProvider()
|
||||
.getBiomes()
|
||||
.spliterator(), false)
|
||||
.map(b -> biomes.getOrCreateEntry(((ProtoPlatformBiome) b.getPlatformBiome()).getDelegate())));
|
||||
this.biomeRegistry = biomes;
|
||||
this.seed = seed;
|
||||
this.pack = pack;
|
||||
|
||||
LOGGER.debug("Biomes: " + getBiomes());
|
||||
@ -58,17 +61,12 @@ public class TerraBiomeSource extends BiomeSource {
|
||||
return Codecs.TERRA_BIOME_SOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeSource withSeed(long seed) {
|
||||
return new TerraBiomeSource(this.biomeRegistry, seed, pack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntry<net.minecraft.world.biome.Biome> getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) {
|
||||
return biomeRegistry
|
||||
.entryOf(((ProtoPlatformBiome) pack
|
||||
.getBiomeProvider()
|
||||
.getBiome(biomeX << 2, biomeY << 2, biomeZ << 2, seed)
|
||||
.getBiome(biomeX << 2, biomeY << 2, biomeZ << 2, SeedHack.getSeed(noiseSampler))
|
||||
.getPlatformBiome()).getDelegate()
|
||||
);
|
||||
}
|
||||
@ -88,8 +86,4 @@ public class TerraBiomeSource extends BiomeSource {
|
||||
public void setPack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +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.generation;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.world.GeneratorType;
|
||||
import net.minecraft.structure.StructureSet;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class TerraGeneratorType extends GeneratorType {
|
||||
private final ConfigPack pack;
|
||||
|
||||
public TerraGeneratorType(ConfigPack pack) {
|
||||
super("terra." + pack.getID());
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChunkGenerator getChunkGenerator(DynamicRegistryManager manager, long seed) {
|
||||
Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry = manager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY);
|
||||
RegistryEntry<ChunkGeneratorSettings>
|
||||
settingsSupplier = chunkGeneratorSettingsRegistry.getEntry(ChunkGeneratorSettings.OVERWORLD).orElseThrow();
|
||||
Registry<StructureSet> noiseRegistry = manager.get(Registry.STRUCTURE_SET_KEY);
|
||||
return new FabricChunkGeneratorWrapper(noiseRegistry, new TerraBiomeSource(manager.get(Registry.BIOME_KEY), seed, pack), seed, pack,
|
||||
settingsSupplier);
|
||||
}
|
||||
}
|
@ -17,8 +17,11 @@
|
||||
|
||||
package com.dfsek.terra.fabric.handle;
|
||||
|
||||
import com.dfsek.terra.fabric.FabricEntryPoint;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.command.CommandRegistryAccess;
|
||||
import net.minecraft.command.argument.ItemStackArgumentType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
@ -36,7 +39,7 @@ public class FabricItemHandle implements ItemHandle {
|
||||
@Override
|
||||
public Item createItem(String data) {
|
||||
try {
|
||||
return (Item) new ItemStackArgumentType().parse(new StringReader(data)).getItem();
|
||||
return (Item) new ItemStackArgumentType(new CommandRegistryAccess(FabricEntryPoint.getPlatform().getServer().getRegistryManager())).parse(new StringReader(data)).getItem();
|
||||
} catch(CommandSyntaxException e) {
|
||||
throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e);
|
||||
}
|
||||
|
@ -17,11 +17,14 @@
|
||||
|
||||
package com.dfsek.terra.fabric.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;
|
||||
|
||||
@ -36,9 +39,8 @@ public class FabricWorldHandle implements WorldHandle {
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState createBlockState(@NotNull String data) {
|
||||
BlockArgumentParser parser = new BlockArgumentParser(new StringReader(data), true);
|
||||
try {
|
||||
net.minecraft.block.BlockState state = parser.parse(true).getBlockState();
|
||||
net.minecraft.block.BlockState state = BlockArgumentParser.block(Registry.BLOCK, data, true).blockState();
|
||||
if(state == null) throw new IllegalArgumentException("Invalid data: " + data);
|
||||
return (BlockState) state;
|
||||
} catch(CommandSyntaxException e) {
|
||||
|
@ -0,0 +1,25 @@
|
||||
package com.dfsek.terra.fabric.mixin;
|
||||
|
||||
import com.dfsek.terra.fabric.FabricEntryPoint;
|
||||
|
||||
import net.minecraft.server.command.ReloadCommand;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import org.checkerframework.checker.units.qual.A;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
@Mixin(ReloadCommand.class)
|
||||
public class ReloadCommandMixin {
|
||||
@Inject(method = "tryReloadDataPacks", at = @At("HEAD"))
|
||||
private static void inject(Collection<String> dataPacks, ServerCommandSource source, CallbackInfo ci) {
|
||||
source.sendFeedback(Text.literal("Reloading Terra..."), true);
|
||||
FabricEntryPoint.getPlatform().reload();
|
||||
source.sendFeedback(Text.literal("Done."), true);
|
||||
}
|
||||
}
|
@ -1,39 +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.mixin.access;
|
||||
|
||||
import net.minecraft.client.world.GeneratorType;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Mixin(GeneratorType.class)
|
||||
public interface GeneratorTypeAccessor {
|
||||
@Accessor("VALUES")
|
||||
static List<GeneratorType> getValues() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Mutable
|
||||
@Accessor("displayName")
|
||||
void setDisplayName(Text translationKey);
|
||||
}
|
@ -18,7 +18,6 @@
|
||||
package com.dfsek.terra.fabric.mixin.implementations.block.entity;
|
||||
|
||||
import net.minecraft.block.entity.SignBlockEntity;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
@ -42,19 +41,19 @@ public abstract class SignBlockEntityMixin {
|
||||
public abstract void setTextOnRow(int row, Text text);
|
||||
|
||||
public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
|
||||
setTextOnRow(index, new LiteralText(line));
|
||||
setTextOnRow(index, Text.literal(line));
|
||||
}
|
||||
|
||||
public @NotNull String[] terra$getLines() {
|
||||
String[] lines = new String[texts.length];
|
||||
for(int i = 0; i < texts.length; i++) {
|
||||
lines[i] = texts[i].asString();
|
||||
lines[i] = texts[i].getString();
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException {
|
||||
return texts[index].asString();
|
||||
return texts[index].getString();
|
||||
}
|
||||
|
||||
public void terra$applyState(String state) {
|
||||
|
@ -44,9 +44,6 @@ public abstract class EntityMixin {
|
||||
@Shadow
|
||||
public abstract void teleport(double destX, double destY, double destZ);
|
||||
|
||||
@Shadow
|
||||
public abstract void sendSystemMessage(Text message, UUID senderUuid);
|
||||
|
||||
public Vector3 terra$position() {
|
||||
return FabricAdapter.adapt(blockPos);
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ package com.dfsek.terra.fabric.mixin.implementations.entity;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Implements;
|
||||
@ -49,7 +48,7 @@ public abstract class ServerCommandSourceMixin {
|
||||
public abstract net.minecraft.entity.@Nullable Entity getEntity();
|
||||
|
||||
public void terra$sendMessage(String message) {
|
||||
sendFeedback(new LiteralText(message), true);
|
||||
sendFeedback(Text.literal(message), true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -81,10 +81,8 @@ public abstract class ChunkRegionMixin {
|
||||
this.config = ((ServerWorld) world).getPack();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Entity terraWorld$spawnEntity(Vector3 location, EntityType entityType) {
|
||||
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(
|
||||
((ChunkRegion) (Object) this).toServerWorld());
|
||||
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(null);
|
||||
entity.setPos(location.getX(), location.getY(), location.getZ());
|
||||
((ChunkRegion) (Object) this).spawnEntity(entity);
|
||||
return (Entity) entity;
|
||||
|
@ -42,8 +42,7 @@ import com.dfsek.terra.fabric.util.FabricUtil;
|
||||
@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$"))
|
||||
public abstract class ServerWorldMixin {
|
||||
public Entity terra$spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(
|
||||
((net.minecraft.server.world.ServerWorld) (Object) this));
|
||||
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(null);
|
||||
entity.setPos(x, y, z);
|
||||
((net.minecraft.server.world.ServerWorld) (Object) this).spawnEntity(entity);
|
||||
return (Entity) entity;
|
||||
|
@ -19,8 +19,10 @@ public class DataPackContentsMixin {
|
||||
*/
|
||||
@Inject(method = "refresh(Lnet/minecraft/util/registry/DynamicRegistryManager;)V", at = @At("RETURN"))
|
||||
private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) {
|
||||
TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(Registry.WORLD_PRESET_KEY));
|
||||
|
||||
Registry<Biome> biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY);
|
||||
TagUtil.registerTags(biomeRegistry);
|
||||
TagUtil.registerBiomeTags(biomeRegistry);
|
||||
BiomeUtil.registerFlora(biomeRegistry);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import net.minecraft.resource.ResourcePackManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.SaveLoader;
|
||||
import net.minecraft.server.WorldGenerationProgressListenerFactory;
|
||||
import net.minecraft.util.ApiServices;
|
||||
import net.minecraft.util.UserCache;
|
||||
import net.minecraft.world.level.storage.LevelStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@ -23,13 +24,11 @@ import com.dfsek.terra.fabric.FabricEntryPoint;
|
||||
public class MinecraftServerMixin {
|
||||
@Inject(method = "<init>(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" +
|
||||
"Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" +
|
||||
"Lcom/mojang/datafixers/DataFixer;Lcom/mojang/authlib/minecraft/MinecraftSessionService;" +
|
||||
"Lcom/mojang/authlib/GameProfileRepository;Lnet/minecraft/util/UserCache;" +
|
||||
"Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/util/ApiServices;" +
|
||||
"Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V",
|
||||
at = @At("RETURN"))
|
||||
private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager,
|
||||
SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, MinecraftSessionService sessionService,
|
||||
GameProfileRepository gameProfileRepo, UserCache userCache,
|
||||
SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices,
|
||||
WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) {
|
||||
FabricEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this);
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package com.dfsek.terra.fabric.mixin.lifecycle;
|
||||
|
||||
import com.dfsek.terra.fabric.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;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Hack to map noise sampler to seeds
|
||||
*/
|
||||
@Mixin(NoiseConfig.class)
|
||||
public class NoiseConfigMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private MultiNoiseSampler multiNoiseSampler;
|
||||
|
||||
@Inject(method = "<init>(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/util/registry/Registry;J)V", at = @At("TAIL"))
|
||||
private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, Registry<DoublePerlinNoiseSampler.NoiseParameters> noiseRegistry, long seed, CallbackInfo ci) {
|
||||
SeedHack.register(multiNoiseSampler, seed);
|
||||
}
|
||||
}
|
@ -17,11 +17,10 @@
|
||||
|
||||
package com.dfsek.terra.fabric.mixin.lifecycle.client;
|
||||
|
||||
import com.dfsek.terra.fabric.util.BiomeUtil;
|
||||
import com.dfsek.terra.fabric.util.LifecycleUtil;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.RunArgs;
|
||||
import net.minecraft.client.world.GeneratorType;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@ -29,8 +28,7 @@ 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.generation.TerraGeneratorType;
|
||||
import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor;
|
||||
import com.dfsek.terra.fabric.util.BiomeUtil;
|
||||
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
@ -42,13 +40,6 @@ public class MinecraftClientMixin {
|
||||
// sorta arbitrary position, after mod init, before window opens
|
||||
shift = At.Shift.BEFORE))
|
||||
public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) {
|
||||
FabricEntryPoint.getPlatform().getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> {
|
||||
final GeneratorType generatorType = new TerraGeneratorType(pack);
|
||||
//noinspection ConstantConditions
|
||||
((GeneratorTypeAccessor) generatorType).setDisplayName(new LiteralText("Terra:" + pack.getID()));
|
||||
GeneratorTypeAccessor.getValues().add(1, generatorType);
|
||||
});
|
||||
BiomeUtil.registerBiomes();
|
||||
LifecycleUtil.initialize();
|
||||
}
|
||||
}
|
||||
|
@ -1,111 +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.mixin.lifecycle.server;
|
||||
|
||||
import net.minecraft.server.dedicated.ServerPropertiesHandler;
|
||||
import net.minecraft.structure.StructureSet;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.GeneratorOptions;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.fabric.FabricEntryPoint;
|
||||
import com.dfsek.terra.fabric.PlatformImpl;
|
||||
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
|
||||
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
|
||||
|
||||
|
||||
@Mixin(GeneratorOptions.class)
|
||||
public abstract class GeneratorOptionsMixin {
|
||||
@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;" +
|
||||
"Lnet/minecraft/server/dedicated/ServerPropertiesHandler$WorldGenProperties;)" +
|
||||
"Lnet/minecraft/world/gen/GeneratorOptions;",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true)
|
||||
private static void fromProperties(DynamicRegistryManager manager,
|
||||
ServerPropertiesHandler.WorldGenProperties properties,
|
||||
CallbackInfoReturnable<GeneratorOptions> cir) {
|
||||
if(properties.levelType() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlatformImpl main = FabricEntryPoint.getPlatform();
|
||||
|
||||
String levelType = properties.levelType();
|
||||
|
||||
if(levelType.toLowerCase(Locale.ROOT).startsWith("terra")) {
|
||||
String seedProperty = properties.levelSeed();
|
||||
long seed = new Random().nextLong();
|
||||
if(seedProperty != null) {
|
||||
try {
|
||||
long m = Long.parseLong(seedProperty);
|
||||
if(m != 0L) {
|
||||
seed = m;
|
||||
}
|
||||
} catch(NumberFormatException exception) {
|
||||
seed = seedProperty.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
boolean generateStructures = properties.generateStructures();
|
||||
Registry<DimensionType> dimensionTypes = manager.get(Registry.DIMENSION_TYPE_KEY);
|
||||
Registry<Biome> biomeRegistry = manager.get(Registry.BIOME_KEY);
|
||||
Registry<DimensionOptions> dimensionOptions = DimensionType.createDefaultDimensionOptions(manager, seed, false);
|
||||
|
||||
Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry = manager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY);
|
||||
RegistryEntry<ChunkGeneratorSettings>
|
||||
settingsSupplier = chunkGeneratorSettingsRegistry.getEntry(ChunkGeneratorSettings.OVERWORLD).orElseThrow();
|
||||
Registry<StructureSet> noiseRegistry = manager.get(Registry.STRUCTURE_SET_KEY);
|
||||
|
||||
String pack = levelType.substring(levelType.indexOf(":") + 1);
|
||||
|
||||
CheckedRegistry<ConfigPack> configRegistry = main.getConfigRegistry();
|
||||
ConfigPack config = configRegistry
|
||||
.getByID(pack)
|
||||
.or(() -> configRegistry.getByID(pack.toUpperCase(Locale.ROOT)))
|
||||
.orElseThrow(() -> new IllegalArgumentException("No such pack " + pack));
|
||||
|
||||
cir.setReturnValue(
|
||||
new GeneratorOptions(seed,
|
||||
generateStructures,
|
||||
false,
|
||||
GeneratorOptions
|
||||
.getRegistryWithReplacedOverworldGenerator(
|
||||
dimensionTypes,
|
||||
dimensionOptions,
|
||||
new FabricChunkGeneratorWrapper(noiseRegistry,
|
||||
new TerraBiomeSource(biomeRegistry, seed, config),
|
||||
seed,
|
||||
config,
|
||||
settingsSupplier))));
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@
|
||||
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;
|
||||
@ -37,9 +39,6 @@ public class ServerMainMixin {
|
||||
// after registry manager creation
|
||||
)
|
||||
private static void injectConstructor(String[] args, CallbackInfo ci) {
|
||||
FabricEntryPoint.getPlatform().getEventManager().callEvent(
|
||||
new PlatformInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks
|
||||
// and stuff
|
||||
BiomeUtil.registerBiomes();
|
||||
LifecycleUtil.initialize();
|
||||
}
|
||||
}
|
||||
|
@ -137,12 +137,9 @@ public final class BiomeUtil {
|
||||
effects.foliageColor(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
|
||||
builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation()))
|
||||
.category(Objects.requireNonNullElse(vanillaBiomeProperties.getCategory(), vanilla.getCategory()));
|
||||
builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation()));
|
||||
|
||||
} else {
|
||||
|
||||
effects.waterColor(vanilla.getWaterColor())
|
||||
.waterFogColor(vanilla.getWaterFogColor())
|
||||
.fogColor(vanilla.getFogColor())
|
||||
@ -150,11 +147,9 @@ public final class BiomeUtil {
|
||||
vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor);
|
||||
vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor);
|
||||
|
||||
builder.precipitation(vanilla.getPrecipitation())
|
||||
.category(vanilla.getCategory());
|
||||
builder.precipitation(vanilla.getPrecipitation());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return builder
|
||||
.temperature(vanilla.getTemperature())
|
||||
.downfall(vanilla.getDownfall())
|
||||
|
@ -0,0 +1,100 @@
|
||||
package com.dfsek.terra.fabric.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 net.minecraft.structure.StructureSet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters;
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.source.MultiNoiseBiomeSource;
|
||||
import net.minecraft.world.biome.source.TheEndBiomeSource;
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.dimension.DimensionTypes;
|
||||
import net.minecraft.world.gen.WorldPreset;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
import net.minecraft.world.gen.chunk.NoiseChunkGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class LifecycleUtil {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleUtil.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...");
|
||||
|
||||
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);
|
||||
DimensionOptions netherDimensionOptions = new DimensionOptions(theNetherDimensionType,
|
||||
new NoiseChunkGenerator(structureSetRegistry,
|
||||
noiseParametersRegistry,
|
||||
MultiNoiseBiomeSource.Preset.NETHER.getBiomeSource(
|
||||
biomeRegistry),
|
||||
netherChunkGeneratorSettings));
|
||||
RegistryEntry<DimensionType> theEndDimensionType = dimensionTypeRegistry.getOrCreateEntry(DimensionTypes.THE_END);
|
||||
RegistryEntry<ChunkGeneratorSettings> endChunkGeneratorSettings = chunkGeneratorSettingsRegistry.getOrCreateEntry(
|
||||
ChunkGeneratorSettings.END);
|
||||
DimensionOptions endDimensionOptions = new DimensionOptions(theEndDimensionType,
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static List<Identifier> getPresets() {
|
||||
return PRESETS;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.dfsek.terra.fabric.util;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
|
||||
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Holder for hacky biome source seed workaround
|
||||
*/
|
||||
public class SeedHack {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SeedHack.class);
|
||||
|
||||
private static final Object2LongMap<MultiNoiseSampler> seedMap = new Object2LongOpenHashMap<>();
|
||||
|
||||
public static long getSeed(MultiNoiseSampler sampler) {
|
||||
if(!seedMap.containsKey(sampler)) {
|
||||
throw new IllegalArgumentException("Sampler is not registered: " + sampler);
|
||||
}
|
||||
return seedMap.getLong(sampler);
|
||||
}
|
||||
|
||||
public static void register(MultiNoiseSampler sampler, long seed) {
|
||||
LOGGER.info("Registered seed {} to sampler {}", seed, sampler.hashCode());
|
||||
seedMap.put(sampler, seed);
|
||||
}
|
||||
}
|
@ -2,9 +2,11 @@ package com.dfsek.terra.fabric.util;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.tag.TagKey;
|
||||
import net.minecraft.tag.WorldPresetTags;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.WorldPreset;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -21,48 +23,72 @@ public final class TagUtil {
|
||||
|
||||
}
|
||||
|
||||
public static void registerTags(Registry<Biome> registry) {
|
||||
logger.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<RegistryEntry<Biome>>> collect = registry
|
||||
private static <T> Map<TagKey<T>, List<RegistryEntry<T>>> tagsToMutableMap(Registry<T> registry) {
|
||||
return registry
|
||||
.streamTagsAndEntries()
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
}
|
||||
|
||||
public static void registerWorldPresetTags(Registry<WorldPreset> registry) {
|
||||
logger.info("Doing preset tag garbage....");
|
||||
Map<TagKey<WorldPreset>, List<RegistryEntry<WorldPreset>>> collect = tagsToMutableMap(registry);
|
||||
|
||||
LifecycleUtil
|
||||
.getPresets()
|
||||
.forEach(id -> FabricUtil
|
||||
.getEntry(registry, id)
|
||||
.ifPresentOrElse(
|
||||
preset -> collect
|
||||
.computeIfAbsent(WorldPresetTags.NORMAL, tag -> new ArrayList<>())
|
||||
.add(preset),
|
||||
() -> logger.error("Preset {} does not exist!", id)));
|
||||
|
||||
registry.clearTags();
|
||||
registry.populateTags(ImmutableMap.copyOf(collect));
|
||||
}
|
||||
|
||||
public static void registerBiomeTags(Registry<Biome> registry) {
|
||||
logger.info("Doing biome tag garbage....");
|
||||
Map<TagKey<Biome>, List<RegistryEntry<Biome>>> collect = tagsToMutableMap(registry);
|
||||
|
||||
BiomeUtil
|
||||
.getTerraBiomeMap()
|
||||
.forEach((vb, terraBiomes) ->
|
||||
FabricUtil.getEntry(registry, vb)
|
||||
.ifPresentOrElse(vanilla -> terraBiomes
|
||||
.forEach(tb -> FabricUtil
|
||||
.getEntry(registry, tb)
|
||||
.ifPresentOrElse(
|
||||
terra -> {
|
||||
logger.debug(
|
||||
vanilla.getKey()
|
||||
.orElseThrow()
|
||||
.getValue() +
|
||||
" (vanilla for " +
|
||||
terra.getKey()
|
||||
.orElseThrow()
|
||||
.getValue() +
|
||||
": " +
|
||||
vanilla.streamTags()
|
||||
.toList());
|
||||
|
||||
vanilla.streamTags()
|
||||
.forEach(
|
||||
tag -> collect
|
||||
.computeIfAbsent(
|
||||
tag,
|
||||
t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> logger.error(
|
||||
"No such biome: {}",
|
||||
tb))),
|
||||
() -> logger.error("No vanilla biome: {}", vb)));
|
||||
FabricUtil
|
||||
.getEntry(registry, vb)
|
||||
.ifPresentOrElse(
|
||||
vanilla -> terraBiomes
|
||||
.forEach(tb -> FabricUtil
|
||||
.getEntry(registry, tb)
|
||||
.ifPresentOrElse(
|
||||
terra -> {
|
||||
logger.debug(
|
||||
vanilla.getKey()
|
||||
.orElseThrow()
|
||||
.getValue() +
|
||||
" (vanilla for " +
|
||||
terra.getKey()
|
||||
.orElseThrow()
|
||||
.getValue() +
|
||||
": " +
|
||||
vanilla.streamTags()
|
||||
.toList());
|
||||
|
||||
vanilla.streamTags()
|
||||
.forEach(
|
||||
tag -> collect
|
||||
.computeIfAbsent(
|
||||
tag,
|
||||
t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> logger.error(
|
||||
"No such biome: {}",
|
||||
tb))),
|
||||
() -> logger.error("No vanilla biome: {}", vb)));
|
||||
|
||||
registry.clearTags();
|
||||
registry.populateTags(ImmutableMap.copyOf(collect));
|
||||
|
@ -26,7 +26,7 @@
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.2",
|
||||
"java": ">=17",
|
||||
"minecraft": "1.18.x"
|
||||
"minecraft": "1.19.x"
|
||||
},
|
||||
"accessWidener": "terra.accesswidener"
|
||||
}
|
@ -1,5 +1 @@
|
||||
accessWidener v1 named
|
||||
|
||||
extendable method net/minecraft/client/world/GeneratorType <init> (Ljava/lang/String;)V
|
||||
|
||||
accessible method net/minecraft/world/biome/Biome getCategory ()Lnet/minecraft/world/biome/Biome$Category;
|
||||
|
@ -1,51 +1,51 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "com.dfsek.terra.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"access.MobSpawnerLogicAccessor",
|
||||
"access.StateAccessor",
|
||||
"access.StructureAccessorAccessor",
|
||||
"compat.GenerationSettingsFloraFeaturesMixin",
|
||||
"implementations.BiomeMixin",
|
||||
"implementations.HandleImplementationMixin",
|
||||
"implementations.block.BlockMixin",
|
||||
"implementations.block.entity.BlockEntityMixin",
|
||||
"implementations.block.entity.LootableContainerBlockEntityMixin",
|
||||
"implementations.block.entity.MobSpawnerBlockEntityMixin",
|
||||
"implementations.block.entity.SignBlockEntityMixin",
|
||||
"implementations.block.state.BlockStateMixin",
|
||||
"implementations.block.state.PropertyMixin",
|
||||
"implementations.chunk.ChunkRegionMixin",
|
||||
"implementations.chunk.WorldChunkMixin",
|
||||
"implementations.chunk.data.ProtoChunkMixin",
|
||||
"implementations.entity.EntityMixin",
|
||||
"implementations.entity.EntityTypeMixin",
|
||||
"implementations.entity.PlayerEntityMixin",
|
||||
"implementations.entity.ServerCommandSourceMixin",
|
||||
"implementations.inventory.LockableContainerBlockEntityMixin",
|
||||
"implementations.inventory.item.ItemMixin",
|
||||
"implementations.inventory.item.ItemStackMixin",
|
||||
"implementations.inventory.meta.EnchantmentMixin",
|
||||
"implementations.inventory.meta.ItemStackDamageableMixin",
|
||||
"implementations.inventory.meta.ItemStackMetaMixin",
|
||||
"implementations.world.ChunkRegionMixin",
|
||||
"implementations.world.ServerWorldMixin",
|
||||
"lifecycle.DataPackContentsMixin",
|
||||
"lifecycle.MinecraftServerMixin",
|
||||
"lifecycle.RegistryMixin"
|
||||
],
|
||||
"client": [
|
||||
"access.GeneratorTypeAccessor",
|
||||
"lifecycle.client.MinecraftClientMixin"
|
||||
],
|
||||
"server": [
|
||||
"lifecycle.server.GeneratorOptionsMixin",
|
||||
"lifecycle.server.ServerMainMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"refmap": "terra-refmap.json"
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "com.dfsek.terra.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"ReloadCommandMixin",
|
||||
"access.MobSpawnerLogicAccessor",
|
||||
"access.StateAccessor",
|
||||
"access.StructureAccessorAccessor",
|
||||
"compat.GenerationSettingsFloraFeaturesMixin",
|
||||
"implementations.BiomeMixin",
|
||||
"implementations.HandleImplementationMixin",
|
||||
"implementations.block.BlockMixin",
|
||||
"implementations.block.entity.BlockEntityMixin",
|
||||
"implementations.block.entity.LootableContainerBlockEntityMixin",
|
||||
"implementations.block.entity.MobSpawnerBlockEntityMixin",
|
||||
"implementations.block.entity.SignBlockEntityMixin",
|
||||
"implementations.block.state.BlockStateMixin",
|
||||
"implementations.block.state.PropertyMixin",
|
||||
"implementations.chunk.ChunkRegionMixin",
|
||||
"implementations.chunk.WorldChunkMixin",
|
||||
"implementations.chunk.data.ProtoChunkMixin",
|
||||
"implementations.entity.EntityMixin",
|
||||
"implementations.entity.EntityTypeMixin",
|
||||
"implementations.entity.PlayerEntityMixin",
|
||||
"implementations.entity.ServerCommandSourceMixin",
|
||||
"implementations.inventory.LockableContainerBlockEntityMixin",
|
||||
"implementations.inventory.item.ItemMixin",
|
||||
"implementations.inventory.item.ItemStackMixin",
|
||||
"implementations.inventory.meta.EnchantmentMixin",
|
||||
"implementations.inventory.meta.ItemStackDamageableMixin",
|
||||
"implementations.inventory.meta.ItemStackMetaMixin",
|
||||
"implementations.world.ChunkRegionMixin",
|
||||
"implementations.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"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user