This commit is contained in:
parent
8749276420
commit
e409c0d907
|
|
@ -15,12 +15,16 @@ import java.time.Duration;
|
|||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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 Gson GSON = new Gson();
|
||||
private final HttpClient http;
|
||||
|
||||
private volatile HttpClient http;
|
||||
private volatile String baseUrl;
|
||||
|
||||
public WhitelistApiClient() {
|
||||
|
|
@ -38,12 +42,16 @@ public class WhitelistApiClient {
|
|||
private static String normalizeBaseUrl(String url) {
|
||||
if (url == null || url.isBlank()) return "";
|
||||
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;
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> addPlayer(String playerName) {
|
||||
return addPlayer(playerName, null, null, null);
|
||||
private HttpRequest.Builder baseBuilder(String path) {
|
||||
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) {
|
||||
|
|
@ -52,120 +60,59 @@ public class WhitelistApiClient {
|
|||
|
||||
public CompletableFuture<Boolean> addPlayer(String playerName, String playerUuid, String addedBy, String addedAt) {
|
||||
Objects.requireNonNull(playerName, "playerName");
|
||||
Instant t0 = Instant.now();
|
||||
if (Config.enableLogging) LOGGER.info("[ADD] start -> player={}, reason=null", playerName);
|
||||
if (Config.enableLogging) LOGGER.info("[ADD] player={}", playerName);
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("player_name", playerName);
|
||||
if (playerUuid != null && !playerUuid.isBlank()) body.addProperty("player_uuid", playerUuid);
|
||||
if (addedBy != null && !addedBy.isBlank()) body.addProperty("added_by", addedBy);
|
||||
if (addedAt != null && !addedAt.isBlank()) body.addProperty("added_at", addedAt);
|
||||
return makeRequest("POST", "/add", body)
|
||||
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS)
|
||||
.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;
|
||||
});
|
||||
return makeRequest("POST", "/add", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||
.thenApply(resp -> resp != null && resp.statusCode() / 100 == 2);
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> removePlayer(String playerName) {
|
||||
Objects.requireNonNull(playerName, "playerName");
|
||||
Instant t0 = Instant.now();
|
||||
if (Config.enableLogging) LOGGER.info("[REMOVE] start -> player={}", playerName);
|
||||
if (Config.enableLogging) LOGGER.info("[REMOVE] player={}", playerName);
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("player_name", playerName);
|
||||
return makeRequest("POST", "/remove", body)
|
||||
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS)
|
||||
.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;
|
||||
});
|
||||
return makeRequest("POST", "/remove", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||
.thenApply(resp -> resp != null && resp.statusCode() / 100 == 2);
|
||||
}
|
||||
|
||||
public CompletableFuture<CheckResponse> checkPlayer(String playerName) {
|
||||
Objects.requireNonNull(playerName, "playerName");
|
||||
Instant t0 = Instant.now();
|
||||
if (Config.enableLogging) LOGGER.info("[CHECK] start -> player={}", playerName);
|
||||
if (Config.enableLogging) LOGGER.info("[CHECK] player={}", playerName);
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("player_name", playerName);
|
||||
return makeRequest("POST", "/check", body)
|
||||
.orTimeout(Config.requestTimeout, TimeUnit.SECONDS)
|
||||
.thenApply(resp -> {
|
||||
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);
|
||||
return makeRequest("POST", "/check", HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||
.thenApply(response -> {
|
||||
if (response == null) return new CheckResponse(false, false, null);
|
||||
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();
|
||||
String uuid = json.has("player_uuid") && !json.get("player_uuid").isJsonNull()
|
||||
? json.get("player_uuid").getAsString()
|
||||
: null;
|
||||
if (Config.enableLogging) LOGGER.info("[CHECK] ok player={} -> isWhitelisted={}, uuid={}, {} ms",
|
||||
playerName, isWhitelisted, uuid, ms);
|
||||
return new CheckResponse(true, isWhitelisted, uuid);
|
||||
return new CheckResponse(ok, isWhitelisted, uuid);
|
||||
} 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);
|
||||
}
|
||||
})
|
||||
.exceptionally(ex -> {
|
||||
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);
|
||||
});
|
||||
.exceptionally(ex -> new CheckResponse(false, false, null));
|
||||
}
|
||||
|
||||
private CompletableFuture<HttpResponse<String>> makeRequest(String method, String path, JsonObject body) {
|
||||
String url = baseUrl + path;
|
||||
String payload = body == null ? "{}" : GSON.toJson(body);
|
||||
if (Config.enableLogging) LOGGER.info("[HTTP] {} {} payload_len={}", method, url, payload.length());
|
||||
HttpRequest.Builder b = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.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);
|
||||
}
|
||||
private CompletableFuture<HttpResponse<String>> makeRequest(String method, String path, HttpRequest.BodyPublisher body) {
|
||||
HttpRequest.Builder b = baseBuilder(path);
|
||||
if ("POST".equalsIgnoreCase(method)) b.POST(body);
|
||||
else if ("PUT".equalsIgnoreCase(method)) b.PUT(body);
|
||||
else if ("DELETE".equalsIgnoreCase(method)) b.method("DELETE", body);
|
||||
else b.method(method, body);
|
||||
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 {
|
||||
private final boolean success;
|
||||
private final boolean isWhitelisted;
|
||||
|
|
@ -179,12 +126,4 @@ public class WhitelistApiClient {
|
|||
public boolean isWhitelisted() { return isWhitelisted; }
|
||||
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)) + "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,29 +3,32 @@ package org.itqop.whitelist;
|
|||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
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.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.neoforged.fml.loading.FMLPaths;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WhitelistCommands {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
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) {
|
||||
dispatcher.register(Commands.literal("wl")
|
||||
.requires(src -> src.hasPermission(3))
|
||||
|
|
@ -34,152 +37,134 @@ public class WhitelistCommands {
|
|||
.then(Commands.literal("status").executes(WhitelistCommands::whitelistStatus))
|
||||
.then(Commands.literal("add")
|
||||
.then(Commands.argument("player", StringArgumentType.string())
|
||||
.suggests(ONLINE_PLAYER_SUGGESTIONS)
|
||||
.executes(WhitelistCommands::addPlayer)
|
||||
.then(Commands.argument("reason", StringArgumentType.greedyString())
|
||||
.executes(WhitelistCommands::addPlayer))))
|
||||
.then(Commands.literal("remove")
|
||||
.then(Commands.argument("player", StringArgumentType.string())
|
||||
.suggests(ONLINE_PLAYER_SUGGESTIONS)
|
||||
.executes(WhitelistCommands::removePlayer)))
|
||||
.then(Commands.literal("check")
|
||||
.then(Commands.argument("player", StringArgumentType.string())
|
||||
.suggests(ONLINE_PLAYER_SUGGESTIONS)
|
||||
.executes(WhitelistCommands::checkPlayer)))
|
||||
);
|
||||
}
|
||||
|
||||
private static int enableWhitelist(CommandContext<CommandSourceStack> ctx) {
|
||||
boolean changed = setEnableWhitelistPersisted(ctx, true);
|
||||
if (!changed) return 0;
|
||||
sendOnServer(ctx, Component.literal("Whitelist enabled"), true);
|
||||
if (!changed) {
|
||||
ctx.getSource().sendFailure(Component.literal("Whitelist already enabled"));
|
||||
return 0;
|
||||
}
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Whitelist enabled"), true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int disableWhitelist(CommandContext<CommandSourceStack> ctx) {
|
||||
boolean changed = setEnableWhitelistPersisted(ctx, false);
|
||||
if (!changed) return 0;
|
||||
sendOnServer(ctx, Component.literal("Whitelist disabled"), true);
|
||||
if (!changed) {
|
||||
ctx.getSource().sendFailure(Component.literal("Whitelist already disabled"));
|
||||
return 0;
|
||||
}
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Whitelist disabled"), true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int whitelistStatus(CommandContext<CommandSourceStack> ctx) {
|
||||
boolean enabled = Config.enableWhitelist;
|
||||
sendOnServer(ctx, Component.literal("Whitelist status: " + (enabled ? "ON" : "OFF")), false);
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Whitelist is " + (Config.enableWhitelist ? "ON" : "OFF")), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int addPlayer(CommandContext<CommandSourceStack> ctx) {
|
||||
final 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(" ")
|
||||
? ctx.getInput().substring(ctx.getInput().indexOf(" add ") + 5 + player.length()).trim()
|
||||
: null;
|
||||
final String addedBy = getSourceName(ctx);
|
||||
final String addedAt = Instant.now().toString();
|
||||
final String uuid = resolveUuid(ctx.getSource().getServer(), player);
|
||||
String player = StringArgumentType.getString(ctx, "player");
|
||||
String input = ctx.getInput();
|
||||
String reason = null;
|
||||
int idx = input.indexOf(" add ");
|
||||
if (idx >= 0) {
|
||||
String tail = input.substring(idx + 5);
|
||||
int sp = tail.indexOf(' ');
|
||||
if (sp >= 0) reason = tail.substring(sp + 1).trim();
|
||||
}
|
||||
String addedBy = getSourceName(ctx);
|
||||
String addedAt = Instant.now().toString();
|
||||
String uuid = resolveUuid(ctx.getSource().getServer(), player);
|
||||
sendOnServer(ctx, Component.literal("Adding player to whitelist: " + player), false);
|
||||
API.addPlayer(player, uuid, addedBy, addedAt)
|
||||
.thenAccept(success -> dispatchBack(ctx, () -> {
|
||||
API.addPlayer(player, uuid, addedBy, addedAt).thenAccept(success ->
|
||||
dispatchBack(ctx, () -> {
|
||||
if (success) {
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " added to whitelist"), true);
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " added"), false);
|
||||
} else {
|
||||
ctx.getSource().sendFailure(Component.literal("Failed to add player " + player + " to whitelist"));
|
||||
ctx.getSource().sendFailure(Component.literal("Failed to add " + player));
|
||||
}
|
||||
}))
|
||||
.exceptionally(ex -> {
|
||||
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Error adding player: " + ex.getMessage())));
|
||||
return null;
|
||||
});
|
||||
})
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
API.removePlayer(player)
|
||||
.thenAccept(success -> dispatchBack(ctx, () -> {
|
||||
API.removePlayer(player).thenAccept(success ->
|
||||
dispatchBack(ctx, () -> {
|
||||
if (success) {
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " removed from whitelist"), true);
|
||||
ctx.getSource().sendSuccess(() -> Component.literal("Player " + player + " removed"), false);
|
||||
ServerPlayer sp = ctx.getSource().getServer().getPlayerList().getPlayerByName(player);
|
||||
if (sp != null) {
|
||||
sp.connection.disconnect(Component.literal("Removed from whitelist"));
|
||||
}
|
||||
} else {
|
||||
ctx.getSource().sendFailure(Component.literal("Failed to remove player " + player + " from whitelist"));
|
||||
ctx.getSource().sendFailure(Component.literal("Failed to remove " + player));
|
||||
}
|
||||
}))
|
||||
.exceptionally(ex -> {
|
||||
dispatchBack(ctx, () -> ctx.getSource().sendFailure(Component.literal("Error removing player: " + ex.getMessage())));
|
||||
return null;
|
||||
});
|
||||
})
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int checkPlayer(CommandContext<CommandSourceStack> ctx) {
|
||||
final String player = StringArgumentType.getString(ctx, "player");
|
||||
sendOnServer(ctx, Component.literal("Checking whitelist status: " + player), false);
|
||||
API.checkPlayer(player)
|
||||
.thenAccept(res -> dispatchBack(ctx, () -> {
|
||||
if (!res.isSuccess()) {
|
||||
ctx.getSource().sendFailure(Component.literal("Check failed for player " + player));
|
||||
return;
|
||||
String player = StringArgumentType.getString(ctx, "player");
|
||||
API.checkPlayer(player).thenAccept(resp ->
|
||||
dispatchBack(ctx, () -> {
|
||||
if (resp != null && resp.isSuccess()) {
|
||||
String msg = resp.isWhitelisted() ? "is in whitelist" : "is NOT in whitelist";
|
||||
ctx.getSource().sendSuccess(() -> Component.literal(player + " " + msg), false);
|
||||
} 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;
|
||||
}
|
||||
|
||||
private static void sendOnServer(CommandContext<CommandSourceStack> ctx, Component msg, boolean broadcastToAdmins) {
|
||||
dispatchBack(ctx, () -> ctx.getSource().sendSuccess(() -> msg, broadcastToAdmins));
|
||||
}
|
||||
|
||||
private static void dispatchBack(CommandContext<CommandSourceStack> ctx, Runnable action) {
|
||||
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 void sendOnServer(CommandContext<CommandSourceStack> ctx, Component msg, boolean broadcast) {
|
||||
if (broadcast) {
|
||||
ctx.getSource().getServer().getPlayerList().broadcastSystemMessage(msg, false);
|
||||
} else {
|
||||
ctx.getSource().sendSuccess(() -> msg, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static String replaceEnableWhitelist(String toml, boolean value) {
|
||||
Pattern p = Pattern.compile("(?m)^\\s*enableWhitelist\\s*=\\s*(true|false)\\s*$");
|
||||
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 void dispatchBack(CommandContext<CommandSourceStack> ctx, Runnable task) {
|
||||
ctx.getSource().getServer().execute(task);
|
||||
}
|
||||
|
||||
private static String getSourceName(CommandContext<CommandSourceStack> ctx) {
|
||||
try {
|
||||
if (ctx.getSource().getEntity() instanceof ServerPlayer sp) {
|
||||
return sp.getGameProfile().getName();
|
||||
}
|
||||
String s = ctx.getSource().getDisplayName().getString();
|
||||
if (!s.isEmpty()) return s;
|
||||
} catch (Exception ignored) {}
|
||||
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) {
|
||||
try {
|
||||
ServerPlayer sp = srv.getPlayerList().getPlayerByName(player);
|
||||
|
|
|
|||
|
|
@ -1,18 +1,43 @@
|
|||
package org.itqop.whitelist;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
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)
|
||||
public class WhitelistEventHandler {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerCommands(RegisterCommandsEvent event) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue