Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions common/src/main/java/dev/xpple/betterconfig/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,23 @@
*/
String comment() default "";

// TODO the command suggestions do not work as described
/// A custom name that will be used as command literal in place of the name of the config field. This essentially configures
/// a custom user-facing name, without having to change the name of the config field. This is particularly useful because of
/// the way command suggestions work in Minecraft. When a suggested string contains any of `._/`, the string will be split
/// up at those characters. Each part of the string is then matched individually to the input string. If any of them match,
/// the entire string will be suggested. Below is an example:
/// {@snippet lang = java:
/// @Config(customName = "custom_name")
/// public static String customName = "";
/// }
/// Without the custom name, the config will only be suggested when typing `c`. With the custom name, the config will also be
/// suggested when typing `n`.
///
/// The caller has to verify themselves that the custom name is a valid command literal, and that it is unique.
/// @return the custom name
String customName() default "";

/**
* A method name that will be used to represent the config value in the chat. The method should have no parameters and return
* a chat {@code Component}, which is {@link net.minecraft.network.chat.Component} on Fabric and {@link net.kyori.adventure.text.Component}
Expand Down
11 changes: 9 additions & 2 deletions common/src/main/java/dev/xpple/betterconfig/api/ModConfig.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.xpple.betterconfig.api;

import com.mojang.brigadier.exceptions.CommandSyntaxException;
import org.jspecify.annotations.Nullable;

import java.nio.file.Path;
import java.util.Set;
Expand Down Expand Up @@ -33,9 +34,15 @@ public interface ModConfig<P> {

/// Get the comment for a config.
/// @param config the config's key
/// @return the config comment
/// @return the config comment or `null` if none has been configured
/// @throws IllegalArgumentException when there is no config associated to this key
P getComment(String config);
@Nullable P getComment(String config);

/// Get the custom name for a config.
/// @param config the config's key
/// @return the custom name or `null` if none has been configured
/// @throws IllegalArgumentException when there is no config associated to this key
@Nullable String getCustomName(String config);

/// Get a config value based on the key.
/// @param config the config's key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ protected final LiteralArgumentBuilder<S> create(Collection<? extends ModConfigI
for (ModConfigImpl<S, C, P> modConfig : modConfigs) {
LiteralArgumentBuilder<S> identifierLiteral = LiteralArgumentBuilder.literal(modConfig.getModId());
for (String config : modConfig.getConfigs().keySet()) {
String customName = modConfig.getCustomNames().get(config);
String commandLiteral = customName != null ? customName : config;
Predicate<S> condition = modConfig.getConditions().get(config);
LiteralArgumentBuilder<S> configLiteral = LiteralArgumentBuilder.<S>literal(config).requires(condition);
LiteralArgumentBuilder<S> configLiteral = LiteralArgumentBuilder.<S>literal(commandLiteral).requires(condition);

configLiteral.then(LiteralArgumentBuilder.<S>literal("get").executes(ctx -> get(ctx.getSource(), modConfig, config)));
Config annotation = modConfig.getAnnotations().get(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public static void init(ModConfigImpl<?, ?, ?> modConfig) {
}
}

initCustomName(modConfig, annotation.customName(), fieldName);

initCondition(modConfig, annotation.condition(), fieldName);

initChatRepresentation(modConfig, field, annotation.chatRepresentation());
Expand Down Expand Up @@ -163,9 +165,16 @@ private static void initChatRepresentation(ModConfigImpl<?, ?, ?> modConfig, Fie
});
}

private static void initCustomName(ModConfigImpl<?, ?, ?> modConfig, String customName, String fieldName) {
if (customName.isEmpty()) {
return;
}
modConfig.getCustomNames().put(fieldName, customName);
}

private static void initCondition(ModConfigImpl<?, ?, ?> modConfig, String condition, String fieldName) {
if (condition.isEmpty()) {
modConfig.getConditions().put(fieldName, source -> true);
modConfig.getConditions().put(fieldName, _ -> true);
return;
}
Method predicateMethod;
Expand Down Expand Up @@ -200,7 +209,7 @@ private static void initCondition(ModConfigImpl<?, ?, ?> modConfig, String condi
}
});
} else {
modConfig.getConditions().put(fieldName, source -> {
modConfig.getConditions().put(fieldName, _ -> {
try {
return (Boolean) predicateMethod_f.invoke(null);
} catch (ReflectiveOperationException e) {
Expand All @@ -212,7 +221,7 @@ private static void initCondition(ModConfigImpl<?, ?, ?> modConfig, String condi

private static BiConsumer<Object, Object> initOnChange(ModConfigImpl<?, ?, ?> modConfig, Field field, String onChangeMethodName) {
if (onChangeMethodName.isEmpty()) {
BiConsumer<Object, Object> onChange = (oldValue, newValue) -> {};
BiConsumer<Object, Object> onChange = (_, _) -> {};
modConfig.getOnChangeCallbacks().put(field.getName(), onChange);
return onChange;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import dev.xpple.betterconfig.api.ModConfig;
import dev.xpple.betterconfig.util.CheckedBiConsumer;
import dev.xpple.betterconfig.util.CheckedConsumer;
import org.jspecify.annotations.Nullable;

import java.io.BufferedWriter;
import java.io.IOException;
Expand Down Expand Up @@ -53,6 +54,7 @@ public class ModConfigImpl<S, C, P> implements ModConfig<P> {

private final Map<String, Field> configs = new HashMap<>();
private final Map<String, Config> annotations = new HashMap<>();
private final Map<String, String> customNames = new HashMap<>();
private final Map<String, Object> defaults = new HashMap<>();
private final Map<String, Supplier<P>> comments = new HashMap<>();
private final Map<String, Predicate<S>> conditions = new HashMap<>();
Expand Down Expand Up @@ -105,6 +107,10 @@ public Map<String, Config> getAnnotations() {
return this.annotations;
}

public Map<String, String> getCustomNames() {
return this.customNames;
}

Map<String, Object> getDefaults() {
return this.defaults;
}
Expand Down Expand Up @@ -170,14 +176,25 @@ public Object getDefault(String config) {
}

@Override
public P getComment(String config) {
public @Nullable P getComment(String config) {
if (!this.configs.containsKey(config)) {
throw new IllegalArgumentException();
}
Supplier<P> comment = this.comments.get(config);
if (comment == null) {
throw new IllegalArgumentException();
return null;
}
return comment.get();
}

@Override
public @Nullable String getCustomName(String config) {
if (!this.configs.containsKey(config)) {
throw new IllegalArgumentException();
}
return this.customNames.get(config);
}

@Override
public Object get(String config) {
Field field = this.configs.get(config);
Expand Down
5 changes: 5 additions & 0 deletions fabric/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ loom {
splitEnvironmentSourceSets()
}

loom.runs.configureEach {
jvmArguments.add("-enableassertions")
systemProperties.put("fabric.loom.suppressNarratorError", "true")
}

sourceSets {
testmod {
compileClasspath += main.compileClasspath
Expand Down
3 changes: 3 additions & 0 deletions fabric/src/testmod/java/dev/xpple/betterconfig/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,7 @@ private static Component customChatRepresentation() {
private static boolean isClient(SharedSuggestionProvider source) {
return !(source instanceof CommandSourceStack);
}

@Config(customName = "example_custom_name")
public static String exampleCustomName = "";
}
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ maven_group=dev.xpple
archives_base_name=betterconfig

# Minecraft properties
minecraft_version=26.3-rc-1
minecraft_version=26.3
minecraft_dependency=>=26.3-rc.1 <26.4

# Fabric Properties
# check these on https://fabricmc.net/develop
fabric_api_version=0.160.3+26.3
fabric_api_version=0.161.0+26.3
fabric_loader_version=0.19.5
fabric_loom_version=1.17-SNAPSHOT
fabric_loom_version=1.18-SNAPSHOT

devauth_version=1.2.2

# Paper Properties
paper_api_version=26.3-pre-2.build.0-alpha
paper_api_version=26.3.build.49-alpha
plugin_yml_paper_api_version=26.3
3 changes: 3 additions & 0 deletions paper/src/testplugin/java/dev/xpple/betterconfig/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,7 @@ private static Component customChatRepresentation() {
})
.toList()));
}

@Config(customName = "example_custom_name")
public static String exampleCustomName = "";
}
Loading