This commit is contained in:
parent
1392d82480
commit
f3a57dc8d9
14
API/pom.xml
14
API/pom.xml
@ -107,6 +107,12 @@
|
|||||||
<version>1.20-R0.2</version>
|
<version>1.20-R0.2</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
<artifactId>plexus-archiver</artifactId>
|
||||||
|
<version>4.9.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- DNS Lookup -->
|
<!-- DNS Lookup -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -116,6 +122,14 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- GeoIP -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.maxmind.geoip2</groupId>
|
||||||
|
<artifactId>geoip2</artifactId>
|
||||||
|
<version>4.2.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- SwaggerUI -->
|
<!-- SwaggerUI -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
*/
|
*/
|
||||||
package me.braydon.mc.model;
|
package me.braydon.mc.model;
|
||||||
|
|
||||||
|
import com.maxmind.geoip2.model.CityResponse;
|
||||||
|
import com.maxmind.geoip2.record.City;
|
||||||
|
import com.maxmind.geoip2.record.Continent;
|
||||||
|
import com.maxmind.geoip2.record.Country;
|
||||||
|
import com.maxmind.geoip2.record.Location;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import me.braydon.mc.common.ColorUtils;
|
import me.braydon.mc.common.ColorUtils;
|
||||||
import me.braydon.mc.model.dns.DNSRecord;
|
import me.braydon.mc.model.dns.DNSRecord;
|
||||||
@ -41,7 +46,7 @@ import java.util.UUID;
|
|||||||
*
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor @Getter @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
@AllArgsConstructor @Setter @Getter @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||||
public class MinecraftServer {
|
public class MinecraftServer {
|
||||||
/**
|
/**
|
||||||
* The hostname of this server.
|
* The hostname of this server.
|
||||||
@ -63,6 +68,11 @@ public class MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final DNSRecord[] records;
|
@NonNull private final DNSRecord[] records;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Geo location of this server, null if unknown.
|
||||||
|
*/
|
||||||
|
private GeoLocation geo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player counts of this server.
|
* The player counts of this server.
|
||||||
*/
|
*/
|
||||||
@ -73,6 +83,74 @@ public class MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final MOTD motd;
|
@NonNull private final MOTD motd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Geo location of a server.
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Getter @ToString
|
||||||
|
public static class GeoLocation {
|
||||||
|
/**
|
||||||
|
* The continent of this server.
|
||||||
|
*/
|
||||||
|
@NonNull private final LocationData continent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The country of this server.
|
||||||
|
*/
|
||||||
|
@NonNull private final LocationData country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The city of this server, null if unknown.
|
||||||
|
*/
|
||||||
|
private final String city;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The latitude of this server.
|
||||||
|
*/
|
||||||
|
private final double latitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The longitude of this server.
|
||||||
|
*/
|
||||||
|
private final double longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new geo location data
|
||||||
|
* from the given city response.
|
||||||
|
*
|
||||||
|
* @param geo the geo city response
|
||||||
|
* @return the geo location
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static GeoLocation create(@NonNull CityResponse geo) {
|
||||||
|
Continent continent = geo.getContinent();
|
||||||
|
Country country = geo.getCountry();
|
||||||
|
City city = geo.getCity();
|
||||||
|
Location location = geo.getLocation();
|
||||||
|
return new GeoLocation(
|
||||||
|
new LocationData(continent.getCode(), continent.getName()),
|
||||||
|
new LocationData(country.getIsoCode(), country.getName()),
|
||||||
|
city == null ? null : city.getName(),
|
||||||
|
location.getLatitude(), location.getLongitude()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a location.
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Getter @ToString
|
||||||
|
public static class LocationData {
|
||||||
|
/**
|
||||||
|
* The location code.
|
||||||
|
*/
|
||||||
|
@NonNull private final String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location name.
|
||||||
|
*/
|
||||||
|
@NonNull private final String name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player count data for a server.
|
* Player count data for a server.
|
||||||
*/
|
*/
|
||||||
|
@ -54,10 +54,10 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final GameMode gamemode;
|
@NonNull private final GameMode gamemode;
|
||||||
|
|
||||||
private BedrockMinecraftServer(@NonNull String id, @NonNull String hostname, String ip, int port, @NonNull DNSRecord[] records,
|
private BedrockMinecraftServer(@NonNull String id, @NonNull String hostname, String ip, int port, GeoLocation geo,
|
||||||
@NonNull Edition edition, @NonNull Version version, @NonNull Players players, @NonNull MOTD motd,
|
@NonNull DNSRecord[] records, @NonNull Edition edition, @NonNull Version version,
|
||||||
@NonNull GameMode gamemode) {
|
@NonNull Players players, @NonNull MOTD motd, @NonNull GameMode gamemode) {
|
||||||
super(hostname, ip, port, records, players, motd);
|
super(hostname, ip, port, records, geo, players, motd);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.edition = edition;
|
this.edition = edition;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@ -83,7 +83,7 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
|||||||
Players players = new Players(Integer.parseInt(split[4]), Integer.parseInt(split[5]), null);
|
Players players = new Players(Integer.parseInt(split[4]), Integer.parseInt(split[5]), null);
|
||||||
MOTD motd = MOTD.create(split[1] + "\n" + split[7]);
|
MOTD motd = MOTD.create(split[1] + "\n" + split[7]);
|
||||||
GameMode gameMode = new GameMode(split[8], split.length > 9 ? Integer.parseInt(split[9]) : -1);
|
GameMode gameMode = new GameMode(split[8], split.length > 9 ? Integer.parseInt(split[9]) : -1);
|
||||||
return new BedrockMinecraftServer(split[6], hostname, ip, port, records, edition, version, players, motd, gameMode);
|
return new BedrockMinecraftServer(split[6], hostname, ip, port, null, records, edition, version, players, motd, gameMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,11 +123,12 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
private boolean mojangBanned;
|
private boolean mojangBanned;
|
||||||
|
|
||||||
private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull DNSRecord[] records, @NonNull Version version,
|
private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull DNSRecord[] records, GeoLocation geo,
|
||||||
@NonNull Players players, @NonNull MOTD motd, Favicon favicon, String software, Plugin[] plugins,
|
@NonNull Version version, @NonNull Players players, @NonNull MOTD motd, Favicon favicon,
|
||||||
ModInfo modInfo, ForgeData forgeData, String world, boolean queryEnabled, boolean previewsChat,
|
String software, Plugin[] plugins, ModInfo modInfo, ForgeData forgeData, String world,
|
||||||
boolean enforcesSecureChat, boolean preventsChatReports, boolean mojangBanned) {
|
boolean queryEnabled, boolean previewsChat, boolean enforcesSecureChat, boolean preventsChatReports,
|
||||||
super(hostname, ip, port, records, players, motd);
|
boolean mojangBanned) {
|
||||||
|
super(hostname, ip, port, records, geo, players, motd);
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.favicon = favicon;
|
this.favicon = favicon;
|
||||||
this.software = software;
|
this.software = software;
|
||||||
@ -173,7 +174,7 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
|||||||
}
|
}
|
||||||
String world = challengeStatusToken == null ? null : challengeStatusToken.getMap(); // The main server world
|
String world = challengeStatusToken == null ? null : challengeStatusToken.getMap(); // The main server world
|
||||||
|
|
||||||
return new JavaMinecraftServer(hostname, ip, port, records, statusToken.getVersion().detailedCopy(), Players.create(statusToken.getPlayers()),
|
return new JavaMinecraftServer(hostname, ip, port, records, null, statusToken.getVersion().detailedCopy(), Players.create(statusToken.getPlayers()),
|
||||||
MOTD.create(motdString), Favicon.create(statusToken.getFavicon(), hostname), software, plugins, statusToken.getModInfo(),
|
MOTD.create(motdString), Favicon.create(statusToken.getFavicon(), hostname), software, plugins, statusToken.getModInfo(),
|
||||||
statusToken.getForgeData(), world, challengeStatusToken != null, statusToken.isPreviewsChat(),
|
statusToken.getForgeData(), world, challengeStatusToken != null, statusToken.isPreviewsChat(),
|
||||||
statusToken.isEnforcesSecureChat(), statusToken.isPreventsChatReports(), false
|
statusToken.isEnforcesSecureChat(), statusToken.isPreventsChatReports(), false
|
||||||
|
@ -23,14 +23,189 @@
|
|||||||
*/
|
*/
|
||||||
package me.braydon.mc.service;
|
package me.braydon.mc.service;
|
||||||
|
|
||||||
|
import com.maxmind.db.CHMCache;
|
||||||
|
import com.maxmind.geoip2.DatabaseReader;
|
||||||
|
import com.maxmind.geoip2.model.CityResponse;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.codehaus.plexus.archiver.tar.TarGZipUnArchiver;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service @Log4j2(topic = "MaxMind")
|
||||||
public final class MaxMindService {
|
public final class MaxMindService {
|
||||||
|
/**
|
||||||
|
* The directory to store databases.
|
||||||
|
*/
|
||||||
|
private static final File DATABASES_DIRECTORY = new File("databases");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The endpoint to download database files from.
|
||||||
|
*/
|
||||||
|
private static final String DATABASE_DOWNLOAD_ENDPOINT = "https://download.maxmind.com/app/geoip_download?edition_id=%s&license_key=%s&suffix=tar.gz";
|
||||||
|
|
||||||
@Value("${maxmind.license}")
|
@Value("${maxmind.license}")
|
||||||
private String license;
|
private String license;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently loaded databases.
|
||||||
|
*/
|
||||||
|
private final Map<Database, DatabaseReader> databases = new HashMap<>();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void onInitialize() {
|
||||||
|
loadDatabases(); // Load the databases
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the databases.
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
private void loadDatabases() {
|
||||||
|
log.info("Loading databases...");
|
||||||
|
|
||||||
|
// Create the directory if it doesn't exist
|
||||||
|
if (!DATABASES_DIRECTORY.exists()) {
|
||||||
|
DATABASES_DIRECTORY.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download missing databases
|
||||||
|
for (Database database : Database.values()) {
|
||||||
|
File databaseFile = new File(DATABASES_DIRECTORY, database.getEdition() + ".mmdb");
|
||||||
|
if (!databaseFile.exists()) { // Doesn't exist, download it
|
||||||
|
downloadDatabase(database, databaseFile);
|
||||||
|
}
|
||||||
|
// Load the database and store it
|
||||||
|
databases.put(database, new DatabaseReader.Builder(databaseFile)
|
||||||
|
.withCache(new CHMCache()) // Enable caching
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
log.info("Loaded database {}", database.getEdition());
|
||||||
|
}
|
||||||
|
log.info("Loaded {} database(s)", databases.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a city by the given address.
|
||||||
|
*
|
||||||
|
* @param address the address
|
||||||
|
* @return the city response
|
||||||
|
*/
|
||||||
|
@SneakyThrows @NonNull
|
||||||
|
public CityResponse lookupCity(@NonNull InetAddress address) {
|
||||||
|
return getDatabase(Database.CITY).city(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download the required files
|
||||||
|
* for the given database.
|
||||||
|
*
|
||||||
|
* @param database the database to download
|
||||||
|
* @param databaseFile the file for the database
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
private void downloadDatabase(@NonNull Database database, @NonNull File databaseFile) {
|
||||||
|
File downloadedFile = new File(DATABASES_DIRECTORY, database.getEdition() + ".tar.gz"); // The downloaded file
|
||||||
|
|
||||||
|
// Download the database if required
|
||||||
|
if (!downloadedFile.exists()) {
|
||||||
|
log.info("Downloading database {}...", database.getEdition());
|
||||||
|
long before = System.currentTimeMillis();
|
||||||
|
try (
|
||||||
|
BufferedInputStream inputStream = new BufferedInputStream(new URL(DATABASE_DOWNLOAD_ENDPOINT.formatted(database.getEdition(), license)).openStream());
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(downloadedFile)
|
||||||
|
) {
|
||||||
|
byte[] dataBuffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(dataBuffer, 0, 1024)) != -1) {
|
||||||
|
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("Downloaded database {} in {}ms", database.getEdition(), System.currentTimeMillis() - before);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the database once downloaded
|
||||||
|
log.info("Extracting database {}...", database.getEdition());
|
||||||
|
TarGZipUnArchiver archiver = new TarGZipUnArchiver();
|
||||||
|
archiver.setSourceFile(downloadedFile);
|
||||||
|
archiver.setDestDirectory(DATABASES_DIRECTORY);
|
||||||
|
archiver.extract();
|
||||||
|
log.info("Extracted database {}", database.getEdition());
|
||||||
|
|
||||||
|
// Locate the database file in the extracted directory
|
||||||
|
File[] files = DATABASES_DIRECTORY.listFiles();
|
||||||
|
assert files != null; // Ensure files is present
|
||||||
|
dirLoop: for (File directory : files) {
|
||||||
|
if (!directory.isDirectory() || !directory.getName().startsWith(database.getEdition())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File[] downloadedFiles = directory.listFiles();
|
||||||
|
assert downloadedFiles != null; // Ensures downloaded files is present
|
||||||
|
|
||||||
|
// Find the file for the database, move it to the
|
||||||
|
// correct directory, and delete the downloaded contents
|
||||||
|
for (File file : downloadedFiles) {
|
||||||
|
if (file.isFile() && file.getName().equals(databaseFile.getName())) {
|
||||||
|
Files.move(file.toPath(), databaseFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
|
// Delete the downloaded contents
|
||||||
|
FileUtils.deleteDirectory(directory);
|
||||||
|
FileUtils.deleteQuietly(downloadedFile);
|
||||||
|
|
||||||
|
break dirLoop; // We're done here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the reader for the given database.
|
||||||
|
*
|
||||||
|
* @param database the database to get
|
||||||
|
* @return the database reader
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public DatabaseReader getDatabase(@NonNull Database database) {
|
||||||
|
return databases.get(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup when the app is destroyed.
|
||||||
|
*/
|
||||||
|
@PreDestroy @SneakyThrows
|
||||||
|
public void cleanup() {
|
||||||
|
for (DatabaseReader database : databases.values()) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
databases.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A database for MaxMind.
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor @Getter @ToString
|
||||||
|
public enum Database {
|
||||||
|
CITY("GeoLite2-City");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The edition of this database.
|
||||||
|
*/
|
||||||
|
@NonNull private final String edition;
|
||||||
|
}
|
||||||
}
|
}
|
@ -27,6 +27,7 @@ import com.google.common.base.Joiner;
|
|||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
|
import com.maxmind.geoip2.model.CityResponse;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.PreDestroy;
|
import jakarta.annotation.PreDestroy;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -65,6 +66,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -91,6 +93,11 @@ public final class MojangService {
|
|||||||
private static final Splitter DOT_SPLITTER = Splitter.on('.');
|
private static final Splitter DOT_SPLITTER = Splitter.on('.');
|
||||||
private static final Joiner DOT_JOINER = Joiner.on('.');
|
private static final Joiner DOT_JOINER = Joiner.on('.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MaxMind service to use for Geo lookups.
|
||||||
|
*/
|
||||||
|
@NonNull private final MaxMindService maxMindService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cache repository for {@link Player}'s by their username.
|
* The cache repository for {@link Player}'s by their username.
|
||||||
*/
|
*/
|
||||||
@ -135,8 +142,9 @@ public final class MojangService {
|
|||||||
private final ExpiringSet<String> blockedServersCache = new ExpiringSet<>(ExpirationPolicy.CREATED, 10L, TimeUnit.MINUTES);
|
private final ExpiringSet<String> blockedServersCache = new ExpiringSet<>(ExpirationPolicy.CREATED, 10L, TimeUnit.MINUTES);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public MojangService(@NonNull PlayerNameCacheRepository playerNameCache, @NonNull PlayerCacheRepository playerCache,
|
public MojangService(@NonNull MaxMindService maxMindService, @NonNull PlayerNameCacheRepository playerNameCache, @NonNull PlayerCacheRepository playerCache,
|
||||||
@NonNull SkinPartTextureCacheRepository skinPartTextureCache, @NonNull MinecraftServerCacheRepository minecraftServerCache) {
|
@NonNull SkinPartTextureCacheRepository skinPartTextureCache, @NonNull MinecraftServerCacheRepository minecraftServerCache) {
|
||||||
|
this.maxMindService = maxMindService;
|
||||||
this.playerNameCache = playerNameCache;
|
this.playerNameCache = playerNameCache;
|
||||||
this.playerCache = playerCache;
|
this.playerCache = playerCache;
|
||||||
this.skinPartTextureCache = skinPartTextureCache;
|
this.skinPartTextureCache = skinPartTextureCache;
|
||||||
@ -454,11 +462,24 @@ public final class MojangService {
|
|||||||
log.info("Resolved hostname: {} -> {}", hostname, ip);
|
log.info("Resolved hostname: {} -> {}", hostname, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to perform a Geo lookup on the server
|
||||||
|
CityResponse geo = null; // The server's Geo location
|
||||||
|
try {
|
||||||
|
log.info("Looking up Geo location data for {}...", ip);
|
||||||
|
geo = maxMindService.lookupCity(InetAddress.getByName(ip)); // Get the Geo location
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("Failed looking up Geo location data for %s:".formatted(ip), ex);
|
||||||
|
}
|
||||||
|
|
||||||
// Build our server model, cache it, and then return it
|
// Build our server model, cache it, and then return it
|
||||||
MinecraftServer response = platform.getPinger().ping(hostname, ip, port, records.toArray(new DNSRecord[0])); // Ping the server and await a response
|
MinecraftServer response = platform.getPinger().ping(hostname, ip, port, records.toArray(new DNSRecord[0])); // Ping the server and await a response
|
||||||
if (response == null) { // No response from ping
|
if (response == null) { // No response from ping
|
||||||
throw new ResourceNotFoundException("Server didn't respond to ping");
|
throw new ResourceNotFoundException("Server didn't respond to ping");
|
||||||
}
|
}
|
||||||
|
if (geo != null) { // Update Geo location data in the server if present
|
||||||
|
response.setGeo(MinecraftServer.GeoLocation.create(geo));
|
||||||
|
}
|
||||||
|
|
||||||
CachedMinecraftServer minecraftServer = new CachedMinecraftServer(
|
CachedMinecraftServer minecraftServer = new CachedMinecraftServer(
|
||||||
platform.name() + "-" + lookupHostname, response, System.currentTimeMillis()
|
platform.name() + "-" + lookupHostname, response, System.currentTimeMillis()
|
||||||
);
|
);
|
||||||
@ -567,6 +588,9 @@ public final class MojangService {
|
|||||||
return blocked;
|
return blocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup when the app is destroyed.
|
||||||
|
*/
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
mojangServerStatuses.clear();
|
mojangServerStatuses.clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user