Compare commits

..
14 Commits
Author SHA1 Message Date
frqnny 3b91570a8c 1.21 update 2024-06-17 17:16:47 -04:00
frqnny de04d5a2cf minor toolchain changes 2024-06-17 16:45:00 -04:00
frqnny f9b19cff35 bump version 2024-06-17 16:30:50 -04:00
frqnny 89132f1e54 fix jitpack.yml 2024-06-17 16:29:05 -04:00
frqnny 08824ba045 1.20.6 update 2024-06-17 16:15:07 -04:00
frqnny 8b2f1db5e9 let's see if this fixes things? 2024-06-17 14:19:40 -04:00
Draylar 5f19348fdc 1.20.1 update without Omega Config GUI 2023-07-01 16:30:59 -05:00
Draylar 505d3e70f8 1.19.2 update with maven publishing and README polishing 2023-03-01 21:16:38 -06:00
DraylarandGitHub 239ec7c3bc 1.2.3 version bump 2022-01-18 11:14:38 -06:00
DraylarandGitHub 0f0abe558e Merge pull request #12 from Luligabi1/1.18
Better config screen title
2022-01-18 11:14:04 -06:00
Luligabi1 5bdce25e29 OmegaConfigGui's generated config screen now has a TranslatableText for its title rather than a LiteralText.q 2021-12-28 15:07:41 -03:00
frqnny 9d7aa7581d Automated fabric mod json version
Closes #11
2021-12-28 10:58:42 -05:00
Draylar 8611edb92c update README 2021-12-20 18:38:58 -06:00
Draylar 58c420d35f add null check for modid when registering modmenu screens 2021-12-20 17:52:54 -06:00
21 changed files with 163 additions and 376 deletions
+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.
+15 -5
View File
@@ -1,10 +1,10 @@
plugins {
id "fabric-loom" version "0.10-SNAPSHOT"
id "fabric-loom" version "1.6-SNAPSHOT"
id "maven-publish"
id "java-library"
}
group = "draylar"
group = "dev.draylar"
archivesBaseName = "omega-config"
subprojects {
@@ -12,10 +12,21 @@ subprojects {
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 {
repositories {
maven {
name = "draylarRepository"
url = "https://maven.draylar.dev/releases"
credentials(PasswordCredentials)
authentication {
basic(BasicAuthentication)
}
}
}
publications {
mavenJava(MavenPublication) {
from components.java
@@ -32,7 +43,7 @@ subprojects {
allprojects {
apply plugin: "fabric-loom"
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21
version = project.mod_version + "-" + project.minecraft_version
repositories {
@@ -71,7 +82,6 @@ allprojects {
// 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
+11 -9
View File
@@ -1,16 +1,18 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
# 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
#Fabric api
fabric_version=0.44.0+1.18
minecraft_version=1.21
yarn_mappings=1.21+build.2
loader_version=0.15.11
# Fabric API
fabric_version=0.100.2+1.21
# Mod Properties
mod_version=1.2.1
maven_group=draylar
mod_version=1.4.4
maven_group=dev.draylar
archives_base_name=omega-config
modmenu_version=3.0.1
modmenu_version=7.1.0
+1 -1
View File
@@ -1,5 +1,5 @@
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.8-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+4 -3
View File
@@ -1,4 +1,5 @@
jdk:
- openjdk21
before_install:
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- source install-jdk.sh --feature 17
- jshell --version
- sdk install java 21.0.3-open
- sdk use java 21.0.3-open
@@ -5,14 +5,16 @@ import com.google.gson.GsonBuilder;
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.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -24,45 +26,15 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.*;
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");
public static final Gson SYNC_ONLY_GSON = new GsonBuilder().addSerializationExclusionStrategy(new SyncableExclusionStrategy()).setPrettyPrinting().create();
public static final Logger LOGGER = LogManager.getLogger();
private static final List<Config> REGISTERED_CONFIGURATIONS = new ArrayList<>();
@Override
public void onInitialize() {
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> server.execute(() -> {
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
// list of configurations that are synced
NbtCompound root = new NbtCompound();
NbtList configurations = new NbtList();
// Iterate over each configuration.
// Find values that should be synced and send the value over.
OmegaConfig.getRegisteredConfigurations().forEach(config -> {
if (config.hasAnySyncable()) {
configurations.add(config.writeSyncingTag());
}
});
// save to packet and send to user
root.put("Configurations", configurations);
packet.writeNbt(root);
handler.sendPacket(ServerPlayNetworking.createS2CPacket(CONFIG_SYNC_PACKET, packet));
}));
}
public static <T extends Config> T register(Class<T> configClass) {
try {
// Attempt to instantiate a new instance of this class.
@@ -96,7 +68,8 @@ public class OmegaConfig implements ModInitializer {
}
return config;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException exception) {
exception.printStackTrace();
throw new RuntimeException("No valid constructor found for: " + configClass.getName());
}
@@ -179,10 +152,8 @@ public class OmegaConfig implements ModInitializer {
Class<?>[] classes = aClass.getDeclaredClasses();
if (classes.length != 0) {
for (Class<?> clazz : classes) {
populateRecursively(list, clazz);
}
for (Class<?> clazz : classes) {
populateRecursively(list, clazz);
}
}
@@ -241,4 +212,38 @@ public class OmegaConfig implements ModInitializer {
public static List<Config> getRegisteredConfigurations() {
return REGISTERED_CONFIGURATIONS;
}
@Override
public void onInitialize() {
PayloadTypeRegistry.playS2C().register(OmegaConfig.SyncConfigPayload.ID, OmegaConfig.SyncConfigPayload.CODEC);
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> server.execute(() -> {
// list of configurations that are synced
NbtCompound root = new NbtCompound();
NbtList configurations = new NbtList();
// Iterate over each configuration.
// Find values that should be synced and send the value over.
OmegaConfig.getRegisteredConfigurations().forEach(config -> {
if (config.hasAnySyncable()) {
configurations.add(config.writeSyncingTag());
}
});
// save to packet and send to user
root.put("Configurations", configurations);
sender.sendPacket(new SyncConfigPayload(root));
}));
}
public record SyncConfigPayload(NbtCompound nbtCompound) implements CustomPayload {
public static final Identifier CONFIG_SYNC_PACKET = Identifier.of("omegaconfig", "sync");
public static final CustomPayload.Id<SyncConfigPayload> ID = new Id<>(CONFIG_SYNC_PACKET);
public static final PacketCodec<PacketByteBuf, SyncConfigPayload> CODEC = PacketCodecs.NBT_COMPOUND.xmap(SyncConfigPayload::new, SyncConfigPayload::nbtCompound).cast();
@Override
public Id<? extends CustomPayload> getId() {
return ID;
}
}
}
@@ -30,11 +30,12 @@ public class ClientMixin {
method = "<init>",
at = @At("RETURN"))
private void onReturn(RunArgs args, CallbackInfo ci) {
ClientPlayNetworking.registerGlobalReceiver(OmegaConfig.CONFIG_SYNC_PACKET, (client, handler, buf, responseSender) -> {
NbtCompound tag = buf.readNbt();
ClientPlayNetworking.registerGlobalReceiver(OmegaConfig.SyncConfigPayload.ID, (payload, context) -> {
NbtCompound tag = payload.nbtCompound();
savedClientConfig.clear();
client.execute(() -> {
context.client().execute(() -> {
if (tag != null && tag.contains("Configurations")) {
NbtList list = tag.getList("Configurations", NbtType.COMPOUND);
list.forEach(compound -> {
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "omega-config",
"version": "1.1.0",
"version": "${version}",
"name": "OmegaConfig",
"description": "The last config solution you will ever use.",
"authors": [
-29
View File
@@ -1,29 +0,0 @@
repositories {
maven {
name = "Shedaniel's Maven"
url = "https://maven.shedaniel.me/"
}
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/releases/"
}
}
dependencies {
implementation project(":omega-config-base")
// Mod Menu
modCompileOnly ("com.terraformersmc:modmenu:${project.modmenu_version}") {
transitive(false)
}
modRuntime ("com.terraformersmc:modmenu:${project.modmenu_version}") {
transitive(false)
}
// Cloth Config Lite
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,93 +0,0 @@
package draylar.omegaconfiggui;
import draylar.omegaconfig.OmegaConfig;
import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.api.screen.OmegaModMenu;
import draylar.omegaconfiggui.api.screen.OmegaScreenFactory;
import me.shedaniel.clothconfiglite.api.ConfigScreen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.LiteralText;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
@Environment(EnvType.CLIENT)
public class OmegaConfigGui {
private static final Map<Config, OmegaScreenFactory<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);
} else {
REGISTERED_CONFIGURATIONS.put(config, factory);
}
}
}
/**
* 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;
};
}
public static Map<Config, OmegaScreenFactory<Screen>> getConfigScreenFactories() {
return REGISTERED_CONFIGURATIONS;
}
}
@@ -1,22 +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.mixin.modmenu.ModMenuAccessor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.Screen;
@Environment(EnvType.CLIENT)
public class OmegaModMenu {
public static <T extends Config> void injectScreen(T config, OmegaScreenFactory<Screen> factory) {
// they will suspect nothing
ModMenuAccessor.setConfigScreenFactories(
new ImmutableMap.Builder<String, ConfigScreenFactory<?>>()
.putAll(ModMenuAccessor.getConfigScreenFactories())
.put(config.getModid(), factory::get)
.build());
}
}
@@ -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,24 +0,0 @@
package draylar.omegaconfiggui.mixin;
import com.terraformersmc.modmenu.ModMenu;
import draylar.omegaconfiggui.OmegaConfigGui;
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) {
OmegaConfigGui.modMenuInitialized = true;
// Add loaded configuration screens to mod menu.
OmegaConfigGui.getConfigScreenFactories().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
View File
@@ -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.OmegaConfigGui;
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() {
OmegaConfigGui.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);
});
}
}
@@ -0,0 +1,3 @@
{
"config.omega-config-test.test-config": "Omega Config - Test Config"
}