diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java index 32a059721..2c37356ca 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java @@ -23,7 +23,10 @@ import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.terra.bukkit.nms.Initializer; +import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryKey; import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -31,7 +34,6 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.List; -import java.util.Locale; import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.api.addon.BaseAddon; @@ -132,7 +134,8 @@ public class PlatformImpl extends AbstractPlatform { } 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))); + NamespacedKey key = NamespacedKey.fromString(id); + if(key == null || !key.namespace().equals("minecraft")) throw new LoadException("Invalid biome identifier " + id, depthTracker); + return new BukkitPlatformBiome(RegistryAccess.registryAccess().getRegistry(RegistryKey.BIOME).getOrThrow(key)); } } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java index bc48a7277..4c670a7d1 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java @@ -18,20 +18,36 @@ package com.dfsek.terra.bukkit.listeners; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.hooks.MultiverseGeneratorPluginHook; +import com.dfsek.terra.bukkit.world.BukkitBiomeInfo; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; + +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.Wolf.Variant; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.server.PluginEnableEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + /** * Listener for events on all implementations. */ public class CommonListener implements Listener { private static final Logger logger = LoggerFactory.getLogger(CommonListener.class); + private static final List WOLF_VARIANT_SPAWN_REASONS = List.of( + SpawnReason.SPAWNER, SpawnReason.TRIAL_SPAWNER, SpawnReason.SPAWNER_EGG, SpawnReason.DEFAULT + ); private final Platform platform; public CommonListener(Platform platform) { @@ -51,4 +67,50 @@ public class CommonListener implements Listener { } } } + + @EventHandler + public void onWolfSpawn(CreatureSpawnEvent event) { + if (!(event.getEntity() instanceof Wolf wolf)) { + return; + } + + // Doesn't apply if variant has already been applied + if (wolf.getVariant() != Variant.PALE) { + return; + } + + if (!WOLF_VARIANT_SPAWN_REASONS.contains(event.getSpawnReason())) { + return; + } + + World world = wolf.getWorld(); + if (!(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper)) { + return; + } + + ConfigPack pack = platform.getConfigRegistry().get(wrapper.getPack().getRegistryKey()).orElse(null); + if (pack == null) { + return; + } + + NamespacedKey biomeKey = wolf.getWorld().getBiome(wolf.getLocation()).getKey(); + pack.getBiomeProvider().stream() + .filter(biome -> { + NamespacedKey key = ((BukkitPlatformBiome) biome.getPlatformBiome()).getContext() + .get(BukkitBiomeInfo.class) + .biomeKey(); + return key.equals(biomeKey); + }) + .findFirst() + .ifPresent(biome -> { + NamespacedKey vanillaBiomeKey = ((BukkitPlatformBiome) biome.getPlatformBiome()).getHandle().getKey(); + switch(vanillaBiomeKey.toString()) { + case "minecraft:snowy_taiga" -> wolf.setVariant(Variant.ASHEN); + case "minecraft:old_growth_pine_taiga" -> wolf.setVariant(Variant.BLACK); + case "minecraft:old_growth_spruce_taiga" -> wolf.setVariant(Variant.CHESTNUT); + case "minecraft:grove" -> wolf.setVariant(Variant.SNOWY); + case "minecraft:forest" -> wolf.setVariant(Variant.WOODS); + } + }); + } } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeInfo.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeInfo.java new file mode 100644 index 000000000..7e0499c0c --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeInfo.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.properties.Properties; + +import org.bukkit.NamespacedKey; + + +public record BukkitBiomeInfo(NamespacedKey biomeKey) implements Properties {} diff --git a/platforms/bukkit/nms/v1_21_6/src/main/java/com/dfsek/terra/bukkit/nms/v1_21_6/AwfulBukkitHacks.java b/platforms/bukkit/nms/v1_21_6/src/main/java/com/dfsek/terra/bukkit/nms/v1_21_6/AwfulBukkitHacks.java index 980194f92..5411fdcac 100644 --- a/platforms/bukkit/nms/v1_21_6/src/main/java/com/dfsek/terra/bukkit/nms/v1_21_6/AwfulBukkitHacks.java +++ b/platforms/bukkit/nms/v1_21_6/src/main/java/com/dfsek/terra/bukkit/nms/v1_21_6/AwfulBukkitHacks.java @@ -2,6 +2,8 @@ package com.dfsek.terra.bukkit.nms.v1_21_6; import com.dfsek.terra.bukkit.nms.v1_21_6.config.VanillaBiomeProperties; +import com.dfsek.terra.bukkit.world.BukkitBiomeInfo; + import net.minecraft.core.Holder; import net.minecraft.core.Holder.Reference; import net.minecraft.core.HolderSet; @@ -54,14 +56,14 @@ public class AwfulBukkitHacks { Biome platform = NMSBiomeInjector.createBiome(biomeRegistry.get(vanillaMinecraftKey).orElseThrow().value(), vanillaBiomeProperties); - ResourceKey delegateKey = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key)) - ); + ResourceLocation delegateMinecraftKey = ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key)); + NamespacedKey delegateBukkitKey = NamespacedKey.fromString(delegateMinecraftKey.toString()); + ResourceKey delegateKey = ResourceKey.create(Registries.BIOME, delegateMinecraftKey); Reference holder = biomeRegistry.register(delegateKey, platform, RegistrationInfo.BUILT_IN); Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder. + platformBiome.getContext().put(new BukkitBiomeInfo(delegateBukkitKey)); platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());