Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-24 15:20:35 +01:00
Wait for player disconnect events on shutdown. (#229)
Dieser Commit ist enthalten in:
Ursprung
a053ab6c34
Commit
6d2e1bf379
@ -59,9 +59,14 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.kyori.text.Component;
|
import net.kyori.text.Component;
|
||||||
import net.kyori.text.TextComponent;
|
import net.kyori.text.TextComponent;
|
||||||
@ -379,14 +384,35 @@ public class VelocityServer implements ProxyServer {
|
|||||||
Runnable shutdownProcess = () -> {
|
Runnable shutdownProcess = () -> {
|
||||||
logger.info("Shutting down the proxy...");
|
logger.info("Shutting down the proxy...");
|
||||||
|
|
||||||
for (ConnectedPlayer player : ImmutableList.copyOf(connectionsByUuid.values())) {
|
// Shutdown the connection manager, this should be
|
||||||
|
// done first to refuse new connections
|
||||||
|
cm.shutdown();
|
||||||
|
|
||||||
|
ImmutableList<ConnectedPlayer> players = ImmutableList.copyOf(connectionsByUuid.values());
|
||||||
|
for (ConnectedPlayer player : players) {
|
||||||
player.disconnect(TextComponent.of("Proxy shutting down."));
|
player.disconnect(TextComponent.of("Proxy shutting down."));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cm.shutdown();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!eventManager.shutdown() || !scheduler.shutdown()) {
|
boolean timedOut = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wait for the connections finish tearing down, this
|
||||||
|
// makes sure that all the disconnect events are being fired
|
||||||
|
|
||||||
|
CompletableFuture<Void> playersTeardownFuture = CompletableFuture.allOf(players.stream()
|
||||||
|
.map(ConnectedPlayer::getTeardownFuture)
|
||||||
|
.toArray((IntFunction<CompletableFuture<Void>[]>) CompletableFuture[]::new));
|
||||||
|
|
||||||
|
playersTeardownFuture.get(10, TimeUnit.SECONDS);
|
||||||
|
} catch (TimeoutException | ExecutionException e) {
|
||||||
|
timedOut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
timedOut = !eventManager.shutdown() || timedOut;
|
||||||
|
timedOut = !scheduler.shutdown() || timedOut;
|
||||||
|
|
||||||
|
if (timedOut) {
|
||||||
logger.error("Your plugins took over 10 seconds to shut down.");
|
logger.error("Your plugins took over 10 seconds to shut down.");
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -58,6 +58,7 @@ import java.util.Optional;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import net.kyori.text.Component;
|
import net.kyori.text.Component;
|
||||||
import net.kyori.text.TextComponent;
|
import net.kyori.text.TextComponent;
|
||||||
@ -97,6 +98,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
private final VelocityServer server;
|
private final VelocityServer server;
|
||||||
private ClientConnectionPhase connectionPhase;
|
private ClientConnectionPhase connectionPhase;
|
||||||
private final Collection<String> knownChannels;
|
private final Collection<String> knownChannels;
|
||||||
|
private final CompletableFuture<Void> teardownFuture = new CompletableFuture<>();
|
||||||
|
|
||||||
private @MonotonicNonNull List<String> serversToTry = null;
|
private @MonotonicNonNull List<String> serversToTry = null;
|
||||||
|
|
||||||
@ -554,7 +556,12 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
connectedServer.disconnect();
|
connectedServer.disconnect();
|
||||||
}
|
}
|
||||||
server.unregisterConnection(this);
|
server.unregisterConnection(this);
|
||||||
server.getEventManager().fireAndForget(new DisconnectEvent(this));
|
server.getEventManager().fire(new DisconnectEvent(this))
|
||||||
|
.thenRun(() -> this.teardownFuture.complete(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> getTeardownFuture() {
|
||||||
|
return teardownFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren