Compare commits

...
30 Commits
Author SHA1 Message Date
Draylar 58c420d35f add null check for modid when registering modmenu screens 2021-12-20 17:52:54 -06:00
Draylar 270db37dba fix omega config class loading too early in static block, make modmenu dep transitive 2021-12-20 17:41:14 -06:00
Draylar 2968111445 Move ModMenu dependency to the GUI module 2021-12-20 17:20:50 -06:00
Draylar 136cfe6a9a fix classloading for mod menu by moving registration methods to OmegaConfigGui class, fix versioning 2021-12-20 17:16:02 -06:00
Draylar 3f7c461689 Add mod icons, finish GUI support through Cloth Config Lite 2021-12-20 16:40:03 -06:00
Draylar 36ce7bc924 🦀 proguard is dead, clean up build.gradle 2021-12-20 15:23:52 -06:00
DraylarandGitHub a3cde2c8e7 JDK17 for JitPack.yml on 1.18 2021-12-13 20:39:14 -06:00
DraylarandGitHub 6fa8e58665 Merge pull request #7 from Luligabi1/1.17
Updates to 1.18.1
2021-12-13 20:37:46 -06:00
Luligabi1 ed4e9f6c19 Updates to 1.18.1 2021-12-11 15:09:18 -03:00
DraylarandGitHub 24c0d9a039 Version bump to 1.1.0 2021-12-09 00:13:32 -06:00
DraylarandGitHub 6db4f12eed Merge pull request #6 from RDKRACZ/patch-1
Add "library" badge for ModMenu; Add contact tags to the fabric.mod.json file.
2021-12-09 00:13:04 -06:00
DraylarandGitHub 6ed97d4e00 Merge pull request #4 from alkyaly/fix/comments-in-nested-classes
Fixes comments not applying when inside nested classes.
2021-12-09 00:11:55 -06:00
DraylarandGitHub 3ecbae5593 Merge pull request #5 from alkyaly/fix/multiline
Fixes multi-line comments breaking
2021-12-09 00:11:44 -06:00
K0RRandGitHub d15fcd0732 Update gradle.properties 2021-09-09 12:42:47 +02:00
K0RRandGitHub bd2cc57eb9 Update fabric.mod.json 2021-08-18 13:20:55 +02:00
K0RRandGitHub 539d3ee1af Update gradle-wrapper.properties 2021-08-18 13:18:37 +02:00
adrianoy ebfaac9fb9 Add multiline comments more sensibly... 2021-08-10 01:21:53 -03:00
K0RRandGitHub fbc0a2b354 Add "library" badge for ModMenu; Add contact tags to the fabric.mod.json file.
>It aims to achieve the following goals:
Be lightweight (<10 KB) for JIJ usage

