事件系统入门 - Junye-666/RideBattleLib_NeoForge_1.21.1 GitHub Wiki

RideBattleLib 提供 NeoForge 事件监听,同时提供 ServerRiderDispatcher / ClientRiderDispatcher 分发系统。
1.3.3 推荐大型骑士使用分发系统,小型逻辑可直接监听 NeoForge 事件。

直接监听 NeoForge 事件

@EventBusSubscriber(modid = "yourmod")
public class YourEventHandler {

    @SubscribeEvent
    public static void onHenshinPre(HenshinEvent.Pre event) {
        Player player = event.getPlayer();
        ResourceLocation formId = event.getFormId();

        player.level().playSound(
                null,
                player,
                SoundEvents.LIGHTNING_BOLT_THUNDER,
                SoundSource.PLAYERS,
                1.0f,
                1.0f
        );
    }

    @SubscribeEvent
    public static void onHenshinPost(HenshinEvent.Post event) {
        event.getPlayer().displayClientMessage(
                Component.literal("变身完成!").withStyle(ChatFormatting.GOLD),
                true
        );
    }
}

服务端事件速查

事件类 Pre Post 说明
HenshinEvent 可取消 有 变身前后
UnhenshinEvent 可取消 有 解除变身前后
FormSwitchEvent 可取消 有 形态切换前后
HenshinPauseEvent 可取消 有 变身暂停前后
DriverActivationEvent 可取消 无 驱动器激活
ItemInsertionEvent 可取消,可改物品 有 插入物品前后
SlotExtractionEvent 可取消,可改物品 有 取出物品前后
ReturnItemsEvent 可取消 有 返还物品前后
ItemGrantEvent 可取消,可改物品 有 授予物品前后
SkillEvent 可取消 有 技能触发前后
RotateSkillEvent 可取消 无 技能轮转
FormOverrideEvent 可取消,可覆盖形态 无 形态匹配覆盖
FindRiderConfigEvent 可取消 无 搜索 RiderConfig 时插入逻辑
PenaltyEvent 子事件可取消 无 吃瘪各阶段

常用事件示例

解除变身:吃瘪提示

@SubscribeEvent
public static void onUnhenshin(UnhenshinEvent.Pre event) {
    if (event.isPenalty()) {
        event.getPlayer().displayClientMessage(
                Component.literal("我的身体已经菠萝菠萝哒!").withStyle(ChatFormatting.RED),
                true
        );
    }
}

形态切换

@SubscribeEvent
public static void onFormSwitchPre(FormSwitchEvent.Pre event) {
    Player player = event.getPlayer();
    ResourceLocation oldForm = event.getOldFormId();
    ResourceLocation newForm = event.getNewFormId();

    player.displayClientMessage(
            Component.literal("形态切换: " + newForm.getPath()),
            true
    );
}

技能触发:骑士踢

@SubscribeEvent
public static void onSkillTrigger(SkillEvent.Post event) {
    ResourceLocation skillId = event.getSkillId();

    if (skillId.getPath().equals("rider_kick")) {
        Player player = event.getPlayer();

        Vec3 lookVec = player.getLookAngle();
        player.setDeltaMovement(lookVec.x * 2.0, 0.5, lookVec.z * 2.0);
        player.hurtMarked = true;

        AABB area = player.getBoundingBox().inflate(3.0);
        player.level().getEntities(player, area).forEach(entity -> {
            if (entity instanceof LivingEntity target) {
                target.hurt(player.damageSources().playerAttack(player), 10.0f);
            }
        });

        player.level().explode(
                player,
                player.getX(), player.getY() + 1.0, player.getZ(),
                2.0f,
                false,
                Level.ExplosionInteraction.NONE
        );
    }
}

插入物品替换

@SubscribeEvent
public static void onItemInsert(ItemInsertionEvent.Pre event) {
    ItemStack original = event.getStack();

    if (original.is(Items.DIAMOND)) {
        event.setStack(new ItemStack(Items.NETHERITE_INGOT));
        event.getPlayer().displayClientMessage(
                Component.literal("钻石被转换为下界合金!"),
                true
        );
    }
}

授予物品替换

@SubscribeEvent
public static void onItemGrant(ItemGrantEvent.Pre event) {
    if (event.getStack().is(Items.IRON_SWORD)) {
        event.setStack(new ItemStack(Items.DIAMOND_SWORD));
    }
}

形态覆盖:FormOverrideEvent

@SubscribeEvent
public static void onFormOverride(FormOverrideEvent event) {
    Player player = event.getPlayer();

    boolean hasSpecialItem = false;
    for (ItemStack stack : player.getInventory().items) {
        if (!stack.isEmpty() && stack.is(Items.NETHERITE_INGOT)) {
            hasSpecialItem = true;
            break;
        }
    }

    if (hasSpecialItem) {
        event.overrideForm(
                ResourceLocation.fromNamespaceAndPath("mymod", "super_form")
        );
    }
}

注意:在 FormOverrideEvent 中调用 event.setCanceled(true) 会中止变身并返回 null。

FindRiderConfigEvent 与 Curios 联动

@SubscribeEvent
public static void onFindConfig(FindRiderConfigEvent event) {
    Player player = event.getPlayer();

    Optional<ItemStack> found = CuriosApi.getCuriosHelper()
            .findEquippedCurio(ModItems.DRIVER.get(), player)
            .map(SlotResult::stack);

    if (found.isPresent()) {
        event.setConfig(MyRider.CONFIG);
    }
}

注意:在此处调用 event.setCanceled(true) 会使玩家变身失败。

⚠️ **GitHub.com Fallback** ⚠️