fix some logic

This commit is contained in:
Colbster937 2025-05-11 14:40:36 -05:00
parent 8dbd01f016
commit af478adb3b
33 changed files with 244 additions and 104 deletions

7
bin/main/bungee.yml Normal file
View File

@ -0,0 +1,7 @@
name: OriginBlacklist
version: ${version}
main: dev.colbster937.originblacklist.bungee.OriginBlacklistBungee
description: ${description}
author: Colbster937
depends:
- EaglercraftXServer

69
bin/main/config.yml Normal file
View File

@ -0,0 +1,69 @@
messages:
# Valid Placeholders:
# - %blocked% - The player's origin/brand that was blocked
# - %blocktype% - Shows what the player was blocked for
# - %easyblocktype% - Shows what the player was blocked for in an eagler-kid readable form
# - %host% - The IP the player pinged
kick: |
<red>This %easyblocktype% is not allowed on the server!</red>
<dark_gray>»</dark_gray> <gray>%blocked%</gray> <dark_gray>«</dark_gray>
<gray>Think this is a mistake? Join our discord:</gray>
<blue>discord.gg/changethisintheconfig</blue>
motd:
enabled: true
text: |
<red>This %easyblocktype% is not allowed!</red>
<dark_gray>»</dark_gray> <gray>%blocked%</gray> <dark_gray>«</dark_gray>
icon: "blacklisted.png"
# Origin + Brand blacklist supports wildcards
# Everything should be lowercase
blacklist:
origins:
- "hack.example.com"
brands:
- "*dragonx*"
- "*piclient*"
missing_origin: false
blacklist_redirect: ""
discord:
webhook: ""
# :>

9
bin/main/plugin.yml Normal file
View File

@ -0,0 +1,9 @@
name: OriginBlacklist
version: ${version}
main: dev.colbster937.originblacklist.bukkit.OriginBlacklistBukkit
description: ${description}
author: Colbster937
depend:
- EaglercraftXServer
commands:
originblacklist:

BIN
bin/main/server-blocked.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,14 @@
{
"id": "originblacklist",
"name": "OriginBlacklist",
"version": "${version}",
"description": "${description}",
"main": "dev.colbster937.originblacklist.velocity.OriginBlacklistVelocity",
"authors": ["Colbster937"],
"dependencies": [
{
"id": "eaglerxserver",
"optional": false
}
]
}

View File

