Merge pull request #252 from PolyhedralDev/dev/addon-splits

Make TerraPlugin implementations less boilerplate-y
This commit is contained in:
dfsek
2021-07-26 21:34:06 -07:00
committed by GitHub
28 changed files with 514 additions and 397 deletions

View File

@@ -23,8 +23,8 @@ allprojects {
failFast = true
maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1
reports.html.isEnabled = false
reports.junitXml.isEnabled = false
reports.html.required.set(false)
reports.junitXml.required.set(false)
}
}

View File

@@ -2,7 +2,7 @@ package com.dfsek.terra
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
@@ -15,7 +15,7 @@ fun Project.configureCompilation() {
apply(plugin = "java-library")
apply(plugin = "idea")
configure<JavaPluginConvention> {
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}

View File

@@ -3,11 +3,11 @@ package com.dfsek.terra
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.plugins.BasePluginExtension
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getPlugin
import org.gradle.kotlin.dsl.named
import org.yaml.snakeyaml.DumperOptions
import org.yaml.snakeyaml.Yaml
@@ -126,7 +126,10 @@ fun Project.configureDistribution() {
relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
}
convention.getPlugin<BasePluginConvention>().archivesBaseName = project.name
configure<BasePluginExtension> {
archivesName.set(project.name)
}
tasks.named<DefaultTask>("build") {
dependsOn(tasks["shadowJar"])

View File

@@ -36,8 +36,6 @@ public interface TerraPlugin extends LoaderRegistrar {
ItemHandle getItemHandle();
void saveDefaultConfig();
String platformName();
Logger getDebugLogger();

View File

@@ -9,7 +9,7 @@ import java.util.Collection;
public interface EnumProperty<T extends Enum<T>> extends Property<T> {
static <T extends Enum<T>> EnumProperty<T> of(String name, Class<T> clazz) {
return new EnumProperty<T>() {
private final Lazy<Collection<T>> constants = Lazy.of(() -> Arrays.asList(clazz.getEnumConstants()));
private final Lazy<Collection<T>> constants = Lazy.lazy(() -> Arrays.asList(clazz.getEnumConstants()));
@Override
public Class<T> getType() {

View File

@@ -0,0 +1,9 @@
package com.dfsek.terra.api.event.events.platform;
import com.dfsek.terra.api.event.events.Event;
/**
* Called when the platform is initialized.
*/
public class PlatformInitializationEvent implements Event {
}

View File

@@ -11,7 +11,7 @@ public final class Lazy<T> {
this.valueSupplier = valueSupplier;
}
public static <T> Lazy<T> of(Supplier<T> valueSupplier) {
public static <T> Lazy<T> lazy(Supplier<T> valueSupplier) {
return new Lazy<>(valueSupplier);
}

View File

@@ -0,0 +1,171 @@
package com.dfsek.terra;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.Logger;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.exception.MalformedCommandException;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.PluginConfig;
import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.lang.Language;
import com.dfsek.terra.api.profiler.Profiler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.api.util.mutable.MutableBoolean;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.commands.TerraCommandManager;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfigImpl;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.event.EventManagerImpl;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.CheckedRegistryImpl;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.util.logging.DebugLogger;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
/**
* Skeleton implementation of {@link TerraPlugin}
*
* Implementations must invoke {@link #load()} in their constructors.
*/
public abstract class AbstractTerraPlugin implements TerraPlugin {
private final Lazy<DebugLogger> debugLogger = Lazy.lazy(() -> new DebugLogger(logger()));
private final EventManager eventManager = new EventManagerImpl(this);
private final ConfigRegistry configRegistry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedConfigRegistry = new CheckedRegistryImpl<>(configRegistry);
private final Profiler profiler = new ProfilerImpl();
private final GenericLoaders loaders = new GenericLoaders(this);
private final PluginConfigImpl config = new PluginConfigImpl();
private final CommandManager manager = new TerraCommandManager(this);
private final AddonRegistry addonRegistry;
private final Logger logger;
private static final MutableBoolean LOADED = new MutableBoolean(false);
public AbstractTerraPlugin() {
this.logger = createLogger();
addonRegistry = getPlatformAddon().map(terraAddon -> new AddonRegistry(terraAddon, this)).orElseGet(() -> new AddonRegistry(this));
}
protected void load() {
if(LOADED.get()) {
throw new IllegalStateException("Someone tried to initialize Terra, but Terra has already initialized. This is most likely due to a broken platform implementation, or a misbehaving mod.");
}
LOADED.set(true);
logger().info("Initializing Terra...");
try(InputStream stream = getClass().getResourceAsStream("/config.yml")) {
File configFile = new File(getDataFolder(), "config.yml");
if(!configFile.exists()) {
FileUtils.copyInputStreamToFile(stream, configFile);
}
} catch(IOException e) {
e.printStackTrace();
}
config.load(this); // load config.yml
LangUtil.load(config.getLanguage(), this); // load language
debugLogger.value().setDebug(config.isDebugLogging()); // enable debug logger if applicable
if(config.isDebugProfiler()) { // if debug.profiler is enabled, start profiling
profiler.start();
}
addonRegistry.register(new InternalAddon(this));
if(!addonRegistry.loadAll(getClass().getClassLoader())) { // load all addons
throw new IllegalStateException("Failed to load addons. Please correct addon installations to continue.");
}
logger().info("Loaded addons.");
try {
CommandUtil.registerAll(manager);
} catch(MalformedCommandException e) {
e.printStackTrace(); // TODO do something here even though this should literally never happen
}
logger().info("Finished initialization.");
}
protected Optional<TerraAddon> getPlatformAddon() {
return Optional.empty();
}
protected abstract Logger createLogger();
@Override
public PluginConfig getTerraConfig() {
return config;
}
@Override
public CheckedRegistry<ConfigPack> getConfigRegistry() {
return checkedConfigRegistry;
}
@Override
public Registry<TerraAddon> getAddons() {
return addonRegistry;
}
public ConfigRegistry getRawConfigRegistry() {
return configRegistry;
}
public CommandManager getManager() {
return manager;
}
@Override
public Logger getDebugLogger() {
return debugLogger.value();
}
@Override
public EventManager getEventManager() {
return eventManager;
}
@Override
public Profiler getProfiler() {
return profiler;
}
@Override
public void register(TypeRegistry registry) {
loaders.register(registry);
}
@Override
public Language getLanguage() {
return LangUtil.getLanguage();
}
@Override
public Logger logger() {
return logger;
}
}

View File

@@ -0,0 +1,33 @@
package com.dfsek.terra;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
@Addon("terra")
@Author("Terra")
@Version("1.0.0")
public class InternalAddon extends TerraAddon {
private final AbstractTerraPlugin main;
public InternalAddon(AbstractTerraPlugin main) {
this.main = main;
}
@Override
public void initialize() {
main.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, PlatformInitializationEvent.class)
.then(event -> {
main.logger().info("Loading config packs...");
main.getRawConfigRegistry().loadAll(main);
main.logger().info("Loaded packs.");
})
.global();
}
}

View File

@@ -8,7 +8,6 @@ import com.dfsek.terra.api.registry.meta.RegistryFactory;
import com.dfsek.terra.api.util.generic.Lazy;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Type;
import java.util.function.Function;
public class RegistryFactoryImpl implements RegistryFactory {
@@ -20,7 +19,7 @@ public class RegistryFactoryImpl implements RegistryFactory {
@Override
public <T> OpenRegistry<T> create(Function<OpenRegistry<T>, TypeLoader<T>> loader) {
return new OpenRegistryImpl<>() {
private final Lazy<TypeLoader<T>> loaderCache = Lazy.of(() -> loader.apply(this));
private final Lazy<TypeLoader<T>> loaderCache = Lazy.lazy(() -> loader.apply(this));
@Override
public T load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {

View File

@@ -27,7 +27,7 @@ public class AddonRegistry extends OpenRegistryImpl<TerraAddon> {
public AddonRegistry(TerraAddon addon, TerraPlugin main) {
this.main = main;
register(addon.getName(), addon);
register(addon);
}
@Override
@@ -38,6 +38,10 @@ public class AddonRegistry extends OpenRegistryImpl<TerraAddon> {
return super.register(identifier, addon);
}
public boolean register(TerraAddon addon) {
return register(addon.getName(), addon);
}
@Override
public void clear() {
throw new UnsupportedOperationException();

View File

@@ -0,0 +1,109 @@
package com.dfsek.terra.fabric;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import com.dfsek.terra.fabric.util.FabricUtil;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import java.util.HashMap;
import java.util.Map;
@Addon("terra-fabric")
@Author("Terra")
@Version("1.0.0")
public final class FabricAddon extends TerraAddon {
private final TerraPluginImpl terraFabricPlugin;
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
public FabricAddon(TerraPluginImpl terraFabricPlugin) {
this.terraFabricPlugin = terraFabricPlugin;
}
@Override
public void initialize() {
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
if(template.doRegistryInjection()) {
BuiltinRegistries.CONFIGURED_FEATURE.getEntries().forEach(entry -> {
if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) {
try {
event.getPack().getCheckedRegistry(Tree.class).register(entry.getKey().getValue().toString(), (Tree) entry.getValue());
terraFabricPlugin.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree.");
} catch(DuplicateEntryException ignored) {
}
}
});
}
templates.put(event.getPack(), Pair.of(template, null));
})
.global();
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPostLoadEvent.class)
.then(event -> {
PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
templates.get(event.getPack()).setRight(template);
})
.priority(100)
.global();
terraFabricPlugin.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, BiomeRegistrationEvent.class)
.then(event -> {
terraFabricPlugin.logger().info("Registering biomes...");
Registry<Biome> biomeRegistry = event.getRegistryManager().get(Registry.BIOME_KEY);
terraFabricPlugin.getConfigRegistry().forEach(pack -> pack.getCheckedRegistry(TerraBiome.class).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.
terraFabricPlugin.logger().info("Biomes registered.");
})
.global();
}
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try {
registry.register(id, (Tree) tree);
} catch(DuplicateEntryException ignore) {
}
}
public Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> getTemplates() {
return templates;
}
}

View File

@@ -0,0 +1,38 @@
package com.dfsek.terra.fabric;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.PopulatorFeature;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import net.fabricmc.api.ModInitializer;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.FeatureConfig;
public class FabricEntryPoint implements ModInitializer {
private static final TerraPluginImpl TERRA_PLUGIN = new TerraPluginImpl();
public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC);
public static final ConfiguredFeature<?, ?> POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE));
@Override
public void onInitialize() {
// register the things
Registry.register(Registry.FEATURE, new Identifier("terra", "populator"), POPULATOR_FEATURE);
RegistryKey<ConfiguredFeature<?, ?>> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_KEY, new Identifier("terra", "populator"));
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE);
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC);
}
public static TerraPluginImpl getTerraPlugin() {
return TERRA_PLUGIN;
}
}

View File

@@ -1,343 +0,0 @@
package com.dfsek.terra.fabric;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.Logger;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.exception.MalformedCommandException;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.PluginConfig;
import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.lang.Language;
import com.dfsek.terra.api.profiler.Profiler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.commands.TerraCommandManager;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfigImpl;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.event.EventManagerImpl;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
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.PopulatorFeature;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.dfsek.terra.fabric.util.ProtoBiome;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.CheckedRegistryImpl;
import com.dfsek.terra.registry.LockedRegistryImpl;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.util.logging.DebugLogger;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.FeatureConfig;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC);
public static final ConfiguredFeature<?, ?> POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE));
private static TerraFabricPlugin instance;
private final org.apache.logging.log4j.Logger log4jLogger = LogManager.getLogger();
private final EventManager eventManager = new EventManagerImpl(this);
private final GenericLoaders genericLoaders = new GenericLoaders(this);
private final Profiler profiler = new ProfilerImpl();
private final Logger logger = new Logger() {
@Override
public void info(String message) {
log4jLogger.info(message);
}
@Override
public void warning(String message) {
log4jLogger.warn(message);
}
@Override
public void severe(String message) {
log4jLogger.error(message);
}
};
private final DebugLogger debugLogger = new DebugLogger(logger);
private final ItemHandle itemHandle = new FabricItemHandle();
private final WorldHandle worldHandle = new FabricWorldHandle();
private final ConfigRegistry configRegistry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistryImpl<>(configRegistry);
private final FabricAddon fabricAddon = new FabricAddon();
private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this);
private final com.dfsek.terra.api.registry.Registry<TerraAddon> addonLockedRegistry = new LockedRegistryImpl<>(addonRegistry);
private final PluginConfig config = new PluginConfigImpl();
private final CommandManager manager = new TerraCommandManager(this);
private File dataFolder;
public static TerraFabricPlugin getInstance() {
return instance;
}
private ProtoBiome parseBiome(String id) throws LoadException {
Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier); // failure.
return new ProtoBiome(identifier);
}
public CommandManager getManager() {
return manager;
}
@Override
public WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public Logger logger() {
return logger;
}
@Override
public PluginConfig getTerraConfig() {
return config;
}
@Override
public File getDataFolder() {
return dataFolder;
}
@Override
public Language getLanguage() {
return LangUtil.getLanguage();
}
public FabricAddon getFabricAddon() {
return fabricAddon;
}
@Override
public CheckedRegistry<ConfigPack> getConfigRegistry() {
return checkedRegistry;
}
@Override
public com.dfsek.terra.api.registry.Registry<TerraAddon> getAddons() {
return addonLockedRegistry;
}
@Override
public boolean reload() {
config.load(this);
LangUtil.load(config.getLanguage(), this); // Load language.
boolean succeed = configRegistry.loadAll(this);
return succeed;
}
@Override
public ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public void saveDefaultConfig() {
try(InputStream stream = getClass().getResourceAsStream("/config.yml")) {
File configFile = new File(getDataFolder(), "config.yml");
if(!configFile.exists()) FileUtils.copyInputStreamToFile(stream, configFile);
} catch(IOException e) {
e.printStackTrace();
}
}
@Override
public String platformName() {
return "Fabric";
}
@Override
public Logger getDebugLogger() {
return debugLogger;
}
@SuppressWarnings("unchecked")
@Override
public void register(TypeRegistry registry) {
genericLoaders.register(registry);
registry
.registerLoader(BlockState.class, (t, o, l) -> worldHandle.createBlockData((String) o))
.registerLoader(com.dfsek.terra.api.world.biome.Biome.class, (t, o, l) -> parseBiome((String) o))
.registerLoader(Identifier.class, (t, o, l) -> {
Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null) throw new LoadException("Invalid identifier: " + o);
return identifier;
});
}
@Override
public void onInitialize() {
instance = this;
this.dataFolder = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra");
saveDefaultConfig();
config.load(this);
LangUtil.load(config.getLanguage(), this);
logger.info("Initializing Terra...");
debugLogger.setDebug(config.isDebugLogging());
if(config.isDebugProfiler()) profiler.start();
if(!addonRegistry.loadAll(getClass().getClassLoader())) {
throw new IllegalStateException("Failed to load addons. Please correct addon installations to continue.");
}
logger.info("Loaded addons.");
Registry.register(Registry.FEATURE, new Identifier("terra", "populator"), POPULATOR_FEATURE);
RegistryKey<ConfiguredFeature<?, ?>> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_KEY, new Identifier("terra", "populator"));
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE);
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC);
try {
CommandUtil.registerAll(manager);
} catch(MalformedCommandException e) {
e.printStackTrace(); // TODO do something here even though this should literally never happen
}
logger.info("Finished initialization.");
}
@Override
public EventManager getEventManager() {
return eventManager;
}
@Override
public Profiler getProfiler() {
return profiler;
}
@Addon("Terra-Fabric")
@Author("Terra")
@Version("1.0.0")
public final class FabricAddon extends TerraAddon {
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
@Override
public void initialize() {
eventManager
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
if(template.doRegistryInjection()) {
BuiltinRegistries.CONFIGURED_FEATURE.getEntries().forEach(entry -> {
if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) {
try {
event.getPack().getCheckedRegistry(Tree.class).register(entry.getKey().getValue().toString(), (Tree) entry.getValue());
debugLogger.info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree.");
} catch(DuplicateEntryException ignored) {
}
}
});
}
templates.put(event.getPack(), Pair.of(template, null));
})
.global();
eventManager
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPostLoadEvent.class)
.then(event -> {
PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
templates.get(event.getPack()).setRight(template);
})
.priority(100)
.global();
eventManager
.getHandler(FunctionalEventHandler.class)
.register(this, BiomeRegistrationEvent.class)
.then(event -> {
logger.info("Registering biomes...");
Registry<Biome> biomeRegistry = event.getRegistryManager().get(Registry.BIOME_KEY);
configRegistry.forEach(pack -> pack.getCheckedRegistry(TerraBiome.class).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();
eventManager
.getHandler(FunctionalEventHandler.class)
.register(this, GameInitializationEvent.class)
.then(event -> {
TerraFabricPlugin main = TerraFabricPlugin.getInstance();
main.logger().info("Loading config packs...");
configRegistry.loadAll(TerraFabricPlugin.this);
logger.info("Loaded packs.");
})
.global();
}
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try {
registry.register(id, (Tree) tree);
} catch(DuplicateEntryException ignore) {
}
}
public Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> getTemplates() {
return templates;
}
}
}

