This commit is contained in:
devreluije 2024-04-30 21:13:44 -06:00 committed by GitHub
commit a751940f40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 55 additions and 11 deletions

View File

@ -194,6 +194,10 @@ public final class MinecraftServer {
return !isStarted();
}
public static boolean isStopped() {
return serverProcess.isStopped();
}
/**
* Gets the chunk view distance of the server.
* <p>

View File

@ -137,10 +137,29 @@ public interface ServerProcess extends Snapshotable {
void start(@NotNull SocketAddress socketAddress);
/**
* Request the server to stop
*/
void stop();
/**
* Shutdown all sub processes
* <p>
* Order:
* <ul>
* {@link SchedulerManager#shutdown()}
* {@link ConnectionManager#shutdown()}
* {@link Server#stop()}
* {@link BenchmarkManager#disable()}
* {@link ThreadDispatcher#shutdown()}
* </ul>
*/
void shutdown();
boolean isAlive();
boolean isStopped();
@ApiStatus.NonExtendable
interface Ticker {
void tick(long nanoTime);

View File

@ -71,6 +71,7 @@ final class ServerProcessImpl implements ServerProcess {
private final Ticker ticker;
private final AtomicBoolean started = new AtomicBoolean();
private final AtomicBoolean stopping = new AtomicBoolean();
private final AtomicBoolean stopped = new AtomicBoolean();
public ServerProcessImpl() throws IOException {
@ -230,6 +231,13 @@ final class ServerProcessImpl implements ServerProcess {
@Override
public void stop() {
if (!stopping.compareAndSet(false, true))
return;
LOGGER.info("Stopping " + MinecraftServer.getBrandName() + " server...");
}
@Override
public void shutdown() {
if (!stopped.compareAndSet(false, true))
return;
LOGGER.info("Stopping " + MinecraftServer.getBrandName() + " server.");
@ -242,9 +250,14 @@ final class ServerProcessImpl implements ServerProcess {
LOGGER.info(MinecraftServer.getBrandName() + " server stopped successfully.");
}
@Override
public boolean isStopped() {
return stopped.get();
}
@Override
public boolean isAlive() {
return started.get() && !stopped.get();
return started.get() && !stopping.get() && !stopped.get();
}
@Override

View File

@ -23,6 +23,7 @@ public final class TickSchedulerThread extends MinestomThread {
public void run() {
long ticks = 0;
long baseTime = System.nanoTime();
while (serverProcess.isAlive()) {
final long tickStart = System.nanoTime();
try {
@ -32,16 +33,20 @@ public final class TickSchedulerThread extends MinestomThread {
}
ticks++;
long nextTickTime = baseTime + ticks * TICK_TIME_NANOS;
waitUntilNextTick(nextTickTime);
// Check if the server can not keep up with the tickrate
// if it gets too far behind, reset the ticks & baseTime
// to avoid running too many ticks at once
if (System.nanoTime() > nextTickTime + TICK_TIME_NANOS * ServerFlag.SERVER_MAX_TICK_CATCH_UP) {
baseTime = System.nanoTime();
ticks = 0;
// don't wait next tick if server is stopping/stopped
if (serverProcess.isAlive()) {
long nextTickTime = baseTime + ticks * TICK_TIME_NANOS;
waitUntilNextTick(nextTickTime);
// Check if the server can not keep up with the tickrate
// if it gets too far behind, reset the ticks & baseTime
// to avoid running too many ticks at once
if (System.nanoTime() > nextTickTime + TICK_TIME_NANOS * ServerFlag.SERVER_MAX_TICK_CATCH_UP) {
baseTime = System.nanoTime();
ticks = 0;
}
}
}
serverProcess.shutdown();
}
private void waitUntilNextTick(long nextTickTimeNanos) {

View File

@ -5,8 +5,7 @@ import org.junit.jupiter.api.Test;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class ServerProcessTest {
@ -21,6 +20,8 @@ public class ServerProcessTest {
assertDoesNotThrow(() -> process.get().start(new InetSocketAddress("localhost", 25565)));
assertThrows(Exception.class, () -> process.get().start(new InetSocketAddress("localhost", 25566)));
assertDoesNotThrow(() -> process.get().stop());
assertFalse(() -> process.get().isAlive(), "Server is still alive");
assertDoesNotThrow(() -> process.get().shutdown());
}
@Test
@ -33,5 +34,7 @@ public class ServerProcessTest {
var ticker = process.ticker();
assertDoesNotThrow(() -> ticker.tick(System.currentTimeMillis()));
assertDoesNotThrow(process::stop);
assertFalse(process::isAlive, "Server is still alive");
assertDoesNotThrow(process::shutdown);
}
}