Skip to content

Commit 54a6587

Browse files
authored
Merge pull request #55 from CyR1en/development
Development
2 parents 935a98b + 307311b commit 54a6587

15 files changed

Lines changed: 381 additions & 85 deletions

build.gradle

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ java {
3939

4040
PluginManifest pluginManifest = [
4141
name : 'CommandPrompter',
42-
version : new Version(major: 2, minor: 10, patch: 0, fix: 0, classifier: 'SNAPSHOT'),
42+
version : new Version(major: 2, minor: 11, patch: 0, fix: 0, classifier: 'SNAPSHOT'),
4343
author : 'CyR1en',
4444
description: 'Making Commands More Interactive!',
4545
entry : 'com.cyr1en.commandprompter.CommandPrompter'
@@ -66,13 +66,13 @@ repositories {
6666
dependencies {
6767
implementation 'com.cyr1en:kiso-utils:1.8-SNAPSHOT'
6868
implementation 'com.cyr1en:kiso-mc:1.8-SNAPSHOT'
69-
implementation 'net.wesjd:anvilgui:1.10.1-SNAPSHOT'
69+
implementation 'net.wesjd:anvilgui:1.10.3-SNAPSHOT'
7070
implementation 'org.bstats:bstats-bukkit:3.0.2'
7171
implementation group: 'org.fusesource.jansi', name: 'jansi', version: '2.4.0'
72-
implementation 'com.github.stefvanschie.inventoryframework:IF:0.10.17'
72+
implementation 'com.github.stefvanschie.inventoryframework:IF:0.10.18'
7373
implementation "net.kyori:adventure-text-minimessage:4.17.0"
74-
implementation "dev.jorel:commandapi-bukkit-shade:9.5.3"
75-
implementation 'de.rapha149.signgui:signgui:2.4.1'
74+
implementation "dev.jorel:commandapi-bukkit-shade:9.6.1"
75+
implementation 'de.rapha149.signgui:signgui:2.4.2'
7676

7777
compileOnly 'me.clip:placeholderapi:2.11.2'
7878
compileOnly "net.kyori:adventure-text-serializer-legacy:4.17.0"
@@ -96,13 +96,15 @@ configurations.implementation {
9696
exclude group: 'org.atteo.classindex', module: 'classindex'
9797
}
9898

99+
tasks.named('jar').configure { enabled = false }
100+
99101
shadowJar {
100102
dependencies {
101103
exclude(dependency('com.mojang:brigadier'))
102104
}
103105

104106
archiveBaseName.set("$project.name")
105-
archiveClassifier.set('shaded')
107+
archiveClassifier.set('')
106108
archiveVersion.set(pluginManifest.version.getFullVersion())
107109

108110
relocate 'com.github.stefvanschie.inventoryframework', 'com.cyr1en.inventoryframework'

src/main/java/com/cyr1en/commandprompter/PluginMessenger.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.cyr1en.commandprompter;
22

3-
import org.bukkit.ChatColor;
3+
import com.cyr1en.commandprompter.util.Util;
44
import org.bukkit.command.CommandSender;
55

66
public class PluginMessenger {
@@ -18,6 +18,6 @@ public void setPrefix(String prefix) {
1818
public void sendMessage(CommandSender sender, String message) {
1919
if (message.isBlank()) return;
2020
var whole = prefix + message;
21-
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', whole));
21+
sender.sendMessage(Util.color(whole));
2222
}
2323
}

src/main/java/com/cyr1en/commandprompter/config/ConfigurationManager.java

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
import com.cyr1en.commandprompter.config.annotations.type.ConfigHeader;
77
import com.cyr1en.commandprompter.config.annotations.type.ConfigPath;
88
import com.cyr1en.commandprompter.config.annotations.type.Configuration;
9+
import com.cyr1en.commandprompter.config.handlers.ConfigTypeHandlerFactory;
910
import com.cyr1en.kiso.mc.configuration.base.Config;
1011
import com.cyr1en.kiso.mc.configuration.base.ConfigManager;
1112

1213
import java.lang.reflect.Field;
1314
import java.lang.reflect.InvocationTargetException;
1415
import java.util.ArrayList;
15-
import java.util.Arrays;
16-
import java.util.List;
1716
import java.util.regex.Pattern;
1817

1918
/**
@@ -36,11 +35,23 @@ public class ConfigurationManager {
3635
private final ConfigManager configManager;
3736
private final PluginLogger logger;
3837

38+
/**
39+
* Constructs a new ConfigurationManager for a given plugin.
40+
*
41+
* @param plugin The plugin instance which this manager will handle configurations for.
42+
*/
3943
public ConfigurationManager(CommandPrompter plugin) {
4044
this.configManager = new ConfigManager(plugin);
4145
this.logger = plugin.getPluginLogger();
4246
}
4347

48+
/**
49+
* Retrieves or initializes the configuration for a specified configuration class.
50+
*
51+
* @param <T> The type of the configuration record.
52+
* @param configClass The class of the configuration record.
53+
* @return An instance of T with values from the configuration, or null if configuration class is not annotated properly.
54+
*/
4455
public <T> T getConfig(Class<T> configClass) {
4556
if (configClass.getAnnotation(Configuration.class) == null)
4657
return null;
@@ -52,39 +63,30 @@ public <T> T getConfig(Class<T> configClass) {
5263
var configValues = new ArrayList<>();
5364
configValues.add(config);
5465

55-
for (Field declaredField : configClass.getDeclaredFields()) {
56-
if (declaredField.getAnnotation(ConfigNode.class) == null) continue;
66+
for (Field field : configClass.getDeclaredFields()) {
67+
if (field.getAnnotation(ConfigNode.class) == null) continue;
5768

58-
var nameAnnotation = declaredField.getAnnotation(NodeName.class);
69+
var nameAnnotation = field.getAnnotation(NodeName.class);
70+
String nodeName = nameAnnotation != null ? nameAnnotation.value() : field.getName();
5971

60-
if (declaredField.isAnnotationPresent(Match.class)) {
61-
var matchAnnotation = declaredField.getAnnotation(Match.class);
72+
var handler = ConfigTypeHandlerFactory.getHandler(field.getType());
73+
74+
if (field.isAnnotationPresent(Match.class)) {
75+
var matchAnnotation = field.getAnnotation(Match.class);
6276
var regex = matchAnnotation.regex();
6377
var pattern = Pattern.compile(regex);
64-
var res = pattern.matcher(config.getString(nameAnnotation.value())).matches();
78+
var res = pattern.matcher(config.getString(nodeName)).matches();
6579
if (!res) {
66-
logger.warn("Configured value for " + nameAnnotation.value() + " is invalid! Falling back to default value.");
67-
configValues.add(constructDefaultField(declaredField));
80+
logger.warn("Configured value for " + nodeName + " is invalid! Using default.");
81+
configValues.add(handler.getDefault(field));
6882
continue;
6983
}
7084
}
7185

72-
if (declaredField.getType().equals(int.class)) {
73-
var val = config.getInt(nameAnnotation.value());
74-
var constraint = declaredField.getAnnotation(IntegerConstraint.class);
75-
if (constraint != null)
76-
val = val > constraint.max() ? constraint.max() : Math.max(val, constraint.min());
77-
configValues.add(val);
78-
} else if (declaredField.getType().equals(boolean.class))
79-
configValues.add(config.getBoolean(nameAnnotation.value()));
80-
else if (declaredField.getType().equals(double.class))
81-
configValues.add(config.getDouble(nameAnnotation.value()));
82-
else if (declaredField.getType().equals(List.class))
83-
configValues.add(config.getList(nameAnnotation.value()));
84-
else configValues.add(config.getString(nameAnnotation.value()));
86+
configValues.add(handler.getValue(config, nodeName, field));
8587
}
8688
try {
87-
// Records only have 1 constructor so just access index 0
89+
// Since records in Java have canonical constructors, we directly use the first constructor
8890
var recordConfig = configClass.getDeclaredConstructors()[0].newInstance(configValues.toArray());
8991
@SuppressWarnings("unchecked") var out = (T) recordConfig;
9092
return out;
@@ -94,17 +96,37 @@ else if (declaredField.getType().equals(List.class))
9496
return null;
9597
}
9698

99+
/**
100+
* Reloads the configuration for the given configuration class. This method simply calls getConfig.
101+
*
102+
* @param <T> The type of the configuration record.
103+
* @param configClass The class of the configuration record to reload.
104+
* @return A reloaded instance of T or null if reload fails or configClass is invalid.
105+
*/
97106
public <T> T reload(Class<T> configClass) {
98107
return getConfig(configClass);
99108
}
100109

110+
/**
111+
* Initializes the configuration file with default values defined in the record.
112+
*
113+
* @param configClass The class of the record for which configuration needs to be initialized.
114+
* @param config The Config object representing the YAML file.
115+
*/
101116
private void initializeConfig(Class<?> configClass, Config config) {
102117
var fields = configClass.getDeclaredFields();
103118
for (Field field : fields)
104119
initializeField(field, config);
105120
}
106121

122+
/**
123+
* Initializes or retrieves the configuration file for the given configuration class.
124+
*
125+
* @param configClass The class of the configuration record.
126+
* @return A Config object representing the configuration file.
127+
*/
107128
private Config initConfigFile(Class<?> configClass) {
129+
// Determine file path and header for the config file
108130
var pathAnnotation = configClass.getAnnotation(ConfigPath.class);
109131
var filePath = pathAnnotation == null ? configClass.getSimpleName() : pathAnnotation.value();
110132

@@ -114,53 +136,60 @@ private Config initConfigFile(Class<?> configClass) {
114136
return configManager.getNewConfig(filePath, header);
115137
}
116138

139+
/**
140+
* Initializes a single field of the configuration with its default value or annotated default.
141+
*
142+
* @param field The field from the record to initialize in the config.
143+
* @param config The Config object where the field should be initialized.
144+
*/
117145
private void initializeField(Field field, Config config) {
118146
if (field.getAnnotation(ConfigNode.class) == null) return;
119147

120148
var nameAnnotation = field.getAnnotation(NodeName.class);
121-
var nodeName = nameAnnotation == null ? field.getName() : nameAnnotation.value();
149+
var nodeName = nameAnnotation != null ? nameAnnotation.value() : field.getName();
150+
151+
var handler = ConfigTypeHandlerFactory.getHandler(field.getType());
122152

123153
var defaultAnnotation = field.getAnnotation(NodeDefault.class);
124-
var nodeDefault = defaultAnnotation == null ? constructDefaultField(field) : parseDefault(field);
154+
var nodeDefault = defaultAnnotation != null ? parseDefault(field) : handler.getDefault(field);
125155

126156
var commentAnnotation = field.getAnnotation(NodeComment.class);
127-
var nodeComment = commentAnnotation == null ? new String[]{} : commentAnnotation.value();
157+
var nodeComment = commentAnnotation != null ? commentAnnotation.value() : new String[]{};
128158

129-
if (config.get(nodeName) != null) return;
130-
config.set(nodeName, nodeDefault, nodeComment);
131-
config.saveConfig();
159+
if (config.get(nodeName) == null) {
160+
handler.setValue(config, nodeName, nodeDefault, nodeComment);
161+
config.saveConfig();
162+
}
132163
}
133164

165+
/**
166+
* Constructs a default value for a field when no default is provided via annotations.
167+
*
168+
* @param f The field for which to construct a default value.
169+
* @return An object representing the default value for the field, or null on failure.
170+
*/
134171
private Object constructDefaultField(Field f) {
172+
135173
try {
136174
if (f.getType().isPrimitive()) {
137-
if (f.getType().equals(int.class))
138-
return 0;
139-
if (f.getType().equals(boolean.class))
140-
return false;
141-
if (f.getType().equals(double.class))
142-
return 0.0;
143-
if (f.getType().equals(List.class))
144-
return new ArrayList<>();
175+
var handler = ConfigTypeHandlerFactory.getHandler(f.getType());
176+
return handler.getDefault(f);
145177
}
146178
return f.getType().getDeclaredConstructor().newInstance();
147-
} catch (NoSuchMethodException | InvocationTargetException |
148-
InstantiationException | IllegalAccessException e) {
179+
} catch (Exception e) {
149180
logger.err("Failed to instantiate default value for field: " + f.getName());
150181
}
151182
return null;
152183
}
153184

185+
/**
186+
* Parses the default value from the @NodeDefault annotation for a field.
187+
*
188+
* @param field The field with a @NodeDefault annotation.
189+
* @return The parsed default value as an object, according to the field's type.
190+
*/
154191
private Object parseDefault(Field field) {
155-
var defaultAnnotation = field.getAnnotation(NodeDefault.class);
156-
if (field.getType().equals(int.class))
157-
return Integer.valueOf(defaultAnnotation.value());
158-
if (field.getType().equals(boolean.class))
159-
return Boolean.valueOf(defaultAnnotation.value());
160-
if (field.getType().equals(double.class))
161-
return Double.valueOf(defaultAnnotation.value());
162-
if (field.getType().equals(List.class))
163-
return Arrays.stream(defaultAnnotation.value().split(",\\s+")).toList();
164-
return defaultAnnotation.value();
192+
var handler = ConfigTypeHandlerFactory.getHandler(field.getType());
193+
return handler.getDefault(field);
165194
}
166195
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.cyr1en.commandprompter.config.handlers;
2+
3+
import com.cyr1en.kiso.mc.configuration.base.Config;
4+
5+
import java.lang.reflect.Field;
6+
7+
public interface ConfigTypeHandler<T> {
8+
T getValue(Config config, String nodeName, Field field);
9+
10+
void setValue(Config config, String nodeName, Object value, String[] comments);
11+
12+
T getDefault(Field field);
13+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.cyr1en.commandprompter.config.handlers;
2+
3+
import com.cyr1en.commandprompter.config.handlers.impl.*;
4+
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
public class ConfigTypeHandlerFactory {
10+
private static final Map<Class<?>, ConfigTypeHandler<?>> handlers = new HashMap<>();
11+
12+
static {
13+
handlers.put(int.class, new IntegerHandler());
14+
handlers.put(boolean.class, new BooleanHandler());
15+
handlers.put(String.class, new StringHandler());
16+
handlers.put(double.class, new DoubleHandler());
17+
handlers.put(List.class, new ListHandler());
18+
}
19+
20+
public static ConfigTypeHandler<?> getHandler(Class<?> type) {
21+
if (handlers.containsKey(type)) {
22+
return handlers.get(type);
23+
}
24+
return handlers.getOrDefault(type, new StringHandler()); // Fallback handler
25+
}
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.cyr1en.commandprompter.config.handlers.impl;
2+
3+
import com.cyr1en.commandprompter.config.annotations.field.NodeDefault;
4+
import com.cyr1en.commandprompter.config.handlers.ConfigTypeHandler;
5+
import com.cyr1en.kiso.mc.configuration.base.Config;
6+
7+
import java.lang.reflect.Field;
8+
9+
public class BooleanHandler implements ConfigTypeHandler<Boolean> {
10+
11+
12+
@Override
13+
public Boolean getValue(Config config, String nodeName, Field field) {
14+
return config.getBoolean(nodeName);
15+
}
16+
17+
@Override
18+
public void setValue(Config config, String nodeName, Object value, String[] comments) {
19+
config.set(nodeName, value, comments);
20+
}
21+
22+
@Override
23+
public Boolean getDefault(Field field) {
24+
var defaultAnnotation = field.getAnnotation(NodeDefault.class);
25+
return defaultAnnotation != null && Boolean.parseBoolean(defaultAnnotation.value());
26+
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.cyr1en.commandprompter.config.handlers.impl;
2+
3+
import com.cyr1en.commandprompter.config.annotations.field.NodeDefault;
4+
import com.cyr1en.commandprompter.config.handlers.ConfigTypeHandler;
5+
import com.cyr1en.kiso.mc.configuration.base.Config;
6+
7+
import java.lang.reflect.Field;
8+
9+
public class DoubleHandler implements ConfigTypeHandler<Double> {
10+
@Override
11+
public Double getValue(Config config, String nodeName, Field field) {
12+
return config.getDouble(nodeName);
13+
}
14+
15+
@Override
16+
public void setValue(Config config, String nodeName, Object value, String[] comments) {
17+
config.set(nodeName, value, comments);
18+
}
19+
20+
@Override
21+
public Double getDefault(Field field) {
22+
var defaultAnnotation = field.getAnnotation(NodeDefault.class);
23+
return defaultAnnotation != null ? Double.parseDouble(defaultAnnotation.value()) : 0.0;
24+
}
25+
}

0 commit comments

Comments
 (0)