Merge branch 'master' into dev/1.19

This commit is contained in:
dfsek
2022-06-02 07:19:14 -07:00
54 changed files with 525 additions and 289 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ allprojects {
} }
afterEvaluate { afterEvaluate {
forSubProjects(":platforms") { forImmediateSubProjects(":platforms") {
configureDistribution() configureDistribution()
} }
forSubProjects(":common:addons") { forSubProjects(":common:addons") {
+18 -25
View File
@@ -1,11 +1,10 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import java.io.File import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.FileWriter import java.io.FileWriter
import java.net.URL import java.net.URL
import java.util.zip.ZipEntry import java.nio.file.FileSystems
import java.util.zip.ZipOutputStream import java.nio.file.Files
import java.nio.file.StandardCopyOption
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.BasePluginExtension import org.gradle.api.plugins.BasePluginExtension
@@ -39,41 +38,32 @@ fun Project.configureDistribution() {
} }
doLast { doLast {
// The addons are copied into a JAR because of a ShadowJar bug
// which expands *all* JARs, even resource ones, into the fat JAR.
// To get around this, we copy all addon JARs into a *new* JAR,
// then, ShadowJar expands the newly created JAR, putting the original
// JARs where they should go.
//
// https://github.com/johnrengelman/shadow/issues/111 // https://github.com/johnrengelman/shadow/issues/111
val dest = File(buildDir, "/resources/main/addons.jar") val dest = tasks.named<ShadowJar>("shadowJar").get().archiveFile.get().asFile.toPath()
dest.parentFile.mkdirs()
val zip = ZipOutputStream(FileOutputStream(dest)) FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs ->
forSubProjects(":common:addons") {
val jar = getJarTask()
forSubProjects(":common:addons") { println("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB")
val jar = getJarTask()
println("Packaging addon ${jar.archiveFileName.get()} to ${dest.absolutePath}. size: ${jar.archiveFile.get().asFile.length() / 1024}KB") val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}");
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" if(!Files.exists(addonPath)) {
Files.createDirectories(addonPath.parent)
Files.createFile(addonPath)
Files.copy(jar.archiveFile.get().asFile.toPath(), addonPath, StandardCopyOption.REPLACE_EXISTING)
}
val entry = ZipEntry("addons/$boot${jar.archiveFileName.get()}")
zip.putNextEntry(entry)
FileInputStream(jar.archiveFile.get().asFile).run {
copyTo(zip)
close()
} }
zip.closeEntry()
} }
zip.close()
} }
} }
val generateResourceManifest = tasks.create("generateResourceManifest") { val generateResourceManifest = tasks.create("generateResourceManifest") {
group = "terra" group = "terra"
dependsOn(downloadDefaultPacks) dependsOn(downloadDefaultPacks)
dependsOn(installAddons)
doLast { doLast {
val resources = HashMap<String, MutableList<String>>() val resources = HashMap<String, MutableList<String>>()
val packsDir = File("${project.buildDir}/resources/main/packs/") val packsDir = File("${project.buildDir}/resources/main/packs/")
@@ -118,6 +108,7 @@ fun Project.configureDistribution() {
tasks["processResources"].dependsOn(generateResourceManifest) tasks["processResources"].dependsOn(generateResourceManifest)
tasks.named<ShadowJar>("shadowJar") { tasks.named<ShadowJar>("shadowJar") {
// Tell shadow to download the packs // Tell shadow to download the packs
dependsOn(downloadDefaultPacks) dependsOn(downloadDefaultPacks)
@@ -129,6 +120,8 @@ fun Project.configureDistribution() {
relocate("com.dfsek.paralithic", "com.dfsek.terra.lib.paralithic") relocate("com.dfsek.paralithic", "com.dfsek.terra.lib.paralithic")
relocate("org.json", "com.dfsek.terra.lib.json") relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml") relocate("org.yaml", "com.dfsek.terra.lib.yaml")
finalizedBy(installAddons)
} }
configure<BasePluginExtension> { configure<BasePluginExtension> {
+6
View File
@@ -29,6 +29,12 @@ fun Project.forSubProjects(project: String, action: Action<Project>) {
} }
} }
fun Project.forImmediateSubProjects(project: String, action: Action<Project>) {
project(project).childProjects.forEach {
action.execute(it.value)
}
}
fun preRelease(preRelease: Boolean) { fun preRelease(preRelease: Boolean) {
isPrerelease = preRelease isPrerelease = preRelease
} }
+9 -17
View File
@@ -14,25 +14,13 @@ val paperURL = "https://papermc.io/api/v2/projects/paper/versions/%version%/buil
val purpurURL = "https://api.purpurmc.org/v2/purpur/%version%/latest/download" val purpurURL = "https://api.purpurmc.org/v2/purpur/%version%/latest/download"
dependencies { dependencies {
shadedApi(project(":common:implementation:base")) shaded(project(":platforms:bukkit:common"))
shaded(project(":platforms:bukkit:nms:v1_18_R2"))
api("org.slf4j:slf4j-api:1.8.0-beta4") {
because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.")
}
implementation("org.apache.logging.log4j", "log4j-slf4j18-impl", Versions.Libraries.log4j_slf4j_impl) {
because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.")
}
compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-20220519.005047-123")
compileOnly(group = "org.spigotmc", name = "spigot", version = "1.18.2-R0.1-SNAPSHOT")
shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib)
shadedApi("com.google.guava:guava:30.0-jre")
shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud)
} }
val jvmFlags = listOf( val throttleCoreCount = 0
val jvmFlags = mutableListOf(
"-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", "-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
@@ -42,6 +30,10 @@ val jvmFlags = listOf(
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", /*"-javaagent:paperclip.jar"*/ "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", /*"-javaagent:paperclip.jar"*/
) )
if(throttleCoreCount > 0) {
jvmFlags.add("-XX:ActiveProcessorCount=$throttleCoreCount")
}
fun downloadPaperclip(url: String, dir: String) { fun downloadPaperclip(url: String, dir: String) {
val clip = URL(url.replace("%version%", mcVersion)) val clip = URL(url.replace("%version%", mcVersion))
+18
View File
@@ -0,0 +1,18 @@
repositories {
}
dependencies {
shadedApi(project(":common:implementation:base"))
api("org.slf4j:slf4j-api:1.8.0-beta4") {
because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.")
}
compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT")
shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib)
shadedApi("com.google.guava:guava:30.0-jre")
shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud)
}
@@ -21,10 +21,6 @@ import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.CloudBukkitCapabilities; import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.paper.PaperCommandManager; import cloud.commandframework.paper.PaperCommandManager;
import com.dfsek.terra.bukkit.nms.NMSBiomeInjector;
import com.dfsek.terra.bukkit.nms.NMSInjectListener;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -42,6 +38,7 @@ import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
import com.dfsek.terra.bukkit.listeners.CommonListener; import com.dfsek.terra.bukkit.listeners.CommonListener;
import com.dfsek.terra.bukkit.nms.Initializer;
import com.dfsek.terra.bukkit.util.PaperUtil; import com.dfsek.terra.bukkit.util.PaperUtil;
import com.dfsek.terra.bukkit.util.VersionUtil; import com.dfsek.terra.bukkit.util.VersionUtil;
import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.BukkitAdapter;
@@ -60,7 +57,6 @@ public class TerraBukkitPlugin extends JavaPlugin {
} }
platform.getEventManager().callEvent(new PlatformInitializationEvent()); platform.getEventManager().callEvent(new PlatformInitializationEvent());
NMSBiomeInjector.registerBiomes(platform.getRawConfigRegistry());
try { try {
@@ -94,8 +90,13 @@ public class TerraBukkitPlugin extends JavaPlugin {
} }
Bukkit.getPluginManager().registerEvents(new CommonListener(), this); // Register master event listener Bukkit.getPluginManager().registerEvents(new CommonListener(), this); // Register master event listener
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), this); // Register master event listener
PaperUtil.checkPaper(this); PaperUtil.checkPaper(this);
Initializer.init(platform);
}
public PlatformImpl getPlatform() {
return platform;
} }
@SuppressWarnings({ "deprecation", "AccessOfSystemProperties" }) @SuppressWarnings({ "deprecation", "AccessOfSystemProperties" })
@@ -93,7 +93,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
@Override @Override
public boolean shouldGenerateDecorations() { public boolean shouldGenerateDecorations() {
return false; return true;
} }
@@ -0,0 +1,43 @@
package com.dfsek.terra.bukkit.nms;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import org.bukkit.Bukkit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
public interface Initializer {
String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
String TERRA_PACKAGE = Initializer.class.getPackageName();
void initialize(PlatformImpl plugin);
static void init(PlatformImpl platform) {
Logger logger = LoggerFactory.getLogger(Initializer.class);
try {
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSInitializer");
try {
Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance();
initializer.initialize(platform);
} catch(ReflectiveOperationException e) {
throw new RuntimeException("Error initializing NMS bindings. Report this to Terra.", e);
}
} catch(ClassNotFoundException e) {
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
logger.error("");
logger.error("");
for(int i = 0; i < 20; i++) {
logger.error("PROCEEDING WITH AN EXISTING TERRA WORLD WILL RESULT IN CORRUPTION!!!");
}
logger.error("");
logger.error("");
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
}
}
}
@@ -1,5 +1,7 @@
package com.dfsek.terra.bukkit.util; package com.dfsek.terra.bukkit.util;
import ca.solostudios.strata.Versions;
import ca.solostudios.strata.version.Version;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -17,30 +17,26 @@
package com.dfsek.terra.bukkit.world; package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.properties.Context;
import com.dfsek.terra.api.properties.PropertyHolder;
import com.dfsek.terra.api.world.biome.PlatformBiome; import com.dfsek.terra.api.world.biome.PlatformBiome;
import net.minecraft.core.Holder;
import net.minecraft.world.level.biome.BiomeBase;
public class BukkitPlatformBiome implements PlatformBiome, PropertyHolder {
public class BukkitPlatformBiome implements PlatformBiome {
private final org.bukkit.block.Biome biome; private final org.bukkit.block.Biome biome;
private Holder<BiomeBase> resourceKey; private final Context context = new Context();
public BukkitPlatformBiome(org.bukkit.block.Biome biome) { public BukkitPlatformBiome(org.bukkit.block.Biome biome) {
this.biome = biome; this.biome = biome;
} }
public void setResourceKey(Holder<BiomeBase> resourceKey) {
this.resourceKey = resourceKey;
}
public Holder<BiomeBase> getResourceKey() {
return resourceKey;
}
@Override @Override
public org.bukkit.block.Biome getHandle() { public org.bukkit.block.Biome getHandle() {
return biome; return biome;
} }
@Override
public Context getContext() {
return context;
}
} }
@@ -0,0 +1,6 @@
dependencies {
api(project(":platforms:bukkit:common"))
compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-20220519.005047-123")
compileOnly(group = "org.spigotmc", name = "spigot", version = "1.18.2-R0.1-SNAPSHOT")
}
@@ -0,0 +1,10 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.dfsek.terra.api.properties.Properties;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeBase;
public record NMSBiomeInfo(ResourceKey<BiomeBase> biomeKey) implements Properties {
}
@@ -1,32 +1,21 @@
package com.dfsek.terra.bukkit.nms; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet.Named;
import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryWritable; import net.minecraft.core.IRegistryWritable;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryMaterials; import net.minecraft.core.RegistryMaterials;
import net.minecraft.data.RegistryGeneration; import net.minecraft.data.RegistryGeneration;
import net.minecraft.resources.MinecraftKey; import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.BiomeFog; import net.minecraft.world.level.biome.BiomeFog;
import net.minecraft.world.level.biome.BiomeFog.GrassColor; import net.minecraft.world.level.biome.BiomeFog.GrassColor;
import net.minecraft.world.level.biome.BiomeSettingsGeneration; import net.minecraft.world.level.biome.BiomeSettingsGeneration;
import net.minecraft.world.level.biome.BiomeSettingsMobs; import net.minecraft.world.level.biome.BiomeSettingsMobs;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -39,28 +28,26 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.dfsek.terra.registry.master.ConfigRegistry;
public class NMSBiomeInjector { public class NMSBiomeInjector {
private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class);
private static final Map<MinecraftKey, List<MinecraftKey>> terraBiomeMap = new HashMap<>();
public static void registerBiomes(ConfigRegistry configRegistry) { public static void registerBiomes(ConfigRegistry configRegistry) {
CraftServer craftserver = (CraftServer) Bukkit.getServer();
DedicatedServer dedicatedserver = craftserver.getServer();
IRegistryWritable<BiomeBase> biomeRegistry = (IRegistryWritable<BiomeBase>) dedicatedserver
.aU() // getRegistryManager
.b( // getRegistry
IRegistry.aP // biome registry key
);
try { try {
LOGGER.info("Hacking biome registry..."); LOGGER.info("Hacking biome registry...");
IRegistryWritable<BiomeBase> biomeRegistry = (IRegistryWritable<BiomeBase>) Registries.biomeRegistry();
Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field
frozen.setAccessible(true); frozen.setAccessible(true);
frozen.set(biomeRegistry, false); frozen.set(biomeRegistry, false);
Map<MinecraftKey, List<MinecraftKey>> terraBiomeMap = new HashMap<>();
configRegistry.forEach(pack -> pack.getRegistry(Biome.class).forEach((key, biome) -> { configRegistry.forEach(pack -> pack.getRegistry(Biome.class).forEach((key, biome) -> {
try { try {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
@@ -74,8 +61,8 @@ public class NMSBiomeInjector {
ResourceKey<BiomeBase> delegateKey = ResourceKey.a(IRegistry.aP, new MinecraftKey("terra", createBiomeID(pack, key))); ResourceKey<BiomeBase> delegateKey = ResourceKey.a(IRegistry.aP, new MinecraftKey("terra", createBiomeID(pack, key)));
RegistryGeneration.a(RegistryGeneration.i, delegateKey, platform); RegistryGeneration.a(RegistryGeneration.i, delegateKey, platform);
Holder<BiomeBase> resourceKey = biomeRegistry.a(delegateKey, platform, Lifecycle.stable()); biomeRegistry.a(delegateKey, platform, Lifecycle.stable());
platformBiome.setResourceKey(resourceKey); platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.a()); terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.a());
@@ -98,38 +85,32 @@ public class NMSBiomeInjector {
terraBiomeMap terraBiomeMap
.forEach((vb, terraBiomes) -> .forEach((vb, terraBiomes) ->
getEntry(biomeRegistry, vb) getEntry(biomeRegistry, vb)
.ifPresentOrElse(vanilla -> terraBiomes .ifPresentOrElse(
.forEach(tb -> vanilla -> terraBiomes
getEntry(biomeRegistry, tb) .forEach(tb -> getEntry(biomeRegistry, tb)
.ifPresentOrElse( .ifPresentOrElse(
terra -> { terra -> {
LOGGER.debug( LOGGER.debug(vanilla.e().orElseThrow().a() +
vanilla.e() " (vanilla for " +
.orElseThrow() terra.e().orElseThrow().a() +
.a() + ": " +
" (vanilla for " + vanilla.c().toList());
terra.e()
.orElseThrow()
.a() +
": " +
vanilla.c()
.toList());
vanilla.c() vanilla.c()
.forEach( .forEach(
tag -> collect tag -> collect
.computeIfAbsent( .computeIfAbsent(tag,
tag, t -> new ArrayList<>())
t -> new ArrayList<>()) .add(terra));
.add(terra)); },
}, () -> LOGGER.error(
() -> LOGGER.error( "No such biome: {}",
"No such biome: {}", tb))),
tb))), () -> LOGGER.error("No vanilla biome: {}", vb)));
() -> LOGGER.error("No vanilla biome: {}", vb)));
biomeRegistry.k(); // clearTags biomeRegistry.k(); // clearTags
biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) { } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) {
throw new RuntimeException(exception); throw new RuntimeException(exception);
} }
@@ -156,13 +137,12 @@ public class NMSBiomeInjector {
BiomeSettingsMobs biomeSettingMobs = (BiomeSettingsMobs) biomeSettingMobsField.get(vanilla); BiomeSettingsMobs biomeSettingMobs = (BiomeSettingsMobs) biomeSettingMobsField.get(vanilla);
builder.a(biomeSettingMobs); builder.a(biomeSettingMobs);
Field biomeSettingGenField = BiomeBase.class.getDeclaredField("j");
biomeSettingGenField.setAccessible(true); BiomeSettingsGeneration.a generationBuilder = new BiomeSettingsGeneration.a(); // builder
BiomeSettingsGeneration biomeSettingGen = (BiomeSettingsGeneration) biomeSettingGenField.get(vanilla); builder.a(generationBuilder.a())
builder.a(biomeSettingGen) .a(vanilla.c())
.a(vanilla.c()) .b(vanilla.h()) // precipitation
.b(vanilla.h()) // precipitation .a(vanilla.i()); // temp
.a(vanilla.i()); // temp
BiomeFog.a effects = new BiomeFog.a(); // Builder BiomeFog.a effects = new BiomeFog.a(); // Builder
@@ -1,14 +1,18 @@
package com.dfsek.terra.bukkit.nms; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.Climate.Sampler; import net.minecraft.world.level.biome.Climate.Sampler;
import net.minecraft.world.level.biome.WorldChunkManager; import net.minecraft.world.level.biome.WorldChunkManager;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
public class NMSBiomeProvider extends WorldChunkManager { public class NMSBiomeProvider extends WorldChunkManager {
@@ -16,8 +20,13 @@ public class NMSBiomeProvider extends WorldChunkManager {
private final WorldChunkManager vanilla; private final WorldChunkManager vanilla;
private final long seed; private final long seed;
private static final Lazy<IRegistry<BiomeBase>> biomeRegistry = Lazy.lazy(() -> {
DedicatedServer dedicatedserver = ((CraftServer) Bukkit.getServer()).getServer();
return dedicatedserver.aU().b(IRegistry.aP);
});
public NMSBiomeProvider(BiomeProvider delegate, WorldChunkManager vanilla, long seed) { public NMSBiomeProvider(BiomeProvider delegate, WorldChunkManager vanilla, long seed) {
super(vanilla.b().stream()); super(delegate.stream().map(biome -> biomeRegistry.value().g(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey())));
this.delegate = delegate; this.delegate = delegate;
this.vanilla = vanilla; this.vanilla = vanilla;
this.seed = seed; this.seed = seed;
@@ -39,6 +48,7 @@ public class NMSBiomeProvider extends WorldChunkManager {
@Override @Override
public Holder<BiomeBase> getNoiseBiome(int x, int y, int z, Sampler sampler) { public Holder<BiomeBase> getNoiseBiome(int x, int y, int z, Sampler sampler) {
return ((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getResourceKey(); //return CraftBlock.biomeToBiomeBase(biomeRegistry.value(), ((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getHandle());
return biomeRegistry.value().g(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey());
} }
} }
@@ -0,0 +1,239 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistryCustom;
import net.minecraft.core.SectionPosition;
import net.minecraft.server.level.RegionLimitedWorldAccess;
import net.minecraft.world.level.BlockColumn;
import net.minecraft.world.level.ChunkCoordIntPair;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.Climate.Sampler;
import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.levelgen.ChunkGeneratorAbstract;
import net.minecraft.world.level.levelgen.HeightMap;
import net.minecraft.world.level.levelgen.WorldGenStage;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
private final NMSBiomeProvider biomeSource;
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
private final ChunkGenerator vanilla;
private final ConfigPack pack;
private final long seed;
private final Map<ConcentricRingsStructurePlacement, Lazy<List<ChunkCoordIntPair>>> h = new Object2ObjectArrayMap<>();
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
super(Registries.structureSet(), Optional.empty(), biomeProvider, biomeProvider, seed);
this.delegate = pack.getGeneratorProvider().newInstance(pack);
this.vanilla = vanilla;
this.biomeSource = biomeProvider;
this.pack = pack;
this.seed = seed;
}
@Override //applyCarvers
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, long var2, BiomeManager var4, StructureManager var5,
IChunkAccess ichunkaccess, WorldGenStage.Features var7) {
// no-op
}
@Override // getSeaLevel
public int g() {
return vanilla.g();
}
@Override //fillFromNoise
public CompletableFuture<IChunkAccess> a(Executor executor, Blender blender, StructureManager structuremanager,
IChunkAccess ichunkaccess) {
return vanilla.a(executor, blender, structuremanager, ichunkaccess);
}
@Override //buildSurface. Used to be buildBase
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, StructureManager structuremanager, IChunkAccess ichunkaccess) {
}
@Override
protected Codec<? extends ChunkGenerator> b() {
return ChunkGeneratorAbstract.a;
}
@Override // getColumn
public BlockColumn a(int x, int z, LevelHeightAccessor height) {
IBlockData[] array = new IBlockData[height.v_()];
WorldProperties properties = new NMSWorldProperties(seed, height);
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) {
array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider)
.getHandle()).getState();
}
return new BlockColumn(getMinimumY(), array);
}
@Override // withSeed
public ChunkGenerator a(long seed) {
return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, seed);
}
//spawnOriginalMobs
public void a(RegionLimitedWorldAccess regionlimitedworldaccess) {
vanilla.a(regionlimitedworldaccess);
}
// getGenDepth
public int f() {
return vanilla.f();
}
// climateSampler
public Sampler d() {
return Climate.a();
}
//getMinY
@Override
public int h() {
return vanilla.h();
}
@Override // getBaseHeight
public int a(int x, int z, HeightMap.Type heightmap, LevelHeightAccessor height) {
WorldProperties properties = new NMSWorldProperties(seed, height);
int y = properties.getMaxHeight();
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
while(y >= getMinimumY() && !heightmap.e().test(
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
y--;
}
return y;
}
@Override
public void a(IRegistryCustom iregistrycustom, StructureManager structuremanager, IChunkAccess ichunkaccess,
DefinedStructureManager definedstructuremanager, long i) {
super.a(iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i);
}
@Nullable
@Override
public List<ChunkCoordIntPair> a(ConcentricRingsStructurePlacement concentricringsstructureplacement) {
this.i();
return this.h.get(concentricringsstructureplacement).value();
}
private volatile boolean rings = false;
@Override
public synchronized void i() {
if(!this.rings) {
super.i();
this.populateStrongholdData();
this.rings = true;
}
}
private void populateStrongholdData() {
LOGGER.info("Generating safe stronghold data. This may take up to a minute.");
Set<Holder<BiomeBase>> set = this.d.b();
a().map(h -> h.a()).forEach((holder) -> { // we dont need the spigot crap because it doesnt touch concentric.
StructurePlacement structureplacement = holder.b();
if(structureplacement instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) {
if(holder.a().stream().anyMatch((structureset_a1) -> structureset_a1.a(set::contains))) {
this.h.put(concentricringsstructureplacement,
Lazy.lazy(() -> this.generateRingPositions(holder, concentricringsstructureplacement)));
}
}
});
}
private List<ChunkCoordIntPair> generateRingPositions(StructureSet holder,
ConcentricRingsStructurePlacement concentricringsstructureplacement) {
if(concentricringsstructureplacement.d() == 0) {
return List.of();
}
List<ChunkCoordIntPair> list = new ArrayList<>();
Set<Holder<BiomeBase>> set = holder.a().stream().flatMap((structureset_a) -> (structureset_a.a().a()).a().a()).collect(
Collectors.toSet());
int i = concentricringsstructureplacement.b();
int j = concentricringsstructureplacement.d();
int k = concentricringsstructureplacement.c();
Random random = new Random();
random.setSeed(this.j);
double d0 = random.nextDouble() * Math.PI * 2.0;
int l = 0;
int i1 = 0;
for(int j1 = 0; j1 < j; ++j1) {
double d1 = (double) (4 * i + i * i1 * 6) + (random.nextDouble() - 0.5) * (double) i * 2.5;
int k1 = (int) Math.round(Math.cos(d0) * d1);
int l1 = (int) Math.round(Math.sin(d0) * d1);
int i2 = SectionPosition.a(k1, 8);
int j2 = SectionPosition.a(l1, 8);
Objects.requireNonNull(set);
Pair<BlockPosition, Holder<BiomeBase>> pair = this.c.a(i2, 0, j2, 112, set::contains, random, this.d());
if(pair != null) {
BlockPosition blockposition = pair.getFirst();
k1 = SectionPosition.a(blockposition.u());
l1 = SectionPosition.a(blockposition.w());
}
list.add(new ChunkCoordIntPair(k1, l1));
d0 += 6.283185307179586 / (double) k;
++l;
if(l == k) {
++i1;
l = 0;
k += 2 * k / (i1 + 1);
k = Math.min(k, j - j1);
d0 += random.nextDouble() * Math.PI * 2.0;
}
}
return list;
}
public int getMinimumY() {
return h();
}
@Override //addDebugScreenInfo
public void a(List<String> arg0, BlockPosition arg1) {
}
}
@@ -0,0 +1,15 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import org.bukkit.Bukkit;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.nms.Initializer;
public class NMSInitializer implements Initializer {
@Override
public void initialize(PlatformImpl platform) {
NMSBiomeInjector.registerBiomes(platform.getRawConfigRegistry());
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
}
}
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.server.level.WorldServer; import net.minecraft.server.level.WorldServer;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
@@ -36,13 +36,16 @@ public class NMSInjectListener implements Listener {
ChunkGenerator vanilla = serverWorld.k().g(); ChunkGenerator vanilla = serverWorld.k().g();
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.e(), craftWorld.getSeed()); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.e(), craftWorld.getSeed());
NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld); NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
custom.conf = vanilla.conf; // world config from Spigot custom.conf = vanilla.conf; // world config from Spigot
serverWorld.k().a.u = custom; serverWorld.k().a.u = custom;
LOGGER.info("Successfully injected into world."); LOGGER.info("Successfully injected into world.");
serverWorld.k().a.u.i(); // generate stronghold data now
INJECT_LOCK.unlock(); INJECT_LOCK.unlock();
} }
} }
@@ -0,0 +1,36 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.world.level.LevelHeightAccessor;
import com.dfsek.terra.api.world.info.WorldProperties;
public class NMSWorldProperties implements WorldProperties {
private final long seed;
private final LevelHeightAccessor height;
public NMSWorldProperties(long seed, LevelHeightAccessor height) {
this.seed = seed;
this.height = height;
}
@Override
public Object getHandle() {
return height;
}
@Override
public long getSeed() {
return seed;
}
@Override
public int getMaxHeight() {
return height.ag();
}
@Override
public int getMinHeight() {
return height.u_();
}
}
@@ -0,0 +1,30 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.core.IRegistry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
public class Registries {
private static <T> IRegistry<T> getRegistry(ResourceKey<IRegistry<T>> key) {
CraftServer craftserver = (CraftServer) Bukkit.getServer();
DedicatedServer dedicatedserver = craftserver.getServer();
return dedicatedserver
.aU() // getRegistryManager
.b( // getRegistry
key
);
}
public static IRegistry<BiomeBase> biomeRegistry() {
return getRegistry(IRegistry.aP);
}
public static IRegistry<StructureSet> structureSet() {
return getRegistry(IRegistry.aM);
}
}
@@ -1,149 +0,0 @@
package com.dfsek.terra.bukkit.nms;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.bukkit.generator.BukkitProtoChunk;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.bukkit.world.BukkitServerWorld;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.RegionLimitedWorldAccess;
import net.minecraft.world.level.BlockColumn;
import net.minecraft.world.level.GeneratorAccessSeed;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.Climate.Sampler;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.levelgen.ChunkGeneratorAbstract;
import net.minecraft.world.level.levelgen.HeightMap;
import net.minecraft.world.level.levelgen.WorldGenStage;
import net.minecraft.world.level.levelgen.blending.Blender;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.generator.CraftChunkData;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
private final NMSBiomeProvider biomeSource;
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
private final ChunkGenerator vanilla;
private final ConfigPack pack;
private final CraftWorld world;
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, CraftWorld world) {
super(vanilla.b, vanilla.e, biomeProvider);
this.delegate = pack.getGeneratorProvider().newInstance(pack);
this.vanilla = vanilla;
this.biomeSource = biomeProvider;
this.pack = pack;
this.world = world;
}
@Override //applyCarvers
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, long var2, BiomeManager var4, StructureManager var5,
IChunkAccess ichunkaccess, WorldGenStage.Features var7) {
// no-op
}
@Override // getSeaLevel
public int g() {
return vanilla.g();
}
@Override //fillFromNoise
public CompletableFuture<IChunkAccess> a(Executor executor, Blender blender, StructureManager structuremanager,
IChunkAccess ichunkaccess) {
return vanilla.a(executor, blender, structuremanager, ichunkaccess);
}
@Override //buildSurface. Used to be buildBase
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, StructureManager structuremanager, IChunkAccess ichunkaccess) {
}
@Override
public void a(GeneratorAccessSeed gas, StructureManager manager, IChunkAccess ica) {
vanilla.a(gas, manager, ica);
}
@Override
protected Codec<? extends ChunkGenerator> b() {
return ChunkGeneratorAbstract.a;
}
@Override // getColumn
public BlockColumn a(int var0, int var1, LevelHeightAccessor var2) {
return vanilla.a(var0, var1, var2);
}
@Override // withSeed
public ChunkGenerator a(long seed) {
return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, world);
}
//spawnOriginalMobs
public void a(RegionLimitedWorldAccess regionlimitedworldaccess) {
vanilla.a(regionlimitedworldaccess);
}
// getGenDepth
public int f() {
return vanilla.f();
}
// climateSampler
public Sampler d() {
return Climate.a();
}
//getMinY
@Override
public int h() {
return vanilla.h();
}
@Override //getFirstFreeHeight
public int b(int i, int j, HeightMap.Type heightmap_type, LevelHeightAccessor levelheightaccessor) {
return this.a(i, j, heightmap_type, levelheightaccessor);
}
@Override //getFirstOccupiedHeight
public int c(int i, int j, HeightMap.Type heightmap_type, LevelHeightAccessor levelheightaccessor) {
return this.a(i, j, heightmap_type, levelheightaccessor) - 1;
}
@Override // getBaseHeight
public int a(int x, int z, HeightMap.Type heightmap, LevelHeightAccessor height) {
int y = world.getMaxHeight();
WorldProperties properties = BukkitAdapter.adapt(world);
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
while(y >= getMinimumY() && !heightmap.e().test(
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
y--;
}
return y;
}
public int getMinimumY() {
return h();
}
@Override //addDebugScreenInfo
public void a(List<String> arg0, BlockPosition arg1) {
}
}
+1
View File
@@ -48,6 +48,7 @@ tasks.getByName<ShadowJar>("shadowJar") {
} }
val remapped = tasks.register<RemapJarTask>("remapShadedJar") { val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
dependsOn("installAddons")
group = "fabric" group = "fabric"
val shadowJar = tasks.getByName<ShadowJar>("shadowJar") val shadowJar = tasks.getByName<ShadowJar>("shadowJar")
dependsOn(shadowJar) dependsOn(shadowJar)
+4
View File
@@ -18,6 +18,10 @@ includeImmediateChildren(file("common/addons"), "addon")
includeImmediateChildren(file("platforms"), "platform") includeImmediateChildren(file("platforms"), "platform")
includeImmediateChildren(file("platforms/bukkit/nms"), "Bukkit NMS")
include(":platforms:bukkit:common")
pluginManagement { pluginManagement {
repositories { repositories {
maven(url = "https://maven.fabricmc.net") { maven(url = "https://maven.fabricmc.net") {