Skip to content

Commit

Permalink
Reworked mod blocking to allow total customization of mod list, based…
Browse files Browse the repository at this point in the history
… on #800
  • Loading branch information
FabioZumbi12 committed Jun 25, 2024
1 parent 029824d commit 266a34a
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 177 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2024 - @FabioZumbi12
* Last Modified: 24/06/2024 18:40
* Last Modified: 24/06/2024 22:56
*
* This class is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any
* damages arising from the use of this class.
Expand All @@ -26,9 +26,12 @@

package br.net.fabiozumbi12.RedProtect.Core.config.Category;

import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;

import java.nio.charset.StandardCharsets;
import java.util.*;

@ConfigSerializable
Expand Down Expand Up @@ -450,7 +453,8 @@ public static class serverProtection {
@Setting(value = "mods-permissions", comment = """
Deny players to join with one of this mods or use in your server.
The permission 'redprotect.mods.<mod-name>.bypass' bypass this configurations.
Some mods like World Downloader and Schematica have your actions blocked, others only execute the command.""")
Byte configuration may be hard to know and is represented as String, but instead to do actions, can disable specific menus in some mods.
You can set bytes as string. Will be converted internally as byte array with charset UTF-8.""")
public Map<String, ModActions> mods_permissions = createModMap();

// Create world map
Expand All @@ -462,33 +466,84 @@ private Map<String, List<String>> createMapCmdWorld() {

// Create mods list config
private Map<String, ModActions> createModMap() {
Map<String, ModActions> map = new HashMap<>();
map.put("5zig", new ModActions());
map.put("bettersprinting", new ModActions());
map.put("fabric", new ModActions());
map.put("forge", new ModActions());
map.put("liteloader", new ModActions());
map.put("rift", new ModActions());
map.put("schematica", new ModActions());
map.put("litematica", new ModActions());
map.put("worlddownloader", new ModActions());
return map;
Map<String, ModActions> list = new HashMap<>();
list.put("fabric", new ModActions("Fabric", List.of("fabric"), false, "kick {p} The mod {mod} is not allowed in this server!", new ArrayList<>(), true, false));
list.put("forge", new ModActions("Forge",List.of("fml", "forge"), false, "kick {p} The mod {mod} is not allowed in this server!", new ArrayList<>(), true, false));
list.put("liteloader", new ModActions("Lite Loader", List.of("LiteLoader", "Lite"), false, "kick {p} The mod {mod} is not allowed in this server!", new ArrayList<>(), true, false));
list.put("rift", new ModActions("Rift", List.of("rift"), false, "kick {p} The mod {mod} is not allowed in this server!", new ArrayList<>(), true, false));
list.put("5zigmod", new ModActions("5ZigMod", List.of("the5zigmod:5zig_set"), false, "kick {p} The mod {mod} is not allowed in this server!", List.of(new String(new byte[]{0x1,0x2,0x4,0x8,0x16,0x32}, StandardCharsets.UTF_8)), true, true));
list.put("bsm", new ModActions("BSM Settings", List.of("bsm:settings"), false, "kick {p} The mod {mod} is not allowed in this server!", List.of(new String(new byte[]{1}, StandardCharsets.UTF_8)), true, true));
list.put("wdl" ,new ModActions("World Downloader Init", List.of("wdl:init"), false, "kick {p} The mod {mod} is not allowed in this server!", List.of(new String(createWDLPacket0(), StandardCharsets.UTF_8), new String(createWDLPacket1(), StandardCharsets.UTF_8)), true, true));
list.put("schematica", new ModActions("Schematica", List.of("dev:null"), false, "", List.of(new String(getSchematicaPayload(), StandardCharsets.UTF_8)), false, true));
list.put("litematica", new ModActions("Litematica", List.of("litematica"), false, "", new ArrayList<>(), true, false));
return list;
}

@ConfigSerializable
public static class signSpy {
@Setting
public boolean enabled = true;
@Setting(value = "only-console")
public boolean only_console = true;
private static byte[] getSchematicaPayload() {
final ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeByte(0);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
return output.toByteArray();
}

public static byte[] createWDLPacket0() {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeInt(0);
output.writeBoolean(false);
return output.toByteArray();
}

public static byte[] createWDLPacket1() {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeInt(1);

output.writeBoolean(false);
output.writeInt(0);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
return output.toByteArray();
}

@ConfigSerializable
public static class ModActions {
public ModActions(){}

public ModActions(String _name, List<String> id, boolean _block, String _action, List<String> _bytes, boolean _validateChannel, boolean _registerPacket){
name = _name;
modId = id;
block = _block;
action = _action;
bytes = _bytes;
validateChannel = _validateChannel;
registerPacket = _registerPacket;
}

@Setting
public String name = "";
@Setting(value = "mod-id", comment = "MOD id must be as \"modid:modid\" format to listen for in/outcoming packets.")
public List<String> modId = new ArrayList<>();
@Setting(comment = "Block this mod on server?")
public boolean block = false;
@Setting(comment = "Use {p} for player name and {mod} for mod name.\nLeave blank to don't execute commands.")
public String action = "kick {p} The mod {mod} is not allowed in this server!";
@Setting(comment = "Byte array (as string) relative to the mod you is blocking, to send via packet to client")
public List<String> bytes = new ArrayList<>();
@Setting(value = "validate-channel", comment = "Check packet channel id?")
public boolean validateChannel = true;
@Setting(value = "register-packet", comment = "Register in/outcoming packets? Modid must be in the format \"modid:modid\".")
public boolean registerPacket = true;
}

@ConfigSerializable
public static class signSpy {
@Setting
public boolean enabled = true;
@Setting(value = "only-console")
public boolean only_console = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2023 - @FabioZumbi12
* Last Modified: 02/10/2023 22:14
* Copyright (c) 2012-2024 - @FabioZumbi12
* Last Modified: 24/06/2024 23:00
*
* This class is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any
* damages arising from the use of this class.
Expand All @@ -27,8 +27,6 @@
package br.net.fabiozumbi12.RedProtect.Bukkit.listeners;

import br.net.fabiozumbi12.RedProtect.Bukkit.RedProtect;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;

Expand All @@ -38,70 +36,34 @@ public class ModListener implements PluginMessageListener {

private final RedProtect plugin;

String ZIG = "5zig_Set";
String BSM = "BSM";
String MCBRAND = "MC|Brand";
String SCHEMATICA = "schematica";
String WDLINIT = "WDL|INIT";
String WDLCONTROL = "WDL|CONTROL";

public ModListener(RedProtect plugin) {
this.plugin = plugin;

try {
// If newer versions
Class.forName("org.bukkit.entity.Dolphin");

ZIG = "the5zigmod:5zig_set";
BSM = "bsm:settings";
MCBRAND = "minecraft:brand";
SCHEMATICA = "dev:null";
WDLINIT = "wdl:init";
WDLCONTROL = "wdl:control";
} catch (ClassNotFoundException ignored) {
}

plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, ZIG, this);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, BSM, this);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, MCBRAND, this);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, SCHEMATICA, this);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, WDLINIT, this);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, ZIG);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, BSM);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, SCHEMATICA);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, WDLCONTROL);

plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, "BungeeCord", this);
}

/* Packets */
private static byte[] getSchematicaPayload() {
final ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeByte(0);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
return output.toByteArray();
}

public static byte[] createWDLPacket0() {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeInt(0);
output.writeBoolean(false);
return output.toByteArray();
}

public static byte[] createWDLPacket1() {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeInt(1);

output.writeBoolean(false);
output.writeInt(0);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
output.writeBoolean(false);
return output.toByteArray();
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, MCBRAND, this);
plugin.getConfigManager().configRoot().server_protection.mods_permissions.forEach((k,v) -> {
if (v.registerPacket){
v.modId.forEach(i -> {
try{
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, i, this);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, i);
} catch (Exception ex){
RedProtect.get().logger.severe("Error on register MOD packet listener: " + ex.getMessage());
}
});
}
});

plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, "BungeeCord", this);
} catch (ClassNotFoundException ex) {
RedProtect.get().logger.severe("This server don't allow packet listener for MOD restrictions: " + ex.getMessage());
}
}

public void unload() {
Expand All @@ -111,107 +73,37 @@ public void unload() {

@Override
public void onPluginMessageReceived(String channel, Player player, byte[] value) {
if (channel.equalsIgnoreCase(MCBRAND)) {
if (player != null && channel != null && channel.equalsIgnoreCase(MCBRAND)) {
String brand = new String(value, StandardCharsets.UTF_8);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("fabric").block)
denyFabric(player, brand);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("forge").block)
denyForge(player, brand);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("liteloader").block)
denyLiteLoader(player, brand);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("rift").block)
denyRift(player, brand);
}
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("5zig").block)
deny5Zig(player, channel);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("bettersprinting").block)
denyBSM(player, channel);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("schematica").block)
denySchematica(player);
if (plugin.getConfigManager().configRoot().server_protection.mods_permissions.get("worlddownloader").block)
denyWDL(player, channel);
}

/* Actions */
private void denySchematica(Player player) {
if (!player.hasPermission("redprotect.mods.schematica.bypass")) {
player.sendPluginMessage(plugin, SCHEMATICA, getSchematicaPayload());
//executeAction(player, "schematica");
}
}

private void denyLitematica(Player player) {
if (!player.hasPermission("redprotect.mods.litematica.bypass")) {
//executeAction(player, "litematica");
}
}

private void deny5Zig(Player player, String channel) {
if (channel.equalsIgnoreCase(ZIG) && !player.hasPermission("redprotect.mods.5zig.bypass")) {
/*
* 0x1 = Potion HUD
* 0x2 = Potion Indicator
* 0x4 = Armor HUD
* 0x8 = Saturation
* 0x16 = Unused
* 0x32 = Auto Reconnect
*/
player.sendPluginMessage(plugin, channel, new byte[]{0x1 | 0x2 | 0x4 | 0x8 | 0x16 | 0x32});

executeAction(player, "5zig");
}
}

private void denyBSM(Player player, String channel) {
if (channel.equalsIgnoreCase(BSM) && !player.hasPermission("redprotect.mods.bettersprinting.bypass")) {
player.sendPluginMessage(plugin, channel, new byte[]{1});

executeAction(player, "bettersprinting");
}
}

private void denyFabric(Player player, String channel) {
if (channel.contains("fabric") && !player.hasPermission("redprotect.mods.fabric.bypass")) {
executeAction(player, "fabric");
}
}

private void denyForge(Player player, String channel) {
if ((channel.contains("fml") || channel.contains("forge")) && !player.hasPermission("redprotect.mods.forge.bypass")) {
executeAction(player, "forge");
}
}

private void denyLiteLoader(Player player, String channel) {
if ((channel.equalsIgnoreCase("LiteLoader") || channel.contains("Lite")) && !player.hasPermission("redprotect.mods.liteloader.bypass")) {
executeAction(player, "liteloader");
}
}

private void denyRift(Player player, String channel) {
if (channel.contains("rift") && !player.hasPermission("redprotect.mods.rift.bypass")) {
executeAction(player, "rift");
}
}

private void denyWDL(Player player, String channel) {
if (channel.equalsIgnoreCase(WDLINIT) && !player.hasPermission("redprotect.mods.worlddownloader.bypass")) {
byte[][] packets = new byte[2][];
packets[0] = createWDLPacket0();
packets[1] = createWDLPacket1();
for (byte[] packet : packets) player.sendPluginMessage(plugin, WDLCONTROL, packet);

executeAction(player, "worlddownloader");
}
}

private void executeAction(Player player, String mod) {
String action = plugin.getConfigManager().configRoot().server_protection.mods_permissions.get(mod).action;
if (!action.isEmpty()) {
action = action
.replace("{p}", player.getName())
.replace("{mod}", mod);
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), action);
plugin.getConfigManager().configRoot().server_protection.mods_permissions.forEach((k,v) -> {
if (v.block){
v.modId.forEach(i ->{
if (brand.contains(i) && !player.hasPermission("redprotect.mods."+i+".bypass")) {
v.bytes.forEach(b -> {
player.sendPluginMessage(plugin, brand, b.getBytes(StandardCharsets.UTF_8));
});
var act = v.action;
if (!act.isEmpty()) {
act = act
.replace("{p}", player.getName())
.replace("{mod}", i);
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), act);
}
} else if (channel.contains(i) && !player.hasPermission("redprotect.mods."+i+".bypass")) {
v.bytes.forEach(b -> {
player.sendPluginMessage(plugin, brand, b.getBytes(StandardCharsets.UTF_8));
});
var act = v.action;
if (!act.isEmpty()) {
act = act
.replace("{p}", player.getName())
.replace("{mod}", i);
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), act);
}
}
});
}
});
}
}
}

0 comments on commit 266a34a

Please sign in to comment.