View File

@@ -0,0 +1,105 @@
package com.dfsek.terra.fabric;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.AbstractTerraPlugin;
import com.dfsek.terra.api.Logger;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.util.ProtoBiome;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.util.Optional;
public class TerraPluginImpl extends AbstractTerraPlugin {
private final ItemHandle itemHandle = new FabricItemHandle();
private final WorldHandle worldHandle = new FabricWorldHandle();
private final Lazy<File> dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"));
@Override
public WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
protected Optional<TerraAddon> getPlatformAddon() {
return Optional.of(new FabricAddon(this));
}
public TerraPluginImpl() {
load();
}
@Override
protected Logger createLogger() {
final org.apache.logging.log4j.Logger log4jLogger = LogManager.getLogger();
return new Logger() {
@Override
public void info(String message) {
log4jLogger.info(message);
}
@Override
public void warning(String message) {
log4jLogger.warn(message);
}
@Override
public void severe(String message) {
log4jLogger.error(message);
}
};
}
@Override
public File getDataFolder() {
return dataFolder.value();
}
@Override
public boolean reload() {
getTerraConfig().load(this);
LangUtil.load(getTerraConfig().getLanguage(), this); // Load language.
boolean succeed = getRawConfigRegistry().loadAll(this);
return succeed;
}
@Override
public ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public String platformName() {
return "Fabric";
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry
.registerLoader(com.dfsek.terra.api.world.biome.Biome.class, (t, o, l) -> parseBiome((String) o))
.registerLoader(Identifier.class, (t, o, l) -> {
Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null) throw new LoadException("Invalid identifier: " + o);
return identifier;
});
}
private ProtoBiome parseBiome(String id) throws LoadException {
Identifier identifier = Identifier.tryParse(id);
if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier); // failure.
return new ProtoBiome(identifier);
}
}

