mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-17 05:40:16 +00:00
Merge remote-tracking branch 'origin/master' into dev/layered-generator
This commit is contained in:
@@ -1,18 +1,10 @@
|
||||
plugins {
|
||||
id("xyz.jpenilla.run-paper") version "1.0.6"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
id("xyz.jpenilla.run-paper") version Versions.Bukkit.runPaper
|
||||
}
|
||||
|
||||
dependencies {
|
||||
shaded(project(":platforms:bukkit:common"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_18_R2", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R1", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R2", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_19_R3", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_20_R1", configuration = "reobf"))
|
||||
shaded(project(":platforms:bukkit:nms:v1_21", configuration = "reobf"))
|
||||
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
|
||||
}
|
||||
|
||||
@@ -29,7 +21,7 @@ tasks {
|
||||
exclude("com/google/j2objc/**")
|
||||
exclude("javax/**")
|
||||
}
|
||||
|
||||
|
||||
runServer {
|
||||
minecraftVersion(Versions.Bukkit.minecraft)
|
||||
dependsOn(shadowJar)
|
||||
|
||||
@@ -4,15 +4,12 @@ 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:${Versions.Bukkit.paper}")
|
||||
|
||||
|
||||
compileOnly("io.papermc.paper", "paper-api", Versions.Bukkit.paper)
|
||||
|
||||
shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib)
|
||||
shadedApi("com.google.guava:guava:30.0-jre")
|
||||
|
||||
shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud)
|
||||
|
||||
shadedApi("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
|
||||
shadedApi("org.incendo", "cloud-paper", Versions.Libraries.cloudPaper)
|
||||
}
|
||||
|
||||
@@ -14,37 +14,37 @@ import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
public class BukkitAddon implements BaseAddon {
|
||||
private static final Version VERSION = Versions.getVersion(1, 0, 0);
|
||||
|
||||
|
||||
private final PlatformImpl terraBukkitPlugin;
|
||||
|
||||
|
||||
public BukkitAddon(PlatformImpl terraBukkitPlugin) {
|
||||
this.terraBukkitPlugin = terraBukkitPlugin;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
terraBukkitPlugin.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions())))
|
||||
.global();
|
||||
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions())))
|
||||
.global();
|
||||
|
||||
terraBukkitPlugin.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigurationLoadEvent.class)
|
||||
.then(event -> {
|
||||
if(event.is(Biome.class)) {
|
||||
event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties()));
|
||||
}
|
||||
})
|
||||
.global();
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigurationLoadEvent.class)
|
||||
.then(event -> {
|
||||
if(event.is(Biome.class)) {
|
||||
event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties()));
|
||||
}
|
||||
})
|
||||
.global();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "terra-bukkit";
|
||||
|
||||
@@ -29,16 +29,16 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitCommandSender implements CommandSender {
|
||||
private final org.bukkit.command.CommandSender delegate;
|
||||
|
||||
|
||||
public BukkitCommandSender(org.bukkit.command.CommandSender delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
delegate.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Entity> getEntity() {
|
||||
if(delegate instanceof org.bukkit.entity.Entity entity) {
|
||||
@@ -46,7 +46,7 @@ public class BukkitCommandSender implements CommandSender {
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer() {
|
||||
if(delegate instanceof org.bukkit.entity.Player player) {
|
||||
@@ -54,7 +54,7 @@ public class BukkitCommandSender implements CommandSender {
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.command.CommandSender getHandle() {
|
||||
return delegate;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package com.dfsek.terra.bukkit;
|
||||
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
@@ -27,33 +28,33 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitEntity implements Entity {
|
||||
private final org.bukkit.entity.Entity entity;
|
||||
|
||||
|
||||
public BukkitEntity(org.bukkit.entity.Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Entity getHandle() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vector3 position() {
|
||||
return BukkitAdapter.adapt(entity.getLocation().toVector());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void position(Vector3 location) {
|
||||
entity.teleport(BukkitAdapter.adapt(location).toLocation(entity.getWorld()));
|
||||
PaperLib.teleportAsync(entity, BukkitAdapter.adapt(location).toLocation(entity.getWorld()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void world(ServerWorld world) {
|
||||
Location newLoc = entity.getLocation().clone();
|
||||
newLoc.setWorld(BukkitAdapter.adapt(world));
|
||||
entity.teleport(newLoc);
|
||||
PaperLib.teleportAsync(entity, newLoc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld world() {
|
||||
return BukkitAdapter.adapt(entity.getWorld());
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package com.dfsek.terra.bukkit;
|
||||
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import com.dfsek.terra.api.entity.Player;
|
||||
@@ -27,34 +28,34 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitPlayer implements Player {
|
||||
private final org.bukkit.entity.Player delegate;
|
||||
|
||||
|
||||
public BukkitPlayer(org.bukkit.entity.Player delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Player getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vector3 position() {
|
||||
org.bukkit.Location bukkit = delegate.getLocation();
|
||||
return Vector3.of(bukkit.getX(), bukkit.getY(), bukkit.getZ());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void position(Vector3 location) {
|
||||
delegate.teleport(BukkitAdapter.adapt(location).toLocation(delegate.getWorld()));
|
||||
PaperLib.teleportAsync(delegate, BukkitAdapter.adapt(location).toLocation(delegate.getWorld()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void world(ServerWorld world) {
|
||||
Location newLoc = delegate.getLocation().clone();
|
||||
newLoc.setWorld(BukkitAdapter.adapt(world));
|
||||
delegate.teleport(newLoc);
|
||||
PaperLib.teleportAsync(delegate, newLoc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld world() {
|
||||
return BukkitAdapter.adapt(delegate.getWorld());
|
||||
|
||||
@@ -44,28 +44,28 @@ import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
public class PlatformImpl extends AbstractPlatform {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class);
|
||||
|
||||
|
||||
private final ItemHandle itemHandle = new BukkitItemHandle();
|
||||
|
||||
|
||||
private final WorldHandle handle = new BukkitWorldHandle();
|
||||
|
||||
|
||||
private final TerraBukkitPlugin plugin;
|
||||
|
||||
|
||||
public PlatformImpl(TerraBukkitPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
load();
|
||||
}
|
||||
|
||||
|
||||
public TerraBukkitPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean reload() {
|
||||
getTerraConfig().load(this);
|
||||
getRawConfigRegistry().clear();
|
||||
boolean succeed = getRawConfigRegistry().loadAll(this);
|
||||
|
||||
|
||||
Bukkit.getWorlds().forEach(world -> {
|
||||
if(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper) {
|
||||
getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> {
|
||||
@@ -74,49 +74,49 @@ public class PlatformImpl extends AbstractPlatform {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return succeed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull String platformName() {
|
||||
return "Bukkit";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void runPossiblyUnsafeTask(@NotNull Runnable task) {
|
||||
Bukkit.getScheduler().runTask(plugin, task);
|
||||
public void runPossiblyUnsafeTask(@NotNull Runnable runnable) {
|
||||
plugin.getGlobalRegionScheduler().run(plugin, task -> runnable.run());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Iterable<BaseAddon> platformAddon() {
|
||||
return List.of(new BukkitAddon(this));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull WorldHandle getWorldHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull File getDataFolder() {
|
||||
return plugin.getDataFolder();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull ItemHandle getItemHandle() {
|
||||
return itemHandle;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
super.register(registry);
|
||||
registry.registerLoader(BlockState.class, (type, o, loader, depthTracker) -> handle.createBlockState((String) o))
|
||||
.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
|
||||
.registerLoader(EntityType.class, (type, o, loader, depthTracker) -> EntityType.valueOf((String) o));
|
||||
|
||||
.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
|
||||
.registerLoader(EntityType.class, (type, o, loader, depthTracker) -> EntityType.valueOf((String) o));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private BukkitPlatformBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException {
|
||||
if(!id.startsWith("minecraft:")) throw new LoadException("Invalid biome identifier " + id, depthTracker);
|
||||
return new BukkitPlatformBiome(org.bukkit.block.Biome.valueOf(id.toUpperCase(Locale.ROOT).substring(10)));
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
|
||||
package com.dfsek.terra.bukkit;
|
||||
|
||||
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.paper.PaperCommandManager;
|
||||
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
|
||||
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.incendo.cloud.SenderMapper;
|
||||
import org.incendo.cloud.brigadier.CloudBrigadierManager;
|
||||
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.paper.LegacyPaperCommandManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@@ -31,6 +34,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.dfsek.terra.api.command.CommandSender;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
@@ -46,67 +50,86 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class TerraBukkitPlugin extends JavaPlugin {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TerraBukkitPlugin.class);
|
||||
|
||||
|
||||
private final PlatformImpl platform = new PlatformImpl(this);
|
||||
private final Map<String, com.dfsek.terra.api.world.chunk.generation.ChunkGenerator> generatorMap = new HashMap<>();
|
||||
|
||||
|
||||
private AsyncScheduler asyncScheduler = this.getServer().getAsyncScheduler();
|
||||
|
||||
private GlobalRegionScheduler globalRegionScheduler = this.getServer().getGlobalRegionScheduler();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if(!doVersionCheck()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
platform.getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
|
||||
|
||||
|
||||
if(!Initializer.init(platform)) {
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PaperCommandManager<CommandSender> commandManager = new PaperCommandManager<>(this,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
BukkitAdapter::adapt,
|
||||
BukkitAdapter::adapt);
|
||||
if(commandManager.queryCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
|
||||
commandManager.registerBrigadier();
|
||||
final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager();
|
||||
if(brigManager != null) {
|
||||
brigManager.setNativeNumberSuggestions(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(commandManager.queryCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
|
||||
commandManager.registerAsynchronousCompletions();
|
||||
}
|
||||
|
||||
LegacyPaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
|
||||
|
||||
platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager));
|
||||
|
||||
|
||||
} catch(Exception e) { // This should never happen.
|
||||
logger.error("""
|
||||
TERRA HAS BEEN DISABLED
|
||||
|
||||
|
||||
Errors occurred while registering commands.
|
||||
Please report this to Terra.
|
||||
""".strip(), e);
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new CommonListener(), this); // Register master event listener
|
||||
PaperUtil.checkPaper(this);
|
||||
|
||||
Initializer.init(platform);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private LegacyPaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
|
||||
// TODO: Update to PaperCommandManager
|
||||
LegacyPaperCommandManager<CommandSender> commandManager = new LegacyPaperCommandManager<>(
|
||||
this,
|
||||
ExecutionCoordinator.simpleCoordinator(),
|
||||
SenderMapper.create(
|
||||
BukkitAdapter::adapt,
|
||||
BukkitAdapter::adapt
|
||||
));
|
||||
|
||||
if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
|
||||
commandManager.registerBrigadier();
|
||||
final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager();
|
||||
if(brigManager != null) {
|
||||
brigManager.setNativeNumberSuggestions(false);
|
||||
}
|
||||
} else if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
|
||||
commandManager.registerAsynchronousCompletions();
|
||||
}
|
||||
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
public PlatformImpl getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "deprecation", "AccessOfSystemProperties" })
|
||||
private boolean doVersionCheck() {
|
||||
logger.info("Running on Minecraft version {} with server implementation {}.", VersionUtil.getMinecraftVersionInfo(),
|
||||
Bukkit.getServer().getName());
|
||||
|
||||
Bukkit.getServer().getName());
|
||||
|
||||
if(!VersionUtil.getSpigotVersionInfo().isSpigot())
|
||||
logger.error("YOU ARE RUNNING A CRAFTBUKKIT OR BUKKIT SERVER. PLEASE UPGRADE TO PAPER.");
|
||||
|
||||
|
||||
if(!VersionUtil.getSpigotVersionInfo().isPaper())
|
||||
logger.error("YOU ARE RUNNING A SPIGOT SERVER. PLEASE UPGRADE TO PAPER.");
|
||||
|
||||
if(VersionUtil.getSpigotVersionInfo().isMohist()) {
|
||||
if(System.getProperty("IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways") == null) {
|
||||
Runnable runnable = () -> { // scary big block of text
|
||||
@@ -150,7 +173,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
|
||||
""".strip());
|
||||
};
|
||||
runnable.run();
|
||||
Bukkit.getScheduler().scheduleAsyncDelayedTask(this, runnable, 200L);
|
||||
asyncScheduler.runDelayed(this, task -> runnable.run(), 200L, TimeUnit.SECONDS);
|
||||
// Bukkit.shutdown(); // we're not *that* evil
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return false;
|
||||
@@ -158,7 +181,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
|
||||
logger.warn("""
|
||||
You are using Mohist, so we will not give you any support for issues that may arise.
|
||||
Since you enabled the "IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways" flag, we won't disable Terra. But be warned.
|
||||
|
||||
|
||||
> I felt a great disturbance in the JVM, as if millions of plugins suddenly cried out in stack traces and were suddenly silenced.
|
||||
> I fear something terrible has happened.
|
||||
> - Astrash
|
||||
@@ -167,14 +190,23 @@ public class TerraBukkitPlugin extends JavaPlugin {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable
|
||||
ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) {
|
||||
if(id == null || id.trim().equals("")) { return null; }
|
||||
return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> {
|
||||
ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow(
|
||||
() -> new IllegalArgumentException("No such config pack \"" + id + "\""));
|
||||
() -> new IllegalArgumentException("No such config pack \"" + id + "\""));
|
||||
return pack.getGeneratorProvider().newInstance(pack);
|
||||
}), platform.getRawConfigRegistry().getByID(id).orElseThrow(), platform.getWorldHandle().air());
|
||||
}
|
||||
|
||||
public AsyncScheduler getAsyncScheduler() {
|
||||
return asyncScheduler;
|
||||
}
|
||||
|
||||
public GlobalRegionScheduler getGlobalRegionScheduler() {
|
||||
return globalRegionScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,31 +29,31 @@ public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties {
|
||||
@Value("minecraft.use-vanilla-biomes")
|
||||
@Default
|
||||
private boolean vanillaBiomes = false;
|
||||
|
||||
|
||||
@Value("minecraft.beard.enable")
|
||||
@Default
|
||||
private boolean beard = true;
|
||||
|
||||
|
||||
@Value("minecraft.beard.threshold")
|
||||
@Default
|
||||
private double beardThreshold = 0.5;
|
||||
|
||||
|
||||
@Value("minecraft.beard.air-threshold")
|
||||
@Default
|
||||
private double airThreshold = -0.5;
|
||||
|
||||
|
||||
public boolean useVanillaBiomes() {
|
||||
return vanillaBiomes;
|
||||
}
|
||||
|
||||
|
||||
public boolean isBeard() {
|
||||
return beard;
|
||||
}
|
||||
|
||||
|
||||
public double getBeardThreshold() {
|
||||
return beardThreshold;
|
||||
}
|
||||
|
||||
|
||||
public double getAirThreshold() {
|
||||
return airThreshold;
|
||||
}
|
||||
|
||||
@@ -11,47 +11,47 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties {
|
||||
@Value("colors.grass")
|
||||
@Default
|
||||
private Integer grassColor = null;
|
||||
|
||||
|
||||
@Value("colors.fog")
|
||||
@Default
|
||||
private Integer fogColor = null;
|
||||
|
||||
|
||||
@Value("colors.water")
|
||||
@Default
|
||||
private Integer waterColor = null;
|
||||
|
||||
|
||||
@Value("colors.water-fog")
|
||||
@Default
|
||||
private Integer waterFogColor = null;
|
||||
|
||||
|
||||
@Value("colors.foliage")
|
||||
@Default
|
||||
private Integer foliageColor = null;
|
||||
|
||||
|
||||
@Value("colors.sky")
|
||||
@Default
|
||||
private Integer skyColor = null;
|
||||
|
||||
|
||||
public Integer getFogColor() {
|
||||
return fogColor;
|
||||
}
|
||||
|
||||
|
||||
public Integer getFoliageColor() {
|
||||
return foliageColor;
|
||||
}
|
||||
|
||||
|
||||
public Integer getGrassColor() {
|
||||
return grassColor;
|
||||
}
|
||||
|
||||
|
||||
public Integer getWaterColor() {
|
||||
return waterColor;
|
||||
}
|
||||
|
||||
|
||||
public Integer getWaterFogColor() {
|
||||
return waterFogColor;
|
||||
}
|
||||
|
||||
|
||||
public Integer getSkyColor() {
|
||||
return skyColor;
|
||||
}
|
||||
|
||||
@@ -14,22 +14,22 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
public class BukkitBiomeProvider extends BiomeProvider implements Handle {
|
||||
private final com.dfsek.terra.api.world.biome.generation.BiomeProvider delegate;
|
||||
|
||||
|
||||
public BukkitBiomeProvider(com.dfsek.terra.api.world.biome.generation.BiomeProvider delegate) { this.delegate = delegate; }
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull org.bukkit.block.Biome getBiome(@NotNull WorldInfo worldInfo, int x, int y, int z) {
|
||||
Biome biome = delegate.getBiome(x, y, z, worldInfo.getSeed());
|
||||
return (org.bukkit.block.Biome) biome.getPlatformBiome().getHandle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull List<org.bukkit.block.Biome> getBiomes(@NotNull WorldInfo worldInfo) {
|
||||
return StreamSupport.stream(delegate.getBiomes().spliterator(), false)
|
||||
.map(terraBiome -> (org.bukkit.block.Biome) terraBiome.getPlatformBiome().getHandle())
|
||||
.collect(Collectors.toList());
|
||||
.map(terraBiome -> (org.bukkit.block.Biome) terraBiome.getPlatformBiome().getHandle())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate;
|
||||
|
||||
@@ -13,21 +13,22 @@ import com.dfsek.terra.bukkit.world.BukkitProtoWorld;
|
||||
|
||||
|
||||
public class BukkitBlockPopulator extends BlockPopulator {
|
||||
private ConfigPack pack;
|
||||
private final BlockState air;
|
||||
|
||||
private ConfigPack pack;
|
||||
|
||||
public BukkitBlockPopulator(ConfigPack pack, BlockState air) {
|
||||
this.pack = pack;
|
||||
this.air = air;
|
||||
}
|
||||
|
||||
|
||||
public void setPack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int chunkX, int chunkZ,
|
||||
@NotNull LimitedRegion limitedRegion) {
|
||||
pack.getStages().forEach(generationStage -> generationStage.populate(new BukkitProtoWorld(limitedRegion, air, pack.getBiomeProvider())));
|
||||
pack.getStages().forEach(
|
||||
generationStage -> generationStage.populate(new BukkitProtoWorld(limitedRegion, air, pack.getBiomeProvider())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.dfsek.terra.bukkit.generator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.LimitedRegion;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,24 +28,22 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
import com.dfsek.terra.bukkit.world.BukkitProtoWorld;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
|
||||
|
||||
public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BukkitChunkGeneratorWrapper.class);
|
||||
private final BlockState air;
|
||||
private final BukkitBlockPopulator blockPopulator;
|
||||
private ChunkGenerator delegate;
|
||||
private ConfigPack pack;
|
||||
private final BukkitBlockPopulator blockPopulator;
|
||||
|
||||
|
||||
|
||||
public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, BlockState air) {
|
||||
this.delegate = delegate;
|
||||
@@ -54,38 +51,38 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
|
||||
this.air = air;
|
||||
this.blockPopulator = new BukkitBlockPopulator(pack, air);
|
||||
}
|
||||
|
||||
|
||||
public void setDelegate(ChunkGenerator delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) {
|
||||
return new BukkitBiomeProvider(pack.getBiomeProvider());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull ChunkData chunkData) {
|
||||
BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo);
|
||||
delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider(), x, z);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
|
||||
return List.of(blockPopulator);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateCaves() {
|
||||
return false;
|
||||
//return pack.vanillaCaves();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateDecorations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateMobs() {
|
||||
return true;
|
||||
@@ -95,21 +92,21 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
|
||||
public boolean shouldGenerateStructures() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
|
||||
public void setPack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
setDelegate(pack.getGeneratorProvider().newInstance(pack));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private record SeededVector(int x, int z, WorldProperties worldProperties) {
|
||||
@Override
|
||||
|
||||
@@ -26,30 +26,30 @@ import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
|
||||
public class BukkitProtoChunk implements ProtoChunk {
|
||||
|
||||
|
||||
private final ChunkGenerator.ChunkData delegate;
|
||||
|
||||
|
||||
public BukkitProtoChunk(ChunkGenerator.ChunkData delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkGenerator.ChunkData getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return delegate.getMaxHeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||
delegate.setBlock(x, y, z, ((BukkitBlockState) blockState).getHandle());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return BukkitBlockState.newInstance(delegate.getBlockData(x, y, z));
|
||||
|
||||
@@ -32,18 +32,18 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
|
||||
public class BukkitItemHandle implements ItemHandle {
|
||||
|
||||
|
||||
@Override
|
||||
public Item createItem(String data) {
|
||||
return BukkitAdapter.adapt(Material.matchMaterial(data));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Enchantment getEnchantment(String id) {
|
||||
return BukkitAdapter.adapt(
|
||||
org.bukkit.enchantments.Enchantment.getByKey(NamespacedKey.minecraft(MinecraftUtils.stripMinecraftNamespace(id))));
|
||||
org.bukkit.enchantments.Enchantment.getByKey(NamespacedKey.minecraft(MinecraftUtils.stripMinecraftNamespace(id))));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Enchantment> getEnchantments() {
|
||||
return Arrays.stream(org.bukkit.enchantments.Enchantment.values()).map(BukkitAdapter::adapt).collect(Collectors.toSet());
|
||||
|
||||
@@ -20,44 +20,45 @@ package com.dfsek.terra.bukkit.handles;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
import com.dfsek.terra.bukkit.util.BukkitUtils;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
public class BukkitWorldHandle implements WorldHandle {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BukkitWorldHandle.class);
|
||||
private final BlockState air;
|
||||
|
||||
|
||||
public BukkitWorldHandle() {
|
||||
this.air = BukkitBlockState.newInstance(Material.AIR.createBlockData());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized @NotNull BlockState createBlockState(@NotNull String data) {
|
||||
if(data.equals("minecraft:grass")) { //TODO: remove in 7.0
|
||||
data = "minecraft:short_grass";
|
||||
logger.warn(
|
||||
"Translating minecraft:grass to minecraft:short_grass. In 1.20.3 minecraft:grass was renamed to minecraft:short_grass" +
|
||||
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
|
||||
"version of Terra.");
|
||||
}
|
||||
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(
|
||||
data); // somehow bukkit managed to make this not thread safe! :)
|
||||
data); // somehow bukkit managed to make this not thread safe! :)
|
||||
return BukkitBlockState.newInstance(bukkitData);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState air() {
|
||||
return air;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getEntity(@NotNull String id) {
|
||||
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
|
||||
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
|
||||
|
||||
return new BukkitEntityType(switch(entityID) {
|
||||
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.ENDER_CRYSTAL;
|
||||
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException("Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
|
||||
default -> org.bukkit.entity.EntityType.valueOf(entityID);
|
||||
});
|
||||
return BukkitUtils.getEntityType(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ import com.dfsek.terra.api.Platform;
|
||||
public class SpigotListener implements Listener {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpigotListener.class);
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public SpigotListener(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onEnderEye(EntitySpawnEvent e) {
|
||||
/*
|
||||
@@ -68,7 +68,7 @@ public class SpigotListener implements Listener {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onCartographerChange(VillagerAcquireTradeEvent e) {
|
||||
if(!(e.getEntity() instanceof Villager))
|
||||
@@ -85,7 +85,7 @@ public class SpigotListener implements Listener {
|
||||
e.setCancelled(true); // Cancel leveling if the villager is a Cartographer, to prevent crashing server.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onCartographerLevel(VillagerCareerChangeEvent e) {
|
||||
if(e.getProfession() == Villager.Profession.CARTOGRAPHER) {
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
package com.dfsek.terra.bukkit.nms;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dfsek.terra.bukkit.PlatformImpl;
|
||||
import com.dfsek.terra.bukkit.util.VersionUtil;
|
||||
|
||||
|
||||
public interface Initializer {
|
||||
String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
String NMS = VersionUtil.getMinecraftVersionInfo().toString().replace(".", "_");
|
||||
String TERRA_PACKAGE = Initializer.class.getPackageName();
|
||||
|
||||
static void init(PlatformImpl platform) {
|
||||
|
||||
static boolean init(PlatformImpl platform) {
|
||||
Logger logger = LoggerFactory.getLogger(Initializer.class);
|
||||
try {
|
||||
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSInitializer");
|
||||
String packageVersion = NMS;
|
||||
if(NMS.equals("v1_21_1")) {
|
||||
packageVersion = "v1_21";
|
||||
}
|
||||
|
||||
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
|
||||
try {
|
||||
Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance();
|
||||
initializer.initialize(platform);
|
||||
@@ -24,17 +29,28 @@ public interface Initializer {
|
||||
} 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!!!");
|
||||
String bypassKey = "IKnowThereAreNoNMSBindingsFor" + NMS + "ButIWillProceedAnyway";
|
||||
if(System.getProperty(bypassKey) == null) {
|
||||
logger.error("Because of this **TERRA HAS BEEN DISABLED**.");
|
||||
logger.error("Do not come ask us why it is not working.");
|
||||
logger.error("If you wish to proceed anyways, you can add the JVM System Property \"{}\" to enable the plugin.", bypassKey);
|
||||
return false;
|
||||
} else {
|
||||
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.");
|
||||
logger.error("We will not give you any support for issues that may arise.");
|
||||
logger.error("Since you enabled the \"{}\" flag, we won't disable Terra. But be warned.", bypassKey);
|
||||
}
|
||||
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.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void initialize(PlatformImpl plugin);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.dfsek.terra.bukkit.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
public class BukkitUtils {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BukkitUtils.class);
|
||||
|
||||
public static boolean isLiquid(BlockData blockState) {
|
||||
Material material = blockState.getMaterial();
|
||||
return material == Material.WATER || material == Material.LAVA;
|
||||
}
|
||||
|
||||
public static EntityType getEntityType(String id) {
|
||||
if(!id.contains(":")) { //TODO: remove in 7.0
|
||||
String newid = "minecraft:" + id.toLowerCase();
|
||||
;
|
||||
logger.warn(
|
||||
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
|
||||
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
|
||||
"version of Terra.");
|
||||
}
|
||||
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
|
||||
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
|
||||
|
||||
return new BukkitEntityType(switch(entityID) {
|
||||
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
|
||||
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
|
||||
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
|
||||
default -> org.bukkit.entity.EntityType.valueOf(entityID);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,20 @@
|
||||
package com.dfsek.terra.bukkit.util;
|
||||
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
|
||||
|
||||
import static io.papermc.lib.PaperLib.suggestPaper;
|
||||
|
||||
|
||||
public final class PaperUtil {
|
||||
public static void checkPaper(JavaPlugin main) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(main, () -> {
|
||||
public static void checkPaper(TerraBukkitPlugin plugin) {
|
||||
plugin.getAsyncScheduler().runDelayed(plugin, task -> {
|
||||
if(!PaperLib.isPaper()) {
|
||||
suggestPaper(main);
|
||||
suggestPaper(plugin);
|
||||
}
|
||||
}, 100L);
|
||||
}, 100L, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ import java.util.regex.Pattern;
|
||||
public final class VersionUtil {
|
||||
public static final SpigotVersionInfo SPIGOT_VERSION_INFO;
|
||||
public static final MinecraftVersionInfo MINECRAFT_VERSION_INFO;
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VersionUtil.class);
|
||||
|
||||
|
||||
static {
|
||||
SPIGOT_VERSION_INFO = new SpigotVersionInfo();
|
||||
|
||||
|
||||
MinecraftVersionInfo mcVersionInfo;
|
||||
try {
|
||||
mcVersionInfo = new MinecraftVersionInfo();
|
||||
@@ -27,28 +27,28 @@ public final class VersionUtil {
|
||||
}
|
||||
MINECRAFT_VERSION_INFO = mcVersionInfo;
|
||||
}
|
||||
|
||||
|
||||
public static MinecraftVersionInfo getMinecraftVersionInfo() {
|
||||
return MINECRAFT_VERSION_INFO;
|
||||
}
|
||||
|
||||
|
||||
public static SpigotVersionInfo getSpigotVersionInfo() {
|
||||
return SPIGOT_VERSION_INFO;
|
||||
}
|
||||
|
||||
|
||||
public static final class SpigotVersionInfo {
|
||||
private final boolean spigot;
|
||||
private final boolean paper;
|
||||
private final boolean mohist;
|
||||
|
||||
|
||||
|
||||
|
||||
public SpigotVersionInfo() {
|
||||
logger.debug("Parsing spigot version info...");
|
||||
|
||||
|
||||
paper = PaperLib.isPaper();
|
||||
spigot = PaperLib.isSpigot();
|
||||
|
||||
|
||||
|
||||
|
||||
boolean isMohist = false;
|
||||
try {
|
||||
Class.forName("com.mohistmc.MohistMC");
|
||||
@@ -56,73 +56,77 @@ public final class VersionUtil {
|
||||
isMohist = true;
|
||||
} catch(ClassNotFoundException ignore) { }
|
||||
this.mohist = isMohist;
|
||||
|
||||
|
||||
logger.debug("Spigot version info parsed successfully.");
|
||||
}
|
||||
|
||||
|
||||
public boolean isPaper() {
|
||||
return paper;
|
||||
}
|
||||
|
||||
|
||||
public boolean isMohist() {
|
||||
return mohist;
|
||||
}
|
||||
|
||||
|
||||
public boolean isSpigot() {
|
||||
return spigot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static final class MinecraftVersionInfo {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MinecraftVersionInfo.class);
|
||||
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("v?(\\d+)_(\\d+)_R(\\d+)");
|
||||
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?");
|
||||
private final int major;
|
||||
private final int minor;
|
||||
private final int patch;
|
||||
|
||||
|
||||
private MinecraftVersionInfo() {
|
||||
this(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
|
||||
this(Bukkit.getServer().getBukkitVersion().split("-")[0]);
|
||||
}
|
||||
|
||||
|
||||
private MinecraftVersionInfo(int major, int minor, int patch) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.patch = patch;
|
||||
}
|
||||
|
||||
|
||||
private MinecraftVersionInfo(String versionString) {
|
||||
Matcher versionMatcher = VERSION_PATTERN.matcher(versionString);
|
||||
if(versionMatcher.find()) {
|
||||
major = Integer.parseInt(versionMatcher.group(1));
|
||||
minor = Integer.parseInt(versionMatcher.group(2));
|
||||
patch = Integer.parseInt(versionMatcher.group(3));
|
||||
patch = versionMatcher.group(3) != null ? Integer.parseInt(versionMatcher.group(3)) : -1;
|
||||
} else {
|
||||
logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1.");
|
||||
|
||||
|
||||
major = -1;
|
||||
minor = -1;
|
||||
patch = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if(major == -1 && minor == -1 && patch == -1)
|
||||
return "Unknown";
|
||||
|
||||
return String.format("v%d.%d.%d", major, minor, patch);
|
||||
|
||||
if(patch >= 0) {
|
||||
return String.format("v%d.%d.%d", major, minor, patch);
|
||||
} else {
|
||||
return String.format("v%d.%d", major, minor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getMajor() {
|
||||
return major;
|
||||
}
|
||||
|
||||
|
||||
public int getMinor() {
|
||||
return minor;
|
||||
}
|
||||
|
||||
|
||||
public int getPatch() {
|
||||
return patch;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.dfsek.terra.bukkit.world;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -46,35 +45,20 @@ import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack;
|
||||
import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment;
|
||||
import com.dfsek.terra.transform.MapTransform;
|
||||
import com.dfsek.terra.transform.TransformerImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class to adapt Bukkit enums to Terra enums.
|
||||
*/
|
||||
public final class BukkitAdapter {
|
||||
public static TransformerImpl<TreeType, String> TREE_TRANSFORMER = new TransformerImpl.Builder<TreeType, String>()
|
||||
.addTransform(new MapTransform<TreeType, String>()
|
||||
.add(TreeType.COCOA_TREE, "JUNGLE_COCOA")
|
||||
.add(TreeType.BIG_TREE, "LARGE_OAK")
|
||||
.add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE")
|
||||
.add(TreeType.REDWOOD, "SPRUCE")
|
||||
.add(TreeType.TREE, "OAK")
|
||||
.add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE")
|
||||
.add(TreeType.SWAMP, "SWAMP_OAK"))
|
||||
.addTransform(TreeType::toString)
|
||||
.build();
|
||||
|
||||
|
||||
public static BlockState adapt(org.bukkit.block.data.BlockData data) {
|
||||
return BukkitBlockState.newInstance(data);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.block.data.BlockData adapt(BlockState data) {
|
||||
return ((BukkitBlockState) data).getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static Axis adapt(org.bukkit.Axis axis) {
|
||||
return switch(axis) {
|
||||
case X -> Axis.X;
|
||||
@@ -82,22 +66,22 @@ public final class BukkitAdapter {
|
||||
case Z -> Axis.Z;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static WorldProperties adapt(WorldInfo worldInfo) {
|
||||
return new BukkitWorldProperties(worldInfo);
|
||||
}
|
||||
|
||||
|
||||
public static WorldInfo adapt(WorldProperties properties) {
|
||||
return (WorldInfo) properties.getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static Half adapt(org.bukkit.block.data.Bisected.Half half) {
|
||||
return switch(half) {
|
||||
case BOTTOM -> Half.BOTTOM;
|
||||
case TOP -> Half.TOP;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static RedstoneConnection adapt(org.bukkit.block.data.type.RedstoneWire.Connection connection) {
|
||||
return switch(connection) {
|
||||
case NONE -> RedstoneConnection.NONE;
|
||||
@@ -105,7 +89,7 @@ public final class BukkitAdapter {
|
||||
case SIDE -> RedstoneConnection.SIDE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.block.data.type.RedstoneWire.Connection adapt(RedstoneConnection connection) {
|
||||
return switch(connection) {
|
||||
case SIDE -> org.bukkit.block.data.type.RedstoneWire.Connection.SIDE;
|
||||
@@ -113,7 +97,7 @@ public final class BukkitAdapter {
|
||||
case NONE -> org.bukkit.block.data.type.RedstoneWire.Connection.NONE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static RailShape adapt(org.bukkit.block.data.Rail.Shape shape) {
|
||||
return switch(shape) {
|
||||
case SOUTH_WEST -> RailShape.SOUTH_WEST;
|
||||
@@ -128,7 +112,7 @@ public final class BukkitAdapter {
|
||||
case EAST_WEST -> RailShape.EAST_WEST;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.block.data.Rail.Shape adapt(RailShape shape) {
|
||||
return switch(shape) {
|
||||
case EAST_WEST -> org.bukkit.block.data.Rail.Shape.EAST_WEST;
|
||||
@@ -143,8 +127,8 @@ public final class BukkitAdapter {
|
||||
case SOUTH_WEST -> org.bukkit.block.data.Rail.Shape.SOUTH_WEST;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static org.bukkit.block.data.Bisected.Half adapt(Half half) {
|
||||
return switch(half) {
|
||||
case TOP -> org.bukkit.block.data.Bisected.Half.TOP;
|
||||
@@ -152,7 +136,7 @@ public final class BukkitAdapter {
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.Axis adapt(Axis axis) {
|
||||
return switch(axis) {
|
||||
case Z -> org.bukkit.Axis.Z;
|
||||
@@ -160,75 +144,75 @@ public final class BukkitAdapter {
|
||||
case X -> org.bukkit.Axis.X;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 adapt(Location location) {
|
||||
return Vector3.of(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
|
||||
|
||||
public static Vector adapt(Vector3 vector3) {
|
||||
return new Vector(vector3.getX(), vector3.getY(), vector3.getZ());
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 adapt(Vector vector) {
|
||||
return Vector3.of(vector.getX(), vector.getY(), vector.getZ());
|
||||
}
|
||||
|
||||
|
||||
public static CommandSender adapt(org.bukkit.command.CommandSender sender) {
|
||||
return new BukkitCommandSender(sender);
|
||||
}
|
||||
|
||||
|
||||
public static Entity adapt(org.bukkit.entity.Entity entity) {
|
||||
return new BukkitEntity(entity);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.command.CommandSender adapt(CommandSender sender) {
|
||||
return ((BukkitCommandSender) sender).getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static ServerWorld adapt(org.bukkit.World world) {
|
||||
return new BukkitServerWorld(world);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.World adapt(ServerWorld world) {
|
||||
return (org.bukkit.World) world.getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static Chunk adapt(org.bukkit.Chunk chunk) {
|
||||
return new BukkitChunk(chunk);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.Chunk adapt(Chunk chunk) {
|
||||
return (org.bukkit.Chunk) chunk.getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static Enchantment adapt(org.bukkit.enchantments.Enchantment enchantment) {
|
||||
return new BukkitEnchantment(enchantment);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.enchantments.Enchantment adapt(Enchantment enchantment) {
|
||||
return ((BukkitEnchantment) enchantment).getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static Player adapt(com.dfsek.terra.api.entity.Player player) {
|
||||
return ((BukkitPlayer) player).getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static com.dfsek.terra.api.entity.Player adapt(Player player) {
|
||||
return new BukkitPlayer(player);
|
||||
}
|
||||
|
||||
|
||||
public static BukkitBlockTypeAndItem adapt(Material material) {
|
||||
return new BukkitBlockTypeAndItem(material);
|
||||
}
|
||||
|
||||
|
||||
public static Material adapt(BlockType type) {
|
||||
return ((BukkitBlockTypeAndItem) type).getHandle();
|
||||
}
|
||||
|
||||
|
||||
public static ItemStack adapt(org.bukkit.inventory.ItemStack in) {
|
||||
return new BukkitItemStack(in);
|
||||
}
|
||||
|
||||
|
||||
public static org.bukkit.inventory.ItemStack adapt(ItemStack in) {
|
||||
return ((BukkitItemStack) in).getHandle();
|
||||
}
|
||||
|
||||
@@ -26,41 +26,41 @@ import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
public class BukkitChunk implements Chunk {
|
||||
private final org.bukkit.Chunk delegate;
|
||||
|
||||
|
||||
public BukkitChunk(org.bukkit.Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.Chunk getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
delegate.getBlock(x, y, z).setBlockData(BukkitAdapter.adapt(data), physics);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||
delegate.getBlock(x, y, z).setBlockData(BukkitAdapter.adapt(blockState));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return BukkitAdapter.adapt(delegate.getBlock(x, y, z).getBlockData());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return BukkitAdapter.adapt(delegate.getWorld());
|
||||
|
||||
@@ -25,16 +25,16 @@ import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
public class BukkitPlatformBiome implements PlatformBiome, PropertyHolder {
|
||||
private final org.bukkit.block.Biome biome;
|
||||
private final Context context = new Context();
|
||||
|
||||
|
||||
public BukkitPlatformBiome(org.bukkit.block.Biome biome) {
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.block.Biome getHandle() {
|
||||
return biome;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return context;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.bukkit.world;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.LimitedRegion;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -20,6 +21,7 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
import com.dfsek.terra.bukkit.BukkitEntity;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
import com.dfsek.terra.bukkit.util.BukkitUtils;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
import com.dfsek.terra.bukkit.world.block.state.BukkitBlockEntity;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
@@ -30,114 +32,119 @@ public class BukkitProtoWorld implements ProtoWorld {
|
||||
private static final AtomicBoolean warn = new AtomicBoolean(true);
|
||||
private final LimitedRegion delegate;
|
||||
private final BlockState air;
|
||||
|
||||
|
||||
private final BiomeProvider biomeProvider;
|
||||
|
||||
|
||||
public BukkitProtoWorld(LimitedRegion delegate, BlockState air, BiomeProvider provider) {
|
||||
this.delegate = delegate;
|
||||
this.air = air;
|
||||
this.biomeProvider = provider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LimitedRegion getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
access(x, y, z, () -> {
|
||||
delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data));
|
||||
BlockData bukkitData = BukkitAdapter.adapt(data);
|
||||
delegate.setBlockData(x, y, z, bukkitData);
|
||||
if(physics) {
|
||||
delegate.scheduleBlockUpdate(x, y, z);
|
||||
if(BukkitUtils.isLiquid(bukkitData)) {
|
||||
delegate.scheduleFluidUpdate(x, y, z);
|
||||
} else {
|
||||
delegate.scheduleBlockUpdate(x, y, z);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return delegate.getWorld().getSeed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return delegate.getWorld().getMaxHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
return access(x, y, z, () -> BukkitBlockState.newInstance(delegate.getBlockData(x, y, z))).orElse(air);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return access(x, y, z, () -> BukkitBlockEntity.newInstance(delegate.getBlockState(x, y, z))).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return delegate.getWorld().getMinHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return access((int) x, (int) y, (int) z, () -> new BukkitEntity(
|
||||
delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle()))).orElse(
|
||||
null);
|
||||
delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle()))).orElse(
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getHandle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return biomeProvider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int centerChunkX() {
|
||||
return delegate.getCenterChunkX();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int centerChunkZ() {
|
||||
return delegate.getCenterChunkZ();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return new BukkitServerWorld(delegate.getWorld());
|
||||
}
|
||||
|
||||
|
||||
private <T> Optional<T> access(int x, int y, int z, Supplier<T> action) {
|
||||
if(delegate.isInRegion(x, y, z)) {
|
||||
return Optional.of(action.get());
|
||||
} else if(warn.getAndSet(false)) {
|
||||
LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z,
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
} else {
|
||||
LOGGER.debug("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z,
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
private void access(int x, int y, int z, Runnable action) {
|
||||
if(delegate.isInRegion(x, y, z)) {
|
||||
action.run();
|
||||
} else if(warn.getAndSet(false)) {
|
||||
LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z,
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
} else {
|
||||
LOGGER.debug("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z,
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
delegate.getCenterChunkX(), delegate.getCenterChunkZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,83 +36,83 @@ import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
public class BukkitServerWorld implements ServerWorld {
|
||||
private final org.bukkit.World delegate;
|
||||
|
||||
|
||||
public BukkitServerWorld(org.bukkit.World delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return new BukkitEntity(
|
||||
delegate.spawnEntity(new Location(delegate, x, y, z), ((BukkitEntityType) entityType).getHandle()));
|
||||
delegate.spawnEntity(new Location(delegate, x, y, z), ((BukkitEntityType) entityType).getHandle()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
delegate.getBlockAt(x, y, z).setBlockData(BukkitAdapter.adapt(data), physics);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return delegate.getSeed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return delegate.getMaxHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return BukkitAdapter.adapt(delegate.getChunkAt(x, z));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
return BukkitAdapter.adapt(delegate.getBlockAt(x, y, z).getBlockData());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return BukkitBlockEntity.newInstance(delegate.getBlockAt(x, y, z).getState());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return delegate.getMinHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getHandle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack().getBiomeProvider();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.World getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof BukkitServerWorld other)) return false;
|
||||
return other.getHandle().equals(delegate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
package com.dfsek.terra.bukkit.world;
|
||||
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
|
||||
|
||||
public class BukkitWorldProperties implements WorldProperties {
|
||||
private final WorldInfo delegate;
|
||||
|
||||
|
||||
public BukkitWorldProperties(WorldInfo delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return delegate.getSeed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return delegate.getMaxHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return delegate.getMinHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof WorldProperties that) {
|
||||
|
||||
@@ -28,46 +28,46 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitBlockTypeAndItem implements BlockType, Item {
|
||||
private final Material delegate;
|
||||
|
||||
|
||||
public BukkitBlockTypeAndItem(Material delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Material getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getDefaultState() {
|
||||
return BukkitAdapter.adapt(delegate.createBlockData());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return delegate.isOccluding();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isWater() {
|
||||
return delegate == Material.WATER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ItemStack newItemStack(int amount) {
|
||||
return BukkitAdapter.adapt(new org.bukkit.inventory.ItemStack(delegate, amount));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getMaxDurability() {
|
||||
return delegate.getMaxDurability();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof BukkitBlockTypeAndItem)) return false;
|
||||
|
||||
@@ -25,51 +25,51 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitBlockState implements BlockState {
|
||||
private final org.bukkit.block.data.BlockData delegate;
|
||||
|
||||
|
||||
protected BukkitBlockState(org.bukkit.block.data.BlockData delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
public static BlockState newInstance(org.bukkit.block.data.BlockData bukkitData) {
|
||||
return new BukkitBlockState(bukkitData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.block.data.BlockData getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(BlockState data) {
|
||||
return delegate.getMaterial() == ((BukkitBlockState) data).getHandle().getMaterial();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> boolean has(Property<T> property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> T get(Property<T> property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> BlockState set(Property<T> property, T value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockType getBlockType() {
|
||||
return BukkitAdapter.adapt(delegate.getMaterial());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAsString(boolean properties) {
|
||||
return delegate.getAsString(!properties);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return delegate.getMaterial().isAir();
|
||||
|
||||
@@ -30,48 +30,48 @@ import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
public class BukkitBlockEntity implements BlockEntity {
|
||||
private final org.bukkit.block.BlockState delegate;
|
||||
|
||||
|
||||
protected BukkitBlockEntity(org.bukkit.block.BlockState block) {
|
||||
this.delegate = block;
|
||||
}
|
||||
|
||||
|
||||
public static BukkitBlockEntity newInstance(org.bukkit.block.BlockState block) {
|
||||
if(block instanceof Container) return new BukkitContainer((Container) block);
|
||||
if(block instanceof Sign) return new BukkitSign((Sign) block);
|
||||
if(block instanceof CreatureSpawner) return new BukkitMobSpawner((CreatureSpawner) block);
|
||||
return new BukkitBlockEntity(block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.block.BlockState getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean update(boolean applyPhysics) {
|
||||
return delegate.update(true, applyPhysics);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vector3 getPosition() {
|
||||
return BukkitAdapter.adapt(delegate.getBlock().getLocation().toVector());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getY() {
|
||||
return delegate.getY();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState() {
|
||||
return BukkitBlockState.newInstance(delegate.getBlockData());
|
||||
|
||||
@@ -23,16 +23,16 @@ import com.dfsek.terra.bukkit.world.inventory.BukkitInventory;
|
||||
|
||||
|
||||
public class BukkitContainer extends BukkitBlockEntity implements Container {
|
||||
|
||||
|
||||
protected BukkitContainer(org.bukkit.block.Container block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean update(boolean applyPhysics) {
|
||||
return false; // This clears the inventory. we don't want that.
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import com.dfsek.terra.api.block.entity.MobSpawner;
|
||||
import com.dfsek.terra.api.block.entity.SerialState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.bukkit.util.BukkitUtils;
|
||||
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
|
||||
|
||||
|
||||
@@ -30,92 +31,92 @@ public class BukkitMobSpawner extends BukkitBlockEntity implements MobSpawner {
|
||||
protected BukkitMobSpawner(CreatureSpawner block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EntityType getSpawnedType() {
|
||||
return new BukkitEntityType(((CreatureSpawner) getHandle()).getSpawnedType());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSpawnedType(@NotNull EntityType creatureType) {
|
||||
((CreatureSpawner) getHandle()).setSpawnedType(((BukkitEntityType) creatureType).getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getDelay() {
|
||||
return ((CreatureSpawner) getHandle()).getDelay();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDelay(int delay) {
|
||||
((CreatureSpawner) getHandle()).setDelay(delay);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinSpawnDelay() {
|
||||
return ((CreatureSpawner) getHandle()).getMinSpawnDelay();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMinSpawnDelay(int delay) {
|
||||
((CreatureSpawner) getHandle()).setMinSpawnDelay(delay);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxSpawnDelay() {
|
||||
return ((CreatureSpawner) getHandle()).getMaxSpawnDelay();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMaxSpawnDelay(int delay) {
|
||||
((CreatureSpawner) getHandle()).setMaxSpawnDelay(delay);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSpawnCount() {
|
||||
return ((CreatureSpawner) getHandle()).getSpawnCount();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSpawnCount(int spawnCount) {
|
||||
((CreatureSpawner) getHandle()).setSpawnCount(spawnCount);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxNearbyEntities() {
|
||||
return ((CreatureSpawner) getHandle()).getMaxNearbyEntities();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMaxNearbyEntities(int maxNearbyEntities) {
|
||||
((CreatureSpawner) getHandle()).setMaxNearbyEntities(maxNearbyEntities);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRequiredPlayerRange() {
|
||||
return ((CreatureSpawner) getHandle()).getRequiredPlayerRange();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRequiredPlayerRange(int requiredPlayerRange) {
|
||||
((CreatureSpawner) getHandle()).setRequiredPlayerRange(requiredPlayerRange);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSpawnRange() {
|
||||
return ((CreatureSpawner) getHandle()).getSpawnRange();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSpawnRange(int spawnRange) {
|
||||
((CreatureSpawner) getHandle()).setSpawnRange(spawnRange);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyState(String state) {
|
||||
SerialState.parse(state).forEach((k, v) -> {
|
||||
switch(k) {
|
||||
case "type" -> setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase())));
|
||||
case "type" -> setSpawnedType(BukkitUtils.getEntityType(v));
|
||||
case "delay" -> setDelay(Integer.parseInt(v));
|
||||
case "min_delay" -> setMinSpawnDelay(Integer.parseInt(v));
|
||||
case "max_delay" -> setMaxSpawnDelay(Integer.parseInt(v));
|
||||
|
||||
@@ -28,22 +28,22 @@ public class BukkitSign extends BukkitBlockEntity implements Sign {
|
||||
protected BukkitSign(org.bukkit.block.Sign block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
|
||||
((org.bukkit.block.Sign) getHandle()).setLine(index, line);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull String[] getLines() {
|
||||
return ((org.bukkit.block.Sign) getHandle()).getLines();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull String getLine(int index) throws IndexOutOfBoundsException {
|
||||
return ((org.bukkit.block.Sign) getHandle()).getLine(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyState(String state) {
|
||||
SerialState.parse(state).forEach((k, v) -> {
|
||||
|
||||
@@ -22,11 +22,11 @@ import com.dfsek.terra.api.entity.EntityType;
|
||||
|
||||
public class BukkitEntityType implements EntityType {
|
||||
private final org.bukkit.entity.EntityType delegate;
|
||||
|
||||
|
||||
public BukkitEntityType(org.bukkit.entity.EntityType delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.EntityType getHandle() {
|
||||
return delegate;
|
||||
|
||||
@@ -23,27 +23,27 @@ import com.dfsek.terra.api.inventory.ItemStack;
|
||||
|
||||
public class BukkitInventory implements Inventory {
|
||||
private final org.bukkit.inventory.Inventory delegate;
|
||||
|
||||
|
||||
public BukkitInventory(org.bukkit.inventory.Inventory delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack newStack) {
|
||||
delegate.setItem(slot, ((BukkitItemStack) newStack).getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return delegate.getSize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int slot) {
|
||||
org.bukkit.inventory.ItemStack itemStack = delegate.getItem(slot);
|
||||
return itemStack == null ? null : new BukkitItemStack(itemStack);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.Inventory getHandle() {
|
||||
return delegate;
|
||||
|
||||
@@ -31,26 +31,26 @@ import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment;
|
||||
|
||||
public class BukkitItemMeta implements ItemMeta {
|
||||
private final org.bukkit.inventory.meta.ItemMeta delegate;
|
||||
|
||||
|
||||
protected BukkitItemMeta(org.bukkit.inventory.meta.ItemMeta delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
public static BukkitItemMeta newInstance(org.bukkit.inventory.meta.ItemMeta delegate) {
|
||||
if(delegate instanceof Damageable) return new BukkitDamageable((Damageable) delegate);
|
||||
return new BukkitItemMeta(delegate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.meta.ItemMeta getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addEnchantment(Enchantment enchantment, int level) {
|
||||
delegate.addEnchant(((BukkitEnchantment) enchantment).getHandle(), level, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<Enchantment, Integer> getEnchantments() {
|
||||
Map<Enchantment, Integer> map = new HashMap<>();
|
||||
|
||||
@@ -25,36 +25,36 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
public class BukkitItemStack implements ItemStack {
|
||||
private final org.bukkit.inventory.ItemStack delegate;
|
||||
|
||||
|
||||
public BukkitItemStack(org.bukkit.inventory.ItemStack delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getAmount() {
|
||||
return delegate.getAmount();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAmount(int i) {
|
||||
delegate.setAmount(i);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Item getType() {
|
||||
return BukkitAdapter.adapt(delegate.getType());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ItemMeta getItemMeta() {
|
||||
return BukkitItemMeta.newInstance(delegate.getItemMeta());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setItemMeta(ItemMeta meta) {
|
||||
delegate.setItemMeta(((BukkitItemMeta) meta).getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.inventory.ItemStack getHandle() {
|
||||
return delegate;
|
||||
|
||||
@@ -25,17 +25,17 @@ public class BukkitDamageable extends BukkitItemMeta implements Damageable {
|
||||
public BukkitDamageable(org.bukkit.inventory.meta.Damageable delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getDamage() {
|
||||
return ((org.bukkit.inventory.meta.Damageable) getHandle()).getDamage();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDamage(int damage) {
|
||||
((org.bukkit.inventory.meta.Damageable) getHandle()).setDamage(damage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
return ((org.bukkit.inventory.meta.Damageable) getHandle()).hasDamage();
|
||||
|
||||
@@ -24,31 +24,31 @@ import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack;
|
||||
|
||||
public class BukkitEnchantment implements Enchantment {
|
||||
private final org.bukkit.enchantments.Enchantment delegate;
|
||||
|
||||
|
||||
public BukkitEnchantment(org.bukkit.enchantments.Enchantment delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.bukkit.enchantments.Enchantment getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canEnchantItem(ItemStack itemStack) {
|
||||
return delegate.canEnchantItem(((BukkitItemStack) itemStack).getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean conflictsWith(Enchantment other) {
|
||||
return delegate.conflictsWith(((BukkitEnchantment) other).getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return delegate.getKey().toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxLevel() {
|
||||
return delegate.getMaxLevel();
|
||||
|
||||
@@ -2,7 +2,8 @@ name: "Terra"
|
||||
main: "com.dfsek.terra.bukkit.TerraBukkitPlugin"
|
||||
version: "@VERSION@"
|
||||
load: "STARTUP"
|
||||
author: dfsek
|
||||
authors: [ "dfsek", "duplexsystem", "Astrash", "solonovamax", "Sancires", "Aureus", "RogueShade" ]
|
||||
website: "@WIKI@"
|
||||
api-version: "1.13"
|
||||
api-version: "1.21.1"
|
||||
description: "@DESCRIPTION@"
|
||||
folia-supported: true
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle("1.18.2-R0.1-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn("reobfJar")
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class);
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) Registries.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(
|
||||
biome,
|
||||
biomeRegistry.get(vanillaMinecraftKey) // get
|
||||
);
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra",
|
||||
NMSBiomeInjector.createBiomeID(
|
||||
pack, key)));
|
||||
|
||||
BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform);
|
||||
biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb)
|
||||
.ifPresentOrElse(
|
||||
vanilla -> terraBiomes
|
||||
.forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb)
|
||||
.ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug(
|
||||
vanilla.unwrapKey()
|
||||
.orElseThrow()
|
||||
.location() +
|
||||
" (vanilla for " +
|
||||
terra.unwrapKey()
|
||||
.orElseThrow()
|
||||
.location() +
|
||||
": " +
|
||||
vanilla.tags()
|
||||
.toList());
|
||||
|
||||
vanilla.tags()
|
||||
.forEach(
|
||||
tag -> collect
|
||||
.computeIfAbsent(
|
||||
tag,
|
||||
t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error(
|
||||
"No such biome: {}",
|
||||
tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags(); // clearTags
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); // populateTags
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
|
||||
public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.map(registry::getOrCreateHolder);
|
||||
}
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder(); // Builder
|
||||
|
||||
|
||||
builder.biomeCategory(Reflection.BIOME.getBiomeCategory(vanilla))
|
||||
.precipitation(vanilla.getPrecipitation()) // getPrecipitation
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.downfall(vanilla.getDownfall());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
return builder.build(); // build()
|
||||
}
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
|
||||
public class NMSBiomeProvider extends BiomeSource {
|
||||
private final BiomeProvider delegate;
|
||||
private final BiomeSource vanilla;
|
||||
private final long seed;
|
||||
private final Registry<Biome> biomeRegistry = Registries.biomeRegistry();
|
||||
|
||||
public NMSBiomeProvider(BiomeProvider delegate, BiomeSource vanilla, long seed) {
|
||||
super(delegate.stream()
|
||||
.map(biome -> Registries.biomeRegistry()
|
||||
.getOrCreateHolder(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey())));
|
||||
this.delegate = delegate;
|
||||
this.vanilla = vanilla;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BiomeSource withSeed(long seed) {
|
||||
return new NMSBiomeProvider(delegate, vanilla, seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getOrCreateHolder(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome())
|
||||
.getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
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.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
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 org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
private static final Lazy<List<ChunkPos>> EMPTY = Lazy.lazy(List::of);
|
||||
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<ChunkPos>>> ringPositions = new Object2ObjectArrayMap<>();
|
||||
private volatile boolean rings = false;
|
||||
|
||||
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
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull BiomeManager biomeAccess,
|
||||
@NotNull StructureFeatureManager structureAccessor,
|
||||
@NotNull ChunkAccess chunk, GenerationStep.@NotNull Carving generationStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureFeatureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull StructureFeatureManager structureAccessor,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, structureAccessor, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureFeatureManager structures, @NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height) {
|
||||
/*
|
||||
BlockState[] array = new BlockState[height.getHeight()];
|
||||
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 NoiseColumn(getMinY(), array);
|
||||
*/
|
||||
return vanilla.getBaseColumn(x, z, height);
|
||||
}
|
||||
|
||||
@Override // withSeed
|
||||
public @NotNull ChunkGenerator withSeed(long seed) {
|
||||
return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion regionlimitedworldaccess) {
|
||||
vanilla.spawnOriginalMobs(regionlimitedworldaccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sampler climateSampler() {
|
||||
return Climate.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, Heightmap.@NotNull Types heightmap, @NotNull LevelHeightAccessor world) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<ChunkPos> getRingPositionsFor(@NotNull ConcentricRingsStructurePlacement concentricringsstructureplacement) {
|
||||
ensureStructuresGenerated();
|
||||
return ringPositions.getOrDefault(concentricringsstructureplacement, EMPTY).value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void ensureStructuresGenerated() {
|
||||
if(!this.rings) {
|
||||
super.ensureStructuresGenerated();
|
||||
this.populateStrongholdData();
|
||||
this.rings = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void populateStrongholdData() {
|
||||
LOGGER.info("Generating safe stronghold data. This may take up to a minute.");
|
||||
Set<Holder<Biome>> set = this.runtimeBiomeSource.possibleBiomes();
|
||||
possibleStructureSets().map(Holder::value).forEach((holder) -> { // we dont need the spigot crap because it doesnt touch concentric.
|
||||
StructurePlacement structureplacement = holder.placement();
|
||||
if(structureplacement instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) {
|
||||
if(holder.structures().stream().anyMatch((structureset_a1) -> structureset_a1.generatesInMatchingBiome(set::contains))) {
|
||||
this.ringPositions.put(concentricringsstructureplacement,
|
||||
Lazy.lazy(() -> this.generateRingPositions(holder, concentricringsstructureplacement)));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<ChunkPos> generateRingPositions(StructureSet holder,
|
||||
ConcentricRingsStructurePlacement concentricringsstructureplacement) { // Spigot
|
||||
if(concentricringsstructureplacement.count() == 0) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<ChunkPos> list = new ArrayList<>();
|
||||
Set<Holder<Biome>> set = holder
|
||||
.structures()
|
||||
.stream()
|
||||
.flatMap((structureset_a) -> structureset_a.structure().value().biomes().stream())
|
||||
.collect(Collectors.toSet());
|
||||
int i = concentricringsstructureplacement.distance();
|
||||
int j = concentricringsstructureplacement.count();
|
||||
int k = concentricringsstructureplacement.spread();
|
||||
Random random = new Random();
|
||||
|
||||
// Paper start
|
||||
if(this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) ==
|
||||
net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) {
|
||||
random.setSeed(this.conf.strongholdSeed);
|
||||
} else {
|
||||
// Paper end
|
||||
random.setSeed(this.ringPlacementSeed);
|
||||
} // Paper
|
||||
double d0 = random.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
int l = 0;
|
||||
int i1 = 0;
|
||||
|
||||
for(int j1 = 0; j1 < j; ++j1) {
|
||||
double d1 = (double) (4 * i + i * i1 * 6) + (random.nextDouble() - 0.5D) * (double) i * 2.5D;
|
||||
int k1 = (int) Math.round(Math.cos(d0) * d1);
|
||||
int l1 = (int) Math.round(Math.sin(d0) * d1);
|
||||
int i2 = SectionPos.sectionToBlockCoord(k1, 8);
|
||||
int j2 = SectionPos.sectionToBlockCoord(l1, 8);
|
||||
|
||||
Objects.requireNonNull(set);
|
||||
Pair<BlockPos, Holder<Biome>> pair = this.biomeSource.findBiomeHorizontal(i2, 0, j2, 112, set::contains, random,
|
||||
this.climateSampler());
|
||||
|
||||
if(pair != null) {
|
||||
BlockPos blockposition = pair.getFirst();
|
||||
|
||||
k1 = SectionPos.blockToSectionCoord(blockposition.getX());
|
||||
l1 = SectionPos.blockToSectionCoord(blockposition.getZ());
|
||||
}
|
||||
|
||||
list.add(new ChunkPos(k1, l1));
|
||||
d0 += 6.283185307179586D / (double) k;
|
||||
++l;
|
||||
if(l == k) {
|
||||
++i1;
|
||||
l = 0;
|
||||
k += 2 * k / (i1 + 1);
|
||||
k = Math.min(k, j - j1);
|
||||
d0 += random.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(@NotNull List<String> arg0, @NotNull BlockPos arg1) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
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) {
|
||||
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
|
||||
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) {
|
||||
INJECT_LOCK.lock();
|
||||
INJECTED.add(event.getWorld());
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.getBiomeSource(), craftWorld.getSeed());
|
||||
NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
custom.conf = vanilla.conf; // world config from Spigot
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = custom;
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator.ensureStructuresGenerated(); // generate stronghold data now
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final BiomeProxy BIOME;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(Biome.class)
|
||||
public interface BiomeProxy {
|
||||
@FieldGetter("biomeCategory")
|
||||
Biome.BiomeCategory getBiomeCategory(Biome instance);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_18_R2;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
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> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow( // getRegistry
|
||||
key
|
||||
);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registry.BIOME_REGISTRY);
|
||||
}
|
||||
|
||||
public static Registry<StructureSet> structureSet() {
|
||||
return getRegistry(Registry.STRUCTURE_SET_REGISTRY);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle("1.19-R0.1-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn("reobfJar")
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);
|
||||
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) Registries.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(
|
||||
biome,
|
||||
Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)) // get
|
||||
);
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY,
|
||||
new ResourceLocation("terra",
|
||||
NMSBiomeInjector.createBiomeID(pack, key)));
|
||||
|
||||
BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform);
|
||||
biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb)
|
||||
.ifPresentOrElse(
|
||||
vanilla -> terraBiomes
|
||||
.forEach(tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb)
|
||||
.ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug(
|
||||
vanilla.unwrapKey()
|
||||
.orElseThrow()
|
||||
.location() +
|
||||
" (vanilla for " +
|
||||
terra.unwrapKey()
|
||||
.orElseThrow()
|
||||
.location() +
|
||||
": " +
|
||||
vanilla.tags()
|
||||
.toList());
|
||||
|
||||
vanilla.tags()
|
||||
.forEach(
|
||||
tag -> collect
|
||||
.computeIfAbsent(
|
||||
tag,
|
||||
t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error(
|
||||
"No such biome: {}",
|
||||
tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags();
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect));
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
|
||||
public class NMSBiomeProvider extends BiomeSource {
|
||||
private final BiomeProvider delegate;
|
||||
private final long seed;
|
||||
private final Registry<Biome> biomeRegistry = Registries.biomeRegistry();
|
||||
|
||||
public NMSBiomeProvider(BiomeProvider delegate, long seed) {
|
||||
super(delegate.stream()
|
||||
.map(biome -> Registries.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey())));
|
||||
this.delegate = delegate;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed)
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import com.dfsek.terra.bukkit.config.PreLoadCompatibilityOptions;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.FunctionContext;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.SinglePointContext;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet.StructureSelectionEntry;
|
||||
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
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<ChunkPos>>> ringPositions = new Object2ObjectArrayMap<>();
|
||||
private volatile boolean rings = false;
|
||||
|
||||
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
|
||||
super(Registries.structureSet(), Optional.empty(), biomeProvider);
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
this.vanilla = vanilla;
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull RandomState noiseConfig, @NotNull BiomeManager world,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk, @NotNull Carving carverStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureManager structures, @NotNull RandomState noiseConfig,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion region) {
|
||||
vanilla.spawnOriginalMobs(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(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.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), ((CraftBlockData) ((BukkitBlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
/*
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
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 NoiseColumn(getMinY(), array);
|
||||
|
||||
*/
|
||||
return vanilla.getBaseColumn(x, z, world, noiseConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(@NotNull List<String> text, @NotNull RandomState noiseConfig, @NotNull BlockPos pos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureStructuresGenerated(@NotNull RandomState noiseConfig) {
|
||||
if(!this.rings) {
|
||||
super.ensureStructuresGenerated(noiseConfig);
|
||||
this.populateStrongholdData(noiseConfig);
|
||||
this.rings = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChunkPos> getRingPositionsFor(@NotNull ConcentricRingsStructurePlacement structurePlacement,
|
||||
@NotNull RandomState noiseConfig) {
|
||||
ensureStructuresGenerated(noiseConfig);
|
||||
return ringPositions.get(structurePlacement).value();
|
||||
}
|
||||
|
||||
private void populateStrongholdData(RandomState noiseConfig) {
|
||||
LOGGER.info("Generating safe stronghold data. This may take up to a minute.");
|
||||
Set<Holder<Biome>> set = this.biomeSource.possibleBiomes();
|
||||
possibleStructureSets().map(Holder::value).forEach((holder) -> {
|
||||
boolean match = false;
|
||||
for(StructureSelectionEntry structureset_a : holder.structures()) {
|
||||
Structure structure = structureset_a.structure().value();
|
||||
Stream<Holder<Biome>> stream = structure.biomes().stream();
|
||||
if(stream.anyMatch(set::contains)) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(match) {
|
||||
if(holder.placement() instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) {
|
||||
this.ringPositions.put(concentricringsstructureplacement, Lazy.lazy(
|
||||
() -> this.generateRingPositions(holder, noiseConfig, concentricringsstructureplacement)));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<ChunkPos> generateRingPositions(StructureSet holder, RandomState randomstate,
|
||||
ConcentricRingsStructurePlacement concentricringsstructureplacement) { // Spigot
|
||||
if(concentricringsstructureplacement.count() == 0) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<ChunkPos> list = new ArrayList<>();
|
||||
int i = concentricringsstructureplacement.distance();
|
||||
int j = concentricringsstructureplacement.count();
|
||||
int k = concentricringsstructureplacement.spread();
|
||||
HolderSet<Biome> holderset = concentricringsstructureplacement.preferredBiomes();
|
||||
RandomSource randomsource = RandomSource.create();
|
||||
|
||||
if(this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) ==
|
||||
net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) {
|
||||
randomsource.setSeed(this.conf.strongholdSeed);
|
||||
} else {
|
||||
randomsource.setSeed(randomstate.legacyLevelSeed());
|
||||
}
|
||||
double d0 = randomsource.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
int l = 0;
|
||||
int i1 = 0;
|
||||
|
||||
for(int j1 = 0; j1 < j; ++j1) {
|
||||
double d1 = (double) (4 * i + i * i1 * 6) + (randomsource.nextDouble() - 0.5D) * (double) i * 2.5D;
|
||||
int k1 = (int) Math.round(Math.cos(d0) * d1);
|
||||
int l1 = (int) Math.round(Math.sin(d0) * d1);
|
||||
int i2 = SectionPos.sectionToBlockCoord(k1, 8);
|
||||
int j2 = SectionPos.sectionToBlockCoord(l1, 8);
|
||||
|
||||
Objects.requireNonNull(holderset);
|
||||
Pair<BlockPos, Holder<Biome>> pair = this.biomeSource.findBiomeHorizontal(i2, 0, j2, 112, holderset::contains, randomsource,
|
||||
randomstate.sampler());
|
||||
|
||||
if(pair != null) {
|
||||
BlockPos blockposition = pair.getFirst();
|
||||
|
||||
k1 = SectionPos.blockToSectionCoord(blockposition.getX());
|
||||
l1 = SectionPos.blockToSectionCoord(blockposition.getZ());
|
||||
}
|
||||
|
||||
list.add(new ChunkPos(k1, l1));
|
||||
d0 += 6.283185307179586D / (double) k;
|
||||
++l;
|
||||
if(l == k) {
|
||||
++i1;
|
||||
l = 0;
|
||||
k += 2 * k / (i1 + 1);
|
||||
k = Math.min(k, j - j1);
|
||||
d0 += randomsource.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) {
|
||||
INJECT_LOCK.lock();
|
||||
INJECTED.add(event.getWorld());
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
|
||||
NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
custom.conf = vanilla.conf; // world config from Spigot
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = custom;
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||
|
||||
|
||||
public class Registries {
|
||||
private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow( // getRegistry
|
||||
key
|
||||
);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registry.BIOME_REGISTRY);
|
||||
}
|
||||
|
||||
public static Registry<StructureSet> structureSet() {
|
||||
return getRegistry(Registry.STRUCTURE_SET_REGISTRY);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle("1.19.3-R0.1-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn("reobfJar")
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);
|
||||
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))
|
||||
);
|
||||
|
||||
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
|
||||
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb).ifPresentOrElse(
|
||||
vanilla -> terraBiomes.forEach(
|
||||
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug("{} (vanilla for {}): {}",
|
||||
vanilla.unwrapKey().orElseThrow().location(),
|
||||
terra.unwrapKey().orElseThrow().location(),
|
||||
vanilla.tags().toList());
|
||||
vanilla.tags()
|
||||
.forEach(tag -> collect
|
||||
.computeIfAbsent(tag, t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags();
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect));
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
|
||||
public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.flatMap(registry::getHolder);
|
||||
}
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder();
|
||||
|
||||
builder
|
||||
.precipitation(vanilla.getPrecipitation())
|
||||
.downfall(vanilla.getDownfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
// grass
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
|
||||
public class NMSBiomeProvider extends BiomeSource {
|
||||
private final BiomeProvider delegate;
|
||||
private final long seed;
|
||||
private final Registry<Biome> biomeRegistry = RegistryFetcher.biomeRegistry();
|
||||
|
||||
public NMSBiomeProvider(BiomeProvider delegate, long seed) {
|
||||
super(delegate.stream()
|
||||
.map(biome -> RegistryFetcher.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey())));
|
||||
this.delegate = delegate;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed)
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.SinglePointContext;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
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.config.PreLoadCompatibilityOptions;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
|
||||
|
||||
private final ChunkGenerator vanilla;
|
||||
private final ConfigPack pack;
|
||||
|
||||
private final long seed;
|
||||
|
||||
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
|
||||
super(biomeProvider);
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
this.vanilla = vanilla;
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull RandomState noiseConfig, @NotNull BiomeManager world,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk, @NotNull Carving carverStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureManager structures, @NotNull RandomState noiseConfig,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion region) {
|
||||
vanilla.spawnOriginalMobs(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(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.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), ((CraftBlockData) ((BukkitBlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
/*
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
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 NoiseColumn(getMinY(), array);
|
||||
|
||||
*/
|
||||
return vanilla.getBaseColumn(x, z, world, noiseConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(@NotNull List<String> text, @NotNull RandomState noiseConfig, @NotNull BlockPos pos) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_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) {
|
||||
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
|
||||
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_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.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.CraftServer;
|
||||
|
||||
|
||||
public class RegistryFetcher {
|
||||
private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow(key);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registries.BIOME);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle("1.19.4-R0.1-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn("reobfJar")
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);
|
||||
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))
|
||||
);
|
||||
|
||||
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
|
||||
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb).ifPresentOrElse(
|
||||
vanilla -> terraBiomes.forEach(
|
||||
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug("{} (vanilla for {}): {}",
|
||||
vanilla.unwrapKey().orElseThrow().location(),
|
||||
terra.unwrapKey().orElseThrow().location(),
|
||||
vanilla.tags().toList());
|
||||
vanilla.tags()
|
||||
.forEach(tag -> collect
|
||||
.computeIfAbsent(tag, t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags();
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect));
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
import static net.minecraft.world.level.biome.Biome.ClimateSettings;
|
||||
import static net.minecraft.world.level.biome.Biome.Precipitation;
|
||||
|
||||
public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.flatMap(registry::getHolder);
|
||||
}
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder();
|
||||
|
||||
builder
|
||||
.downfall(vanilla.climateSettings.downfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
// grass
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
|
||||
public class NMSBiomeProvider extends BiomeSource {
|
||||
private final BiomeProvider delegate;
|
||||
private final long seed;
|
||||
private final Registry<Biome> biomeRegistry = RegistryFetcher.biomeRegistry();
|
||||
|
||||
public NMSBiomeProvider(BiomeProvider delegate, long seed) {
|
||||
super();
|
||||
this.delegate = delegate;
|
||||
this.seed = seed;
|
||||
}
|
||||
@Override
|
||||
protected Stream<Holder<Biome>> collectPossibleBiomes() {
|
||||
return delegate.stream()
|
||||
.map(biome -> RegistryFetcher.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed)
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.SinglePointContext;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
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.config.PreLoadCompatibilityOptions;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
|
||||
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
|
||||
|
||||
private final ChunkGenerator vanilla;
|
||||
private final ConfigPack pack;
|
||||
|
||||
private final long seed;
|
||||
|
||||
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
|
||||
super(biomeProvider);
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
this.vanilla = vanilla;
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull RandomState noiseConfig, @NotNull BiomeManager world,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk, @NotNull Carving carverStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureManager structures, @NotNull RandomState noiseConfig,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion region) {
|
||||
vanilla.spawnOriginalMobs(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(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.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), ((CraftBlockData) ((BukkitBlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
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 NoiseColumn(getMinY(), array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDebugScreenInfo(@NotNull List<String> text, @NotNull RandomState noiseConfig, @NotNull BlockPos pos) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
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) {
|
||||
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
|
||||
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) {
|
||||
INJECT_LOCK.lock();
|
||||
INJECTED.add(event.getWorld());
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
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.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
||||
|
||||
|
||||
public class RegistryFetcher {
|
||||
private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow(key);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registries.BIOME);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
import static net.minecraft.world.level.biome.Biome.ClimateSettings;
|
||||
import static net.minecraft.world.level.biome.Biome.Precipitation;
|
||||
|
||||
public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.flatMap(registry::getHolder);
|
||||
}
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder();
|
||||
|
||||
builder
|
||||
.downfall(vanilla.climateSettings.downfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
// grass
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
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) {
|
||||
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
|
||||
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) {
|
||||
INJECT_LOCK.lock();
|
||||
INJECTED.add(event.getWorld());
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
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.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
apply(plugin = "io.papermc.paperweight.userdev")
|
||||
|
||||
repositories {
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":platforms:bukkit:common"))
|
||||
paperDevBundle(Versions.Bukkit.paperDevBundle)
|
||||
implementation("xyz.jpenilla", "reflection-remapper", "0.1.0-SNAPSHOT")
|
||||
implementation("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
@@ -27,72 +27,73 @@ import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
|
||||
public class AwfulBukkitHacks {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);
|
||||
|
||||
|
||||
private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
|
||||
|
||||
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
|
||||
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
|
||||
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
|
||||
ResourceLocation vanillaMinecraftKey = ResourceLocation.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
|
||||
vanillaBukkitKey.getKey());
|
||||
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
|
||||
|
||||
|
||||
ResourceKey<Biome> delegateKey = ResourceKey.create(
|
||||
Registries.BIOME,
|
||||
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))
|
||||
);
|
||||
|
||||
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
|
||||
Registries.BIOME,
|
||||
ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key))
|
||||
);
|
||||
|
||||
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, RegistrationInfo.BUILT_IN);
|
||||
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
|
||||
|
||||
|
||||
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
|
||||
|
||||
|
||||
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
|
||||
|
||||
|
||||
LOGGER.debug("Registered biome: " + delegateKey);
|
||||
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
.getTags() // streamKeysAndEntries
|
||||
.collect(HashMap::new,
|
||||
(map, pair) ->
|
||||
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
|
||||
HashMap::putAll);
|
||||
|
||||
terraBiomeMap
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb).ifPresentOrElse(
|
||||
vanilla -> terraBiomes.forEach(
|
||||
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug("{} (vanilla for {}): {}",
|
||||
vanilla.unwrapKey().orElseThrow().location(),
|
||||
terra.unwrapKey().orElseThrow().location(),
|
||||
vanilla.tags().toList());
|
||||
vanilla.tags()
|
||||
.forEach(tag -> collect
|
||||
.computeIfAbsent(tag, t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
.forEach((vb, terraBiomes) ->
|
||||
NMSBiomeInjector.getEntry(biomeRegistry, vb).ifPresentOrElse(
|
||||
vanilla -> terraBiomes.forEach(
|
||||
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
|
||||
terra -> {
|
||||
LOGGER.debug("{} (vanilla for {}): {}",
|
||||
vanilla.unwrapKey().orElseThrow().location(),
|
||||
terra.unwrapKey().orElseThrow().location(),
|
||||
vanilla.tags().toList());
|
||||
vanilla.tags()
|
||||
.forEach(tag -> collect
|
||||
.computeIfAbsent(tag, t -> new ArrayList<>())
|
||||
.add(terra));
|
||||
},
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
biomeRegistry.resetTags();
|
||||
biomeRegistry.bindTags(ImmutableMap.copyOf(collect));
|
||||
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
@@ -18,60 +18,59 @@ public class NMSBiomeInjector {
|
||||
|
||||
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
|
||||
return registry.getOptional(identifier)
|
||||
.flatMap(registry::getResourceKey)
|
||||
.map(registry::getOrCreateHolderOrThrow);
|
||||
.flatMap(registry::getResourceKey)
|
||||
.flatMap(registry::getHolder);
|
||||
}
|
||||
|
||||
|
||||
public static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Biome.BiomeBuilder builder = new Biome.BiomeBuilder();
|
||||
|
||||
|
||||
builder
|
||||
.precipitation(vanilla.getPrecipitation())
|
||||
.downfall(vanilla.getDownfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
.downfall(vanilla.climateSettings.downfall())
|
||||
.temperature(vanilla.getBaseTemperature())
|
||||
.mobSpawnSettings(vanilla.getMobSettings())
|
||||
.generationSettings(vanilla.getGenerationSettings());
|
||||
|
||||
|
||||
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
|
||||
|
||||
|
||||
effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
|
||||
|
||||
|
||||
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
|
||||
|
||||
|
||||
effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
// grass
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
|
||||
vanilla.getAmbientLoop().ifPresent(effects::ambientLoopSound);
|
||||
vanilla.getAmbientAdditions().ifPresent(effects::ambientAdditionsSound);
|
||||
vanilla.getAmbientMood().ifPresent(effects::ambientMoodSound);
|
||||
vanilla.getBackgroundMusic().ifPresent(effects::backgroundMusic);
|
||||
vanilla.getAmbientParticle().ifPresent(effects::ambientParticle);
|
||||
|
||||
|
||||
builder.specialEffects(effects.build());
|
||||
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {
|
||||
return pack.getID()
|
||||
.toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT);
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.Holder;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
|
||||
@@ -23,25 +24,30 @@ public class NMSBiomeProvider extends BiomeSource {
|
||||
this.delegate = delegate;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Holder<Biome>> collectPossibleBiomes() {
|
||||
return delegate.stream()
|
||||
.map(biome -> RegistryFetcher.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey()));
|
||||
return delegate.stream()
|
||||
.map(biome -> RegistryFetcher.biomeRegistry()
|
||||
.getHolderOrThrow(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends BiomeSource> codec() {
|
||||
return BiomeSource.CODEC;
|
||||
protected @NotNull MapCodec<? extends BiomeSource> codec() {
|
||||
return MapCodec.assumeMapUnsafe(BiomeSource.CODEC);
|
||||
// return MapCodec.unit(null);
|
||||
// BuiltInRegistries.BIOME_SOURCE.byNameCodec().dispatchMap(this::codec, Function.identity());
|
||||
// BuiltInRegistries.BIOME_SOURCE.byNameCodec().dispatchStable(BiomeSource::codec, Function.identity());
|
||||
// return BiomeSource.CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
|
||||
return biomeRegistry.getHolderOrThrow(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed)
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
.getPlatformBiome()).getContext()
|
||||
.get(NMSBiomeInfo.class)
|
||||
.biomeKey());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
@@ -19,14 +19,13 @@ import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
@@ -39,12 +38,12 @@ import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
|
||||
public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class);
|
||||
private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate;
|
||||
|
||||
|
||||
private final ChunkGenerator vanilla;
|
||||
private final ConfigPack pack;
|
||||
|
||||
|
||||
private final long seed;
|
||||
|
||||
|
||||
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
|
||||
super(biomeProvider);
|
||||
this.delegate = pack.getGeneratorProvider().newInstance(pack);
|
||||
@@ -52,56 +51,57 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @NotNull Codec<? extends ChunkGenerator> codec() {
|
||||
return ChunkGenerator.CODEC;
|
||||
protected @NotNull MapCodec<? extends ChunkGenerator> codec() {
|
||||
return MapCodec.assumeMapUnsafe(ChunkGenerator.CODEC);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull RandomState noiseConfig, @NotNull BiomeManager world,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk, @NotNull Carving carverStep) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureManager structures, @NotNull RandomState noiseConfig,
|
||||
@NotNull ChunkAccess chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyBiomeDecoration(@NotNull WorldGenLevel world, @NotNull ChunkAccess chunk,
|
||||
@NotNull StructureManager structureAccessor) {
|
||||
vanilla.applyBiomeDecoration(world, chunk, structureAccessor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void spawnOriginalMobs(@NotNull WorldGenRegion region) {
|
||||
vanilla.spawnOriginalMobs(region);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getGenDepth() {
|
||||
return vanilla.getGenDepth();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
public CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()),
|
||||
biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(structureAccessor, chunk.getPos());
|
||||
@@ -116,8 +116,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
double noise = structureWeightSampler.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), ((CraftBlockData) ((BukkitBlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed())).getHandle()).getState(), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
@@ -128,29 +128,29 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return vanilla.getSeaLevel();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return vanilla.getMinY();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(int x, int z, @NotNull Types heightmap, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
WorldProperties properties = new NMSWorldProperties(seed, world);
|
||||
int y = properties.getMaxHeight();
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
while(y >= getMinY() && !heightmap.isOpaque().test(
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull NoiseColumn getBaseColumn(int x, int z, @NotNull LevelHeightAccessor world, @NotNull RandomState noiseConfig) {
|
||||
BlockState[] array = new BlockState[world.getHeight()];
|
||||
@@ -158,7 +158,7 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) {
|
||||
array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider)
|
||||
.getHandle()).getState();
|
||||
.getHandle()).getState();
|
||||
}
|
||||
return new NoiseColumn(getMinY(), array);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R2;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
@@ -15,6 +17,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
|
||||
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
|
||||
|
||||
|
||||
@@ -22,7 +25,7 @@ public class NMSInjectListener implements Listener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class);
|
||||
private static final Set<World> INJECTED = new HashSet<>();
|
||||
private static final ReentrantLock INJECT_LOCK = new ReentrantLock();
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if(!INJECTED.contains(event.getWorld()) &&
|
||||
@@ -32,16 +35,23 @@ public class NMSInjectListener implements Listener {
|
||||
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
|
||||
CraftWorld craftWorld = (CraftWorld) event.getWorld();
|
||||
ServerLevel serverWorld = craftWorld.getHandle();
|
||||
|
||||
|
||||
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
|
||||
|
||||
|
||||
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
|
||||
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
|
||||
|
||||
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
|
||||
|
||||
ChunkMap chunkMap = serverWorld.getChunkSource().chunkMap;
|
||||
WorldGenContext worldGenContext = chunkMap.worldGenContext;
|
||||
Reflection.CHUNKMAP.setWorldGenContext(chunkMap, new WorldGenContext(
|
||||
worldGenContext.level(),
|
||||
new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()),
|
||||
worldGenContext.structureManager(),
|
||||
worldGenContext.lightEngine(),
|
||||
worldGenContext.mainThreadMailBox()
|
||||
));
|
||||
|
||||
LOGGER.info("Successfully injected into world.");
|
||||
|
||||
|
||||
INJECT_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
|
||||
@@ -8,27 +8,27 @@ 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.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return height.getMinBuildHeight();
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R3;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
@@ -12,41 +14,50 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
|
||||
public static final ChunkMapProxy CHUNKMAP;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper,
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
CHUNKMAP = reflectionProxyFactory.reflectionProxy(ChunkMapProxy.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
}
|
||||
|
||||
@Proxies(ChunkMap.class)
|
||||
public interface ChunkMapProxy {
|
||||
@FieldSetter("worldGenContext")
|
||||
void setWorldGenContext(ChunkMap instance, WorldGenContext worldGenContext);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_20_R1;
|
||||
package com.dfsek.terra.bukkit.nms.v1_21;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
@@ -6,7 +6,7 @@ import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
|
||||
|
||||
public class RegistryFetcher {
|
||||
@@ -14,10 +14,10 @@ public class RegistryFetcher {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
.registryAccess()
|
||||
.registryOrThrow(key);
|
||||
.registryAccess()
|
||||
.registryOrThrow(key);
|
||||
}
|
||||
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
return getRegistry(Registries.BIOME);
|
||||
}
|
||||
@@ -6,15 +6,15 @@ val javaMainClass = "com.dfsek.terra.cli.TerraCLI"
|
||||
|
||||
dependencies {
|
||||
shadedApi(project(":common:implementation:base"))
|
||||
|
||||
shadedApi("commons-io:commons-io:${Versions.CLI.commonsIO}")
|
||||
shadedApi("com.github.Querz:NBT:${Versions.CLI.nbt}")
|
||||
|
||||
shadedImplementation("com.google.guava:guava:${Versions.CLI.guava}")
|
||||
|
||||
shadedImplementation("ch.qos.logback:logback-classic:${Versions.CLI.logback}")
|
||||
|
||||
implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama)
|
||||
|
||||
shadedApi("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
|
||||
shadedApi("com.github.Querz", "NBT", Versions.CLI.nbt)
|
||||
|
||||
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
|
||||
shadedImplementation("ch.qos.logback", "logback-classic", Versions.CLI.logback)
|
||||
|
||||
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
@@ -22,7 +22,7 @@ tasks.withType<Jar> {
|
||||
manifest {
|
||||
attributes(
|
||||
"Main-Class" to javaMainClass,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,41 +18,41 @@ import com.dfsek.terra.cli.handle.CLIWorldHandle;
|
||||
|
||||
public class CLIPlatform extends AbstractPlatform {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CLIPlatform.class);
|
||||
|
||||
|
||||
private final CLIWorldHandle worldHandle = new CLIWorldHandle();
|
||||
private final CLIItemHandle itemHandle = new CLIItemHandle();
|
||||
|
||||
|
||||
public CLIPlatform() {
|
||||
LOGGER.info("Root directory: {}", getDataFolder().getAbsoluteFile());
|
||||
load();
|
||||
LOGGER.info("Initialized Terra platform.");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean reload() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull String platformName() {
|
||||
return "CLI";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull WorldHandle getWorldHandle() {
|
||||
return worldHandle;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull File getDataFolder() {
|
||||
return new File("./");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull ItemHandle getItemHandle() {
|
||||
return itemHandle;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
super.register(registry);
|
||||
|
||||
@@ -14,24 +14,24 @@ import com.dfsek.terra.cli.world.CLIWorld;
|
||||
|
||||
public final class TerraCLI {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
|
||||
|
||||
|
||||
public static void main(String... args) {
|
||||
LOGGER.info("Starting Terra CLI...");
|
||||
|
||||
|
||||
CLIPlatform platform = new CLIPlatform();
|
||||
platform.getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
|
||||
|
||||
ConfigPack generate = platform.getConfigRegistry().getByID("OVERWORLD").orElseThrow(); // TODO: make this a cli argument
|
||||
|
||||
|
||||
CLIWorld world = new CLIWorld(2, 2, 384, -64, generate);
|
||||
|
||||
|
||||
world.generate();
|
||||
|
||||
|
||||
world.serialize().parallel().forEach(mcaFile -> {
|
||||
Vector2Int pos = mcaFile.getLeft();
|
||||
String name = MCAUtil.createNameFromRegionLocation(pos.getX(), pos.getZ());
|
||||
LOGGER.info("Writing region ({}, {}) to {}", pos.getX(), pos.getZ(), name);
|
||||
|
||||
|
||||
try {
|
||||
MCAUtil.write(mcaFile.getRight(), name);
|
||||
} catch(IOException e) {
|
||||
|
||||
@@ -12,7 +12,7 @@ public class CLIBlockState implements BlockState {
|
||||
private final CLIBlockType type;
|
||||
private final boolean isAir;
|
||||
private final CompoundTag nbt;
|
||||
|
||||
|
||||
public CLIBlockState(String value) {
|
||||
this.value = value;
|
||||
if(value.contains("[")) {
|
||||
@@ -30,54 +30,54 @@ public class CLIBlockState implements BlockState {
|
||||
for(String property : props) {
|
||||
String name = property.substring(0, property.indexOf('='));
|
||||
String val = property.substring(property.indexOf('=') + 1);
|
||||
|
||||
|
||||
pTag.putString(name, val);
|
||||
}
|
||||
this.nbt.put("Properties", pTag);
|
||||
} else this.type = new CLIBlockType(value);
|
||||
this.nbt.putString("Name", type.getHandle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(BlockState other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> boolean has(Property<T> property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> T get(Property<T> property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> BlockState set(Property<T> property, T value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockType getBlockType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAsString(boolean properties) {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return isAir;
|
||||
}
|
||||
|
||||
|
||||
public CompoundTag getNbt() {
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public class CLIBlockType implements BlockType {
|
||||
private final boolean solid;
|
||||
private final boolean water;
|
||||
private final Lazy<CLIBlockState> defaultState;
|
||||
|
||||
|
||||
public CLIBlockType(String value) {
|
||||
if(value.contains("[")) throw new IllegalArgumentException("Block Type must not contain properties");
|
||||
this.value = value;
|
||||
@@ -18,22 +18,22 @@ public class CLIBlockType implements BlockType {
|
||||
this.water = value.equals("minecraft:water");
|
||||
this.defaultState = Lazy.lazy(() -> new CLIBlockState(value));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHandle() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getDefaultState() {
|
||||
return defaultState.value();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return solid;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isWater() {
|
||||
return water;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user