diff --git a/blcmodapibukkit-1.17/pom.xml b/blcmodapibukkit-1.17/pom.xml
new file mode 100644
index 0000000..f203977
--- /dev/null
+++ b/blcmodapibukkit-1.17/pom.xml
@@ -0,0 +1,81 @@
+
+
+
+ badlionclientmodapi
+ net.badlion
+ 1.2.3
+
+ 4.0.0
+
+ blcmodapibukkit-1.17
+
+
+ UTF-8
+
+
+
+ clean install
+ badlionclientmodapibukkit-1.17
+ src/main/java
+
+
+ .
+ true
+ src/main/resources/
+
+ *.yml
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.7
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.17-R0.1-SNAPSHOT
+ provided
+
+
+ com.google.code.gson
+ gson
+ 2.6.2
+ compile
+
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+
+
\ No newline at end of file
diff --git a/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java
new file mode 100644
index 0000000..ab3b7f2
--- /dev/null
+++ b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java
@@ -0,0 +1,76 @@
+package net.badlion.blcmodapibukkit;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import net.badlion.blcmodapibukkit.listener.PlayerListener;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.logging.Level;
+
+public class BlcModApiBukkit extends JavaPlugin {
+
+ public static final Gson GSON_NON_PRETTY = new GsonBuilder().enableComplexMapKeySerialization().disableHtmlEscaping().create();
+ public static final Gson GSON_PRETTY = new GsonBuilder().enableComplexMapKeySerialization().disableHtmlEscaping().setPrettyPrinting().create();
+
+ private Conf conf;
+
+ @Override
+ public void onEnable() {
+ if (!this.getDataFolder().exists()) {
+ if (!this.getDataFolder().mkdir()) {
+ this.getLogger().log(Level.SEVERE, "Failed to create plugin directory.");
+ }
+ }
+
+ try {
+ this.conf = this.loadConf(new File(this.getDataFolder(), "config.json"));
+
+ // Register channel
+ this.getServer().getMessenger().registerOutgoingPluginChannel(this, "badlion:mods");
+
+ // Only register the listener if the config loads successfully
+ this.getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
+
+ this.getLogger().log(Level.INFO, "Successfully setup BadlionClientModAPI plugin.");
+ } catch (IOException e) {
+ this.getLogger().log(Level.SEVERE, "Error with config for BadlionClientModAPI plugin.");
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onDisable() {
+
+ }
+
+ public Conf loadConf(File file) throws IOException {
+ try (Reader reader = new FileReader(file)) {
+ return BlcModApiBukkit.GSON_NON_PRETTY.fromJson(reader, Conf.class);
+
+ } catch (FileNotFoundException ex) {
+ this.getLogger().log(Level.INFO, "No Config Found: Saving default...");
+ Conf conf = new Conf();
+ this.saveConf(conf, new File(this.getDataFolder(), "config.json"));
+ return conf;
+ }
+ }
+
+ private void saveConf(Conf conf, File file) {
+ try (FileWriter writer = new FileWriter(file)) {
+ BlcModApiBukkit.GSON_PRETTY.toJson(conf, writer);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public Conf getConf() {
+ return this.conf;
+ }
+}
diff --git a/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/Conf.java b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/Conf.java
new file mode 100644
index 0000000..832f167
--- /dev/null
+++ b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/Conf.java
@@ -0,0 +1,20 @@
+package net.badlion.blcmodapibukkit;
+
+import com.google.gson.JsonObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Conf {
+ private Map modsDisallowed = new HashMap();
+
+ public Map getModsDisallowed() {
+ return this.modsDisallowed;
+ }
+
+ private static class DisallowedMods {
+ private boolean disabled;
+ private JsonObject extra_data;
+ private JsonObject settings;
+ }
+}
diff --git a/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/listener/PlayerListener.java b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/listener/PlayerListener.java
new file mode 100644
index 0000000..0b3ecff
--- /dev/null
+++ b/blcmodapibukkit-1.17/src/main/java/net/badlion/blcmodapibukkit/listener/PlayerListener.java
@@ -0,0 +1,222 @@
+package net.badlion.blcmodapibukkit.listener;
+
+import net.badlion.blcmodapibukkit.BlcModApiBukkit;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+public class PlayerListener implements Listener {
+ private final BlcModApiBukkit plugin;
+ private String versionSuffix;
+
+ private final Method getHandleMethod;
+
+ private final Field playerConnectionField;
+
+ private final Method sendPacketMethod;
+
+ private Constructor> packetPlayOutCustomPayloadConstructor;
+ private Constructor> packetPlayOutMinecraftKeyConstructor;
+ private boolean useMinecraftKey;
+
+ // Bukkit 1.8+ support
+ private Class> packetDataSerializerClass;
+ private Constructor> packetDataSerializerConstructor;
+
+ private Method wrappedBufferMethod;
+
+ public PlayerListener(BlcModApiBukkit plugin) {
+ this.plugin = plugin;
+
+ // Get the v1_X_Y from the end of the package name, e.g. v_1_7_R4 or v_1_12_R1
+ String packageName = Bukkit.getServer().getClass().getPackage().getName();
+ String[] parts = packageName.split("\\.");
+
+ if (parts.length > 0) {
+ String suffix = parts[parts.length - 1];
+ if (!suffix.startsWith("v")) {
+ throw new RuntimeException("Failed to find version for running Minecraft server, got suffix " + suffix);
+ }
+
+ this.versionSuffix = suffix;
+
+ this.plugin.getLogger().info("Found version " + this.versionSuffix);
+ }
+
+ // We need to use reflection because Bukkit by default handles plugin messages in a really silly way
+ // Reflection stuff
+ Class> craftPlayerClass = this.getClass("org.bukkit.craftbukkit." + this.versionSuffix + ".entity.CraftPlayer");
+ if (craftPlayerClass == null) {
+ throw new RuntimeException("Failed to find CraftPlayer class");
+ }
+
+ Class> nmsPlayerClass = this.getClass("net.minecraft.server.level.EntityPlayer");
+ if (nmsPlayerClass == null) {
+ throw new RuntimeException("Failed to find EntityPlayer class");
+ }
+
+ Class> playerConnectionClass = this.getClass("net.minecraft.server.network.PlayerConnection");
+ if (playerConnectionClass == null) {
+ throw new RuntimeException("Failed to find PlayerConnection class");
+ }
+
+ Class> packetPlayOutCustomPayloadClass = this.getClass("net.minecraft.network.protocol.game.PacketPlayOutCustomPayload");
+ if (packetPlayOutCustomPayloadClass == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload class");
+ }
+
+ this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, String.class, byte[].class);
+ if (this.packetPlayOutCustomPayloadConstructor == null) {
+ // Newer versions of Minecraft use a different custom packet system
+ this.packetDataSerializerClass = this.getClass("net.minecraft.network.PacketDataSerializer");
+ if (this.packetDataSerializerClass == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor or PacketDataSerializer class");
+ }
+
+ // Netty classes used by newer 1.8 and newer
+ Class> byteBufClass = this.getClass("io.netty.buffer.ByteBuf");
+ if (byteBufClass == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor or ByteBuf class");
+ }
+
+ this.packetDataSerializerConstructor = this.getConstructor(this.packetDataSerializerClass, byteBufClass);
+ if (this.packetDataSerializerConstructor == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor or PacketDataSerializer constructor");
+ }
+
+ Class> unpooledClass = this.getClass("io.netty.buffer.Unpooled");
+ if (unpooledClass == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor or Unpooled class");
+ }
+
+ this.wrappedBufferMethod = this.getMethod(unpooledClass, "wrappedBuffer", byte[].class);
+ if (this.wrappedBufferMethod == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor or wrappedBuffer()");
+ }
+
+ // If we made it this far in theory we are on at least 1.8
+ this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, String.class, this.packetDataSerializerClass);
+ if (this.packetPlayOutCustomPayloadConstructor == null) {
+ Class> minecraftKeyClass = this.getClass("net.minecraft.resources.MinecraftKey");
+
+ // Fix for Paper in newer versions
+ this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, minecraftKeyClass, this.packetDataSerializerClass);
+
+ if (this.packetPlayOutCustomPayloadConstructor == null) {
+ throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor 2x");
+ } else {
+ this.useMinecraftKey = true;
+ this.packetPlayOutMinecraftKeyConstructor = this.getConstructor(minecraftKeyClass, String.class);
+ }
+ }
+ }
+
+ this.getHandleMethod = this.getMethod(craftPlayerClass, "getHandle");
+ if (this.getHandleMethod == null) {
+ throw new RuntimeException("Failed to find CraftPlayer.getHandle()");
+ }
+
+ this.playerConnectionField = this.getField(nmsPlayerClass, "b");
+ if (this.playerConnectionField == null) {
+ throw new RuntimeException("Failed to find EntityPlayer.playerConnection");
+ }
+
+ this.sendPacketMethod = this.getMethod(playerConnectionClass, "sendPacket");
+ if (this.sendPacketMethod == null) {
+ throw new RuntimeException("Failed to find PlayerConnection.sendPacket()");
+ }
+ }
+
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ Player player = event.getPlayer();
+
+ // Create data we need for packet;
+ String channel = "badlion:mods";
+ Object message = BlcModApiBukkit.GSON_NON_PRETTY.toJson(this.plugin.getConf().getModsDisallowed()).getBytes();
+
+ try {
+ Object packet;
+ // Newer MC version, setup ByteBuf object
+ if (this.packetDataSerializerClass != null) {
+ Object byteBuf = this.wrappedBufferMethod.invoke(null, message);
+ Object packetDataSerializer = this.packetDataSerializerConstructor.newInstance(byteBuf);
+
+ if (this.useMinecraftKey) {
+ Object key = this.packetPlayOutMinecraftKeyConstructor.newInstance(channel);
+ packet = this.packetPlayOutCustomPayloadConstructor.newInstance(key, packetDataSerializer);
+ } else {
+ packet = this.packetPlayOutCustomPayloadConstructor.newInstance(channel, packetDataSerializer);
+ }
+ } else {
+ // Work our magic to make the packet
+ packet = this.packetPlayOutCustomPayloadConstructor.newInstance(channel, message);
+ }
+
+ // Work our magic to send the packet
+ Object nmsPlayer = this.getHandleMethod.invoke(player);
+ Object playerConnection = this.playerConnectionField.get(nmsPlayer);
+ this.sendPacketMethod.invoke(playerConnection, packet);
+ } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
+ this.plugin.getLogger().severe("Failed to send BLC mod packet");
+ e.printStackTrace();
+ }
+ }
+
+ public Class> getClass(String className) {
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ public Constructor> getConstructor(Class> clazz, Class>... params) {
+ for (final Constructor> constructor : clazz.getDeclaredConstructors()) {
+ if (Arrays.equals(constructor.getParameterTypes(), params)) {
+ constructor.setAccessible(true);
+ return constructor;
+ }
+ }
+
+ return null;
+ }
+
+ public Method getMethod(Class> clazz, String methodName, Class>... params) {
+ for (final Method method : clazz.getDeclaredMethods()) {
+ if (method.getName().equals(methodName)) {
+ if (params.length > 0) {
+ if (Arrays.equals(method.getParameterTypes(), params)) {
+ method.setAccessible(true);
+ return method;
+ }
+ } else {
+ method.setAccessible(true);
+ return method;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public Field getField(Class> clazz, String fieldName) {
+ for (final Field field : clazz.getDeclaredFields()) {
+ if (field.getName().equals(fieldName)) {
+ field.setAccessible(true);
+ return field;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/blcmodapibukkit-1.17/src/main/resources/plugin.yml b/blcmodapibukkit-1.17/src/main/resources/plugin.yml
new file mode 100644
index 0000000..c5bfea7
--- /dev/null
+++ b/blcmodapibukkit-1.17/src/main/resources/plugin.yml
@@ -0,0 +1,5 @@
+name: BadlionClientModAPI
+main: net.badlion.blcmodapibukkit.BlcModApiBukkit
+version: 1.0
+author: Badlion
+api-version: 1.17
\ No newline at end of file
diff --git a/blcmodapibukkit/pom.xml b/blcmodapibukkit/pom.xml
index b0db901..ad2ba59 100644
--- a/blcmodapibukkit/pom.xml
+++ b/blcmodapibukkit/pom.xml
@@ -5,7 +5,7 @@
badlionclientmodapi
net.badlion
- 1.2.2
+ 1.2.3
4.0.0
@@ -35,8 +35,8 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 1.6
+
+ 1.7
diff --git a/blcmodapibukkit/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java b/blcmodapibukkit/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java
index c2e7102..1c69041 100644
--- a/blcmodapibukkit/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java
+++ b/blcmodapibukkit/src/main/java/net/badlion/blcmodapibukkit/BlcModApiBukkit.java
@@ -5,7 +5,6 @@
import net.badlion.blcmodapibukkit.listener.PlayerListener;
import org.bukkit.plugin.java.JavaPlugin;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -31,7 +30,7 @@ public void onEnable() {
}
try {
- this.conf = loadConf(new File(this.getDataFolder(), "config.json"));
+ this.conf = this.loadConf(new File(this.getDataFolder(), "config.json"));
// Register channel
this.getServer().getMessenger().registerOutgoingPluginChannel(this, "badlion:mods");
@@ -52,9 +51,9 @@ public void onDisable() {
}
public Conf loadConf(File file) throws IOException {
- try {
- Reader reader = new BufferedReader(new FileReader(file));
+ try (Reader reader = new FileReader(file)) {
return BlcModApiBukkit.GSON_NON_PRETTY.fromJson(reader, Conf.class);
+
} catch (FileNotFoundException ex) {
this.getLogger().log(Level.INFO,"No Config Found: Saving default...");
Conf conf = new Conf();
@@ -64,9 +63,9 @@ public Conf loadConf(File file) throws IOException {
}
private void saveConf(Conf conf, File file) {
- try {
- FileWriter writer = new FileWriter(file);
+ try (FileWriter writer = new FileWriter(file)) {
BlcModApiBukkit.GSON_PRETTY.toJson(conf, writer);
+
} catch (Exception ex) {
ex.printStackTrace();
}
diff --git a/blcmodapibungee/pom.xml b/blcmodapibungee/pom.xml
index 7f247da..abe916b 100644
--- a/blcmodapibungee/pom.xml
+++ b/blcmodapibungee/pom.xml
@@ -5,7 +5,7 @@
badlionclientmodapi
net.badlion
- 1.2.2
+ 1.2.3
4.0.0
diff --git a/blcmodapibungee/src/main/java/net/badlion/blcmodapibungee/BlcModApiBungee.java b/blcmodapibungee/src/main/java/net/badlion/blcmodapibungee/BlcModApiBungee.java
index 711a71c..be06ee9 100644
--- a/blcmodapibungee/src/main/java/net/badlion/blcmodapibungee/BlcModApiBungee.java
+++ b/blcmodapibungee/src/main/java/net/badlion/blcmodapibungee/BlcModApiBungee.java
@@ -5,7 +5,6 @@
import net.badlion.blcmodapibungee.listener.PlayerListener;
import net.md_5.bungee.api.plugin.Plugin;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -48,8 +47,9 @@ public void onDisable() {
}
public Conf loadConf(File file) throws IOException {
- try (Reader reader = new BufferedReader(new FileReader(file))) {
+ try (Reader reader = new FileReader(file)) {
return BlcModApiBungee.GSON_NON_PRETTY.fromJson(reader, Conf.class);
+
} catch (FileNotFoundException ex) {
this.getLogger().log(Level.INFO,"No Config Found: Saving default...");
Conf conf = new Conf();
@@ -61,6 +61,7 @@ public Conf loadConf(File file) throws IOException {
private void saveConf(Conf conf, File file) {
try (FileWriter writer = new FileWriter(file)) {
BlcModApiBungee.GSON_PRETTY.toJson(conf, writer);
+
} catch (Exception ex) {
ex.printStackTrace();
}
diff --git a/pom.xml b/pom.xml
index 2e6e6a5..b88a14f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,10 +7,11 @@
net.badlion
badlionclientmodapi
pom
- 1.2.2
+ 1.2.3
blcmodapibungee
blcmodapibukkit
+ blcmodapibukkit-1.17