It's 15 KB already :)
2021-08-04 20:18:04 +02:00
adrianoy 3da79e7860 Fixes multi-line comments breaking 2021-07-28 03:38:36 -03:00
adrianoy 228c1bb7e6 This check does nothing. 2021-07-25 23:54:52 -03:00
adrianoy e09f903332 oops. 2021-07-25 22:21:02 -03:00
adrianoy 1fe4d53565 Makes comments apply when inside nested classes of nested classes. 2021-07-25 22:20:35 -03:00
DraylarandGitHub 48f5962f57 Merge pull request #3 from frqnny/modularize
Some more important changes
2021-06-15 23:06:11 -05:00
ffrann 6099b30f3d Add new mo structures as test 2021-06-15 23:48:09 -04:00
ffrann 09658ffee6 Fix mixin compat level being set to JAVA_16
Delete NoValidConstructorException.java (waste of space smh)
2021-06-15 23:39:08 -04:00
ffrann b6b7a67866 1.0.7 update :) 2021-06-11 12:08:11 -04:00
DraylarandGitHub 73730feced Merge pull request #2 from frqnny/modularize
Port to java 16 and MC 1.17
2021-05-27 10:43:32 -05:00
ffrann f468546eea Port to java 16 and MC 1.17 2021-05-26 20:27:14 -04:00
Draylar c2d7cacdab different approach to jitpack j16 support 2021-05-26 14:52:34 -05:00
Draylar c21e5ff3ff force openjdk16 for jitpack 2021-05-26 14:43:31 -05:00
42 changed files with 572 additions and 817 deletions
+10 -4
View File
@@ -4,13 +4,15 @@
*The last config library you will ever use.* *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 ΩConfig is a hyper-minimal config library based on [Auto Config](https://github.com/shedaniel/AutoConfig). It aims to
the following goals: achieve the following goals:
- Be lightweight (<10 KB) for JIJ usage - Be lightweight (<10 KB) for JIJ usage
- Exceedingly simple design & API for developers - Exceedingly simple design & API for developers
- Intuition and usability for players - Intuition and usability for players
The following is an example of a simple ΩConfig setup: The following is an example of a simple ΩConfig setup:
```java ```java
public class TestConfig implements Config { public class TestConfig implements Config {
@@ -24,6 +26,7 @@ public class TestConfig implements Config {
} }
``` ```
```java ```java
public class MyModInitializer { public class MyModInitializer {
@@ -35,7 +38,9 @@ public class MyModInitializer {
} }
} }
``` ```
--- ---
### Extra API Utilities ### Extra API Utilities
ΩConfig provides several utility methods for developers. ΩConfig provides several utility methods for developers.
@@ -48,6 +53,7 @@ MyModInitializer.CONFIG.save(); // writes the new value to disk
``` ```
--- ---
### License ### 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 Public Domain. You are encouraged to utilize the code in this repository in any way you wish.
+27 -177
View File
@@ -1,21 +1,5 @@
import java.nio.charset.StandardCharsets
// this build.gradle is tweaked from CCA: https://github.com/OnyxStudios/Cardinal-Components-API/blob/master/build.gradle
buildscript {
repositories {
mavenLocal()
jcenter()
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.0.1'
}
}
plugins { plugins {
id "fabric-loom" version "0.8-SNAPSHOT" id "fabric-loom" version "0.10-SNAPSHOT"
id "maven-publish" id "maven-publish"
id "java-library" id "java-library"
} }
@@ -26,216 +10,82 @@ archivesBaseName = "omega-config"
subprojects { subprojects {
apply plugin: 'fabric-loom' apply plugin: 'fabric-loom'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
apply plugin: 'java-library'
archivesBaseName = project.name archivesBaseName = project.name
group = "draylar.${project.group}" group = "draylar.${project.group}"
// import utility functions // Only publish for submodules (not the root project) - add standard jar, + sources & development jar
apply from: "https://raw.githubusercontent.com/NerdHubMC/Gradle-Scripts/master/scripts/utilities.gradle"
repositories {
mavenCentral()
}
compileJava {
options.encoding = StandardCharsets.UTF_8.name()
}
if (JavaVersion.current().isJava8Compatible()) {
allprojects {
tasks.withType(Javadoc) {
options.addStringOption("Xdoclint:none", "-quiet")
}
}
}
jar {
from "LICENSE.md"
from "LICENSE"
manifest.mainAttributes(
"Implementation-Title": project.archivesBaseName,
"Implementation-Version": mod_version,
"Maven-Artifact": "${project.group}:${project.name}:${mod_version}".toLowerCase(Locale.ROOT),
"Built-On-Minecraft": "${project.minecraft_version}",
"Built-On-Java": "${System.getProperty("java.vm.version")} (${System.getProperty("java.vm.vendor")})"
)
}
task sourcesJar(type: Jar, dependsOn: classes) {
from sourceSets.main.allSource
classifier = "sources"
}
task javadocJar(type: Jar, dependsOn: javadoc) {
from javadoc.destinationDir
classifier = "javadoc"
}
tasks.build.dependsOn javadocJar
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
artifact(remapJar) { from components.java
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
artifact(file("${project.buildDir}/libs/${archivesBaseName}-${project.mod_version}-min.jar")) {
builtBy(remapJar)
classifier = 'min'
}
pom.withXml {
def depsNode = asNode().appendNode("dependencies")
subprojects.each {
def depNode = depsNode.appendNode("dependency")
depNode.appendNode("groupId", it.group)
depNode.appendNode("artifactId", it.name)
depNode.appendNode("version", it.version)
depNode.appendNode("scope", "compile")
}
}
} }
} }
} }
tasks.publish.dependsOn build //stupid fix for maven/loom not publishing the main artifact // Add sources & javadoc artifacts
java {
task ('proguard', type: proguard.gradle.ProGuardTask) { withSourcesJar()
configuration './proguard.conf' withJavadocJar()
verbose
injars project.buildDir.toString() + '/libs/' + archivesBaseName + "-" + project.mod_version + ".jar"
outjars project.buildDir.toString() + '/libs/' + archivesBaseName + "-" + project.mod_version + "-min.jar"
printmapping 'out.map'
keepparameternames
renamesourcefileattribute 'SourceFile'
keepattributes 'Signature,Exceptions,InnerClasses,PermittedSubclasses,EnclosingMethod,Deprecated,SourceFile,LineNumberTable'
keepattributes '*Annotation*'
keep 'public class * { \
public protected *; \
}'
keepclassmembernames 'class * { \
java.lang.Class class$(java.lang.String); \
java.lang.Class class$(java.lang.String, boolean); \
}'
keepclassmembers 'class draylar.omegaconfig.mixin.* {\
<fields>;\
<init>();\
<methods>;\
}'
} }
remapJar.finalizedBy proguard
} }
allprojects { allprojects {
apply plugin: "fabric-loom" apply plugin: "fabric-loom"
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 version = project.mod_version + "-" + project.minecraft_version
version = System.getenv("TRAVIS_TAG") ?: project.mod_version
repositories { repositories {
maven { maven {
name = "FabricMC" name = "FabricMC"
url = "https://maven.fabricmc.net" url = "https://maven.fabricmc.net"
} }
maven { url = "https://maven.terraformersmc.com/releases/"}
} }
dependencies { dependencies {
//to change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}" minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modRuntime "com.terraformersmc:modmenu:1.16.8"
modCompileOnly "com.terraformersmc:modmenu:1.16.8"
} }
processResources { processResources {
// this will ensure that this task is redone when there"s a change inputs.property "version", project.version
inputs.property "version", mod_version
// replace stuff in fabric.mod.json, nothing else filesMatching("fabric.mod.json") {
from(sourceSets.main.resources.srcDirs) { expand "version": project.version
include "fabric.mod.json" }
// add mod metadata
expand "version": mod_version
} }
// copy everything else, that"s not the fabric.mod.json tasks.withType(JavaCompile) {
from(sourceSets.main.resources.srcDirs) { javadoc.options.addStringOption('Xdoclint:none', '-quiet')
exclude "fabric.mod.json"
}
} }
jar { jar {
from(rootProject.file("LICENSE.md")) { from(rootProject.file("LICENSE")) {
rename { "LICENSE_${project.archivesBaseName.replace('-', '_')}" } 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
}
}
sourceSets { sourceSets {
testmod { testmod {
compileClasspath += main.compileClasspath compileClasspath += main.compileClasspath
runtimeClasspath += main.runtimeClasspath runtimeClasspath += main.runtimeClasspath
} }
test { test {
compileClasspath += main.compileClasspath compileClasspath += main.compileClasspath
runtimeClasspath += main.runtimeClasspath runtimeClasspath += main.runtimeClasspath
} }
} }
task licenseFormatAll
subprojects { p -> licenseFormatAll.dependsOn("${p.path}:licenseFormat") }
subprojects.each { remapJar.dependsOn("${it.path}:remapJar") }
repositories {
maven {
name = "JitPack"
url = "https://jitpack.io"
}
}
dependencies {
implementation project(":omega-config-base")
implementation project(":omega-config-gui")
modRuntime "com.terraformersmc:modmenu:1.16.8"
modCompileOnly "com.terraformersmc:modmenu:1.16.8"
afterEvaluate {
testmodImplementation sourceSets.main.output
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(file("${project.buildDir}/libs/${archivesBaseName}-${project.mod_version}.jar")) {
builtBy(remapJar)
}
pom.withXml {
def depsNode = asNode().appendNode("dependencies")
subprojects.each {
def depNode = depsNode.appendNode("dependency")
depNode.appendNode("groupId", it.group)
depNode.appendNode("artifactId", it.name)
depNode.appendNode("version", it.version)
depNode.appendNode("scope", "compile")
}
}
}
}
}
tasks.publish.dependsOn build //stupid fix for maven/loom not publishing the main artifact
+9 -10
View File
@@ -1,17 +1,16 @@
# Done to increase the memory available to gradle. # Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G org.gradle.jvmargs=-Xmx2G
# Fabric Properties # Fabric Properties
# check these on https://modmuss50.me/fabric.html # check these on https://fabricmc.net/versions.html
minecraft_version=1.16.5 minecraft_version=1.18.1
yarn_mappings=1.16.5+build.5 yarn_mappings=1.18.1+build.2
loader_version=0.11.2 loader_version=0.12.11
#Fabric api
fabric_version=0.44.0+1.18
# Mod Properties # Mod Properties
mod_version=1.0.5 mod_version=1.2.1
maven_group=draylar maven_group=draylar
archives_base_name=omega-config archives_base_name=omega-config
# Dependencies modmenu_version=3.0.1
# check this on https://modmuss50.me/fabric.html
fabric_version=0.32.0+1.16
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
+4
View File
@@ -0,0 +1,4 @@
before_install:
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- source install-jdk.sh --feature 17
- jshell --version
-3
View File
@@ -1,3 +0,0 @@
-ignorewarnings
-keep class net.fabricmc.api.** { *; }
@@ -4,14 +4,14 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import draylar.omegaconfig.api.Comment; import draylar.omegaconfig.api.Comment;
import draylar.omegaconfig.api.Config; import draylar.omegaconfig.api.Config;
import draylar.omegaconfig.exception.NoValidConstructorException;
import draylar.omegaconfig.gson.SyncableExclusionStrategy; import draylar.omegaconfig.gson.SyncableExclusionStrategy;
import io.netty.buffer.Unpooled; 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.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtList;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@@ -24,25 +24,29 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class OmegaConfig { public class OmegaConfig implements ModInitializer {
private static final Logger LOGGER = LogManager.getLogger();
private static final List<Config> REGISTERED_CONFIGURATIONS = new ArrayList<>();
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Identifier CONFIG_SYNC_PACKET = new Identifier("omegaconfig", "sync"); 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 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<>();
static { @Override
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { public void onInitialize() {
server.execute(() -> { ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> server.execute(() -> {
PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer()); PacketByteBuf packet = new PacketByteBuf(Unpooled.buffer());
// list of configurations that are synced // list of configurations that are synced
CompoundTag root = new CompoundTag(); NbtCompound root = new NbtCompound();
ListTag configurations = new ListTag(); NbtList configurations = new NbtList();
// Iterate over each configuration. // Iterate over each configuration.
// Find values that should be synced and send the value over. // Find values that should be synced and send the value over.
@@ -54,10 +58,9 @@ public class OmegaConfig {
// save to packet and send to user // save to packet and send to user
root.put("Configurations", configurations); root.put("Configurations", configurations);
packet.writeCompoundTag(root); packet.writeNbt(root);
handler.sendPacket(ServerPlayNetworking.createS2CPacket(CONFIG_SYNC_PACKET, packet)); handler.sendPacket(ServerPlayNetworking.createS2CPacket(CONFIG_SYNC_PACKET, packet));
}); }));
});
} }
public static <T extends Config> T register(Class<T> configClass) { public static <T extends Config> T register(Class<T> configClass) {
@@ -70,7 +73,7 @@ public class OmegaConfig {
// 1. serialize to disk if the config does not already exist // 1. serialize to disk if the config does not already exist
// 2. read from disk if it does exist // 2. read from disk if it does exist
if (!configExists(config)) { if (!configExists(config)) {
writeConfig(configClass, config); config.save();
REGISTERED_CONFIGURATIONS.add(config); REGISTERED_CONFIGURATIONS.add(config);
} else { } else {
try { try {
@@ -82,7 +85,7 @@ public class OmegaConfig {
T object = GSON.fromJson(res.toString(), configClass); T object = GSON.fromJson(res.toString(), configClass);
// re-write the config to add new values // re-write the config to add new values
writeConfig(configClass, object); object.save();
REGISTERED_CONFIGURATIONS.add(object); REGISTERED_CONFIGURATIONS.add(object);
return object; return object;
} catch (Exception e) { } catch (Exception e) {
@@ -95,7 +98,7 @@ public class OmegaConfig {
return config; return config;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) { } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
exception.printStackTrace(); exception.printStackTrace();
throw new NoValidConstructorException(); throw new RuntimeException("No valid constructor found for: " + configClass.getName());
} }
} }
@@ -113,10 +116,9 @@ public class OmegaConfig {
addFieldComments(field, keyToComments); addFieldComments(field, keyToComments);
} }
// get inner-class fields // "flattens" all the inner classes of the Config class into a single list
// TODO: recursively get inner classes? for (Class<?> clazz : flatten(configClass.getDeclaredClasses())) {
for(Class<?> innerClass : configClass.getDeclaredClasses()) { for (Field field : clazz.getDeclaredFields()) {
for(Field field : innerClass.getDeclaredFields()) {
addFieldComments(field, keyToComments); addFieldComments(field, keyToComments);
} }
} }
@@ -124,14 +126,18 @@ public class OmegaConfig {
// Find areas we should insert comments into... // Find areas we should insert comments into...
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
String at = lines.get(i); String at = lines.get(i);
String startingWhitespace = getStartingWhitespace(at);
// Check if we should insert comment
for (Map.Entry<String, String> entry : keyToComments.entrySet()) { for (Map.Entry<String, String> entry : keyToComments.entrySet()) {
String key = entry.getKey();
String comment = entry.getValue(); String comment = entry.getValue();
// Check if we should insert comment
if (at.trim().startsWith(String.format("\"%s\"", key))) { if (at.trim().startsWith(String.format("\"%s\"", entry.getKey()))) {
insertions.put(i + insertions.size(), String.format("%s//%s", getStartingWhitespace(at), comment)); if (comment.contains("\n")) {
comment = startingWhitespace + "//" + String.join(String.format("\n%s//", startingWhitespace), comment.split("\n"));
} else {
comment = String.format("%s//%s", startingWhitespace, comment);
}
insertions.put(i + insertions.size(), comment);
break; break;
} }
} }
@@ -154,7 +160,29 @@ public class OmegaConfig {
Files.write(configPath, res.toString().getBytes()); Files.write(configPath, res.toString().getBytes());
} catch (IOException ioException) { } catch (IOException ioException) {
LOGGER.error(ioException); LOGGER.error(ioException);
LOGGER.info(String.format("Write error, using default values for config %s.", configClass.toString())); LOGGER.info(String.format("Write error, using default values for config %s.", configClass));
}
}
public static List<Class<?>> flatten(Class<?>[] array) {
List<Class<?>> list = new ArrayList<>();
for (Class<?> clazz : array) {
populateRecursively(list, clazz);
}
return list;
}
private static void populateRecursively(List<Class<?>> list, Class<?> aClass) {
list.add(aClass);
Class<?>[] classes = aClass.getDeclaredClasses();
if (classes.length != 0) {
for (Class<?> clazz : classes) {
populateRecursively(list, clazz);
}
} }
} }
@@ -1,7 +1,7 @@
package draylar.omegaconfig.api; package draylar.omegaconfig.api;
import draylar.omegaconfig.OmegaConfig; import draylar.omegaconfig.OmegaConfig;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtCompound;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
@@ -16,8 +16,8 @@ public interface Config {
OmegaConfig.writeConfig((Class<Config>) getClass(), this); OmegaConfig.writeConfig((Class<Config>) getClass(), this);
} }
default CompoundTag writeSyncingTag() { default NbtCompound writeSyncingTag() {
CompoundTag tag = new CompoundTag(); NbtCompound tag = new NbtCompound();
tag.putString("ConfigName", getName()); tag.putString("ConfigName", getName());
// all config vs. individual fields // all config vs. individual fields
@@ -67,7 +67,7 @@ public interface Config {
* modids for configuration screen instances in their menu. * modids for configuration screen instances in their menu.
* If you are intending for this config to have a ModMenu config * If you are intending for this config to have a ModMenu config
* screen, this method should return the modid specified in your fabric.mod.json. * screen, this method should return the modid specified in your fabric.mod.json.
* * <p>
* If this method is not overridden, null will be returned, which * If this method is not overridden, null will be returned, which
* means this config is not explicitly associated with any particular mod. * means this config is not explicitly associated with any particular mod.
* *
@@ -99,7 +99,7 @@ public interface Config {
* By default, a config such as 'my_config' will appear at /config/my_config.json. * By default, a config such as 'my_config' will appear at /config/my_config.json.
* If this method specifies a directory, such as 'configurations', * If this method specifies a directory, such as 'configurations',
* the config file will appear at /config/configurations/my_config.json. * the config file will appear at /config/configurations/my_config.json.
* * <p>
* Nested directories can be specified by using a string such as 'configurations/client'. * Nested directories can be specified by using a string such as 'configurations/client'.
* *
* @return the directory of this config * @return the directory of this config
@@ -1,5 +0,0 @@
package draylar.omegaconfig.exception;
public class NoValidConstructorException extends RuntimeException {
}
@@ -3,13 +3,12 @@ package draylar.omegaconfig.mixin;
import draylar.omegaconfig.OmegaConfig; import draylar.omegaconfig.OmegaConfig;
import draylar.omegaconfig.api.Config; import draylar.omegaconfig.api.Config;
import draylar.omegaconfig.api.Syncing; import draylar.omegaconfig.api.Syncing;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.util.NbtType; import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.RunArgs; import net.minecraft.client.RunArgs;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.ListTag;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -31,15 +30,15 @@ public class ClientMixin {
method = "<init>", method = "<init>",
at = @At("RETURN")) at = @At("RETURN"))
private void onReturn(RunArgs args, CallbackInfo ci) { private void onReturn(RunArgs args, CallbackInfo ci) {
ClientSidePacketRegistry.INSTANCE.register(OmegaConfig.CONFIG_SYNC_PACKET, (context, buffer) -> { ClientPlayNetworking.registerGlobalReceiver(OmegaConfig.CONFIG_SYNC_PACKET, (client, handler, buf, responseSender) -> {
CompoundTag tag = buffer.readCompoundTag(); NbtCompound tag = buf.readNbt();
savedClientConfig.clear(); savedClientConfig.clear();
context.getTaskQueue().execute(() -> { client.execute(() -> {
if (tag != null && tag.contains("Configurations")) { if (tag != null && tag.contains("Configurations")) {
ListTag list = tag.getList("Configurations", NbtType.COMPOUND); NbtList list = tag.getList("Configurations", NbtType.COMPOUND);
list.forEach(compound -> { list.forEach(compound -> {
CompoundTag syncedConfiguration = (CompoundTag) compound; NbtCompound syncedConfiguration = (NbtCompound) compound;
String name = syncedConfiguration.getString("ConfigName"); String name = syncedConfiguration.getString("ConfigName");
String json = syncedConfiguration.getString("Serialized"); String json = syncedConfiguration.getString("Serialized");
boolean allSync = syncedConfiguration.getBoolean("AllSync"); boolean allSync = syncedConfiguration.getBoolean("AllSync");
@@ -79,7 +78,7 @@ public class ClientMixin {
@Inject( @Inject(
method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V",
at = @At("RETURN")) at = @At("RETURN"))
private void restoreConfigurations(Screen screen, CallbackInfo ci) { private void restoreConfigurations(CallbackInfo ci) {
for (Config config : savedClientConfig) { for (Config config : savedClientConfig) {
for (Config potentiallySynced : OmegaConfig.getRegisteredConfigurations()) { for (Config potentiallySynced : OmegaConfig.getRegisteredConfigurations()) {
if (config.getName().equals(potentiallySynced.getName())) { if (config.getName().equals(potentiallySynced.getName())) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

@@ -1,13 +1,23 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "omega-config", "id": "omega-config",
"version": "${version}", "version": "1.1.0",
"name": "OmegaConfig", "name": "OmegaConfig",
"description": "The last config solution you will ever use.", "description": "The last config solution you will ever use.",
"authors": [ "authors": [
"Draylar" "Draylar",
"Frqnny"
], ],
"contact": {}, "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"
},
"license": "MIT", "license": "MIT",
"environment": "*", "environment": "*",
"mixins": [ "mixins": [
@@ -17,5 +27,10 @@
"fabricloader": "*", "fabricloader": "*",
"fabric": "*", "fabric": "*",
"minecraft": "*" "minecraft": "*"
},
"custom": {
"modmenu": {
"badges": [ "library" ]
}
} }
} }
@@ -2,9 +2,8 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "draylar.omegaconfig.mixin", "package": "draylar.omegaconfig.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_16",
"mixins": [ "mixins": [
], ],
"client": [ "client": [
"ClientMixin" "ClientMixin"
+26
View File
@@ -1,3 +1,29 @@
repositories {
maven {
name = "Shedaniel's Maven"
url = "https://maven.shedaniel.me/"
}
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/releases/"
}
}
dependencies { dependencies {
implementation project(":omega-config-base") 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"
}
} }
-3
View File
@@ -1,3 +0,0 @@
-ignorewarnings
-keep class net.fabricmc.api.** { *; }
@@ -1,23 +1,98 @@
package draylar.omegaconfiggui; package draylar.omegaconfiggui;
import draylar.omegaconfig.OmegaConfig;
import draylar.omegaconfig.api.Config; import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.api.screen.ModMenuHelper; import draylar.omegaconfiggui.api.screen.OmegaModMenu;
import draylar.omegaconfiggui.api.screen.OmegaConfigScreen; import draylar.omegaconfiggui.api.screen.OmegaScreenFactory;
import me.shedaniel.clothconfiglite.api.ConfigScreen;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader; 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) @Environment(EnvType.CLIENT)
public class OmegaConfigGui { 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. * Registers a ModMenu configuration screen for the given {@link Config} instance.
*
* @param config registered config to create a ModMenu screen for * @param config registered config to create a ModMenu screen for
* @param <T> config type * @param <T> config type
*/ */
public static <T extends Config> void registerConfigScreen(T config) { public static <T extends Config> void registerConfigScreen(T config) {
if(FabricLoader.getInstance().isModLoaded("modmenu")) { if(FabricLoader.getInstance().isModLoaded("modmenu")) {
ModMenuHelper.injectScreen(config, parent -> new OmegaConfigScreen<>(config, parent)); // Ensure the config has a valid modid.
if(config.getModid() != null) {
OmegaScreenFactory<Screen> factory = OmegaConfigGui.getConfigScreenFactory(config);
if(modMenuInitialized) {
OmegaModMenu.injectScreen(config, factory);
} else {
REGISTERED_CONFIGURATIONS.put(config, factory);
}
} else {
OmegaConfig.LOGGER.warn(String.format("Skipping config screen registration for '%s' - you must implement getModid() in your config class!", config.getName()));
} }
} }
} }
/**
* 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,141 +0,0 @@
package draylar.omegaconfiggui.api.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.api.screen.widget.LabelWidget;
import draylar.omegaconfiggui.api.screen.widget.TypeWidgets;
import draylar.omegaconfiggui.api.screen.widget.WidgetSupplier;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class OmegaConfigScreen<T extends Config> extends Screen {
private static final List<Class<?>> validClasses = Arrays.asList(Double.class, String.class, Boolean.class);
private final T config;
private final Screen parent;
private final Map<Field, Pair<WidgetSupplier<Object, AbstractButtonWidget>, AbstractButtonWidget>> fieldWidgets = new HashMap<>();
public OmegaConfigScreen(T config, Screen parent) {
super(new LiteralText(""));
this.config = config;
this.parent = parent;
}
@Override
public void init() {
super.init();
try {
// add label & button for each config entry
// TODO: SUB-CLASS SUPPORT
List<Field> collect = Arrays.stream(config.getClass().getDeclaredFields()).filter(field -> validClasses.contains(TypeWidgets.unbox(field.getType()))).collect(Collectors.toList());
int over = 0;
for (Field field : collect) {
Class<?> unbox = TypeWidgets.unbox(field.getType());
// label
addChild(new LabelWidget(150, 15 + height / 6 + 20 * over, new LiteralText(field.getName())));
// get value
field.setAccessible(true);
Object value = field.get(config);
// button / interact
AbstractButtonWidget button;
WidgetSupplier<Object, AbstractButtonWidget> widgetSupplier = (WidgetSupplier<Object, AbstractButtonWidget>) TypeWidgets.get(unbox);
if(widgetSupplier != null) {
button = widgetSupplier.create(this,250, 5 + height / 6 + 25 * over, 100, 20, new LiteralText(field.getName()), value);
} else {
button = new TextFieldWidget(client.textRenderer, 250, 5 + height / 6 + 25 * over, 100, 20, new LiteralText(field.getName()));
}
fieldWidgets.put(field, new Pair<>(widgetSupplier, button));
addButton(button);
over++;
}
} catch (Exception e) {
e.printStackTrace();
}
// save and exit
ButtonWidget exit = new ButtonWidget(width - 60, height - 30, 50, 20, new LiteralText("Exit"), widget -> onClose());
ButtonWidget save = new ButtonWidget(10, height - 30, 50, 20, new LiteralText("Save"), widget -> {
fieldWidgets.forEach((field, pair) -> {
try {
field.set(config, pair.getLeft().get(pair.getRight()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
config.save();
});
addButton(save);
addButton(exit);
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
renderBackground(matrices);
for (AbstractButtonWidget button : this.buttons) {
button.render(matrices, mouseX, mouseY, delta);
}
for (Element element : this.children) {
if (element instanceof Drawable && !buttons.contains(element)) {
((Drawable) element).render(matrices, mouseX, mouseY, delta);
}
}
}
@Override
public void onClose() {
client.openScreen(parent);
}
@Override
public void renderBackground(MatrixStack matrices) {
// TODO: option for transparent BG
// this.fillGradient(matrices, 0, 0, this.width, this.height, -1072689136, -804253680);
renderCustomBackgroundTexture(0, 64, 64, 64, 0, 0, this.height, this.width);
renderCustomBackgroundTexture(0, 32, 32, 32, 0, this.height / 8, this.height / 8 * 6, this.width);
textRenderer.draw(matrices, config.getName(), width / 2f - textRenderer.getWidth(config.getName()) / 2f, 10, 0xffffff);
}
public void renderCustomBackgroundTexture(int vOffset, int r, int g, int b, int x, int y, int height, int width) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
this.client.getTextureManager().bindTexture(OPTIONS_BACKGROUND_TEXTURE);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
bufferBuilder.begin(7, VertexFormats.POSITION_TEXTURE_COLOR);
bufferBuilder.vertex(x, height + y, 0.0D).texture(0.0F, (float)height / 32.0F + (float)vOffset).color(r, g, b, 255).next();
bufferBuilder.vertex(width + x, height + y, 0.0D).texture((float)width / 32.0F, (float)height / 32.0F + (float)vOffset).color(r, g, b, 255).next();
bufferBuilder.vertex(width + x, y, 0.0D).texture((float)width / 32.0F, (float)vOffset).color(r, g, b, 255).next();
bufferBuilder.vertex(x, y, 0.0D).texture(0.0F, (float)vOffset).color(r, g, b, 255).next();
tessellator.draw();
}
}
@@ -1,8 +0,0 @@
package draylar.omegaconfiggui.api.screen;
import draylar.omegaconfig.api.Config;
import net.minecraft.client.gui.screen.Screen;
public interface OmegaConfigScreenSupplier<T extends Config> {
OmegaConfigScreen<T> get(Screen parent);
}
@@ -3,14 +3,15 @@ package draylar.omegaconfiggui.api.screen;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import draylar.omegaconfig.api.Config; import draylar.omegaconfig.api.Config;
import draylar.omegaconfiggui.mixin.ModMenuAccessor; import draylar.omegaconfiggui.mixin.modmenu.ModMenuAccessor;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.Screen;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class ModMenuHelper { public class OmegaModMenu {
public static <T extends Config> void injectScreen(T config, OmegaConfigScreenSupplier<T> factory) { public static <T extends Config> void injectScreen(T config, OmegaScreenFactory<Screen> factory) {
// they will suspect nothing // they will suspect nothing
ModMenuAccessor.setConfigScreenFactories( ModMenuAccessor.setConfigScreenFactories(
new ImmutableMap.Builder<String, ConfigScreenFactory<?>>() new ImmutableMap.Builder<String, ConfigScreenFactory<?>>()
@@ -0,0 +1,10 @@
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,30 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget;
import draylar.omegaconfiggui.mixin.AbstractButtonWidgetAccessor;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.Text;
public class BaseTextFieldWidget extends TextFieldWidget {
protected final Screen parent;
public BaseTextFieldWidget(Screen parent, TextRenderer textRenderer, int x, int y, int width, int height, Text text) {
super(textRenderer, x, y, width, height, text);
this.parent = parent;
}
@Override
public void setTextFieldFocused(boolean focused) {
// unfocus all others
parent.children().forEach(element -> {
if(element instanceof AbstractButtonWidget) {
((AbstractButtonWidgetAccessor) element).callSetFocused(false);
}
});
super.setFocused(focused);
}
}
@@ -1,27 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
public class DoubleFieldWidget extends BaseTextFieldWidget {
public DoubleFieldWidget(Screen parent, TextRenderer textRenderer, int x, int y, int width, int height, Text text) {
super(parent, textRenderer, x, y, width, height, text);
}
@Override
public void write(String string) {
try {
if(string.equals(".") && !getText().contains(".")) {
super.write(string);
} else {
Double.parseDouble(string);
super.write(string);
}
} catch(NumberFormatException ignored) {
}
}
}
@@ -1,26 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.Element;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
public class LabelWidget extends DrawableHelper implements Drawable, Element {
private final int x;
private final int y;
private final Text message;
public LabelWidget(int x, int y, Text message) {
this.x = x;
this.y = y;
this.message = message;
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
drawTextWithShadow(matrices, MinecraftClient.getInstance().textRenderer, message, x, y, 0xffffff);
}
}
@@ -1,45 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget;
import draylar.omegaconfiggui.api.screen.widget.supplier.BooleanWidgetSupplier;
import draylar.omegaconfiggui.api.screen.widget.supplier.DoubleWidgetSupplier;
import draylar.omegaconfiggui.api.screen.widget.supplier.StringWidgetSupplier;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class TypeWidgets {
public static final Map<Class<?>, WidgetSupplier<?, ?>> CLASS_WIDGETS = new HashMap<>();
public static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED = new HashMap<>();
static {
CLASS_WIDGETS.put(Double.class, new DoubleWidgetSupplier());
CLASS_WIDGETS.put(Boolean.class, new BooleanWidgetSupplier());
CLASS_WIDGETS.put(String.class, new StringWidgetSupplier());
// primitive -> boxed
PRIMITIVE_TO_BOXED.put(boolean.class, Boolean.class);
PRIMITIVE_TO_BOXED.put(byte.class, Byte.class);
PRIMITIVE_TO_BOXED.put(char.class, Character.class);
PRIMITIVE_TO_BOXED.put(double.class, Double.class);
PRIMITIVE_TO_BOXED.put(float.class, Float.class);
PRIMITIVE_TO_BOXED.put(int.class, Integer.class);
PRIMITIVE_TO_BOXED.put(long.class, Long.class);
PRIMITIVE_TO_BOXED.put(short.class, Short.class);
PRIMITIVE_TO_BOXED.put(void.class, Void.class);
}
@Nullable
public static <T> WidgetSupplier<T, ?> get(Class<T> typeClass) {
return (WidgetSupplier<T, ?>) CLASS_WIDGETS.get(unbox(typeClass));
}
public static Class<?> unbox(Class<?> c) {
return PRIMITIVE_TO_BOXED.getOrDefault(c, c);
}
private TypeWidgets() {
// NO-OP
}
}
@@ -1,10 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.text.LiteralText;
public interface WidgetSupplier<T, A extends AbstractButtonWidget> {
AbstractButtonWidget create(Screen parent, int x, int y, int width, int height, LiteralText prompt, T value);
T get(A widget);
}
@@ -1,19 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget.supplier;
import draylar.omegaconfiggui.api.screen.widget.WidgetSupplier;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.CheckboxWidget;
import net.minecraft.text.LiteralText;
public class BooleanWidgetSupplier implements WidgetSupplier<Boolean, CheckboxWidget> {
@Override
public CheckboxWidget create(Screen parent, int x, int y, int width, int height, LiteralText prompt, Boolean value) {
return new CheckboxWidget(x, y, 20, 20, new LiteralText(""), value);
}
@Override
public Boolean get(CheckboxWidget widget) {
return widget.isChecked();
}
}
@@ -1,35 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget.supplier;
import draylar.omegaconfiggui.api.screen.widget.DoubleFieldWidget;
import draylar.omegaconfiggui.api.screen.widget.WidgetSupplier;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.LiteralText;
public class DoubleWidgetSupplier implements WidgetSupplier<Double, DoubleFieldWidget> {
@Override
public DoubleFieldWidget create(Screen parent, int x, int y, int width, int height, LiteralText prompt, Double value) {
LiteralText text = new LiteralText(String.valueOf(value));
DoubleFieldWidget widget = new DoubleFieldWidget(parent, MinecraftClient.getInstance().textRenderer, x, y, width, height, text);
widget.setText(text.asString());
return widget;
}
@Override
public Double get(DoubleFieldWidget widget) {
String message = widget.getText();
// if it is just a . or empty, return 0
if(message.equals(".") || message.isEmpty()) {
return 0.0;
}
// trim potential trailing .
if(message.indexOf(".") == message.length()) {
message = message.substring(0, message.length() - 1);
}
return Double.parseDouble(message);
}
}
@@ -1,25 +0,0 @@
package draylar.omegaconfiggui.api.screen.widget.supplier;
import draylar.omegaconfiggui.api.screen.widget.BaseTextFieldWidget;
import draylar.omegaconfiggui.api.screen.widget.WidgetSupplier;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.LiteralText;
public class StringWidgetSupplier implements WidgetSupplier<String, TextFieldWidget> {
@Override
public TextFieldWidget create(Screen parent, int x, int y, int width, int height, LiteralText prompt, String value) {
LiteralText text = new LiteralText(value);
TextFieldWidget textField = new BaseTextFieldWidget(parent, MinecraftClient.getInstance().textRenderer, x, y, width, height, text);
textField.setText(value);
return textField;
}
@Override
public String get(TextFieldWidget widget) {
return widget.getText();
}
}
@@ -1,11 +0,0 @@
package draylar.omegaconfiggui.mixin;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(AbstractButtonWidget.class)
public interface AbstractButtonWidgetAccessor {
@Invoker
void callSetFocused(boolean focused);
}
@@ -0,0 +1,24 @@
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);
}
}
@@ -0,0 +1,51 @@
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,20 +1,24 @@
package draylar.omegaconfiggui.mixin; package draylar.omegaconfiggui.mixin.modmenu;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.terraformersmc.modmenu.ModMenu; import com.terraformersmc.modmenu.ModMenu;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; 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.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
@Environment(EnvType.CLIENT)
@Mixin(ModMenu.class) @Mixin(ModMenu.class)
public interface ModMenuAccessor { public interface ModMenuAccessor {
@Accessor @Accessor
static ImmutableMap<String, ConfigScreenFactory<?>> getConfigScreenFactories() { static ImmutableMap<String, ConfigScreenFactory<?>> getConfigScreenFactories() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Accessor @Accessor
static void setConfigScreenFactories(ImmutableMap<String, ConfigScreenFactory<?>> configScreenFactories) { static void setConfigScreenFactories(ImmutableMap<String, ConfigScreenFactory<?>> factories) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

@@ -2,12 +2,16 @@
"schemaVersion": 1, "schemaVersion": 1,
"id": "omega-config-gui", "id": "omega-config-gui",
"version": "${version}", "version": "${version}",
"name": "OmegaConfigGui", "name": "Omega Config GUI",
"description": "GUI support for Omega Config.", "description": "GUI support for Omega Config.",
"authors": [ "authors": [
"Draylar" "Draylar"
], ],
"contact": {}, "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", "license": "MIT",
"environment": "*", "environment": "*",
"mixins": [ "mixins": [
@@ -17,5 +21,13 @@
"fabricloader": "*", "fabricloader": "*",
"fabric": "*", "fabric": "*",
"minecraft": "*" "minecraft": "*"
},
"recommends": {
"modmenu": "3.0.1"
},
"custom": {
"modmenu": {
"badges": [ "library" ]
}
} }
} }
@@ -2,12 +2,11 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "draylar.omegaconfiggui.mixin", "package": "draylar.omegaconfiggui.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_17",
"mixins": [ "plugin": "draylar.omegaconfiggui.mixin.OmegaConfigMixinPlugin",
"AbstractButtonWidgetAccessor",
"ModMenuAccessor"
],
"client": [ "client": [
"modmenu.ModMenuAccessor",
"ModMenuMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
-3
View File
@@ -1,3 +0,0 @@
-ignorewarnings
-keep class net.fabricmc.api.** { *; }
@@ -2,9 +2,10 @@ package draylar.omegatest;
import draylar.omegaconfig.OmegaConfig; import draylar.omegaconfig.OmegaConfig;
import draylar.omegatest.config.ClassConfigTest; import draylar.omegatest.config.ClassConfigTest;
import draylar.omegatest.config.CommentedNestedClassConfig;
import draylar.omegatest.config.NestedConfigTest; import draylar.omegatest.config.NestedConfigTest;
import draylar.omegatest.config.StructuresConfigTest;
import draylar.omegatest.config.SimpleConfigTest; import draylar.omegatest.config.SimpleConfigTest;
import draylar.omegatest.config.StructuresConfigTest;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class OmegaTestMain implements ModInitializer { public class OmegaTestMain implements ModInitializer {
@@ -13,6 +14,7 @@ public class OmegaTestMain implements ModInitializer {
public static final StructuresConfigTest MO_CONFIG = OmegaConfig.register(StructuresConfigTest.class); public static final StructuresConfigTest MO_CONFIG = OmegaConfig.register(StructuresConfigTest.class);
public static final NestedConfigTest NESTED = OmegaConfig.register(NestedConfigTest.class); public static final NestedConfigTest NESTED = OmegaConfig.register(NestedConfigTest.class);
public static final ClassConfigTest CLASS = OmegaConfig.register(ClassConfigTest.class); public static final ClassConfigTest CLASS = OmegaConfig.register(ClassConfigTest.class);
public static final CommentedNestedClassConfig COMMENTED_NESTED_CLASS = OmegaConfig.register(CommentedNestedClassConfig.class);
@Override @Override
public void onInitialize() { public void onInitialize() {
@@ -0,0 +1,73 @@
package draylar.omegatest.config;
import draylar.omegaconfig.api.Comment;
import draylar.omegaconfig.api.Config;
public class CommentedNestedClassConfig implements Config {
@Comment("Very nested test")
public First first = new First();
@Comment("True")
public boolean test = false;
@Comment("First-Level")
public VeryNested veryNested = new VeryNested();
public static class First {
@Comment("Cucumbers")
public boolean cucumbers = true;
@Comment("InnerFirst")
public InnerFirst innerFirst = new InnerFirst();
@Comment("InnerSecond")
public InnerSecond innerSecond = new InnerSecond();
public static class InnerFirst {
@Comment("Number of Tomatoes")
public int numberOfTomatoes = 10;
}
public static class InnerSecond {
@Comment("Inner Second First")
public InnerSecondFirst innerSecondFirst = new InnerSecondFirst();
public static class InnerSecondFirst {
@Comment("Olive Oil")
public String oliveOil = "oliveOil";
}
}
}
public static class VeryNested {
@Comment("Second-Level")
public Very very = new Very();
public static class Very {
@Comment("Third-Level")
public VeryVery veryVery = new VeryVery();
public static class VeryVery {
@Comment("Forth-Level")
public VeryVeryVery veryVeryVery = new VeryVeryVery();
public static class VeryVeryVery {
@Comment("Fifth-Level")
public VeryVeryVeryVery veryVeryVeryVery = new VeryVeryVeryVery();
public static class VeryVeryVeryVery {
@Comment("Sixth-Level")
public String last = "last";
}
}
}
}
}
@Override
public String getName() {
return "commented-inner-classes";
}
@Override
public String getExtension() {
return "json5";
}
}
@@ -19,12 +19,6 @@ public class SimpleConfigTest implements Config {
@Comment(value = "This is an inner static class.") @Comment(value = "This is an inner static class.")
public Test test = new Test(); public Test test = new Test();
public static class Test {
@Comment(value = "This is the value inside the class!")
public boolean innerTest = false;
}
@Override @Override
public String getName() { public String getName() {
return "test-config"; return "test-config";
@@ -34,4 +28,10 @@ public class SimpleConfigTest implements Config {
public @Nullable String getModid() { public @Nullable String getModid() {
return "omega-config-test"; return "omega-config-test";
} }
public static class Test {
@Comment(value = "This is the value inside the class!")
public boolean innerTest = false;
}
} }
@@ -0,0 +1,42 @@
package draylar.omegatest.config;
import java.util.Map;
public class StructureConfigEntry {
public final boolean activated;
public final int separation;
public final int spacing;
public final int salt;
private StructureConfigEntry(int separation, int spacing, int salt) {
this.activated = true;
this.spacing = spacing;
this.separation = separation;
this.salt = salt;
}
public static StructureConfigEntry of(int separation, int spacing, int salt) {
return new StructureConfigEntry(separation, spacing, salt);
}
public static void computeConfigMap(Map<String, StructureConfigEntry> map) {
map.computeIfAbsent("abandoned_church", (id) -> of(14, 38, 66996840));
map.computeIfAbsent("barn_house", (id) -> of(8, 38, 165757306));
map.computeIfAbsent("big_pyramid", (id) -> of(5, 25, 239284294));
map.computeIfAbsent("jungle_pyramid", (id) -> of(5, 25, 312178642));
map.computeIfAbsent("the_castle_in_the_sky", (id) -> of(8, 30, 423494938));
map.computeIfAbsent("killer_bunny_castle", (id) -> of(25, 45, 48123900));
map.computeIfAbsent("villager_tower", (id) -> of(16, 34, 550292492));
map.computeIfAbsent("villager_market", (id) -> of(16, 36, 784939542));
map.computeIfAbsent("pillager_factory", (id) -> of(16, 36, 839204924));
map.computeIfAbsent("ice_tower", (id) -> of(8, 28, 964058305));
map.computeIfAbsent("tavern", (id) -> of(12, 32, 19296726));
map.computeIfAbsent("pirate_ship", (id) -> of(16, 40, 583957395));
map.computeIfAbsent("lighthouse", (id) -> of(16, 32, 29502322));
map.computeIfAbsent("volcanic_vent", (id) -> of(4, 8, 84981094));
map.computeIfAbsent("moai", (id) -> of(4, 8, 12994829));
map.computeIfAbsent("air_balloon", (id) -> of(1, 6, 29483148));
}
}
@@ -2,130 +2,57 @@ package draylar.omegatest.config;
import draylar.omegaconfig.api.Comment; import draylar.omegaconfig.api.Comment;
import draylar.omegaconfig.api.Config; import draylar.omegaconfig.api.Config;
import net.minecraft.util.Identifier;
import java.util.HashMap;
import java.util.Map;
//taken straight out of Mo' Structures
public class StructuresConfigTest implements Config { public class StructuresConfigTest implements Config {
@Comment("Mo' Structures feature toggles.")
public Features features = new Features();
@Comment("Chances are once per the number of chunks. A Chance 500 makes a feature spawn every 500 chunks. Affected by biomes it spawns in and the chunk, so not all are proportional.") @Comment("""
public FeatureChances feature_chances = new FeatureChances(); Welcome to Mo'Structures Config!
@Comment("Structure toggles. These do not have chances, but in the future they may. ") Here, you can turn off structures, change their chance, and also change their salt.
public Structures structures = new Structures();
@Comment("Structure chances. Seperation is the least amount of chunks that a structure will spawn from itself. Spacing is the maximum amount of chunks, and both are used to randomly spawn structures and can be tweaked.") To turn off a structure, simply go to the corresponding entry and set `activated` to false.
public StructureChances structureChances = new StructureChances();
Mo' Structures uses the vanilla structure spawning system. That is-
- Seperation is the minimum chunks between structures
- Spacing is the average chunks between structures
Salt is a special field that gives structures unique spawning positions. DO NOT TOUCH IT, ONLY ADVANCED TROUBLESHOOTING!
""")
public final Map<String, StructureConfigEntry> structureConfigEntries = new HashMap<>(17);
@Override @Override
public String getName() { public String getName() {
return "mostructures-config-v2"; return "mostructures-config-v2";
} }
public static class Features {
@Comment("Airplanes & Air Balloons")
public boolean air_features = true;
@Comment("Fallen Trees")
public boolean fallen_trees = true;
@Comment("Desert Features")
public boolean desert_features = true;
@Comment("Ruins")
public boolean ruins = true;
@Comment("Lamppost")
public boolean lamppost = true;
@Comment("Boulder")
public boolean boulder = true;
@Comment("Volcanic Vent")
public boolean volcanic_vent = true;
@Comment("Beach Features")
public boolean beach_features = true;
@Comment("Boats")
public boolean boats = true;
}
public static class FeatureChances {
@Comment("Airplanes & Air Balloons")
public int air_feature_chance = 4600;
@Comment("Fallen Trees")
public int fallen_trees_chance = 17;
@Comment("Desert Features")
public int desert_features_chance = 555;
@Comment("Ruins")
public int ruins_chance = 3500;
@Comment("Lamppost")
public int lamppost_chance = 100;
@Comment("Boulder")
public int boulder_chance = 4000;
@Comment("Volcanic Vent")
public int volcanic_vent_chance = 85;
@Comment("Beach Features")
public int beach_features_chance = 75;
@Comment("Boats")
public int boats_chance = 4000;
}
public static class Structures {
@Comment("Barnhouse")
public boolean barn_house = true;
@Comment("Jungle Pyramid")
public boolean jungle_pyramid = true;
@Comment("Big Pyramid")
public boolean big_pyramid = true;
@Comment("The Castle In The Sky")
public boolean the_castle_in_the_sky = true;
@Comment("Villager Tower")
public boolean villager_tower = true;
@Comment("Abandoned Churches")
public boolean abandoned_churches = true;
@Comment("Villager Market")
public boolean villager_market = true;
@Comment("Pillager Factory")
public boolean pillager_factory = true;
@Comment("Ice Tower")
public boolean ice_tower = true;
@Comment("Boar Hat Tavern")
public boolean tavern = true;
@Comment("Killer Bunny Castle")
public boolean killer_bunny_castle = true;
}
public static class StructureChances {
@Comment("Barn House")
public int barn_house_seperation = 16;
public int barn_house_spacing = 40;
@Comment("Big Pyramid")
public int big_pyramid_seperation = 5;
public int big_pyramid_spacing = 25;
@Comment("Jungle Pyramid")
public int jungle_pyramid_seperation = 5;
public int jungle_pyramid_spacing = 25;
@Comment("The Castle In The Sky")
public int the_castle_in_the_sky_seperation = 8;
public int the_castle_in_the_sky_spacing = 32;
@Comment("Villager Tower")
public int villager_tower_seperation = 16;
public int villager_tower_spacing = 40;
@Comment("Abandoned Church")
public int abandoned_church_seperation = 16;
public int abandoned_church_spacing = 40;
@Comment("Villager Market")
public int villager_market_seperation = 27;
public int villager_market_spacing = 50;
@Comment("Pillager Factory")
public int pillager_factory_seperation = 27;
public int pillager_factory_spacing = 50;
@Comment("Ice Tower")
public int ice_tower_seperation = 8;
public int ice_tower_spacing = 32;
@Comment("Boar Hat Tavern")
public int tavern_seperation = 16;
public int tavern_spacing = 46;
@Comment("Killer Bunny Castle")
public int killer_bunny_castle_seperation = 25;
public int killer_bunny_castle_spacing = 50;
}
@Override @Override
public String getExtension() { public String getExtension() {
return "json5"; return "json5";
} }
public StructureConfigEntry get(Identifier id) {
for (Map.Entry<String, StructureConfigEntry> entry : structureConfigEntries.entrySet()) {
if (entry.getKey().equals(id.getPath())) {
return entry.getValue();
}
}
throw new NullPointerException("Tried StructureConfigEntry with id: " + id + ", but it was null!");
}
@Override
public void save() {
StructureConfigEntry.computeConfigMap(structureConfigEntries);
Config.super.save();
}
} }