@ -8,7 +8,7 @@ plugins {
group = 'dev.colbster937' group = 'dev.colbster937'
version = '1.0.4' version = '1.0.5'
description = 'A reimplementation of OriginBlacklist for EaglerXServer' description = 'A reimplementation of OriginBlacklist for EaglerXServer'
def targetJavaVersion = 17 def targetJavaVersion = 17
@ -64,7 +64,7 @@ java {
} }
processResources { processResources {
filesMatching(['plugin.yml', 'bungee.yml', 'velocity-plugin.json']) { filesMatching(['plugin.yml', 'bungee.yml', 'velocity-plugin.json', 'Base.java']) {
expand( expand(
version: project.version, version: project.version,
description: project.description description: project.description

View File

@ -5,20 +5,21 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.lax1dude.eaglercraft.backend.server.api.*; import net.lax1dude.eaglercraft.backend.server.api.*;
import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftClientBrandEvent; import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftClientBrandEvent;
import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftLoginEvent;
import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftMOTDEvent; import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftMOTDEvent;
import net.lax1dude.eaglercraft.backend.server.api.query.IMOTDConnection; import net.lax1dude.eaglercraft.backend.server.api.query.IMOTDConnection;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.*;
import java.io.IOException; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class Base { public class Base {
@ -42,46 +43,51 @@ public class Base {
for (int i = 0; i < Math.max(c.length, r.length); i++) { for (int i = 0; i < Math.max(c.length, r.length); i++) {
int c1 = i < c.length ? Integer.parseInt(c[i]) : 0; int c1 = i < c.length ? Integer.parseInt(c[i]) : 0;
int r1 = i < r.length ? Integer.parseInt(r[i]) : 0; int r1 = i < r.length ? Integer.parseInt(r[i]) : 0;
if (c1 < r1) return false; if (c1 < r1)
if (c1 > r1) return true; return false;
if (c1 > r1)
return true;
} }
return true; return true;
} }
public static LoggerAdapter getLogger() { public static LoggerAdapter getLogger() {
if (adapter == null) throw new IllegalStateException("Logger not initialized!"); if (adapter == null)
throw new IllegalStateException("Logger not initialized!");
return adapter; return adapter;
} }
public interface LoggerAdapter { public interface LoggerAdapter {
void info(String msg); void info(String msg);
void warn(String msg); void warn(String msg);
void error(String msg); void error(String msg);
} }
public static void handleConnection(IEaglercraftClientBrandEvent e) { public static void handleConnection(IEaglercraftLoginEvent e) {
IEaglerPendingConnection conn = e.getPendingConnection(); IEaglerLoginConnection conn = e.getLoginConnection();
String origin = conn.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN); String origin = conn.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN);
String brand = conn.getEaglerBrandString(); String brand = conn.getEaglerBrandString();
if ((origin != "null" || origin != null) && !config.blacklist.missing_origin) {
if (origin != null && !origin.equals("null") && !config.blacklist.missing_origin) {
for (String origin1 : config.blacklist.origins) { for (String origin1 : config.blacklist.origins) {
if (matches(origin, origin1)) { if (matches(origin, origin1)) {
setKickMessage(e, kick("origin", "website", origin, conn.getWebSocketHost())); setKick(e, kick("origin", "website", origin, conn.getWebSocketHost()));
webhook(conn, origin, brand, "origin"); webhook(conn, origin, brand, "origin");
return; return;
} }
} }
} else { } else if (origin != null && !origin.equals("null")) {
if (origin != "null" || origin != null) { setKick(e, kick("origin", "website", origin, conn.getWebSocketHost()));
setKickMessage(e, kick("origin", "website", origin, conn.getWebSocketHost())); webhook(conn, "null", brand, "origin");
webhook(conn, "null", brand, "origin"); return;
return;
}
} }
if (brand != "null" && brand != null) {
if (brand != null && !brand.equals("null")) {
for (String brand1 : config.blacklist.brands) { for (String brand1 : config.blacklist.brands) {
if (matches(brand, brand1)) { if (matches(brand, brand1)) {
setKickMessage(e, kick("brand", "client", brand, conn.getWebSocketHost())); setKick(e, kick("brand", "client", brand, conn.getWebSocketHost()));
webhook(conn, origin, brand, "brand"); webhook(conn, origin, brand, "brand");
return; return;
} }
@ -89,9 +95,15 @@ public class Base {
} }
} }
public static void setKickMessage(IEaglercraftClientBrandEvent e, Component msg) { public static void setKick(IEaglercraftLoginEvent e, Component msg) {
try { try {
e.setKickMessage(msg); String redir = config.blacklist.blacklist_redirect;
if (redir.equals("") || redir.equals("null")) {
e.setKickMessage(msg);
} else {
e.setKickRedirect(redir);
}
getLogger().info("Kicked " + e.getProfileUsername());
} catch (Throwable ignored) { } catch (Throwable ignored) {
String msg1 = LegacyComponentSerializer.legacySection().serialize(msg); String msg1 = LegacyComponentSerializer.legacySection().serialize(msg);
e.setKickMessage(msg1); e.setKickMessage(msg1);
@ -104,26 +116,23 @@ public class Base {
String origin = conn.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN); String origin = conn.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN);
List<String> m = List.of(config.messages.motd.text.split("\n")).stream() List<String> m = List.of(config.messages.motd.text.split("\n")).stream()
.map(line -> line .map(line -> line
.replaceAll("%blocktype%", "origin") .replaceAll("%blocktype%", "origin")
.replaceAll("%easyblocktype%", "website") .replaceAll("%easyblocktype%", "website")
.replaceAll("%blocked%", origin) .replaceAll("%blocked%", origin)
.replaceAll("%host%", conn.getWebSocketHost())) .replaceAll("%host%", conn.getWebSocketHost()))
.map(line -> LegacyComponentSerializer.legacySection().serialize( .map(line -> LegacyComponentSerializer.legacySection().serialize(
MiniMessage.miniMessage().deserialize( MiniMessage.miniMessage().deserialize(line)))
line .collect(Collectors.toList());
)
)).collect(Collectors.toList()); if (origin != null && !origin.equals("null") && !config.blacklist.missing_origin) {
if ((origin != "null" || origin != null) && !config.blacklist.missing_origin) {
for (String origin1 : config.blacklist.origins) { for (String origin1 : config.blacklist.origins) {
if (matches(origin, origin1)) { if (matches(origin, origin1)) {
setMOTD(conn, m); setMOTD(conn, m);
return; return;
} }
} }
} else { } else if (origin != null && !origin.equals("null")) {
if (origin != "null" || origin != null) { setMOTD(conn, m);
setMOTD(conn, m);
}
} }
} }
} }
@ -133,13 +142,15 @@ public class Base {
conn.setPlayerTotal(0); conn.setPlayerTotal(0);
conn.setPlayerMax(0); conn.setPlayerMax(0);
conn.setPlayerList(List.of()); conn.setPlayerList(List.of());
if (config.messages.motd.icon != null && !config.messages.motd.icon.isEmpty())
if (config.messages.motd.icon != null && !config.messages.motd.icon.isEmpty()) {
try { try {
BufferedImage img = ImageIO.read(new File(config.messages.motd.icon)); BufferedImage img = ImageIO.read(new File(config.messages.motd.icon));
if (img.getWidth() != 64 || img.getHeight() != 64) { if (img.getWidth() != 64 || img.getHeight() != 64) {
getLogger().warn("Icon must be 64x64"); getLogger().warn("Icon must be 64x64");
return; return;
} }
byte[] bytes = new byte[64 * 64 * 4]; byte[] bytes = new byte[64 * 64 * 4];
for (int y = 0; y < 64; y++) { for (int y = 0; y < 64; y++) {
for (int x = 0; x < 64; x++) { for (int x = 0; x < 64; x++) {
@ -155,6 +166,7 @@ public class Base {
} catch (IOException ex) { } catch (IOException ex) {
getLogger().error(ex.toString()); getLogger().error(ex.toString());
} }
}
} }
public static boolean matches(String text1, String text2) { public static boolean matches(String text1, String text2) {
@ -163,55 +175,58 @@ public class Base {
public static Component kick(String type, String easytype, String value, String host) { public static Component kick(String type, String easytype, String value, String host) {
return MiniMessage.miniMessage().deserialize( return MiniMessage.miniMessage().deserialize(
config.messages.kick config.messages.kick
.replaceAll("%blocktype%", type) .replaceAll("%blocktype%", type)
.replaceAll("%easyblocktype%", easytype) .replaceAll("%easyblocktype%", easytype)
.replaceAll("%blocked%", value) .replaceAll("%blocked%", value)
.replaceAll("%host%", host) .replaceAll("%host%", host));
);
} }
public static void webhook(IEaglerPendingConnection plr, String origin, String brand, String type) { public static void webhook(IEaglerLoginConnection plr, String origin, String brand, String type) {
String webhook = config.discord.webhook; String webhook = config.discord.webhook;
if (webhook == null || webhook.isBlank()) return; if (webhook == null || webhook.isBlank())
return;
String addr = plr.getPlayerAddress() != null ? plr.getPlayerAddress().toString().substring(1) : "undefined"; CompletableFuture.runAsync(() -> {
String protocol = plr.isEaglerXRewindPlayer() String addr = (plr.getPlayerAddress() != null ? plr.getPlayerAddress().toString().substring(1) : "undefined:undefined").split(":")[0];
? (String.valueOf(plr.getRewindProtocolVersion()) != null ? String.valueOf(plr.getRewindProtocolVersion()) : "undefined") int protocol = !plr.isEaglerXRewindPlayer() ? plr.getMinecraftProtocol() : plr.getRewindProtocolVersion();
: (String.valueOf(plr.getMinecraftProtocol()) != null ? String.valueOf(plr.getMinecraftProtocol()) : "undefined"); String host = plr.getWebSocketHost();
String rewind = plr.isEaglerXRewindPlayer() ? "Yes" : "No"; String userAgent = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_USER_AGENT);
String host = plr.getWebSocketHost(); Boolean rewind = plr.isEaglerXRewindPlayer();
String userAgent = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_USER_AGENT); if (userAgent == null || userAgent.isEmpty())
if (userAgent == null || userAgent.isEmpty()) userAgent = "undefined"; userAgent = "undefined";
String payload = String.format(""" String payload = String.format(
{ """
"content": "Blocked a blacklisted %s from joining", {
"embeds": [ "content": "Blocked a blacklisted %s from joining",
{ "embeds": [
"title": "Player Information", {
"description": "🎮 **Name:** %s\\n🏠 **Address:** %s\\n🌄 **PVN:** %s\\n🌐 **Origin:** %s\\n🔋 **Brand:** %s\\n🪑 **Host:** %s\\n🧊 **User Agent:** %s\\n⏪ **Rewind:** %s" "title": "Player Information",
"description": "🎮 **Name:** %s\\n🏠 **IP:** %s\\n🌄 **PVN:** %s\\n🌐 **Origin:** %s\\n🔋 **Brand:** %s\\n🪑 **Host:** %s\\n🧊 **User Agent:** %s\\n⏪ **Rewind:** %s"
}
]
}
""",
type, plr.getUsername(), addr, protocol, origin, brand, plr.isWebSocketSecure() ? "wss://" : "ws://" + host, userAgent, rewind ? "Yes" : "No");
try {
HttpURLConnection conn = (HttpURLConnection) new URL(webhook).openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
try (OutputStream os = conn.getOutputStream()) {
os.write(payload.getBytes());
}
conn.getInputStream().close();
} catch (Exception e) {
getLogger().warn("Failed to send webhook: " + e);
} }
] });
}
""", type, plr.getAuthUsername(), addr, protocol, origin, brand, host, userAgent, rewind);
try {
HttpURLConnection conn = (HttpURLConnection) new URL(webhook).openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
try (OutputStream os = conn.getOutputStream()) {
os.write(payload.getBytes());
}
conn.getInputStream().close();
} catch (Exception e) {
getLogger().warn("Failed to send webhook: " + e);
}
} }
public static void init() { public static void init() {

View File

@ -3,47 +3,73 @@ package dev.colbster937.originblacklist.base;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.Constructor;
import java.io.File; import org.yaml.snakeyaml.DumperOptions;
import java.io.InputStream; import java.io.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.List; import java.util.List;
import java.util.Map;
public class ConfigManager { public class ConfigManager {
public Messages messages = new Messages(); public Messages messages = new Messages();
public List<String> subscriptions; public List<String> subscriptions = List.of();
public Blacklist blacklist = new Blacklist(); public Blacklist blacklist = new Blacklist();
public Discord discord = new Discord(); public Discord discord = new Discord();
public static ConfigManager loadConfig(Base.LoggerAdapter logger) { public static ConfigManager loadConfig(Base.LoggerAdapter logger) {
File conf = new File("plugins/originblacklist/config.yml"); File f = new File("plugins/originblacklist/config.yml");
try { try {
if (!conf.exists()) { if (!f.exists()) {
conf.getParentFile().mkdirs(); f.getParentFile().mkdirs();
try (InputStream in = ConfigManager.class.getResourceAsStream("/config.yml")) { try (InputStream in = ConfigManager.class.getResourceAsStream("/config.yml")) {
if (in != null) { if (in != null) Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING);
Files.copy(in, conf.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
} }
} }
LoaderOptions options = new LoaderOptions(); Yaml y = new Yaml(new Constructor(ConfigManager.class, new LoaderOptions()));
Constructor constructor = new Constructor(ConfigManager.class, options); ConfigManager l;
Yaml yaml = new Yaml(constructor); try (InputStream in = new FileInputStream(f)) { l = y.load(in); }
return yaml.load(new FileInputStream(conf));
if (l == null) l = new ConfigManager();
Yaml raw = new Yaml();
Map<String, Object> u = raw.load(new FileInputStream(f));
Map<String, Object> d = raw.load(ConfigManager.class.getResourceAsStream("/config.yml"));
if (mergeConfig(u, d)) saveConfig(u, f);
return l;
} catch (IOException e) { } catch (IOException e) {
return new ConfigManager(); return new ConfigManager();
} }
} }
@SuppressWarnings("unchecked")
private static boolean mergeConfig(Map<String, Object> u, Map<String, Object> d) {
boolean c = false;
for (String k : d.keySet()) {
if (!u.containsKey(k)) {
u.put(k, d.get(k));
c = true;
} else if (u.get(k) instanceof Map && d.get(k) instanceof Map)
c |= mergeConfig((Map<String, Object>) u.get(k), (Map<String, Object>) d.get(k));
}
return c;
}
private static void saveConfig(Map<String, Object> m, File f) throws IOException {
DumperOptions o = new DumperOptions();
o.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
o.setPrettyFlow(true);
new Yaml(o).dump(m, new FileWriter(f));
}
public static class Blacklist { public static class Blacklist {
public List<String> origins; public List<String> origins;
public List<String> brands; public List<String> brands;
public List<String> players; public List<String> players;
public boolean missing_origin; public boolean missing_origin;
public String blacklist_redirect;
} }
public static class Discord { public static class Discord {

View File

@ -2,7 +2,7 @@ package dev.colbster937.originblacklist.bukkit;
import dev.colbster937.originblacklist.base.Base; import dev.colbster937.originblacklist.base.Base;
import net.lax1dude.eaglercraft.backend.server.api.bukkit.EaglerXServerAPI; import net.lax1dude.eaglercraft.backend.server.api.bukkit.EaglerXServerAPI;
import net.lax1dude.eaglercraft.backend.server.api.bukkit.event.EaglercraftClientBrandEvent; import net.lax1dude.eaglercraft.backend.server.api.bukkit.event.EaglercraftLoginEvent;
import net.lax1dude.eaglercraft.backend.server.api.bukkit.event.EaglercraftMOTDEvent; import net.lax1dude.eaglercraft.backend.server.api.bukkit.event.EaglercraftMOTDEvent;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -42,7 +42,7 @@ public class OriginBlacklistBukkit extends JavaPlugin implements Listener {
} }
@EventHandler @EventHandler
public void onLogin(EaglercraftClientBrandEvent event) { public void onLogin(EaglercraftLoginEvent event) {
Base.handleConnection(event); Base.handleConnection(event);
} }

View File

@ -2,7 +2,7 @@ package dev.colbster937.originblacklist.bungee;
import dev.colbster937.originblacklist.base.Base; import dev.colbster937.originblacklist.base.Base;
import net.lax1dude.eaglercraft.backend.server.api.bungee.EaglerXServerAPI; import net.lax1dude.eaglercraft.backend.server.api.bungee.EaglerXServerAPI;
import net.lax1dude.eaglercraft.backend.server.api.bungee.event.EaglercraftClientBrandEvent; import net.lax1dude.eaglercraft.backend.server.api.bungee.event.EaglercraftLoginEvent;
import net.lax1dude.eaglercraft.backend.server.api.bungee.event.EaglercraftMOTDEvent; import net.lax1dude.eaglercraft.backend.server.api.bungee.event.EaglercraftMOTDEvent;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Listener;
@ -41,7 +41,7 @@ public class OriginBlacklistBungee extends Plugin implements Listener {
} }
@EventHandler @EventHandler
public void onLogin(EaglercraftClientBrandEvent event) { public void onLogin(EaglercraftLoginEvent event) {
Base.handleConnection(event); Base.handleConnection(event);
} }

View File

@ -6,7 +6,7 @@ import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import dev.colbster937.originblacklist.base.Base; import dev.colbster937.originblacklist.base.Base;
import net.lax1dude.eaglercraft.backend.server.api.velocity.EaglerXServerAPI; import net.lax1dude.eaglercraft.backend.server.api.velocity.EaglerXServerAPI;
import net.lax1dude.eaglercraft.backend.server.api.velocity.event.EaglercraftClientBrandEvent; import net.lax1dude.eaglercraft.backend.server.api.velocity.event.EaglercraftLoginEvent;
import net.lax1dude.eaglercraft.backend.server.api.velocity.event.EaglercraftMOTDEvent; import net.lax1dude.eaglercraft.backend.server.api.velocity.event.EaglercraftMOTDEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -44,7 +44,7 @@ public class OriginBlacklistVelocity {
} }
@Subscribe @Subscribe
public void onLogin(EaglercraftClientBrandEvent event) { public void onLogin(EaglercraftLoginEvent event) {
Base.handleConnection(event); Base.handleConnection(event);
} }

View File

@ -28,6 +28,7 @@ blacklist:
- "*dragonx*" - "*dragonx*"
- "*piclient*" - "*piclient*"
missing_origin: false missing_origin: false
blacklist_redirect: ""
discord: discord:
webhook: "" webhook: ""
@ -63,7 +64,6 @@ discord:
# :> # :>