我的世界1.20.1forge模组进阶开发——生物生成2

怎么才能在特定的生物群系或结构生成生物?我们来研究一下alexmob,看看它是怎么写的。

自定义生物群系生成规则

先研究源码以便更好的开发模组

AMMobSpawnBiomeModifier类

package com.github.alexthe666.alexsmobs.world;import com.github.alexthe666.alexsmobs.AlexsMobs;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraftforge.common.world.BiomeModifier;
import net.minecraftforge.common.world.ModifiableBiomeInfo;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;public class AMMobSpawnBiomeModifier implements BiomeModifier {private static final RegistryObject<Codec<? extends BiomeModifier>> SERIALIZER = RegistryObject.create(new ResourceLocation(AlexsMobs.MODID, "am_mob_spawns"), ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, AlexsMobs.MODID);public AMMobSpawnBiomeModifier() {}public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {if (phase == Phase.ADD) {AMWorldRegistry.addBiomeSpawns(biome, builder);}}public Codec<? extends BiomeModifier> codec() {return (Codec)SERIALIZER.get();}public static Codec<AMMobSpawnBiomeModifier> makeCodec() {return Codec.unit(AMMobSpawnBiomeModifier::new);}
}

这段代码是 Minecraft Forge 模组 Alex’s Mobs 中用于动态修改生物群系(Biome)生成规则的实现。它的核心功能是向特定生物群系中添加自定义生物的生成规则。以下是对代码的详细解释:


1. 类定义与接口实现

public class AMMobSpawnBiomeModifier implements BiomeModifier {

• 类名 AMMobSpawnBiomeModifier 表明这是一个与生物生成(Mob Spawn)相关的生物群系修改器。
• 实现了 Forge 的 BiomeModifier 接口,允许在生物群系加载时动态修改其属性(如添加生物生成规则)。


2. 序列化器注册

private static final RegistryObject<Codec<? extends BiomeModifier>> SERIALIZER = RegistryObject.create(new ResourceLocation(AlexsMobs.MODID, "am_mob_spawns"), ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, AlexsMobs.MODID);

作用: 注册一个序列化器(Codec),用于将配置数据与 AMMobSpawnBiomeModifier 实例相互转换。
关键参数:
ResourceLocation: 唯一标识符,格式为 <modid>:am_mob_spawns(例如 alexsmobs:am_mob_spawns)。
ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS: 表明注册到 Forge 的生物群系修改器序列化器注册表中。
• 通过 RegistryObject 延迟获取序列化器,确保注册顺序正确。


3. 核心方法 modify

public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {if (phase == Phase.ADD) {AMWorldRegistry.addBiomeSpawns(biome, builder);}
}

作用: 在生物群系加载时,根据指定的 Phase 阶段修改其属性。
参数:
biome: 当前正在处理的生物群系。
phase: 修改阶段(ADD 表示添加新内容,MODIFY 表示修改现有内容)。
builder: 用于构建生物群系信息的工具类。
逻辑:
• 仅在 Phase.ADD 阶段触发,调用 AMWorldRegistry.addBiomeSpawns 方法,将自定义生物的生成规则添加到该生物群系中。
AMWorldRegistry.addBiomeSpawns 的具体实现(未在此展示)可能涉及添加生物生成规则(如生物类型、生成权重、最小/最大数量等)。


4. 序列化相关方法

public Codec<? extends BiomeModifier> codec() {return (Codec)SERIALIZER.get();
}public static Codec<AMMobSpawnBiomeModifier> makeCodec() {return Codec.unit(AMMobSpawnBiomeModifier::new);
}

codec():
• 返回该类使用的序列化器(Codec),即之前注册的 SERIALIZER
makeCodec():
• 创建一个简单的 Codec,直接通过构造函数 AMMobSpawnBiomeModifier::new 生成实例。
Codec.unit 表示该 Codec 不需要额外配置参数,直接返回一个默认实例。


5. 整体工作流程

  1. 注册序列化器:
    • 在 Forge 的注册表中声明 AMMobSpawnBiomeModifier 的序列化器,使游戏能识别并加载相关配置。

  2. 生物群系修改阶段:
    • 当游戏加载生物群系时,Forge 会调用 modify 方法。
    • 在 Phase.ADD 阶段,通过 AMWorldRegistry.addBiomeSpawns 向生物群系添加自定义生物生成规则。

