Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This repository is TF-Minecraft's fork of CoreProtect, developed by [PlayPro](ht
- **Detailed activity searches** — narrow results by player, time, action, location, and affected materials.
- **Targeted recovery** — roll back selected changes and restore previously rolled-back activity.
- **Recovery previews** — review the effect of a rollback or restore before applying it.
- **Broad world coverage** — logging includes player block changes, container contents, explosions, fire, liquids, many entity interactions, and where each online player is once a minute.
- **Broad world coverage** — logging includes player block changes, container contents, explosions, fire, liquids, many entity interactions, skills players use and where they teleport them, and where each online player is once a minute.
- **Staff investigation tools** — paginated lookups, inventory history, and WorldEdit selection support help investigate incidents of different sizes.

CoreProtect supports both investigation and recovery; the recorded history available to staff depends on the server's logging settings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.tfminecraft.coreprotect.language.Selector;
import net.tfminecraft.coreprotect.model.action.EntityActionFilter;
import net.tfminecraft.coreprotect.model.action.LookupActions;
import net.tfminecraft.coreprotect.model.action.SkillLog;
import net.tfminecraft.coreprotect.model.lookup.LookupOutputMode;
import net.tfminecraft.coreprotect.model.lookup.LookupRollbackState;
import net.tfminecraft.coreprotect.utility.Chat;
Expand All @@ -52,6 +53,9 @@ public static void runCommand(CommandSender player, Command command, boolean per
ActionParser.ParseResult actionResult = CommandParser.parseActions(args, true);
List<Integer> argAction = actionResult.getActions();
EntityActionFilter argEntityActionFilter = actionResult.getEntityActionFilter();
if (actionResult.isSkillLookup()) {
argFilters = SkillLog.lookupFilters(argFilters);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
List<Object> argBlocks = CommandParser.parseRestricted(player, args, argAction);
Map<Object, Boolean> argExclude = CommandParser.parseExcluded(player, args, argAction);
List<String> argExcludeUsers = CommandParser.parseExcludedUsers(player, args);
Expand Down Expand Up @@ -194,6 +198,11 @@ else if (resultc > 1) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_ACTION));
return;
}
// The skill prefix filter would also apply to the other action's rows, such as chat.
if (actionResult.isSkillLookup() && argAction.stream().anyMatch(action -> action != LookupActions.COMMAND)) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INCOMPATIBLE_ACTION, "a:skill"));
return;
}
if (rollbackState != LookupRollbackState.ANY && (argAction.contains(LookupActions.CHAT) || argAction.contains(LookupActions.COMMAND) || argAction.contains(LookupActions.SESSION) || argAction.contains(LookupActions.USERNAME) || argAction.contains(LookupActions.SIGN))) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INCOMPATIBLE_ACTION, rollbackState == LookupRollbackState.ROLLED_BACK ? "#rolledback" : "#restored"));
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class TabHandler implements TabCompleter {
// private static String[] COMMANDS = new String[] { "help", "inspect", "rollback", "restore", "lookup", "purge", "reload", "status", "near", "undo" }; // max 10!
private static final String[] HELP = new String[] { "inspect", "rollback", "restore", "lookup", "purge", "teleport", "status", "params", "users", "time", "radius", "action", "include", "exclude", "filter" };
private static final String[] PARAMS = new String[] { "user:", "time:", "radius:", "action:", "include:", "exclude:", "filter:", "#container" };
private static final String[] ACTIONS = new String[] { "block", "+block", "-block", "click", "kill", "spawn", "+container", "-container", "container", "chat", "command", "+inventory", "-inventory", "inventory", "item", "+item", "-item", "sign", "session", "+session", "-session", "ping", "username" };
private static final String[] ACTIONS = new String[] { "block", "+block", "-block", "click", "kill", "spawn", "+container", "-container", "container", "chat", "command", "skill", "+inventory", "-inventory", "inventory", "item", "+item", "-item", "sign", "session", "+session", "-session", "ping", "username" };
private static final String[] NUMBERS = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
private static final String[] TIMES = new String[] { "w", "d", "h", "m", "s" };
private static ArrayList<String> materials = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public static ParseResult parseActions(String[] inputArguments, boolean allowMul
String[] argumentArray = inputArguments.clone();
List<Integer> result = new ArrayList<>();
EntityActionFilter entityActionFilter = EntityActionFilter.DEFAULT;
boolean skillLookup = false;
boolean commandLookup = false;
int count = 0;
int next = 0;
for (String argument : argumentArray) {
Expand All @@ -65,6 +67,8 @@ public static ParseResult parseActions(String[] inputArguments, boolean allowMul
else if (next == 1 || argument.startsWith("a:") || argument.startsWith("action:")) {
result.clear();
entityActionFilter = EntityActionFilter.NONE;
skillLookup = false;
commandLookup = false;
argument = argument.replaceAll("action:", "");
argument = argument.replaceAll("a:", "");
if (argument.startsWith("#")) {
Expand All @@ -76,6 +80,8 @@ else if (next == 1 || argument.startsWith("a:") || argument.startsWith("action:"
ParseResult parsedAction = parseActions(new String[] { "lookup", "a:" + action }, false);
result.addAll(parsedAction.getActions());
entityActionFilter = entityActionFilter.merge(parsedAction.getEntityActionFilter());
skillLookup |= parsedAction.isSkillLookup();
commandLookup |= parsedAction.getActions().contains(LookupActions.COMMAND) && !parsedAction.isSkillLookup();
}
}
next = 0;
Expand Down Expand Up @@ -120,6 +126,12 @@ else if (argument.equals("chat") || argument.equals("chats") || argument.equals(
}
else if (argument.equals("command") || argument.equals("commands")) {
result.add(LookupActions.COMMAND);
commandLookup = true;
}
else if (argument.equals("skill") || argument.equals("skills") || argument.equals("ability") || argument.equals("abilities")) {
// Skill casts are command rows; see SkillLog.
result.add(LookupActions.COMMAND);
skillLookup = true;
}
else if (argument.equals("logins") || argument.equals("login") || argument.equals("+session") || argument.equals("+sessions") || argument.equals("session+") || argument.equals("+connection") || argument.equals("connection+")) {
result.add(LookupActions.SESSION);
Expand Down Expand Up @@ -180,17 +192,27 @@ else if (argument.equals("+item") || argument.equals("item+") || argument.equals
}
count++;
}
return new ParseResult(result, entityActionFilter);
return new ParseResult(result, entityActionFilter, skillLookup && !commandLookup);
}

public static final class ParseResult {

private final List<Integer> actions;
private final EntityActionFilter entityActionFilter;
private final boolean skillLookup;

private ParseResult(List<Integer> actions, EntityActionFilter entityActionFilter) {
private ParseResult(List<Integer> actions, EntityActionFilter entityActionFilter, boolean skillLookup) {
this.actions = actions;
this.entityActionFilter = entityActionFilter;
this.skillLookup = skillLookup;
}

/**
* Whether command rows should be limited to skill casts. Asking for commands as well
* keeps every command row.
*/
public boolean isSkillLookup() {
return skillLookup;
}

public List<Integer> getActions() {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/tfminecraft/coreprotect/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public class Config extends Language {
public boolean PLAYER_INTERACTIONS;
public boolean PLAYER_MESSAGES;
public boolean PLAYER_COMMANDS;
public boolean PLAYER_SKILLS;
public boolean PLAYER_SESSIONS;
public boolean UNKNOWN_LOGGING;
public boolean USERNAME_CHANGES;
Expand Down Expand Up @@ -172,6 +173,7 @@ public class Config extends Language {
DEFAULT_VALUES.put("player-interactions", "true");
DEFAULT_VALUES.put("player-messages", "true");
DEFAULT_VALUES.put("player-commands", "true");
DEFAULT_VALUES.put("player-skills", "true");
DEFAULT_VALUES.put("player-sessions", "true");
DEFAULT_VALUES.put("player-pings", "60");
DEFAULT_VALUES.put("username-changes", "true");
Expand Down Expand Up @@ -223,6 +225,7 @@ public class Config extends Language {
HEADERS.put("player-interactions", new String[] { "# Track player interactions, such as when a player opens a door, presses", "# a button, or opens a chest. Player interactions can't be rolled back." });
HEADERS.put("player-messages", new String[] { "# Logs messages that players send in the chat." });
HEADERS.put("player-commands", new String[] { "# Logs all commands used by players." });
HEADERS.put("player-skills", new String[] { "# Logs MythicLib skills that players activate, and where skills teleport them.", "# Search them with \"/co lookup a:skill\"." });
HEADERS.put("player-sessions", new String[] { "# Logs the logins and logouts of players." });
HEADERS.put("player-pings", new String[] { "# Logs the position of each online player at this interval, in seconds.", "# Search them with \"/co lookup a:ping\". Set to \"0\" to disable." });
HEADERS.put("username-changes", new String[] { "# Logs when a player changes their Minecraft username." });
Expand Down Expand Up @@ -303,6 +306,7 @@ private void readValues() {
this.PLAYER_INTERACTIONS = this.getBoolean("player-interactions");
this.PLAYER_MESSAGES = this.getBoolean("player-messages");
this.PLAYER_COMMANDS = this.getBoolean("player-commands");
this.PLAYER_SKILLS = this.getBoolean("player-skills");
this.PLAYER_SESSIONS = this.getBoolean("player-sessions");
this.PLAYER_PINGS = this.getInt("player-pings");
this.USERNAME_CHANGES = this.getBoolean("username-changes");
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/tfminecraft/coreprotect/consumer/Queue.java
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,10 @@ protected static void queuePlayerCommand(Player player, String message, long tim
queueStandardData(new Object[] { null, Process.PLAYER_COMMAND, null, 0, null, 0, 0, null }, new String[] { player.getName(), null }, new Object[] { timestamp, player.getLocation().clone() }, false, Consumer.consumerStrings, message, Consumer.reserveConsumer());
}

protected static void queuePlayerSkill(Player player, String message, long timestamp, Location location) {
queueStandardData(new Object[] { null, Process.PLAYER_COMMAND, null, 0, null, 0, 0, null }, new String[] { player.getName(), null }, new Object[] { timestamp, location.clone() }, false, Consumer.consumerStrings, message, Consumer.reserveConsumer());
}

protected static void queuePlayerInteraction(String user, BlockState block, Material type) {
queueStandardData(new Object[] { null, Process.PLAYER_INTERACTION, type, 0, null, 0, 0, null }, new String[] { user, null }, block, false, Consumer.reserveConsumer());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import net.tfminecraft.coreprotect.listener.player.PlayerTakeLecternBookListener;
import net.tfminecraft.coreprotect.listener.player.ProjectileLaunchListener;
import net.tfminecraft.coreprotect.listener.player.SignChangeListener;
import net.tfminecraft.coreprotect.listener.player.SkillCastListener;
import net.tfminecraft.coreprotect.listener.player.SpawnEggUseListener;
import net.tfminecraft.coreprotect.listener.world.ChunkPopulateListener;
import net.tfminecraft.coreprotect.listener.world.LeavesDecayListener;
Expand Down Expand Up @@ -203,6 +204,7 @@ public ListenerHandler(CoreProtect plugin) {
pluginManager.registerEvents(new SpawnEggUseListener(), plugin);
pluginManager.registerEvents(new PlayerTakeLecternBookListener(), plugin);
pluginManager.registerEvents(new ProjectileLaunchListener(), plugin);
SkillCastListener.register(plugin);

// World Listeners
pluginManager.registerEvents(new ChunkPopulateListener(), plugin);
Expand Down
Loading