commit fdf4847239826a7db8bfb4413c4a84f11c7189b3 Author: Colbster937 <96893162+colbychittenden@users.noreply.github.com> Date: Tue May 6 22:12:35 2025 -0500 cool diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa5793c --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +**/.DS_Store +.idea +.gradle +build +run +gradlew +gradlew.bat \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d482378 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# OriginBlacklist + +basically just a reimplementation of originblacklist but for eaglerxserver + +> [!WARNING] +> **Velocity is the main platform I'm developing this for, bungee & bukkit will still work but will probably have some bugs and will receive less support!** + +### Download +**[https://github.com/colbster937/originblacklist/releases](https://github.com/colbster937/originblacklist/releases)** + +### Building +``` +$ gradle wrapper +$ ./gradle. shadowJar +``` \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..7b096dd --- /dev/null +++ b/build.gradle @@ -0,0 +1,93 @@ +plugins { + id 'java' + id 'eclipse' + id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.8' + id 'com.github.johnrengelman.shadow' version '8.1.1' + id("xyz.jpenilla.run-velocity") version "2.3.1" +} + + +group = 'dev.colbster937' +version = '1.0.0' + +repositories { + mavenCentral() + maven { + name = "papermc-repo" + url = "https://repo.papermc.io/repository/maven-public/" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/groups/public/" + } + maven { + name = "spigotmc-repo" + url = "https://hub.spigotmc.org/nexus/content/repositories/public/" + } + maven { + name = "md_5" + url = "https://repo.md-5.net/content/repositories/releases/" + } + maven { + name = "aikar" + url = "https://repo.aikar.co/nexus/content/groups/aikar/" + } + maven { + name = "lax1dude" + url = "https://repo.lax1dude.net/repository/releases/" + } +} + +dependencies { + compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") + annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") + compileOnly("org.bukkit:bukkit:1.8-R0.1-SNAPSHOT") + compileOnly("net.md-5:bungeecord-api:1.8-SNAPSHOT") + compileOnly("net.lax1dude.eaglercraft.backend:api-velocity:1.0.0") + compileOnly("net.lax1dude.eaglercraft.backend:api-bungee:1.0.0") + compileOnly("net.lax1dude.eaglercraft.backend:api-bukkit:1.0.0") + implementation("org.yaml:snakeyaml:2.2") + implementation("net.kyori:adventure-api:4.20.0") + implementation("net.kyori:adventure-text-serializer-legacy:4.20.0") + implementation("net.kyori:adventure-text-minimessage:4.20.0") +} + +tasks { + runVelocity { + // Configure the Velocity version for our task. + // This is the only required configuration besides applying the plugin. + // Your plugin's jar (or shadowJar if present) will be used automatically. + velocityVersion("3.3.0-SNAPSHOT") + } +} + +def targetJavaVersion = 17 +java { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) +} + +shadowJar { + relocate 'org.yaml.snakeyaml', 'dev.colbster937.shaded.snakeyaml' + archiveClassifier.set('all') +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' + options.release.set(targetJavaVersion) +} + +/*def templateSource = file('src/main/templates') +def templateDest = layout.buildDirectory.dir('generated/sources/templates') +def generateTemplates = tasks.register('generateTemplates', Copy) { task -> + def props = ['version': project.version] + task.inputs.properties props + + task.from templateSource + task.into templateDest + task.expand props +} + +sourceSets.main.java.srcDir(generateTemplates.map { it.outputs }) + +project.idea.project.settings.taskTriggers.afterSync generateTemplates +project.eclipse.synchronizationTasks(generateTemplates)*/ diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e644113 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a441313 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..6d9264f --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'OriginBlacklist' diff --git a/src/main/java/dev/colbster937/originblacklist/base/Base.java b/src/main/java/dev/colbster937/originblacklist/base/Base.java new file mode 100644 index 0000000..d248bad --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/base/Base.java @@ -0,0 +1,125 @@ +package dev.colbster937.originblacklist.base; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.lax1dude.eaglercraft.backend.server.api.IEaglerXServerAPI; +import net.lax1dude.eaglercraft.backend.server.api.IEaglerPlayer; +import net.lax1dude.eaglercraft.backend.server.api.EnumWebSocketHeader; +import net.lax1dude.eaglercraft.backend.server.api.event.IEaglercraftInitializePlayerEvent; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Base { + private static LoggerAdapter adapter; + private static IEaglerXServerAPI api; + private static ConfigManager config; + + public static void setLogger(LoggerAdapter log) { + adapter = log; + } + + public static void setApi(IEaglerXServerAPI api1) { + api = api1; + } + + public static LoggerAdapter getLogger() { + if (adapter == null) throw new IllegalStateException("Logger not initialized!"); + return adapter; + } + + public interface LoggerAdapter { + void info(String msg); + void warn(String msg); + void error(String msg); + } + + public static void handleConnection(IEaglercraftInitializePlayerEvent e) { + IEaglerPlayer plr = e.getPlayer(); + String origin = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_ORIGIN); + String brand = plr.getEaglerBrandString(); + if ((origin != "null" || origin != null) && !config.blacklist.missing_origin) { + for (String origin1 : config.blacklist.origins) { + if (matches(origin, origin1)) { + plr.disconnect(kick("origin", "website", origin)); + webhook(plr, origin, brand, "origin"); + return; + } + } + } else { + plr.disconnect(kick("origin", "website", origin)); + webhook(plr, "null", brand, "origin"); + } + if (brand != "null" && brand != null) { + for (String brand1 : config.blacklist.brands) { + if (matches(brand, brand1)) { + plr.disconnect(kick("brand", "client", brand)); + webhook(plr, origin, brand, "brand"); + return; + } + } + } + } + + public static boolean matches(String text1, String text2) { + return text1.toLowerCase().matches(text2.replace(".", "\\.").replaceAll("\\*", ".*").toLowerCase()); + } + + public static String kick(String type, String easytype, String value) { + return LegacyComponentSerializer.legacySection().serialize( + MiniMessage.miniMessage().deserialize( + config.messages.kick + .replace("%blocktype%", type) + .replace("%easyblocktype%", easytype) + .replace("%blocked%", value) + ) + ); + } + + + public static void webhook(IEaglerPlayer plr, String origin, String brand, String type) { + String webhook = config.discord.webhook; + if (webhook == null || webhook.isBlank()) return; + + String addr = plr.getPlayerAddress() != null ? plr.getPlayerAddress().toString().substring(1) : "undefined"; + String protocol = plr.isEaglerXRewindPlayer() + ? (String.valueOf(plr.getRewindProtocolVersion()) != null ? String.valueOf(plr.getRewindProtocolVersion()) : "undefined") + : (String.valueOf(plr.getMinecraftProtocol()) != null ? String.valueOf(plr.getMinecraftProtocol()) : "undefined"); + String rewind = plr.isEaglerXRewindPlayer() ? "Yes" : "No"; + String userAgent = plr.getWebSocketHeader(EnumWebSocketHeader.HEADER_USER_AGENT); + if (userAgent == null || userAgent.isEmpty()) userAgent = "undefined"; + + String payload = String.format(""" + { + "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๐ŸงŠ **User Agent:** %s\\nโช **Rewind:** %s" + } + ] + } + """, type, plr.getUsername(), addr, protocol, origin, brand, 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 reloadConfig() { + config = ConfigManager.loadConfig(adapter); + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/base/Command.java b/src/main/java/dev/colbster937/originblacklist/base/Command.java new file mode 100644 index 0000000..9c0e020 --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/base/Command.java @@ -0,0 +1,39 @@ +package dev.colbster937.originblacklist.base; + +public class Command { + + public interface CommandContext { + String getName(); + void reply(String message); + boolean hasPermission(String permission); + String[] getArgs(); + } + + + public static void usage(CommandContext ctx) { + ctx.reply("Commands:"); + ctx.reply(" - /originblacklist reload"); + } + + public static void handle(CommandContext ctx) { + String[] args = ctx.getArgs(); + if (!ctx.hasPermission("originblacklist.reload")) { + ctx.reply("You do not have permission to use this command."); + return; + } else if (args.length == 0) { + usage(ctx); + return; + } + + String sub = args[0].toLowerCase(); + + switch (sub) { + case "reload" -> { + Base.reloadConfig(); + ctx.reply("Reloaded."); + } + + default -> usage(ctx); + } + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/base/ConfigManager.java b/src/main/java/dev/colbster937/originblacklist/base/ConfigManager.java new file mode 100644 index 0000000..007101c --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/base/ConfigManager.java @@ -0,0 +1,58 @@ +package dev.colbster937.originblacklist.base; + +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.constructor.Constructor; +import java.io.File; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.List; + +public class ConfigManager { + public Messages messages = new Messages(); + public List subscriptions; + public Blacklist blacklist = new Blacklist(); + public Discord discord = new Discord(); + + public static ConfigManager loadConfig(Base.LoggerAdapter logger) { + File conf = new File("plugins/originblacklist/config.yml"); + + try { + if (!conf.exists()) { + conf.getParentFile().mkdirs(); + try (InputStream in = ConfigManager.class.getResourceAsStream("/config.yml")) { + if (in != null) { + Files.copy(in, conf.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } + } + + LoaderOptions options = new LoaderOptions(); + Constructor constructor = new Constructor(ConfigManager.class, options); + Yaml yaml = new Yaml(constructor); + return yaml.load(new FileInputStream(conf)); + } catch (IOException e) { + return new ConfigManager(); + } + } + + public static class Blacklist { + public List origins; + public List brands; + public List players; + public boolean missing_origin; + + public Blacklist() {} + } + + public static class Discord { + public String webhook; + } + + public static class Messages { + public String kick; + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/bukkit/CommandBukkit.java b/src/main/java/dev/colbster937/originblacklist/bukkit/CommandBukkit.java new file mode 100644 index 0000000..1d874f3 --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/bukkit/CommandBukkit.java @@ -0,0 +1,24 @@ +package dev.colbster937.originblacklist.bukkit; + +import dev.colbster937.originblacklist.base.Command; +import dev.colbster937.originblacklist.base.Command.CommandContext; +import org.bukkit.command.CommandSender; +import org.bukkit.command.CommandExecutor; + +public class CommandBukkit implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { + Command.handle(new CommandContext() { + public String getName() { return sender.getName(); } + public void reply(String msg) { sender.sendMessage(msg); } + public boolean hasPermission(String permission) { + return sender.hasPermission(permission); + } + public String[] getArgs() { + return args; + } + }); + return true; + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/bukkit/OriginBlacklistBukkit.java b/src/main/java/dev/colbster937/originblacklist/bukkit/OriginBlacklistBukkit.java new file mode 100644 index 0000000..c02b177 --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/bukkit/OriginBlacklistBukkit.java @@ -0,0 +1,33 @@ +package dev.colbster937.originblacklist.bukkit; + +import dev.colbster937.originblacklist.base.Base; +import net.lax1dude.eaglercraft.backend.server.api.bukkit.EaglerXServerAPI; +import net.lax1dude.eaglercraft.backend.server.api.bukkit.event.EaglercraftInitializePlayerEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +public class OriginBlacklistBukkit extends JavaPlugin implements Listener { + + @Override + public void onEnable() { + Base.setLogger(new Base.LoggerAdapter() { + @Override public void info(String msg) { getLogger().info(msg); } + @Override public void warn(String msg) { getLogger().warning(msg); } + @Override public void error(String msg) { getLogger().severe(msg); } + }); + + Base.setApi(EaglerXServerAPI.instance()); + Base.reloadConfig(); + + getCommand("originblacklist").setExecutor(new CommandBukkit()); + getServer().getPluginManager().registerEvents(this, this); + + getLogger().info("Loaded Bukkit plugin"); + } + + @EventHandler + public void onLogin(EaglercraftInitializePlayerEvent event) { + Base.handleConnection(event); + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/bungee/CommandBungee.java b/src/main/java/dev/colbster937/originblacklist/bungee/CommandBungee.java new file mode 100644 index 0000000..d3432d3 --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/bungee/CommandBungee.java @@ -0,0 +1,26 @@ +package dev.colbster937.originblacklist.bungee; + +import dev.colbster937.originblacklist.base.Command; +import dev.colbster937.originblacklist.base.Command.CommandContext; +import net.md_5.bungee.api.CommandSender; + +public class CommandBungee extends net.md_5.bungee.api.plugin.Command { + + public CommandBungee() { + super("originblacklist", "originblacklist.use"); + } + + @Override + public void execute(CommandSender sender, String[] args) { + Command.handle(new CommandContext() { + public String getName() { return sender.getName(); } + public void reply(String msg) { sender.sendMessage(msg); } + public boolean hasPermission(String permission) { + return sender.hasPermission(permission); + } + public String[] getArgs() { + return args; + } + }); + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/bungee/OriginBlacklistBungee.java b/src/main/java/dev/colbster937/originblacklist/bungee/OriginBlacklistBungee.java new file mode 100644 index 0000000..9fb9735 --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/bungee/OriginBlacklistBungee.java @@ -0,0 +1,33 @@ +package dev.colbster937.originblacklist.bungee; + +import dev.colbster937.originblacklist.base.Base; +import net.lax1dude.eaglercraft.backend.server.api.bungee.EaglerXServerAPI; +import net.lax1dude.eaglercraft.backend.server.api.bungee.event.EaglercraftInitializePlayerEvent; +import net.md_5.bungee.api.plugin.Plugin; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; + +public class OriginBlacklistBungee extends Plugin implements Listener { + + @Override + public void onEnable() { + Base.setLogger(new Base.LoggerAdapter() { + @Override public void info(String msg) { getLogger().info(msg); } + @Override public void warn(String msg) { getLogger().warning(msg); } + @Override public void error(String msg) { getLogger().severe(msg); } + }); + + Base.setApi(EaglerXServerAPI.instance()); + Base.reloadConfig(); + + getProxy().getPluginManager().registerCommand(this, new CommandBungee()); + getProxy().getPluginManager().registerListener(this, this); + + getLogger().info("Loaded Bungee plugin"); + } + + @EventHandler + public void onLogin(EaglercraftInitializePlayerEvent event) { + Base.handleConnection(event); + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/velocity/CommandVelocity.java b/src/main/java/dev/colbster937/originblacklist/velocity/CommandVelocity.java new file mode 100644 index 0000000..f60562a --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/velocity/CommandVelocity.java @@ -0,0 +1,34 @@ +package dev.colbster937.originblacklist.velocity; + +import com.velocitypowered.api.command.SimpleCommand; +import dev.colbster937.originblacklist.base.Command.CommandContext; +import net.kyori.adventure.text.minimessage.MiniMessage; +import com.velocitypowered.api.command.CommandSource; + +public class CommandVelocity implements SimpleCommand { + + @Override + public void execute(Invocation invocation) { + CommandSource source = invocation.source(); + dev.colbster937.originblacklist.base.Command.handle(new CommandContext() { + @Override + public String getName() { + return source.toString(); + } + + @Override + public void reply(String msg) { + source.sendMessage(MiniMessage.miniMessage().deserialize(msg)); + } + + @Override + public boolean hasPermission(String permission) { + return source.hasPermission(permission); + } + + public String[] getArgs() { + return invocation.arguments(); + } + }); + } +} diff --git a/src/main/java/dev/colbster937/originblacklist/velocity/OriginBlacklistVelocity.java b/src/main/java/dev/colbster937/originblacklist/velocity/OriginBlacklistVelocity.java new file mode 100644 index 0000000..4e19d5b --- /dev/null +++ b/src/main/java/dev/colbster937/originblacklist/velocity/OriginBlacklistVelocity.java @@ -0,0 +1,50 @@ +package dev.colbster937.originblacklist.velocity; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.plugin.Dependency; +import com.velocitypowered.api.proxy.ProxyServer; +import dev.colbster937.originblacklist.base.Base; +import net.lax1dude.eaglercraft.backend.server.api.velocity.EaglerXServerAPI; +import net.lax1dude.eaglercraft.backend.server.api.velocity.event.EaglercraftInitializePlayerEvent; +import org.slf4j.Logger; + +@Plugin( + id = "originblacklist", + name = "OriginBlacklist", + version = "1.0.0", + authors = {"Colbster937"}, + description = "A reimplementation of OriginBlacklist for EaglerXServer", + dependencies = {@Dependency(id = "eaglerxserver")} +) +public class OriginBlacklistVelocity { + + private final ProxyServer proxy; + private final Base.LoggerAdapter logger; + + @Inject + public OriginBlacklistVelocity(ProxyServer proxy1, Logger logger1) { + this.proxy = proxy1; + this.logger = new Base.LoggerAdapter() { + @Override public void info(String msg) { logger1.info(msg); } + @Override public void warn(String msg) { logger1.warn(msg); } + @Override public void error(String msg) { logger1.error(msg); } + }; + Base.setLogger(this.logger); + } + + @Subscribe + public void onProxyInitialization(ProxyInitializeEvent event) { + Base.setApi(EaglerXServerAPI.instance()); + Base.reloadConfig(); + proxy.getCommandManager().register("originblacklist", new CommandVelocity()); + logger.info("Loaded Velocity plugin"); + } + + @Subscribe + public void onLogin(EaglercraftInitializePlayerEvent event) { + Base.handleConnection(event); + } +} diff --git a/src/main/resources/bungee.yml b/src/main/resources/bungee.yml new file mode 100644 index 0000000..0c9a60d --- /dev/null +++ b/src/main/resources/bungee.yml @@ -0,0 +1,7 @@ +name: OriginBlacklist +version: 1.0.0 +main: dev.colbster937.originblacklist.bungee.OriginBlacklistBungee +description: A reimplementation of OriginBlacklist for EaglerXServer +author: Colbster937 +depends: + - EaglercraftXServer \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..c6c7e56 --- /dev/null +++ b/src/main/resources/config.yml @@ -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 + + kick: | + This %easyblocktype% is not allowed on the server! + ยป %blocked% ยซ + + Think this is a mistake? Join our discord: + discord.gg/changethisintheconfig + +# Origin + Brand blacklist supports wildcards +# Everything should be lowercase +blacklist: + origins: + - "hack.example.com" + brands: + - "*dragonx*" + - "*piclient*" + missing_origin: false + +discord: + webhook: "" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# :> \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..953a8b8 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: OriginBlacklist +version: 1.0.0 +main: dev.colbster937.originblacklist.bukkit.OriginBlacklistBukkit +description: A reimplementation of OriginBlacklist for EaglerXServer +author: Colbster937 +depend: + - EaglercraftXServer +commands: + originblacklist: \ No newline at end of file