Updated the command block whitelist to add functionality to restore, clear, and remove whitelisted blocks from specific players, or globaly. I also patched the full system check bug that left a residual command block.

This commit is contained in:
trouper
2024-05-31 13:30:55 -05:00
parent 76dee13cd0
commit 3cc69a9ae1
11 changed files with 217 additions and 55 deletions

View File

@@ -9,6 +9,7 @@ import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
import io.github.thetrouper.sentinel.server.functions.*;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
@@ -16,11 +17,15 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@CommandRegistry(value = "sentinel",permission = @Permission("sentinel.staff"),printStackTrace = true)
public class SentinelCommand implements CustomCommand {
public static boolean debugMode;
public static List<UUID> autoWhitelist = new ArrayList<>();
@Override
public void dispatchCommand(CommandSender commandSender, Args args) {
Player p = (Player) commandSender;
@@ -64,7 +69,6 @@ public class SentinelCommand implements CustomCommand {
if (target.getType().equals(Material.COMMAND_BLOCK) || target.getType().equals(Material.REPEATING_COMMAND_BLOCK) || target.getType().equals(Material.CHAIN_COMMAND_BLOCK)) {
CommandBlock cb = (CommandBlock) target.getState();
CMDBlockWhitelist.add(cb,p.getUniqueId());
p.sendMessage(Text.prefix("Successfully whitelisted a &b" + Text.cleanName(cb.getType().toString()) + "&7 with the command &a" + cb.getCommand() + "&7."));
return;
}
p.sendMessage(Text.prefix("Could not whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it is not a command block!"));
@@ -78,6 +82,37 @@ public class SentinelCommand implements CustomCommand {
}
p.sendMessage(Text.prefix("Could not un-whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it wasn't whitelisted in the first place!"));
}
case "auto" -> {
if (autoWhitelist.contains(p.getUniqueId())) {
autoWhitelist.remove(p.getUniqueId());
p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 off for you."));
} else {
autoWhitelist.add(p.getUniqueId());
p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 on for you."));
}
}
case "restore" -> {
if (args.get(2).toString().equals("all")) {
int result = CMDBlockWhitelist.restoreAll();
p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks.".formatted(result)));
return;
}
String who = args.get(2).toString();
UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
int result = CMDBlockWhitelist.restoreAll(id);
p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
}
case "clear" -> {
if (args.get(2).toString().equals("all")) {
int result = CMDBlockWhitelist.clearAll();
p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks.".formatted(result)));
return;
}
String who = args.get(2).toString();
UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
int result = CMDBlockWhitelist.clearAll(id);
p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
}
}
}
@@ -107,6 +142,10 @@ public class SentinelCommand implements CustomCommand {
b.then(b.arg("false-positive").then(b.arg("add","remove")));
b.then(b.arg("debug").then(
b.arg("lang","toggle","chat")));
b.then(b.arg("commandblock"));
b.then(b.arg("commandblock").then(b.arg("add","remove","auto"))
.then(b.arg("restore")
.then(b.arg("<player>","all")))
.then(b.arg("clear")
.then(b.arg("<player>","all"))));
}
}

View File

@@ -5,6 +5,7 @@ import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
public class WhitelistStorage implements JsonSerializable<WhitelistStorage> {
@Override
@@ -14,6 +15,6 @@ public class WhitelistStorage implements JsonSerializable<WhitelistStorage> {
return file;
}
public List<WhitelistedBlock> whitelistedCMDBlocks = new ArrayList<>();
public ConcurrentLinkedQueue<WhitelistedBlock> whitelistedCMDBlocks = new ConcurrentLinkedQueue<>();
}

View File

