Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/2.0-alpha.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
Atilist committed Jun 30, 2024
2 parents 11c63ae + 0d2389b commit 9ac942a
Show file tree
Hide file tree
Showing 23 changed files with 187 additions and 37 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Make sure to use Java 17 (disable Java compatibility checks in Prism if it compl

## Using This to Make Mods

[See the wiki.](https://github.com/ModificationStation/StationAPI/wiki)
[See the wiki.](https://github.com/ModificationStation/StationAPI/wiki)
[Using GCAPI](glass-config-api-v3/docs/Home.md)

Proper code documentation coming eventually. There are some JavaDoc comments for some commonly used classes.

Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ allprojects {
// adds some useful annotations for miscellaneous uses. does not add any dependencies, though people without the lib will be missing some useful context hints.
"implementationOnly"("org.jetbrains:annotations:23.0.0")

modLocalRuntime("com.github.calmilamsy:ModMenu:${project.properties["modmenu_version"]}") {
modLocalRuntime("net.glasslauncher.mods:ModMenu:${project.properties["modmenu_version"]}") {
isTransitive = false
}

compileOnlyApi("com.github.calmilamsy:ModMenu:${project.properties["modmenu_version"]}") {
compileOnlyApi("net.glasslauncher.mods:ModMenu:${project.properties["modmenu_version"]}") {
isTransitive = false
}

Expand Down
5 changes: 5 additions & 0 deletions glass-config-api-v3/docs/Adding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Adding Glass Config API

You want to use GCAPI to handle your mod config? Great!

You already have GCAPI in your workspace if you have [StationAPI](../../wiki/Setting-up-workspace). For the next steps, see [Using](Using.md).
9 changes: 9 additions & 0 deletions glass-config-api-v3/docs/Home.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Welcome to the Glass Config API wiki!

[Adding GCAPI to your project](Adding.md)

[Using GCAPI for your config](Using.md)

[TODO for GCAPI](Todo.md)

[Migrating from 1.0 to 2.0](Migration1.0.md)
39 changes: 39 additions & 0 deletions glass-config-api-v3/docs/Migration1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## Migrating from 1.0 to 2.0

Some breaking changes happened between these two versions, mostly for config factories, save/load listeners, and custom config entries.

Anything that mixes into GCCore will likely no longer work, due to some invasive changes.

NEW:
- `ConfigEntry`
- `reset(Ljava/lang/Object)V`
- Used when resetting to a specified value.
- `vanillaServerBehavior()V`
- Called when joining a vanilla server. Make sure to check for the vanilla server annotations if you don't want to always do something on vanilla servers.
- `@DefaultOnVanillaServer`
- Resets the given field to default on joining a vanilla server.
- `@ValueOnVanillaServer`
- `stringValue`, `booleanValue` (`TriBoolean`), `intValue`, `floatValue`.
- Fill one of these out, and it will be applied to the config field on joining a vanilla server.
- Specifying an invalid value WILL result in a crash.
- `TriBoolean`
- Used in `@ValueOnVanillaServer`.
- Has three states: `TRUE`, `FALSE`, `DEFAULT` (`null`).
- `ConfigFactoryProvider`
- `provideLoadTypeAdapterFactories(ImmutableMap.Builder)V`
- An optional method for providing load type adapters. See `ExampleConfigEnumFactories` for an example.
- `GeneratedConfig`
- Implement this interface in your config classes to allow for picking the fields you want to load, and if you want the class itself to be loaded.

CHANGED:
- `GCCore`
- Saving and loading got changed somewhat drastically. Reduced copy-paste code to almost nothing.
- `ConfigFactoryProvider`
- `provideLoadFactories`
- Added a new parameter. The function is now `NonFunction`, and the new parameter is the default value, positioned after value.
- `ConfigEntry`
- `saveToField()V` is now used whenever saving the value stored to the config field.
- `init(Screen,TextRenderer)V` no longer handles adding icons indicating server sync.
- `PreConfigSavedListener` and `PostConfigLoadedListener`
- A new `source` parameter was added.
- See `EventStorage.EventSource` for more information.
9 changes: 9 additions & 0 deletions glass-config-api-v3/docs/Migration2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## Migrating from 2.0 to 3.0

A LOT of breaking changes happened between v2 and v3, the most important one being that GCAPI is now **part of StationAPI**, and proper config validation on load, along with in-game config editing for server admins.

Most breaking changes are package changes, and annotation changes, with only one major change happening elsewhere for proper validation on load.

- `@ConfigEntry` and `@ConfigCategory` now house all information about the field is on, removing the need for checking for 6 different annotations on load.
- `@GConfig` had it's `primary` value removed, and instead replaced with `priority`.
-
8 changes: 8 additions & 0 deletions glass-config-api-v3/docs/Todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# TODO List
Mostly for me. In rough order of priority weighted with estimated difficulty.

1. Get people to actually use this and report issues and suggestions to me.
2. Add the ability to easily and cleanly edit config fields programmatically.
3. Add support for colours with an ingame colour picker. Adding an actual colour picker might be a pain the the arse. I have a couple of ideas on how to do this.
4. Add field validation on game load. JSON files are not validated on load, currently.
5. Add block and item selection support. Should be easy enough with StAPI registries. I currently cannot think of a good use for this config option yet, though.
16 changes: 16 additions & 0 deletions glass-config-api-v3/docs/Types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Supported Types

This is a limited list for now, but it's already easily doable by mods to add their own classes for use as config factories.

The built-in factories are as follows:

- java.lang.String
- java.lang.Integer
- java.lang.Float
- java.lang.Boolean
- java.lang.String[]
- java.lang.Integer[]
- java.lang.Float[]
- [java.lang.Enum](Using.md#enums)

Should this list ever fall out of date, see [DefaultFactoryProvider.java](../blob/master/src/main/java/net/glasslauncher/mods/api/gcapi/impl/config/factory/DefaultFactoryProvider.java).
62 changes: 62 additions & 0 deletions glass-config-api-v3/docs/Using.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[Quick Usage](#quick-usage)
[Categories](#categories)
[Annotations](#annotations)
[Multiplayer Syncing](#multiplayer-syncing)
[Multiple Config Pages](#multiple-config-pages)
[IMPORTANT NOTES](#important-notes)

# Quick Usage

1. Create an empty non-static class somewhere in your project. We will be using this later.
2. Create an instantiated `public static final` field for your first config screen and annotate it with `@GConfig`, make sure the field's type is the class you just created. **Do not** put it inside your newly made class. (e.g. `public static final ExampleConfigClass config = new ExampleConfigClass()`)
3. Fill out the required `value` and `visibleName` parameters on the [annotation](#Annotations). Value is the name of your config file. (e.g. `@GConfig(value = "config", visibleName = "My Config GUI")`)
4. Go into your `fabric.mod.json` and add the snippet below inside your `entrypoints` section:
```
"gcapi": [
"<path.to.the.class.containing.the.field.here>"
]
```
5. Now let's go back to the empty class you made earlier.
6. Create some fields with the type you want ([Valid Types](Types)) and annotate them with `@ConfigName`, filling out the value parameter with what you'd like the user to see your option called in the config GUI. (e.g. `@ConfigName("My Config Field") public String myField = ""`)
7. Done! You can use the field in your code, GCAPI will handle loading and syncing logic for you.

# Categories
To make a category, you will need to:
1. Create a class that will represent your category and fill it with fields like normal, including the required [annotations](#Annotations).
2. In the class where you want the category, add a `@ConfigCategory` annotation, and fill out the required value parameter.
3. Done! You can have categories inside of categories if you so wish to.

# Annotations
| Annotation | Description | Required |
|-----------------|----------------------------------------------------|:----------------------------------------------:|
| @GConfig | Used by GCAPI to find your mod configs in a class. | <ul><li>- [x] (config class fields) </li></ul> |
| @ConfigEntry | Holds all the metadata of a config entry. | <ul><li>- [x] (config fields) </li></ul> |
| @ConfigCategory | Holds all the metadata of a config category. | <ul><li>- [x] (categories)</li></ul> |

# Multiplayer Syncing
Just set `multiplayerSynced` `ConfigEntry`/`ConfigCategory` annotation value to `false` on the field or categories you want synced with the server.

# Multiple Config Pages
Just add another `@GConfig` field, and if it's in a different class from the first one, add it's class to the `entrypoints` section in `fabric.mod.json` too.

Buttons will be added at the top of the config page for your mod for navigating these.

You are able to set a priority for these pages, with a lower number meaning it will appear sooner in the list.

# Enums
In 2.0.0, you can now use enums to create cycling config values.

The catch is that you need to create your enum type, and provide a set of simple config factories.

See [ExampleConfigEnum](../../src/test/java/net/modificationstation/sltest/gcapi/ExampleConfigEnum.java) and [ExampleConfigEnumFactories](../../src/test/java/net/modificationstation/sltest/gcapi/ExampleConfigEnumFactories.java) on how to do it.

# Generated Configs
In 2.0.0, you can now dynamically supply config categories and fields.

Make your config category class, implement `GeneratedConfig`.

# IMPORTANT NOTES

- Use `GCAPI.reloadConfig` to manually set config values. This is to ensure mods are notified properly and can post-process things.
- The config.json files are not sanitised or checked when loaded. This will be fixed in a later update once I figure out a good way to handle it. This is low on my list.
- Servers are able to send whatever configs they want, so long as the config field on the client is MP syncable. The server doesn't even need to have the mod installed. This would require emulating GCAPI's config export code to do so, though. I'm not sure if I'll patch this. It seems like it would have its uses.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.google.common.collect.ImmutableMap;
import net.modificationstation.stationapi.api.config.ConfigFactoryProvider;
import net.modificationstation.stationapi.api.config.ConfigEntry;
import net.modificationstation.stationapi.impl.config.NonFunction;
import net.modificationstation.stationapi.impl.config.object.ConfigEntryHandler;
import net.modificationstation.stationapi.impl.config.object.entry.BooleanConfigEntryHandler;
import net.modificationstation.stationapi.impl.config.object.entry.FloatConfigEntryHandler;
Expand All @@ -12,7 +11,6 @@
import net.modificationstation.stationapi.impl.config.object.entry.IntegerListConfigEntryHandler;
import net.modificationstation.stationapi.impl.config.object.entry.StringConfigEntryHandler;
import net.modificationstation.stationapi.impl.config.object.entry.StringListConfigEntryHandler;
import uk.co.benjiweber.expressions.function.OctFunction;
import uk.co.benjiweber.expressions.function.SeptFunction;

import java.lang.reflect.*;
Expand All @@ -28,9 +26,9 @@ public void provideLoadFactories(ImmutableMap.Builder<Type, SeptFunction<String,
immutableBuilder.put(Integer.class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new IntegerConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, Integer.valueOf(String.valueOf(value)), Integer.valueOf(String.valueOf(defaultValue)))));
immutableBuilder.put(Float.class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new FloatConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, Float.valueOf(String.valueOf(value)), Float.valueOf(String.valueOf(defaultValue)))));
immutableBuilder.put(Boolean.class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new BooleanConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, (boolean) value, (boolean) defaultValue)));
immutableBuilder.put(String[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new StringListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, ((ArrayList<String>) value).toArray(new String[0]), (String[]) defaultValue))); // the new ArrayList is required or it returns java.util.Arrays.ArrayList, which is fucking dumb.
immutableBuilder.put(Integer[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new IntegerListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, ((ArrayList<Integer>) value).toArray(new Integer[0]), (Integer[]) defaultValue)));
immutableBuilder.put(Float[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new FloatListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, ((ArrayList<Float>) value).toArray(new Float[0]), (Float[]) defaultValue)));
immutableBuilder.put(String[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new StringListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, listOrArrayToArray(value, new String[0]), (String[]) defaultValue)));
immutableBuilder.put(Integer[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new IntegerListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, listOrArrayToArray(value, new Integer[0]), (Integer[]) defaultValue)));
immutableBuilder.put(Float[].class, ((id, configEntry, parentField, parentObject, isMultiplayerSynced, value, defaultValue) -> new FloatListConfigEntryHandler(id, configEntry, parentField, parentObject, isMultiplayerSynced, listOrArrayToArray(value, new Float[0]), (Float[]) defaultValue)));
}

@Override
Expand All @@ -44,7 +42,15 @@ public void provideSaveFactories(ImmutableMap.Builder<Type, Function<Object, Obj
immutableBuilder.put(Float[].class, DefaultFactoryProvider::justPass);
}

private static <T> T justPass(T object) {
public static <T> T justPass(T object) {
return object;
}

public static <T> T[] listOrArrayToArray(Object object, T[] type) {
if (object instanceof List<?> list) {
return list.toArray(type);
}
//noinspection unchecked // If this isn't right, we're fucked anyways
return (T[]) object;
}
}
12 changes: 1 addition & 11 deletions glass-config-api-v3/src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,8 @@
"preLaunch": [
"net.modificationstation.stationapi.impl.config.GCCore"
],
"gcapi": [
"net.modificationstation.stationapi.impl.config.example.ExampleConfig"
],
"gcapi:factory_provider": [
"net.modificationstation.stationapi.impl.config.factory.DefaultFactoryProvider",
"net.modificationstation.stationapi.impl.config.example.ExampleConfigEnumFactories"
],
"gcapi:postload": [
"net.modificationstation.stationapi.impl.config.example.ExampleEntryPointListeners"
],
"gcapi:presave": [
"net.modificationstation.stationapi.impl.config.example.ExampleEntryPointListeners"
"net.modificationstation.stationapi.impl.config.factory.DefaultFactoryProvider"
],
"stationapi:event_bus_server": [
"net.modificationstation.stationapi.impl.config.event.InitServerNetworking"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ fabric.loom.multiProjectOptimisation=true
# Test properties
gcapi_version = 1.3.1
hmi_version = 5.1.1
modmenu_version = v1.8.5-beta.3
modmenu_version = 1.8.5-beta.4
mojangfix_version = 0.5.2
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigRoot;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigCategory;
import net.modificationstation.stationapi.api.config.ConfigEntry;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigEntry;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigCategory;
import net.modificationstation.stationapi.api.config.ConfigEntry;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

public enum ExampleConfigEnum {
YAY("Yay!"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import com.google.common.collect.ImmutableMap;
import net.modificationstation.stationapi.api.config.ConfigFactoryProvider;
import net.modificationstation.stationapi.api.config.ConfigEntry;
import net.modificationstation.stationapi.impl.config.NonFunction;
import net.modificationstation.stationapi.impl.config.object.ConfigEntryHandler;
import net.modificationstation.stationapi.impl.config.object.entry.EnumConfigEntryHandler;
import uk.co.benjiweber.expressions.function.SeptFunction;
import uk.co.benjiweber.expressions.function.SexFunction;

import java.lang.reflect.*;
import java.util.function.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.PostConfigLoadedListener;
import net.modificationstation.stationapi.api.config.PreConfigSavedListener;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigEntry;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.modificationstation.stationapi.impl.config.example;
package net.modificationstation.sltest.gcapi;

import net.modificationstation.stationapi.api.config.ConfigEntry;

Expand Down
12 changes: 12 additions & 0 deletions src/test/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@
],
"preLaunch": [
"net.modificationstation.sltest.PreLaunchTest"
],
"gcapi": [
"net.modificationstation.sltest.gcapi.ExampleConfig"
],
"gcapi:factory_provider": [
"net.modificationstation.sltest.gcapi.ExampleConfigEnumFactories"
],
"gcapi:postload": [
"net.modificationstation.sltest.gcapi.ExampleEntryPointListeners"
],
"gcapi:presave": [
"net.modificationstation.sltest.gcapi.ExampleEntryPointListeners"
]
},

Expand Down

0 comments on commit 9ac942a

Please sign in to comment.