View File

@@ -1,9 +0,0 @@
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 {
}

View File

@@ -6,7 +6,7 @@ import com.dfsek.terra.api.world.generator.ChunkData;
import com.dfsek.terra.api.world.generator.Chunkified;
import com.dfsek.terra.api.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generator.ChunkGenerator;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.block.FabricBlockState;
import com.dfsek.terra.fabric.mixin.StructureAccessorAccessor;
import com.dfsek.terra.util.FastRandom;
@@ -44,7 +44,7 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
config -> config.group(
Codec.STRING.fieldOf("pack")
.forGetter(ConfigPack::getID)
).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)));
).apply(config, config.stable(FabricEntryPoint.getTerraPlugin().getConfigRegistry()::get)));
public static final Codec<FabricChunkGeneratorWrapper> CODEC = RecordCodecBuilder.create(
instance -> instance.group(

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -19,7 +19,7 @@ import java.util.stream.Collectors;
public class TerraBiomeSource extends BiomeSource {
public static final Codec<ConfigPack> PACK_CODEC = (RecordCodecBuilder.create(config -> config.group(
Codec.STRING.fieldOf("pack").forGetter(ConfigPack::getID)
).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get))));
).apply(config, config.stable(FabricEntryPoint.getTerraPlugin().getConfigRegistry()::get))));
public static final Codec<TerraBiomeSource> CODEC = RecordCodecBuilder.create(instance -> instance.group(
RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry),
Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed),

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -25,7 +25,7 @@ public class TerraGeneratorType extends GeneratorType {
@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
FabricEntryPoint.getTerraPlugin().getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes
return options;
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.fabric.mixin;
import com.dfsek.terra.api.command.exception.CommandException;
import com.dfsek.terra.api.entity.CommandSender;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
@@ -33,7 +33,7 @@ public abstract class CommandManagerMixin {
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V", remap = false))
private void injectTerraCommands(CommandManager.RegistrationEnvironment environment, CallbackInfo ci) {
com.dfsek.terra.api.command.CommandManager manager = TerraFabricPlugin.getInstance().getManager();
com.dfsek.terra.api.command.CommandManager manager = FabricEntryPoint.getTerraPlugin().getManager();
int max = manager.getMaxArgumentDepth();
RequiredArgumentBuilder<ServerCommandSource, String> arg = argument("arg" + (max - 1), StringArgumentType.word());
for(int i = 0; i < max; i++) {

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.fabric.mixin;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener;
@@ -26,7 +26,7 @@ public abstract class ServerWorldMixin {
public void injectConstructor(MinecraftServer server, Executor workerExecutor, LevelStorage.Session session, ServerWorldProperties properties, RegistryKey<World> registryKey, DimensionType dimensionType, WorldGenerationProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List<Spawner> list, boolean bl, CallbackInfo ci) {
if(chunkGenerator instanceof FabricChunkGeneratorWrapper) {
((FabricChunkGeneratorWrapper) chunkGenerator).setWorld((ServerWorld) (Object) this);
TerraFabricPlugin.getInstance().logger().info("Registered world " + this);
FabricEntryPoint.getTerraPlugin().logger().info("Registered world " + this);
}
}
}

View File

@@ -6,12 +6,11 @@ import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import org.spongepowered.asm.mixin.Implements;
@@ -32,7 +31,7 @@ public abstract class ConfiguredFeatureMixin {
@SuppressWarnings({"ConstantConditions", "try"})
public boolean terra$plant(Vector3 l, World world, Random r) {
String id = BuiltinRegistries.CONFIGURED_FEATURE.getId((ConfiguredFeature<?, ?>) (Object) this).toString();
try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) {
try(ProfileFrame ignore = FabricEntryPoint.getTerraPlugin().getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) {
StructureWorldAccess fabricWorldAccess = ((StructureWorldAccess) world);
ChunkGenerator generatorWrapper = ((ServerWorldAccess) world).toServerWorld().getChunkManager().getChunkGenerator();
return generate(fabricWorldAccess, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
@@ -40,8 +39,8 @@ public abstract class ConfiguredFeatureMixin {
}
public Set<BlockType> terra$getSpawnable() {
return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium"));
return MaterialSet.get(FabricEntryPoint.getTerraPlugin().getWorldHandle().createBlockData("minecraft:grass_block"),
FabricEntryPoint.getTerraPlugin().getWorldHandle().createBlockData("minecraft:podzol"),
FabricEntryPoint.getTerraPlugin().getWorldHandle().createBlockData("minecraft:mycelium"));
}
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.fabric.mixin.implementations.block.state;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.SerialState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
@@ -96,7 +96,7 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type":
terra$setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v));
terra$setSpawnedType(FabricEntryPoint.getTerraPlugin().getWorldHandle().getEntity(v));
return;
case "delay":
terra$setDelay(Integer.parseInt(v));

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.mixin.lifecycle.client;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.GameInitializationEvent;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.fabric.generation.TerraGeneratorType;
import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor;
import net.minecraft.client.MinecraftClient;
@@ -19,8 +19,8 @@ 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
shift = At.Shift.BEFORE))
public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) {
TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent());
TerraFabricPlugin.getInstance().getConfigRegistry().forEach(pack -> {
FabricEntryPoint.getTerraPlugin().getEventManager().callEvent(new PlatformInitializationEvent());
FabricEntryPoint.getTerraPlugin().getConfigRegistry().forEach(pack -> {
final GeneratorType generatorType = new TerraGeneratorType(pack);
//noinspection ConstantConditions
((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getID()));

View File

@@ -1,7 +1,8 @@
package com.dfsek.terra.fabric.mixin.lifecycle.server;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.TerraPluginImpl;
import com.dfsek.terra.fabric.event.BiomeRegistrationEvent;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
@@ -30,7 +31,7 @@ public abstract class GeneratorOptionsMixin {
return;
}
TerraFabricPlugin main = TerraFabricPlugin.getInstance();
TerraPluginImpl main = FabricEntryPoint.getTerraPlugin();
String prop = properties.get("level-type").toString().trim();
if(prop.startsWith("Terra")) {

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.mixin.lifecycle.server;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.event.GameInitializationEvent;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import net.minecraft.server.Main;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -12,6 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
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;"))
private static void injectConstructor(String[] args, CallbackInfo ci) {
TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks and stuff
FabricEntryPoint.getTerraPlugin().getEventManager().callEvent(new PlatformInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks and stuff
}
}

View File

@@ -6,7 +6,7 @@ import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.Sign;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.FabricEntryPoint;
import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor;
import com.mojang.serialization.Lifecycle;
import net.minecraft.block.entity.LootableContainerBlockEntity;
@@ -47,7 +47,7 @@ public final class FabricUtil {
// BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = new HashMap<>(); // template.getColors();
TerraFabricPlugin.FabricAddon fabricAddon = TerraFabricPlugin.getInstance().getFabricAddon();
//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);
@@ -56,7 +56,7 @@ public final class FabricUtil {
generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it.
generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, TerraFabricPlugin.POPULATOR_CONFIGURED_FEATURE);
generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, FabricEntryPoint.POPULATOR_CONFIGURED_FEATURE);
if(pack.vanillaCaves()) {
for(GenerationStep.Carver carver : GenerationStep.Carver.values()) {

View File

@@ -17,7 +17,7 @@
"environment": "*",
"entrypoints": {
"main": [
"com.dfsek.terra.fabric.TerraFabricPlugin"
"com.dfsek.terra.fabric.FabricEntryPoint"
]
},
"mixins": [