Flandre923
1340 words
7 minutes
16 是否用物品右键了某个方块

16 是否用物品右键了某个方块#



    /**
     *  UseBlockHandler
     */
    public static boolean isButtonUsed = false;
    @SubscribeEvent
    public static void UseBlockHandler(UseItemOnBlockEvent event){
        Level level = event.getLevel();
        BlockPos pos = event.getPos();
        BlockState state = level.getBlockState(pos);
        if (!level.isClientSide)
        {
            if(state.is(BlockTags.BUTTONS)){ // 判断是那个方块
                isButtonUsed = true;
            }
        }
    }

这里看一下主要通过按钮设置了一个随机的事件.这个事件主要是玩家右键了按钮之后,会进行一个随机的奖励和惩罚,包括给与一些药水效果,赋予一些附魔,获得一些物品,移除一些物品.等等.

package com.mafuyu33.neomafishmod.mixin.enchantmentblockmixin.custom.buttonrandom;


// Mixin 类,用于修改 Player 类的行为
@Mixin(Player.class)
public abstract class PlayerEntityMixin extends LivingEntity {

    // 构造函数初始化实体类型和世界
    protected PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, Level level) {
        super(entityType, level);
    }

    // Shadow 注解的方法,用于访问 Player 类的方法
    @Shadow
    public abstract void displayClientMessage(Component chatComponent, boolean actionBar);

    @Shadow public abstract Inventory getInventory();

    @Shadow public abstract double entityInteractionRange();

    @Shadow public abstract ItemStack eat(Level level, ItemStack food, FoodProperties foodProperties);

    @Shadow public abstract boolean addItem(ItemStack stack);

    // Unique 注解的字段,用于存储随机附魔、物品、效果等
    @Unique
    Holder<Enchantment> randomPositiveEnchantment;
    @Unique
    Holder<Enchantment> randomNegativeEnchantment;

    @Unique
    Item randomItem;
    @Unique
    ItemStack randomItemStack;
    @Unique
    Holder<MobEffect> randomPositiveEffect;
    @Unique
    Holder<MobEffect> randomNegativeEffect;
    @Unique
    int flag = -1;
    @Unique
    int buttonCount = 0;
    @Unique
    int randomNumber = (random.nextInt(10) + 1);
    @Unique
    String goodEvent;
    @Unique
    String badEvent;

    // 在 tick 方法开始时注入的代码
    @Inject(at = @At("HEAD"), method = "tick")
    private void init(CallbackInfo info) {
        // 确保只有在服务器端运行
        if (!level().isClientSide) {
            // 如果 goodEvent 和 badEvent 为空,则初始化它们
            if (goodEvent == null || badEvent == null) {
                goodEvent = getRandomGoodEvent();
                badEvent = getRandomBadEvent();
            }
        
            // 获取玩家的视线位置和方向
            Vec3 playerPos = this.getEyePosition(1.0F);
            Vec3 playerLook = this.getViewVector(1.0F);
            Vec3 rayEnd = playerPos.add(playerLook.scale(10)); // 定义射线的结束点
        
            // 执行射线检测以检测方块的碰撞
            BlockHitResult blockHitResult = level().clip(new ClipContext(playerPos, rayEnd, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this));
        
            // 检查碰撞到的方块是否为按钮,并且满足某些条件
            if (level().getBlockState(blockHitResult.getBlockPos()).is(BlockTags.BUTTONS)
                    && !PlayerServerEvent.isButtonUsed && BlockEnchantmentStorage.getLevel(Enchantments.INFINITY, blockHitResult.getBlockPos()) > 0) {
                // 向玩家发送关于好事件和坏事件的消息
                this.displayClientMessage(
                        Component.literal("获得 ")
                                .append(Component.literal(goodEvent))
                                .append(" ")
                                .append(Component.literal(toRoman(randomNumber)))
                                .append(", 但代价是 ")
                                .append(Component.literal(badEvent).withStyle(ChatFormatting.RED)),
                        true
                );
            }
        
            // 检查按钮是否已被使用,并根据情况执行事件
            if (PlayerServerEvent.isButtonUsed && BlockEnchantmentStorage.getLevel(Enchantments.INFINITY, blockHitResult.getBlockPos()) > 0) {
                this.displayClientMessage(Component.literal("实现了..."), true);
                if (buttonCount == 0) {
                    // 执行事件并重置 goodEvent 和 badEvent
                    executeEvent(randomNumber);
                    goodEvent = getRandomGoodEvent();
                    badEvent = getRandomBadEvent();
                }
                buttonCount++;
            }
        
            // 每30个 tick 重置 buttonCount 和 randomNumber
            if (buttonCount >= 30) {
                buttonCount = 0;
                PlayerServerEvent.isButtonUsed = false;
                randomNumber = (random.nextInt(10) + 1);
            }
        }
    }

    // 根据 flag 执行事件的方法
    @Unique
    private void executeEvent(int randomNumber) {
        switch (flag) {
            case 0:
                // 应用随机正面和负面效果
                this.addEffect(new MobEffectInstance(randomPositiveEffect, 100 * randomNumber, randomNumber - 1));
                this.addEffect(new MobEffectInstance(randomNegativeEffect, 100 * randomNumber, randomNumber - 1));
                break;
            case 1:
                // 给玩家主手中的物品附加随机正面和负面附魔
                Player player = (Player) (Object) this;
                ItemStack heldItem = player.getMainHandItem();
                heldItem.enchant(randomPositiveEnchantment, randomNumber);
                heldItem.enchant(randomNegativeEnchantment, randomNumber);
                break;
            case 2:
                // 将随机物品添加到玩家的背包中,如果背包满了则掉落物品
                randomItemStack.setCount(randomNumber);
                if (!this.getInventory().add(randomItemStack)) {
                    this.spawnAtLocation(randomItem);
                }
                clearRandomItems(randomNumber, randomItemStack);
                break;
            case -1:
                // 没有事件
                break;
            default:
                // 处理未知事件
                break;
        }
    }

    // 获取随机好事件的方法
    @Unique
    private String getRandomGoodEvent() {
        Optional<HolderLookup.RegistryLookup<MobEffect>> mobEffectRegistryLookup = level().registryAccess().lookup(Registries.MOB_EFFECT);
        HolderLookup.RegistryLookup<MobEffect> mobEffectRegistryLookup1 = mobEffectRegistryLookup.get();
        List<Holder.Reference<MobEffect>> POSITIVE_EFFECTS = mobEffectRegistryLookup1.listElements()
                .filter(mobEffectReference -> mobEffectReference.value().getCategory() == MobEffectCategory.BENEFICIAL || mobEffectReference.value().getCategory() == MobEffectCategory.NEUTRAL)
                .toList();

        Optional<HolderLookup.RegistryLookup<Enchantment>> lookup = level().registryAccess().lookup(Registries.ENCHANTMENT);
        HolderLookup.RegistryLookup<Enchantment> enchantmentRegistryLookup = lookup.get();
        List<Holder.Reference<Enchantment>> POSITIVE_ENCHANTMENTS = enchantmentRegistryLookup.listElements()
                .filter(enchantmentReference -> !enchantmentReference.is(EnchantmentTags.CURSE))
                .toList();

        List<Item> RANDOM_ITEMS = StreamSupport.stream(BuiltInRegistries.ITEM.spliterator(), false)
                .filter(item -> item.getFoodProperties(item.getDefaultInstance(), null) == null)
                .toList();

        int randomChoice = random.nextInt(4);
        if (randomChoice == 0) {
            flag = 0;
            return applyRandomPositiveEffect(POSITIVE_EFFECTS);
        } else if (randomChoice == 1) {
            flag = 1;
            return applyRandomPositiveEnchantment(POSITIVE_ENCHANTMENTS);
        } else {
            flag = 2;
            return grantRandomItem(RANDOM_ITEMS);
        }
    }

    // 获取随机坏事件的方法
    @Unique
    private String getRandomBadEvent() {
        Optional<HolderLookup.RegistryLookup<MobEffect>> mobEffectRegistryLookup = level().registryAccess().lookup(Registries.MOB_EFFECT);
        HolderLookup.RegistryLookup<MobEffect> mobEffectRegistryLookup1 = mobEffectRegistryLookup.get();
        List<Holder.Reference<MobEffect>> NEGATIVE_EFFECTS = mobEffectRegistryLookup1.listElements()
                .filter(mobEffectReference -> mobEffectReference.value().getCategory() == MobEffectCategory.HARMFUL)
                .toList();

        Optional<HolderLookup.RegistryLookup<Enchantment>> lookup = level().registryAccess().lookup(Registries.ENCHANTMENT);
        HolderLookup.RegistryLookup<Enchantment> enchantmentRegistryLookup = lookup.get();
        List<Holder.Reference<Enchantment>> NEGATIVE_ENCHANTMENTS = enchantmentRegistryLookup.listElements()
                .filter(enchantmentReference -> enchantmentReference.is(EnchantmentTags.CURSE))
                .toList();

        int flag = random.nextInt(3);
        if (flag == 0) {
            return "获得" + applyRandomNegativeEffect(NEGATIVE_EFFECTS);
        } else if (flag == 1) {
            return "获得" + applyRandomNegativeEnchantment(NEGATIVE_ENCHANTMENTS);
        } else if (flag == 2) {
            return "献祭相同数量的物品";
        } else {
            return "null";
        }
    }

    // 随机应用正面附魔的方法
    @Unique
    private String applyRandomPositiveEnchantment(List<Holder.Reference<Enchantment>> POSITIVE_ENCHANTMENTS) {
        if (!POSITIVE_ENCHANTMENTS.isEmpty()) {
            randomPositiveEnchantment = POSITIVE_ENCHANTMENTS.get(random.nextInt(POSITIVE_ENCHANTMENTS.size()));
            MutableComponent enchantmentName = Component.translatable(randomPositiveEnchantment.getKey().toString());
            return enchantmentName.getString();
        }
        return "一个正面附魔";
    }

    // 随机应用负面附魔的方法
    @Unique
    private String applyRandomNegativeEnchantment(List<Holder.Reference<Enchantment>> NEGATIVE_ENCHANTMENTS) {
        if (!NEGATIVE_ENCHANTMENTS.isEmpty()) {
            randomNegativeEnchantment = NEGATIVE_ENCHANTMENTS.get(random.nextInt(NEGATIVE_ENCHANTMENTS.size()));
            MutableComponent enchantmentName = Component.translatable(randomNegativeEnchantment.getKey().toString());
            return enchantmentName.getString();
        }
        return "一个反面附魔";
    }

    // 随机应用正面效果的方法
    @Unique
    private String applyRandomPositiveEffect(List<Holder.Reference<MobEffect>> POSITIVE_EFFECTS) {
        if (!POSITIVE_EFFECTS.isEmpty()) {
            randomPositiveEffect = POSITIVE_EFFECTS.get(random.nextInt(POSITIVE_EFFECTS.size()));
            return randomPositiveEffect.value().getDisplayName().getString();
        }
        return "一个正面效果";
    }

    // 随机应用负面效果的方法
    @Unique
    private String applyRandomNegativeEffect(List<Holder.Reference<MobEffect>> NEGATIVE_EFFECTS) {
        if (!NEGATIVE_EFFECTS.isEmpty()) {
            randomNegativeEffect = NEGATIVE_EFFECTS.get(random.nextInt(NEGATIVE_EFFECTS.size()));
            return randomNegativeEffect.value().getDisplayName().getString();
        }
        return "一个负面效果";
    }

    // 从玩家背包中清除随机数量的物品
    @Unique
    private void clearRandomItems(int itemCount, ItemStack priorityItem) {
        Player player = (Player) (Object) this;
        List<ItemStack> inventory = player.getInventory().items;

        Random random = new Random();
        int itemsCleared = 0;

        while (itemsCleared < itemCount) {
            int slot = random.nextInt(inventory.size());
            ItemStack stack = inventory.get(slot);

            if (!stack.isEmpty() && !stack.is(priorityItem.getItem())) {
                int removeCount = Math.min(stack.getCount(), itemCount - itemsCleared);
                stack.shrink(removeCount);
                itemsCleared += removeCount;

                if (stack.isEmpty()) {
                    inventory.set(slot, ItemStack.EMPTY);
                }
            }

            if (itemsCleared < itemCount) {
                boolean hasNonPriorityItems = false;
                for (ItemStack itemStack : inventory) {
                    if (!itemStack.isEmpty() && !itemStack.is(priorityItem.getItem())) {
                        hasNonPriorityItems = true;
                        break;
                    }
                }
                if (!hasNonPriorityItems) {
                    break;
                }
            }
        }

        if (itemsCleared < itemCount) {
            for (int i = 0; i < inventory.size() && itemsCleared < itemCount; i++) {
                ItemStack stack = inventory.get(i);

                if (stack.is(priorityItem.getItem())) {
                    int removeCount = Math.min(stack.getCount(), itemCount - itemsCleared);
                    stack.shrink(removeCount);
                    itemsCleared += removeCount;

                    if (stack.isEmpty()) {
                        inventory.set(i, ItemStack.EMPTY);
                    }
                }
            }
        }
    }

    // 给玩家发放随机物品的方法
    @Unique
    private String grantRandomItem(List<Item> RANDOM_ITEMS) {
        if (!RANDOM_ITEMS.isEmpty()) {
            randomItem = RANDOM_ITEMS.get(random.nextInt(RANDOM_ITEMS.size()));
            randomItemStack = new ItemStack(randomItem);
            return randomItem.getDescription().getString();
        }
        return "一个随机物品";
    }

    // 用于罗马数字转换的静态映射表
    @Unique
    private static final Map<Integer, String> romanMap = new HashMap<>();

    static {
        romanMap.put(1, "I");
        romanMap.put(2, "II");
        romanMap.put(3, "III");
        romanMap.put(4, "IV");
        romanMap.put(5, "V");
        romanMap.put(6, "VI");
        romanMap.put(7, "VII");
        romanMap.put(8, "VIII");
        romanMap.put(9, "IX");
        romanMap.put(10, "X");
    }

    // 将整数转换为罗马数字的方法
    @Unique
    private static String toRoman(int number) {
        return romanMap.getOrDefault(number, "");
    }
}

16 是否用物品右键了某个方块
https://fuwari.vercel.app/posts/minecraft1_21_0/16_是否用物品右键了某个方块/
Author
Flandre923
Published at
2024-08-24