Merge pull request #318 from PolyhedralDev/dev/1.19

Update to 1.19
This commit is contained in:
dfsek 2022-06-07 15:40:41 -07:00 committed by GitHub
commit 0feae25be5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 557 additions and 721 deletions

View File

@ -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 {

View File

@ -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")
}

View File

@ -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> {

View 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 {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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
*/
}
}

View File

@ -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)));
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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))
);
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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))));
}
}
}

View File

@ -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();
}
}

View File

@ -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())

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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));

View File

@ -26,7 +26,7 @@
"depends": {
"fabricloader": ">=0.14.2",
"java": ">=17",
"minecraft": "1.18.x"
"minecraft": "1.19.x"
},
"accessWidener": "terra.accesswidener"
}

View File

@ -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;

View File

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