@@ -2,11 +2,15 @@ package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockPlaceEvent;
@@ -25,7 +29,11 @@ public class CMDBlockPlace implements CustomListener {
b.getType().equals(Material.CHAIN_COMMAND_BLOCK))) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Block is a command block");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
CMDBlockWhitelist.add((CommandBlock) b.getState(),p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockPlace: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()

View File

@@ -2,8 +2,10 @@ package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -26,9 +28,16 @@ public class CMDBlockUse implements CustomListener {
ServerUtils.sendDebugMessage("CommandBlockUse: Block isn't null");
Block b = e.getClickedBlock();
if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return;
CommandBlock cb = (CommandBlock) b.getState();
ServerUtils.sendDebugMessage("CommandBlockUse: Block is a command block");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
if (CMDBlockWhitelist.canRun(cb.getBlock())) return;
e.setCancelled(true);
CMDBlockWhitelist.add(cb,p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockUse: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()
@@ -54,10 +63,15 @@ public class CMDBlockUse implements CustomListener {
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !p.isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Player is op");
Block b = e.getBlock();
if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return; ServerUtils.sendDebugMessage("CommandBlockChange: Block is a command block");
if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Block is a command block");
BlockState state = b.getState();
CommandBlock cb = (CommandBlock) state;
if (Sentinel.isTrusted(p)) return;
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
CMDBlockWhitelist.add(cb,p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockChange: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()

View File

@@ -10,6 +10,7 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class PluginHiderEvents implements CustomListener {
private final String[] aliases = TabCompleteEvent.VERSION_ALIASES;
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();

View File

@@ -2,7 +2,11 @@ package io.github.thetrouper.sentinel.server.functions;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
@@ -11,21 +15,20 @@ import org.bukkit.persistence.PersistentDataType;
import java.util.UUID;
public class CMDBlockWhitelist {
public static void add(CommandBlock cb, UUID owner) {
ServerUtils.sendDebugMessage("Adding a command block to the whitelist.");
boolean alwaysActive = getNBTBoolean(cb, "auto");
WhitelistedBlock wb = new WhitelistedBlock(owner.toString(),WhitelistedBlock.serialize(cb.getLocation()),getType(cb),alwaysActive,cb.getCommand());
Location wbl = WhitelistedBlock.fromSerialized(wb.loc());
Location wbloc = WhitelistedBlock.fromSerialized(wb.loc());
for (WhitelistedBlock wl : Sentinel.whitelist.whitelistedCMDBlocks) {
Location wll = WhitelistedBlock.fromSerialized(wl.loc());
if (wll.distance(wbl) < 0.5) {
Sentinel.whitelist.whitelistedCMDBlocks.remove(wb);
}
}
remove(wbloc);
Sentinel.whitelist.whitelistedCMDBlocks.add(wb);
Sentinel.whitelist.save();
if (Bukkit.getPlayer(owner) != null && !Bukkit.getPlayer(owner).isOnline()) return;
Bukkit.getPlayer(owner).sendMessage(Text.prefix("Successfully whitelisted a &b" + Text.cleanName(cb.getType().toString()) + "&7 with the command &a" + cb.getCommand() + "&7."));
}
public static void remove(Location where) {
@@ -33,7 +36,6 @@ public class CMDBlockWhitelist {
Location cbl = WhitelistedBlock.fromSerialized(cb.loc());
if (cbl.distance(where) < 0.5) {
Sentinel.whitelist.whitelistedCMDBlocks.remove(cb);
break;
}
}
@@ -65,6 +67,71 @@ public class CMDBlockWhitelist {
return null;
}
public static int clearAll() {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
Location remove = WhitelistedBlock.fromSerialized(cb.loc());
remove(remove);
remove.getBlock().setType(Material.AIR);
total++;
}
return total;
}
public static int clearAll(UUID who) {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (!cb.owner().equals(who.toString())) continue;
Location remove = WhitelistedBlock.fromSerialized(cb.loc());
remove(remove);
remove.getBlock().setType(Material.AIR);
total++;
}
return total;
}
public static int restoreAll() {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++;
}
return total;
}
public static int restoreAll(UUID who) {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (!cb.owner().equals(who.toString())) continue;
if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++;
}
return total;
}
public static boolean restore(Location where) {
WhitelistedBlock wb = get(where);
if (wb == null) {
ServerUtils.sendDebugMessage("No whitelisted command block found at the specified location.");
return false;
}
Block block = where.getBlock();
block.setType(getBlockType(wb.type()));
if (!(block.getState() instanceof CommandBlock)) {
ServerUtils.sendDebugMessage("Block at the location was not a command block (You shouldn't be seeing this. Report it).");
return false;
}
CommandBlock cb = (CommandBlock) block.getState();
cb.setCommand(wb.command());
cb.setType(getBlockType(wb.type()));
setNBTBoolean(cb, "auto", wb.active());
cb.update();
ServerUtils.sendDebugMessage("Command block at " + where.toString() + " has been restored.");
return true;
}
public static String getType(CommandBlock cb) {
switch (cb.getType()) {
case COMMAND_BLOCK -> {
@@ -80,6 +147,24 @@ public class CMDBlockWhitelist {
return null;
}
private static Material getBlockType(String type) {
return switch (type) {
case "impulse" -> Material.COMMAND_BLOCK;
case "repeat" -> Material.REPEATING_COMMAND_BLOCK;
case "chain" -> Material.CHAIN_COMMAND_BLOCK;
default -> throw new IllegalArgumentException("Unknown command block type: " + type);
};
}
private static void setNBTBoolean(CommandBlock cmdBlock, String key, boolean value) {
cmdBlock.getPersistentDataContainer().set(
getKey(key),
PersistentDataType.BYTE,
value ? (byte) 1 : (byte) 0
);
}
private static boolean getNBTBoolean(CommandBlock cmdBlock, String key) {
return cmdBlock.getPersistentDataContainer().has(
getKey(key),

View File

@@ -29,6 +29,9 @@ import java.util.List;
import java.util.Set;
public class SystemCheck {
private static Material save = Material.AIR;
public static void fullCheck(Player p) {
if (!Sentinel.isTrusted(p)) return;
Sentinel.mainConfig.plugin.trustedPlayers.remove(p.getUniqueId().toString());
@@ -43,12 +46,20 @@ public class SystemCheck {
p.setOp(true);
nbtCheck(p);
p.setOp(true);
cleanup(p);
Sentinel.mainConfig.plugin.trustedPlayers.add(p.getUniqueId().toString());
}
public static void cleanup(Player p) {
Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
placed.setType(save);
}
public static void cmdPlaceCheck(Player p) {
Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
save = placed.getType();
BlockState bs = placed.getState();
placed.setType(Material.COMMAND_BLOCK);
EquipmentSlot es = EquipmentSlot.HAND;