Skip to content

Commit c4760af

Browse files
authored
Server links support (#2754)
* add util method * add link send event * add player and server mechs * move event to paper * fixes * fix * some fixes * meta change * fixes * ups * rename
1 parent 543e135 commit c4760af

File tree

7 files changed

+189
-0
lines changed

7 files changed

+189
-0
lines changed

paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ public static void init() {
6666
ScriptEvent.registerScriptEvent(PlayerItemTakesDamageScriptEventPaperImpl.class);
6767
ScriptEvent.registerScriptEvent(PlayerJumpsScriptEventPaperImpl.class);
6868
ScriptEvent.registerScriptEvent(PlayerLecternPageChangeScriptEvent.class);
69+
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
70+
ScriptEvent.registerScriptEvent(PlayerLinksSendScriptEvent.class);
71+
}
6972
ScriptEvent.registerScriptEvent(PlayerLoomPatternSelectScriptEvent.class);
7073
ScriptEvent.registerScriptEvent(PlayerNameEntityScriptEvent.class);
7174
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.denizenscript.denizen.paper.events;
2+
3+
import com.denizenscript.denizen.events.BukkitScriptEvent;
4+
import com.denizenscript.denizen.objects.PlayerTag;
5+
import com.denizenscript.denizen.utilities.Utilities;
6+
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
7+
import com.denizenscript.denizencore.objects.core.ListTag;
8+
import com.denizenscript.denizencore.scripts.ScriptEntryData;
9+
import io.papermc.paper.connection.PlayerConfigurationConnection;
10+
import io.papermc.paper.connection.PlayerGameConnection;
11+
import org.bukkit.event.EventHandler;
12+
import org.bukkit.event.Listener;
13+
import org.bukkit.event.player.PlayerLinksSendEvent;
14+
15+
public class PlayerLinksSendScriptEvent extends BukkitScriptEvent implements Listener {
16+
17+
// <--[event]
18+
// @Events
19+
// player receives links
20+
//
21+
// @Group Paper
22+
//
23+
// @Plugin Paper
24+
//
25+
// @Triggers when a player receives a list of links
26+
//
27+
// @Determine
28+
// "LINKS:<ListTag(MapTag)>" to set the links sent to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
29+
// "ADD_LINKS:<ListTag(MapTag)>" to add to the links sent to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
30+
//
31+
// @Player Always.
32+
//
33+
// @Warning this may fire early in the player login process, during which the linked player is essentially an offline player
34+
//
35+
// -->
36+
37+
public PlayerLinksSendEvent event;
38+
public PlayerTag player;
39+
40+
public PlayerLinksSendScriptEvent() {
41+
registerCouldMatcher("player receives links");
42+
this.<PlayerLinksSendScriptEvent, ListTag>registerDetermination("links", ListTag.class, (evt, context, value) -> {
43+
Utilities.replaceServerLinks(evt.event.getLinks(), value, context);
44+
});
45+
this.<PlayerLinksSendScriptEvent, ListTag>registerDetermination("add_links", ListTag.class, (evt, context, value) -> {
46+
Utilities.fillServerLinks(evt.event.getLinks(), value, context);
47+
});
48+
}
49+
50+
@Override
51+
public ScriptEntryData getScriptEntryData() {
52+
return new BukkitScriptEntryData(player, null);
53+
}
54+
55+
@EventHandler
56+
public void onPlayerLinksSend(PlayerLinksSendEvent event) {
57+
if (event.getConnection() instanceof PlayerGameConnection connection) {
58+
player = new PlayerTag(connection.getPlayer());
59+
}
60+
else if (event.getConnection() instanceof PlayerConfigurationConnection connection) {
61+
player = new PlayerTag(connection.getProfile().getId());
62+
}
63+
else {
64+
player = null;
65+
}
66+
this.event = event;
67+
fire(event);
68+
}
69+
}

paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.bukkit.scoreboard.Team;
4141
import org.bukkit.util.Consumer;
4242

43+
import java.net.URI;
4344
import java.util.*;
4445
import java.util.function.Predicate;
4546
import java.util.stream.Collectors;
@@ -409,6 +410,11 @@ public void setMaterialTags(Material type, Set<NamespacedKey> tags) {
409410
BlockTagsSetter.INSTANCE.setTags(type, tags);
410411
}
411412

413+
@Override
414+
public void addLink(ServerLinks links, String display, URI uri) {
415+
links.addLink(PaperModule.parseFormattedText(display, ChatColor.WHITE), uri);
416+
}
417+
412418
@Override
413419
public double[] getRecentTps() {
414420
return Bukkit.getTPS();

plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,33 @@ else if (mechanism.requireObject(LocationTag.class)) {
26792679
object.getNBTEditor().setSpawnForced(input.asBoolean());
26802680
}
26812681
});
2682+
2683+
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
2684+
2685+
// <--[mechanism]
2686+
// @object PlayerTag
2687+
// @name links
2688+
// @input ListTag(MapTag)
2689+
// @description
2690+
// Sends the specified list of server links to the player. This will override existing links player has.
2691+
// Each item in the list must be a MapTag in <@link language Server Links Format>.
2692+
// Generally prefer <@link mechanism PlayerTag.add_links>
2693+
// -->
2694+
registerOnlineOnlyMechanism("links", ListTag.class, (player, mechanism, input) -> {
2695+
player.getPlayerEntity().sendLinks(Utilities.replaceServerLinks(Bukkit.getServerLinks().copy(), input, mechanism.context));
2696+
});
2697+
2698+
// <--[mechanism]
2699+
// @object PlayerTag
2700+
// @name add_links
2701+
// @input ListTag(MapTag)
2702+
// @description
2703+
// Adds the specified list of server links to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
2704+
// -->
2705+
registerOnlineOnlyMechanism("add_links", ListTag.class, (player, mechanism, input) -> {
2706+
player.getPlayerEntity().sendLinks(Utilities.fillServerLinks(Bukkit.getServerLinks().copy(), input, mechanism.context));
2707+
});
2708+
}
26822709
}
26832710

