fix deadlock

This commit is contained in:
dfsek
2022-05-31 15:20:23 -07:00
parent a54b48f68a
commit e3dd42c856
2 changed files with 77 additions and 57 deletions

View File

@@ -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<MinecraftKey, List<MinecraftKey>> terraBiomeMap = new HashMap<>();
public static void registerBiomes(ConfigRegistry configRegistry) {
public static IRegistryWritable<BiomeBase> getBiomeRegistry() {
CraftServer craftserver = (CraftServer) Bukkit.getServer();
DedicatedServer dedicatedserver = craftserver.getServer();
IRegistryWritable<BiomeBase> biomeRegistry = (IRegistryWritable<BiomeBase>) dedicatedserver
return (IRegistryWritable<BiomeBase>) dedicatedserver
.aU() // getRegistryManager
.b( // getRegistry
IRegistry.aP // biome registry key
);
}
public static void registerBiomes(ConfigRegistry configRegistry) {
try {
LOGGER.info("Hacking biome registry...");
IRegistryWritable<BiomeBase> biomeRegistry = getBiomeRegistry();
Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field
frozen.setAccessible(true);
frozen.set(biomeRegistry, false);
Map<MinecraftKey, List<MinecraftKey>> 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<TagKey<BiomeBase>, List<Holder<BiomeBase>>> 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<BiomeBase> biomeRegistry = getBiomeRegistry();
Map<TagKey<BiomeBase>, List<Holder<BiomeBase>>> 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 <T> Optional<Holder<T>> getEntry(IRegistry<T> registry, MinecraftKey identifier) {
return registry.b(identifier)
.flatMap(registry::c)

View File

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