跳转至内容
  • 版块
  • 最新
  • 热门
  • 标签
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Zephyr)
  • 不使用皮肤
折叠
品牌标识

VariedMC 魔改论坛

不是椰浆不

不是椰浆

@不是椰浆
VariedMC Packing KubeJS
关于
帖子
9
主题
3
分享
0
群组
4
粉丝
0
关注
0
Blog

帖子

最新 最佳 有争议的

  • [原创][1.20.1][EidolonJS开发实录]基于链式调用达成在Schema注册中使用回调函数构建配方
    不是椰浆不 不是椰浆

    项目地址:PickAID/EidolonJS: as the name says


    在为Eidolon中的坩埚注册相应的Schema时,我发现了一个问题:

    坩埚配方的输入并不能够使用简单的RecipeKey添加,相关的代码如下:

    public static class Step {
            public final List<Ingredient> matches = new ArrayList<>();
            public final int stirs;
    
            public Step(int stirs, List<Ingredient> matches) {
                this.stirs = stirs;
                this.matches.addAll(matches);
            }
        }
    

    而最初一版的RecipeKey与Schema设计如下:

    public interface CrucibleSchema {
        RecipeKey<OutputItem> OUTPUT = ItemComponents.OUTPUT_ID_WITH_COUNT.key("result");
        RecipeKey<OutputItem[]> OUTPUT = ItemComponents.OUTPUT_ARRAY.key("result");
    
        RecipeComponentBuilder STEP_BUILDER = new RecipeComponentBuilder(2)
                .add(NumberComponent.INT.key("stirs").optional(1))
                .add(NumberComponent.INT.key("stirs").defaultOptional())
                .add(ItemComponents.INPUT_ARRAY.key("items"));
        RecipeKey<RecipeComponentBuilderMap[]> STEPS = STEP_BUILDER.inputRole().asArray().key("steps");
        RecipeSchema SCHEMA = new RecipeSchema(OUTPUT, STEPS);
    

    进行注册后简单对代码进行测试:

    ServerEvents.recipes(event => {
        event.recipes.eidolon.crucible("2x stone", [
            {stirs: 1, items: ["#forge:dusts/redstone", "2x eidolon:soul_shard"]},
            {items: ["#forge:dusts/redstone", "eidolon:soul_shard"]},
            {stirs: 1},
            {stirs: 3}
        ])
    }
    

    配方的确可以正常注册,但是可以看到,Step部分的格式与json几乎一致,不够优雅。
    于是笔者开始尝试在RecipeKey中使用回调函数,然而失败了(也有可能是我菜),
    而我在阅读了SummoningRitual的源代码之后(AlmostReliable/summoningrituals at 1.20.1-forge)有了不一样的想法。
    或许可以使用链式调用形式的配方,并在链式调用的方法中使用回调函数。
    完整的代码实现如下:

    //篇幅原因省去import
    
    //CrucibleSchema.java
    public interface CrucibleSchema {
        FunctionalInterface
        interface StepBuilderCallback {
            void applyStepBuilderJS builder;
        }
        class CrucibleRecipeJS extends RecipeJS {
            public CrucibleRecipeJS steps(StepBuilderCallback callback) {
                var builder = new StepBuilderJS();
                callback.apply(builder);
                setValue(STEPS, builder.getStepList().toArray(CrucibleRecipe.Step[]::new));
                return this;
            }
    
    
        }
    
        RecipeKey<CrucibleRecipe.Step[]> STEPS = new RecipeComponent<CrucibleRecipe.Step[]>() {
            @Override
            public Class<?> componentClass() {
                return CrucibleRecipe.Step[].class;
            }
    
            Override
            public JsonElement writeRecipeJS recipe, CrucibleRecipe.Step[] value {
                if (value == null) {
                    return null;
                }
    
                JsonArray stepsArray = new JsonArray();
                for (CrucibleRecipe.Step step : value) {
                    JsonObject stepObj = new JsonObject();
    
                    // Add stirs
                    stepObj.addProperty("stirs", step.stirs);
    
                    // Add items
                    if (!step.matches.isEmpty()) {
                        JsonArray itemsArray = new JsonArray();
                        for (Ingredient ingredient : step.matches) {
                            itemsArray.add(ingredient.toJson());
                        }
                        stepObj.add("items", itemsArray);
                    }
    
                    stepsArray.add(stepObj);
                }
    
                return stepsArray;
            }
    
            Override
            public CrucibleRecipe.Step[] readRecipeJS recipe, Object from {
                if (from instanceof JsonElement) {
                    JsonArray stepsArray = ((JsonElement) from).getAsJsonArray();
                    List<CrucibleRecipe.Step> steps = new ArrayList<>();
    
                    for (JsonElement element : stepsArray) {
                        if (!element.isJsonObject()) {
                            throw new JsonSyntaxException("Each step must be a JSON object");
                        }
    
                        JsonObject stepObj = element.getAsJsonObject();
                        int stirs = stepObj.has("stirs") ? stepObj.get("stirs").getAsInt() : 0;
    
                        List<Ingredient> ingredients = new ArrayList<>();
                        if (stepObj.has("items")) {
                            JsonArray itemsArray = stepObj.getAsJsonArray("items");
                            for (JsonElement item : itemsArray) {
                                ingredients.add(Ingredient.fromJson(item));
                            }
                        }
    
                        steps.add(new CrucibleRecipe.Step(stirs, ingredients));
                    }
    
                    return steps.toArray(CrucibleRecipe.Step[]::new);
                } else {
                    throw new JsonSyntaxException("Each step must be a JSON object");
                }
            }
        }.key("steps").noBuilders();
    
        RecipeKey<OutputItem> OUTPUT = ItemComponents.OUTPUT.key("result").noBuilders();
    
        RecipeSchema SCHEMA = new RecipeSchema(CrucibleRecipeJS.class, CrucibleRecipeJS::new, OUTPUT, STEPS).constructor(((recipe, schemaType, keys, from) -> {
            recipe.setValue(OUTPUT, from.getValue(recipe, OUTPUT));
            recipe.setValue(STEPS, new CrucibleRecipe.Step[0]);
        }), OUTPUT);
    
    }
    
    
    //StepBuilderJS.java
    public class StepBuilderJS {
        List<CrucibleRecipe.Step> stepList = new ArrayList<>();
        List<Ingredient> item = new ArrayList<>();
        int stirs = 0;
    
        public StepBuilderJS stirs(int count) {
            stirs = count;
            return this;
        }
    
        public StepBuilderJS stirs() {
            return stirs(1);
        }
    
        public StepBuilderJS items(Ingredient... items) {
            item.addAll(List.of(items));
            return this;
        }
    
        public void step(int count, Ingredient... items) {
            var step = new CrucibleRecipe.Step(count, item);
            stepList.add(step);
        }
    
        public void build(){
            var step = new CrucibleRecipe.Step(stirs, item);
            stepList.add(step);
            stirs(0);
            item.clear();
        }
    
        @HideFromJS
        public List<CrucibleRecipe.Step> getStepList() {
            return stepList;
        }
    }
    

    最终实现的效果如下:

    event.recipes.eidolon.crucible("2x stone").steps((step) => {
            step.stirs(1).items("#forge:dusts/redstone", "eidolon:soul_shard").build()
            step.items("#forge:dusts/redstone","eidolon:soul_shard").build()
            step.stirs(3).build()
        })
    

    或许直接使用链式调用传入每一步的设计更为直接,但是出于个人偏好,笔者仍然选择使用回调函数的形式处理这部分。
    (//TODO 代码详解施工中)

    灵感大王 forge kubejs 1.20.1 java
  • 1 / 1
  • 登录

  • 没有帐号? 注册

  • 登录或注册以进行搜索。
  • 第一个帖子
    最后一个帖子
0
  • 版块
  • 最新
  • 热门
  • 标签
  • 群组