diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSBiomeInjector.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSBiomeInjector.java index f9db6aa15..cda50042f 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSBiomeInjector.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSBiomeInjector.java @@ -1,18 +1,10 @@ package com.dfsek.terra.bukkit.nms; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.world.biome.Biome; -import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; -import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; -import com.dfsek.terra.registry.master.ConfigRegistry; - import com.google.common.collect.ImmutableMap; import com.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet.Named; import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistryWritable; -import net.minecraft.core.Registry; import net.minecraft.core.RegistryMaterials; import net.minecraft.data.RegistryGeneration; import net.minecraft.resources.MinecraftKey; @@ -39,27 +31,39 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; + public class NMSBiomeInjector { private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); + private static final Map> terraBiomeMap = new HashMap<>(); - public static void registerBiomes(ConfigRegistry configRegistry) { + public static IRegistryWritable getBiomeRegistry() { CraftServer craftserver = (CraftServer) Bukkit.getServer(); DedicatedServer dedicatedserver = craftserver.getServer(); - - IRegistryWritable biomeRegistry = (IRegistryWritable) dedicatedserver + + return (IRegistryWritable) dedicatedserver .aU() // getRegistryManager .b( // getRegistry IRegistry.aP // biome registry key ); + } + + public static void registerBiomes(ConfigRegistry configRegistry) { + try { LOGGER.info("Hacking biome registry..."); + IRegistryWritable biomeRegistry = getBiomeRegistry(); Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field frozen.setAccessible(true); frozen.set(biomeRegistry, false); - Map> terraBiomeMap = new HashMap<>(); + configRegistry.forEach(pack -> pack.getRegistry(Biome.class).forEach((key, biome) -> { try { @@ -87,57 +91,61 @@ public class NMSBiomeInjector { frozen.set(biomeRegistry, true); // freeze registry again :) - /* - LOGGER.info("Doing tag garbage...."); - Map, List>> collect = biomeRegistry - .g() // streamKeysAndEntries - .collect(HashMap::new, - (map, pair) -> - map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().a().toList())), - HashMap::putAll); - - terraBiomeMap - .forEach((vb, terraBiomes) -> - getEntry(biomeRegistry, vb) - .ifPresentOrElse(vanilla -> terraBiomes - .forEach(tb -> - getEntry(biomeRegistry, tb) - .ifPresentOrElse( - terra -> { - LOGGER.debug( - vanilla.e() - .orElseThrow() - .a() + - " (vanilla for " + - terra.e() - .orElseThrow() - .a() + - ": " + - vanilla.c() - .toList()); - - vanilla.c() - .forEach( - tag -> collect - .computeIfAbsent( - tag, - t -> new ArrayList<>()) - .add(terra)); - }, - () -> LOGGER.error( - "No such biome: {}", - tb))), - () -> LOGGER.error("No vanilla biome: {}", vb))); - - biomeRegistry.k(); // clearTags - biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags - */ + } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) { throw new RuntimeException(exception); } } + public static void injectTags() { + LOGGER.info("Doing tag garbage...."); + IRegistryWritable biomeRegistry = getBiomeRegistry(); + Map, List>> collect = biomeRegistry + .g() // streamKeysAndEntries + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().a().toList())), + HashMap::putAll); + + terraBiomeMap + .forEach((vb, terraBiomes) -> + getEntry(biomeRegistry, vb) + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> + getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug( + vanilla.e() + .orElseThrow() + .a() + + " (vanilla for " + + terra.e() + .orElseThrow() + .a() + + ": " + + vanilla.c() + .toList()); + + vanilla.c() + .forEach( + tag -> collect + .computeIfAbsent( + tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); + + biomeRegistry.k(); // clearTags + biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags + + } + public static Optional> getEntry(IRegistry registry, MinecraftKey identifier) { return registry.b(identifier) .flatMap(registry::c) diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSInjectListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSInjectListener.java index 3f0ebfe87..3f5d27d15 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSInjectListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/nms/NMSInjectListener.java @@ -7,6 +7,7 @@ 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.bukkit.event.world.WorldLoadEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +24,8 @@ public class NMSInjectListener implements Listener { private static final Set INJECTED = new HashSet<>(); private static final ReentrantLock INJECT_LOCK = new ReentrantLock(); + private volatile boolean tags = false; + @EventHandler public void onWorldInit(WorldInitEvent event) { if (!INJECTED.contains(event.getWorld()) && event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { @@ -47,4 +50,13 @@ public class NMSInjectListener implements Listener { INJECT_LOCK.unlock(); } } + + @EventHandler + public void onWorldLoad(WorldLoadEvent load) { + if(!tags) { + System.out.println("Injecting tags late to prevent deadlock. Thank you Bukkit."); + tags = true; + NMSBiomeInjector.injectTags(); + } + } }