From 381d0134a013526b4b3dc2dc884144b4ac495475 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Thu, 22 Jun 2023 17:49:36 +0800 Subject: [PATCH] Fix NPE loading fluids (#1017) --- .../mixin/bukkit/CraftMagicNumbersMixin.java | 13 ++++++++++- .../common/mod/server/BukkitRegistry.java | 22 +++++++++++++++++++ .../arclight/boot/asm/EnumDefinalizer.java | 3 ++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMagicNumbersMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMagicNumbersMixin.java index c835fcc7..92f077a1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMagicNumbersMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMagicNumbersMixin.java @@ -1,8 +1,19 @@ package io.izzel.arclight.common.mixin.bukkit; +import com.google.common.collect.BiMap; import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin(CraftMagicNumbers.class) +@Mixin(value = CraftMagicNumbers.class, remap = false) public class CraftMagicNumbersMixin { + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) + private static V arclight$skip(BiMap instance, K k, V v) { + if (v == null) { + return null; + } + return instance.put(k, v); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java index 53543d48..f7e16ea9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java @@ -38,6 +38,7 @@ import net.minecraft.world.item.crafting.CookingBookCategory; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.material.Fluid; import net.minecraftforge.fml.CrashReportCallables; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistry; @@ -95,6 +96,7 @@ public class BukkitRegistry { private static final Map ART_BY_NAME = Unsafe.getStatic(Art.class, "BY_NAME"); private static final Map ART_BY_ID = Unsafe.getStatic(Art.class, "BY_ID"); private static final BiMap STATS = HashBiMap.create(Unsafe.getStatic(CraftStatistic.class, "statistics")); + private static final BiMap FLUIDTYPE_FLUID = Unsafe.getStatic(CraftMagicNumbers.class, "FLUIDTYPE_FLUID"); public static void registerAll(DedicatedServer console) { CrashReportCallables.registerCrashCallable("Arclight Release", ArclightVersion.current()::getReleaseName); @@ -110,6 +112,7 @@ public class BukkitRegistry { loadSpawnCategory(); loadEndDragonPhase(); loadCookingBookCategory(); + loadFluids(); try { for (var field : org.bukkit.Registry.class.getFields()) { if (Modifier.isStatic(field.getModifiers()) && field.get(null) instanceof org.bukkit.Registry.SimpleRegistry registry) { @@ -120,6 +123,25 @@ public class BukkitRegistry { } } + private static void loadFluids() { + var id = org.bukkit.Fluid.values().length; + var newTypes = new ArrayList(); + Field keyField = Arrays.stream(org.bukkit.Fluid.class.getDeclaredFields()).filter(it -> it.getName().equals("key")).findAny().orElse(null); + long keyOffset = Unsafe.objectFieldOffset(keyField); + for (var fluidType : ForgeRegistries.FLUIDS) { + if (!FLUIDTYPE_FLUID.containsKey(fluidType)) { + var key = ForgeRegistries.FLUIDS.getKey(fluidType); + var name = ResourceLocationUtil.standardize(key); + var bukkit = EnumHelper.makeEnum(org.bukkit.Fluid.class, name, id++, List.of(), List.of()); + Unsafe.putObject(bukkit, keyOffset, CraftNamespacedKey.fromMinecraft(key)); + newTypes.add(bukkit); + FLUIDTYPE_FLUID.put(fluidType, bukkit); + ArclightMod.LOGGER.debug("Registered {} as fluid {}", key, bukkit); + } + } + EnumHelper.addEnums(org.bukkit.Fluid.class, newTypes); + } + private static void loadCookingBookCategory() { var id = CookingBookCategory.values().length; var newTypes = new ArrayList(); diff --git a/arclight-forge/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java b/arclight-forge/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java index bb971adb..5af8711b 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java @@ -21,7 +21,8 @@ public class EnumDefinalizer implements Implementer { "org/bukkit/inventory/CreativeCategory", "org/bukkit/entity/SpawnCategory", "org/bukkit/entity/EnderDragon$Phase", - "org/bukkit/inventory/recipe/CookingBookCategory" + "org/bukkit/inventory/recipe/CookingBookCategory", + "org/bukkit/Fluid" ); @Override