diff --git a/bukkit/compatibility/build.gradle.kts b/bukkit/compatibility/build.gradle.kts index 55151de14..e995978d5 100644 --- a/bukkit/compatibility/build.gradle.kts +++ b/bukkit/compatibility/build.gradle.kts @@ -7,7 +7,7 @@ repositories { maven("https://repo.rapture.pw/repository/maven-releases/") // slime world maven("https://repo.infernalsuite.com/repository/maven-snapshots/") // slime world maven("https://repo.momirealms.net/releases/") - maven("https://mvn.lumine.io/repository/maven-public/") // model engine + maven("https://mvn.lumine.io/repository/maven-public/") // model engine mythic mobs maven("https://nexus.phoenixdevt.fr/repository/maven-public/") // mmoitems maven("https://repo.viaversion.com") // via maven("https://repo.skriptlang.org/releases/") // skript @@ -47,6 +47,8 @@ dependencies { compileOnly(platform("com.intellectualsites.bom:bom-newest:1.52")) compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core") compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false } + // MythicMobs + compileOnly("io.lumine:Mythic-Dist:5.9.0") } java { diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java index 680455c0a..2d1879e43 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java @@ -3,11 +3,13 @@ package net.momirealms.craftengine.bukkit.compatibility; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel; import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider; +import net.momirealms.craftengine.bukkit.compatibility.item.MythicMobsProvider; import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider; import net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld.LegacySlimeFormatStorageAdaptor; import net.momirealms.craftengine.bukkit.compatibility.leveler.AuraSkillsLevelerProvider; import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel; import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineUtils; +import net.momirealms.craftengine.bukkit.compatibility.mythicmobs.MythicMobsListener; import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils; import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners; import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook; @@ -105,6 +107,11 @@ public class BukkitCompatibilityManager implements CompatibilityManager { if (this.isPluginEnabled("AuraSkills")) { this.registerLevelerProvider("AuraSkills", new AuraSkillsLevelerProvider()); } + if (this.isPluginEnabled("MythicMobs")) { + BukkitItemManager.instance().registerExternalItemProvider(new MythicMobsProvider()); + new MythicMobsListener(this.plugin); + logHook("MythicMobs"); + } } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java new file mode 100644 index 000000000..8b01bc237 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java @@ -0,0 +1,25 @@ +package net.momirealms.craftengine.bukkit.compatibility.item; + +import io.lumine.mythic.bukkit.MythicBukkit; +import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +public class MythicMobsProvider implements ExternalItemProvider { + private MythicBukkit mythicBukkit; + + @Override + public String plugin() { + return "MythicMobs"; + } + + @Nullable + @Override + public ItemStack build(String id, ItemBuildContext context) { + if (mythicBukkit == null || mythicBukkit.isClosed()) { + this.mythicBukkit = MythicBukkit.inst(); + } + return mythicBukkit.getItemManager().getItemStack(id); + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/CraftEngineItemDrop.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/CraftEngineItemDrop.java new file mode 100644 index 000000000..8c144b4c5 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/CraftEngineItemDrop.java @@ -0,0 +1,64 @@ +package net.momirealms.craftengine.bukkit.compatibility.mythicmobs; + +import io.lumine.mythic.api.adapters.AbstractItemStack; +import io.lumine.mythic.api.adapters.AbstractPlayer; +import io.lumine.mythic.api.config.MythicLineConfig; +import io.lumine.mythic.api.drops.DropMetadata; +import io.lumine.mythic.api.drops.IItemDrop; +import io.lumine.mythic.api.skills.SkillCaster; +import io.lumine.mythic.bukkit.BukkitAdapter; +import io.lumine.mythic.bukkit.adapters.BukkitItemStack; +import io.lumine.mythic.core.drops.droppables.ItemDrop; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.ReflectionUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Constructor; + +public class CraftEngineItemDrop extends ItemDrop implements IItemDrop { + private final CustomItem customItem; + private static final Constructor constructor$BukkitItemStack = ReflectionUtils.getConstructor(BukkitItemStack.class, ItemStack.class); + private static final boolean useReflection = constructor$BukkitItemStack != null; + + public CraftEngineItemDrop(String line, MythicLineConfig config, CustomItem customItem) { + super(line, config); + this.customItem = customItem; + CraftEngine.instance().debug(() -> "[MM调试] " + customItem.id() + " 注册成功"); + } + + @Override + public AbstractItemStack getDrop(DropMetadata dropMetadata, double amount) { + CraftEngine.instance().debug(() -> "[MM调试] getDrop() dropMetadata={" + dropMetadata + "}, amount={" + amount + "}"); + ItemBuildContext context = ItemBuildContext.EMPTY; + SkillCaster caster = dropMetadata.getCaster(); + if (caster != null && caster.getEntity() instanceof AbstractPlayer abstractPlayer) { + Entity bukkitEntity = abstractPlayer.getBukkitEntity(); + if (bukkitEntity instanceof Player bukkitPlayer) { + var player = BukkitCraftEngine.instance().adapt(bukkitPlayer); + context = ItemBuildContext.of(player); + } + } + int amountInt = MCUtils.fastFloor(amount + 0.5F); + ItemStack itemStack = this.customItem.buildItemStack(context, amountInt); + return adapt(itemStack).amount(amountInt); + } + + private static AbstractItemStack adapt(ItemStack itemStack) { + if (useReflection) { + try { + return (AbstractItemStack) constructor$BukkitItemStack.newInstance(itemStack); + } catch (Exception e) { + CraftEngine.instance().logger().warn("adapt(ItemStack itemStack) error: " + e.getMessage()); + return null; + } + } else { + return BukkitAdapter.adapt(itemStack); + } + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/MythicMobsListener.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/MythicMobsListener.java new file mode 100644 index 000000000..9d59cab3a --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/mythicmobs/MythicMobsListener.java @@ -0,0 +1,31 @@ +package net.momirealms.craftengine.bukkit.compatibility.mythicmobs; + +import io.lumine.mythic.api.config.MythicLineConfig; +import io.lumine.mythic.bukkit.events.MythicDropLoadEvent; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.core.util.Key; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class MythicMobsListener implements Listener { + private final BukkitCraftEngine plugin; + + public MythicMobsListener(BukkitCraftEngine plugin) { + this.plugin = plugin; + Bukkit.getPluginManager().registerEvents(this, plugin.javaPlugin()); + } + + @EventHandler + public void onMythicDropLoad(MythicDropLoadEvent event) { + if (!event.getDropName().equalsIgnoreCase("craftengine")) return; + String argument = event.getArgument(); + plugin.debug(() -> "[MM调试] " + argument); + Key itemId = Key.of(argument); + this.plugin.itemManager().getCustomItem(itemId).ifPresent(customItem -> { + String line = event.getContainer().getConfigLine(); + MythicLineConfig config = event.getConfig(); + event.register(new CraftEngineItemDrop(line, config, customItem)); + }); + } +} diff --git a/bukkit/paper-loader/build.gradle.kts b/bukkit/paper-loader/build.gradle.kts index 2697d94db..15dc5a852 100644 --- a/bukkit/paper-loader/build.gradle.kts +++ b/bukkit/paper-loader/build.gradle.kts @@ -92,6 +92,9 @@ paper { register("ViaVersion") { required = false } + register("MythicMobs") { + required = false + } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 62c17ccaa..17e26e141 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -579,6 +579,7 @@ public class BukkitBlockManager extends AbstractBlockManager { Object resourceLocation = KeyUtils.toResourceLocation(BlockKeys.NOTE_BLOCK); Object block = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation); Object stateDefinition = CoreReflections.field$Block$StateDefinition.get(block); + @SuppressWarnings("unchecked") ImmutableList states = (ImmutableList) CoreReflections.field$StateDefinition$states.get(stateDefinition); for (Object state : states) { BlockStateUtils.CLIENT_SIDE_NOTE_BLOCKS.put(state, new Object());