Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
236397e
Initial work to adjust and update owo config
Dragon-Seeker Mar 26, 2025
7e1b4ed
Update owo UI xml validation
Dragon-Seeker Mar 26, 2025
4482526
Add renderdoc test run
Dragon-Seeker Mar 26, 2025
8e5532f
Adjust Game rule disabling feature to prevent constant disabling inst…
Dragon-Seeker Mar 26, 2025
d37611c
Fix issues with passing Wrapper component instead of clickable widget
Dragon-Seeker Mar 26, 2025
66e8b7f
Add some wisdom
Dragon-Seeker Mar 26, 2025
835d282
Fix issue with button appearing for configuration with owolib
Dragon-Seeker Jul 31, 2025
ab30f2d
Change Config Constaints, add translation dumping, rework option anno…
Dragon-Seeker Aug 1, 2025
f7e5a2c
Adjust Client/Server switch button with a Icon and implement such as …
Dragon-Seeker Aug 1, 2025
e44b611
Add `ReloadRequired` annotation
Dragon-Seeker Aug 1, 2025
6a6359f
Update ConfigSynchronizer to use Identifier with use of OwoNetworking
Dragon-Seeker Aug 1, 2025
13ba544
Adjust commands related to config access/reload
Dragon-Seeker Aug 1, 2025
0d9606c
Fix issue with not properly transferring parent screen from opening s…
Dragon-Seeker Aug 1, 2025
88e5cd1
Fix issues with not checking if a given message can be sent within Ow…
Dragon-Seeker Aug 1, 2025
c69c097
Properly send error for when OwoUIAdapater errors in `render` for Bas…
Dragon-Seeker Aug 1, 2025
b9290ae
Update Test mod config wrappers with new field for reload and other s…
Dragon-Seeker Aug 1, 2025
c5cc1cb
Fix issues with client mixins in common side leading to annoying errors
Dragon-Seeker Aug 1, 2025
9b1c76f
Use `ConfigIdentifierArgumentType` arg for uwu debug command
Dragon-Seeker Aug 1, 2025
f4f3daf
Add uwu mod icon
Dragon-Seeker Aug 1, 2025
9913462
Add ability to dump translations to log from debug button instead of …
Dragon-Seeker Aug 1, 2025
420bb0d
Update struct option container to clean up `addOptionComponent` method
Dragon-Seeker Aug 1, 2025
5d9e438
Add `-XX:+AllowEnhancedClassRedefinition`
Dragon-Seeker Aug 1, 2025
70cd60e
Fix issues with porting to 1.21.6
Dragon-Seeker Aug 2, 2025
a9641ca
Remove `configName` and unused classes
Dragon-Seeker Aug 31, 2025
f5a4e54
Adjust options method names for label and tooltip translation keys
Dragon-Seeker Aug 31, 2025
97038af
Add more docs and include some annotations for various classes in config
Dragon-Seeker Aug 31, 2025
1eeadd0
Merge branch '1.21.9' into 1.21.6-ConfigAdjustments
Dragon-Seeker Oct 22, 2025
29f65cb
Update for Config PR for 1.21.10
Dragon-Seeker Oct 23, 2025
64db5a8
Update EndecArgumentSerializer for yarn and use constant argument ser…
Dragon-Seeker Oct 30, 2025
48859e3
Sweeping fixes with updating docs, adjusting code and overall cleanup
Dragon-Seeker Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,22 @@ loom {
ideConfigGenerated project.rootProject == project
name = "Testmod Client"
source sourceSets.testmod
vmArg "-XX:+AllowEnhancedClassRedefinition"
}
testmodClientRenderDoc {
client()
ideConfigGenerated project.rootProject == project
name = "Testmod Client [RenderDoc]"
source sourceSets.testmod
vmArg "-Dowo.renderdocPath=${System.getenv('renderDocPath')}"
vmArg "-XX:+AllowEnhancedClassRedefinition"
}
testmodServer {
server()
ideConfigGenerated project.rootProject == project
name = "Testmod Server"
source sourceSets.testmod
vmArg "-XX:+AllowEnhancedClassRedefinition"
}
}

Expand Down
258 changes: 253 additions & 5 deletions owo-ui.xsd

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/main/java/io/wispforest/owo/Owo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@

