Compare commits

..
14 Commits
23 changed files with 243 additions and 390 deletions
+43
View File
@@ -0,0 +1,43 @@
name: release
on:
push:
tags:
- "*"
env:
VERSION: "${{github.ref_name}}"
jobs:
build:
strategy:
matrix:
java: [
21, # Current Java LTS
]
runs-on: ubuntu-22.04
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v2
- name: setup jdk ${{ matrix.java }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: "temurin"
- name: make gradle wrapper executable
run: chmod +x ./gradlew
- name: build
run: ./gradlew build
- name: publish maven
continue-on-error: true
env:
MAVEN_TOKEN: "${{secrets.MAVEN_TOKEN}}"
run: ./gradlew publish
- name: publish release
uses: akkuman/gitea-release-action@v1
with:
files: |-
build/libs/**
token: "${{secrets.GITHUB_TOKEN}}"
+74 -7
View File
@@ -1,15 +1,15 @@
# ΩConfig
<h1 align="center">Omega Config Ω </h1>
<p align="center">A configuration library by <a href="https://github.com/Draylar">Draylar</a></p>
---
*The last config library you will ever use.*
ΩConfig is a hyper-minimal config library based on [Auto Config](https://github.com/shedaniel/AutoConfig). It aims to
achieve the following goals:
- Be lightweight (<10 KB) for JIJ usage
- Be lightweight (<25 KB) for JIJ usage
- Exceedingly simple design & API for developers
- Intuition and usability for players
- Bonus annotations for advanced config options (syncing values)
The following is an example of a simple ΩConfig setup:
@@ -19,6 +19,10 @@ public class TestConfig implements Config {
@Comment(value = "Hello!")
boolean value = false;
@Syncing
@Comment(value = "This value will sync to the client!")
boolean syncableValue = false;
@Override
public String getFileName() {
return "test-config";
@@ -39,6 +43,66 @@ public class MyModInitializer {
}
```
Looking for a simple config screen? Talk about easy!
```java
public class ClientInitializer implements ClientModInitializer {
@Override
public void onInitializeClient() {
// Make sure you implement getModid in your config class!
OmegaConfigGui.registerConfigScreen(MainInitializer.CONFIG);
}
}
```
---
### Pulling Omega Config into Development
To use Omega Config, you will have to add it to your build.gradle file.
What you pull in depends on whether you want GUI functionality. For basic config files using the base module (~20KB),
you can use the following gradle declarations:
```groovy
repositories {
maven { url 'https://maven.draylar.dev/releases' }
}
// 1.19.2 version: 1.3.0+1.19.2
dependencies {
modImplementation include("dev.draylar.omega-config:omega-config-base:${project.omega_config_version}")
}
```
Easy - you now have a bundled configuration library. Use the examples in the first section to implement your config.
If you want to add GUI functionality (most likely Mod Menu support), you can pull in the GUI module (~25 KB):
```groovy
repositories {
...
// Needed to retrieve Cloth Config Lite for Omega Config in development environments.
maven {
name = "Shedaniel's Maven"
url = "https://maven.shedaniel.me/"
}
// Optional dependency for Mod Menu - recommended for viewing your screen in development
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/releases/"
}
}
dependencies {
... (including the base declarations)
modImplementation include("dev.draylar.omega-config:omega-config-gui:${project.omega_config_version}")
modRuntimeOnly ("com.terraformersmc:modmenu:${project.modmenu_version}") // 3.0.1 for 1.18.1
}
```
---
### Extra API Utilities
@@ -48,12 +112,15 @@ public class MyModInitializer {
**save()** - *saves a modified configuration instance to disk*
```java
MyModInitializer.CONFIG.value=false;
MyModInitializer.CONFIG.save(); // writes the new value to disk
MyModInitializer.CONFIG.value = false;
MyModInitializer.CONFIG.save(); // writes the new value to disk
```
`@Syncing` - *configuration options marked with this annotation will automatically sync to the client when they join a server.*
---
### License
ΩConfig is available under Public Domain. You are encouraged to utilize the code in this repository in any way you wish.
ΩConfig is available under MIT. Omega Config will bundle the MIT license inside the jar you pull as a dependency, which means you can distribute it as a bundled dependency without any additional steps.
+70 -53
View File
@@ -1,26 +1,89 @@
plugins {
id "fabric-loom" version "0.10-SNAPSHOT"
id "maven-publish"
id "java-library"
id 'fabric-loom' version '1.8-SNAPSHOT'
id 'maven-publish'
}
group = "draylar"
archivesBaseName = "omega-config"
if (System.getenv("VERSION")) {
project.mod_version = System.getenv("VERSION")
}
version = "${project.mod_version}"
group = "dev.draylar"
base {
archivesName = "omega-config"
}
allprojects {
apply plugin: "fabric-loom"
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
version = project.mod_version
repositories {}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
it.options.release = 17
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
}
jar {
from(rootProject.file("LICENSE")) {
rename { "LICENSE_${project.archivesBaseName.replace('-', '_')}" }
}
}
}
subprojects {
apply plugin: 'fabric-loom'
apply plugin: 'maven-publish'
archivesBaseName = project.name
group = "draylar.${project.group}"
group = "dev.draylar.${project.group}"
// Only publish for submodules (not the root project) - add standard jar, + sources & development jar
publishing {
publications {
mavenJava(MavenPublication) {
create("mavenJava", MavenPublication) {
artifactId = project.archives_base_name
version = "${project.mod_version}+${project.minecraft_version}"
from components.java
}
}
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
maven {
name = "Gitea"
url = uri("https://git.bigduckie.dev/api/packages/big-duckie/maven")
credentials(HttpHeaderCredentials) {
name = "Authorization"
value = "token ${System.getenv("MAVEN_TOKEN")}"
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
// Add sources & javadoc artifacts
@@ -30,55 +93,9 @@ subprojects {
}
}
allprojects {
apply plugin: "fabric-loom"
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
version = project.mod_version
repositories {
maven {
name = "FabricMC"
url = "https://maven.fabricmc.net"
}
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/releases/"
}
}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modRuntimeOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile) {
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
}
jar {
from(rootProject.file("LICENSE")) {
rename { "LICENSE_${project.archivesBaseName.replace('-', '_')}" }
}
}
}
// Main project depends on the base & gui module for testing
dependencies {
implementation project(path: ":omega-config-base", configuration: "namedElements")
implementation project(path: ":omega-config-gui", configuration: "namedElements")
afterEvaluate {
testmodImplementation sourceSets.main.output
+12 -9
View File
@@ -1,16 +1,19 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/versions.html
minecraft_version=1.18.1
yarn_mappings=1.18.1+build.2
loader_version=0.12.11
minecraft_version=1.20.1
yarn_mappings=1.20.1+build.10
loader_version=0.16.7
#Fabric api
fabric_version=0.44.0+1.18
# Mod Properties
mod_version=1.2.0
maven_group=draylar
mod_version=1.4.1
maven_group=dev.bigduckie
archives_base_name=omega-config
modmenu_version=3.0.1
# Dependencies
fabric_version=0.92.2+1.20.1
modmenu_version=7.1.0
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-4
View File
@@ -1,4 +0,0 @@
before_install:
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- source install-jdk.sh --feature 17
- jshell --version
@@ -6,6 +6,7 @@ import draylar.omegaconfig.api.Comment;
import draylar.omegaconfig.api.Config;
import draylar.omegaconfig.gson.SyncableExclusionStrategy;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
@@ -30,7 +31,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class OmegaConfig {
public class OmegaConfig implements ModInitializer {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Identifier CONFIG_SYNC_PACKET = new Identifier("omegaconfig", "sync");
@@ -38,7 +39,8 @@ public class OmegaConfig {
public static final Logger LOGGER = LogManager.getLogger();
private static final List<Config> REGISTERED_CONFIGURATIONS = new ArrayList<>();
static {
@Override
public void onInitialize() {
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> server.execute(() -> {
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
@@ -94,8 +96,9 @@ public class OmegaConfig {
}
return config;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
exception.printStackTrace();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException("No valid constructor found for: " + configClass.getName());
}
}
@@ -177,10 +180,8 @@ public class OmegaConfig {
Class<?>[] classes = aClass.getDeclaredClasses();
if (classes.length != 0) {
for (Class<?> clazz : classes) {
populateRecursively(list, clazz);
}
for (Class<?> clazz : classes) {
populateRecursively(list, clazz);
}
}
@@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.RunArgs;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@@ -36,7 +37,7 @@ public class ClientMixin {
client.execute(() -> {
if (tag != null && tag.contains("Configurations")) {
NbtList list = tag.getList("Configurations", NbtType.COMPOUND);
NbtList list = tag.getList("Configurations", NbtElement.COMPOUND_TYPE);
list.forEach(compound -> {
NbtCompound syncedConfiguration = (NbtCompound) compound;
String name = syncedConfiguration.getString("ConfigName");
@@ -1,18 +1,24 @@
{
"schemaVersion": 1,
"id": "omega-config",
"version": "1.1.0",
"version": "${version}",
"name": "OmegaConfig",
"description": "The last config solution you will ever use.",
"authors": [
"Draylar",
"Frqnny"
"Frqnny",
"Big Duckie"
],
"entrypoints": {
"main": [
"draylar.omegaconfig.OmegaConfig"
]
},
"contact": {
"homepage": "https://github.com/Draylar/omega-config",
"sources": "https://github.com/Draylar/omega-config",
"issues": "https://github.com/Draylar/omega-config/issues"
},
"homepage": "https://github.com/Draylar/omega-config",
"sources": "https://github.com/Draylar/omega-config",
"issues": "https://github.com/Draylar/omega-config/issues"
},
"license": "MIT",
"environment": "*",
"mixins": [
@@ -23,9 +29,11 @@
"fabric": "*",
"minecraft": "*"
},
"custom": {
"modmenu": {
"badges": [ "library" ]
}
"custom": {
"modmenu": {
"badges": [
"library"
]
}
}
}
-12
View File
@@ -1,12 +0,0 @@
repositories {
maven { url "https://maven.shedaniel.me/" }
}
dependencies {
implementation project(":omega-config-base")
include "me.shedaniel.cloth:cloth-config-lite-fabric:2.0.6"
modApi ("me.shedaniel.cloth:cloth-config-lite-fabric:2.0.6") {
exclude group: "net.fabricmc.fabric-api"
}
}
@@ -1,63 +0,0 @@
package draylar.omegaconfiggui;
import draylar.omegaconfig.OmegaConfig;
import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.api.screen.OmegaScreenFactory;
import me.shedaniel.clothconfiglite.api.ConfigScreen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.LiteralText;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@Environment(EnvType.CLIENT)
public class OmegaConfigGui {
/**
* Returns a factory which provides new Cloth Config Lite {@link Screen} instances for the given {@link Config}.
* @param config Omega Config instance to create the screen factory for
* @return a factory which provides new Cloth Config Lite {@link Screen} instances for the given {@link Config}.
*/
public static OmegaScreenFactory<Screen> getConfigScreenFactory(Config config) {
return parent -> {
try {
Config defaultConfig = config.getClass().getDeclaredConstructor().newInstance();
ConfigScreen screen = ConfigScreen.create(new LiteralText(config.getName()), parent);
// Fields
for (Field field : config.getClass().getDeclaredFields()) {
try {
screen.add(new LiteralText(field.getName()), field.get(config), () -> {
try {
return field.get(defaultConfig);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return 0.0d;
}, newValue -> {
try {
field.set(config, newValue);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
config.save();
});
} catch (IllegalAccessException | IllegalArgumentException exception) {
// ignored
}
}
return screen.get();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
OmegaConfig.LOGGER.error(String.format("Configuration class for mod %s must have a no-argument constructor for retrieving default values.", config.getModid()));
}
// todo: is this a bad idea
return null;
};
}
}
@@ -1,56 +0,0 @@
package draylar.omegaconfiggui.api.screen;
import com.google.common.collect.ImmutableMap;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.OmegaConfigGui;
import draylar.omegaconfiggui.mixin.modmenu.ModMenuAccessor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.gui.screen.Screen;
import java.util.HashMap;
import java.util.Map;
@Environment(EnvType.CLIENT)
public class OmegaModMenu {
private static final Map<Config, ConfigScreenFactory<Screen>> REGISTERED_CONFIGURATIONS = new HashMap<>();
public static boolean modMenuInitialized = false;
/**
* Registers a ModMenu configuration screen for the given {@link Config} instance.
*
* @param config registered config to create a ModMenu screen for
* @param <T> config type
*/
public static <T extends Config> void registerConfigScreen(T config) {
if(FabricLoader.getInstance().isModLoaded("modmenu")) {
OmegaScreenFactory<Screen> factory = OmegaConfigGui.getConfigScreenFactory(config);
if(modMenuInitialized) {
OmegaModMenu.injectScreen(config, factory::get);
} else {
addConfiguration(config, factory::get);
}
}
}
public static <T extends Config> void injectScreen(T config, ConfigScreenFactory<Screen> factory) {
// they will suspect nothing
ModMenuAccessor.setConfigScreenFactories(
new ImmutableMap.Builder<String, ConfigScreenFactory<?>>()
.putAll(ModMenuAccessor.getConfigScreenFactories())
.put(config.getModid(), factory)
.build());
}
public static Map<Config, ConfigScreenFactory<Screen>> getRegisteredConfigurations() {
return REGISTERED_CONFIGURATIONS;
}
public static void addConfiguration(Config config, ConfigScreenFactory<Screen> screen) {
REGISTERED_CONFIGURATIONS.put(config, screen);
}
}
@@ -1,10 +0,0 @@
package draylar.omegaconfiggui.api.screen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.Screen;
@Environment(EnvType.CLIENT)
public interface OmegaScreenFactory<T extends Screen> {
T get(Screen parent);
}
@@ -1,23 +0,0 @@
package draylar.omegaconfiggui.mixin;
import com.terraformersmc.modmenu.ModMenu;
import draylar.omegaconfiggui.api.screen.OmegaModMenu;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Environment(EnvType.CLIENT)
@Mixin(ModMenu.class)
public class ModMenuMixin {
@Inject(method = "onInitializeClient", at = @At("RETURN"), remap = false)
private void addOmegaConfigurationScreens(CallbackInfo ci) {
OmegaModMenu.modMenuInitialized = true;
// Add loaded configuration screens to mod menu.
OmegaModMenu.getRegisteredConfigurations().forEach(OmegaModMenu::injectScreen);
}
}
@@ -1,51 +0,0 @@
package draylar.omegaconfiggui.mixin;
import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Set;
public class OmegaConfigMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if(targetClassName.contains("ModMenu")) {
return FabricLoader.getInstance().isModLoaded("modmenu");
}
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}
@@ -1,24 +0,0 @@
package draylar.omegaconfiggui.mixin.modmenu;
import com.google.common.collect.ImmutableMap;
import com.terraformersmc.modmenu.ModMenu;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Environment(EnvType.CLIENT)
@Mixin(ModMenu.class)
public interface ModMenuAccessor {
@Accessor
static ImmutableMap<String, ConfigScreenFactory<?>> getConfigScreenFactories() {
throw new UnsupportedOperationException();
}
@Accessor
static void setConfigScreenFactories(ImmutableMap<String, ConfigScreenFactory<?>> factories) {
throw new UnsupportedOperationException();
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

@@ -1,33 +0,0 @@
{
"schemaVersion": 1,
"id": "omega-config-gui",
"version": "${version}",
"name": "Omega Config GUI",
"description": "GUI support for Omega Config.",
"authors": [
"Draylar"
],
"contact": {
"homepage": "https://github.com/Draylar/omega-config",
"sources": "https://github.com/Draylar/omega-config",
"issues": "https://github.com/Draylar/omega-config/issues"
},
"license": "MIT",
"environment": "*",
"mixins": [
"omega-config-gui.mixins.json"
],
"depends": {
"fabricloader": "*",
"fabric": "*",
"minecraft": "*"
},
"recommends": {
"modmenu": "3.0.1"
},
"custom": {
"modmenu": {
"badges": [ "library" ]
}
}
}
@@ -1,14 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "draylar.omegaconfiggui.mixin",
"compatibilityLevel": "JAVA_17",
"plugin": "draylar.omegaconfiggui.mixin.OmegaConfigMixinPlugin",
"client": [
"modmenu.ModMenuAccessor",
"ModMenuMixin"
],
"injectors": {
"defaultRequire": 1
}
}
+1 -2
View File
@@ -1,10 +1,10 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
mavenCentral()
gradlePluginPortal()
}
}
@@ -12,4 +12,3 @@ pluginManagement {
rootProject.name = 'omega-config'
include 'omega-config-base'
include 'omega-config-gui'
@@ -1,20 +1,19 @@
package draylar.omegatest;
import draylar.omegaconfiggui.api.screen.OmegaModMenu;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.LiteralText;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.text.Text;
public class OmegaTestClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
OmegaModMenu.registerConfigScreen(OmegaTestMain.CONFIG);
HudRenderCallback.EVENT.register((stack, delta) -> {
MinecraftClient.getInstance().textRenderer.draw(stack, new LiteralText(String.valueOf(OmegaTestMain.CONFIG.v)), 15, 15, 0xffffff);
MinecraftClient.getInstance().textRenderer.draw(stack, new LiteralText(String.valueOf(OmegaTestMain.CONFIG.doubleTest)), 15, 30, 0xffffff);
HudRenderCallback.EVENT.register((context, delta) -> {
TextRenderer tr = MinecraftClient.getInstance().textRenderer;
context.drawText(tr, Text.literal(String.valueOf(OmegaTestMain.CONFIG.v)), 15, 15, 0xffffff, true);
context.drawText(tr, Text.literal(String.valueOf(OmegaTestMain.CONFIG.doubleTest)), 15, 25, 0xffffff, true);
});
}
}
@@ -8,7 +8,7 @@ import java.util.HashMap;
import java.util.Map;
//taken straight out of Mo' Structures
//taken straight out of Mo Structures
public class StructuresConfigTest implements Config {
@Comment("""
@@ -0,0 +1,3 @@
{
"config.omega-config-test.test-config": "Omega Config - Test Config"
}