1
1
package org .zeroBzeroT .anarchyqueue ;
2
2
3
3
import com .velocitypowered .api .event .Subscribe ;
4
+ import com .velocitypowered .api .event .player .KickedFromServerEvent ;
4
5
import com .velocitypowered .api .event .player .ServerConnectedEvent ;
5
6
import com .velocitypowered .api .proxy .ProxyServer ;
6
7
import com .velocitypowered .api .proxy .server .RegisteredServer ;
7
- import net .kyori .adventure .identity .Identity ;
8
8
import net .kyori .adventure .text .Component ;
9
- import org . slf4j .Logger ;
9
+ import net . kyori . adventure . text . logger . slf4j .ComponentLogger ;
10
10
11
11
import java .time .Duration ;
12
12
import java .time .Instant ;
13
- import java .util .List ;
13
+ import java .util .Deque ;
14
+ import java .util .LinkedList ;
14
15
import java .util .Optional ;
15
16
import java .util .UUID ;
16
- import java .util .concurrent .CopyOnWriteArrayList ;
17
17
import java .util .concurrent .ExecutionException ;
18
18
import java .util .concurrent .Semaphore ;
19
19
20
+ import static org .zeroBzeroT .anarchyqueue .Components .mm ;
21
+
20
22
// velocity api event docs:
21
23
// https://jd.papermc.io/velocity/3.3.0/com/velocitypowered/api/event/package-summary.html
22
24
23
25
public class Queue {
24
- private final Logger log ;
26
+ private final ComponentLogger log ;
25
27
26
28
private final ProxyServer proxyServer ;
27
29
28
30
private final Semaphore queueSemaphore = new Semaphore (1 );
29
31
30
- /**
31
- * We don't use ConcurrentLinkedQueue for this because we want index-based access to players.
32
- */
33
- private final List <QueuedPlayer > queuedPlayers = new CopyOnWriteArrayList <>();
32
+ private final Deque <QueuedPlayer > queuedPlayers = new LinkedList <>();
34
33
35
34
/**
36
- * Initializes a queue
35
+ * Initializes the queue.
37
36
*/
38
37
public Queue (ProxyServer proxyServer ) {
39
38
this .log = Main .getInstance ().log ;
@@ -48,24 +47,23 @@ public Queue(ProxyServer proxyServer) {
48
47
}
49
48
50
49
/**
51
- * This event is called once a connection to a server is fully operational.
52
- * Add a Player to the queue if they join the queue server.
50
+ * This event is fired once the player has successfully connected to the
51
+ * target server and the connection to the previous server has been de-established .
53
52
*/
54
53
@ Subscribe
55
- public void onServerConnectedEvent (ServerConnectedEvent e ) {
56
- if (!e .getServer ().getServerInfo ().getName ().equals (Config .serverQueue ))
54
+ public void onServerConnected (ServerConnectedEvent event ) {
55
+ if (!event .getServer ().getServerInfo ().getName ().equals (Config .serverQueue ))
57
56
return ;
58
57
59
- var queuedPlayer = new QueuedPlayer (e .getPlayer (), System .currentTimeMillis ());
60
-
61
- if (queuedPlayers .contains (queuedPlayer ))
58
+ // stop adding the player several times
59
+ if (queuedPlayers .stream ().anyMatch (p -> p .player () == event .getPlayer ()))
62
60
return ;
63
61
64
62
// Add Player to queue
65
63
try {
66
64
queueSemaphore .acquire ();
67
- queuedPlayers .add (queuedPlayer );
68
- log .info (" \u00A7 f " + e .getPlayer ().getUsername () + "\u00A7 3 was added to the §dplayer queue\u00A7 3 . Queue count is " + queuedPlayers .size () + "." );
65
+ queuedPlayers .add (new QueuedPlayer ( event . getPlayer (), System . currentTimeMillis ()) );
66
+ log .info (mm ( "<white> " + event .getPlayer ().getUsername () + "<dark_aqua> was added to the <light_purple> queue<dark_aqua> . Queue count is " + queuedPlayers .size () + "." ) );
69
67
} catch (InterruptedException e1 ) {
70
68
e1 .printStackTrace ();
71
69
} finally {
@@ -74,9 +72,21 @@ public void onServerConnectedEvent(ServerConnectedEvent e) {
74
72
}
75
73
76
74
/**
77
- * Try to connect one player to the server
75
+ * Fired when a player is kicked from a server.
76
+ */
77
+ @ Subscribe
78
+ public void onKickedFromServer (KickedFromServerEvent event ) {
79
+ log .info (mm ("<white>" + event .getPlayer ().getUsername () + "<dark_aqua> was kicked from <light_purple>" + event .getServer ().getServerInfo ().getName () + "<dark_aqua> for <light_purple>" ).append (event .getServerKickReason ().isPresent () ? event .getServerKickReason ().get () : mm ("<empty>" )).append (mm ("<dark_aqua>." )));
80
+ }
81
+
82
+ /**
83
+ * Try to connect one player to the server.
78
84
*/
79
85
public void flushQueue () {
86
+ // Ignore if queue is empty
87
+ if (queuedPlayers .isEmpty ())
88
+ return ;
89
+
80
90
// check queue server reachability
81
91
final RegisteredServer serverQueue ;
82
92
@@ -87,22 +97,16 @@ public void flushQueue() {
87
97
return ;
88
98
}
89
99
90
- // Ignore if queue is empty
91
- if (queuedPlayers .isEmpty ())
92
- return ;
93
-
94
100
// check the main server reachability
95
101
final RegisteredServer serverMain ;
96
102
97
103
try {
98
104
serverMain = getServer (Config .serverMain );
99
105
} catch (ServerNotReachableException e ) {
100
106
if (Instant .now ().getEpochSecond () % 10 == 0 ) {
101
- serverQueue .getPlayersConnected ().forEach (queuedPlayer ->
102
- queuedPlayer .sendMessage (Identity .nil (), Component .text (
103
- Config .messageOffline
104
- )));
107
+ serverQueue .getPlayersConnected ().forEach (queuedPlayer -> queuedPlayer .sendMessage (Component .text (Config .messageOffline )));
105
108
}
109
+
106
110
return ;
107
111
}
108
112
@@ -145,21 +149,21 @@ public void flushQueue() {
145
149
serverQueue .getPlayersConnected ().stream ()
146
150
.filter (p -> p .getUniqueId ().equals (uuid ))
147
151
.findAny ().ifPresentOrElse (p -> {
148
- p .sendMessage (Identity . nil (), Component .text (Config .messageConnecting ));
152
+ p .sendMessage (Component .text (Config .messageConnecting ));
149
153
try {
150
154
if (p .createConnectionRequest (serverMain ).connect ().get ().isSuccessful ()) {
151
155
queuedPlayers .removeFirst ();
152
- log .info (" \u00A7 f " + p .getUsername () + "\u00A7 3 connected to server §b " + serverMain .getServerInfo ().getName () + "\u00A7 3 . Queue count is " + serverQueue .getPlayersConnected ().size () + ". Main count is " + (serverMain .getPlayersConnected ().size ()) + " of " + Config .maxPlayers + "." );
156
+ log .info (mm ( "<white> " + p .getUsername () + "<dark_aqua> connected to server <aqua> " + serverMain .getServerInfo ().getName () + "<dark_aqua> . Queue count is " + serverQueue .getPlayersConnected ().size () + ". Main count is " + (serverMain .getPlayersConnected ().size ()) + " of " + Config .maxPlayers + "." ) );
153
157
}
154
158
} catch (InterruptedException | ExecutionException e ) {
155
- log .error (" \u00A7 f " + p .getUsername () + "s\u00A7 c connection to server §b " + Config .serverMain + "\u00A7 c failed: " + e .getMessage ());
159
+ log .error (mm ( "<white> " + p .getUsername () + "s<red> connection to server <aqua> " + Config .serverMain + "<red> failed: " + e .getMessage () ));
156
160
// FIXME: requeue
157
161
queuedPlayers .removeFirst ();
158
162
queuedPlayers .add (new QueuedPlayer (finalCurrPlayer .player (), System .currentTimeMillis ()));
159
163
}
160
164
},
161
165
() -> {
162
- log .error (" \u00A7 f " + finalCurrPlayer .player ().getUsername () + "s\u00A7 c connection to server §b " + Config .serverMain + "\u00A7 c failed: player is not connected to " + serverQueue .getServerInfo ().getName ());
166
+ log .error (mm ( "<white> " + finalCurrPlayer .player ().getUsername () + "s<red> connection to server <aqua> " + Config .serverMain + "<red> failed: player is not connected to " + serverQueue .getServerInfo ().getName () ));
163
167
queuedPlayers .removeFirst ();
164
168
}
165
169
);
@@ -171,25 +175,20 @@ public void flushQueue() {
171
175
}
172
176
173
177
private void sendInfo (RegisteredServer serverQueue , boolean full ) {
174
- for (int i = 0 ; i < queuedPlayers .size (); i ++) {
175
- queuedPlayers
176
- .get (i )
177
- .player ()
178
- .sendMessage (Identity .nil (), Component .text (
179
- Config .messagePosition + (i + 1 ) + "/" + queuedPlayers .size ()
180
- ));
178
+ int i = 1 ;
179
+
180
+ for (QueuedPlayer player : queuedPlayers ) {
181
+ player .player ().sendMessage (Component .text (Config .messagePosition + (i + 1 ) + "/" + queuedPlayers .size ()));
182
+ i ++;
181
183
}
182
184
183
185
if (full ) {
184
- serverQueue .getPlayersConnected ().forEach (queuedPlayer ->
185
- queuedPlayer .sendMessage (Identity .nil (), Component .text (
186
- Config .messageFull
187
- )));
186
+ serverQueue .getPlayersConnected ().forEach (queuedPlayer -> queuedPlayer .sendMessage (Component .text (Config .messageFull )));
188
187
}
189
188
}
190
189
191
190
private RegisteredServer getServer (String name ) throws ServerNotReachableException {
192
- // get server configured in velocity.toml by name
191
+ // Get server configured in velocity.toml by name
193
192
Optional <RegisteredServer > serverOpt = proxyServer .getServer (name );
194
193
195
194
if (serverOpt .isEmpty ()) {
@@ -198,7 +197,7 @@ private RegisteredServer getServer(String name) throws ServerNotReachableExcepti
198
197
199
198
final RegisteredServer server = serverOpt .get ();
200
199
201
- // test server availability by pinging
200
+ // Test server availability by pinging
202
201
try {
203
202
server .ping ().get ();
204
203
} catch (InterruptedException | ExecutionException e ) {
0 commit comments