|
5 | 5 | import com.comphenix.protocol.events.ListenerPriority; |
6 | 6 | import com.comphenix.protocol.events.PacketAdapter; |
7 | 7 | import com.comphenix.protocol.events.PacketEvent; |
| 8 | +import com.comphenix.protocol.reflect.accessors.Accessors; |
| 9 | +import com.comphenix.protocol.reflect.accessors.FieldAccessor; |
8 | 10 | import com.comphenix.protocol.utility.MinecraftVersion; |
9 | 11 | import com.comphenix.protocol.wrappers.WrappedGameProfile; |
| 12 | +import com.comphenix.protocol.wrappers.WrappedServerPing; |
| 13 | +import com.comphenix.protocol.wrappers.ping.ServerPingImpl; |
| 14 | +import com.comphenix.protocol.wrappers.ping.ServerPingRecord; |
10 | 15 | import com.rexcantor64.triton.Triton; |
11 | | -import com.rexcantor64.triton.language.parser.AdventureParser; |
12 | 16 | import com.rexcantor64.triton.language.parser.MessageParser; |
13 | 17 | import com.rexcantor64.triton.spigot.SpigotTriton; |
14 | 18 | import com.rexcantor64.triton.spigot.utils.WrappedComponentUtils; |
| 19 | +import com.rexcantor64.triton.spigot.wrappers.WrappedNameAndId; |
15 | 20 | import lombok.val; |
16 | 21 | import net.kyori.adventure.text.Component; |
17 | 22 | import org.bukkit.entity.Player; |
|
20 | 25 | import java.net.InetSocketAddress; |
21 | 26 | import java.util.Arrays; |
22 | 27 | import java.util.Collections; |
23 | | -import java.util.Objects; |
24 | 28 | import java.util.Optional; |
25 | 29 | import java.util.UUID; |
26 | 30 | import java.util.stream.Collectors; |
27 | 31 | import java.util.stream.Stream; |
28 | 32 |
|
29 | 33 | public class MotdPacketHandler extends PacketAdapter { |
30 | 34 |
|
| 35 | + private final FieldAccessor WRAPPED_SERVER_PING_IMPL; |
| 36 | + private final FieldAccessor SERVER_PING_RECORD_PLAYERS_SAMPLE; |
| 37 | + |
31 | 38 | public MotdPacketHandler() { |
32 | 39 | super(SpigotTriton.asSpigot().getJavaPlugin(), ListenerPriority.HIGHEST, |
33 | 40 | Collections.singleton(PacketType.Status.Server.SERVER_INFO), ListenerOptions.ASYNC); |
| 41 | + |
| 42 | + WRAPPED_SERVER_PING_IMPL = Accessors.getFieldAccessor(WrappedServerPing.class, ServerPingImpl.class, true); |
| 43 | + SERVER_PING_RECORD_PLAYERS_SAMPLE = Accessors.getFieldAccessor(ServerPingRecord.class, ServerPingRecord.PlayerSample.class, true); |
34 | 44 | } |
35 | 45 |
|
36 | 46 | /** |
@@ -65,31 +75,70 @@ private void handleServerInfo(PacketEvent event) { |
65 | 75 | val syntax = Triton.get().getConfig().getMotdSyntax(); |
66 | 76 |
|
67 | 77 | val serverPing = event.getPacket().getServerPings().readSafely(0); |
68 | | - serverPing.setPlayers(serverPing.getPlayers().stream().flatMap((gp) -> { |
69 | | - if (gp.getName() == null) { |
70 | | - return Stream.of(gp); |
| 78 | + if (WrappedNameAndId.getWrappedClass() == null) { |
| 79 | + // MC 1.21.8 and below |
| 80 | + serverPing.setPlayers(serverPing.getPlayers().stream().flatMap((gp) -> { |
| 81 | + if (gp.getName() == null) { |
| 82 | + return Stream.of(gp); |
| 83 | + } |
| 84 | + |
| 85 | + return parser() |
| 86 | + .translateString( |
| 87 | + gp.getName(), |
| 88 | + lang, |
| 89 | + syntax |
| 90 | + ) |
| 91 | + .mapToObj( |
| 92 | + (translatedName) -> { |
| 93 | + val translatedNameSplit = translatedName.split("\n", -1); |
| 94 | + if (translatedNameSplit.length > 1) { |
| 95 | + return Arrays.stream(translatedNameSplit).map(name -> new WrappedGameProfile(UUID.randomUUID(), name)); |
| 96 | + } else { |
| 97 | + return Stream.of(gp.withName(translatedName)); |
| 98 | + } |
| 99 | + }, |
| 100 | + () -> Stream.of(gp), |
| 101 | + Stream::empty |
| 102 | + ); |
| 103 | + |
| 104 | + }).collect(Collectors.toList())); |
| 105 | + } else { |
| 106 | + // MC 1.21.9+ |
| 107 | + |
| 108 | + // I guess we're doing reflection on ProtocolLib again... |
| 109 | + ServerPingRecord impl = (ServerPingRecord) WRAPPED_SERVER_PING_IMPL.get(serverPing); |
| 110 | + ServerPingRecord.PlayerSample playerSample = (ServerPingRecord.PlayerSample) SERVER_PING_RECORD_PLAYERS_SAMPLE.get(impl); |
| 111 | + |
| 112 | + if (playerSample.sample != null) { |
| 113 | + val sample = WrappedNameAndId.LIST_CONVERTER.getSpecific(playerSample.sample); |
| 114 | + val newList = sample.stream().flatMap((player) -> { |
| 115 | + if (player.getName() == null) { |
| 116 | + return Stream.of(player); |
| 117 | + } |
| 118 | + |
| 119 | + return parser() |
| 120 | + .translateString( |
| 121 | + player.getName(), |
| 122 | + lang, |
| 123 | + syntax |
| 124 | + ) |
| 125 | + .mapToObj( |
| 126 | + (translatedName) -> { |
| 127 | + val translatedNameSplit = translatedName.split("\n", -1); |
| 128 | + if (translatedNameSplit.length > 1) { |
| 129 | + return Arrays.stream(translatedNameSplit).map(name -> new WrappedNameAndId(UUID.randomUUID(), name)); |
| 130 | + } else { |
| 131 | + return Stream.of(player.withName(translatedName)); |
| 132 | + } |
| 133 | + }, |
| 134 | + () -> Stream.of(player), |
| 135 | + Stream::empty |
| 136 | + ); |
| 137 | + }).collect(Collectors.toList()); |
| 138 | + |
| 139 | + playerSample.sample = WrappedNameAndId.LIST_CONVERTER.getGeneric(newList); |
71 | 140 | } |
72 | | - |
73 | | - return parser() |
74 | | - .translateString( |
75 | | - gp.getName(), |
76 | | - lang, |
77 | | - syntax |
78 | | - ) |
79 | | - .mapToObj( |
80 | | - (translatedName) -> { |
81 | | - val translatedNameSplit = translatedName.split("\n", -1); |
82 | | - if (translatedNameSplit.length > 1) { |
83 | | - return Arrays.stream(translatedNameSplit).map(name -> new WrappedGameProfile(UUID.randomUUID(), name)); |
84 | | - } else { |
85 | | - return Stream.of(gp.withName(translatedName)); |
86 | | - } |
87 | | - }, |
88 | | - () -> Stream.of(gp), |
89 | | - Stream::empty |
90 | | - ); |
91 | | - |
92 | | - }).collect(Collectors.toList())); |
| 141 | + } |
93 | 142 |
|
94 | 143 | parser().translateString(serverPing.getVersionName(), lang, syntax) |
95 | 144 | .ifChanged(serverPing::setVersionName); |
|
0 commit comments