26842711
public static ObjectTagProcessor<PlayerTag> tagProcessor = new ObjectTagProcessor<>();

plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,32 @@ else if (nameLow.startsWith(matchInput) && (newMatch.isOnline() == matchPlayer.i
20252025
}
20262026
});
20272027

2028+
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
2029+
2030+
// <--[mechanism]
2031+
// @object server
2032+
// @name links
2033+
// @input ListTag(MapTag)
2034+
// @description
2035+
// Sets the default server links. Each item in the list must be a MapTag in <@link language Server Links Format>.
2036+
// Generally prefer <@link mechanism server.add_links>
2037+
// -->
2038+
tagProcessor.registerMechanism("links", false, ListTag.class, (object, mechanism, input) -> {
2039+
Utilities.replaceServerLinks(Bukkit.getServerLinks(), input, mechanism.context);
2040+
});
2041+
2042+
// <--[mechanism]
2043+
// @object server
2044+
// @name add_links
2045+
// @input ListTag(MapTag)
2046+
// @description
2047+
// Adds links to the default server links. Each item in the list must be a MapTag in <@link language Server Links Format>.
2048+
// -->
2049+
tagProcessor.registerMechanism("add_links", false, ListTag.class, (object, mechanism, input) -> {
2050+
Utilities.fillServerLinks(Bukkit.getServerLinks(), input, mechanism.context);
2051+
});
2052+
}
2053+
20282054
// <--[mechanism]
20292055
// @object server
20302056
// @name default_colors

plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.bukkit.util.Consumer;
2525

