This commit is contained in:
itqop 2025-10-18 19:05:40 +03:00
parent 8749276420
commit e409c0d907
3 changed files with 147 additions and 198 deletions

View File

@ -15,12 +15,16 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class WhitelistApiClient { public class WhitelistApiClient {
private static final WhitelistApiClient INSTANCE = new WhitelistApiClient();
public static WhitelistApiClient get() { return INSTANCE; }
public static void refreshConfigFromSpec() { INSTANCE.refreshFromConfig(); }
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
private static final Gson GSON = new Gson(); private static final Gson GSON = new Gson();
private final HttpClient http;
private volatile HttpClient http;
private volatile String baseUrl; private volatile String baseUrl;
public WhitelistApiClient() { public WhitelistApiClient() {
@ -38,12 +42,16 @@ public class WhitelistApiClient {
private static String normalizeBaseUrl(String url) { private static String normalizeBaseUrl(String url) {
if (url == null || url.isBlank()) return ""; if (url == null || url.isBlank()) return "";
String u = url.trim(); String u = url.trim();
while (u.endsWith("/")) u = u.substring(0, u.length() - 1); if (u.endsWith("/")) u = u.substring(0, u.length() - 1);
return u; return u;
} }
public CompletableFuture<Boolean> addPlayer(String playerName) { private HttpRequest.Builder baseBuilder(String path) {
return addPlayer(playerName, null, null, null); return HttpRequest.newBuilder(URI.create(baseUrl + path))
.timeout(Duration.ofSeconds(Math.max(1, Config.requestTimeout)))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("X-API-Key", Config.apiKey);
} }
public CompletableFuture<Boolean> addPlayer(String playerName, String reason) { public CompletableFuture<Boolean> addPlayer(String playerName, String reason) {
@ -52,120 +60,59 @@ public class WhitelistApiClient {
public CompletableFuture<Boolean> addPlayer(String playerName, String playerUuid, String addedBy, String addedAt) { public CompletableFuture<Boolean> addPlayer(String playerName, String playerUuid, String addedBy, String addedAt) {
Objects.requireNonNull(playerName, "playerName"); Objects.requireNonNull(playerName, "playerName");
Instant t0 = Instant.now(); if (Config.enableLogging) LOGGER.info("[ADD] player={}", playerName);
if (Config.enableLogging) LOGGER.info("[ADD] start -> player={}, reason=null", playerName);
JsonObject body = new JsonObject(); JsonObject body = new JsonObject();
body.addProperty("player_name", playerName); body.addProperty("player_name", playerName);
if (playerUuid != null && !playerUuid.isBlank()) body.addProperty("player_uuid", playerUuid); if (playerUuid != null && !playerUuid.isBlank()) body.addProperty("player_uuid", playerUuid);
if (addedBy != null && !addedBy.isBlank()) body.addProperty("added_by", addedBy); if (addedBy != null && !addedBy.isBlank()) body.addProperty("added_by", addedBy);
if (addedAt != null && !addedAt.isBlank()) body.addProperty("added_at", addedAt); if (addedAt != null && !addedAt.isBlank()) body.addProperty("added_at", addedAt);
return makeRequest("POST", "/add", body) return makeRequest("POST", "/add", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS) .thenApply(resp -> resp != null && resp.statusCode() / 100 == 2);
.thenApply(resp -> handleBooleanResponse(resp, "ADD", playerName, t0))
.exceptionally(ex -> {
long ms = Duration.between(t0, Instant.now()).toMillis();
LOGGER.error("[ADD] fail player={} in {} ms: {}", playerName, ms, ex.toString());
return false;
});
} }
public CompletableFuture<Boolean> removePlayer(String playerName) { public CompletableFuture<Boolean> removePlayer(String playerName) {
Objects.requireNonNull(playerName, "playerName"); Objects.requireNonNull(playerName, "playerName");
Instant t0 = Instant.now(); if (Config.enableLogging) LOGGER.info("[REMOVE] player={}", playerName);
if (Config.enableLogging) LOGGER.info("[REMOVE] start -> player={}", playerName);
JsonObject body = new JsonObject(); JsonObject body = new JsonObject();
body.addProperty("player_name", playerName); body.addProperty("player_name", playerName);
return makeRequest("POST", "/remove", body) return makeRequest("POST", "/remove", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS) .thenApply(resp -> resp != null && resp.statusCode() / 100 == 2);
.thenApply(resp -> handleBooleanResponse(resp, "REMOVE", playerName, t0))
.exceptionally(ex -> {
long ms = Duration.between(t0, Instant.now()).toMillis();
LOGGER.error("[REMOVE] fail player={} in {} ms: {}", playerName, ms, ex.toString());
return false;
});
} }
public CompletableFuture<CheckResponse> checkPlayer(String playerName) { public CompletableFuture<CheckResponse> checkPlayer(String playerName) {
Objects.requireNonNull(playerName, "playerName"); Objects.requireNonNull(playerName, "playerName");
Instant t0 = Instant.now(); if (Config.enableLogging) LOGGER.info("[CHECK] player={}", playerName);
if (Config.enableLogging) LOGGER.info("[CHECK] start -> player={}", playerName);
JsonObject body = new JsonObject(); JsonObject body = new JsonObject();
body.addProperty("player_name", playerName); body.addProperty("player_name", playerName);
return makeRequest("POST", "/check", body) return makeRequest("POST", "/check", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS) .thenApply(response -> {
.thenApply(resp -> { if (response == null) return new CheckResponse(false, false, null);
long ms = Duration.between(t0, Instant.now()).toMillis();
int code = resp.statusCode();
String bodyStr = resp.body();
if (code / 100 != 2) {
LOGGER.warn("[CHECK] non-2xx code={} for player={}, {} ms; body={}",
code, playerName, ms, HttpUtils.abbreviate(bodyStr, 512));
return new CheckResponse(false, false, null);
}
if (bodyStr == null || bodyStr.isBlank()) return new CheckResponse(true, false, null);
try { try {
JsonObject json = JsonParser.parseString(bodyStr).getAsJsonObject(); String bodyStr = response.body();
JsonElement el = JsonParser.parseString(bodyStr);
JsonObject json = el.getAsJsonObject();
boolean ok = json.has("ok") && json.get("ok").getAsBoolean();
boolean isWhitelisted = json.has("is_whitelisted") && json.get("is_whitelisted").getAsBoolean(); boolean isWhitelisted = json.has("is_whitelisted") && json.get("is_whitelisted").getAsBoolean();
String uuid = json.has("player_uuid") && !json.get("player_uuid").isJsonNull() String uuid = json.has("player_uuid") && !json.get("player_uuid").isJsonNull()
? json.get("player_uuid").getAsString() ? json.get("player_uuid").getAsString()
: null; : null;
if (Config.enableLogging) LOGGER.info("[CHECK] ok player={} -> isWhitelisted={}, uuid={}, {} ms", return new CheckResponse(ok, isWhitelisted, uuid);
playerName, isWhitelisted, uuid, ms);
return new CheckResponse(true, isWhitelisted, uuid);
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("[CHECK] parse error player={} in {} ms: {}\nbody={}",
playerName, ms, e.toString(), HttpUtils.abbreviate(bodyStr, 512));
return new CheckResponse(false, false, null); return new CheckResponse(false, false, null);
} }
}) })
.exceptionally(ex -> { .exceptionally(ex -> new CheckResponse(false, false, null));
long ms = Duration.between(t0, Instant.now()).toMillis();
LOGGER.error("[CHECK] fail player={} in {} ms: {}", playerName, ms, ex.toString());
return new CheckResponse(false, false, null);
});
} }
private CompletableFuture<HttpResponse<String>> makeRequest(String method, String path, JsonObject body) { private CompletableFuture<HttpResponse<String>> makeRequest(String method, String path, HttpRequest.BodyPublisher body) {
String url = baseUrl + path; HttpRequest.Builder b = baseBuilder(path);
String payload = body == null ? "{}" : GSON.toJson(body); if ("POST".equalsIgnoreCase(method)) b.POST(body);
if (Config.enableLogging) LOGGER.info("[HTTP] {} {} payload_len={}", method, url, payload.length()); else if ("PUT".equalsIgnoreCase(method)) b.PUT(body);
HttpRequest.Builder b = HttpRequest.newBuilder() else if ("DELETE".equalsIgnoreCase(method)) b.method("DELETE", body);
.uri(URI.create(url)) else b.method(method, body);
.timeout(Duration.ofSeconds(Math.max(1, Config.requestTimeout)))
.header("Accept", "application/json");
if (Config.apiKey != null && !Config.apiKey.isBlank()) b.header("X-API-Key", Config.apiKey);
if ("GET".equals(method)) {
b.GET();
} else if ("POST".equals(method)) {
b.header("Content-Type", "application/json");
b.POST(HttpRequest.BodyPublishers.ofString(payload));
} else {
throw new IllegalArgumentException("Unsupported method: " + method);
}
return http.sendAsync(b.build(), HttpResponse.BodyHandlers.ofString()); return http.sendAsync(b.build(), HttpResponse.BodyHandlers.ofString());
} }
private boolean handleBooleanResponse(HttpResponse<String> resp, String op, String playerName, Instant t0) {
long ms = Duration.between(t0, Instant.now()).toMillis();
int code = resp.statusCode();
String body = resp.body();
if (code / 100 != 2) {
LOGGER.warn("[{}] non-2xx code={} player={} {} ms; body={}", op, code, playerName, ms, HttpUtils.abbreviate(body, 512));
return false;
}
if (body == null || body.isBlank()) return true;
try {
JsonElement el = JsonParser.parseString(body);
if (el.isJsonObject()) {
JsonObject json = el.getAsJsonObject();
if (json.has("success")) return json.get("success").getAsBoolean();
}
return true;
} catch (Exception e) {
return true;
}
}
public static final class CheckResponse { public static final class CheckResponse {
private final boolean success; private final boolean success;
private final boolean isWhitelisted; private final boolean isWhitelisted;
@ -179,12 +126,4 @@ public class WhitelistApiClient {
public boolean isWhitelisted() { return isWhitelisted; } public boolean isWhitelisted() { return isWhitelisted; }
public String getPlayerUuid() { return playerUuid; } public String getPlayerUuid() { return playerUuid; }
} }
private static final class HttpUtils {
static String abbreviate(String s, int max) {
if (s == null) return null;
if (s.length() <= max) return s;
return s.substring(0, Math.max(0, max - 3)) + "...";
}
}
} }

View File

@ -3,29 +3,32 @@ package org.itqop.whitelist;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.logging.LogUtils; import com.mojang.brigadier.suggestion.SuggestionProvider;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant; import java.time.Instant;
import java.util.Locale; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher; import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern; import java.util.stream.Collectors;
import net.neoforged.fml.loading.FMLPaths;
public class WhitelistCommands { public class WhitelistCommands {
private static final Logger LOGGER = LogUtils.getLogger();
private static final WhitelistApiClient API = new WhitelistApiClient(); private static final WhitelistApiClient API = new WhitelistApiClient();
private static final SuggestionProvider<CommandSourceStack> ONLINE_PLAYER_SUGGESTIONS = (ctx, builder) -> {
List<String> names = ctx.getSource().getServer().getPlayerList().getPlayers()
.stream()
.map(p -> p.getGameProfile().getName())
.collect(Collectors.toList());
return SharedSuggestionProvider.suggest(names, builder);
};
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) { public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("wl") dispatcher.register(Commands.literal("wl")
.requires(src -> src.hasPermission(3)) .requires(src -> src.hasPermission(3))
@ -34,152 +37,134 @@ public class WhitelistCommands {
.then(Commands.literal("status").executes(WhitelistCommands::whitelistStatus)) .then(Commands.literal("status").executes(WhitelistCommands::whitelistStatus))
.then(Commands.literal("add") .then(Commands.literal("add")
.then(Commands.argument("player", StringArgumentType.string()) .then(Commands.argument("player", StringArgumentType.string())
.suggests(ONLINE_PLAYER_SUGGESTIONS)
.executes(WhitelistCommands::addPlayer) .executes(WhitelistCommands::addPlayer)
.then(Commands.argument("reason", StringArgumentType.greedyString()) .then(Commands.argument("reason", StringArgumentType.greedyString())
.executes(WhitelistCommands::addPlayer)))) .executes(WhitelistCommands::addPlayer))))
.then(Commands.literal("remove") .then(Commands.literal("remove")
.then(Commands.argument("player", StringArgumentType.string()) .then(Commands.argument("player", StringArgumentType.string())
.suggests(ONLINE_PLAYER_SUGGESTIONS)
.executes(WhitelistCommands::removePlayer))) .executes(WhitelistCommands::removePlayer)))
.then(Commands.literal("check") .then(Commands.literal("check")
.then(Commands.argument("player", StringArgumentType.string()) .then(Commands.argument("player", StringArgumentType.string())
.suggests(ONLINE_PLAYER_SUGGESTIONS)
.executes(WhitelistCommands::checkPlayer))) .executes(WhitelistCommands::checkPlayer)))
); );
} }
private static int enableWhitelist(CommandContext<CommandSourceStack> ctx) { private static int enableWhitelist(CommandContext<CommandSourceStack> ctx) {
boolean changed = setEnableWhitelistPersisted(ctx, true); boolean changed = setEnableWhitelistPersisted(ctx, true);
if (!changed) return 0; if (!changed) {
sendOnServer(ctx, Component.literal("Whitelist enabled"), true); ctx.getSource().sendFailure(Component.literal("Whitelist already enabled"));
return 0;
}
ctx.getSource().sendSuccess(() -> Component.literal("Whitelist enabled"), true);
return 1; return 1;
} }
private static int disableWhitelist(CommandContext<CommandSourceStack> ctx) { private static int disableWhitelist(CommandContext<CommandSourceStack> ctx) {
boolean changed = setEnableWhitelistPersisted(ctx, false); boolean changed = setEnableWhitelistPersisted(ctx, false);
if (!changed) return 0; if (!changed) {
sendOnServer(ctx, Component.literal("Whitelist disabled"), true); ctx.getSource().sendFailure(Component.literal("Whitelist already disabled"));
return 0;
}
ctx.getSource().sendSuccess(() -> Component.literal("Whitelist disabled"), true);
return 1; return 1;
} }
private static int whitelistStatus(CommandContext<CommandSourceStack> ctx) { private static int whitelistStatus(CommandContext<CommandSourceStack> ctx) {
boolean enabled = Config.enableWhitelist; ctx.getSource().sendSuccess(() -> Component.literal("Whitelist is " + (Config.enableWhitelist ? "ON" : "OFF")), false);
sendOnServer(ctx, Component.literal("Whitelist status: " + (enabled ? "ON" : "OFF")), false);
return 1; return 1;
} }
private static int addPlayer(CommandContext<CommandSourceStack> ctx) { private static int addPlayer(CommandContext<CommandSourceStack> ctx) {
final String player = StringArgumentType.getString(ctx, "player"); String player = StringArgumentType.getString(ctx, "player");
final String reason = ctx.getInput().contains(" add ") && ctx.getInput().split(" add ").length > 1 && ctx.getInput().split(" add ")[1].contains(" ") String input = ctx.getInput();
? ctx.getInput().substring(ctx.getInput().indexOf(" add ") + 5 + player.length()).trim() String reason = null;
: null; int idx = input.indexOf(" add ");
final String addedBy = getSourceName(ctx); if (idx >= 0) {
final String addedAt = Instant.now().toString(); String tail = input.substring(idx + 5);
final String uuid = resolveUuid(ctx.getSource().getServer(), player); int sp = tail.indexOf(' ');
sendOnServer(ctx, Component.literal("Adding player to whitelist: " + player), false); if (sp >= 0) reason = tail.substring(sp + 1).trim();
API.addPlayer(player, uuid, addedBy, addedAt)
.thenAccept(success -> dispatchBack(ctx, () -> {
if (success) {
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " added to whitelist"), true);
} else {
ctx.getSource().sendFailure(Component.literal("Failed to add player " + player + " to whitelist"));
} }
})) String addedBy = getSourceName(ctx);
.exceptionally(ex -> { String addedAt = Instant.now().toString();
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Error adding player: " + ex.getMessage()))); String uuid = resolveUuid(ctx.getSource().getServer(), player);
return null; sendOnServer(ctx, Component.literal("Adding player to whitelist: " + player), false);
}); API.addPlayer(player, uuid, addedBy, addedAt).thenAccept(success ->
dispatchBack(ctx, () -> {
if (success) {
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " added"), false);
} else {
ctx.getSource().sendFailure(Component.literal("Failed to add " + player));
}
})
);
return 1; return 1;
} }
private static int removePlayer(CommandContext<CommandSourceStack> ctx) { private static int removePlayer(CommandContext<CommandSourceStack> ctx) {
final String player = StringArgumentType.getString(ctx, "player"); String player = StringArgumentType.getString(ctx, "player");
sendOnServer(ctx, Component.literal("Removing player from whitelist: " + player), false); sendOnServer(ctx, Component.literal("Removing player from whitelist: " + player), false);
API.removePlayer(player) API.removePlayer(player).thenAccept(success ->
.thenAccept(success -> dispatchBack(ctx, () -> { dispatchBack(ctx, () -> {
if (success) { if (success) {
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " removed from whitelist"), true); ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " removed"), false);
} else { ServerPlayer sp = ctx.getSource().getServer().getPlayerList().getPlayerByName(player);
ctx.getSource().sendFailure(Component.literal("Failed to remove player " + player + " from whitelist")); if (sp != null) {
sp.connection.disconnect(Component.literal("Removed from whitelist"));
} }
})) } else {
.exceptionally(ex -> { ctx.getSource().sendFailure(Component.literal("Failed to remove " + player));
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Error removing player: " + ex.getMessage()))); }
return null; })
}); );
return 1; return 1;
} }
private static int checkPlayer(CommandContext<CommandSourceStack> ctx) { private static int checkPlayer(CommandContext<CommandSourceStack> ctx) {
final String player = StringArgumentType.getString(ctx, "player"); String player = StringArgumentType.getString(ctx, "player");
sendOnServer(ctx, Component.literal("Checking whitelist status: " + player), false); API.checkPlayer(player).thenAccept(resp ->
API.checkPlayer(player) dispatchBack(ctx, () -> {
.thenAccept(res -> dispatchBack(ctx, () -> { if (resp != null && resp.isSuccess()) {
if (!res.isSuccess()) { String msg = resp.isWhitelisted() ? "is in whitelist" : "is NOT in whitelist";
ctx.getSource().sendFailure(Component.literal("Check failed for player " + player)); ctx.getSource().sendSuccess(() -> Component.literal(player + " " + msg), false);
return; } else {
ctx.getSource().sendFailure(Component.literal("Check failed for " + player));
} }
String msg = String.format(Locale.ROOT, })
"Player %s -> whitelisted=%s%s", );
player,
res.isWhitelisted(),
res.getPlayerUuid() != null ? ", uuid=" + res.getPlayerUuid() : "");
ctx.getSource().sendSuccess(() -> Component.literal(msg), false);
}))
.exceptionally(ex -> {
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Error checking player: " + ex.getMessage())));
return null;
});
return 1; return 1;
} }
private static void sendOnServer(CommandContext<CommandSourceStack> ctx, Component msg, boolean broadcastToAdmins) { private static void sendOnServer(CommandContext<CommandSourceStack> ctx, Component msg, boolean broadcast) {
dispatchBack(ctx, () -> ctx.getSource().sendSuccess(() -> msg, broadcastToAdmins)); if (broadcast) {
} ctx.getSource().getServer().getPlayerList().broadcastSystemMessage(msg, false);
} else {
private static void dispatchBack(CommandContext<CommandSourceStack> ctx, Runnable action) { ctx.getSource().sendSuccess(() -> msg, false);
MinecraftServer srv = ctx.getSource().getServer();
srv.execute(action);
}
private static boolean setEnableWhitelistPersisted(CommandContext<CommandSourceStack> ctx, boolean value) {
try {
Config.enableWhitelist = value;
Path cfgPath = FMLPaths.CONFIGDIR.get().resolve(Whitelist.MODID + "-common.toml");
if (Files.exists(cfgPath)) {
String content = Files.readString(cfgPath);
String updated = replaceEnableWhitelist(content, value);
if (!content.equals(updated)) {
Files.writeString(cfgPath, updated);
}
}
API.refreshFromConfig();
return true;
} catch (Exception e) {
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Failed to persist config: " + e.getMessage())));
LOGGER.error("Persist enableWhitelist error", e);
return false;
} }
} }
private static String replaceEnableWhitelist(String toml, boolean value) { private static void dispatchBack(CommandContext<CommandSourceStack> ctx, Runnable task) {
Pattern p = Pattern.compile("(?m)^\\s*enableWhitelist\\s*=\\s*(true|false)\\s*$"); ctx.getSource().getServer().execute(task);
Matcher m = p.matcher(toml);
String replacement = "enableWhitelist = " + (value ? "true" : "false");
if (m.find()) {
return m.replaceFirst(replacement);
}
String sep = toml.endsWith("\n") ? "" : "\n";
return toml + sep + replacement + "\n";
} }
private static String getSourceName(CommandContext<CommandSourceStack> ctx) { private static String getSourceName(CommandContext<CommandSourceStack> ctx) {
try { try {
if (ctx.getSource().getEntity() instanceof ServerPlayer sp) { String s = ctx.getSource().getDisplayName().getString();
return sp.getGameProfile().getName(); if (!s.isEmpty()) return s;
}
} catch (Exception ignored) {} } catch (Exception ignored) {}
return "server"; return "server";
} }
private static boolean setEnableWhitelistPersisted(CommandContext<CommandSourceStack> ctx, boolean enabled) {
boolean changed = Config.enableWhitelist != enabled;
Config.enableWhitelist = enabled;
WhitelistApiClient.refreshConfigFromSpec();
ctx.getSource().getServer().submit(() -> {}).join();
return changed;
}
private static String resolveUuid(MinecraftServer srv, String player) { private static String resolveUuid(MinecraftServer srv, String player) {
try { try {
ServerPlayer sp = srv.getPlayerList().getPlayerByName(player); ServerPlayer sp = srv.getPlayerList().getPlayerByName(player);

View File

@ -1,18 +1,43 @@
package org.itqop.whitelist; package org.itqop.whitelist;
import com.mojang.logging.LogUtils;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent;
import org.slf4j.Logger; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
@EventBusSubscriber(modid = Whitelist.MODID) @EventBusSubscriber(modid = Whitelist.MODID)
public class WhitelistEventHandler { public class WhitelistEventHandler {
private static final Logger LOGGER = LogUtils.getLogger();
@SubscribeEvent @SubscribeEvent
public static void registerCommands(RegisterCommandsEvent event) { public static void registerCommands(RegisterCommandsEvent event) {
WhitelistCommands.register(event.getDispatcher()); WhitelistCommands.register(event.getDispatcher());
LOGGER.info("Whitelist commands registered"); }
@SubscribeEvent
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
if (!Config.enableWhitelist) return;
if (!(event.getEntity() instanceof ServerPlayer sp)) return;
String name = sp.getGameProfile().getName();
WhitelistApiClient.get().checkPlayer(name).thenAccept(resp -> {
if (resp != null && resp.isSuccess() && !resp.isWhitelisted()) {
sp.server.execute(() -> {
Component msg = Component.literal("Вас нету в белом списке сервера.\n")
.append(
Component.literal("Для входа необходимо приобрести проходку на сайте ")
.append(
Component.literal("hubmc.org/shop")
.withStyle(style -> style
.withUnderlined(true)
.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://hubmc.org/shop"))
)
)
);
sp.connection.disconnect(msg);
});
}
});
} }
} }