Skip to content

Commit 1322563

Browse files
authored
Feature - Mod Status API (#243)
* Apollo Mod Status API * Remove mod options loading logic from auto gen * example: add mod status command * Receive mod status from the handshake packet * don't use WeakHashMap for options * Markdown docs * Fix hyperlinks * Move mod status API into ModSettingsModule * Option API improvements * Remove debug * add mod settings module tests * Make global options protected * Link mod available options in the mod status example * example: remove debug * Prepare for merge
1 parent fb97136 commit 1322563

File tree

32 files changed

+1200
-217
lines changed

32 files changed

+1200
-217
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* This file is part of Apollo, licensed under the MIT License.
3+
*
4+
* Copyright (c) 2023 Moonsworth
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package com.lunarclient.apollo.event.modsetting;
25+
26+
import com.lunarclient.apollo.event.Event;
27+
import com.lunarclient.apollo.option.Option;
28+
import com.lunarclient.apollo.player.ApolloPlayer;
29+
import lombok.Value;
30+
import org.jetbrains.annotations.Nullable;
31+
32+
/**
33+
* Represents an event that is fired when an option is updated.
34+
*
35+
* @since 1.2.1
36+
*/
37+
@Value
38+
public class ApolloUpdateModOptionEvent implements Event {
39+
40+
/**
41+
* The {@link ApolloPlayer} that the option was updated for.
42+
*
43+
* @return the player
44+
* @since 1.2.1
45+
*/
46+
ApolloPlayer player;
47+
48+
/**
49+
* The {@link Option} that was updated.
50+
*
51+
* @return the option
52+
* @since 1.2.1
53+
*/
54+
Option<?, ?, ?> option;
55+
56+
/**
57+
* The new value of the option.
58+
*
59+
* @return the new value
60+
* @since 1.2.1
61+
*/
62+
@Nullable Object value;
63+
64+
}

api/src/main/java/com/lunarclient/apollo/module/ApolloModule.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,17 @@ protected ApolloModule() {
120120
* @since 1.0.0
121121
*/
122122
protected void registerOptions(Option<?, ?, ?>... options) {
123-
this.optionKeys.addAll(Arrays.asList(options));
123+
this.registerOptions(Arrays.asList(options));
124+
}
125+
126+
/**
127+
* Registers {@link Option}s for this module.
128+
*
129+
* @param options the option keys
130+
* @since 1.2.1
131+
*/
132+
protected void registerOptions(Collection<Option<?, ?, ?>> options) {
133+
this.optionKeys.addAll(options);
124134
}
125135

126136
/**

api/src/main/java/com/lunarclient/apollo/module/modsetting/ModSettingModule.java

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,25 @@
2424
package com.lunarclient.apollo.module.modsetting;
2525

2626
import com.lunarclient.apollo.ApolloPlatform;
27-
import com.lunarclient.apollo.mods.Mods;
2827
import com.lunarclient.apollo.module.ApolloModule;
2928
import com.lunarclient.apollo.module.ModuleDefinition;
3029
import com.lunarclient.apollo.option.Option;
30+
import com.lunarclient.apollo.player.ApolloPlayer;
3131
import com.lunarclient.apollo.util.ConfigTarget;
32-
import java.lang.reflect.Field;
3332
import java.util.Arrays;
3433
import java.util.Collection;
34+
import lombok.NonNull;
35+
import org.jetbrains.annotations.ApiStatus;
36+
import org.jetbrains.annotations.NotNull;
3537

3638
/**
3739
* Represents the mod settings module.
3840
*
3941
* @since 1.0.0
4042
*/
43+
@ApiStatus.NonExtendable
4144
@ModuleDefinition(id = "mod_setting", name = "Mod Setting", configTarget = ConfigTarget.MOD_SETTINGS)
42-
public final class ModSettingModule extends ApolloModule {
43-
44-
ModSettingModule() {
45-
this.registerModOptions();
46-
}
45+
public abstract class ModSettingModule extends ApolloModule {
4746

4847
@Override
4948
public Collection<ApolloPlatform.Kind> getSupportedPlatforms() {
@@ -55,20 +54,16 @@ public boolean isClientNotify() {
5554
return true;
5655
}
5756

58-
private void registerModOptions() {
59-
for (Class<?> mod : Mods.ALL_MODS) {
60-
Field[] fields = mod.getDeclaredFields();
61-
62-
for (Field field : fields) {
63-
try {
64-
field.setAccessible(true);
65-
Option<?, ?, ?> option = (Option<?, ?, ?>) field.get(Option.class);
66-
this.registerOptions(option);
67-
} catch (IllegalAccessException e) {
68-
e.printStackTrace();
69-
}
70-
}
71-
}
72-
}
57+
/**
58+
* Gets the value of the specified {@link Option} for the {@link ApolloPlayer}.
59+
*
60+
* @param player the apollo player
61+
* @param option the option
62+
* @param <T> the value type
63+
* @param <C> the option type
64+
* @return the value of the option
65+
* @since 1.2.1
66+
*/
67+
public abstract <T, C extends Option<T, ?, ?>> T getStatus(@NotNull ApolloPlayer player, @NonNull C option);
7368

7469
}

api/src/main/java/com/lunarclient/apollo/option/EmptyOptions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.lunarclient.apollo.player.ApolloPlayer;
2727
import java.util.Collections;
2828
import java.util.Iterator;
29+
import java.util.Map;
2930
import java.util.Optional;
3031
import java.util.function.BiFunction;
3132
import lombok.AccessLevel;
@@ -97,6 +98,16 @@ public <T> void replace(ApolloPlayer player, Option<?, ?, ?> option, BiFunction<
9798

9899
}
99100

101+
@Override
102+
public <T, C extends Option<T, ?, ?>> void register(C option) {
103+
104+
}
105+
106+
@Override
107+
public Map<String, Option<?, ?, ?>> getRegistry() {
108+
return Collections.emptyMap();
109+
}
110+
100111
@Override
101112
public @NonNull Iterator<Option<?, ?, ?>> iterator() {
102113
return Collections.emptyIterator();

api/src/main/java/com/lunarclient/apollo/option/Option.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
@Getter
4444
@EqualsAndHashCode
4545
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
46-
public abstract class Option<V, M extends OptionBuilder<V, M, I>, I extends Option<V, M, I>> {
46+
public abstract class Option<V, M extends OptionBuilder<V, M, I>, I extends Option<V, M, I>> implements Cloneable {
4747

4848
/**
4949
* Returns a new {@link SimpleOption.SimpleOptionBuilder}.
@@ -149,4 +149,14 @@ public String getKey() {
149149
return String.join(".", this.getPath());
150150
}
151151

152+
@Override
153+
@SuppressWarnings("unchecked")
154+
public Option<V, M, I> clone() {
155+
try {
156+
return (Option<V, M, I>) super.clone();
157+
} catch (CloneNotSupportedException e) {
158+
throw new AssertionError(e);
159+
}
160+
}
161+
152162
}

api/src/main/java/com/lunarclient/apollo/option/Options.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package com.lunarclient.apollo.option;
2525

2626
import com.lunarclient.apollo.player.ApolloPlayer;
27+
import java.util.Map;
2728
import java.util.Optional;
2829
import java.util.function.BiFunction;
2930
import org.jetbrains.annotations.Nullable;
@@ -188,4 +189,22 @@ static Options empty() {
188189
*/
189190
<T> void replace(ApolloPlayer player, Option<?, ?, ?> option, BiFunction<Option<?, ?, ?>, T, T> remappingFunction);
190191

192+
/**
193+
* Registers the provided {@code C} option for the {@link Options} implementation.
194+
*
195+
* @param option the option
196+
* @param <T> the value type
197+
* @param <C> the option type
198+
* @since 1.2.1
199+
*/
200+
<T, C extends Option<T, ?, ?>> void register(C option);
201+
202+
/**
203+
* Returns the internal registry containing all registered {@link Option} instances, mapped by their keys.
204+
*
205+
* @return the map of option keys to their corresponding {@link Option} instances
206+
* @since 1.2.1
207+
*/
208+
Map<String, Option<?, ?, ?>> getRegistry();
209+
191210
}

common/src/main/java/com/lunarclient/apollo/ApolloManager.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626
import com.google.gson.Gson;
2727
import com.google.gson.GsonBuilder;
2828
import com.lunarclient.apollo.api.ApolloHttpManager;
29+
import com.lunarclient.apollo.mods.ApolloModsManager;
2930
import com.lunarclient.apollo.module.ApolloModuleManagerImpl;
3031
import com.lunarclient.apollo.network.ApolloNetworkManager;
3132
import com.lunarclient.apollo.option.ConfigOptions;
3233
import com.lunarclient.apollo.option.Option;
34+
import com.lunarclient.apollo.option.Options;
3335
import com.lunarclient.apollo.option.config.CommonSerializers;
3436
import com.lunarclient.apollo.player.ApolloPlayerManagerImpl;
3537
import com.lunarclient.apollo.roundtrip.ApolloRoundtripManager;
@@ -39,9 +41,7 @@
3941
import com.lunarclient.apollo.version.ApolloVersionManager;
4042
import com.lunarclient.apollo.world.ApolloWorldManagerImpl;
4143
import java.nio.file.Path;
42-
import java.util.Arrays;
43-
import java.util.LinkedList;
44-
import java.util.List;
44+
import java.util.Collection;
4545
import lombok.Getter;
4646
import lombok.Setter;
4747

@@ -67,15 +67,14 @@ public final class ApolloManager {
6767
*/
6868
public static final Gson GSON = new GsonBuilder().create();
6969

70-
private static final List<Option<?, ?, ?>> optionKeys = new LinkedList<>();
71-
7270
private static ApolloPlatform platform;
7371

7472
@Getter private static ApolloRoundtripManager roundtripManager;
7573
@Getter private static ApolloHttpManager httpManager;
7674
@Getter private static ApolloNetworkManager networkManager;
7775
@Getter private static ApolloVersionManager versionManager;
7876
@Getter private static ApolloStatsManager statsManager;
77+
@Getter private static ApolloModsManager modsManager;
7978
@Getter @Setter private static ApolloMetadataManager metadataManager;
8079

8180
@Getter private static Path configPath;
@@ -106,6 +105,7 @@ public static void bootstrap(ApolloPlatform platform) {
106105
ApolloManager.networkManager = new ApolloNetworkManager();
107106
ApolloManager.versionManager = new ApolloVersionManager();
108107
ApolloManager.statsManager = new ApolloStatsManager();
108+
ApolloManager.modsManager = new ApolloModsManager();
109109

110110
new CommonSerializers();
111111

@@ -124,7 +124,10 @@ public static void bootstrap(ApolloPlatform platform) {
124124
* @since 1.0.0
125125
*/
126126
public static void registerOptions(Option<?, ?, ?>... options) {
127-
ApolloManager.optionKeys.addAll(Arrays.asList(options));
127+
Options platformOptions = Apollo.getPlatform().getOptions();
128+
for (Option<?, ?, ?> option : options) {
129+
platformOptions.register(option);
130+
}
128131
}
129132

130133
/**
@@ -147,8 +150,9 @@ public static void loadConfiguration() throws Throwable {
147150
config.reset();
148151
}
149152

153+
Collection<Option<?, ?, ?>> platformOptions = Apollo.getPlatform().getOptions().getRegistry().values();
150154
ApolloConfig generalSettings = ApolloConfig.compute(ApolloManager.configPath, ConfigTarget.GENERAL_SETTINGS);
151-
ConfigOptions.loadOptions(ApolloManager.platform.getOptions(), generalSettings.node(), ApolloManager.optionKeys);
155+
ConfigOptions.loadOptions(ApolloManager.platform.getOptions(), generalSettings.node(), platformOptions);
152156
}
153157

154158
/**
@@ -157,8 +161,9 @@ public static void loadConfiguration() throws Throwable {
157161
* @since 1.0.0
158162
*/
159163
public static void saveConfiguration() throws Throwable {
164+
Collection<Option<?, ?, ?>> platformOptions = Apollo.getPlatform().getOptions().getRegistry().values();
160165
ApolloConfig generalSettings = ApolloConfig.compute(ApolloManager.configPath, ConfigTarget.GENERAL_SETTINGS);
161-
ConfigOptions.saveOptions(ApolloManager.platform.getOptions(), generalSettings.node(), ApolloManager.optionKeys);
166+
ConfigOptions.saveOptions(ApolloManager.platform.getOptions(), generalSettings.node(), platformOptions);
162167

163168
((ApolloModuleManagerImpl) Apollo.getModuleManager()).saveConfiguration();
164169

0 commit comments

Comments
 (0)