2626
import java.lang.invoke.MethodHandle;
27+
import java.net.URI;
2728
import java.util.List;
2829
import java.util.Set;
2930
import java.util.function.Predicate;
@@ -233,6 +234,10 @@ public void setMaterialTags(Material type, Set<NamespacedKey> tags) {
233234
NMSHandler.blockHelper.setVanillaTags(type, tags);
234235
}
235236

237+
public void addLink(ServerLinks links, String display, URI uri) {
238+
links.addLink(display, uri);
239+
}
240+
236241
public double[] getRecentTps() {
237242
return NMSHandler.instance.getRecentTps();
238243
}

plugin/src/main/java/com/denizenscript/denizen/utilities/Utilities.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
import com.denizenscript.denizencore.objects.Mechanism;
1414
import com.denizenscript.denizencore.objects.core.ElementTag;
1515
import com.denizenscript.denizencore.objects.core.ListTag;
16+
import com.denizenscript.denizencore.objects.core.MapTag;
1617
import com.denizenscript.denizencore.objects.core.ScriptTag;
1718
import com.denizenscript.denizencore.scripts.ScriptEntry;
19+
import com.denizenscript.denizencore.tags.TagContext;
1820
import com.denizenscript.denizencore.tags.TagManager;
1921
import com.denizenscript.denizencore.utilities.AsciiMatcher;
2022
import com.denizenscript.denizencore.utilities.CoreConfiguration;
@@ -38,6 +40,8 @@
3840

3941
import java.io.File;
4042
import java.io.IOException;
43+
import java.net.URI;
44+
import java.net.URISyntaxException;
4145
import java.util.*;
4246

4347
/**
@@ -645,4 +649,53 @@ public static boolean requireEnumlike(Mechanism mechanism, Class<?> type) {
645649
}
646650
return true;
647651
}
652+
653+
// <--[language]
654+
// @name Server Links Format
655+
// @group Minecraft Logic
656+
// @description
657+
// Server links are represented in Denizen as <@link ObjectType MapTag>s with the following keys:
658+
// - link: The address of the link.
659+
// - type: The type of the link. Valid types are listed at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/ServerLinks.Type.html>
660+
// - display: The display name of the link.
661+
// When constructing this map, the "link" key is required. You can then optionally specify either the "type" or "display" key.
662+
// -->
663+
664+
public static ServerLinks replaceServerLinks(ServerLinks serverLinks, ListTag list, TagContext context) {
665+
serverLinks.getLinks().forEach(serverLinks::removeLink);
666+
return fillServerLinks(serverLinks, list, context);
667+
}
668+
669+
public static ServerLinks fillServerLinks(ServerLinks serverLinks, ListTag list, TagContext context) {
670+
for (MapTag map : list.filter(MapTag.class, context)) {
671+
if (!map.containsKey("link")) {
672+
Debug.echoError("Invalid server links map '" + map + "': missing 'link' key!");
673+
continue;
674+
}
675+
URI uri;
676+
String strUri = map.getElement("link").asString();
677+
try {
678+
uri = new URI(strUri);
679+
}
680+
catch (URISyntaxException e) {
681+
Debug.echoError("Invalid server links map '" + map + "': invalid 'link' key: " + strUri);
682+
continue;
683+
}
684+
if (map.containsKey("display")) {
685+
PaperAPITools.instance.addLink(serverLinks, map.getElement("display").asString(), uri);
686+
}
687+
else if (map.containsKey("type")) {
688+
ServerLinks.Type type = map.getElement("type").asEnum(ServerLinks.Type.class);
689+
if (type == null) {
690+
Debug.echoError("Invalid server links map '" + map + "': invalid 'type' key: " + map.getElement("type"));
691+
continue;
692+
}
693+
serverLinks.addLink(type, uri);
694+
}
695+
else {
696+
Debug.echoError("Invalid server links map '" + map + "': must have either a 'display' or 'type' key!");
697+
}
698+
}
699+
return serverLinks;
700+
}
648701
}

0 commit comments

Comments
 (0)