550 lines
19 KiB
Java
Executable File
550 lines
19 KiB
Java
Executable File
package net.coreprotect;
|
|
|
|
import java.sql.Connection;
|
|
import java.sql.Statement;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.Server;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.block.BlockState;
|
|
import org.bukkit.block.data.BlockData;
|
|
import org.bukkit.entity.EntityType;
|
|
import org.bukkit.entity.Player;
|
|
|
|
import net.coreprotect.api.BlockAPI;
|
|
import net.coreprotect.api.QueueLookup;
|
|
import net.coreprotect.api.SessionLookup;
|
|
import net.coreprotect.config.Config;
|
|
import net.coreprotect.consumer.Queue;
|
|
import net.coreprotect.database.Database;
|
|
import net.coreprotect.database.Lookup;
|
|
import net.coreprotect.database.Rollback;
|
|
import net.coreprotect.language.Phrase;
|
|
import net.coreprotect.listener.player.InventoryChangeListener;
|
|
import net.coreprotect.utility.Chat;
|
|
import net.coreprotect.utility.Util;
|
|
|
|
public class CoreProtectAPI extends Queue {
|
|
|
|
public class ParseResult {
|
|
String[] parse;
|
|
|
|
public ParseResult(String[] data) {
|
|
parse = data;
|
|
}
|
|
|
|
public int getActionId() {
|
|
return Integer.parseInt(parse[7]);
|
|
}
|
|
|
|
public String getActionString() {
|
|
int actionID = Integer.parseInt(parse[7]);
|
|
if (parse.length < 13 && Integer.parseInt(parse[6]) == SessionLookup.ID) {
|
|
switch (actionID) {
|
|
case 0:
|
|
return "logout";
|
|
case 1:
|
|
return "login";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
String result = "unknown";
|
|
if (actionID == 0) {
|
|
result = "break";
|
|
}
|
|
else if (actionID == 1) {
|
|
result = "place";
|
|
}
|
|
else if (actionID == 2) {
|
|
result = "click";
|
|
}
|
|
else if (actionID == 3) {
|
|
result = "kill";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Deprecated
|
|
public int getData() {
|
|
return Integer.parseInt(parse[6]);
|
|
}
|
|
|
|
public String getPlayer() {
|
|
return parse[1];
|
|
}
|
|
|
|
@Deprecated
|
|
public int getTime() {
|
|
return Integer.parseInt(parse[0]);
|
|
}
|
|
|
|
public long getTimestamp() {
|
|
return Long.parseLong(parse[0]) * 1000L;
|
|
}
|
|
|
|
public Material getType() {
|
|
if (parse.length < 13) {
|
|
return null;
|
|
}
|
|
|
|
int actionID = this.getActionId();
|
|
int type = Integer.parseInt(parse[5]);
|
|
String typeName;
|
|
|
|
if (actionID == 3) {
|
|
typeName = Util.getEntityType(type).name();
|
|
}
|
|
else {
|
|
typeName = Util.getType(type).name().toLowerCase(Locale.ROOT);
|
|
typeName = Util.nameFilter(typeName, this.getData());
|
|
}
|
|
|
|
return Util.getType(typeName);
|
|
}
|
|
|
|
public BlockData getBlockData() {
|
|
if (parse.length < 13) {
|
|
return null;
|
|
}
|
|
|
|
String blockData = parse[12];
|
|
if (blockData == null || blockData.length() == 0) {
|
|
return getType().createBlockData();
|
|
}
|
|
return Bukkit.getServer().createBlockData(blockData);
|
|
}
|
|
|
|
public int getX() {
|
|
return Integer.parseInt(parse[2]);
|
|
}
|
|
|
|
public int getY() {
|
|
return Integer.parseInt(parse[3]);
|
|
}
|
|
|
|
public int getZ() {
|
|
return Integer.parseInt(parse[4]);
|
|
}
|
|
|
|
public boolean isRolledBack() {
|
|
if (parse.length < 13) {
|
|
return false;
|
|
}
|
|
|
|
return (Integer.parseInt(parse[8]) == 1 || Integer.parseInt(parse[8]) == 3);
|
|
}
|
|
|
|
public String worldName() {
|
|
return Util.getWorldName(Integer.parseInt(parse.length < 13 ? parse[5] : parse[9]));
|
|
}
|
|
}
|
|
|
|
private static Map<Object, Boolean> parseList(List<Object> list) {
|
|
Map<Object, Boolean> result = new HashMap<>();
|
|
|
|
if (list != null) {
|
|
for (Object value : list) {
|
|
if (value instanceof Material || value instanceof EntityType) {
|
|
result.put(value, false);
|
|
}
|
|
else if (value instanceof Integer) {
|
|
Material material = Util.getType((Integer) value);
|
|
result.put(material, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public int APIVersion() {
|
|
return 9;
|
|
}
|
|
|
|
public List<String[]> blockLookup(Block block, int time) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return BlockAPI.performLookup(block, time);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public List<String[]> queueLookup(Block block) {
|
|
return QueueLookup.performLookup(block);
|
|
}
|
|
|
|
public List<String[]> sessionLookup(String user, int time) {
|
|
return SessionLookup.performLookup(user, time);
|
|
}
|
|
|
|
public boolean hasPlaced(String user, Block block, int time, int offset) {
|
|
// Determine if a user has placed a block at this location in the last # of seconds.
|
|
boolean match = false;
|
|
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
long timestamp = System.currentTimeMillis() / 1000L;
|
|
long offsetTime = timestamp - offset;
|
|
List<String[]> check = blockLookup(block, time);
|
|
|
|
for (String[] value : check) {
|
|
ParseResult result = parseResult(value);
|
|
if (user.equalsIgnoreCase(result.getPlayer()) && result.getActionId() == 1 && result.getTimestamp() <= offsetTime) {
|
|
match = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return match;
|
|
}
|
|
|
|
public boolean hasRemoved(String user, Block block, int time, int offset) {
|
|
// Determine if a user has removed a block at this location in the last # of seconds.
|
|
boolean match = false;
|
|
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
long timestamp = System.currentTimeMillis() / 1000L;
|
|
long offsetTime = timestamp - offset;
|
|
List<String[]> check = blockLookup(block, time);
|
|
|
|
for (String[] value : check) {
|
|
ParseResult result = parseResult(value);
|
|
if (user.equalsIgnoreCase(result.getPlayer()) && result.getActionId() == 0 && result.getTimestamp() <= offsetTime) {
|
|
match = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return match;
|
|
}
|
|
|
|
public boolean isEnabled() {
|
|
return Config.getGlobal().API_ENABLED;
|
|
}
|
|
|
|
public boolean logChat(Player player, String message) {
|
|
if (Config.getGlobal().API_ENABLED && player != null && Config.getConfig(player.getWorld()).PLAYER_MESSAGES) {
|
|
if (message != null) {
|
|
if (message.length() > 0 && !message.startsWith("/")) {
|
|
long timestamp = System.currentTimeMillis() / 1000L;
|
|
|
|
Queue.queuePlayerChat(player, message, timestamp);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean logCommand(Player player, String command) {
|
|
if (Config.getGlobal().API_ENABLED && player != null && Config.getConfig(player.getWorld()).PLAYER_COMMANDS) {
|
|
if (command != null) {
|
|
if (command.length() > 0 && command.startsWith("/")) {
|
|
long timestamp = System.currentTimeMillis() / 1000L;
|
|
|
|
Queue.queuePlayerCommand(player, command, timestamp);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean logInteraction(String user, Location location) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
if (user != null && location != null) {
|
|
if (user.length() > 0) {
|
|
Queue.queuePlayerInteraction(user, location.getBlock().getState(), location.getBlock().getType());
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean logContainerTransaction(String user, Location location) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return InventoryChangeListener.inventoryTransaction(user, location, null);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean logPlacement(String user, Location location, Material type, BlockData blockData) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
if (user != null && location != null) {
|
|
if (user.length() > 0) {
|
|
Block block = location.getBlock();
|
|
BlockState blockState = block.getState();
|
|
String blockDataString = null;
|
|
|
|
if (blockData != null) {
|
|
blockDataString = blockData.getAsString();
|
|
}
|
|
|
|
Queue.queueBlockPlace(user, blockState, block.getType(), null, type, -1, 0, blockDataString);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Deprecated
|
|
public boolean logPlacement(String user, Location location, Material type, byte data) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
if (user != null && location != null) {
|
|
if (user.length() > 0) {
|
|
Queue.queueBlockPlace(user, location.getBlock().getState(), location.getBlock().getType(), null, type, data, 1, null);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean logRemoval(String user, Location location, Material type, BlockData blockData) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
if (user != null && location != null) {
|
|
if (user.length() > 0) {
|
|
String blockDataString = null;
|
|
|
|
if (blockData != null) {
|
|
blockDataString = blockData.getAsString();
|
|
}
|
|
|
|
Block block = location.getBlock();
|
|
Database.containerBreakCheck(user, block.getType(), block, null, location);
|
|
Queue.queueBlockBreak(user, location.getBlock().getState(), type, blockDataString, 0);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Deprecated
|
|
public boolean logRemoval(String user, Location location, Material type, byte data) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
if (user != null && location != null) {
|
|
if (user.length() > 0) {
|
|
Queue.queueBlockBreak(user, location.getBlock().getState(), type, type.createBlockData().getAsString(), data);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public ParseResult parseResult(String[] results) {
|
|
return new ParseResult(results);
|
|
}
|
|
|
|
public List<String[]> performLookup(int time, List<String> restrictUsers, List<String> excludeUsers, List<Object> restrictBlocks, List<Object> excludeBlocks, List<Integer> actionList, int radius, Location radiusLocation) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(time, radius, radiusLocation, parseList(restrictBlocks), parseList(excludeBlocks), restrictUsers, excludeUsers, actionList, 0, 1, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Deprecated
|
|
public List<String[]> performLookup(String user, int time, int radius, Location location, List<Object> restrict, List<Object> exclude) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(user, time, radius, location, parseList(restrict), parseList(exclude), 0, 1, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public List<String[]> performPartialLookup(int time, List<String> restrictUsers, List<String> excludeUsers, List<Object> restrictBlocks, List<Object> excludeBlocks, List<Integer> actionList, int radius, Location radiusLocation, int limitOffset, int limitCount) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(time, radius, radiusLocation, parseList(restrictBlocks), parseList(excludeBlocks), restrictUsers, excludeUsers, actionList, 0, 1, limitOffset, limitCount, true);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Deprecated
|
|
public List<String[]> performPartialLookup(String user, int time, int radius, Location location, List<Object> restrict, List<Object> exclude, int limitOffset, int limitCount) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(user, time, radius, location, parseList(restrict), parseList(exclude), 0, 1, limitOffset, limitCount, true);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void performPurge(int time) {
|
|
Server server = Bukkit.getServer();
|
|
server.dispatchCommand(server.getConsoleSender(), "co purge t:" + time + "s");
|
|
}
|
|
|
|
public List<String[]> performRestore(int time, List<String> restrictUsers, List<String> excludeUsers, List<Object> restrictBlocks, List<Object> excludeBlocks, List<Integer> actionList, int radius, Location radiusLocation) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(time, radius, radiusLocation, parseList(restrictBlocks), parseList(excludeBlocks), restrictUsers, excludeUsers, actionList, 1, 2, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Deprecated
|
|
public List<String[]> performRestore(String user, int time, int radius, Location location, List<Object> restrict, List<Object> exclude) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(user, time, radius, location, parseList(restrict), parseList(exclude), 1, 2, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public List<String[]> performRollback(int time, List<String> restrictUsers, List<String> excludeUsers, List<Object> restrictBlocks, List<Object> excludeBlocks, List<Integer> actionList, int radius, Location radiusLocation) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(time, radius, radiusLocation, parseList(restrictBlocks), parseList(excludeBlocks), restrictUsers, excludeUsers, actionList, 0, 2, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Deprecated
|
|
public List<String[]> performRollback(String user, int time, int radius, Location location, List<Object> restrict, List<Object> exclude) {
|
|
if (Config.getGlobal().API_ENABLED) {
|
|
return processData(user, time, radius, location, parseList(restrict), parseList(exclude), 0, 2, -1, -1, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private List<String[]> processData(int time, int radius, Location location, Map<Object, Boolean> restrictBlocksMap, Map<Object, Boolean> excludeBlocks, List<String> restrictUsers, List<String> excludeUsers, List<Integer> actionList, int action, int lookup, int offset, int rowCount, boolean useLimit) {
|
|
// You need to either specify time/radius or time/user
|
|
List<String[]> result = new ArrayList<>();
|
|
List<String> uuids = new ArrayList<>();
|
|
|
|
if (restrictUsers == null) {
|
|
restrictUsers = new ArrayList<>();
|
|
}
|
|
|
|
if (excludeUsers == null) {
|
|
excludeUsers = new ArrayList<>();
|
|
}
|
|
|
|
if (actionList == null) {
|
|
actionList = new ArrayList<>();
|
|
}
|
|
|
|
List<Object> restrictBlocks = new ArrayList<>(restrictBlocksMap.keySet());
|
|
if (actionList.size() == 0 && restrictBlocks.size() > 0) {
|
|
boolean addedMaterial = false;
|
|
boolean addedEntity = false;
|
|
|
|
for (Object argBlock : restrictBlocks) {
|
|
if (argBlock instanceof Material && !addedMaterial) {
|
|
actionList.add(0);
|
|
actionList.add(1);
|
|
addedMaterial = true;
|
|
}
|
|
else if (argBlock instanceof EntityType && !addedEntity) {
|
|
actionList.add(3);
|
|
addedEntity = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (actionList.size() == 0) {
|
|
actionList.add(0);
|
|
actionList.add(1);
|
|
}
|
|
|
|
actionList.removeIf(actionListItem -> actionListItem > 3);
|
|
|
|
if (restrictUsers.size() == 0) {
|
|
restrictUsers.add("#global");
|
|
}
|
|
|
|
long timestamp = System.currentTimeMillis() / 1000L;
|
|
long startTime = timestamp - time;
|
|
long endTime = 0;
|
|
|
|
if (radius < 1) {
|
|
radius = -1;
|
|
}
|
|
|
|
if (restrictUsers.contains("#global") && radius == -1) {
|
|
return null;
|
|
}
|
|
|
|
if (radius > -1 && location == null) {
|
|
return null;
|
|
}
|
|
|
|
try (Connection connection = Database.getConnection(false, 1000)) {
|
|
if (connection != null) {
|
|
Statement statement = connection.createStatement();
|
|
boolean restrictWorld = false;
|
|
|
|
if (radius > 0) {
|
|
restrictWorld = true;
|
|
}
|
|
|
|
if (location == null) {
|
|
restrictWorld = false;
|
|
}
|
|
|
|
Integer[] argRadius = null;
|
|
if (location != null && radius > 0) {
|
|
int xMin = location.getBlockX() - radius;
|
|
int xMax = location.getBlockX() + radius;
|
|
int zMin = location.getBlockZ() - radius;
|
|
int zMax = location.getBlockZ() + radius;
|
|
argRadius = new Integer[] { radius, xMin, xMax, null, null, zMin, zMax, 0 };
|
|
}
|
|
|
|
if (lookup == 1) {
|
|
if (location != null) {
|
|
restrictWorld = true;
|
|
}
|
|
|
|
if (useLimit) {
|
|
result = Lookup.performPartialLookup(statement, null, uuids, restrictUsers, restrictBlocks, excludeBlocks, excludeUsers, actionList, location, argRadius, null, startTime, endTime, offset, rowCount, restrictWorld, true);
|
|
}
|
|
else {
|
|
result = Lookup.performLookup(statement, null, uuids, restrictUsers, restrictBlocks, excludeBlocks, excludeUsers, actionList, location, argRadius, startTime, endTime, restrictWorld, true);
|
|
}
|
|
}
|
|
else {
|
|
if (!Bukkit.isPrimaryThread()) {
|
|
boolean verbose = false;
|
|
result = Rollback.performRollbackRestore(statement, null, uuids, restrictUsers, null, restrictBlocks, excludeBlocks, excludeUsers, actionList, location, argRadius, startTime, endTime, restrictWorld, false, verbose, action, 0);
|
|
}
|
|
}
|
|
|
|
statement.close();
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Deprecated
|
|
private List<String[]> processData(String user, int time, int radius, Location location, Map<Object, Boolean> restrictBlocks, Map<Object, Boolean> excludeBlocks, int action, int lookup, int offset, int rowCount, boolean useLimit) {
|
|
ArrayList<String> restrictUsers = new ArrayList<>();
|
|
if (user != null) {
|
|
restrictUsers.add(user);
|
|
}
|
|
|
|
return processData(time, radius, location, restrictBlocks, excludeBlocks, restrictUsers, null, null, action, lookup, offset, rowCount, useLimit);
|
|
}
|
|
|
|
public void testAPI() {
|
|
Chat.console(Phrase.build(Phrase.API_TEST));
|
|
}
|
|
|
|
}
|