Added RegistryUpdater to broadcast server data to registries.

This commit is contained in:
Andrew Lalis 2022-08-05 17:30:29 +02:00
parent a808ac1920
commit e38ae65ff9
7 changed files with 87 additions and 1 deletions

View File

@ -73,7 +73,6 @@ public class ServerRegistry {
@Scheduled(fixedRate = 1, timeUnit = TimeUnit.MINUTES, initialDelay = 1) @Scheduled(fixedRate = 1, timeUnit = TimeUnit.MINUTES, initialDelay = 1)
public void purgeOldServers() { public void purgeOldServers() {
log.info("Purging old servers.");
Queue<ServerIdentifier> removalQueue = new LinkedList<>(); Queue<ServerIdentifier> removalQueue = new LinkedList<>();
final Instant cutoff = Instant.now().minus(SERVER_TIMEOUT); final Instant cutoff = Instant.now().minus(SERVER_TIMEOUT);
for (var entry : servers.entrySet()) { for (var entry : servers.entrySet()) {

View File

@ -33,6 +33,12 @@
<artifactId>jansi</artifactId> <artifactId>jansi</artifactId>
<version>2.4.0</version> <version>2.4.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -107,6 +107,11 @@ public class ClientCommunicationHandler {
socket.close(); socket.close();
return; return;
} }
if (server.getPlayerManager().getPlayers().size() >= server.getConfig().maxPlayers) {
Net.write(new ConnectRejectMessage("Server is full."), out);
socket.close();
return;
}
// Try to set the TCP timeout back to 0 now that we've got the correct request. // Try to set the TCP timeout back to 0 now that we've got the correct request.
socket.setSoTimeout(0); socket.setSoTimeout(0);

View File

@ -0,0 +1,59 @@
package nl.andrewl.aos2_server;
import com.google.gson.Gson;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* Component that sends regular updates to any configured server registries.
*/
public class RegistryUpdater {
private final Server server;
private final HttpClient httpClient;
public RegistryUpdater(Server server) {
this.server = server;
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(3))
.build();
}
public void sendUpdates() {
var cfg = server.getConfig();
if (
cfg.registries != null &&
cfg.registries.length > 0 &&
cfg.name != null && !cfg.name.isBlank()
) {
Map<String, Object> data = new HashMap<>();
data.put("port", cfg.port);
data.put("name", cfg.name);
data.put("description", cfg.description);
data.put("maxPlayers", cfg.maxPlayers);
data.put("currentPlayers", server.getPlayerManager().getPlayers().size());
String json = new Gson().toJson(data);
for (String registryUrl : server.getConfig().registries) {
HttpRequest req = HttpRequest.newBuilder(URI.create(registryUrl + "/servers"))
.POST(HttpRequest.BodyPublishers.ofString(json))
.header("Content-Type", "application/json")
.timeout(Duration.ofSeconds(3))
.build();
try {
var resp = httpClient.send(req, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() != 200) {
System.err.println("Error response when sending registry update to " + registryUrl + ": " + resp.statusCode() + " " + resp.body());
}
} catch (IOException | InterruptedException e) {
System.err.println("An error occurred while sending registry update to " + registryUrl + ": " + e.getMessage());
}
}
}
}
}

View File

@ -24,7 +24,10 @@ import java.net.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** /**
* The central server, which mainly contains all the different managers and * The central server, which mainly contains all the different managers and
@ -83,11 +86,15 @@ public class Server implements Runnable {
running = true; running = true;
new Thread(new UdpReceiver(datagramSocket, this::handleUdpMessage)).start(); new Thread(new UdpReceiver(datagramSocket, this::handleUdpMessage)).start();
new Thread(worldUpdater).start(); new Thread(worldUpdater).start();
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
var registryUpdater = new RegistryUpdater(this);
executorService.scheduleAtFixedRate(registryUpdater::sendUpdates, 0, 90, TimeUnit.SECONDS);
System.out.printf("Started AoS2 Server on TCP/UDP port %d; now accepting connections.%n", serverSocket.getLocalPort()); System.out.printf("Started AoS2 Server on TCP/UDP port %d; now accepting connections.%n", serverSocket.getLocalPort());
while (running) { while (running) {
acceptClientConnection(); acceptClientConnection();
} }
System.out.println("Shutting down the server."); System.out.println("Shutting down the server.");
executorService.shutdown();
playerManager.deregisterAll(); playerManager.deregisterAll();
worldUpdater.shutdown(); worldUpdater.shutdown();
datagramSocket.close(); // Shuts down the UdpReceiver. datagramSocket.close(); // Shuts down the UdpReceiver.

View File

@ -2,6 +2,11 @@ package nl.andrewl.aos2_server.config;
public class ServerConfig { public class ServerConfig {
public int port = 25565; public int port = 25565;
public String name = "My Server";
public String description = "My server";
public String[] registries = new String[0];
public int maxPlayers = 32;
public int connectionBacklog = 5; public int connectionBacklog = 5;
public float ticksPerSecond = 20.0f; public float ticksPerSecond = 20.0f;
public String world = "worlds.redfort"; public String world = "worlds.redfort";

View File

@ -1,5 +1,10 @@
# Ace of Shades 2 Server Configuration # Ace of Shades 2 Server Configuration
port: 25565 port: 25565
name: My Server
description: This is my Ace of Shades server.
registries:
- https://reg.aos2.net
maxPlayers: 32
connectionBacklog: 5 connectionBacklog: 5
ticksPerSecond: 20.0 ticksPerSecond: 20.0
world: worlds.redfort world: worlds.redfort