Merge pull request #217 from PolyhedralDev/dev/late-inject

Inject biomes later, fix getHeight issues (again)
This commit is contained in:
dfsek authored and GitHub committed 2021-06-19 13:26:29 -07:00
commit 85e4c0eca1
14 files changed
+228 -93

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash import com.dfsek.terra.getGitHash
val versionObj = Version("5", "4", "0", true) val versionObj = Version("5", "4", "1", true)
allprojects { allprojects {
version = versionObj version = versionObj
@@ -6,10 +6,8 @@ import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.config.pack.WorldConfig;
@@ -70,7 +68,7 @@ public class TerraWorld {
double noise = sampler.sample(fdX, y, fdZ); double noise = sampler.sample(fdX, y, fdZ);
if(noise > 0) { if(noise > 0) {
int level = 0; int level = 0;
for(int yi = world.getMaxHeight(); yi > y; yi--) { for(int yi = world.getMaxHeight() - 1; yi > y; yi--) {
if(sampler.sample(fdX, yi, fdZ) > 0) level++; if(sampler.sample(fdX, yi, fdZ) > 0) level++;
else level = 0; else level = 0;
} }
@@ -38,12 +38,15 @@ import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import com.dfsek.terra.fabric.event.GameInitializationEvent;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.PopulatorFeature; import com.dfsek.terra.fabric.generation.PopulatorFeature;
import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.handle.FabricItemHandle; import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle; import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.util.FabricUtil; import com.dfsek.terra.fabric.util.FabricUtil;
import com.dfsek.terra.fabric.util.ProtoBiome;
import com.dfsek.terra.profiler.Profiler; import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl; import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.exception.DuplicateEntryException; import com.dfsek.terra.registry.exception.DuplicateEntryException;
@@ -112,18 +115,25 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
private final DebugLogger debugLogger = new DebugLogger(logger); private final DebugLogger debugLogger = new DebugLogger(logger);
private final ItemHandle itemHandle = new FabricItemHandle(); private final ItemHandle itemHandle = new FabricItemHandle();
private final WorldHandle worldHandle = new FabricWorldHandle(); private final WorldHandle worldHandle = new FabricWorldHandle();
private final ConfigRegistry registry = new ConfigRegistry(); private final ConfigRegistry configRegistry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry); private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(configRegistry);
private final FabricAddon fabricAddon = new FabricAddon(this); private final FabricAddon fabricAddon = new FabricAddon();
private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this); private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this);
private final LockedRegistry<TerraAddon> addonLockedRegistry = new LockedRegistry<>(addonRegistry); private final LockedRegistry<TerraAddon> addonLockedRegistry = new LockedRegistry<>(addonRegistry);
private final PluginConfig config = new PluginConfig(); private final PluginConfig config = new PluginConfig();
private final Transformer<String, Biome> biomeFixer = new Transformer.Builder<String, Biome>() private final Transformer<String, ProtoBiome> biomeFixer = new Transformer.Builder<String, ProtoBiome>()
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), Validator.notNull()) .addTransform(this::parseBiome, Validator.notNull())
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), Validator.notNull()).build(); .addTransform(id -> parseBiome("minecraft:" + id.toLowerCase()), Validator.notNull()).build();
private ProtoBiome parseBiome(String id) {
Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) return null; // failure.
return new ProtoBiome(identifier);
}
private File dataFolder; private File dataFolder;
private final CommandManager manager = new TerraCommandManager(this); private final CommandManager manager = new TerraCommandManager(this);
@@ -176,6 +186,10 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
return LangUtil.getLanguage(); return LangUtil.getLanguage();
} }
public FabricAddon getFabricAddon() {
return fabricAddon;
}
@Override @Override
public CheckedRegistry<ConfigPack> getConfigRegistry() { public CheckedRegistry<ConfigPack> getConfigRegistry() {
return checkedRegistry; return checkedRegistry;
@@ -190,11 +204,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
public boolean reload() { public boolean reload() {
config.load(this); config.load(this);
LangUtil.load(config.getLanguage(), this); // Load language. LangUtil.load(config.getLanguage(), this); // Load language.
boolean succeed = registry.loadAll(this); boolean succeed = configRegistry.loadAll(this);
worldMap.forEach((seed, pair) -> { worldMap.forEach((seed, pair) -> {
pair.getRight().getConfig().getSamplerCache().clear(); pair.getRight().getConfig().getSamplerCache().clear();
String packID = pair.getRight().getConfig().getTemplate().getID(); String packID = pair.getRight().getConfig().getTemplate().getID();
pair.setRight(new TerraWorld(pair.getRight().getWorld(), registry.get(packID), this)); pair.setRight(new TerraWorld(pair.getRight().getWorld(), configRegistry.get(packID), this));
}); });
return succeed; return succeed;
} }
@@ -237,15 +251,6 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
}); });
} }
public void packInit() {
logger.info("Loading config packs...");
registry.loadAll(this);
registry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", FabricUtil.createBiomeID(pack, id)), FabricUtil.createBiome(fabricAddon, biome, pack)))); // Register all Terra biomes.
logger.info("Loaded packs.");
}
@Override @Override
public void onInitialize() { public void onInitialize() {
instance = this; instance = this;
@@ -293,19 +298,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
@Addon("Terra-Fabric") @Addon("Terra-Fabric")
@Author("Terra") @Author("Terra")
@Version("1.0.0") @Version("1.0.0")
public static final class FabricAddon extends TerraAddon implements EventListener { public final class FabricAddon extends TerraAddon implements EventListener {
private final TerraPlugin main;
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>(); private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
private FabricAddon(TerraPlugin main) {
this.main = main;
}
@Override @Override
public void initialize() { public void initialize() {
main.getEventManager().registerListener(this, this); eventManager.registerListener(this, this);
} }
@Priority(Priority.LOWEST) @Priority(Priority.LOWEST)
@@ -344,7 +342,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) { if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) {
try { try {
event.getPack().getTreeRegistry().add(entry.getKey().getValue().toString(), (Tree) entry.getValue()); event.getPack().getTreeRegistry().add(entry.getKey().getValue().toString(), (Tree) entry.getValue());
main.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree."); debugLogger.info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree.");
} catch(DuplicateEntryException ignored) { } catch(DuplicateEntryException ignored) {
} }
} }
@@ -367,6 +365,21 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
templates.get(event.getPack()).setRight(template); templates.get(event.getPack()).setRight(template);
} }
@Global
public void injectBiomes(BiomeRegistrationEvent event) {
logger.info("Registering biomes...");
Registry<Biome> biomeRegistry = event.getRegistryManager().get(Registry.BIOME_KEY);
configRegistry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> FabricUtil.registerOrOverwrite(biomeRegistry, Registry.BIOME_KEY, new Identifier("terra", FabricUtil.createBiomeID(pack, id)), FabricUtil.createBiome(biome, pack, event.getRegistryManager())))); // Register all Terra biomes.
logger.info("Biomes registered.");
}
@Global
public void initializePacks(GameInitializationEvent event) {
TerraFabricPlugin main = TerraFabricPlugin.getInstance();
main.logger().info("Loading config packs...");
configRegistry.loadAll(TerraFabricPlugin.this);
logger.info("Loaded packs.");
}
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) { private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try { try {
@@ -0,0 +1,19 @@
package com.dfsek.terra.fabric.event;
import com.dfsek.terra.api.event.events.Event;
import net.minecraft.util.registry.DynamicRegistryManager;
/**
* Fired when biomes should be registered.
*/
public class BiomeRegistrationEvent implements Event {
private final DynamicRegistryManager registryManager;
public BiomeRegistrationEvent(DynamicRegistryManager registryManager) {
this.registryManager = registryManager;
}
public DynamicRegistryManager getRegistryManager() {
return registryManager;
}
}
@@ -0,0 +1,9 @@
package com.dfsek.terra.fabric.event;
import com.dfsek.terra.api.event.events.Event;
/**
* Called when the game is initialized and packs should be registered.
*/
public class GameInitializationEvent implements Event {
}
@@ -4,25 +4,24 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.api.platform.world.generator.ChunkData;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.api.world.locate.AsyncStructureFinder;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.dfsek.terra.fabric.mixin.StructureAccessorAccessor; import com.dfsek.terra.fabric.mixin.StructureAccessorAccessor;
import com.dfsek.terra.fabric.util.FabricAdapter; import com.dfsek.terra.fabric.util.FabricAdapter;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.TerraStructure;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.entity.SpawnGroup;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.structure.StructureManager; import net.minecraft.structure.StructureManager;
import net.minecraft.util.collection.Pool;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.DynamicRegistryManager;
@@ -32,6 +31,7 @@ import net.minecraft.world.HeightLimitView;
import net.minecraft.world.Heightmap; import net.minecraft.world.Heightmap;
import net.minecraft.world.SpawnHelper; import net.minecraft.world.SpawnHelper;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.SpawnSettings;
import net.minecraft.world.biome.source.BiomeAccess; import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
@@ -50,24 +50,30 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper {
public static final Codec<ConfigPack> PACK_CODEC = RecordCodecBuilder.create(
config -> config.group(
Codec.STRING.fieldOf("pack")
.forGetter(pack -> pack.getTemplate().getID())
).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)));
public static final Codec<FabricChunkGeneratorWrapper> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
TerraBiomeSource.CODEC.fieldOf("biome_source")
.forGetter(generator -> generator.biomeSource),
Codec.LONG.fieldOf("seed").stable()
.forGetter(generator -> generator.seed),
PACK_CODEC.fieldOf("pack").stable()
.forGetter(generator -> generator.pack)
).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))
);
private final long seed; private final long seed;
private final DefaultChunkGenerator3D delegate; private final DefaultChunkGenerator3D delegate;
private final TerraBiomeSource biomeSource; private final TerraBiomeSource biomeSource;
public static final Codec<ConfigPack> PACK_CODEC = (RecordCodecBuilder.create(config -> config.group(
Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID())
).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get))));
public static final Codec<FabricChunkGeneratorWrapper> CODEC = RecordCodecBuilder.create(instance -> instance.group(
TerraBiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource),
Codec.LONG.fieldOf("seed").stable().forGetter(generator -> generator.seed),
PACK_CODEC.fieldOf("pack").stable().forGetter(generator -> generator.pack))
.apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)));
private final ConfigPack pack; private final ConfigPack pack;
private DimensionType dimensionType; private DimensionType dimensionType;
public ConfigPack getPack() {
return pack;
}
public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) {
super(biomeSource, new StructuresConfig(false)); super(biomeSource, new StructuresConfig(false));
this.pack = configPack; this.pack = configPack;
@@ -90,9 +96,13 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
return new FabricChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); return new FabricChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack);
} }
public ConfigPack getPack() {
return pack;
}
@Override @Override
public void buildSurface(ChunkRegion region, Chunk chunk) { public void buildSurface(ChunkRegion region, Chunk chunk) {
// No-op
} }
public void setDimensionType(DimensionType dimensionType) { public void setDimensionType(DimensionType dimensionType) {
@@ -124,13 +134,16 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override @Override
public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) { public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) {
if(pack.getTemplate().vanillaCaves()) super.carve(seed, access, chunk, carver); if(pack.getTemplate().vanillaCaves()) {
super.carve(seed, access, chunk, carver);
}
} }
@Override @Override
public void setStructureStarts(DynamicRegistryManager dynamicRegistryManager, StructureAccessor structureAccessor, Chunk chunk, StructureManager structureManager, long worldSeed) { public void setStructureStarts(DynamicRegistryManager dynamicRegistryManager, StructureAccessor structureAccessor, Chunk chunk, StructureManager structureManager, long worldSeed) {
if(pack.getTemplate().vanillaStructures()) if(pack.getTemplate().vanillaStructures()) {
super.setStructureStarts(dynamicRegistryManager, structureAccessor, chunk, structureManager, worldSeed); super.setStructureStarts(dynamicRegistryManager, structureAccessor, chunk, structureManager, worldSeed);
}
} }
@Override @Override
@@ -149,7 +162,9 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override @Override
public boolean isStrongholdStartingChunk(ChunkPos chunkPos) { public boolean isStrongholdStartingChunk(ChunkPos chunkPos) {
if(pack.getTemplate().vanillaStructures()) return super.isStrongholdStartingChunk(chunkPos); if(pack.getTemplate().vanillaStructures()) {
return super.isStrongholdStartingChunk(chunkPos);
}
return false; return false;
} }
@@ -161,34 +176,20 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override @Override
public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView heightmapType) { public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView heightmapType) {
TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType);
Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16));
int cx = FastMath.floorMod(x, 16);
int cz = FastMath.floorMod(z, 16);
int height = world.getWorld().getMaxHeight(); int height = world.getWorld().getMaxHeight();
while(height >= world.getWorld().getMinHeight() && !heightmap.getBlockPredicate().test(((FabricBlockData) world.getUngeneratedBlock(x, height - 1, z)).getHandle())) {
while(height >= 0 && sampler.sample(cx, height-1, cz) < 0) height--; height--;
}
return height; return height;
} }
@Override @Override
public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView view) { public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView view) {
TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType);
int height = getHeight(x, z, Heightmap.Type.WORLD_SURFACE, view); BlockState[] array = new BlockState[view.getHeight()];
BlockState[] array = new BlockState[256]; for(int y = view.getBottomY() + view.getHeight() - 1; y >= view.getBottomY(); y--) {
for(int y = view.getBottomY()+view.getHeight(); y >= view.getBottomY(); y--) { array[y] = ((FabricBlockData) world.getUngeneratedBlock(x, y, z)).getHandle();
if(y > height) {
if(y > ((UserDefinedBiome) world.getBiomeProvider().getBiome(x, z)).getConfig().getSeaLevel()) {
array[y] = Blocks.AIR.getDefaultState();
} else {
array[y] = Blocks.WATER.getDefaultState();
}
} else {
array[y] = Blocks.STONE.getDefaultState();
}
} }
return new VerticalBlockSample(view.getBottomY(), array); return new VerticalBlockSample(view.getBottomY(), array);
} }
@@ -204,6 +205,34 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
} }
} }
public Pool<SpawnSettings.SpawnEntry> getEntitySpawnList(Biome biome, StructureAccessor accessor, SpawnGroup group, BlockPos pos) {
if(accessor.getStructureAt(pos, true, StructureFeature.SWAMP_HUT).hasChildren()) {
if(group == SpawnGroup.MONSTER) {
return StructureFeature.SWAMP_HUT.getMonsterSpawns();
}
if(group == SpawnGroup.CREATURE) {
return StructureFeature.SWAMP_HUT.getCreatureSpawns();
}
}
if(group == SpawnGroup.MONSTER) {
if(accessor.getStructureAt(pos, false, StructureFeature.PILLAGER_OUTPOST).hasChildren()) {
return StructureFeature.PILLAGER_OUTPOST.getMonsterSpawns();
}
if(accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren()) {
return StructureFeature.MONUMENT.getMonsterSpawns();
}
if(accessor.getStructureAt(pos, true, StructureFeature.FORTRESS).hasChildren()) {
return StructureFeature.FORTRESS.getMonsterSpawns();
}
}
return group == SpawnGroup.UNDERGROUND_WATER_CREATURE && accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren() ? StructureFeature.MONUMENT.getUndergroundWaterCreatureSpawns() : super.getEntitySpawnList(biome, accessor, group, pos);
}
@Override @Override
public TerraChunkGenerator getHandle() { public TerraChunkGenerator getHandle() {
return delegate; return delegate;
@@ -1,12 +1,21 @@
package com.dfsek.terra.fabric.generation; package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import com.dfsek.terra.fabric.util.FabricUtil;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.world.GeneratorType; import net.minecraft.client.world.GeneratorType;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GeneratorOptions;
import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
@Environment(EnvType.CLIENT)
public class TerraGeneratorType extends GeneratorType { public class TerraGeneratorType extends GeneratorType {
private final ConfigPack pack; private final ConfigPack pack;
@@ -15,6 +24,13 @@ public class TerraGeneratorType extends GeneratorType {
this.pack = pack; this.pack = pack;
} }
@Override
public GeneratorOptions createDefaultOptions(DynamicRegistryManager.Impl registryManager, long seed, boolean generateStructures, boolean bonusChest) {
GeneratorOptions options = super.createDefaultOptions(registryManager, seed, generateStructures, bonusChest);
TerraFabricPlugin.getInstance().getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes
return options;
}
@Override @Override
protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) { protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) {
return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack);
@@ -1,6 +1,7 @@
package com.dfsek.terra.fabric.mixin.init; package com.dfsek.terra.fabric.mixin.lifecycle.client;
import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.GameInitializationEvent;
import com.dfsek.terra.fabric.generation.TerraGeneratorType; import com.dfsek.terra.fabric.generation.TerraGeneratorType;
import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@@ -18,7 +19,7 @@ public class MinecraftClientMixin {
target = "Lnet/minecraft/client/util/WindowProvider;createWindow(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/client/util/Window;", // sorta arbitrary position, after mod init, before window opens target = "Lnet/minecraft/client/util/WindowProvider;createWindow(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/client/util/Window;", // sorta arbitrary position, after mod init, before window opens
shift = At.Shift.BEFORE)) shift = At.Shift.BEFORE))
public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) {
TerraFabricPlugin.getInstance().packInit(); // Load during MinecraftClient construction, after other mods have registered blocks and stuff TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent());
TerraFabricPlugin.getInstance().getConfigRegistry().forEach(pack -> { TerraFabricPlugin.getInstance().getConfigRegistry().forEach(pack -> {
final GeneratorType generatorType = new TerraGeneratorType(pack); final GeneratorType generatorType = new TerraGeneratorType(pack);
//noinspection ConstantConditions //noinspection ConstantConditions
@@ -0,0 +1,4 @@
/**
* Mixins that inject behavior into the client/server lifecycle.
*/
package com.dfsek.terra.fabric.mixin.lifecycle;
@@ -1,10 +1,13 @@
package com.dfsek.terra.fabric.mixin; package com.dfsek.terra.fabric.mixin.lifecycle.server;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.SimpleRegistry; import net.minecraft.util.registry.SimpleRegistry;
@@ -24,11 +27,13 @@ import java.util.Random;
@Mixin(GeneratorOptions.class) @Mixin(GeneratorOptions.class)
public abstract class GeneratorOptionsMixin { public abstract class GeneratorOptionsMixin {
@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true) @Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true)
private static void fromProperties(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable<GeneratorOptions> cir) { private static void fromProperties(DynamicRegistryManager registryManager, Properties properties, CallbackInfoReturnable<GeneratorOptions> cir) {
if(properties.get("level-type") == null) { if(properties.get("level-type") == null) {
return; return;
} }
TerraFabricPlugin main = TerraFabricPlugin.getInstance();
String prop = properties.get("level-type").toString().trim(); String prop = properties.get("level-type").toString().trim();
if(prop.startsWith("Terra")) { if(prop.startsWith("Terra")) {
String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), "");
@@ -46,18 +51,20 @@ public abstract class GeneratorOptionsMixin {
String generate_structures = (String) properties.get("generate-structures"); String generate_structures = (String) properties.get("generate-structures");
boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures);
Registry<DimensionType> dimensionTypes = dynamicRegistryManager.get(Registry.DIMENSION_TYPE_KEY); Registry<DimensionType> dimensionTypes = registryManager.get(Registry.DIMENSION_TYPE_KEY);
Registry<Biome> biomes = dynamicRegistryManager.get(Registry.BIOME_KEY); Registry<Biome> biomeRegistry = registryManager.get(Registry.BIOME_KEY);
Registry<ChunkGeneratorSettings> chunkGeneratorSettings = dynamicRegistryManager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY); Registry<ChunkGeneratorSettings> chunkGeneratorSettings = registryManager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY);
SimpleRegistry<DimensionOptions> dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomes, chunkGeneratorSettings, l); SimpleRegistry<DimensionOptions> dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomeRegistry, chunkGeneratorSettings, l);
prop = prop.substring(prop.indexOf(":") + 1); prop = prop.substring(prop.indexOf(":") + 1);
ConfigPack pack = TerraFabricPlugin.getInstance().getConfigRegistry().get(prop); ConfigPack config = main.getConfigRegistry().get(prop);
if(pack == null) throw new IllegalArgumentException("No such pack " + prop); if(config == null) throw new IllegalArgumentException("No such pack " + prop);
cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.getRegistryWithReplacedOverworldGenerator(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack)))); main.getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes
cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.getRegistryWithReplacedOverworldGenerator(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, l, config), l, config))));
} }
} }
} }
@@ -1,6 +1,7 @@
package com.dfsek.terra.fabric.mixin.init; package com.dfsek.terra.fabric.mixin.lifecycle.server;
import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.GameInitializationEvent;
import net.minecraft.server.Main; import net.minecraft.server.Main;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -11,6 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class ServerMainMixin { public class ServerMainMixin {
@Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager;create()Lnet/minecraft/util/registry/DynamicRegistryManager$Impl;")) @Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager;create()Lnet/minecraft/util/registry/DynamicRegistryManager$Impl;"))
private static void injectConstructor(String[] args, CallbackInfo ci) { private static void injectConstructor(String[] args, CallbackInfo ci) {
TerraFabricPlugin.getInstance().packInit(); // Load during MinecraftServer construction, after other mods have registered blocks and stuff TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks and stuff
} }
} }
@@ -8,8 +8,12 @@ import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor; import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor;
import com.mojang.serialization.Lifecycle;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeEffects; import net.minecraft.world.biome.BiomeEffects;
import net.minecraft.world.biome.GenerationSettings; import net.minecraft.world.biome.GenerationSettings;
@@ -32,16 +36,18 @@ public final class FabricUtil {
/** /**
* Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate.
* *
* @param fabricAddon The Fabric addon instance.
* @param biome The Terra BiomeBuilder. * @param biome The Terra BiomeBuilder.
* @param pack The ConfigPack this biome belongs to. * @param pack The ConfigPack this biome belongs to.
* @return The Minecraft delegate biome. * @return The Minecraft delegate biome.
*/ */
public static Biome createBiome(TerraFabricPlugin.FabricAddon fabricAddon, BiomeBuilder biome, ConfigPack pack) { public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, DynamicRegistryManager registryManager) {
BiomeTemplate template = biome.getTemplate(); BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors(); Map<String, Integer> colors = template.getColors();
Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); TerraFabricPlugin.FabricAddon fabricAddon = TerraFabricPlugin.getInstance().getFabricAddon();
Registry<Biome> biomeRegistry = registryManager.get(Registry.BIOME_KEY);
Biome vanilla = ((ProtoBiome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0))).get(biomeRegistry);
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
@@ -63,8 +69,9 @@ public final class FabricUtil {
TerraFabricPlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID()); TerraFabricPlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID());
Registry<ConfiguredStructureFeature<?, ?>> configuredStructureFeatureRegistry = registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
for(Supplier<ConfiguredStructureFeature<?, ?>> structureFeature : vanilla.getGenerationSettings().getStructureFeatures()) { for(Supplier<ConfiguredStructureFeature<?, ?>> structureFeature : vanilla.getGenerationSettings().getStructureFeatures()) {
Identifier key = BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getId(structureFeature.get()); Identifier key = configuredStructureFeatureRegistry.getId(structureFeature.get());
if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) { if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.structureFeature(structureFeature.get()); generationSettings.structureFeature(structureFeature.get());
TerraFabricPlugin.getInstance().getDebugLogger().info("Injected structure " + key); TerraFabricPlugin.getInstance().getDebugLogger().info("Injected structure " + key);
@@ -72,9 +79,10 @@ public final class FabricUtil {
} }
if(compatibilityOptions.doBiomeInjection()) { if(compatibilityOptions.doBiomeInjection()) {
Registry<ConfiguredFeature<?, ?>> configuredFeatureRegistry = registryManager.get(Registry.CONFIGURED_FEATURE_KEY);
for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) { for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) {
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) { for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) {
Identifier key = BuiltinRegistries.CONFIGURED_FEATURE.getId(featureSupplier.get()); Identifier key = configuredFeatureRegistry.getId(featureSupplier.get());
if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) { if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.feature(step, featureSupplier); generationSettings.feature(step, featureSupplier);
TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step); TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step);
@@ -114,4 +122,12 @@ public final class FabricUtil {
.generationSettings(generationSettings.build()) .generationSettings(generationSettings.build())
.build(); .build();
} }
public static <T> void registerOrOverwrite(Registry<T> registry, RegistryKey<Registry<T>> key, Identifier identifier, T item) {
if(registry.containsId(identifier)) {
((MutableRegistry<T>) registry).set(registry.getRawId(registry.get(identifier)), RegistryKey.of(key, identifier), item, Lifecycle.stable());
} else {
Registry.register(registry, identifier, item);
}
}
} }
@@ -0,0 +1,22 @@
package com.dfsek.terra.fabric.util;
import com.dfsek.terra.api.platform.world.Biome;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class ProtoBiome implements Biome {
private final Identifier identifier;
public ProtoBiome(Identifier identifier) {
this.identifier = identifier;
}
public net.minecraft.world.biome.Biome get(Registry<net.minecraft.world.biome.Biome> registry) {
return registry.get(identifier);
}
@Override
public Object getHandle() {
return identifier;
}
}
@@ -6,7 +6,6 @@
"mixins": [ "mixins": [
"StructureAccessorAccessor", "StructureAccessorAccessor",
"CommandManagerMixin", "CommandManagerMixin",
"GeneratorOptionsMixin",
"ServerWorldMixin", "ServerWorldMixin",
"access.BiomeEffectsAccessor", "access.BiomeEffectsAccessor",
"access.MobSpawnerLogicAccessor", "access.MobSpawnerLogicAccessor",
@@ -37,10 +36,11 @@
], ],
"client": [ "client": [
"access.GeneratorTypeAccessor", "access.GeneratorTypeAccessor",
"init.MinecraftClientMixin" "lifecycle.client.MinecraftClientMixin"
], ],
"server": [ "server": [
"init.ServerMainMixin" "lifecycle.server.GeneratorOptionsMixin",
"lifecycle.server.ServerMainMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1