进度触发器

进度触发器

进度触发器

触发方式

实现原理

触发方式

它使用的是trigger进行触发

我们先看看mojang的代码

展开查看代码 net.minecraft.advancements.critereon.RecipeUnlockedTrigger

package net.minecraft.advancements.critereon;

import com.google.gson.JsonObject;

import net.minecraft.advancements.critereon.EntityPredicate.Composite;

import net.minecraft.resources.ResourceLocation;

import net.minecraft.server.level.ServerPlayer;

import net.minecraft.util.GsonHelper;

import net.minecraft.world.item.crafting.Recipe;

public class RecipeUnlockedTrigger extends SimpleCriterionTrigger {

static final ResourceLocation ID = new ResourceLocation("recipe_unlocked");

public RecipeUnlockedTrigger() {

}

public ResourceLocation getId() {

return ID;

}

public TriggerInstance createInstance(JsonObject json, EntityPredicate.Composite entityPredicate, DeserializationContext conditionsParser) {

ResourceLocation resourceLocation = new ResourceLocation(GsonHelper.getAsString(json, "recipe"));

return new TriggerInstance(entityPredicate, resourceLocation);

}

public void trigger(ServerPlayer player, Recipe recipe) {

this.trigger(player, (arg2) -> arg2.matches(recipe));

}

public static TriggerInstance unlocked(ResourceLocation recipe) {

return new TriggerInstance(Composite.ANY, recipe);

}

public static class TriggerInstance extends AbstractCriterionTriggerInstance {

private final ResourceLocation recipe;

public TriggerInstance(EntityPredicate.Composite player, ResourceLocation recipe) {

super(RecipeUnlockedTrigger.ID, player);

this.recipe = recipe;

}

public JsonObject serializeToJson(SerializationContext context) {

JsonObject jsonObject = super.serializeToJson(context);

jsonObject.addProperty("recipe", this.recipe.toString());

return jsonObject;

}

public boolean matches(Recipe recipe) {

return this.recipe.equals(recipe.getId());

}

}

}

它被分为 SimpleCriterionTrigger 和 AbstractCriterionTriggerInstance 两个类

其中我们需要做的就是

写自己的trigger 和 matches

在服务器启动前将触发器注册

实现触发

接下来我们来实现配方合成时触发成就

写一个总触发器 CraftingRecipeTrigger类并且创建CraftingRecipeTrigger内部子类 TriggerInstance类

TriggerInstance需要实现序列化和创建对象

而CraftingRecipeTrigger所需要做的就是解析并反序列化创建实例 createInstance

在TriggerInstance实现matches判断

在CraftingRecipeTrigger实现trigger触发器

trigger触发器使用SimpleCriterionTrigger里面的trigger(ServerPlayer, Predicate)

注册实例(forge,fabric,architectury)

import com.google.gson.JsonObject;

import net.minecraft.advancements.critereon.*;

import net.minecraft.resources.ResourceLocation;

import net.minecraft.world.item.ItemStack;

import org.jetbrains.annotations.NotNull;

public class CraftingRecipeTrigger extends SimpleCriterionTrigger {

static final ResourceLocation ID = new ResourceLocation("tutorial", "crafting_recipe");

@Override

protected @NotNull TriggerInstance createInstance(@NotNull JsonObject json, EntityPredicate.@NotNull Composite player, @NotNull DeserializationContext context) {

return new TriggerInstance(player, ItemPredicate.fromJson(json.get("item")));

}

public void trigger(ServerPlayer player, ItemStack item) {

this.trigger(player, arg -> arg.matches(item));

}

// ... 1

public static class TriggerInstance extends AbstractCriterionTriggerInstance {

private final ItemPredicate item;

public TriggerInstance(EntityPredicate.Composite player, ItemPredicate item) {

super(CraftingRecipeTrigger.ID, player);

this.item = item;

}

@Override

public @NotNull JsonObject serializeToJson(@NotNull SerializationContext context) {

JsonObject jsonObject = super.serializeToJson(context);

jsonObject.add("item", this.item.serializeToJson());

return jsonObject;

}

public boolean matches(ItemStack item) {

return this.item.matches(item);

}

}

}

forge

在主类中实现

import net.minecraftforge.event.entity.player.PlayerEvent;

import net.minecraftforge.fml.common.Mod;

@Mod("tutorial")

public class Tutorial {

public static final CraftingRecipeTrigger cr = new CraftingRecipeTrigger();

public Tutorial() {

}

@SubscribeEvent

public static void craftEvents(PlayerEvent.ItemCraftedEvent event) {

if (event.getEntity() instanceof ServerPlayer serverPlayer) {

cr.trigger(serverPlayer, event.getCrafting());// 触发

}

}

}

Fabric

在主类中实现

import net.fabricmc.api.ModInitializer;

public class Tutorial implements ModInitializer {

public static final CraftingRecipeTrigger cr = new CraftingRecipeTrigger();

@Override

public void onInitialize() {

}

}

import net.minecraft.world.inventory.ResultSlot;

import org.spongepowered.asm.mixin.Mixin;

import org.spongepowered.asm.mixin.injection.At;

import org.spongepowered.asm.mixin.injection.Inject;

@Mixin(ResultSlot.class)

public class MixinCraftingRecipe {

@Inject(

method = "checkTakeAchievements",

at = @At(value = "INVOKE",

target = "Lnet/minecraft/world/item/ItemStack;onCraftedBy(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;I)V",

shift = At.Shift.AFTER)

)

private void craft(ItemStack itemStack, CallbackInfo ci) {

Tutorial.cr.trigger(serverPlayer, itemStack);

}

}

Architectury

多加载器模式触发的事件

import dev.architectury.event.events.common.PlayerEvent;

public class Tutorial {

public static final CraftingRecipeTrigger cr = new CraftingRecipeTrigger();

public static void init() {

PlayerEvent.CRAFT_ITEM.register((player, constructed, inventory) -> {

cr.trigger(serverPlayer, constructed);

});

}

}

相关推荐