跳转至内容

使用数据包修改模组插入的野生作物、植被或生物生成

灵感大王
5 3 200 1
  • 注:本教程适用于forge模组,且可能需要一小点世界生成基础(雾),不过后面也会给出实例与讲解。

    在许多模组中我们都会见到模组插入原版群系的野生作物、植被又或者生物生成等。但这些内容有些时候与整合包需求有所冲突,必须进行修改,可这种修改又一般从何进行呢?

    就拿先前群友的一个例子,禁用农夫乐事的野生作物,即野生胡萝卜等,我们来看看这个改如何操作。

    有一点世界生成基础的开发者可能知道,树、花卉、植被、野生作物包括小型遗迹等,这些群系的“装饰物‘,都被统称为”地物“。而地物是否在一个群系中生成,是写在群系文件中的,如果想要直接向群系写入地物,那么似乎必然要覆盖原本的群系文件。

    问题是,这样不仅工作量庞大,一旦出现两个群系模组双方都覆盖了同一个文件的情况,直接会导致冲突。因此,地物必然不是通过直接写入群系文件的方法插入群系的。

    emm,扯了这么多,终于来到我们的正题,biome_modifier。

    这是一个forge特有的接口,路径位于data/modid/forge/biome_modifier。这其中的json文件即是地物、实体生成等插入群系文件的”通道“。还是以农夫乐事举例,点开jar中相应的文件夹,最后我们会看到以下的内容:

    588d4229-1f2c-4cdf-9e64-5f17fe74aad4-image.png

    这也是老牌模组的一大优点,命名规范清晰,我们可以直接通过命名来判断每个修改器的内容。如果是某些g01.json,a03.json的抽象命名,或许就只能挨个试过去了……

    点开wild_carrots文件,这个显然控制着野生胡萝卜的生成。

    {
      "type": "farmersdelight:add_features_by_filter",
      "allowed_biomes": "#minecraft:is_overworld",
      "denied_biomes": ["minecraft:lush_caves", "minecraft:mushroom_fields"],
      "min_temperature": 0.4,
      "max_temperature": 0.9,
      "features": "farmersdelight:patch_wild_carrots",
      "step": "vegetal_decoration"
    }
    

    嗯,一个平平无奇的json,翻译一下大意基本就能清楚:类型这里采用了农夫乐事自己的一个type,插入的群系是所有主世界群系(主世界群系标签#minecraft:is_overworld),且不会在繁茂洞穴、蘑菇岛两个群系生成。

    温度范围限制……这个可能涉及一些噪声知识,不过只要知道在世界生成时会根据函数跑出每一个点的温度噪声,然后这里就是限制了在温度0.4~0.9才生成就好了。

    最后的"features"以及"step"这个就是地物的知识了,分别代表了放置的地物名称以及到底插入哪个生成步骤。这两行我们在进行修改的时候基本上不可能会碰到。(地物名称你改了那生成的都不是这个地物了,至于步骤,那个几乎和地物本身绑定的,我们修改已有的地物生成,不可能去碰)。

    好的,那么怎么修改呢?如果你要限定生成的群系就修改和群系有关的那两行就可以了,具体步骤就不演示了,用标签或者列表都可以。我们一般接触最多的还是需要直接删除它的生成,简单粗暴。

    这时候就要替换整个文件内容了,把内容换成:

    {
      "type": "forge:none"
    }
    

    是的,就是什么也不做,自然也不会生成地物了。

    然后把修改好的文件用数据包的方式替换掉原文件,不会数据包的可以先简单了解一下,后面我大概率也会稍微讲一点?(雾)

    注:如非必要,务必务必务必不要直接修改jar!这种行为很不好!

    这时候再进入游戏,你会发现野生胡萝卜不会再生成了。

    生物的生成也是一样,这里随便举个例子。

    too_much_bosses,一个非常优秀的mcr模组,不过笨笨作者有个冰花实体的自然生成忘记关了(mcr特色),导致乱刷,这种时候我们就可以直接顺着路径找过去,最后找到文件点开:

    {
      "type": "forge:add_spawns",
      "biomes": {
        "type": "forge:any"
      },
      "spawners": {
        "type": "too_much_bosses:icepoof_maker",
        "weight": 20,
        "minCount": 4,
        "maxCount": 4
      }
    }
    

    不论内容,直接替换成上面写的那一串,什么都不做,这样就不会再乱刷了

  • 抢沙发🛋️,再摸摸半梦

  • 抢沙发🛋️,再摸摸半梦

    @忆然使用数据包修改模组插入的野生作物、植被或生物生成 中说:

    抢沙发🛋️,再摸摸半梦

    事忆然,啃一口喵

  • biome_modifier这儿要是有生成器就好了,虽然不难。

  • 翻了一下Forge原生的有这些

    public static final RegistryObject<Codec<NoneBiomeModifier>> NONE_BIOME_MODIFIER_TYPE = BIOME_MODIFIER_SERIALIZERS.register("none", () -> Codec.unit(NoneBiomeModifier.INSTANCE));
    
        /**
         * Stock biome modifier for adding features to biomes.
         */
        public static final RegistryObject<Codec<AddFeaturesBiomeModifier>> ADD_FEATURES_BIOME_MODIFIER_TYPE = BIOME_MODIFIER_SERIALIZERS.register("add_features", () ->
            RecordCodecBuilder.create(builder -> builder.group(
                    Biome.LIST_CODEC.fieldOf("biomes").forGetter(AddFeaturesBiomeModifier::biomes),
                    PlacedFeature.LIST_CODEC.fieldOf("features").forGetter(AddFeaturesBiomeModifier::features),
                    Decoration.CODEC.fieldOf("step").forGetter(AddFeaturesBiomeModifier::step)
                ).apply(builder, AddFeaturesBiomeModifier::new))
            );
    
        /**
         * Stock biome modifier for removing features from biomes.
         */
        public static final RegistryObject<Codec<RemoveFeaturesBiomeModifier>> REMOVE_FEATURES_BIOME_MODIFIER_TYPE = BIOME_MODIFIER_SERIALIZERS.register("remove_features", () ->
            RecordCodecBuilder.create(builder -> builder.group(
                    Biome.LIST_CODEC.fieldOf("biomes").forGetter(RemoveFeaturesBiomeModifier::biomes),
                    PlacedFeature.LIST_CODEC.fieldOf("features").forGetter(RemoveFeaturesBiomeModifier::features),
                    new ExtraCodecs.EitherCodec<List<Decoration>, Decoration>(Decoration.CODEC.listOf(), Decoration.CODEC).<Set<Decoration>>xmap(
                            either -> either.map(Set::copyOf, Set::of), // convert list/singleton to set when decoding
                            set -> set.size() == 1 ? Either.right(set.toArray(Decoration[]::new)[0]) : Either.left(List.copyOf(set))
                        ).optionalFieldOf("steps", EnumSet.allOf(Decoration.class)).forGetter(RemoveFeaturesBiomeModifier::steps)
                ).apply(builder, RemoveFeaturesBiomeModifier::new))
            );
    
        /**
         * Stock biome modifier for adding mob spawns to biomes.
         */
        public static final RegistryObject<Codec<AddSpawnsBiomeModifier>> ADD_SPAWNS_BIOME_MODIFIER_TYPE = BIOME_MODIFIER_SERIALIZERS.register("add_spawns", () ->
            RecordCodecBuilder.create(builder -> builder.group(
                    Biome.LIST_CODEC.fieldOf("biomes").forGetter(AddSpawnsBiomeModifier::biomes),
                    // Allow either a list or single spawner, attempting to decode the list format first.
                    // Uses the better EitherCodec that logs both errors if both formats fail to parse.
                    new ExtraCodecs.EitherCodec<>(SpawnerData.CODEC.listOf(), SpawnerData.CODEC).xmap(
                            either -> either.map(Function.identity(), List::of), // convert list/singleton to list when decoding
                            list -> list.size() == 1 ? Either.right(list.get(0)) : Either.left(list) // convert list to singleton/list when encoding
                        ).fieldOf("spawners").forGetter(AddSpawnsBiomeModifier::spawners)
                ).apply(builder, AddSpawnsBiomeModifier::new))
            );
    
        /**
         * Stock biome modifier for removing mob spawns from biomes.
         */
        public static final RegistryObject<Codec<RemoveSpawnsBiomeModifier>> REMOVE_SPAWNS_BIOME_MODIFIER_TYPE = BIOME_MODIFIER_SERIALIZERS.register("remove_spawns", () ->
            RecordCodecBuilder.create(builder -> builder.group(
                    Biome.LIST_CODEC.fieldOf("biomes").forGetter(RemoveSpawnsBiomeModifier::biomes),
                    RegistryCodecs.homogeneousList(ForgeRegistries.Keys.ENTITY_TYPES).fieldOf("entity_types").forGetter(RemoveSpawnsBiomeModifier::entityTypes)
                ).apply(builder, RemoveSpawnsBiomeModifier::new))
            );
    

相关推荐


  • 论坛Tag征求

    壁画石窟 kubejs 渲染 数据包 世界生成 物品 实体 附魔
    4
    0 赞同
    4 帖子
    154 浏览
    Y
    tooltip 可以改成提示框或物品提示 https://zh.minecraft.wiki/w/提示框
  • 1 赞同
    1 帖子
    171 浏览
    忆然
    本文使用:CC-BY-NC-SA 4.0协议 kjs本身提供的物品注册比较有限,在注册某些kjs未提供的item的时候我们就需要用到createCustom 如果有需要的item注册可以在本文下方留言,会考虑更新 createCustom注册model是没有的,也就是你还得去写一份model.json(这部分可以参考原版wiki) 下面是使用createCustom去注册一个弓的例子 let $BowItem = Java.loadClass("net.minecraft.world.item.BowItem") let $Item$Properties = Java.loadClass("net.minecraft.world.item.Item$Properties") StartupEvents.registry("item", event => { event.createCustom("modid:item_name", () => { let properties = new $Item$Properties() //修改耐久 为0则无耐久属性 properties.durability(0) //修改最大堆叠数量 properties.stacksTo(1) //修改稀有度 properties.rarity("epic") //创建新的bowitem let item = new $BowItem(properties) //返回新的bowitem进行注册 return item }) })
  • [原创]使用kjs进行文件的删除

    灵感大王 kubejs 危险行为 数据操作
    4
    0 赞同
    4 帖子
    221 浏览
    草莓呜咩B
    @芒果凍布丁 我揣测Client可能被安全化了,所以loadClass,能直接用的话就安全多了呢。