  3. 数据驱动:
    • 通过 Codec 序列化/反序列化,可能支持通过 JSON 文件配置生物生成规则(如不同群系的生成参数)。


6. 实际应用场景

• 假设模组添加了一个名为“袋鼠”的生物,需要在沙漠和草原群系中生成。
• 在 AMWorldRegistry.addBiomeSpawns 中,会根据生物群系类型(通过 biome 参数判断)调用类似 builder.getMobSpawnSettings().addSpawn(...) 的代码,添加生成规则。


总结

这段代码是 Alex’s Mobs 模组中用于动态管理生物生成的核心逻辑,利用 Forge 的 BiomeModifier 系统,在生物群系加载时注入自定义生成规则。通过 Codec 实现数据驱动,使得生物生成配置更加灵活且易于维护。

和Biometag的联系:

这两段代码分别属于 生物群系(Biome)的动态修改生物群系的标签分类 系统,在 Minecraft 模组开发中密切相关但功能不同。以下是它们的联系与区别分析:


联系

  1. 共同目标
    两者均围绕 生物群系的特性管理,但角度不同:
    AMMobSpawnBiomeModifier动态添加生物生成规则到符合条件的生物群系。
    BiomeTags定义生物群系的分类标签(如是否为海洋、森林,是否生成特定结构等),供游戏逻辑判断。

  2. 潜在依赖关系
    AMMobSpawnBiomeModifier 在实现时 可能依赖 BiomeTags 的标签,例如:

    // 假设在 AMWorldRegistry.addBiomeSpawns 中:
    if (biome.is(BiomeTags.IS_FOREST)) {builder.getMobSpawnSettings().addSpawn(...); // 仅在森林群系添加生物
    }
    

    • 通过 BiomeTags 的标签,可以精确控制生物生成的目标群系。