import io.wispforest.owo.client.screens.ScreenInternals;
import io.wispforest.owo.command.debug.OwoDebugCommands;
import io.wispforest.owo.config.OwoConfigCommand;
import io.wispforest.owo.network.OwoNetChannel;
import io.wispforest.owo.ops.LootOps;
import io.wispforest.owo.packets.OwoPackets;
import io.wispforest.owo.text.CustomTextRegistry;
import io.wispforest.owo.text.InsertingTextContent;
import io.wispforest.owo.util.Wisdom;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
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.server.MinecraftServer;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.ApiStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -57,6 +66,10 @@ public void onInitialize() {

Wisdom.spread();

OwoConfigCommand.register();

OwoPackets.initNetworking();

if (!DEBUG) return;

OwoDebugCommands.register();
Expand All @@ -82,5 +95,4 @@ public static void debugWarn(Logger logger, String message, Object... params) {
public static MinecraftServer currentServer() {
return SERVER;
}

}
5 changes: 4 additions & 1 deletion src/main/java/io/wispforest/owo/client/OwoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.wispforest.owo.config.OwoConfigCommand;
import io.wispforest.owo.itemgroup.json.OwoItemGroupLoader;
import io.wispforest.owo.moddata.ModDataLoader;
import io.wispforest.owo.packets.OwoPackets;
import io.wispforest.owo.ui.core.OwoUIPipelines;
import io.wispforest.owo.ui.parsing.UIModelLoader;
import io.wispforest.owo.ui.renderstate.OwoSpecialGuiElementRenderers;
Expand Down Expand Up @@ -67,7 +68,9 @@ public void onInitializeClient() {

ScreenInternals.Client.init();

ClientCommandRegistrationCallback.EVENT.register(OwoConfigCommand::register);
ClientCommandRegistrationCallback.EVENT.register(OwoConfigCommand::registerClient);

OwoPackets.initClientNetworking();

if (Owo.DEBUG) {
OwoDebugCommands.Client.register();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package io.wispforest.owo.command;

import com.google.gson.JsonObject;
import com.mojang.brigadier.arguments.ArgumentType;
import io.wispforest.endec.Endec;
import io.wispforest.endec.StructEndec;
import io.wispforest.endec.format.bytebuf.ByteBufDeserializer;
import io.wispforest.endec.format.bytebuf.ByteBufSerializer;
import io.wispforest.endec.format.gson.GsonSerializer;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.argument.serialize.ArgumentSerializer;
import net.minecraft.network.PacketByteBuf;

import java.util.function.Function;

///
/// An [Endec] based [ArgumentSerializer] requiring a [StructEndec] and
///
public record EndecArgumentSerializer<A extends ArgumentType<?>, T>(StructEndec<T> endec, PropertiesFactory<A, T> propertiesFactory, ArgumentTypeFactory<A, T> argumentTypeFactory)
implements ArgumentSerializer<A, EndecArgumentSerializer.EndecArgumentTypeProperties<A, T>> {

public static <A extends ArgumentType<?>> EndecArgumentSerializer<A, Void> of(Function<CommandRegistryAccess, A> argTypeConstructor) {
return new EndecArgumentSerializer<>(Endec.unit(() -> null), a -> null, (commandBuildContext, unused) -> argTypeConstructor.apply(commandBuildContext));
}

@Override
public void writePacket(EndecArgumentTypeProperties<A, T> properties, PacketByteBuf buffer) {
endec.encodeFully(() -> ByteBufSerializer.of(buffer), properties.data());
}

@Override
public EndecArgumentTypeProperties<A, T> fromPacket(PacketByteBuf buffer) {
return new EndecArgumentTypeProperties<>(this, endec.decodeFully(ByteBufDeserializer::of, buffer), argumentTypeFactory);
}

@Override
public void writeJson(EndecArgumentTypeProperties<A, T> properties, JsonObject json) {
json.asMap().putAll(((JsonObject) endec.encodeFully(GsonSerializer::of, properties.data())).asMap());
}

@Override
public EndecArgumentTypeProperties<A, T> getArgumentTypeProperties(A argument) {
return new EndecArgumentTypeProperties<>(this, propertiesFactory.create(argument), argumentTypeFactory);
}

public record EndecArgumentTypeProperties<A extends ArgumentType<?>, T>(ArgumentSerializer<A, ?> type, T data, ArgumentTypeFactory<A, T> argumentFactory) implements ArgumentTypeProperties<A> {
@Override
public A createType(CommandRegistryAccess ctx) {
return argumentFactory.create(ctx, data());
}

@Override
public ArgumentSerializer<A, ?> getSerializer() {
return type;
}
}

public interface PropertiesFactory<A extends ArgumentType<?>, T> {
T create(A argumentType);
}

public interface ArgumentTypeFactory<A extends ArgumentType<?>, T> {
A create(CommandRegistryAccess access, T properties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.wispforest.owo.config.ui.ConfigScreenProviders;
import io.wispforest.owo.config.ui.SimpleButtonScreen;
import io.wispforest.owo.ui.component.ButtonComponent;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -19,11 +25,32 @@ public class OwoModMenuPlugin implements ModMenuApi {
protected @NotNull Map<String, ConfigScreenFactory<?>> delegate() {
return Util.make(
new HashMap<>(),
map -> ConfigScreenProviders.forEach((s, provider) -> map.put(s, provider::apply))
factoryMap -> {
ConfigScreenProviders.getSortedProviders().forEach((modId, modSpecificProviders) -> {
var configId = Identifier.of(modId, modSpecificProviders.getFirst());

factoryMap.put(modId, parent -> ConfigScreenProviders.safelyCreateConfigScreen(configId, parent, Map.of()));
});
}
);
}
};

@Override
@Nullable
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> new SimpleButtonScreen(
Text.of("The Confurration Screen"),
Text.of("This screen exists due to Mod Menu issue that has not been resolved so are you a... a furry?"),
Map.of(
Text.of("Totally a Furry"),
(btn) -> MinecraftClient.getInstance().currentScreen.close(),
Text.of("Not a Furry"),
(btn) -> MinecraftClient.getInstance().currentScreen.close()
)
);
}

@Override
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
return OWO_FACTORIES;
Expand Down
52 changes: 36 additions & 16 deletions src/main/java/io/wispforest/owo/config/ConfigAP.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.wispforest.owo.config.annotation.Config;
import io.wispforest.owo.config.annotation.Hook;
import io.wispforest.owo.config.annotation.Nest;
import io.wispforest.owo.config.base.Key;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

Expand All @@ -27,10 +28,13 @@ public class ConfigAP extends AbstractProcessor {
package {package};

import blue.endless.jankson.Jankson;
import io.wispforest.endec.impl.ReflectiveEndecBuilder;
import io.wispforest.owo.config.ConfigWrapper;
import io.wispforest.owo.config.ConfigWrapper.BuilderConsumer;
import io.wispforest.owo.config.Option;
import io.wispforest.owo.config.ConfigWrapper.Builder;
import io.wispforest.owo.config.options.FieldOption;
import io.wispforest.owo.config.base.Key;
import io.wispforest.owo.util.Observable;
import io.wispforest.owo.config.serialization.ConfigSerializer;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -46,19 +50,33 @@ public class {wrapper_class_name} extends ConfigWrapper<{config_class_name}> {
super({config_class_name}.class);
}

private {wrapper_class_name}(BuilderConsumer consumer) {
private {wrapper_class_name}(Builder consumer) {
super({config_class_name}.class, consumer);
}

private {wrapper_class_name}(ConfigSerializer<?> serializer, Builder consumer) {
super({config_class_name}.class, serializer, consumer);
}

private {wrapper_class_name}(Class<{config_class_name}> clazz, ConfigSerializer<?> serializer, ReflectiveEndecBuilder builder, boolean setupConfigSyncing) {
super(clazz, serializer, builder, setupConfigSyncing);
}

public static {wrapper_class_name} createAndLoad() {
var wrapper = new {wrapper_class_name}();
wrapper.load();
wrapper.loadFile();
return wrapper;
}

public static {wrapper_class_name} createAndLoad(BuilderConsumer consumer) {
public static {wrapper_class_name} createAndLoad(Builder consumer) {
var wrapper = new {wrapper_class_name}(consumer);
wrapper.load();
wrapper.loadFile();
return wrapper;
}

public static {wrapper_class_name} createAndLoad(ConfigSerializer<?> serializer, Builder consumer) {
var wrapper = new {wrapper_class_name}(serializer, consumer);
wrapper.loadFile();
return wrapper;
}

Expand Down Expand Up @@ -123,10 +141,12 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
var className = clazz.getQualifiedName().toString();
var wrapperName = annotated.getAnnotation(Config.class).wrapperName();

this.nestTypes.clear();

try {
var file = this.processingEnv.getFiler().createSourceFile(wrapperName);
try (var writer = new PrintWriter(file.openWriter())) {
writer.println(makeWrapper(wrapperName, className, this.collectFields(Option.Key.ROOT, clazz, clazz.getAnnotation(Config.class).defaultHook())));
writer.println(makeWrapper(wrapperName, className, this.collectFields(Key.ROOT, clazz, clazz.getAnnotation(Config.class).defaultHook())));
}
} catch (IOException e) {
throw new RuntimeException("Failed to generate config wrapper", e);
Expand All @@ -137,7 +157,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
return true;
}

private List<ConfigField> collectFields(Option.Key parent, TypeElement clazz, boolean defaultHook) {
private List<ConfigField> collectFields(Key parent, TypeElement clazz, boolean defaultHook) {
var messager = this.processingEnv.getMessager();
var list = new ArrayList<ConfigField>();

Expand Down Expand Up @@ -209,28 +229,28 @@ private String makeWrapper(String wrapperClassName, String configClassName, List
.replace("{accessors}\n", accessorMethods.finish());
}

private String makeGetAccessor(String fieldName, Option.Key fieldKey, TypeMirror fieldType) {
private String makeGetAccessor(String fieldName, Key fieldKey, TypeMirror fieldType) {
return GET_ACCESSOR_TEMPLATE
.replace("{option_instance}", constantNameOf(fieldKey))
.replace("{field_name}", fieldName)
.replace("{field_type}", fieldType.toString());
}

private String makeSetAccessor(String fieldName, Option.Key fieldKey, TypeMirror fieldType) {
private String makeSetAccessor(String fieldName, Key fieldKey, TypeMirror fieldType) {
return SET_ACCESSOR_TEMPLATE
.replace("{option_instance}", constantNameOf(fieldKey))
.replace("{field_name}", fieldName)
.replace("{field_type}", fieldType.toString());
}

private String makeSubscribe(String fieldName, Option.Key fieldKey, TypeMirror fieldType) {
private String makeSubscribe(String fieldName, Key fieldKey, TypeMirror fieldType) {
return SUBSCRIBE_TEMPLATE
.replace("{option_instance}", constantNameOf(fieldKey))
.replace("{field_name}", fieldName)
.replace("{field_type}", this.primitivesToWrappers.getOrDefault(fieldType, fieldType).toString());
}

private String constantNameOf(Option.Key key) {
private String constantNameOf(Key key) {
return key.asString().replace(".", "_");
}

Expand All @@ -240,11 +260,11 @@ private interface ConfigField {

private final class ValueField implements ConfigField {
private final String name;
private final Option.Key key;
private final Key key;
private final TypeMirror type;
private final boolean makeSubscribe;

private ValueField(String name, Option.Key key, TypeMirror type, boolean makeSubscribe) {
private ValueField(String name, Key key, TypeMirror type, boolean makeSubscribe) {
this.name = name;
this.key = key;
this.type = type;
Expand All @@ -253,8 +273,8 @@ private ValueField(String name, Option.Key key, TypeMirror type, boolean makeSub

@Override
public void appendAccessors(Writer accessors, Writer optionInstances, Writer keyConstants) {
keyConstants.line("public final Option.Key " + constantNameOf(this.key) + " = new Option.Key(\"" + this.key.asString() + "\");");
optionInstances.line("private final Option<" + primitivesToWrappers.getOrDefault(type, type) + "> " + constantNameOf(this.key) + " = this.optionForKey(this.keys." + constantNameOf(this.key) + ");");
keyConstants.line("public final Key " + constantNameOf(this.key) + " = new Key(\"" + this.key.asString() + "\");");
optionInstances.line("private final FieldOption<" + primitivesToWrappers.getOrDefault(type, type) + "> " + constantNameOf(this.key) + " = this.optionForKey(this.keys." + constantNameOf(this.key) + ");");

accessors.append(makeGetAccessor(this.name, this.key, this.type)).write("\n");
accessors.append(makeSetAccessor(this.name, this.key, this.type)).write("\n");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.wispforest.owo.config;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import io.wispforest.owo.Owo;
import io.wispforest.owo.ops.TextOps;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;

public class ConfigIdentifierArgumentType implements ArgumentType<Identifier> {

public static final ConfigIdentifierArgumentType INSTANCE = new ConfigIdentifierArgumentType();

private static final SimpleCommandExceptionType NO_SUCH_CONFIG_SCREEN = new SimpleCommandExceptionType(
TextOps.concat(Owo.PREFIX, Text.literal("no config with that id"))
);

@Override
public Identifier parse(StringReader reader) throws CommandSyntaxException {
var id = Identifier.fromCommandInput(reader);
if (ConfigWrapper.getKnownConfigInstances().get(id) == null) throw NO_SUCH_CONFIG_SCREEN.create();
return id;
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
var configNames = new ArrayList<String>();
ConfigWrapper.getKnownConfigInstances().keySet().forEach(s -> configNames.add(s.toString()));
return CommandSource.suggestMatching(configNames, builder);
}
}
Loading