Skip to content

Commit 8a11482

Browse files
committed
Add ServerlinkModule#LEGACY_BUTTON_PLACEMENT & ServerLinkModule#MODERN_BUTTON_PLACEMENT (#291)
1 parent b60f27d commit 8a11482

15 files changed

Lines changed: 389 additions & 9 deletions

File tree

api/src/main/java/com/lunarclient/apollo/module/combat/CombatModule.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ public final class CombatModule extends ApolloModule {
4545
* @since 1.0.4
4646
*/
4747
public static final SimpleOption<Boolean> DISABLE_MISS_PENALTY = Option.<Boolean>builder()
48-
.comment("Set to 'true' to remove the miss penalty on all versions 1.8 and above, otherwise 'false'. Enabling this option may cause compatibility issues with anti-cheats.")
48+
.comment(
49+
"Set to 'true' to remove the miss penalty on all versions 1.8 and above, otherwise 'false'.",
50+
"Enabling this option may cause compatibility issues with anti-cheats."
51+
)
4952
.node("disable-miss-penalty").type(TypeToken.get(Boolean.class))
5053
.defaultValue(false).notifyClient().build();
5154

@@ -58,7 +61,10 @@ public final class CombatModule extends ApolloModule {
5861
* @since 1.2.8
5962
*/
6063
public static final SimpleOption<Boolean> ALLOW_DIG_AND_USE = Option.<Boolean>builder()
61-
.comment("Set to 'true' to allow digging and using an item at the same time on all versions 1.8 and above, otherwise 'false'. Enabling this option may cause compatibility issues with anti-cheats.")
64+
.comment(
65+
"Set to 'true' to allow digging and using an item at the same time on all versions 1.8 and above, otherwise 'false'.",
66+
"Enabling this option may cause compatibility issues with anti-cheats."
67+
)
6268
.node("allow-dig-and-use").type(TypeToken.get(Boolean.class))
6369
.defaultValue(false).notifyClient().build();
6470

api/src/main/java/com/lunarclient/apollo/module/serverlink/ServerLinkModule.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@
2626
import com.lunarclient.apollo.common.icon.ResourceLocationIcon;
2727
import com.lunarclient.apollo.module.ApolloModule;
2828
import com.lunarclient.apollo.module.ModuleDefinition;
29+
import com.lunarclient.apollo.module.serverlink.pausemenu.LegacyServerLinkPlacement;
30+
import com.lunarclient.apollo.module.serverlink.pausemenu.ModernServerLinkPlacement;
31+
import com.lunarclient.apollo.option.EnumOption;
32+
import com.lunarclient.apollo.option.Option;
2933
import com.lunarclient.apollo.recipients.Recipients;
34+
import io.leangen.geantyref.TypeToken;
3035
import java.util.List;
3136
import org.jetbrains.annotations.ApiStatus;
3237

@@ -42,6 +47,49 @@
4247
@ModuleDefinition(id = "server_link", name = "Server Link")
4348
public abstract class ServerLinkModule extends ApolloModule {
4449

50+
/**
51+
* Controls where the server links button is placed in the pause menu
52+
* (1.7-1.12), where it is added on a new line by default.
53+
*
54+
* @since 1.2.8
55+
*/
56+
public static final EnumOption<LegacyServerLinkPlacement> LEGACY_BUTTON_PLACEMENT = Option.<LegacyServerLinkPlacement>enumerator()
57+
.comment(
58+
"Where the server links button appears in the pause menu (1.7-1.12), added on a new line by default.",
59+
" 'NEW_ROW' adds a dedicated row.",
60+
" 'REPLACE_ACHIEVEMENTS' reuses the achievements button.",
61+
" 'REPLACE_STATISTICS' reuses the statistics button."
62+
)
63+
.node("legacy-button-placement").type(TypeToken.get(LegacyServerLinkPlacement.class))
64+
.defaultValue(LegacyServerLinkPlacement.NEW_ROW).notifyClient().build();
65+
66+
/**
67+
* Controls where the server links button is placed in the pause menu
68+
* (1.16.1+), where it replaces the existing report bugs button by default.
69+
*
70+
* <p>On 1.21 and above the server links button is handled natively and this
71+
* option has no effect.</p>
72+
*
73+
* @since 1.2.8
74+
*/
75+
public static final EnumOption<ModernServerLinkPlacement> MODERN_BUTTON_PLACEMENT = Option.<ModernServerLinkPlacement>enumerator()
76+
.comment(
77+
"Where the server links button appears in the pause menu (1.16.1+), replaces the existing report bugs button by default.",
78+
" 'REPLACE_REPORT_BUGS' reuses the report bugs button.",
79+
" 'REPLACE_ACHIEVEMENTS' reuses the advancements button.",
80+
" 'REPLACE_STATISTICS' reuses the statistics button.",
81+
"Has no effect on 1.21+ (handled natively)."
82+
)
83+
.node("modern-button-placement").type(TypeToken.get(ModernServerLinkPlacement.class))
84+
.defaultValue(ModernServerLinkPlacement.REPLACE_REPORT_BUGS).notifyClient().build();
85+
86+
ServerLinkModule() {
87+
this.registerOptions(
88+
ServerLinkModule.LEGACY_BUTTON_PLACEMENT,
89+
ServerLinkModule.MODERN_BUTTON_PLACEMENT
90+
);
91+
}
92+
4593
/**
4694
* Overrides the server link menu title image for the {@link Recipients}.
4795
*
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This file is part of Apollo, licensed under the MIT License.
3+
*
4+
* Copyright (c) 2026 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.module.serverlink.pausemenu;
25+
26+
/**
27+
* Represents where the server links button is placed in the pause menu
28+
* (1.7-1.12), where it is added on a new line by default.
29+
*
30+
* @since 1.2.8
31+
*/
32+
public enum LegacyServerLinkPlacement {
33+
34+
/**
35+
* Adds the server links button on a dedicated new row, shifting the
36+
* remaining buttons down.
37+
*
38+
* @since 1.2.8
39+
*/
40+
NEW_ROW,
41+
42+
/**
43+
* Replaces the vanilla achievements button with the server links button.
44+
*
45+
* @since 1.2.8
46+
*/
47+
REPLACE_ACHIEVEMENTS,
48+
49+
/**
50+
* Replaces the vanilla statistics button with the server links button.
51+
*
52+
* @since 1.2.8
53+
*/
54+
REPLACE_STATISTICS
55+
56+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* This file is part of Apollo, licensed under the MIT License.
3+
*
4+
* Copyright (c) 2026 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.module.serverlink.pausemenu;
25+
26+
/**
27+
* Represents where the server links button is placed in the pause menu
28+
* (1.16.1+), where it replaces the existing report bugs button by default.
29+
*
30+
* <p>On 1.21 and above the server links button is handled natively and this
31+
* option has no effect.</p>
32+
*
33+
* @since 1.2.8
34+
*/
35+
public enum ModernServerLinkPlacement {
36+
37+
/**
38+
* Replaces the report bugs button with the server links button.
39+
*
40+
* @since 1.2.8
41+
*/
42+
REPLACE_REPORT_BUGS,
43+
44+
/**
45+
* Replaces the vanilla advancements button with the server links button.
46+
*
47+
* @since 1.2.8
48+
*/
49+
REPLACE_ACHIEVEMENTS,
50+
51+
/**
52+
* Replaces the vanilla statistics button with the server links button.
53+
*
54+
* @since 1.2.8
55+
*/
56+
REPLACE_STATISTICS
57+
58+
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ public M comment(@Nullable String comment) {
8686
return (M) this;
8787
}
8888

89+
/**
90+
* Sets the option comment to the provided lines, joined with a newline, and
91+
* returns this builder.
92+
*
93+
* <p>Each provided line is rendered as its own comment line in the
94+
* configuration.</p>
95+
*
96+
* @param lines the comment lines
97+
* @return this builder
98+
* @since 1.2.8
99+
*/
100+
public M comment(@NonNull String... lines) {
101+
this.comment = String.join("\n", lines);
102+
return (M) this;
103+
}
104+
89105
/**
90106
* Sets the option default value to the provided {@code T} value and
91107
* returns this builder.

docs/developers/lightweight/json/packet-util.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ To utilize Apollo Modules, first define a list of the modules you want to use:
1515
```java
1616
private static final List<String> APOLLO_MODULES = Arrays.asList("auto_text_hotkey", "beam", "border", "chat", "colored_fire", "combat", "cooldown",
1717
"entity", "glint", "glow", "hologram", "inventory", "limb", "mod_setting", "nametag", "nick_hider", "notification", "pay_now", "packet_enrichment",
18-
"rich_presence", "saturation", "server_rule", "staff_mod", "stopwatch", "team", "tebex", "title", "tnt_countdown", "transfer", "vignette", "waypoint"
18+
"rich_presence", "saturation", "server_link", "server_rule", "staff_mod", "stopwatch", "team", "tebex", "title", "tnt_countdown", "transfer", "vignette", "waypoint"
1919
);
2020
```
2121

@@ -41,6 +41,8 @@ static {
4141
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-chat-close.send-packet", false);
4242
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-use-item.send-packet", false);
4343
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-use-item-bucket.send-packet", false);
44+
CONFIG_MODULE_PROPERTIES.put("server_link", "legacy-button-placement", "NEW_ROW");
45+
CONFIG_MODULE_PROPERTIES.put("server_link", "modern-button-placement", "REPLACE_REPORT_BUGS");
4446
CONFIG_MODULE_PROPERTIES.put("server_rule", "competitive-game", false);
4547
CONFIG_MODULE_PROPERTIES.put("server_rule", "competitive-commands", Arrays.asList("/server", "/servers", "/hub"));
4648
CONFIG_MODULE_PROPERTIES.put("server_rule", "disable-shaders", false);

docs/developers/lightweight/protobuf/packet-util.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ To utilize Apollo Modules, first define a list of the modules you want to use:
1515
```java
1616
private static final List<String> APOLLO_MODULES = Arrays.asList("auto_text_hotkey", "beam", "border", "chat", "colored_fire", "combat", "cooldown",
1717
"entity", "glint", "glow", "hologram", "inventory", "limb", "mod_setting", "nametag", "nick_hider", "notification", "pay_now", "packet_enrichment",
18-
"rich_presence", "saturation", "server_rule", "staff_mod", "stopwatch", "team", "tebex", "title", "tnt_countdown", "transfer", "vignette", "waypoint"
18+
"rich_presence", "saturation", "server_link", "server_rule", "staff_mod", "stopwatch", "team", "tebex", "title", "tnt_countdown", "transfer", "vignette", "waypoint"
1919
);
2020
```
2121

@@ -41,6 +41,8 @@ static {
4141
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-chat-close.send-packet", Value.newBuilder().setBoolValue(false).build());
4242
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-use-item.send-packet", Value.newBuilder().setBoolValue(false).build());
4343
CONFIG_MODULE_PROPERTIES.put("packet_enrichment", "player-use-item-bucket.send-packet", Value.newBuilder().setBoolValue(false).build());
44+
CONFIG_MODULE_PROPERTIES.put("server_link", "legacy-button-placement", Value.newBuilder().setStringValue("NEW_ROW").build());
45+
CONFIG_MODULE_PROPERTIES.put("server_link", "modern-button-placement", Value.newBuilder().setStringValue("REPLACE_REPORT_BUGS").build());
4446
CONFIG_MODULE_PROPERTIES.put("server_rule", "competitive-game", Value.newBuilder().setBoolValue(false).build());
4547
CONFIG_MODULE_PROPERTIES.put("server_rule", "competitive-commands", Value.newBuilder().setListValue(
4648
ListValue.newBuilder().addAllValues(Arrays.asList(

docs/developers/modules/serverlink.mdx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,24 @@ public void resetServerLinksExample(Player viewer) {
100100
}
101101
```
102102

103+
### Set Legacy Button Placement
104+
105+
```java
106+
public void setLegacyButtonPlacementExample(String placement) {
107+
LegacyServerLinkPlacement legacyPlacement = LegacyServerLinkPlacement.valueOf(placement);
108+
this.serverLinkModule.getOptions().set(ServerLinkModule.LEGACY_BUTTON_PLACEMENT, legacyPlacement);
109+
}
110+
```
111+
112+
### Set Modern Button Placement
113+
114+
```java
115+
public void setModernButtonPlacementExample(String placement) {
116+
ModernServerLinkPlacement modernPlacement = ModernServerLinkPlacement.valueOf(placement);
117+
this.serverLinkModule.getOptions().set(ServerLinkModule.MODERN_BUTTON_PLACEMENT, modernPlacement);
118+
}
119+
```
120+
103121
### `ServerLink` Options
104122

105123
`.id(String)` sets a unique identifier for the server link.
@@ -205,6 +223,30 @@ public void resetServerLinksExample(Player viewer) {
205223
}
206224
```
207225

226+
**Set Legacy Button Placement**
227+
228+
```java
229+
public void setLegacyButtonPlacementExample(String placement) {
230+
Map<String, Value> properties = new HashMap<>();
231+
properties.put("legacy-button-placement", Value.newBuilder().setStringValue(placement).build());
232+
233+
ConfigurableSettings settings = ProtobufPacketUtil.createModuleMessage("server_link", properties);
234+
ProtobufPacketUtil.broadcastPacket(settings);
235+
}
236+
```
237+
238+
**Set Modern Button Placement**
239+
240+
```java
241+
public void setModernButtonPlacementExample(String placement) {
242+
Map<String, Value> properties = new HashMap<>();
243+
properties.put("modern-button-placement", Value.newBuilder().setStringValue(placement).build());
244+
245+
ConfigurableSettings settings = ProtobufPacketUtil.createModuleMessage("server_link", properties);
246+
ProtobufPacketUtil.broadcastPacket(settings);
247+
}
248+
```
249+
208250
</Tab>
209251

210252
<Tab>
@@ -288,6 +330,44 @@ public void resetServerLinksExample(Player viewer) {
288330
}
289331
```
290332

333+
**Set Legacy Button Placement**
334+
335+
```java
336+
public void setLegacyButtonPlacementExample(String placement) {
337+
Map<String, Object> properties = new HashMap<>();
338+
properties.put("legacy-button-placement", placement);
339+
340+
JsonObject message = JsonUtil.createEnableModuleObjectWithType("server_link", properties);
341+
JsonPacketUtil.broadcastPacket(message);
342+
}
343+
```
344+
345+
**Set Modern Button Placement**
346+
347+
```java
348+
public void setModernButtonPlacementExample(String placement) {
349+
Map<String, Object> properties = new HashMap<>();
350+
properties.put("modern-button-placement", placement);
351+
352+
JsonObject message = JsonUtil.createEnableModuleObjectWithType("server_link", properties);
353+
JsonPacketUtil.broadcastPacket(message);
354+
}
355+
```
356+
291357
</Tab>
292358

293359
</Tabs>
360+
361+
## Available options
362+
363+
- __`LEGACY_BUTTON_PLACEMENT`__
364+
- Where the server links button appears in the pause menu (1.7-1.12), where it is added on a new line by default.
365+
- Values
366+
- Type: `LegacyServerLinkPlacement` (`NEW_ROW`, `REPLACE_ACHIEVEMENTS`, `REPLACE_STATISTICS`)
367+
- Default: `NEW_ROW`
368+
369+
- __`MODERN_BUTTON_PLACEMENT`__
370+
- Where the server links button appears in the pause menu (1.16.1+), where it replaces the existing report bugs button by default. Has no effect on 1.21+ (handled natively).
371+
- Values
372+
- Type: `ModernServerLinkPlacement` (`REPLACE_REPORT_BUGS`, `REPLACE_ACHIEVEMENTS`, `REPLACE_STATISTICS`)
373+
- Default: `REPLACE_REPORT_BUGS`

example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/ServerLinkApiExample.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import com.lunarclient.apollo.example.module.impl.ServerLinkExample;
3030
import com.lunarclient.apollo.module.serverlink.ServerLink;
3131
import com.lunarclient.apollo.module.serverlink.ServerLinkModule;
32+
import com.lunarclient.apollo.module.serverlink.pausemenu.LegacyServerLinkPlacement;
33+
import com.lunarclient.apollo.module.serverlink.pausemenu.ModernServerLinkPlacement;
3234
import com.lunarclient.apollo.player.ApolloPlayer;
3335
import java.util.Optional;
3436
import net.kyori.adventure.text.Component;
@@ -98,4 +100,16 @@ public void resetServerLinksExample(Player viewer) {
98100
apolloPlayerOpt.ifPresent(this.serverLinkModule::resetServerLinks);
99101
}
100102

103+
@Override
104+
public void setLegacyButtonPlacementExample(String placement) {
105+
LegacyServerLinkPlacement legacyPlacement = LegacyServerLinkPlacement.valueOf(placement);
106+
this.serverLinkModule.getOptions().set(ServerLinkModule.LEGACY_BUTTON_PLACEMENT, legacyPlacement);
107+
}
108+
109+
@Override
110+
public void setModernButtonPlacementExample(String placement) {
111+
ModernServerLinkPlacement modernPlacement = ModernServerLinkPlacement.valueOf(placement);
112+
this.serverLinkModule.getOptions().set(ServerLinkModule.MODERN_BUTTON_PLACEMENT, modernPlacement);
113+
}
114+
101115
}

0 commit comments

Comments
 (0)