  3. 数据驱动协同
    BiomeTags 提供 静态标签分类(如 IS_OCEAN),用于描述生物群系的属性。
    AMMobSpawnBiomeModifier 利用这些标签 动态注入逻辑(如只在海洋群系生成某种鱼类)。


区别

特性AMMobSpawnBiomeModifier (模组代码)BiomeTags (原版代码)
功能动态修改生物群系的生成规则(如添加生物)定义生物群系的分类标签(元数据)
所属系统Forge 的 BiomeModifier 系统原版 Minecraft 的标签系统(TagKey
实现方式通过 BiomeModifier 接口和 Codec 序列化静态定义 TagKey 常量
数据驱动可能依赖 JSON 配置或代码硬编码规则标签通过资源包或数据包动态配置
代码层级模组业务逻辑(添加自定义内容)原版基础设施(提供全局分类标准)
典型应用场景模组生物的生成控制原版结构生成、天气逻辑、生物行为等

核心细节解析

  1. BiomeTags 的作用
    • 用于标记生物群系的属性,例如:

    public static final TagKey<Biome> IS_OCEAN = create("is_ocean");
    public static final TagKey<Biome> HAS_OCEAN_MONUMENT = create("has_structure/ocean_monument");
    

    • 游戏逻辑可通过这些标签快速判断群系特性,例如:
    ◦ 海洋神庙只生成在 HAS_OCEAN_MONUMENT 标签的群系。
    ◦ 溺尸生成频率可能在 MORE_FREQUENT_DROWNED_SPAWNS 标签的群系中提高。

  2. AMMobSpawnBiomeModifier 的工作流程
    注册序列化器:通过 SERIALIZER 声明该修改器的配置方式。
    修改阶段:在 Phase.ADD 阶段调用 AMWorldRegistry.addBiomeSpawns,向群系注入生物生成规则。
    潜在标签依赖:若模组生物需在特定标签的群系生成(如森林),需通过 BiomeTags.IS_FOREST 判断。


协作示例

假设模组要添加一个 “森林精灵”生物,仅在森林群系(IS_FOREST)且无巡逻队生成(WITHOUT_PATROL_SPAWNS)的群系中出现:

  1. BiomeTags:利用现有标签 IS_FORESTWITHOUT_PATROL_SPAWNS
  2. AMMobSpawnBiomeModifier
    public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {if (phase == Phase.ADD && biome.is(BiomeTags.IS_FOREST) && biome.is(BiomeTags.WITHOUT_PATROL_SPAWNS)) {builder.getMobSpawnSettings().addSpawn(...); // 添加“森林精灵”生成规则}
    }
    
    • 直接依赖 BiomeTags 的标签实现精准控制。

总结

BiomeTags 是“群系属性字典”:提供全局的群系分类标准,供游戏和模组共用。
AMMobSpawnBiomeModifier 是“动态规则引擎”:利用标签或硬编码逻辑,向群系注入自定义内容。
二者协作:标签系统为动态修改提供判断依据,动态修改器实现具体游戏内容的变化。
(例如:原版用标签控制结构生成,模组用同一标签控制生物生成,实现无缝兼容。)

ModifiableBiomeInfo类

这段代码是 Minecraft Forge 中用于动态修改生物群系(Biome)属性的核心类 ModifiableBiomeInfo,其原理围绕 封装生物群系数据应用模组修改逻辑 展开。以下是代码的详细分析:


1. 类结构与作用

ModifiableBiomeInfo

作用
封装一个生物群系的原始数据,并提供接口让模组(Mod)按阶段动态修改其属性(如气候、特效、地形生成规则、刷怪规则等)。
成员变量
originalBiomeInfo:原始生物群系数据(不可变)。
modifiedBiomeInfo:修改后的生物群系数据(初始为 null,应用修改后生成)。

BiomeInfo 内部记录类(Record)

作用
存储生物群系的完整配置,包含四个核心属性:
climateSettings:气候设置(温度、降水量等)。
effects:视觉效果(天空颜色、水颜色等)。
generationSettings:地形生成规则(如结构、植被)。
mobSpawnSettings:刷怪规则(生物种类、权重等)。

Builder 内部类

作用
基于建造者模式(Builder Pattern)逐步构建 BiomeInfo 对象,允许复制原始数据并分步骤修改。


2. 核心方法解析

applyBiomeModifiers 方法
public void applyBiomeModifiers(Holder<Biome> biome, List<BiomeModifier> biomeModifiers) {if (this.modifiedBiomeInfo != null) {throw new IllegalStateException("Biome already modified");}BiomeInfo original = this.getOriginalBiomeInfo();BiomeInfo.Builder builder = BiomeInfo.Builder.copyOf(original); // 复制原始数据// 按阶段(Phase)应用所有 BiomeModifierfor (Phase phase : Phase.values()) {for (BiomeModifier modifier : biomeModifiers) {modifier.modify(biome, phase, builder); // 调用修改器}}this.modifiedBiomeInfo = builder.build(); // 构建修改后的数据
}

流程

  1. 检查是否已修改:若已修改则抛出异常,避免重复修改。
  2. 复制原始数据:通过 Builder.copyOf 创建一个可修改的副本。
  3. 按阶段应用修改器:遍历所有 BiomeModifier,并按阶段(如 ADDREMOVEMODIFY)调用其 modify 方法。
  4. 构建最终数据:将修改后的 Builder 转换为不可变的 BiomeInfo

关键点
阶段(Phase):允许不同模组按顺序修改生物群系。例如:
ADD 阶段添加新规则。
MODIFY 阶段调整现有规则。
REMOVE 阶段删除某些规则。
不可变数据:修改后的 BiomeInfo 是不可变对象,确保线程安全和数据一致性。


3. 设计模式与原理

建造者模式(Builder Pattern)

BiomeInfo.Builder
提供逐步构建 BiomeInfo 的能力,通过方法链式调用修改各个属性:

BiomeInfo.Builder builder = BiomeInfo.Builder.copyOf(original);
builder.getClimateSettings().setTemperature(0.5f);
builder.getMobSpawnSettings().addSpawn(...);
BiomeInfo modified = builder.build();

优点
将对象构建与表示分离,支持灵活修改且避免参数爆炸。

不可变对象(Immutable Object)

BiomeInfo 为记录类(Record)
所有字段在构造后不可变,确保在多线程环境下无需同步即可安全访问。
修改流程
通过复制原始数据生成新对象,避免直接修改原数据。

事件驱动修改

BiomeModifier 接口
模组通过实现此接口并注册到 Forge 事件系统,在游戏加载生物群系时动态修改其属性。例如:

public class MyBiomeModifier implements BiomeModifier {@Overridepublic void modify(Holder<Biome> biome, Phase phase, BiomeInfo.Builder builder) {if (phase == Phase.ADD) {builder.getMobSpawnSettings().addSpawn(...); // 添加新生物}}
}

4. 与 Alex’s Mobs 的关联

在用户之前提供的 AMWorldRegistry 代码中,addBiomeSpawns 方法可能通过注册 BiomeModifier 来修改生物群系的刷怪规则。例如:

// 伪代码:注册一个 BiomeModifier
BiomeModifierManager.addModifier(context -> {context.getBuilder().getMobSpawnSettings().addSpawn(...); // 添加模组生物
});

ModifiableBiomeInfo 类是这一过程的底层支持,负责协调所有模组的修改请求,并按阶段生成最终配置。


5. 总结

功能
ModifiableBiomeInfo 是 Forge 提供的核心工具类,用于实现生物群系属性的动态修改,支持多模组协作。
设计亮点
• 使用建造者模式逐步构建不可变数据。
• 分阶段应用修改器,确保逻辑顺序和兼容性。
• 通过不可变对象保证线程安全。
应用场景
模组开发者通过注册 BiomeModifier,在游戏加载时修改生物群系的气候、刷怪规则、地形生成等,实现自定义内容与原版或其他模组的无缝集成。

Biome类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package net.minecraft.world.level.biome;import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.longs.Long2FloatLinkedOpenHashMap;
import java.util.Optional;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryCodecs;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryFileCodec;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.Mth;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.FoliageColor;
import net.minecraft.world.level.GrassColor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.common.world.ModifiableBiomeInfo;public final class Biome {public static final Codec<Biome> DIRECT_CODEC = RecordCodecBuilder.create((p_220544_) -> p_220544_.group(Biome.ClimateSettings.CODEC.forGetter((p_151717_) -> p_151717_.modifiableBiomeInfo().getOriginalBiomeInfo().climateSettings()), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((p_220550_) -> p_220550_.modifiableBiomeInfo().getOriginalBiomeInfo().effects()), BiomeGenerationSettings.CODEC.forGetter((p_220548_) -> p_220548_.generationSettings), MobSpawnSettings.CODEC.forGetter((p_220546_) -> p_220546_.mobSettings)).apply(p_220544_, Biome::new));public static final Codec<Biome> NETWORK_CODEC = RecordCodecBuilder.create((p_220540_) -> p_220540_.group(Biome.ClimateSettings.CODEC.forGetter((p_220542_) -> p_220542_.climateSettings), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((p_220538_) -> p_220538_.specialEffects)).apply(p_220540_, (p_220535_, p_220536_) -> new Biome(p_220535_, p_220536_, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY)));public static final Codec<Holder<Biome>> CODEC;public static final Codec<HolderSet<Biome>> LIST_CODEC;private static final PerlinSimplexNoise TEMPERATURE_NOISE;static final PerlinSimplexNoise FROZEN_TEMPERATURE_NOISE;/** @deprecated */@Deprecated(forRemoval = true)public static final PerlinSimplexNoise BIOME_INFO_NOISE;private static final int TEMPERATURE_CACHE_SIZE = 1024;private final ClimateSettings climateSettings;private final BiomeGenerationSettings generationSettings;private final MobSpawnSettings mobSettings;private final BiomeSpecialEffects specialEffects;private final ThreadLocal<Long2FloatLinkedOpenHashMap> temperatureCache = ThreadLocal.withInitial(() -> (Long2FloatLinkedOpenHashMap)Util.make(() -> {Long2FloatLinkedOpenHashMap long2floatlinkedopenhashmap = new Long2FloatLinkedOpenHashMap(1024, 0.25F) {protected void rehash(int p_47580_) {}};long2floatlinkedopenhashmap.defaultReturnValue(Float.NaN);return long2floatlinkedopenhashmap;}));private final ModifiableBiomeInfo modifiableBiomeInfo;Biome(ClimateSettings p_220530_, BiomeSpecialEffects p_220531_, BiomeGenerationSettings p_220532_, MobSpawnSettings p_220533_) {this.climateSettings = p_220530_;this.generationSettings = p_220532_;this.mobSettings = p_220533_;this.specialEffects = p_220531_;this.modifiableBiomeInfo = new ModifiableBiomeInfo(new ModifiableBiomeInfo.BiomeInfo(p_220530_, p_220531_, p_220532_, p_220533_));}public int getSkyColor() {return this.specialEffects.getSkyColor();}public MobSpawnSettings getMobSettings() {return this.modifiableBiomeInfo().get().mobSpawnSettings();}public boolean hasPrecipitation() {return this.climateSettings.hasPrecipitation();}public Precipitation getPrecipitationAt(BlockPos p_265163_) {if (!this.hasPrecipitation()) {return Biome.Precipitation.NONE;} else {return this.coldEnoughToSnow(p_265163_) ? Biome.Precipitation.SNOW : Biome.Precipitation.RAIN;}}private float getHeightAdjustedTemperature(BlockPos p_47529_) {float f = this.climateSettings.temperatureModifier.modifyTemperature(p_47529_, this.getBaseTemperature());if (p_47529_.getY() > 80) {float f1 = (float)(TEMPERATURE_NOISE.getValue((double)((float)p_47529_.getX() / 8.0F), (double)((float)p_47529_.getZ() / 8.0F), false) * (double)8.0F);return f - (f1 + (float)p_47529_.getY() - 80.0F) * 0.05F / 40.0F;} else {return f;}}/** @deprecated */@Deprecatedprivate float getTemperature(BlockPos p_47506_) {long i = p_47506_.asLong();Long2FloatLinkedOpenHashMap long2floatlinkedopenhashmap = (Long2FloatLinkedOpenHashMap)this.temperatureCache.get();float f = long2floatlinkedopenhashmap.get(i);if (!Float.isNaN(f)) {return f;} else {float f1 = this.getHeightAdjustedTemperature(p_47506_);if (long2floatlinkedopenhashmap.size() == 1024) {long2floatlinkedopenhashmap.removeFirstFloat();}long2floatlinkedopenhashmap.put(i, f1);return f1;}}public boolean shouldFreeze(LevelReader p_47478_, BlockPos p_47479_) {return this.shouldFreeze(p_47478_, p_47479_, true);}public boolean shouldFreeze(LevelReader p_47481_, BlockPos p_47482_, boolean p_47483_) {if (this.warmEnoughToRain(p_47482_)) {return false;} else {if (p_47482_.getY() >= p_47481_.getMinBuildHeight() && p_47482_.getY() < p_47481_.getMaxBuildHeight() && p_47481_.getBrightness(LightLayer.BLOCK, p_47482_) < 10) {BlockState blockstate = p_47481_.getBlockState(p_47482_);FluidState fluidstate = p_47481_.getFluidState(p_47482_);if (fluidstate.getType() == Fluids.WATER && blockstate.getBlock() instanceof LiquidBlock) {if (!p_47483_) {return true;}boolean flag = p_47481_.isWaterAt(p_47482_.west()) && p_47481_.isWaterAt(p_47482_.east()) && p_47481_.isWaterAt(p_47482_.north()) && p_47481_.isWaterAt(p_47482_.south());if (!flag) {return true;}}}return false;}}public boolean coldEnoughToSnow(BlockPos p_198905_) {return !this.warmEnoughToRain(p_198905_);}public boolean warmEnoughToRain(BlockPos p_198907_) {return this.getTemperature(p_198907_) >= 0.15F;}public boolean shouldMeltFrozenOceanIcebergSlightly(BlockPos p_198909_) {return this.getTemperature(p_198909_) > 0.1F;}public boolean shouldSnow(LevelReader p_47520_, BlockPos p_47521_) {if (this.warmEnoughToRain(p_47521_)) {return false;} else {if (p_47521_.getY() >= p_47520_.getMinBuildHeight() && p_47521_.getY() < p_47520_.getMaxBuildHeight() && p_47520_.getBrightness(LightLayer.BLOCK, p_47521_) < 10) {BlockState blockstate = p_47520_.getBlockState(p_47521_);if ((blockstate.isAir() || blockstate.is(Blocks.SNOW)) && Blocks.SNOW.defaultBlockState().canSurvive(p_47520_, p_47521_)) {return true;}}return false;}}public BiomeGenerationSettings getGenerationSettings() {return this.modifiableBiomeInfo().get().generationSettings();}public int getFogColor() {return this.specialEffects.getFogColor();}public int getGrassColor(double p_47465_, double p_47466_) {int i = (Integer)this.specialEffects.getGrassColorOverride().orElseGet(this::getGrassColorFromTexture);return this.specialEffects.getGrassColorModifier().modifyColor(p_47465_, p_47466_, i);}private int getGrassColorFromTexture() {double d0 = (double)Mth.clamp(this.climateSettings.temperature, 0.0F, 1.0F);double d1 = (double)Mth.clamp(this.climateSettings.downfall, 0.0F, 1.0F);return GrassColor.get(d0, d1);}public int getFoliageColor() {return (Integer)this.specialEffects.getFoliageColorOverride().orElseGet(this::getFoliageColorFromTexture);}private int getFoliageColorFromTexture() {double d0 = (double)Mth.clamp(this.climateSettings.temperature, 0.0F, 1.0F);double d1 = (double)Mth.clamp(this.climateSettings.downfall, 0.0F, 1.0F);return FoliageColor.get(d0, d1);}public float getBaseTemperature() {return this.climateSettings.temperature;}public BiomeSpecialEffects getSpecialEffects() {return this.specialEffects;}public int getWaterColor() {return this.specialEffects.getWaterColor();}public int getWaterFogColor() {return this.specialEffects.getWaterFogColor();}public Optional<AmbientParticleSettings> getAmbientParticle() {return this.specialEffects.getAmbientParticleSettings();}public Optional<Holder<SoundEvent>> getAmbientLoop() {return this.specialEffects.getAmbientLoopSoundEvent();}public Optional<AmbientMoodSettings> getAmbientMood() {return this.specialEffects.getAmbientMoodSettings();}public Optional<AmbientAdditionsSettings> getAmbientAdditions() {return this.specialEffects.getAmbientAdditionsSettings();}public Optional<Music> getBackgroundMusic() {return this.specialEffects.getBackgroundMusic();}public ModifiableBiomeInfo modifiableBiomeInfo() {return this.modifiableBiomeInfo;}public ClimateSettings getModifiedClimateSettings() {return this.modifiableBiomeInfo().get().climateSettings();}public BiomeSpecialEffects getModifiedSpecialEffects() {return this.modifiableBiomeInfo().get().effects();}static {CODEC = RegistryFileCodec.create(Registries.BIOME, DIRECT_CODEC);LIST_CODEC = RegistryCodecs.homogeneousList(Registries.BIOME, DIRECT_CODEC);TEMPERATURE_NOISE = new PerlinSimplexNoise(new WorldgenRandom(new LegacyRandomSource(1234L)), ImmutableList.of(0));FROZEN_TEMPERATURE_NOISE = new PerlinSimplexNoise(new WorldgenRandom(new LegacyRandomSource(3456L)), ImmutableList.of(-2, -1, 0));BIOME_INFO_NOISE = new PerlinSimplexNoise(new WorldgenRandom(new LegacyRandomSource(2345L)), ImmutableList.of(0));}public static class BiomeBuilder {private boolean hasPrecipitation = true;@Nullableprivate Float temperature;private TemperatureModifier temperatureModifier;@Nullableprivate Float downfall;@Nullableprivate BiomeSpecialEffects specialEffects;@Nullableprivate MobSpawnSettings mobSpawnSettings;@Nullableprivate BiomeGenerationSettings generationSettings;public BiomeBuilder() {this.temperatureModifier = Biome.TemperatureModifier.NONE;}public BiomeBuilder hasPrecipitation(boolean p_265480_) {this.hasPrecipitation = p_265480_;return this;}public BiomeBuilder temperature(float p_47610_) {this.temperature = p_47610_;return this;}public BiomeBuilder downfall(float p_47612_) {this.downfall = p_47612_;return this;}public BiomeBuilder specialEffects(BiomeSpecialEffects p_47604_) {this.specialEffects = p_47604_;return this;}public BiomeBuilder mobSpawnSettings(MobSpawnSettings p_47606_) {this.mobSpawnSettings = p_47606_;return this;}public BiomeBuilder generationSettings(BiomeGenerationSettings p_47602_) {this.generationSettings = p_47602_;return this;}public BiomeBuilder temperatureAdjustment(TemperatureModifier p_47600_) {this.temperatureModifier = p_47600_;return this;}public Biome build() {if (this.temperature != null && this.downfall != null && this.specialEffects != null && this.mobSpawnSettings != null && this.generationSettings != null) {return new Biome(new ClimateSettings(this.hasPrecipitation, this.temperature, this.temperatureModifier, this.downfall), this.specialEffects, this.generationSettings, this.mobSpawnSettings);} else {throw new IllegalStateException("You are missing parameters to build a proper biome\n" + this);}}public String toString() {return "BiomeBuilder{\nhasPrecipitation=" + this.hasPrecipitation + ",\ntemperature=" + this.temperature 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39265.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 HTML 中创建一个有序列表和无序列表,它们的语义有何不同?

大白话如何在 HTML 中创建一个有序列表和无序列表&#xff0c;它们的语义有何不同&#xff1f; 1. HTML 中有序列表和无序列表的基本概念 在 HTML 里&#xff0c;列表是一种用来组织信息的方式。有序列表就是带有编号的列表&#xff0c;它可以让内容按照一定的顺序呈现&#…

c++malloc出来的对象调用构造-------定位new

前言:之前在搓高并发内存池的时候就在想,类对象不能调用自身的构造函数,那直接申请内存出来的类对象岂不是很难受,然后我这两天仔细研究了一下,发现其实构造函数也可以显示去调用,而且含不限量,故做此文 在c中一个类对象不能直接调用自身的构造 class A { public:A() {cout &l…

ElementUI时间选择、日期选择

如大家所发现的&#xff0c;由于ElementUI 时间选择器&#xff0c;日期选择器&#xff0c;时间日期选择器点击清除按钮时&#xff0c;v-model 所绑定的属性值会变成 null&#xff0c;所以当使用 ElementUI 时间选择器&#xff0c;日期选择器&#xff0c;时间日期选择器 时&…

一篇文章入门Python Flask框架前后端数据库开发实践(pycharm在anaconda环境下)

Python Flask 是一个轻量级的 Web 应用框架&#xff0c;也被称为微框架。它以简洁、灵活和易于上手的特点而受到开发者的喜爱。 核心特点 轻量级&#xff1a;Flask 核心代码简洁&#xff0c;仅包含 Web 开发的基本功能&#xff0c;不强制使用特定的数据库、模板引擎等&#xf…

ctfshow WEB web2

1.查当前数据库名称 or 11 union select 1,database(),3 limit 1,2;#-- 得到数据库名称web2 2.查看数据库表的数量 or 11 union select 1,(select count(*) from information_schema.tables where table_schema web2),3 limit 1,2;#-- 得到数据库表数量为2 3.查表的名字 第…

【Git】--- 分支管理

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Git 本篇博客我们来介绍Git的一个重要功能之一 ---- 分支。我们将讲解关于分支的各种操作&#xff0c;以及如何帮助我们进行开发。 &#x1f3e0; 理解分支…

系统思考与心智模式

“问题不是出在我们做了多少&#xff0c;而是出在我们做了什么。” — 赫尔曼凯恩 “一分耕耘一分收获”&#xff0c;这似乎是我们脑海中根深蒂固的心智模式。今天&#xff0c;我在一家餐厅用餐&#xff0c;店员告诉我&#xff0c;打卡收藏可以获得一份小食。没过多久&#xf…

纯文本驱动的数据可视化革命——AI生成图表「图表狐」全场景深度解析

一、技术架构重定义 图表狐核心能力边界 ✅ 纯文本输入&#xff1a;支持任意格式文字描述&#xff08;会议纪要/邮件/手写笔记&#xff09; ✅ 智能解析引擎&#xff1a; 实体识别&#xff08;数值/时间/分类维度&#xff09; 语义纠错&#xff08;自动修复错别字/单位混乱&…

多线程 --- 进程和线程的基本知识

进程 前面我们提到了一个概念是&#xff0c;多任务操作系统&#xff0c;即希望该系统能够同时运行多个程序。本质上说&#xff0c;进程&#xff0c;就算用来解决”并发编程“这样的问题的。 在一些特定的情况下&#xff0c;进程的表现&#xff0c;其实并不能很好的解决”并发…

SCI英文论文Accepted后的第一步——Rights and Access

SCI英文论文Accepted后的第一步——Rights and Access 目录 SCI英文论文Accepted后的第一步——Rights and AccessBased on information provided the embargo period/end date is 24 months. 因为选择闭源**Rights and Access(版权与访问权限)**环节是关键第一步,具体操作流…

流程控制语句

python中的流程控制语句有三种&#xff0c;顺序结构、条件结构和循环结构 1&#xff09;顺序结构&#xff1a; 从上往下&#xff0c;从左到右&#xff0c;依次逐行执行。 #顺序结构python print(start) print(hello world1 ) print(hello world2 ) print(hello world3 ) pri…

2.4 关键路径法

项目进度管理核心工具全解析 &#x1f680; 一、关键路径法&#xff08;CPM&#xff09;精要 1. 核心概念图解 #mermaid-svg-5MOABZm9lR8A53ss {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-5MOABZm9lR8A53ss .e…

Unity 实现一个简易可拓展性的对话系统

本人能力有限,一切实现仅供参考,如有不足还请斧正 起因是我看到学校社团内有人做了对话系统的分享,我想了想之前没写过这种东西,而Fungus插件教程太老了,NodeCanvas插件学习成本又比较高,我就干脆寻找资料 加上自己迭代一下,花了一天时间完成了这个对话系统 目录 1.介绍 2.核…

架构思维:通用系统设计方法论_从复杂度分析到技术实现指南

文章目录 Question订单履约原始架构痛点目标架构架构图说明关键设计点优点 设计方法论复杂来源解决方案评估标准从设计原则出发 技术实现 &#xff08;以选型Redis为例&#xff09;Redis消息队列的实现细节高可用设计 总结 Question 我们经常聊如何设计一个比较完善的系统&…

llama源码学习·model.py[7]Transformer类

一、源码展示 class Transformer(nn.Module):def __init__(self, params: ModelArgs):super().__init__()self.params paramsself.vocab_size params.vocab_sizeself.n_layers params.n_layersself.tok_embeddings VocabParallelEmbedding(params.vocab_size, params.dim,…

MD2Card(markdown)

MD2Card 介绍&#xff1a; 1.小红书爆款神器&#xff0c;Markdown笔记秒转高颜值卡片 2.实时预览15种主题&#xff0c;自动拆长文&#xff0c;图片/SVG导出即用 3.零门槛不登录&#xff0c;免费无限生成&#xff0c;专治排版废和设计手残党 网站地址&#xff1a; https://md2…

第二节第一部分:String字符串

一、导包 二、String字符串 三、String注意事项 四、字符串的比较 五、面试例题 六、String案例一 需求分析&#xff1a; 代码&#xff1a; package com.StringTest;import java.util.Scanner;public class StingTest {public static void main(String[] args) {//1.开发一个…

动态规划(01背包恰好装满型详解):和为目标值的最长子序列长度

0-1背包&#xff1a;有n个物品&#xff0c;第i个物品的体积为w[i]&#xff0c;价值为v[i]&#xff0c;每个物品至多选择一个&#xff0c;求体积和不超过capacity的最大价值和。 对于第i个物品&#xff0c;我们只有两种选择&#xff1a;选&#xff0c;或者不选。如果选&#xf…

Spring漏洞再现

一、CVE-2017-8046 1、开环境 2、访问目录 /customers/1 3、在当前页抓包&#xff0c;并修改数据包 PATCH /customers/1 HTTP/1.1 Host: 150.158.199.164:8080 Accept-Encoding: gzip, deflate Accept: */* User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;…

Ftrans飞驰云联受邀参加“2025汽车零部件CIO年会“并荣获智象奖

2025年3月6日&#xff0c;由栖观汽车、栖观资讯和飞羽商务主办的“2025第二届中国汽车&零部件CIO年会暨智象奖颁奖盛典”于上海盛大召开&#xff0c;Ftrans飞驰云联作为国内领先的企业文件传输与数据交换解决方案提供商&#xff0c;受邀出席了年会&#xff0c;并凭借卓越的…