mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
[1.19.x] Add stock biome modifier types for adding features and spawns (#8697)
This commit is contained in:
1 parent
2a05c7c01d
commit
683bf99fe4
10 files changed
+391
-84
No files matched your search
@@ -20,10 +20,16 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryCodecs;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@@ -42,6 +48,10 @@ import net.minecraftforge.common.extensions.IForgePlayer;
|
||||
import net.minecraftforge.common.loot.CanToolPerformAction;
|
||||
import net.minecraftforge.common.loot.LootTableIdCondition;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import net.minecraftforge.common.world.ForgeBiomeModifiers.AddFeaturesBiomeModifier;
|
||||
import net.minecraftforge.common.world.ForgeBiomeModifiers.AddSpawnsBiomeModifier;
|
||||
import net.minecraftforge.common.world.ForgeBiomeModifiers.RemoveFeaturesBiomeModifier;
|
||||
import net.minecraftforge.common.world.ForgeBiomeModifiers.RemoveSpawnsBiomeModifier;
|
||||
import net.minecraftforge.common.world.NoneBiomeModifier;
|
||||
import net.minecraftforge.common.world.NoneStructureModifier;
|
||||
import net.minecraftforge.common.world.StructureModifier;
|
||||
@@ -92,11 +102,14 @@ import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Mod("forge")
|
||||
public class ForgeMod
|
||||
@@ -147,6 +160,55 @@ public class ForgeMod
|
||||
*/
|
||||
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))
|
||||
);
|
||||
/**
|
||||
* Noop structure modifier. Can be used in a structure modifier json with "type": "forge:none".
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.slf4j.Logger;
|
||||
*
|
||||
* @param <T> the type of thing being generated.
|
||||
*/
|
||||
public final class JsonCodecProvider<T> implements DataProvider
|
||||
public class JsonCodecProvider<T> implements DataProvider
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
protected final DataGenerator dataGenerator;
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.world;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.world.ModifiableBiomeInfo.BiomeInfo.Builder;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public final class ForgeBiomeModifiers
|
||||
{
|
||||
private ForgeBiomeModifiers() {} // Utility class.
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that adds features to biomes. Has the following json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:add_features", // required
|
||||
* "biomes": "#namespace:your_biome_tag" // accepts a biome id, [list of biome ids], or #namespace:biome_tag
|
||||
* "features": "namespace:your_feature", // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag
|
||||
* "step": "underground_ores" // accepts a Decoration enum name
|
||||
* }
|
||||
* </pre>
|
||||
* <p>Be wary of using this to add vanilla PlacedFeatures to biomes, as doing so may cause a feature cycle violation.</p>
|
||||
*
|
||||
* @param biomes Biomes to add features to.
|
||||
* @param features PlacedFeatures to add to biomes.
|
||||
* @param step Decoration step to run features in.
|
||||
*/
|
||||
public static record AddFeaturesBiomeModifier(HolderSet<Biome> biomes, HolderSet<PlacedFeature> features, Decoration step) implements BiomeModifier
|
||||
{
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
if (phase == Phase.ADD && this.biomes.contains(biome))
|
||||
{
|
||||
BiomeGenerationSettingsBuilder generationSettings = builder.getGenerationSettings();
|
||||
this.features.forEach(holder -> generationSettings.addFeature(this.step, holder));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends BiomeModifier> codec()
|
||||
{
|
||||
return ForgeMod.ADD_FEATURES_BIOME_MODIFIER_TYPE.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that removes features from biomes. Has the following json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:removefeatures", // required
|
||||
* "biomes": "#namespace:your_biome_tag", // accepts a biome id, [list of biome ids], or #namespace:biome_tag
|
||||
* "features": "namespace:your_feature", // accepts a placed feature id, [list of placed feature ids], or #namespace:feature_tag
|
||||
* "steps": "underground_ores" OR ["underground_ores", "vegetal_decoration"] // one or more decoration steps; optional field, defaults to all steps if not specified
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param biomes Biomes to remove features from.
|
||||
* @param features PlacedFeatures to remove from biomes.
|
||||
* @param steps Decoration steps to remove features from.
|
||||
*/
|
||||
public static record RemoveFeaturesBiomeModifier(HolderSet<Biome> biomes, HolderSet<PlacedFeature> features, Set<Decoration> steps) implements BiomeModifier
|
||||
{
|
||||
/**
|
||||
* Creates a modifier that removes the given features from all decoration steps in the given biomes.
|
||||
* @param biomes Biomes to remove features from.
|
||||
* @param features PlacedFeatures to remove from biomes.
|
||||
*/
|
||||
public static RemoveFeaturesBiomeModifier allSteps(HolderSet<Biome> biomes, HolderSet<PlacedFeature> features)
|
||||
{
|
||||
return new RemoveFeaturesBiomeModifier(biomes, features, EnumSet.allOf(Decoration.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
if (phase == Phase.REMOVE && this.biomes.contains(biome))
|
||||
{
|
||||
BiomeGenerationSettingsBuilder generationSettings = builder.getGenerationSettings();
|
||||
for (Decoration step : this.steps)
|
||||
{
|
||||
generationSettings.getFeatures(step).removeIf(this.features::contains);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends BiomeModifier> codec()
|
||||
{
|
||||
return ForgeMod.REMOVE_FEATURES_BIOME_MODIFIER_TYPE.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that adds a mob spawn to a biome. Has the following json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:add_spawns", // Required
|
||||
* "biomes": "#namespace:biome_tag", // Accepts a biome id, [list of biome ids], or #namespace:biome_tag
|
||||
* "spawners":
|
||||
* {
|
||||
* "type": "namespace:entity_type", // Type of mob to spawn
|
||||
* "weight": 100, // int, spawn weighting
|
||||
* "minCount": 1, // int, minimum pack size
|
||||
* "maxCount": 4, // int, maximum pack size
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* <p>Optionally accepts a list of spawner objects instead of a single spawner:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:add_spawns", // Required
|
||||
* "biomes": "#namespace:biome_tag", // Accepts a biome id, [list of biome ids], or #namespace:biome_tag
|
||||
* "spawners":
|
||||
* [
|
||||
* {
|
||||
* "type": "namespace:entity_type", // Type of mob to spawn
|
||||
* "weight": 100, // int, spawn weighting
|
||||
* "minCount": 1, // int, minimum pack size
|
||||
* "maxCount": 4, // int, maximum pack size
|
||||
* },
|
||||
* {
|
||||
* // additional spawner object
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param biomes Biomes to add mob spawns to.
|
||||
* @param spawners List of SpawnerDatas specifying EntityType, weight, and pack size.
|
||||
*/
|
||||
public record AddSpawnsBiomeModifier(HolderSet<Biome> biomes, List<SpawnerData> spawners) implements BiomeModifier
|
||||
{
|
||||
/**
|
||||
* Convenience method for using a single spawn data.
|
||||
* @param biomes Biomes to add mob spawns to.
|
||||
* @param spawner SpawnerData specifying EntityTYpe, weight, and pack size.
|
||||
* @return AddSpawnsBiomeModifier that adds a single spawn entry to the specified biomes.
|
||||
*/
|
||||
public static AddSpawnsBiomeModifier singleSpawn(HolderSet<Biome> biomes, SpawnerData spawner)
|
||||
{
|
||||
return new AddSpawnsBiomeModifier(biomes, List.of(spawner));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
if (phase == Phase.ADD && this.biomes.contains(biome))
|
||||
{
|
||||
MobSpawnSettingsBuilder spawns = builder.getMobSpawnSettings();
|
||||
for (SpawnerData spawner : this.spawners)
|
||||
{
|
||||
EntityType<?> type = spawner.type;
|
||||
spawns.addSpawn(type.getCategory(), spawner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends BiomeModifier> codec()
|
||||
{
|
||||
return ForgeMod.ADD_SPAWNS_BIOME_MODIFIER_TYPE.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that removes mob spawns from a biome. Has the following json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:add_spawns", // Required
|
||||
* "biomes": "#namespace:biome_tag", // Accepts a biome id, [list of biome ids], or #namespace:biome_tag
|
||||
* "entity_types": #namespace:entitytype_tag // Accepts an entity type, [list of entity types], or #namespace:entitytype_tag
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param biomes Biomes to add mob spawns to.
|
||||
* @param entityTypes EntityTypes to remove from spawn lists.
|
||||
*/
|
||||
public record RemoveSpawnsBiomeModifier(HolderSet<Biome> biomes, HolderSet<EntityType<?>> entityTypes) implements BiomeModifier
|
||||
{
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
if (phase == Phase.REMOVE && this.biomes.contains(biome))
|
||||
{
|
||||
MobSpawnSettingsBuilder spawnBuilder = builder.getMobSpawnSettings();
|
||||
for (MobCategory category : MobCategory.values())
|
||||
{
|
||||
List<SpawnerData> spawns = spawnBuilder.getSpawner(category);
|
||||
spawns.removeIf(spawnerData -> this.entityTypes.contains(ForgeRegistries.ENTITIES.getHolder(spawnerData.type).get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends BiomeModifier> codec()
|
||||
{
|
||||
return ForgeMod.REMOVE_SPAWNS_BIOME_MODIFIER_TYPE.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user