Compare commits

...

13 Commits

Author SHA1 Message Date
dfsek ed2fa85d81 cache value of ModDependentConfigSection 2021-06-01 01:33:54 -07:00
dfsek 788a3c2d48 switch to namespace based injection 2021-06-01 01:27:30 -07:00
dfsek 1bd5cf31fa move compat options to compat.yml 2021-06-01 01:16:52 -07:00
dfsek bb2601252a add ConfigPackLoadEvent#getLoader 2021-06-01 01:09:51 -07:00
dfsek 0600176e31 override entity spawning stuff 2021-05-28 13:34:12 -07:00
dfsek 51c51111a2 improve fabric/forge getHeight impl 2021-05-27 19:46:05 -07:00
dfsek d3e4270f44 cleanup ModDependentConfigSectionLoader 2021-05-27 19:27:15 -07:00
dfsek 4f3f555aa0 fix stronghold gen with vanilla.structures 2021-05-27 19:14:25 -07:00
dfsek cf0d5cd99c register mod dependent loader in GenericLoaders 2021-05-23 22:40:38 -07:00
dfsek e3bbedb56b make compat options mod dependent 2021-05-23 22:38:41 -07:00
dfsek 3f37907256 implement ModDependentConfigSection#withDefault 2021-05-23 15:57:36 -07:00
dfsek 486dcfc63d implement ModDependentConfigSection 2021-05-22 23:23:59 -07:00
dfsek 34947c2168 implement TerraPlugin#getMods 2021-05-22 23:09:30 -07:00
22 changed files with 353 additions and 82 deletions
@@ -4,6 +4,7 @@ import com.dfsek.terra.api.addons.TerraAddon;
import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.modloader.Mod;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
@@ -19,6 +20,8 @@ import com.dfsek.terra.world.TerraWorld;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Set;
import java.util.jar.JarFile;
/**
@@ -75,4 +78,8 @@ public interface TerraPlugin extends LoaderRegistrar {
default JarFile getModJar() throws URISyntaxException, IOException {
return JarUtil.getJarFile();
}
default Set<Mod> getMods() {
return Collections.emptySet();
}
}
@@ -3,6 +3,7 @@ package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.pack.ConfigPack;
/**
@@ -11,10 +12,12 @@ import com.dfsek.terra.config.pack.ConfigPack;
public abstract class ConfigPackLoadEvent implements PackEvent {
private final ConfigPack pack;
private final ExceptionalConsumer<ConfigTemplate> configLoader;
private final Loader loader;
public ConfigPackLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader) {
public ConfigPackLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader, Loader loader) {
this.pack = pack;
this.configLoader = configLoader;
this.loader = loader;
}
@Override
@@ -34,4 +37,8 @@ public abstract class ConfigPackLoadEvent implements PackEvent {
public interface ExceptionalConsumer<T extends ConfigTemplate> {
void accept(T value) throws ConfigException;
}
public Loader getLoader() {
return loader;
}
}
@@ -1,13 +1,14 @@
package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.pack.ConfigPack;
/**
* Called when a config pack has finished loading.
*/
public class ConfigPackPostLoadEvent extends ConfigPackLoadEvent {
public ConfigPackPostLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> loader) {
super(pack, loader);
public ConfigPackPostLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configTemplateLoader, Loader loader) {
super(pack, configTemplateLoader, loader);
}
}
@@ -1,14 +1,14 @@
package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.pack.ConfigPack;
/**
* Called before a config pack's registries are filled. At this point, the pack manifest has been loaded, and all registries are empty.
*/
public class ConfigPackPreLoadEvent extends ConfigPackLoadEvent {
public ConfigPackPreLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader) {
super(pack, configLoader);
public ConfigPackPreLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader, Loader loader) {
super(pack, configLoader, loader);
}
}
@@ -0,0 +1,9 @@
package com.dfsek.terra.api.platform.modloader;
public interface Mod {
String getID();
String getVersion();
String getName();
}
@@ -46,6 +46,8 @@ import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTempl
import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate;
import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate;
import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate;
import com.dfsek.terra.config.loaders.mod.ModDependentConfigSection;
import com.dfsek.terra.config.loaders.mod.ModDependentConfigSectionLoader;
import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
@@ -108,7 +110,8 @@ public class GenericLoaders implements LoaderRegistrar {
if(main != null) {
registry.registerLoader(TerraAddon.class, main.getAddons())
.registerLoader(BlockType.class, (t, object, cf) -> main.getWorldHandle().createBlockData((String) object).getBlockType());
.registerLoader(BlockType.class, (t, object, cf) -> main.getWorldHandle().createBlockData((String) object).getBlockType())
.registerLoader(ModDependentConfigSection.class, new ModDependentConfigSectionLoader(main));
}
}
}
@@ -1,5 +1,6 @@
package com.dfsek.terra.config.fileloaders;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
@@ -20,7 +21,7 @@ public class ZIPLoader extends Loader {
ZipEntry entry = entries.nextElement();
if(!entry.isDirectory() && entry.getName().equals(singleFile)) return file.getInputStream(entry);
}
throw new IllegalArgumentException("No such file: " + singleFile);
throw new FileNotFoundException("No such file: " + singleFile);
}
@Override
@@ -0,0 +1,46 @@
package com.dfsek.terra.config.loaders.mod;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.modloader.Mod;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ModDependentConfigSection<T> {
private static final Object NULL = new Object(); // Null object
private final TerraPlugin main;
private final Map<String, T> results = new HashMap<>();
private final T defaultValue;
@SuppressWarnings("unchecked")
private T value = (T) NULL;
protected ModDependentConfigSection(TerraPlugin main, T defaultValue) {
this.main = main;
this.defaultValue = defaultValue;
}
public void add(String id, T value) {
results.put(id, value);
}
public static <T1> ModDependentConfigSection<T1> withDefault(T1 defaultValue) {
return new ModDependentConfigSection<>(null, defaultValue);
}
public T get() {
if(value == NULL) value = compute(); // Cache the value.
return value;
}
private T compute() {
if(main != null) {
Set<String> mods = main.getMods().stream().map(Mod::getID).collect(Collectors.toSet());
for(Map.Entry<String, T> entry : results.entrySet()) {
if(mods.contains(entry.getKey())) return entry.getValue();
}
}
return defaultValue;
}
}
@@ -0,0 +1,43 @@
package com.dfsek.terra.config.loaders.mod;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.TerraPlugin;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class ModDependentConfigSectionLoader implements TypeLoader<ModDependentConfigSection<?>> {
private final TerraPlugin main;
public ModDependentConfigSectionLoader(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public ModDependentConfigSection<?> load(Type type, Object c, ConfigLoader loader) throws LoadException {
if(type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Type generic = pType.getActualTypeArguments()[0];
if(c instanceof Map && ((Map<?, ?>) c).containsKey("default")) {
Map<String, ?> map = (Map<String, ?>) c;
ModDependentConfigSection<Object> configSection = new ModDependentConfigSection<>(main, loader.loadType(generic, map.get("default")));
if(map.containsKey("mods")) {
for(Map.Entry<String, ?> modEntry : ((Map<String, ?>) map.get("mods")).entrySet()) {
configSection.add(modEntry.getKey(), loader.loadType(generic, modEntry.getValue()));
}
}
return configSection;
} else {
return ModDependentConfigSection.withDefault(loader.loadType(generic, c)); // Load the original type otherwise.
}
} else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type);
}
}
@@ -138,7 +138,7 @@ public class ConfigPack implements LoaderRegistrar {
main.logger().info("Loading config pack \"" + template.getID() + "\"");
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration), loader));
load(l, main);
@@ -185,7 +185,7 @@ public class ConfigPack implements LoaderRegistrar {
selfLoader.load(template, configuration);
main.logger().info("Loading config pack \"" + template.getID() + "\"");
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration), loader));
load(l, main);
@@ -253,7 +253,7 @@ public class ConfigPack implements LoaderRegistrar {
.open("flora", ".yml").then(configs -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.loadConfigs(configs, FloraTemplate::new), main)).close()
.open("biomes", ".yml").then(configs -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.loadConfigs(configs, () -> new BiomeTemplate(this, main)), main)).close();
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, configuration)));
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, configuration), loader));
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
}
@@ -6,12 +6,14 @@ import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.addons.TerraAddon;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.loaders.mod.ModDependentConfigSection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class ConfigPackTemplate implements ConfigTemplate {
@@ -39,7 +41,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Value("structures.locatable")
@Default
private Map<String, String> locatable = new HashMap<>();
private Map<String, ModDependentConfigSection<String>> locatable = new HashMap<>();
@Value("blend.terrain.elevation")
@Default
@@ -47,19 +49,19 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Value("vanilla.mobs")
@Default
private boolean vanillaMobs = true;
private ModDependentConfigSection<Boolean> vanillaMobs = ModDependentConfigSection.withDefault(true);
@Value("vanilla.caves")
@Default
private boolean vanillaCaves = false;
private ModDependentConfigSection<Boolean> vanillaCaves = ModDependentConfigSection.withDefault(false);
@Value("vanilla.decorations")
@Default
private boolean vanillaDecorations = false;
private ModDependentConfigSection<Boolean> vanillaDecorations = ModDependentConfigSection.withDefault(false);
@Value("vanilla.structures")
@Default
private boolean vanillaStructures = false;
private ModDependentConfigSection<Boolean> vanillaStructures = ModDependentConfigSection.withDefault(false);
@Value("author")
@Default
@@ -67,7 +69,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Value("disable.sapling")
@Default
private boolean disableSaplings = false;
private ModDependentConfigSection<Boolean> disableSaplings = ModDependentConfigSection.withDefault(false);
@Value("version")
@Default
@@ -75,42 +77,42 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Value("disable.carvers")
@Default
private boolean disableCarvers = false;
private ModDependentConfigSection<Boolean> disableCarvers = ModDependentConfigSection.withDefault(false);
@Value("disable.structures")
@Default
private boolean disableStructures = false;
private ModDependentConfigSection<Boolean> disableStructures = ModDependentConfigSection.withDefault(false);
@Value("disable.ores")
@Default
private boolean disableOres = false;
private ModDependentConfigSection<Boolean> disableOres = ModDependentConfigSection.withDefault(false);
@Value("disable.trees")
@Default
private boolean disableTrees = false;
private ModDependentConfigSection<Boolean> disableTrees = ModDependentConfigSection.withDefault(false);
@Value("disable.flora")
@Default
private boolean disableFlora = false;
private ModDependentConfigSection<Boolean> disableFlora = ModDependentConfigSection.withDefault(false);
public boolean disableCarvers() {
return disableCarvers;
return disableCarvers.get();
}
public boolean disableFlora() {
return disableFlora;
return disableFlora.get();
}
public boolean disableOres() {
return disableOres;
return disableOres.get();
}
public boolean disableStructures() {
return disableStructures;
return disableStructures.get();
}
public boolean disableTrees() {
return disableTrees;
return disableTrees.get();
}
public LinkedHashMap<String, FunctionTemplate> getFunctions() {
@@ -122,7 +124,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
}
public boolean isDisableSaplings() {
return disableSaplings;
return disableSaplings.get();
}
public String getID() {
@@ -134,19 +136,19 @@ public class ConfigPackTemplate implements ConfigTemplate {
}
public boolean vanillaMobs() {
return vanillaMobs;
return vanillaMobs.get();
}
public boolean vanillaCaves() {
return vanillaCaves;
return vanillaCaves.get();
}
public boolean vanillaDecorations() {
return vanillaDecorations;
return vanillaDecorations.get();
}
public boolean vanillaStructures() {
return vanillaStructures;
return vanillaStructures.get();
}
public Map<String, NoiseSeeded> getNoiseBuilderMap() {
@@ -162,7 +164,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
}
public Map<String, String> getLocatable() {
return locatable;
return locatable.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get()));
}
public boolean doBetaCarvers() {
@@ -70,7 +70,7 @@ public class TerraWorld {
double noise = sampler.sample(fdX, y, fdZ);
if(noise > 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++;
else level = 0;
}
@@ -0,0 +1,27 @@
package com.dfsek.terra.bukkit;
import com.dfsek.terra.api.platform.modloader.Mod;
import org.bukkit.plugin.Plugin;
public class BukkitPlugin implements Mod {
private final Plugin plugin;
public BukkitPlugin(Plugin plugin) {
this.plugin = plugin;
}
@Override
public String getID() {
return plugin.getName();
}
@Override
public String getVersion() {
return plugin.getDescription().getVersion();
}
@Override
public String getName() {
return plugin.getName();
}
}
@@ -14,6 +14,7 @@ import com.dfsek.terra.api.event.TerraEventManager;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.modloader.Mod;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
@@ -57,9 +58,12 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
@@ -306,6 +310,11 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
genericLoaders.register(registry);
}
@Override
public Set<Mod> getMods() {
return Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(BukkitPlugin::new).collect(Collectors.toSet());
}
@Override
public LockedRegistry<TerraAddon> getAddons() {
return addonLockedRegistry;
@@ -0,0 +1,28 @@
package com.dfsek.terra.fabric;
import com.dfsek.terra.api.platform.modloader.Mod;
import net.fabricmc.loader.api.ModContainer;
public class FabricMod implements Mod {
private final ModContainer mod;
public FabricMod(ModContainer mod) {
this.mod = mod;
}
@Override
public String getID() {
return mod.getMetadata().getId();
}
@Override
public String getVersion() {
return mod.getMetadata().getVersion().getFriendlyString();
}
@Override
public String getName() {
return mod.getMetadata().getName();
}
}
@@ -1,7 +1,9 @@
package com.dfsek.terra.fabric;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addons.TerraAddon;
@@ -21,6 +23,7 @@ import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.modloader.Mod;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
@@ -70,10 +73,13 @@ import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
@@ -285,6 +291,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
return eventManager;
}
@Override
public Set<Mod> getMods() {
return FabricLoader.getInstance().getAllMods().stream().map(FabricMod::new).collect(Collectors.toSet());
}
@Override
public Profiler getProfiler() {
return profiler;
@@ -299,8 +310,13 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
private final Map<ConfigPack, Configuration> compatConfigs = new HashMap<>();
private final ConfigLoader compatLoader = new ConfigLoader();
private FabricAddon(TerraPlugin main) {
this.main = main;
main.register(compatLoader);
}
@Override
@@ -332,9 +348,24 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
injectTree(treeRegistry, "CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI);
injectTree(treeRegistry, "WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI);
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
Configuration compat;
try {
event.loadTemplate(template);
compat = new Configuration(event.getLoader().get("compat.yml"));
main.logger().info("Loading compatibility options from compat.yml.");
} catch(FileNotFoundException e) {
compat = new Configuration(new HashMap<>()); // blank config
main.logger().info("No compat.yml found, not loading compatibility options.");
} catch(IOException e) {
throw new RuntimeException("Failed to load compatibility config", e); // Something went wrong.
}
compatConfigs.put(event.getPack(), compat);
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
try {
compatLoader.load(template, compat);
} catch(ConfigException e) {
e.printStackTrace();
}
@@ -351,6 +382,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
});
}
templates.put(event.getPack(), Pair.of(template, null));
}
@Priority(Priority.HIGHEST)
@@ -359,7 +391,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions();
try {
event.loadTemplate(template);
compatLoader.load(template, compatConfigs.get(event.getPack()));
} catch(ConfigException e) {
e.printStackTrace();
}
@@ -14,39 +14,32 @@ public class PreLoadCompatibilityOptions implements ConfigTemplate {
@Default
private boolean doRegistryInjection = false;
@Value("features.inject-biome.enable")
@Value("features.inject-namespaces")
@Default
private boolean doBiomeInjection = false;
private Set<String> featureNamespaces = new HashSet<>();
@Value("structures.inject-namespaces")
@Default
private Set<String> structureNamespaces = new HashSet<>();
@Value("features.inject-registry.excluded-features")
@Default
private Set<Identifier> excludedRegistryFeatures = new HashSet<>();
@Value("features.inject-biome.excluded-features")
@Default
private Set<Identifier> excludedBiomeFeatures = new HashSet<>();
@Value("structures.inject-biome.excluded-features")
@Default
private Set<Identifier> excludedBiomeStructures = new HashSet<>();
public Set<String> getFeatureNamespaces() {
return featureNamespaces;
}
public boolean doBiomeInjection() {
return doBiomeInjection;
public Set<String> getStructureNamespaces() {
return structureNamespaces;
}
public boolean doRegistryInjection() {
return doRegistryInjection;
}
public Set<Identifier> getExcludedBiomeFeatures() {
return excludedBiomeFeatures;
}
public Set<Identifier> getExcludedRegistryFeatures() {
return excludedRegistryFeatures;
}
public Set<Identifier> getExcludedBiomeStructures() {
return excludedBiomeStructures;
}
}
@@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.locate.AsyncStructureFinder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.dfsek.terra.fabric.util.FabricAdapter;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
@@ -19,6 +20,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.structure.StructureManager;
import net.minecraft.util.math.BlockPos;
@@ -31,6 +33,7 @@ import net.minecraft.world.Heightmap;
import net.minecraft.world.SpawnHelper;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.SpawnSettings;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.dimension.DimensionType;
@@ -43,6 +46,7 @@ import net.minecraft.world.gen.chunk.VerticalBlockSample;
import net.minecraft.world.gen.feature.StructureFeature;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -67,7 +71,7 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
}
public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) {
super(biomeSource, new StructuresConfig(false));
super(biomeSource, new StructuresConfig(configPack.getTemplate().vanillaStructures()));
this.pack = configPack;
this.delegate = new DefaultChunkGenerator3D(pack, TerraFabricPlugin.getInstance());
@@ -145,14 +149,10 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override
public int getHeight(int x, int z, Heightmap.Type heightmapType) {
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();
while(height >= 0 && sampler.sample(cx, height-1, cz) < 0) height--;
while(height >= 0 && !heightmapType.getBlockPredicate().test(((FabricBlockData) world.getUngeneratedBlock(x, height - 1, z)).getHandle())) {
height--;
}
return height;
}
@@ -176,6 +176,27 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
return new VerticalBlockSample(array);
}
@Override
public List<SpawnSettings.SpawnEntry> getEntitySpawnList(Biome biome, StructureAccessor accessor, SpawnGroup group, BlockPos pos) {
if(pack.getTemplate().vanillaStructures()) {
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();
} else if(accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren()) {
return StructureFeature.MONUMENT.getMonsterSpawns();
} else if(accessor.getStructureAt(pos, true, StructureFeature.FORTRESS).hasChildren()) {
return StructureFeature.FORTRESS.getMonsterSpawns();
}
}
}
return super.getEntitySpawnList(biome, accessor, group, pos);
}
@Override
public void populateEntities(ChunkRegion region) {
if(pack.getTemplate().vanillaMobs()) {
@@ -17,11 +17,13 @@ import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
public final class FabricUtil {
@@ -64,25 +66,24 @@ public final class FabricUtil {
TerraFabricPlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID());
for(Supplier<ConfiguredStructureFeature<?, ?>> structureFeature : vanilla.getGenerationSettings().getStructureFeatures()) {
Identifier key = BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getId(structureFeature.get());
if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
Identifier key = Objects.requireNonNull(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getId(structureFeature.get()));
if(compatibilityOptions.getStructureNamespaces().contains(key.getNamespace()) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.structureFeature(structureFeature.get());
TerraFabricPlugin.getInstance().getDebugLogger().info("Injected structure " + key);
}
}
if(compatibilityOptions.doBiomeInjection()) {
for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) {
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) {
Identifier key = BuiltinRegistries.CONFIGURED_FEATURE.getId(featureSupplier.get());
if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.feature(step, featureSupplier);
TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step);
}
for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) {
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) {
Identifier key = Objects.requireNonNull(BuiltinRegistries.CONFIGURED_FEATURE.getId(featureSupplier.get()));
if(compatibilityOptions.getFeatureNamespaces().contains(key.getNamespace()) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) {
generationSettings.feature(step, featureSupplier);
TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step);
}
}
}
BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects();
BiomeEffects.Builder effects = new BiomeEffects.Builder()
.waterColor(colors.getOrDefault("water", accessor.getWaterColor()))
@@ -0,0 +1,27 @@
package com.dfsek.terra.forge;
import com.dfsek.terra.api.platform.modloader.Mod;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
public class ForgeMod implements Mod {
private final ModInfo mod;
public ForgeMod(ModInfo mod) {
this.mod = mod;
}
@Override
public String getID() {
return mod.getModId();
}
@Override
public String getVersion() {
return mod.getVersion().getQualifier();
}
@Override
public String getName() {
return mod.getDisplayName();
}
}
@@ -79,7 +79,9 @@ import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipFile;
@Mod("terra")
@@ -304,6 +306,11 @@ public class TerraForgePlugin implements TerraPlugin {
return eventManager;
}
@Override
public Set<com.dfsek.terra.api.platform.modloader.Mod> getMods() {
return net.minecraftforge.fml.ModList.get().getMods().stream().map(ForgeMod::new).collect(Collectors.toSet());
}
@Override
public Profiler getProfiler() {
return profiler;
@@ -10,6 +10,7 @@ import com.dfsek.terra.api.world.locate.AsyncStructureFinder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.forge.ForgeAdapter;
import com.dfsek.terra.forge.TerraForgePlugin;
import com.dfsek.terra.forge.block.ForgeBlockData;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
@@ -19,6 +20,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityClassification;
import net.minecraft.util.SharedSeedRandom;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
@@ -30,6 +32,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeManager;
import net.minecraft.world.biome.MobSpawnInfo;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationStage;
@@ -44,6 +47,7 @@ import net.minecraft.world.spawner.WorldEntitySpawner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -69,7 +73,7 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera
private DimensionType dimensionType;
public ForgeChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) {
super(biomeSource, new DimensionStructuresSettings(false));
super(biomeSource, new DimensionStructuresSettings(configPack.getTemplate().vanillaStructures()));
this.pack = configPack;
this.delegate = new DefaultChunkGenerator3D(pack, TerraForgePlugin.getInstance());
@@ -139,16 +143,12 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera
}
@Override
public int getBaseHeight(int x, int z, Heightmap.@NotNull Type p_222529_3_) {
public int getBaseHeight(int x, int z, Heightmap.@NotNull Type type) {
TerraWorld world = TerraForgePlugin.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();
while(height >= 0 && sampler.sample(cx, height - 1, cz) < 0) height--;
while(height >= 0 && !type.isOpaque().test(((ForgeBlockData) world.getUngeneratedBlock(x, height - 1, z)).getHandle())) {
height--;
}
return height;
}
@@ -184,6 +184,13 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera
}
}
@Override
public List<MobSpawnInfo.Spawners> getMobsAt(Biome p_230353_1_, StructureManager p_230353_2_, EntityClassification p_230353_3_, BlockPos p_230353_4_) {
List<MobSpawnInfo.Spawners> spawns = net.minecraftforge.common.world.StructureSpawnManager.getStructureSpawns(p_230353_2_, p_230353_3_, p_230353_4_);
if(spawns != null) return spawns;
return super.getMobsAt(p_230353_1_, p_230353_2_, p_230353_3_, p_230353_4_);
}
@Override
public TerraChunkGenerator getHandle() {
return delegate;