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, "");
}
}