Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6441a46542
|
||
|
|
fa9ea0bbc4
|
||
|
|
193e4a5d24 | ||
|
|
e3fc64536e | ||
|
|
16ca190ee5 | ||
|
|
ac2a237ea0 | ||
|
|
06b463f90c | ||
|
|
6541e7dacf | ||
|
|
885b649dcc | ||
|
|
e67199137d | ||
|
|
15b2a12cd1 | ||
|
|
2b26b6b569 | ||
|
|
f981a202d0 | ||
|
|
f1e63c34a2 | ||
|
|
e244c4a60a | ||
|
|
33aa4a6b4a | ||
|
|
c4a8d0cddc | ||
|
|
a824e1efe0 | ||
|
|
0cf794322f | ||
|
|
db6fdf2808 | ||
|
|
4fecf0b59c | ||
|
|
317cec3f9d | ||
|
|
e19f7131f4 | ||
|
|
c117abbed6 | ||
|
|
6a031e3ddd | ||
|
|
32fb98588d | ||
|
|
98bd6dcc9d | ||
|
|
5b15d5f484 | ||
|
|
f7c6ba06e8 | ||
|
|
099a82436d | ||
|
|
7e872d7cbc | ||
|
|
58ab1de049 | ||
|
|
6940173a9a | ||
|
|
d20ea07d9e | ||
|
|
d28f61d476 | ||
|
|
c9256f8da9 | ||
|
|
1ec2962487 | ||
|
|
ceb7dd75ed | ||
|
|
96cc2d2fbc | ||
|
|
acd491a3b3 | ||
|
|
5eb48b19aa | ||
|
|
326bd81f9a | ||
|
|
4ad3eead9b | ||
|
|
aa5276c816 | ||
|
|
03a9a6085d | ||
|
|
1b83a908ef | ||
|
|
08841ad481 | ||
|
|
4953bddbbd | ||
|
|
5945e0edb9 |
No files matched your search
@@ -0,0 +1 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -1,66 +1,73 @@
|
||||
## ***[PULL REQUESTS](https://github.com/the-lockedcraft-legacy-organization/ParamnesticCure/pulls) WELCOME!***
|
||||
|
||||
# Description
|
||||
A spigot patch to prevent rollbacks from stripping creative block data.
|
||||
Block Logging Plugins allow admins to restore/revert the blocks of any area to the way they were any point in time.<br />
|
||||
Unfortunately, when doing this, Loggers do not consider the data Creative Limiter Plugins store.<br />
|
||||
|
||||
### Supported Loggers
|
||||
- https://www.spigotmc.org/resources/coreprotect.8631/
|
||||
For that reason, **Block Logger Plugins are NOT compatible with Creative Limiter Plugins**!<br />
|
||||
Specifically, **they can UNPROTECT CREATIVE BLOCKS and MARK SURVIVAL BLOCKS AS CREATIVE**!<br />
|
||||
|
||||
### Supported Creative Limiters
|
||||
- https://www.spigotmc.org/resources/restrictedcreative.42790/
|
||||
For a technical explanation of the problem, see [this logic chain](https://i.imgur.com/KsChAdh.png).<br />
|
||||
Note that it can be rather complex as that chain can occur recursively, in any order, and/or at any time.
|
||||
<br /><br />
|
||||
**PARAMNESTIC SOLVES THIS INCOMPATIBILITY**!<br />
|
||||
PC stores the location and status of potential block conflicts in a third database.<br />
|
||||
PC will then correct detected conflicts using the Logger's and the Limiter's APIs
|
||||
|
||||
|
||||
## Scope
|
||||
This project is currently a bare-bones patchwork which may or may not be fully featured in future.
|
||||
|
||||
### Features
|
||||
- Blocks removed by a rollback are stripped of their creative data to ensure survival blocks later placed in that spot are not declared as creative.
|
||||
- Creative data is restored to blocks modified by a rollback.
|
||||
### Paramnestic Has Support For:
|
||||
##### Block Loggers:
|
||||
- [CoreProtect by Intelli](https://www.spigotmc.org/resources/coreprotect.8631/)
|
||||
##### Creative Limiters
|
||||
- [RestrictedCreative by Prunt](https://www.spigotmc.org/resources/restrictedcreative.42790/)
|
||||
> Click [here](https://github.com/the-lockedcraft-legacy-organization/ParamnesticCure/issues/17) for a the list of loggers/limiters that may be supported in the future.
|
||||
|
||||
## Background
|
||||
- This plugin was developed for a temporary collaborative public SMP project
|
||||
- It was possible to obtain creative mode, which would be used within the context of a survival world.
|
||||
- Griefing was prohibited by the rules; a block-logger was needed for enforcement.
|
||||
- RB operations from any and all block loggers interfered with creative block protection, and as such, a temporary solution was needed.
|
||||
- This is that temporary solution.
|
||||
- The LCLO was a small (temporary) non-profit that hosted a temporary collaborative SMP event.
|
||||
1. Players could obtain creative mode within the context of a survival world.
|
||||
2. As griefing was prohibited by the rules, a block-logger was needed for enforcement.
|
||||
- RestrictedCreative was used to accomplish `i` and CoreProtect was used to accomplish `ii`
|
||||
- RC is a limiter plugin and CO is a logger plugin; the two were not compatible.
|
||||
- This plugin was created to fix that incompatibility.
|
||||
|
||||
# Permissions
|
||||
> This version of the plugin has no permissions, although some may be added in future!
|
||||
```
|
||||
pc.* -- Description of a parent node
|
||||
pc.subnode -- Description of a node
|
||||
```
|
||||
## Default Permissions
|
||||
```
|
||||
NO PERMISSIONS YET -- Everyone
|
||||
```
|
||||
**NOTE: AS THIS WAS MADE FOR A TEMPORARY PROJECT, SUPPORT BEYOND 1.17 IS NOT GUARANTEED**
|
||||
|
||||
# Instructions
|
||||
## Installing:
|
||||
This plugin is a drag-and-drop; simply put it in the plugins folder of whatever instance is running your creative limiter.
|
||||
Note that, if your creative logger and/or block logger uses a database, you will need to supply that information in the config.
|
||||
Also note that Paramnestic requires its own database (to track creative info for risk-prone blocks).
|
||||
PC is drag-and-drop; drop the jar into the plugins folder of whatever instance is running your logger and limiter.
|
||||
|
||||
Note that PC requires a database; by default, it uses SQLite.<br />
|
||||
If you would like to use a different engine, please specify it in the configuration.<br />
|
||||
## Usage:
|
||||
Once PC is installed, simply forget it is there.
|
||||
Commands sent to the block logger will be intercepted and executed with corrections for incompatibilities.
|
||||
|
||||
# Configuration
|
||||
```
|
||||
configVersion - Last update of PC that substantially changed the config. Do not change.
|
||||
creativeManager - The plugin being used to manage creative block states.
|
||||
blockLogger - The plugin being used to log, and roll back, player block placement.
|
||||
blockLoggerRollbackCommands - All aliases of any command that can be used to trigger a rollback.
|
||||
defaultconnection - The database information to be used if nothing is provided under Database_Names
|
||||
driver - Type of database (options Sqlite, MySQL, or MariaDB)
|
||||
address - Location of that database
|
||||
port - Port database can be reached on
|
||||
user - Username used to connect to database
|
||||
password - Password used to connect to database
|
||||
Database_Names - Specific database specifications.
|
||||
creative - Database being used by your creativeManager
|
||||
database - Database's name.
|
||||
{See fields under defaultconnection}
|
||||
logger - Database being used by your blockLogger
|
||||
database - Database's name.
|
||||
{See fields under defaultconnection}
|
||||
paramestic - Database to be used by this plugin.
|
||||
database - Database's name.
|
||||
{See fields under defaultconnection}
|
||||
On its first installation, Paramnestic will default to a config designed for RestrictedCreative and CoreProtect.<br />
|
||||
Viewing that default configuration can be very helpful; it can be found [here](https://github.com/the-lockedcraft-legacy-organization/ParamnesticCure/blob/main/src/main/resources/config.yml).
|
||||
```yaml
|
||||
configVersion: Last update of PC that substantially changed the config. Please do not change this.
|
||||
creativeManager: The plugin being used to manage creative block states.
|
||||
blockLogger: The plugin being used to log, and roll back, player block placement.
|
||||
blockLoggerRollbackCommands:
|
||||
alias: All aliases of the rollback logger's primary command
|
||||
rollback: The prefix before any subcommand which triggers a rollback.
|
||||
restore: The prefix before any subcommand which triggers a reverse rollback.
|
||||
undo: The prefix before any subcommand which reverts a rollback or restore function.
|
||||
purge: The prefix before any subcommand that deletes past server blockdata.
|
||||
help: The prefix of any subcommand which prints the plugin's command list.
|
||||
blockLoggerPermissions:
|
||||
rollback: The permission a mod needs to trigger a rollback.
|
||||
purge: The permission an admin needs to purge block logger data.
|
||||
restore: The permission a mod needs to trigger a reverse rollback.
|
||||
help: The permission a player needs to see a logger's help files.
|
||||
Database:
|
||||
driver: The engine being used to run PC's database (valid options Sqlite & Mysql)
|
||||
address: The IP of paramnestic's database
|
||||
port: The port of paramnestic's database
|
||||
databasename: The name of Paramnestic's database
|
||||
Plugin_settings:
|
||||
wait_time: The time to between the action and when paramnestic corrects it... higher numbers minimize issues.
|
||||
debug: Whether or not to spam console with debug info
|
||||
```
|
||||
# Changelog
|
||||
```
|
||||
@@ -69,10 +76,46 @@ Version 0.0.0
|
||||
| |_ Feature Release (Adds a new feature)
|
||||
|_ Milestone Release (Adds a major feature from /ParamnesticCure/milestones )
|
||||
```
|
||||
#### [Version 0.4.0] (CURRENT TARGET)
|
||||
- Fix all readily apparent runtime bugs with PC
|
||||
- Preliminary testing of PC logic.
|
||||
#### [Version 0.3.0] (CURRENT RELEASE)
|
||||
#### [Version 1.0.1]
|
||||
- Improved language interpretation
|
||||
- Improved UI messages
|
||||
- Bumped dependencies
|
||||
- Rewrote ReadME for release.
|
||||
- Added metrics.
|
||||
#### [Version 1.0.0]
|
||||
- Fixed a stupid sql structure
|
||||
- Made the logic for rollbacks / restores more rigid
|
||||
- Improved command interpretation
|
||||
- Added a debug option
|
||||
- Code cleanup
|
||||
#### [Version 0.12.10]
|
||||
- Uses hikari.properties file as config
|
||||
- Added the wait_time setting
|
||||
- Removed unnecessary blocktrackig
|
||||
#### [Version 0.12.8]
|
||||
- More formal and clear informational messages
|
||||
#### [Version 0.12.7]
|
||||
- Now cancells command intercept if the rollback/restore was for entities
|
||||
- Better error messages
|
||||
#### [Version 0.12.6]
|
||||
- A huge refactor
|
||||
- Fixed a issue which made sqlite unusable
|
||||
- Made blocktracking more rigid
|
||||
- Fixed an issue with restores
|
||||
- removed the trigger of an annoying errormessage
|
||||
- Removed unnecessary files
|
||||
#### [Version 0.12.0]
|
||||
- Implement SQLite
|
||||
- Complete and functional logic implementation.
|
||||
- Fixed alot of issues
|
||||
- Implements MySQL
|
||||
- Added undo
|
||||
- Added purge
|
||||
- Added Restores
|
||||
- Added Rollbacks
|
||||
- Added console commands
|
||||
- Added command interpretation
|
||||
#### [Version 0.3.0]
|
||||
- Implemented the plugin's logic.
|
||||
#### [Version 0.2.0]
|
||||
- Outlined the logic needed to accomplish PC's goals.
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.mcsmp</groupId>
|
||||
<artifactId>ParamnesticCure</artifactId>
|
||||
<version>0.12.0</version>
|
||||
<version>1.0.1</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spigot-version>1.16</spigot-version>
|
||||
<config-version>8</config-version>
|
||||
<config-version>12</config-version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
@@ -31,7 +31,7 @@
|
||||
<dependency>
|
||||
<groupId>me.prunt.restrictedcreative</groupId>
|
||||
<artifactId>RestrictedCreativeAPI</artifactId>
|
||||
<version>2.4.6</version>
|
||||
<version>2.4.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -49,8 +49,14 @@
|
||||
<dependency>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>CoreProtectAPI</artifactId>
|
||||
<version>19.4</version>
|
||||
<version>19.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>ParamnesticCure-${project.version}</finalName>
|
||||
@@ -61,6 +67,12 @@
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.bstats:*</include>
|
||||
<include>com.zaxxer:*</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -71,9 +83,9 @@
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.xerial</pattern>
|
||||
<shadedPattern>com.mcsmp.xerial</shadedPattern>
|
||||
</relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>com.mcsmp.bstats</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
|
||||
import com.mcsmp.database.DataBases;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
*/
|
||||
public class CacheData {
|
||||
|
||||
private ConcurrentHashMap<String, DataBases> databaseMap = new ConcurrentHashMap<>();
|
||||
private final ParamnesticCure plugin = ParamnesticCure.getInstance();
|
||||
private String address = plugin.getConfig().getString("defaultconnection.address");
|
||||
private int port = plugin.getConfig().getInt("defaultconnection.port");
|
||||
private String user = plugin.getConfig().getString("user");
|
||||
private String password = plugin.getConfig().getString("defaultconnection.password");
|
||||
private String driver = plugin.getConfig().getString("defaultconnection.driver");
|
||||
private String location = "";
|
||||
|
||||
/**
|
||||
* Method to cache database connections.
|
||||
*/
|
||||
public CacheData() {
|
||||
//TODO simplify this
|
||||
for (String databases : plugin.getConfig().getConfigurationSection("Database_Names").getKeys(false)) {
|
||||
if ( !(plugin.getConfig().getString("Database_Names." + databases + ".address").chars().allMatch(Character::isWhitespace))) {
|
||||
address = plugin.getConfig().getString("Database_Names." + databases + ".address");
|
||||
}
|
||||
if ( !(plugin.getConfig().getString("Database_Names." + databases + ".port").chars().allMatch(Character::isWhitespace)) ) {
|
||||
port = plugin.getConfig().getInt("Database_Names." + databases + ".port");
|
||||
}
|
||||
if ( !(plugin.getConfig().getString("Database_Names." + databases + ".user").chars().allMatch(Character::isWhitespace))) {
|
||||
user = plugin.getConfig().getString("Database_Names." + databases + ".user");
|
||||
}
|
||||
if ( !(plugin.getConfig().getString("Database_Names." + databases + ".password").chars().allMatch(Character::isWhitespace))) {
|
||||
password = plugin.getConfig().getString("Database_Names." + databases + ".password");
|
||||
}
|
||||
if ( !(plugin.getConfig().getString("Database_Names." + databases + ".driver").chars().allMatch(Character::isWhitespace))) {
|
||||
driver = plugin.getConfig().getString("Database_Names." + databases + ".driver");
|
||||
}
|
||||
|
||||
location = plugin.getConfig().getString("Database_Names." + databases + ".location");
|
||||
DataBases bases = new DataBases(databases.toLowerCase(), plugin.getConfig().getString("Database_Names." + databases + ".database").toLowerCase(), address, port, user, password, driver, location);
|
||||
databaseMap.put(databases.toLowerCase(), bases);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Method to return hashmap of databases.
|
||||
* @return Hashmap listing databases.
|
||||
*/
|
||||
public ConcurrentHashMap<String, DataBases> getDatabaseMap() {
|
||||
return this.databaseMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import org.bukkit.entity.Player;
|
||||
*/
|
||||
public class MessageManager {
|
||||
private Player target;
|
||||
private String prefix = ChatColor.DARK_GRAY + "[" +ChatColor.GRAY + "" + ChatColor.ITALIC + " Paramnestic " + ChatColor.RESET + "" + ChatColor.DARK_GRAY + "] ";
|
||||
private String prefix = ChatColor.DARK_GRAY + "<" +ChatColor.GRAY + "" + ChatColor.ITALIC + " Paramnestic " + ChatColor.RESET + "" + ChatColor.DARK_GRAY + "> ";
|
||||
private ChatColor errorColor = ChatColor.RED;
|
||||
private ChatColor normalColor = ChatColor.WHITE;
|
||||
|
||||
@@ -23,18 +23,18 @@ public class MessageManager {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param player The player that should get the messages
|
||||
* @param target The player that should get the messages
|
||||
* @param ini_type What type of process that the message manager is for
|
||||
*/
|
||||
MessageManager(Player target,String ini_type){
|
||||
public MessageManager(Player target,String ini_type){
|
||||
this(target);
|
||||
sendMessage("Intercepted a " + ini_type + " command",false) ;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param player The player that should get the messages
|
||||
* @param target The player that should get the messages
|
||||
*/
|
||||
MessageManager(Player target){
|
||||
public MessageManager(Player target){
|
||||
if(target != null)
|
||||
this.target = target;
|
||||
else
|
||||
@@ -46,8 +46,12 @@ public class MessageManager {
|
||||
* @param isError
|
||||
*/
|
||||
public void sendMessage(String message, boolean isError) {
|
||||
if(isConsole)
|
||||
ParamnesticCure.getInstance().getLogger().info( message );
|
||||
if(isConsole) {
|
||||
if(isError)
|
||||
ParamnesticCure.getInstance().getLogger().warning( message );
|
||||
else
|
||||
ParamnesticCure.getInstance().getLogger().info( message );
|
||||
}
|
||||
else {
|
||||
message = ( isError ? errorColor : normalColor) + message;
|
||||
if (!hasShownLogo) {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package com.mcsmp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.lang.Byte.valueOf;
|
||||
import static java.util.logging.Level.SEVERE;
|
||||
|
||||
@@ -14,13 +16,21 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import static org.bukkit.Bukkit.getPluginManager;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.mcsmp.block.BlockListener;
|
||||
import com.mcsmp.commands.CommandListener;
|
||||
import com.mcsmp.database.SqlManager;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
/**
|
||||
@@ -34,29 +44,47 @@ import net.coreprotect.CoreProtectAPI;
|
||||
public class ParamnesticCure extends JavaPlugin {
|
||||
|
||||
private static ParamnesticCure instance;
|
||||
private static boolean isDebug;
|
||||
private Logger log = Bukkit.getLogger();
|
||||
private CacheData dataCache;
|
||||
private Connection connection;
|
||||
private SqlManager database;
|
||||
private boolean isMySql;
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
//sets instance.
|
||||
instance = this;
|
||||
|
||||
|
||||
//registers bstats metrics
|
||||
int pluginId = 10452;
|
||||
new Metrics(this, pluginId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this.saveDefaultConfig();
|
||||
this.getServer().getPluginManager().registerEvents(new ParamnesticCureListener(this), this);
|
||||
log = getLogger();
|
||||
PluginManager pluginManager = this.getServer().getPluginManager();
|
||||
pluginManager.registerEvents(new CommandListener(this), this);
|
||||
pluginManager.registerEvents(new BlockListener(),this);
|
||||
pluginManager.registerEvents(new WorldListener(),this);
|
||||
|
||||
|
||||
log = getLogger();
|
||||
final byte givenVersion = valueOf(getConfig().getString("configVersion"));
|
||||
//Temporary variable indicating desired config version.
|
||||
//Should ideally be maven-based, but currently isn't due to a bug.
|
||||
final byte currentVersion = 8;
|
||||
final byte currentVersion = 12;
|
||||
File configVar = new File(getDataFolder(), "config.yml");
|
||||
//if outdated config, rename old config and install a new one.
|
||||
|
||||
// Manages plugins config.
|
||||
if (givenVersion != currentVersion) {
|
||||
if (configVar.exists()){
|
||||
configVar.renameTo(new File(getDataFolder(), "config.old"));
|
||||
new File(getDataFolder(),"config.old").delete();
|
||||
configVar.renameTo(new File(getDataFolder(), "config.old"));
|
||||
}
|
||||
this.saveDefaultConfig();
|
||||
log.warning("[Startup] Invalid config! This is either your first time running PC, or, the config has updated since you last used it.");
|
||||
@@ -65,35 +93,29 @@ public class ParamnesticCure extends JavaPlugin {
|
||||
} else {
|
||||
log.info("[Startup] Loaded Config");
|
||||
//Temporary Warning.
|
||||
log.warning("[Dev] You have enabled an early development version of this plugin.");
|
||||
log.warning("[Dev] It will probably be unstable");
|
||||
}
|
||||
|
||||
//Creates new cache
|
||||
final String driver = getConfig().getString("defaultconnection.driver");
|
||||
isMySql = (driver.toLowerCase() != "sqlite");
|
||||
log.info("[Debug] Set driver to " + driver);
|
||||
//sets instance.
|
||||
instance = this;
|
||||
dataCache = new CacheData();
|
||||
|
||||
try {
|
||||
this.connection = getCacheData().getDatabaseMap().get("paramnestic").getDatabase().getConnection();
|
||||
}
|
||||
catch(SQLException ex)
|
||||
{
|
||||
ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());
|
||||
getPluginManager().disablePlugin(this);
|
||||
log.warning("[Dev] You have enabled an development version of this plugin.");
|
||||
}
|
||||
|
||||
//Creates new cache
|
||||
final String driver = getConfig().getString("Database.driver");
|
||||
isMySql = !driver.equalsIgnoreCase("sqlite");
|
||||
|
||||
log.config("[Startup] Set driver to " + driver);
|
||||
|
||||
database = new SqlManager(
|
||||
getConfig().getString("Database.driver"),
|
||||
getConfig().getString("Database.address"),
|
||||
getConfig().getInt("Database.port"),
|
||||
getConfig().getString("Database.databasename")
|
||||
);
|
||||
|
||||
createDB();
|
||||
isDebug = getConfig().getBoolean("Plugin_settings.debug");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
try {
|
||||
connection.close();
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,14 +125,6 @@ public class ParamnesticCure extends JavaPlugin {
|
||||
public static ParamnesticCure getInstance() {
|
||||
return instance;
|
||||
}
|
||||
/**
|
||||
* Gets cached data
|
||||
* @return Returns dataCache
|
||||
*/
|
||||
public CacheData getCacheData() {
|
||||
return this.dataCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates all the databases for this plugin, also adds all the worlds to the worlds database (if not done already)
|
||||
@@ -125,7 +139,9 @@ public class ParamnesticCure extends JavaPlugin {
|
||||
+ " ,UNIQUE(time,world,x,y,z));"
|
||||
);
|
||||
statement.execute();
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
try {
|
||||
Connection connection = getConnection();
|
||||
@@ -135,12 +151,14 @@ public class ParamnesticCure extends JavaPlugin {
|
||||
+ ", world VARCHAR(255), UNIQUE(world) );"
|
||||
);
|
||||
statement.execute();
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
List<World> worldlist = ParamnesticCure.getInstance().getServer().getWorlds();
|
||||
List<World> worldlist = getServer().getWorlds();
|
||||
|
||||
for(World world : worldlist) {
|
||||
WorldManager.addWorldToDB(world);
|
||||
WorldListener.addWorldToDB(world);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -172,7 +190,13 @@ public class ParamnesticCure extends JavaPlugin {
|
||||
* Whether this is a good solution or not, i don't know. But it gives no errors
|
||||
* @return Return's this plugin's shared connection
|
||||
*/
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
public Connection getConnection() throws SQLException{
|
||||
return database.getConnection();
|
||||
}
|
||||
static public void debug(String location, String message) {
|
||||
if(isDebug)
|
||||
instance.getLogger().info(location+"::"+message);
|
||||
else
|
||||
instance.getLogger().fine(location+"::"+message);
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
|
||||
import me.prunt.restrictedcreative.RestrictedCreativeAPI;
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
* @author Thorin
|
||||
*/
|
||||
|
||||
/*
|
||||
* Paramnestic's listener class.
|
||||
*/
|
||||
public class ParamnesticCureListener implements Listener {
|
||||
|
||||
|
||||
private ConfigurationSection configSektion;
|
||||
|
||||
/*
|
||||
* Constructor class
|
||||
* @param plugin Instance of the plugin.
|
||||
*/
|
||||
public ParamnesticCureListener(ParamnesticCure plugin) {
|
||||
//
|
||||
configSektion = plugin.getConfig().getConfigurationSection("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Only tracking block break events, as those are the only necessary event that needs to get tracked; All critical actions are blockbreak events (except on rollback rollback)
|
||||
* @param event BlockBreakEvent
|
||||
*/
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
|
||||
//Tracked block checks if the block is creative/critical
|
||||
|
||||
boolean isCreative = RestrictedCreativeAPI.isCreative(event.getBlock());
|
||||
|
||||
Block block = event.getBlock();
|
||||
BlockState blockState = block.getState();
|
||||
|
||||
|
||||
ParamnesticCure.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(ParamnesticCure.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TrackedBlocks.updateCreativeID(block,isCreative);
|
||||
|
||||
|
||||
/*
|
||||
* Makes it so that both blocks for doors get updated
|
||||
*/
|
||||
if( blockState.getType().toString().contains("DOOR") ) {
|
||||
Location loc = blockState.getLocation();
|
||||
Bisected door = (Bisected) blockState.getBlockData();
|
||||
if(door.getHalf() == Bisected.Half.BOTTOM)
|
||||
loc = loc.add(0, 1, 0);
|
||||
else
|
||||
loc = loc.add(0,-1,0);
|
||||
|
||||
TrackedBlocks.updateCreativeID(loc.getBlock(),isCreative);
|
||||
}
|
||||
}
|
||||
},TrackedBlocks.waitPeriod);
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Currently not in use. It would be unnecessary to track blockplace event's as blocks can be creative even though no blockplace event occured (for example a piston moving a creative block)
|
||||
* @param event BlockPlaceEvent
|
||||
*/
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
|
||||
}
|
||||
/**
|
||||
* Checks for commands that should be intercepted
|
||||
* @param event Command being processed
|
||||
*/
|
||||
@EventHandler
|
||||
public void commandRollBack(PlayerCommandPreprocessEvent event) {
|
||||
String command = event.getMessage().toLowerCase();
|
||||
|
||||
command = command.replaceAll(": ", ":");
|
||||
String[] commandListed = command.split(" ");
|
||||
|
||||
|
||||
List<String> commandAlias = configSektion.getStringList("blockLoggerCommands.alias");
|
||||
|
||||
int i = 0;
|
||||
while(i < commandAlias.size()){
|
||||
//the first string from commandListed will have / in front, all commandAlias should as well:
|
||||
commandAlias.set( i , "/" + commandAlias.get(i) );
|
||||
i++;
|
||||
}
|
||||
|
||||
//Unnecessary to process already faulty commands
|
||||
if(!commandAlias.contains(commandListed[0])||commandListed.length < 2) return;
|
||||
|
||||
if(loggerManager.createLoggerManager(commandListed, event.getPlayer().getLocation(),event.getPlayer()))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
/**
|
||||
* Checks for commands that should be intercepted
|
||||
* @param event Command being processed
|
||||
*/
|
||||
@EventHandler
|
||||
public void serverCommandRollBack(ServerCommandEvent event) {
|
||||
//if someone types that alias cancel it.
|
||||
String command = event.getCommand().toLowerCase();
|
||||
command = command.replaceAll(": ", ":");
|
||||
String[] commandListed = command.split(" ");
|
||||
|
||||
List<String> commandAlias = configSektion.getStringList("blockLoggerCommands.alias");
|
||||
|
||||
if(!commandAlias.contains(commandListed[0])||commandListed.length < 2) return;
|
||||
|
||||
|
||||
if(loggerManager.createLoggerManager(commandListed, null, null));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a world get created, its name needs to get stored in the database. TODO I should also add something that tracks if the world was renamed
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler
|
||||
public void worldInit(WorldInitEvent event) {
|
||||
WorldManager.addWorldToDB(event.getWorld());
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import static java.util.logging.Level.SEVERE;
|
||||
import org.bukkit.block.Block;
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||
|
||||
/**
|
||||
* Consist of all the functions that track the location, the time, and the creative status of critical block actions
|
||||
* @author Frostalf
|
||||
* @author Thorin
|
||||
*/
|
||||
public class TrackedBlocks {
|
||||
|
||||
private static ParamnesticCure plugin = ParamnesticCure.getInstance();
|
||||
private static CoreProtectAPI coreprotect = plugin.getCoreProtect();
|
||||
|
||||
public static long waitPeriod = 50L;
|
||||
/**
|
||||
* Checks through the coreprotect database for the most recent block place / remove action. It then calls a function that stores it (if the block fulfils the right criteria)
|
||||
*
|
||||
* @param block the block that is going to be inspected
|
||||
* @param isCreative whether the block was a creative block before the action occurred
|
||||
*/
|
||||
public static void updateCreativeID(Block block,boolean isCreative) {
|
||||
|
||||
|
||||
int time = 0;
|
||||
List<String[]> actiondataMsg = coreprotect.blockLookup(block,0);
|
||||
|
||||
for(String[] actionMsg : actiondataMsg) {
|
||||
ParseResult action = coreprotect.parseResult(actionMsg);
|
||||
if ( action.getActionId() > 2 ) continue; //has to be block place/break action
|
||||
|
||||
time = action.getTime();
|
||||
|
||||
break;//The returned data from parseResult seems to be ordered highest time to lowest, this should therefore return the most recent block action
|
||||
}
|
||||
|
||||
updateCreativeID(time,block,isCreative);
|
||||
|
||||
}
|
||||
/**
|
||||
* Stores the specified action if it was creative, or if there already has been a creative action already on it's location
|
||||
* @param time The time the action occurred according to coreprotect.
|
||||
* @param block
|
||||
* @param isCreative Whether the action had anything to do with a creative block
|
||||
*/
|
||||
public static void updateCreativeID(int time, Block block, boolean isCreative)
|
||||
{
|
||||
|
||||
/*
|
||||
* Avoids duplicate entries, but also irrelevant blocks
|
||||
*/
|
||||
int IsInDB = isInDatabase(block,time);
|
||||
|
||||
|
||||
if( !isCreative && ( IsInDB == 0) || IsInDB == 2 ) return;
|
||||
|
||||
|
||||
if(time == 0) { //this should never trigger, but exists as a safety precaution
|
||||
//ParamnesticCure relies on the loggers for block information, as it takes time for these to process, the thread will have to wait
|
||||
ParamnesticCure.getInstance().getLogger().warning("A action didn't get tracked properly. Please contact plugin author");
|
||||
try {Thread.sleep(waitPeriod);}catch(InterruptedException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
waitPeriod *= 2;
|
||||
updateCreativeID(block,isCreative);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement addToDatabase = connection.prepareStatement(
|
||||
"INSERT INTO blockAction (time,world,x,y,z,is_creative)"
|
||||
+ " VALUES (?,?,?,?,?,?);"
|
||||
);
|
||||
|
||||
addToDatabase.setInt( 1, time);
|
||||
addToDatabase.setInt( 2, WorldManager.getWorldId( block.getWorld().getName() ));
|
||||
addToDatabase.setInt( 3, block.getX());
|
||||
addToDatabase.setInt( 4, block.getY());
|
||||
addToDatabase.setInt( 5, block.getZ());
|
||||
addToDatabase.setInt( 6, isCreative ? 1 : 0 );
|
||||
|
||||
|
||||
addToDatabase.execute();
|
||||
|
||||
|
||||
//plugin.getLogger().info("[Manual Debug] Added the block action into the database as " + (isCreative ? "creative" : "survival") );
|
||||
}catch(SQLException ex) {}
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param block
|
||||
* @param time the time of an action
|
||||
*
|
||||
* @return Is this block in the database?
|
||||
* 0 => No.
|
||||
* 1 => yes, but not this action.
|
||||
* 2 => yes, this action is already stored.
|
||||
*/
|
||||
public static int isInDatabase(Block block, int time) {
|
||||
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement getCreativeStatus = connection.prepareStatement(
|
||||
"SELECT time FROM blockAction INNER JOIN worlds"
|
||||
+ " ON blockAction.world = worlds.world_id"
|
||||
+ " WHERE world = ? AND x = ? AND y = ? AND z = ?"
|
||||
);
|
||||
getCreativeStatus.setString( 1, block.getWorld().getName() );
|
||||
getCreativeStatus.setInt( 2, block.getX() );
|
||||
getCreativeStatus.setInt( 3, block.getY() );
|
||||
getCreativeStatus.setInt( 4, block.getZ() );
|
||||
|
||||
ResultSet set = getCreativeStatus.executeQuery();
|
||||
|
||||
|
||||
if(set.next()) {
|
||||
do{
|
||||
if( set.getInt(1) == time ) // An action at the same timeperiod exist
|
||||
return 2;
|
||||
}while ( set.next() );
|
||||
|
||||
return 1; // No replica action was found
|
||||
}
|
||||
}
|
||||
catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges all data from the database older than specified time
|
||||
* @param time
|
||||
*/
|
||||
public static void purgeDatabase(int time) {
|
||||
|
||||
int oldestDataPoint = Math.round(System.currentTimeMillis()/1000) - time;//seconds
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement addToDatabase = connection.prepareStatement(
|
||||
"DELETE FROM blockAction"
|
||||
+ " WHERE time < ?"
|
||||
);
|
||||
|
||||
addToDatabase.setInt( 1, oldestDataPoint);
|
||||
|
||||
addToDatabase.execute();
|
||||
|
||||
|
||||
plugin.getLogger().info("[Purge] Purged the ParamnesticCure database");
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
}
|
||||
}
|
||||
+16
-2
@@ -11,13 +11,24 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
|
||||
/**
|
||||
* Keeps track of every world and changes the paramnestic database accordingly
|
||||
* @author Thorin
|
||||
*
|
||||
*/
|
||||
public class WorldManager {
|
||||
public class WorldListener implements Listener {
|
||||
/**
|
||||
* If a world get created, its name needs to get stored in the database. TODO I should also add something that tracks if the world was renamed
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler
|
||||
public void worldInit(WorldInitEvent event) {
|
||||
WorldListener.addWorldToDB(event.getWorld());
|
||||
}
|
||||
/**
|
||||
* Adds the world to the worlds table, which will assign it an id
|
||||
* @param world
|
||||
@@ -31,6 +42,8 @@ public class WorldManager {
|
||||
);
|
||||
statement.setString(1, world.getName());
|
||||
statement.execute();
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {}
|
||||
}
|
||||
/**
|
||||
@@ -50,7 +63,8 @@ public class WorldManager {
|
||||
ResultSet set = statement.executeQuery();
|
||||
if(set.next())
|
||||
output = set.getInt(1);
|
||||
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {}
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.block;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import static java.util.logging.Level.SEVERE;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
import com.mcsmp.WorldListener;
|
||||
|
||||
import me.prunt.restrictedcreative.RestrictedCreativeAPI;
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||
|
||||
/**
|
||||
* Consist of all the functions that track the location, the time, and the creative status of critical block actions
|
||||
* @author Frostalf
|
||||
* @author Thorin
|
||||
*/
|
||||
public class BlockListener implements Listener {
|
||||
|
||||
private static ParamnesticCure plugin = ParamnesticCure.getInstance();
|
||||
private static CoreProtectAPI coreprotect = plugin.getCoreProtect();
|
||||
|
||||
public static long waitPeriod = plugin.getConfig().getLong("Plugin_settings.wait_time");
|
||||
/**
|
||||
* @param event BlockBreakEvent
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true,priority = EventPriority.MONITOR)
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
generalBlockEventTrigger(event.getBlock(),true);
|
||||
}
|
||||
/**
|
||||
* @param event BlockPlaceEvent
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true,priority = EventPriority.MONITOR)
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
generalBlockEventTrigger(event.getBlock(),false);
|
||||
}
|
||||
/**
|
||||
* Fetches the creative id of the block, also takes care of a door bug
|
||||
* @param block the block affected
|
||||
* @param isBlockBreak
|
||||
*/
|
||||
private void generalBlockEventTrigger(Block block, boolean isBlockBreak) {
|
||||
|
||||
final BlockState blockState = block.getState();
|
||||
|
||||
//due to async thread limitations i have to define a variable like this
|
||||
final boolean extIsCreative = RestrictedCreativeAPI.isCreative(block);
|
||||
|
||||
ParamnesticCure.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(ParamnesticCure.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean isCreative = extIsCreative;
|
||||
/*
|
||||
* On blockplace events, it is important to wait a while so that the creative logger has time to register the block
|
||||
* whilst for blockbreak events, the status before the database updates is sought after.
|
||||
*/
|
||||
|
||||
if(!isBlockBreak)
|
||||
isCreative = RestrictedCreativeAPI.isCreative(block);
|
||||
|
||||
|
||||
if(!isCreative) return;
|
||||
BlockListener.updateCreativeID(block,isCreative);
|
||||
|
||||
|
||||
/*
|
||||
* Makes it so that both blocks for doors get updated
|
||||
*/
|
||||
if( blockState.getType().toString().contains("DOOR") ) {
|
||||
Location loc = blockState.getLocation();
|
||||
Bisected door = (Bisected) blockState.getBlockData();
|
||||
if(door.getHalf() == Bisected.Half.BOTTOM)
|
||||
loc = loc.add(0, 1, 0);
|
||||
else
|
||||
loc = loc.add(0,-1,0);
|
||||
|
||||
BlockListener.updateCreativeID(loc.getBlock(),isCreative);
|
||||
}
|
||||
}
|
||||
},waitPeriod);
|
||||
}
|
||||
/**
|
||||
* Checks through the coreprotect database for the most recent block place / remove action. It then calls a function that stores it (if the block fulfils the right criteria)
|
||||
*
|
||||
* @param block the block that is going to be inspected
|
||||
* @param isCreative whether the block was a creative block before the action occurred
|
||||
*/
|
||||
public static void updateCreativeID(Block block,boolean isCreative) {
|
||||
|
||||
|
||||
int time = 0;
|
||||
List<String[]> actiondataMsg = coreprotect.blockLookup(block,0);
|
||||
|
||||
for(String[] actionMsg : actiondataMsg) {
|
||||
ParseResult action = coreprotect.parseResult(actionMsg);
|
||||
plugin.getLogger().finer("[BlockTracker.updateCreativeID] Actionid = " + action.getActionId());
|
||||
if ( action.getActionId() > 2 ) continue; //has to be block place/break action
|
||||
|
||||
time = action.getTime();
|
||||
|
||||
break;//The returned data from parseResult seems to be ordered highest time to lowest, this should therefore return the most recent block action
|
||||
}
|
||||
updateCreativeID(time,block,isCreative);
|
||||
}
|
||||
/**
|
||||
* Stores the specified action if it was creative, or if there already has been a creative action already on it's location
|
||||
* @param time The time the action occurred according to coreprotect.
|
||||
* @param block
|
||||
* @param isCreative Whether the action had anything to do with a creative block
|
||||
*/
|
||||
public static void updateCreativeID(int time, Block block, boolean isCreative)
|
||||
{
|
||||
if(time == 0) {
|
||||
//this should never trigger, but exists as a safety precaution
|
||||
//ParamnesticCure relies on the loggers for block information, as it takes time for these to process, the thread will have to wait
|
||||
plugin.getLogger().warning("An action did not get tracked properly, please increase the wait time in Plugin_settings");
|
||||
plugin.getLogger().info("The wait time will temporarily be doubled, to avoid any further issues in this session");
|
||||
try {Thread.sleep(waitPeriod);}catch(InterruptedException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
waitPeriod *= 2;
|
||||
updateCreativeID(block,isCreative);
|
||||
return;
|
||||
}
|
||||
|
||||
ParamnesticCure.debug("BlockTracker.updateCreativeID"," storing a action at " + block.getWorld().getName() + "," + block.getX() +" "+ block.getY() +" "+ block.getZ() + " time = " + time + (isCreative? "creative":"survival"));
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(
|
||||
"INSERT INTO blockAction (time,world,x,y,z,is_creative)"
|
||||
+ " VALUES (?,?,?,?,?,?);"
|
||||
);
|
||||
|
||||
statement.setInt( 1, time);
|
||||
statement.setInt( 2, WorldListener.getWorldId( block.getWorld().getName()) );
|
||||
statement.setInt( 3, block.getX());
|
||||
statement.setInt( 4, block.getY());
|
||||
statement.setInt( 5, block.getZ());
|
||||
statement.setInt( 6, isCreative ? 1 : 0 );
|
||||
|
||||
|
||||
statement.execute();
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {
|
||||
ParamnesticCure.debug("BlockTracker.updateCreativeID"," Action has already been stored" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges all data from the database older than specified time
|
||||
* @param time
|
||||
*/
|
||||
public static void purgeDatabase(int time) {
|
||||
|
||||
int oldestDataPoint = Math.round(System.currentTimeMillis()/1000) - time;//seconds
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(
|
||||
"DELETE FROM blockAction"
|
||||
+ " WHERE time < ?"
|
||||
);
|
||||
|
||||
statement.setInt( 1, oldestDataPoint);
|
||||
|
||||
statement.execute();
|
||||
statement.close();
|
||||
connection.close();
|
||||
|
||||
plugin.getLogger().info("[Purge] Succesfully purged the ParamnesticCure database");
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.block;
|
||||
|
||||
import static java.util.logging.Level.SEVERE;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import com.mcsmp.MessageManager;
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
|
||||
|
||||
/**
|
||||
* An abstract class with methods that are shared between all loggerManagers, It also consist of some
|
||||
* methods that are used to create those loggerManagers.
|
||||
* @author Thorin
|
||||
*/
|
||||
public abstract class LoggerManager {
|
||||
|
||||
|
||||
protected CoreProtectAPI coreprotect;
|
||||
protected int time;
|
||||
protected List<String> restrict_users;
|
||||
protected List<String> exclude_users;
|
||||
protected List<Object> restrict_blocks;
|
||||
protected List<Object> exclude_blocks;
|
||||
protected List<Integer> action_list;
|
||||
protected int radius;
|
||||
protected Location location;
|
||||
protected MessageManager msgManager;
|
||||
protected boolean isCancelled = false;
|
||||
protected boolean isIntercept = true;
|
||||
private static ConfigurationSection configSektion = ParamnesticCure.getInstance().getConfig().getConfigurationSection("");
|
||||
|
||||
|
||||
/**
|
||||
* This function checks if any of the actions has been stored as creative and updates the creative status on that location
|
||||
* @param actions
|
||||
*/
|
||||
protected int changeCreativeStatus(HashMap<ParamnesticLocation,Integer> actions){
|
||||
int creativeBlockCounter = 0;
|
||||
for(ParamnesticLocation actionKey: actions.keySet()) {
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(
|
||||
"SELECT is_creative FROM blockAction INNER JOIN worlds"
|
||||
+ " ON blockAction.world = worlds.world_id"
|
||||
+ " WHERE time = ? AND worlds.world = ? AND x = ? AND y = ? AND z = ?"
|
||||
+ " ORDER BY time DESC"
|
||||
);
|
||||
statement.setInt(1, actions.get(actionKey));
|
||||
statement.setString(2, actionKey.getWorld().getName());
|
||||
statement.setInt(3, actionKey.getBlockX());
|
||||
statement.setInt(4, actionKey.getBlockY());
|
||||
statement.setInt(5, actionKey.getBlockZ());
|
||||
|
||||
ResultSet set = statement.executeQuery();
|
||||
boolean isCreative = false;
|
||||
if(set.next())
|
||||
if(set.getInt(1) == 1) // is_creative == 1 -> action was creative
|
||||
isCreative = true;
|
||||
|
||||
ParamnesticCure.debug("LoggerManager.ChangeCreativeStatus", "Selected location " + actionKey.getWorld().getName() + "," + actionKey.getBlockX() + "," + actionKey.getBlockY() + "," + actionKey.getBlockZ() + ",time=" + actions.get(actionKey));
|
||||
creativeBlockCounter += actionKey.setCreativeStatus(isCreative);
|
||||
statement.close();
|
||||
connection.close();
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
}
|
||||
return creativeBlockCounter;
|
||||
}
|
||||
/**
|
||||
* Interprets the argument, and assigns values to the proper blocks
|
||||
* @param arguments : The arguments of the command
|
||||
* @param location : location where command was thrown
|
||||
*/
|
||||
protected void interpretArguments(String[] arguments, Location location) {
|
||||
|
||||
|
||||
boolean checkForWeirdUserInput = false;
|
||||
|
||||
|
||||
for(String argument :arguments) {
|
||||
argument.replace(" ", "");
|
||||
if(isCancelled)
|
||||
break;
|
||||
if(timeInterpreter(argument))
|
||||
continue;
|
||||
if(userInterpreter(argument))
|
||||
continue;
|
||||
if(excludeInterpreter(argument))
|
||||
continue;
|
||||
if(radiusInterpreter(argument,location))
|
||||
continue;
|
||||
if(blockInterpreter(argument))
|
||||
continue;
|
||||
if(actionInterpreter(argument))
|
||||
continue;
|
||||
if(argument != ""){
|
||||
if(checkForWeirdUserInput) {
|
||||
msgManager.sendMessage("Invalid argument, redirecting to logger",true);
|
||||
isCancelled = true;
|
||||
isIntercept = false;
|
||||
return;
|
||||
}
|
||||
|
||||
checkForWeirdUserInput = true;
|
||||
this.restrict_users = new ArrayList<String>();
|
||||
this.restrict_users.add(argument);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ARGUMENT INTERPRETERS
|
||||
/**
|
||||
* Checks if it's a time argument, if so assigns a time
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean timeInterpreter(String argument) {
|
||||
List<String> timeAlias = configSektion.getStringList("blockLoggerCommands.arguments.time");
|
||||
argument = checkAndTrimArgument(argument,timeAlias);
|
||||
if(argument != "") {
|
||||
long time = 0;//s
|
||||
|
||||
//might as well, right?
|
||||
argument.replaceAll("seconds|second|sec", "s").replaceAll("minute|min","m").replaceAll("hours|hour", "h").replaceAll("days|day", "d").replaceAll("weeks|week", "w");
|
||||
String[] splitedArgument = argument.split("(?<=[w*d*h*m*s])");
|
||||
//convert to seconds
|
||||
try {
|
||||
for(String part : splitedArgument) {
|
||||
if(part.contains("w")){
|
||||
time += 604800 * Double.parseDouble(part.substring( 0 , part.indexOf('w') ));
|
||||
continue;
|
||||
}
|
||||
if(part.contains("d")){
|
||||
time += 86400 * Double.parseDouble(part.substring( 0 , part.indexOf('d') ));
|
||||
continue;
|
||||
}
|
||||
if(part.contains("h")){
|
||||
time += 3600 * Double.parseDouble(part.substring( 0 , part.indexOf('h') ));
|
||||
continue;
|
||||
}
|
||||
if(part.contains("m")){
|
||||
time += 60 * Double.parseDouble(part.substring( 0 , part.indexOf('m') ));
|
||||
continue;
|
||||
}
|
||||
if(part.contains("s")){
|
||||
time += Double.parseDouble(part.substring( 0 , part.indexOf('s') ));
|
||||
continue;
|
||||
}
|
||||
//this is another way to specify seconds in Coreprotect
|
||||
time += Double.parseDouble(part);
|
||||
|
||||
}
|
||||
}catch(NumberFormatException e) {
|
||||
msgManager.sendMessage("Invalid timeargument", true);
|
||||
isCancelled = true;
|
||||
}
|
||||
|
||||
this.time = Math.round(time);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's a user argument, if so assigns a list of all the users
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean userInterpreter(String argument) {
|
||||
List<String> userAlias = configSektion.getStringList("blockLoggerCommands.arguments.user");
|
||||
|
||||
argument = checkAndTrimArgument(argument,userAlias);
|
||||
if(argument != "") {
|
||||
this.restrict_users = new ArrayList<String>();
|
||||
|
||||
String[] argumentSplited = argument.split(",");
|
||||
for(String part : argumentSplited) {
|
||||
this.restrict_users.add(part);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's a exclude blocks argument, if so assigns a list of all the blocks that should be excluded
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean excludeInterpreter(String argument) {
|
||||
List<String> excludeAlias = configSektion.getStringList("blockLoggerCommands.arguments.exclude");
|
||||
argument = checkAndTrimArgument(argument,excludeAlias);
|
||||
if(argument != "") {
|
||||
exclude_blocks = blockStringListToBlockList(argument);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's a block argument, if so assigns a list of all the blocks that should be selected
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean blockInterpreter(String argument) {
|
||||
List<String> blockAlias = configSektion.getStringList("blockLoggerCommands.arguments.block");
|
||||
argument = checkAndTrimArgument(argument,blockAlias);
|
||||
if(argument != "") {
|
||||
restrict_blocks = blockStringListToBlockList(argument);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should (ehm ehm) be able to convert argument into a list of blockdata
|
||||
* @param argument
|
||||
* @return A list with blockdatatypes
|
||||
*/
|
||||
private List<Object> blockStringListToBlockList(String argument){
|
||||
List<Object> tempBlockList = new ArrayList<Object>();
|
||||
if(argument.chars().allMatch(Character::isWhitespace))
|
||||
return tempBlockList;
|
||||
String[] argumentSplited = argument.split(",");
|
||||
for(String part : argumentSplited) {
|
||||
try {
|
||||
tempBlockList.add( Bukkit.createBlockData(part) );
|
||||
}catch(Exception e) {
|
||||
isIntercept = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(tempBlockList.size() == 0) {
|
||||
if(isIntercept)
|
||||
msgManager.sendMessage("No block specified", true);
|
||||
else{
|
||||
msgManager.sendMessage("Entity selection has not yet been implemented",true);
|
||||
msgManager.sendMessage("Cancelling intercept...",false);
|
||||
}
|
||||
isCancelled = true;
|
||||
}
|
||||
else if(!isIntercept){
|
||||
msgManager.sendMessage("Entity selection has not yet been implemented",true);
|
||||
msgManager.sendMessage("Cancelling intercept, paramnestic will still trigger...",false);
|
||||
}
|
||||
|
||||
|
||||
return tempBlockList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's a radius argument, if so assigns radius and location of command
|
||||
* @param argument
|
||||
* @param radius_location the location where the command was issued, null => console
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean radiusInterpreter(String argument,Location location) {
|
||||
List<String> radiusAlias = configSektion.getStringList("blockLoggerCommands.arguments.radius");
|
||||
argument = checkAndTrimArgument(argument,radiusAlias);
|
||||
if(argument != "") {
|
||||
if(location == null) {
|
||||
msgManager.sendMessage("You can't use the radius argument from console",true);
|
||||
isCancelled = true;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
this.radius = Integer.parseInt(argument);
|
||||
this.location = location;
|
||||
}catch(Exception e) {
|
||||
msgManager.sendMessage("Invalid radius", true);
|
||||
isCancelled = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if its a action argument, translates the actions into integer and puts them into a list of actions
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean actionInterpreter(String argument) {
|
||||
List<String> actionAlias = configSektion.getStringList("blockLoggerCommands.arguments.action");
|
||||
argument = checkAndTrimArgument(argument,actionAlias);
|
||||
if(argument != "") {
|
||||
|
||||
this.action_list = new ArrayList<Integer>();
|
||||
String[] argumentSplited = argument.split(",");
|
||||
|
||||
for(String actionArgument : argumentSplited) {
|
||||
if(actionArgument.chars().allMatch(Character::isWhitespace))
|
||||
break;
|
||||
action_list.addAll(actionToInt(actionArgument));
|
||||
}
|
||||
if(isCancelled) {
|
||||
if(isIntercept)
|
||||
msgManager.sendMessage("No action specified", true);
|
||||
else {
|
||||
msgManager.sendMessage("Entity action selection not implemented yet",true);
|
||||
msgManager.sendMessage("Cancelling intercept...",false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* As of now, the only known action integers are block remove, block place and block interaction (0,1,2).
|
||||
* This just looks if its a block action, and with some hefty logic (if I say so myself) assigns the corresponding integers:
|
||||
* block (0,1), +block(1), -block(0). Default value is 2
|
||||
* @param action
|
||||
* @return a list off all the actions that this part of the argument implied
|
||||
*/
|
||||
private List<Integer> actionToInt(String action) {
|
||||
//TODO make this fit better with coreprotect logic
|
||||
List<Integer> output = new ArrayList<Integer>();
|
||||
if(action.contains("block"))
|
||||
{
|
||||
if(!action.contains("-"))
|
||||
output.add(1);//place action
|
||||
if(!action.contains("+"))
|
||||
output.add(0);//remove action
|
||||
}
|
||||
else if(action.chars().allMatch(Character::isWhitespace)) {
|
||||
isCancelled = true;
|
||||
}
|
||||
else {
|
||||
isIntercept = false;
|
||||
isCancelled = true;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function used in command processing, checks if the argument contains any alias and return the argument without its alias
|
||||
* @param argument
|
||||
* @param aliases
|
||||
* @return The argument without alias, or "" if there was no match
|
||||
*/
|
||||
private String checkAndTrimArgument(String argument,List<String> aliases) {
|
||||
Matcher matcher;
|
||||
Pattern pattern = null;
|
||||
|
||||
for(String alias : aliases) {
|
||||
|
||||
pattern = Pattern.compile("^" + alias + ":");
|
||||
matcher = pattern.matcher(argument);
|
||||
if(matcher.find()) {
|
||||
return matcher.replaceAll("");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function is shared between restores and rollbacks
|
||||
*/
|
||||
abstract boolean executeTask();
|
||||
/**
|
||||
* @return the interpreted time
|
||||
*/
|
||||
public int getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.block;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
|
||||
import me.prunt.restrictedcreative.RestrictedCreativeAPI;
|
||||
|
||||
/**
|
||||
* This is mainly a class of convenience, just adds a creative status to a location (which can later be used handily in a hashmap)
|
||||
* @author Thorin
|
||||
*/
|
||||
public class ParamnesticLocation extends Location{
|
||||
//This is needed for the current rollback / restore algorithm to work properly:
|
||||
// - When a block place action gets rollbacked it is always going to rollback to a survival block (air)
|
||||
// - When a block break action gets restored it is always going to restore to a survival block (air)
|
||||
private boolean canBeCreative = false;
|
||||
/**
|
||||
*
|
||||
* @param worldname
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param canBeCreative If this location can have a creative status
|
||||
*/
|
||||
public ParamnesticLocation(String worldname, int x, int y, int z,boolean canBeCreative) {
|
||||
super(Bukkit.getWorld(worldname),x,y,z);
|
||||
this.canBeCreative = canBeCreative;
|
||||
}
|
||||
/**
|
||||
* As i don't care if the canBeCreative status is the same for the to objects in an equals statement, I will redefine it
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof ParamnesticLocation)) {
|
||||
return false;
|
||||
} else {
|
||||
ParamnesticLocation that = (ParamnesticLocation)obj;
|
||||
return super.equals(that.clone());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* As I redefined the equals method, I have to change this function. The equals and hashCode method are closely interlinked.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the creative status in restrictedcreative, but also internally
|
||||
* @param isCreative
|
||||
*/
|
||||
public int setCreativeStatus(boolean isCreative) {
|
||||
isCreative = canBeCreative && isCreative;
|
||||
ParamnesticCure.debug("ParamnesticLocation.setCreativeStatus","Setting creative status as " + (isCreative?"creative":"survival"));
|
||||
|
||||
Block block = getBlock();
|
||||
if(isCreative) {
|
||||
RestrictedCreativeAPI.add(block);
|
||||
}
|
||||
else {
|
||||
RestrictedCreativeAPI.remove(block);
|
||||
}
|
||||
return isCreative?1:0;
|
||||
}
|
||||
}
|
||||
+34
-38
@@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
package com.mcsmp.block;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -11,6 +11,9 @@ import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.mcsmp.MessageManager;
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
|
||||
import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||
/**
|
||||
* Does a series of logical operations to minimise opportunities for restores to mess with creative block data.
|
||||
@@ -18,18 +21,18 @@ import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||
*
|
||||
* @author Thorin
|
||||
*/
|
||||
public class RestoreManager extends loggerManager {
|
||||
public class RestoreManager extends LoggerManager {
|
||||
/**
|
||||
* Constructor for RestoreManager
|
||||
* @param arguments : The arguments of the command
|
||||
* @param radius_location : location where command was thrown
|
||||
* @param location : location where command was thrown
|
||||
*/
|
||||
public RestoreManager(String[] arguments, Location radius_location,Player player) {
|
||||
public RestoreManager(String[] arguments, Location location,Player player) {
|
||||
|
||||
this.msgManager = new MessageManager(player,"Restore");
|
||||
this.coreprotect = ParamnesticCure.getInstance().getCoreProtect();
|
||||
|
||||
interpretArguments(arguments,radius_location);
|
||||
interpretArguments(arguments,location);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,23 +42,23 @@ public class RestoreManager extends loggerManager {
|
||||
*
|
||||
* It then checks through all the returned values, and selects the most recent action on every location,
|
||||
* To then call the changeCreativeStatus function on that action
|
||||
*
|
||||
* @return true if this should cancel the event
|
||||
*/
|
||||
@Override
|
||||
public void executeTask() {
|
||||
public boolean executeTask() {
|
||||
if(isCancelled)
|
||||
return isIntercept;
|
||||
ParamnesticCure.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(ParamnesticCure.getInstance(), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
//perform a restore and get a list of the actions specified
|
||||
List<String[]> blockActionListMSG = coreprotect.performRestore(
|
||||
time,restrict_users, exclude_users, restrict_blocks, exclude_blocks,action_list, radius, radius_location
|
||||
time,restrict_users, exclude_users, restrict_blocks, exclude_blocks,action_list, radius, location
|
||||
);
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
|
||||
msgManager.sendMessage( "Operationall time: " + String.valueOf( (endTime-startTime)*Math.pow(10, -9) ) , false);
|
||||
|
||||
|
||||
if(blockActionListMSG.size() == 0) {
|
||||
@@ -65,43 +68,36 @@ public class RestoreManager extends loggerManager {
|
||||
|
||||
|
||||
|
||||
HashMap<String,Integer> blocks_to_be_changed = new HashMap<String,Integer>();
|
||||
Integer creativeBlockCounter = 0;
|
||||
HashMap<ParamnesticLocation,Integer> blocks_to_be_changed = new HashMap<ParamnesticLocation,Integer>();
|
||||
|
||||
//Go through every action
|
||||
for(String[] parseMSG : blockActionListMSG) {
|
||||
ParseResult blockAction = coreprotect.parseResult(parseMSG);
|
||||
int newestTime = blockAction.getTime();
|
||||
|
||||
if(!blockAction.isRolledBack()) continue;
|
||||
|
||||
int x = blockAction.getX(); int y = blockAction.getY(); int z = blockAction.getZ();
|
||||
int newestTime = blockAction.getTime(); String worldname = blockAction.worldName();
|
||||
|
||||
String compareKey = String.valueOf(x) + "," + String.valueOf(y) + "," + String.valueOf(z) + worldname;
|
||||
if(blocks_to_be_changed.containsKey(compareKey))
|
||||
//Block can only be creative if blockAction.getActionId == 1 (block place)
|
||||
ParamnesticLocation compareKey = new ParamnesticLocation( blockAction.worldName() , blockAction.getX() , blockAction.getY() ,blockAction.getZ() , blockAction.getActionId() == 1);
|
||||
//Only the most recent action on every location should be selected
|
||||
if(blocks_to_be_changed.containsKey(compareKey))
|
||||
if(blocks_to_be_changed.get(compareKey) > newestTime)
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
blocks_to_be_changed.put( compareKey , newestTime );
|
||||
|
||||
boolean isCreative = fetchDBIsCreative(newestTime,worldname,x,y,z);
|
||||
|
||||
if(blockAction.getActionId() == 0) //Any blockbreak action will result in a survival block (air block)
|
||||
isCreative = false;
|
||||
|
||||
|
||||
creativeBlockCounter += isCreative? 1 : 0;
|
||||
changeCreativeStatus(x,y,z,worldname,isCreative);
|
||||
|
||||
blocks_to_be_changed.put( compareKey , newestTime );
|
||||
}
|
||||
|
||||
msgManager.sendMessage( String.valueOf(blockActionListMSG.size()) + " block actions were found, " + String.valueOf( blocks_to_be_changed.size() ) + " Blocks were set", false);
|
||||
msgManager.sendMessage(creativeBlockCounter.toString() + " blocks were set to creative", false);
|
||||
Integer creativeBlockCounter = changeCreativeStatus(blocks_to_be_changed);
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
msgManager.sendMessage( "Operational time: " + String.valueOf( endTime-startTime ) + "ms" , false);
|
||||
msgManager.sendMessage( String.valueOf(blockActionListMSG.size()) + " block "+ "action"+ (blockActionListMSG.size() == 1?"":"s") +" were found, " + String.valueOf( blocks_to_be_changed.size() ) + " Block"+ (blocks_to_be_changed.size() == 1?"":"s") + " were set"
|
||||
, false);
|
||||
msgManager.sendMessage(creativeBlockCounter.toString() + " Block"+ (creativeBlockCounter == 1?"":"s") +" were set to creative", false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
},60L);
|
||||
|
||||
return isIntercept;
|
||||
}
|
||||
|
||||
}
|
||||
+37
-30
@@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
package com.mcsmp.block;
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,13 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.mcsmp.MessageManager;
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
|
||||
/**
|
||||
* Does a series of logical operations to minimise opportunities for rollblacks to mess with creative block data.
|
||||
* Note that this does not include rollback interference with inventories!
|
||||
@@ -21,7 +25,7 @@ import org.bukkit.entity.Player;
|
||||
* @author InteriorCamping
|
||||
* @author Thorin
|
||||
*/
|
||||
public class RollbackManager extends loggerManager{
|
||||
public class RollbackManager extends LoggerManager{
|
||||
|
||||
/**
|
||||
* Constructor for RollbackManager
|
||||
@@ -44,65 +48,68 @@ public class RollbackManager extends loggerManager{
|
||||
*
|
||||
* It then checks through all the returned values, and selects the oldest action on every location,
|
||||
* To then call the changeCreativeStatus function on that action
|
||||
* @return true if this should cancel the event
|
||||
*/
|
||||
@Override
|
||||
public void executeTask() {
|
||||
|
||||
ParamnesticCure.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(ParamnesticCure.getInstance(), new Runnable() {
|
||||
public boolean executeTask() {
|
||||
if(isCancelled)
|
||||
return isIntercept;
|
||||
ParamnesticCure.getInstance().getServer().getScheduler().runTaskAsynchronously(ParamnesticCure.getInstance(), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
long startTime = System.nanoTime(); //nano Seconds
|
||||
long startTime = System.currentTimeMillis(); //nano Seconds
|
||||
List<String[]> blockActionListMSG = new ArrayList<String[]>();
|
||||
|
||||
//perform a rollback and get a list of the actions specified
|
||||
blockActionListMSG = coreprotect.performRollback(
|
||||
time,restrict_users, exclude_users, restrict_blocks, exclude_blocks,action_list, radius, radius_location
|
||||
time,restrict_users, exclude_users, restrict_blocks, exclude_blocks,action_list, radius, location
|
||||
);
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
|
||||
msgManager.sendMessage( "Operationall time: " + String.valueOf( (endTime-startTime)*Math.pow(10, -9) ) , false);
|
||||
|
||||
|
||||
|
||||
if(blockActionListMSG.size() == 0) {
|
||||
msgManager.sendMessage("No actions were found",true);
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String,Integer> blocks_to_be_changed = new HashMap<String,Integer>();
|
||||
Integer creativeBlockCounter = 0;
|
||||
HashMap<ParamnesticLocation,Integer> blocks_to_be_changed = new HashMap<ParamnesticLocation,Integer>();
|
||||
|
||||
|
||||
//Go through every action
|
||||
for(int i = blockActionListMSG.size()-1; i >= 0; i--){//cycles through the list backwards (should be slightly less costly)
|
||||
|
||||
ParseResult blockAction = coreprotect.parseResult(blockActionListMSG.get(i));
|
||||
|
||||
String worldname = blockAction.worldName();
|
||||
|
||||
int oldestTime = blockAction.getTime();
|
||||
int x = blockAction.getX(); int y = blockAction.getY(); int z = blockAction.getZ();
|
||||
|
||||
|
||||
|
||||
String compareKey = String.valueOf(x) + "," + String.valueOf(y) + "," + String.valueOf(z) + worldname;
|
||||
|
||||
|
||||
//Block can only be creative if blockAction.getActionId == 0 (block break)
|
||||
ParamnesticLocation compareKey = new ParamnesticLocation( blockAction.worldName() , blockAction.getX() , blockAction.getY() ,blockAction.getZ() , blockAction.getActionId() == 0);
|
||||
//Only the oldest action on every location should be selected
|
||||
if(blocks_to_be_changed.containsKey(compareKey))
|
||||
if(blocks_to_be_changed.get(compareKey) < oldestTime)
|
||||
continue;
|
||||
|
||||
blocks_to_be_changed.put( compareKey , oldestTime );
|
||||
|
||||
boolean isCreative = fetchDBIsCreative(oldestTime,worldname,x,y,z);
|
||||
|
||||
if (blockAction.getActionId() == 1)
|
||||
isCreative = false; //When a creative block place action is rollbacked, it will get removed. An airblock must have been before this action, which is survival
|
||||
creativeBlockCounter += isCreative ? 1 : 0;
|
||||
|
||||
changeCreativeStatus(x,y,z,worldname,isCreative);
|
||||
blocks_to_be_changed.put( compareKey , oldestTime );
|
||||
}
|
||||
msgManager.sendMessage( String.valueOf(blockActionListMSG.size()) + " block actions were found, " + String.valueOf( blocks_to_be_changed.size() ) + " Blocks were set", false);
|
||||
msgManager.sendMessage(creativeBlockCounter.toString() + " blocks were set to creative", false);
|
||||
|
||||
|
||||
Integer creativeBlockCounter = changeCreativeStatus(blocks_to_be_changed);
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
msgManager.sendMessage( "Operational time: " + String.valueOf( endTime-startTime ) + "ms", false);
|
||||
msgManager.sendMessage(
|
||||
String.valueOf(blockActionListMSG.size()) + " block "+ "action"+ (blockActionListMSG.size() == 1?"":"s") +" were found, " + String.valueOf( blocks_to_be_changed.size() ) + " Block"+ (blocks_to_be_changed.size() == 1?"":"s") + " were set"
|
||||
, false);
|
||||
msgManager.sendMessage(creativeBlockCounter.toString() + " Block"+ (creativeBlockCounter == 1?"":"s")+" were set to creative", false);
|
||||
}
|
||||
|
||||
},60L);
|
||||
});
|
||||
|
||||
return isIntercept;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.commands;
|
||||
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
import com.mcsmp.MessageManager;
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
import com.mcsmp.block.BlockListener;
|
||||
import com.mcsmp.block.RestoreManager;
|
||||
import com.mcsmp.block.RollbackManager;
|
||||
|
||||
/**
|
||||
* Tracks commands, and checks whether they should be intercepted
|
||||
* @author Frostalf
|
||||
* @author Thorin
|
||||
*/
|
||||
public class CommandListener implements Listener {
|
||||
|
||||
|
||||
private static HashMap<String,String[]> storedCommands = new HashMap<String,String[]>();
|
||||
|
||||
private ConfigurationSection configSektion;
|
||||
|
||||
/*
|
||||
* Constructor class
|
||||
* @param plugin Instance of the plugin.
|
||||
*/
|
||||
public CommandListener(ParamnesticCure plugin) {
|
||||
//
|
||||
configSektion = plugin.getConfig().getConfigurationSection("");
|
||||
}
|
||||
|
||||
|
||||
//EVENT HANDLERS
|
||||
|
||||
/**
|
||||
* Checks for commands that should be intercepted
|
||||
* @param event Command being processed
|
||||
*/
|
||||
@EventHandler
|
||||
public void playerCommand(PlayerCommandPreprocessEvent event) {
|
||||
String command = event.getMessage().toLowerCase();
|
||||
|
||||
command = command.replaceAll(": ", ":");
|
||||
String[] commandListed = command.split(" ");
|
||||
|
||||
|
||||
List<String> commandAlias = configSektion.getStringList("blockLoggerCommands.alias");
|
||||
|
||||
int i = 0;
|
||||
while(i < commandAlias.size()){
|
||||
//the first string from commandListed will have / in front, all commandAlias should as well:
|
||||
commandAlias.set( i , "/" + commandAlias.get(i) );
|
||||
i++;
|
||||
}
|
||||
|
||||
//Unnecessary to process already faulty commands
|
||||
if(!commandAlias.contains(commandListed[0])||commandListed.length < 2) return;
|
||||
|
||||
if(createLoggerManager(commandListed, event.getPlayer().getLocation(),event.getPlayer()))
|
||||
event.setCancelled(true);
|
||||
else
|
||||
ParamnesticCure.getInstance().getLogger().fine("[CommandTracker.playerComand] intercept cancelled");
|
||||
}
|
||||
/**
|
||||
* Checks for commands that should be intercepted
|
||||
* @param event Command being processed
|
||||
*/
|
||||
@EventHandler
|
||||
public void serverCommand(ServerCommandEvent event) {
|
||||
//if someone types that alias cancel it.
|
||||
String command = event.getCommand().toLowerCase();
|
||||
command = command.replaceAll(": ", ":");
|
||||
String[] commandListed = command.split(" ");
|
||||
|
||||
List<String> commandAlias = configSektion.getStringList("blockLoggerCommands.alias");
|
||||
|
||||
if(!commandAlias.contains(commandListed[0])||commandListed.length < 2) return;
|
||||
|
||||
|
||||
if(createLoggerManager(commandListed, null, null));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//INTERNAL FUNCTIONS
|
||||
|
||||
|
||||
/**
|
||||
* Interprets a part of the command to see if a rollback,restore,undo, or purge should be created
|
||||
* also does some relevant setup for those commands
|
||||
* @param command The arguments after the logger alias
|
||||
* @param location Location of the player (can be null)
|
||||
* @param playerOperator the player who initiated the command
|
||||
* @return true if command event should be cancelled
|
||||
*/
|
||||
private boolean createLoggerManager(String[] command, Location location, Player playerOperator) {
|
||||
|
||||
String operator = (playerOperator == null) ? null : playerOperator.getName();
|
||||
|
||||
|
||||
List<String> rollbackAlias = configSektion.getStringList("blockLoggerCommands.rollback");
|
||||
String[] arguments = Arrays.copyOfRange(command, 2, command.length);
|
||||
|
||||
if(rollbackAlias.contains(command[1])) {
|
||||
if(!PermissionManager.hasRollback(playerOperator)) return false;
|
||||
|
||||
RollbackManager rollback = new RollbackManager( arguments , location , playerOperator);
|
||||
if(!rollback.executeTask()) {
|
||||
ParamnesticCure.getInstance().getLogger().finest("[CommandTracker.createLoggerManager] this function is going to return false");
|
||||
return false;
|
||||
}
|
||||
storeCommand(operator,command);
|
||||
return true;
|
||||
}
|
||||
List<String> restoreAlias = configSektion.getStringList("blockLoggerCommands.restore");
|
||||
if(restoreAlias.contains(command[1])) {
|
||||
|
||||
if(!PermissionManager.hasRestore(playerOperator)) return false;
|
||||
|
||||
|
||||
RestoreManager restore = new RestoreManager( arguments, location , playerOperator );
|
||||
if(!restore.executeTask())
|
||||
return false;
|
||||
storeCommand(operator,command);
|
||||
return true;
|
||||
}
|
||||
List<String> undoAlias = configSektion.getStringList("blockLoggerCommands.undo");
|
||||
if(undoAlias.contains(command[1])) {
|
||||
if(!(PermissionManager.hasRollback(playerOperator)&&PermissionManager.hasRestore(playerOperator))) return false;
|
||||
//TODO make better undo's, that store location and takes time into consideration
|
||||
|
||||
String player = operator;
|
||||
|
||||
if(command.length == 3)
|
||||
player = command[2];
|
||||
else if(command.length > 3) {
|
||||
return false;
|
||||
}
|
||||
if (undoCommand(player, operator, location))
|
||||
return true;
|
||||
}
|
||||
List<String> purgeAlias = configSektion.getStringList("blockLoggerCommands.purge");
|
||||
if(purgeAlias.contains(command[1])) {
|
||||
if(!PermissionManager.hasPurge(playerOperator)) return false;
|
||||
|
||||
if(command.length > 3) {
|
||||
new MessageManager(playerOperator).sendMessage("Invalid argument " + command[1], true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//don't look here, this is stupid
|
||||
String[] temp = {command[2]};
|
||||
int time = (new RollbackManager(temp,null,null)).getTime();
|
||||
BlockListener.purgeDatabase(time);
|
||||
}
|
||||
List<String> helpAlias = configSektion.getStringList("blockLoggerCommands.help");
|
||||
if(helpAlias.contains(command[1]) && PermissionManager.hasHelp(playerOperator)) {
|
||||
//don't know if this is necessary
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This stores commands for the undo command
|
||||
* @param operator the player who initiated the command
|
||||
* @param command the type of logger command that was used
|
||||
* @param arguments the arguments of that command
|
||||
*/
|
||||
private void storeCommand(String operator, String[] commandListed) {
|
||||
String command = "";
|
||||
for(String argument:commandListed) command = command+" " + argument;
|
||||
storedCommands.put(operator, commandListed);
|
||||
}
|
||||
/**
|
||||
* This is the main logic done to convert a command to it's opposite, to then call the
|
||||
* createLoggerManager with the newly created command.
|
||||
*
|
||||
* This approximately undoes the previous command.
|
||||
* @param player the player which command should be undone
|
||||
* @param operator the player that initiated the command
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean undoCommand(String player,String operator,Location location) {
|
||||
ConfigurationSection configSektion = ParamnesticCure.getInstance().getConfig().getConfigurationSection("");
|
||||
if(storedCommands.containsKey(player)) {
|
||||
String[] commandListed = storedCommands.get(player);
|
||||
|
||||
List<String> rbAlias = configSektion.getStringList("blockLoggerCommands.rollback");
|
||||
List<String> reAlias = configSektion.getStringList("blockLoggerCommands.restore");
|
||||
if(rbAlias.contains(commandListed[1]))
|
||||
commandListed[1] = reAlias.get(0);
|
||||
else
|
||||
commandListed[1] = rbAlias.get(0);
|
||||
|
||||
String command = "";
|
||||
for(String argument:commandListed) command = command+" " + argument;
|
||||
|
||||
Player playerPlayer = Bukkit.getServer().getPlayer(player);
|
||||
//if the createLoggerManager does take the command as intercept
|
||||
if(!createLoggerManager(commandListed, location, playerPlayer))
|
||||
return false;
|
||||
storeCommand(operator,commandListed);
|
||||
return true;
|
||||
}
|
||||
Player playerOperator = (operator == null)? null : Bukkit.getServer().getPlayer(operator);
|
||||
|
||||
new MessageManager(playerOperator).sendMessage("Could not find the user " + player,true);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.commands;
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
*/
|
||||
|
||||
|
||||
public class CommandManager {
|
||||
|
||||
}
|
||||
+3
-1
@@ -3,10 +3,12 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
package com.mcsmp.commands;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.mcsmp.ParamnesticCure;
|
||||
/**
|
||||
* We all know what this does
|
||||
* @author Thorin
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.commands;
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
*/
|
||||
|
||||
|
||||
public class reloadCommand {
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp.database;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import static java.net.InetAddress.getByName;
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
*/
|
||||
|
||||
|
||||
public class DataBases {
|
||||
|
||||
private String name;
|
||||
private String databaseName;
|
||||
private String address;
|
||||
private int port;
|
||||
private String user;
|
||||
private String password;
|
||||
private String driver;
|
||||
private DatabaseCheck databaseConnection;
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* Connects to a certain database.
|
||||
* @param name Name of the plugin this database pertains to.
|
||||
* @param databaseName Name of the database being checked.
|
||||
* @param address Address of the database being checked.
|
||||
* @param port Port on which to communicate with the database being checked.
|
||||
* @param user User to use when communicating with the database.
|
||||
* @param password Password to be used when communicating with the database as provided user.
|
||||
* @param driver Driver to use for this database communication.
|
||||
* @param location db file location.
|
||||
*/
|
||||
public DataBases(String name, String databaseName, String address, int port, String user, String password, String driver, String location) {
|
||||
this.name = name;
|
||||
this.databaseName = databaseName;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
this.driver = driver.toLowerCase();
|
||||
this.location = location;
|
||||
this.databaseConnection = new DatabaseCheck(name, databaseName, address, port, user, password, driver, location);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Config name of database.
|
||||
*/
|
||||
|
||||
public String getConfigName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return Name of database in question.
|
||||
*/
|
||||
public String getDatabaseName() {
|
||||
return this.databaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return Address of database in question.
|
||||
* @throws java.net.UnknownHostException if the host being connected to is unknown.
|
||||
*/
|
||||
public InetAddress getAddress() throws UnknownHostException {
|
||||
return getByName(this.address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return Port of database in question.
|
||||
*/
|
||||
public Integer getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return User of database in question.
|
||||
*/
|
||||
public String getUser() {
|
||||
return this.user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return Password of database in question.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks status of database being interacted with.
|
||||
* @return Driver being used for connection.
|
||||
*/
|
||||
public String getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check database connection.
|
||||
* @return Current database connection.
|
||||
*/
|
||||
//public Connection getConnection() throws SQLException {
|
||||
// return this.databaseConnection.getConnection();
|
||||
//}
|
||||
|
||||
public DatabaseCheck getDatabase() {
|
||||
return this.databaseConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the current database.
|
||||
* @param query SQL query expression.
|
||||
* @return returns the results of the SQL query.
|
||||
* @throws java.sql.SQLException any error with the sql query
|
||||
*/
|
||||
public ResultSet getResults(String query) throws SQLException {
|
||||
return this.databaseConnection.getConnection().createStatement().executeQuery(query);
|
||||
}
|
||||
}
|
||||
+39
-45
@@ -11,6 +11,8 @@ import com.mcsmp.ParamnesticCure;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import static org.bukkit.Bukkit.getPluginManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
@@ -18,62 +20,51 @@ import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* @author Frostalf
|
||||
* @author Thorin
|
||||
*/
|
||||
public class DatabaseCheck {
|
||||
public class SqlManager {
|
||||
|
||||
private HikariDataSource boneCP;
|
||||
private Connection connection;
|
||||
|
||||
private HikariConfig config = null;
|
||||
private ParamnesticCure plugin = ParamnesticCure.getInstance();
|
||||
private String database;
|
||||
private String address;
|
||||
private int port;
|
||||
private String user;
|
||||
private String password;
|
||||
private String driver;
|
||||
private final String database;
|
||||
private final String address;
|
||||
private final int port;
|
||||
private final String driver;
|
||||
private String url;
|
||||
private boolean mysql = false;
|
||||
private String location;
|
||||
|
||||
private final boolean mysql;
|
||||
|
||||
/**
|
||||
* Caches and checks the status of a certain database..
|
||||
* @param name Name of the plugin this database pertains to.
|
||||
* @param database Name of the database being checked.
|
||||
* @param driver Driver to use for this database communication.
|
||||
* @param address Address of the database being checked.
|
||||
* @param port Port on which to communicate with the database being checked.
|
||||
* @param user User to use when communicating with the database.
|
||||
* @param password Password to be used when communicating with the database as provided user.
|
||||
* @param driver Driver to use for this database communication.
|
||||
* @param location location of db file.
|
||||
* @param database Name of the database being checked.
|
||||
*/
|
||||
public DatabaseCheck(String name, String database, String address, int port, String user, String password, String driver, String location) {
|
||||
this.location = location;
|
||||
public SqlManager(String driver, String address, int port, String database) {
|
||||
|
||||
this.database = database;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
if(user == null || user.chars().allMatch(Character::isWhitespace)) {
|
||||
this.user = "default";
|
||||
} else {
|
||||
this.user = user;
|
||||
}
|
||||
this.password = password;
|
||||
this.driver = setDriver(driver).toString();
|
||||
|
||||
this.port = port;
|
||||
this.address = address;
|
||||
if(getDriver() == DriverEnum.SQLITE) {
|
||||
try {
|
||||
setupSQLITE(location);
|
||||
setupSQLITE();
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(DatabaseCheck.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(SqlManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
mysql = false;
|
||||
} else {
|
||||
mysql = true;
|
||||
try {
|
||||
setupMySQL();
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(DatabaseCheck.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(SqlManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +82,7 @@ public class DatabaseCheck {
|
||||
if (mysql) {
|
||||
return connection = this.boneCP.getConnection();
|
||||
}
|
||||
plugin.getLogger().log(Level.INFO, "{0} {1} {2}", new Object[]{this.url, this.user, this.database, this.connection.toString()});
|
||||
plugin.getLogger().log(Level.INFO, "{0} {1} {2}", new Object[]{this.url, this.database, this.connection.toString()});
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
@@ -112,17 +103,24 @@ public class DatabaseCheck {
|
||||
}
|
||||
|
||||
private void setupMySQL() throws SQLException {
|
||||
final int MAXCONNECT = 20;
|
||||
this.config = new HikariConfig();
|
||||
this.config.setMaximumPoolSize(MAXCONNECT);
|
||||
this.config.setUsername(this.user);
|
||||
this.config.setPassword(this.password);
|
||||
ParamnesticCure.getInstance().getLogger().info("[DatabaseCheck.setupMySQL] Values: " + this.driver + "," + this.address + "," + this.port + "," + this.database);
|
||||
//Creates a properties file if it doesn't exist
|
||||
if ( !new File(plugin.getDataFolder(), "hikari.properties").exists() ) {
|
||||
plugin.getLogger().warning("[Startup] hikari.properties file is missing.");
|
||||
plugin.getLogger().info("Providing you with a new properties file");
|
||||
plugin.getDataFolder().mkdirs();
|
||||
plugin.saveResource("hikari.properties", true);
|
||||
getPluginManager().disablePlugin(plugin);
|
||||
}
|
||||
|
||||
//creates a config based on the properties file
|
||||
this.config = new HikariConfig(plugin.getDataFolder()+"/hikari.properties");
|
||||
|
||||
|
||||
config.setJdbcUrl("jdbc:"+ this.driver +"://" + this.address + ":" + this.port + "/" + this.database);
|
||||
try {
|
||||
Class.forName("com.mysql.jdbc.Driver");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(DatabaseCheck.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(SqlManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
|
||||
|
||||
@@ -131,18 +129,14 @@ public class DatabaseCheck {
|
||||
|
||||
private File dbFile;
|
||||
|
||||
private void setupSQLITE(String location) throws SQLException {
|
||||
if (location.chars().allMatch(Character::isWhitespace)) {
|
||||
dbFile = new File(plugin.getDataFolder().getAbsoluteFile(), this.database + ".db");
|
||||
} else {
|
||||
dbFile = new File(location, this.database + ".db");
|
||||
}
|
||||
private void setupSQLITE() throws SQLException {
|
||||
dbFile = new File(plugin.getDataFolder().getAbsoluteFile(), this.database + ".db");
|
||||
|
||||
this.url = ("jdbc:sqlite:" + dbFile.getAbsoluteFile());
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(DatabaseCheck.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(SqlManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
DriverManager.registerDriver(new org.sqlite.JDBC());
|
||||
}
|
||||
@@ -1,474 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.mcsmp;
|
||||
|
||||
import static java.util.logging.Level.SEVERE;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.prunt.restrictedcreative.RestrictedCreativeAPI;
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
|
||||
|
||||
/**
|
||||
* An abstract class with methods that are shared between all loggerManagers, It also consist of some
|
||||
* methods that are used to create those loggerManagers.
|
||||
* @author Thorin
|
||||
*/
|
||||
public abstract class loggerManager {
|
||||
|
||||
|
||||
protected CoreProtectAPI coreprotect;
|
||||
protected int time;
|
||||
protected List<String> restrict_users;
|
||||
protected List<String> exclude_users;
|
||||
protected List<Object> restrict_blocks;
|
||||
protected List<Object> exclude_blocks;
|
||||
protected List<Integer> action_list;
|
||||
protected int radius;
|
||||
protected Location radius_location;
|
||||
protected MessageManager msgManager;
|
||||
private static HashMap<String,String[]> storedCommands = new HashMap<String,String[]>();
|
||||
private static ConfigurationSection configSektion = ParamnesticCure.getInstance().getConfig().getConfigurationSection("");
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks the database if this action has been stored as creative
|
||||
* @param time The time of action
|
||||
* @param worldName
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return true if a creative action at this time and location was stored in the database
|
||||
*/
|
||||
protected boolean fetchDBIsCreative(int time, String worldName, int x, int y, int z) {
|
||||
try {
|
||||
Connection connection = ParamnesticCure.getInstance().getConnection();
|
||||
PreparedStatement getCreativeStatus = connection.prepareStatement(
|
||||
"SELECT is_creative FROM blockAction INNER JOIN worlds"
|
||||
+ " ON blockAction.world = worlds.world_id"
|
||||
+ " WHERE time = ? AND worlds.world = ? AND x = ? AND y = ? AND z = ?"
|
||||
+ " ORDER BY time DESC"
|
||||
);
|
||||
getCreativeStatus.setInt(1, time);
|
||||
getCreativeStatus.setString(2, worldName );
|
||||
getCreativeStatus.setInt(3, x);
|
||||
getCreativeStatus.setInt(4, y);
|
||||
getCreativeStatus.setInt(5, z);
|
||||
|
||||
ResultSet set = getCreativeStatus.executeQuery();
|
||||
if(set.next()) return (set.getInt(1) == 1); // is_creative = 1 -> action was creative
|
||||
}catch(SQLException ex) {ParamnesticCure.getInstance().getLogger().log(SEVERE, ex.getMessage(), ex.getCause());}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an action as input, then calls a function which adds the block into the
|
||||
* database (an important function if you want restores to work properly).
|
||||
*
|
||||
* It also updates the creative status on the location
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param worldname
|
||||
* @param DBCreativeStatus true if this location should be set to creative
|
||||
*/
|
||||
protected void changeCreativeStatus(Integer x, Integer y, Integer z, String worldname, boolean DBCreativeStatus) {
|
||||
|
||||
|
||||
List<World> worldlist = ParamnesticCure.getInstance().getServer().getWorlds();
|
||||
World world = null;
|
||||
for (World worldTest : worldlist) {
|
||||
if(worldTest.getName().equals(worldname)) { world = worldTest; break; }
|
||||
}
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
|
||||
//to prevent issues on restores as some actions would not have been tracked otherways
|
||||
if(RestrictedCreativeAPI.isCreative(block)) {
|
||||
TrackedBlocks.updateCreativeID(block, true);
|
||||
}
|
||||
|
||||
if(DBCreativeStatus) {
|
||||
RestrictedCreativeAPI.add(block);
|
||||
|
||||
}
|
||||
else {
|
||||
RestrictedCreativeAPI.remove(block);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Interprets a part of the command to see if a rollback,restore,undo, or purge should be created
|
||||
* Whether this method fits better in the listener class is unclear
|
||||
* @param command The arguments after the logger alias
|
||||
* @param location Location of the player (can be null)
|
||||
* @param playerOperator the player who initiated the command
|
||||
* @return true if command event should be cancelled
|
||||
*/
|
||||
static public boolean createLoggerManager(String[] command, Location location, Player playerOperator) {
|
||||
|
||||
String operator = (playerOperator == null) ? null : playerOperator.getName();
|
||||
|
||||
|
||||
List<String> rollbackAlias = configSektion.getStringList("blockLoggerCommands.rollback");
|
||||
String[] arguments = Arrays.copyOfRange(command, 2, command.length);
|
||||
|
||||
if(rollbackAlias.contains(command[1])) {
|
||||
if(!PermissionManager.hasRollback(playerOperator)) return false;
|
||||
|
||||
RollbackManager rollback = new RollbackManager( arguments , location , playerOperator);
|
||||
rollback.executeTask();
|
||||
storeCommand(operator,command);
|
||||
return true;
|
||||
}
|
||||
List<String> restoreAlias = configSektion.getStringList("blockLoggerCommands.restore");
|
||||
if(restoreAlias.contains(command[1])) {
|
||||
|
||||
if(!PermissionManager.hasRestore(playerOperator)) return false;
|
||||
|
||||
|
||||
RestoreManager restore = new RestoreManager( arguments, location , playerOperator );
|
||||
restore.executeTask();
|
||||
storeCommand(operator,command);
|
||||
return true;
|
||||
}
|
||||
List<String> undoAlias = configSektion.getStringList("blockLoggerCommands.undo");
|
||||
if(undoAlias.contains(command[1])) {
|
||||
if(!(PermissionManager.hasRollback(playerOperator)&&PermissionManager.hasRestore(playerOperator))) return false;
|
||||
//TODO make better undo's, that store location and takes time into consideration
|
||||
String player = operator;
|
||||
if(command.length == 3)
|
||||
player = command[2];
|
||||
else if(command.length > 3) {
|
||||
return false;
|
||||
}
|
||||
if (undoCommand(player, operator, location))
|
||||
return true;
|
||||
}
|
||||
List<String> purgeAlias = configSektion.getStringList("blockLoggerCommands.purge");
|
||||
if(purgeAlias.contains(command[1])) {
|
||||
if(!PermissionManager.hasPurge(playerOperator)) return false;
|
||||
|
||||
if(command.length > 3) {
|
||||
new MessageManager(playerOperator).sendMessage("Invalid argument " + command[1], true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//don't look here, this is stupid
|
||||
String[] temp = {command[2]};
|
||||
int time = (new RollbackManager(temp,null,null)).time;
|
||||
TrackedBlocks.purgeDatabase(time);
|
||||
}
|
||||
List<String> helpAlias = configSektion.getStringList("blockLoggerCommands.help");
|
||||
if(helpAlias.contains(command[1]) && PermissionManager.hasHelp(playerOperator)) {
|
||||
//don't know if this is necessary
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* This stores commands for the undo command
|
||||
* @param operator the player who initiated the command
|
||||
* @param command the type of logger command that was used
|
||||
* @param arguments the arguments of that command
|
||||
*/
|
||||
static private void storeCommand(String operator, String[] commandListed) {
|
||||
String command = "";
|
||||
for(String argument:commandListed) command = command+" " + argument;
|
||||
storedCommands.put(operator, commandListed);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main logic done to convert a command to it's opposite, to then call the
|
||||
* createLoggerManager with the newly created command.
|
||||
*
|
||||
* This approximately undoes the previous command.
|
||||
* @param player the player which command should be undone
|
||||
* @param operator the player that initiated the command
|
||||
* @return true if successful
|
||||
*/
|
||||
static private boolean undoCommand(String player,String operator,Location location) {
|
||||
ConfigurationSection configSektion = ParamnesticCure.getInstance().getConfig().getConfigurationSection("");
|
||||
if(storedCommands.containsKey(player)) {
|
||||
String[] commandListed = storedCommands.get(player);
|
||||
|
||||
List<String> rbAlias = configSektion.getStringList("blockLoggerCommands.rollback");
|
||||
List<String> reAlias = configSektion.getStringList("blockLoggerCommands.restore");
|
||||
if(rbAlias.contains(commandListed[1]))
|
||||
commandListed[1] = reAlias.get(0);
|
||||
else
|
||||
commandListed[1] = rbAlias.get(0);
|
||||
|
||||
String command = "";
|
||||
for(String argument:commandListed) command = command+" " + argument;
|
||||
|
||||
Player playerPlayer = Bukkit.getServer().getPlayer(player);
|
||||
|
||||
createLoggerManager(commandListed, location, playerPlayer);
|
||||
storeCommand(operator,commandListed);
|
||||
return true;
|
||||
}
|
||||
Player playerOperator = (operator == null)? null : Bukkit.getServer().getPlayer(operator);
|
||||
|
||||
new MessageManager(playerOperator).sendMessage("Could not find the user " + player,true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets the argument, and assigns values to the proper blocks
|
||||
* @param arguments : The arguments of the command
|
||||
* @param radius_location : location where command was thrown
|
||||
*/
|
||||
protected void interpretArguments(String[] arguments, Location radius_location) {
|
||||
|
||||
|
||||
boolean checkForWeirdUserInput = false;
|
||||
|
||||
|
||||
for(String argument :arguments) {
|
||||
argument.replace(" ", "");
|
||||
|
||||
if(timeInterpreter(argument))
|
||||
continue;
|
||||
if(userInterpreter(argument))
|
||||
continue;
|
||||
if(excludeInterpreter(argument))
|
||||
continue;
|
||||
if(radiusInterpreter(argument,radius_location))
|
||||
continue;
|
||||
if(blockInterpreter(argument))
|
||||
continue;
|
||||
if(actionInterpreter(argument))
|
||||
continue;
|
||||
if(argument != ""){
|
||||
if(checkForWeirdUserInput) {
|
||||
msgManager.sendMessage("Invalid argument ''" + argument+"''",true);
|
||||
return;
|
||||
}
|
||||
|
||||
checkForWeirdUserInput = true;
|
||||
this.restrict_users = new ArrayList<String>();
|
||||
this.restrict_users.add(argument);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ARGUMENT INTERPRETERS
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean timeInterpreter(String argument) {
|
||||
List<String> timeAlias = configSektion.getStringList("blockLoggerCommands.arguments.time");
|
||||
argument = checkAndTrimArgument(argument,timeAlias);
|
||||
if(argument != "") {
|
||||
long time = 0;//s
|
||||
|
||||
|
||||
|
||||
String[] splitedArgument = argument.split("(?<=[w*d*h*m*s])");
|
||||
//convert to seconds
|
||||
for(String part : splitedArgument) {
|
||||
if(part.contains("w")){
|
||||
time += 604800 * Double.parseDouble(part.substring( 0 , part.indexOf('w') ));
|
||||
}
|
||||
if(part.contains("d")){
|
||||
time += 86400 * Double.parseDouble(part.substring( 0 , part.indexOf('d') ));
|
||||
}
|
||||
if(part.contains("h")){
|
||||
time += 3600 * Double.parseDouble(part.substring( 0 , part.indexOf('h') ));
|
||||
}
|
||||
if(part.contains("m")){
|
||||
time += 60 * Double.parseDouble(part.substring( 0 , part.indexOf('m') ));
|
||||
}
|
||||
if(part.contains("s")){
|
||||
time += Double.parseDouble(part.substring( 0 , part.indexOf('s') ));
|
||||
}
|
||||
}
|
||||
this.time = Math.round(time);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean userInterpreter(String argument) {
|
||||
List<String> userAlias = configSektion.getStringList("blockLoggerCommands.arguments.user");
|
||||
|
||||
argument = checkAndTrimArgument(argument,userAlias);
|
||||
if(argument != "") {
|
||||
|
||||
this.restrict_users = new ArrayList<String>();
|
||||
|
||||
String[] argumentSplited = argument.split(",");
|
||||
for(String part : argumentSplited) {
|
||||
this.restrict_users.add(part);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean excludeInterpreter(String argument) {
|
||||
List<String> excludeAlias = configSektion.getStringList("blockLoggerCommands.arguments.exclude");
|
||||
argument = checkAndTrimArgument(argument,excludeAlias);
|
||||
if(argument != "") {
|
||||
|
||||
this.exclude_blocks = new ArrayList<Object>();
|
||||
String[] argumentSplited = argument.split(",");
|
||||
for(String part : argumentSplited) { this.exclude_blocks.add( Bukkit.createBlockData(part) ); }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @param radius_location the location where the command was issued, null => console
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean radiusInterpreter(String argument,Location radius_location) {
|
||||
List<String> radiusAlias = configSektion.getStringList("blockLoggerCommands.arguments.radius");
|
||||
argument = checkAndTrimArgument(argument,radiusAlias);
|
||||
if(argument != "") {
|
||||
if(radius_location == null)
|
||||
msgManager.sendMessage(" You can't use the radius argument from the console",true);
|
||||
this.radius = Integer.parseInt(argument);
|
||||
this.radius_location = radius_location;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean blockInterpreter(String argument) {
|
||||
List<String> blockAlias = configSektion.getStringList("blockLoggerCommands.arguments.block");
|
||||
argument = checkAndTrimArgument(argument,blockAlias);
|
||||
if(argument != "") {
|
||||
|
||||
this.restrict_blocks = new ArrayList<Object>();
|
||||
String[] argumentSplited = argument.split(",");
|
||||
|
||||
for(String material : argumentSplited) {
|
||||
this.restrict_blocks.add( Material.getMaterial("material:" + material) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argument
|
||||
* @return true if there was a match
|
||||
*/
|
||||
private boolean actionInterpreter(String argument) {
|
||||
List<String> actionAlias = configSektion.getStringList("blockLoggerCommands.arguments.action");
|
||||
argument = checkAndTrimArgument(argument,actionAlias);
|
||||
if(argument != "") {
|
||||
|
||||
this.action_list = new ArrayList<Integer>();
|
||||
String[] argumentSplited = argument.split(",");
|
||||
for(String actionArgument : argumentSplited) {
|
||||
for(Integer action:actionToInt(actionArgument))
|
||||
action_list.add(action);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* As of now, the only known action integers are block remove, block place and block interaction (0,1,2).
|
||||
* This just looks if its a block action, and with some hefty logic (if I say so myself) assigns the corresponding integers:
|
||||
* block (0,1), +block(1), -block(0). Default value is 2
|
||||
* @param action
|
||||
* @return a list off all the actions that this part of the argument implied
|
||||
*/
|
||||
private List<Integer> actionToInt(String action) {
|
||||
//TODO add numbers for all the other alternatives
|
||||
List<Integer> output = null;
|
||||
if(action.contains("block"))
|
||||
{
|
||||
output = new ArrayList<Integer>();
|
||||
if(!action.contains("-"))
|
||||
output.add(1);//place action
|
||||
if(!action.contains("+"))
|
||||
output.add(0);//remove action
|
||||
}
|
||||
else {
|
||||
output = new ArrayList<Integer>();
|
||||
output.add(2);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function used in command processing, checks if the argument contains any alias and return the argument without its alias
|
||||
* @param argument
|
||||
* @param aliases
|
||||
* @return The argument without alias, or "" if there was no match
|
||||
*/
|
||||
private String checkAndTrimArgument(String argument,List<String> aliases) {
|
||||
Matcher matcher;
|
||||
Pattern pattern = null;
|
||||
|
||||
for(String alias : aliases) {
|
||||
|
||||
pattern = Pattern.compile("^" + alias + ":");
|
||||
matcher = pattern.matcher(argument);
|
||||
if(matcher.find()) {
|
||||
return matcher.replaceAll("");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function is shared between restores and rollbacks
|
||||
*/
|
||||
abstract void executeTask();
|
||||
|
||||
|
||||
}
|
||||
@@ -56,34 +56,28 @@ blockLoggerCommands:
|
||||
block:
|
||||
- b
|
||||
- block
|
||||
# The permessions for the blocklogger
|
||||
blockLoggerPermissions:
|
||||
rollback: coreprotect.rollback
|
||||
purge: coreprotect.purge
|
||||
restore: coreprotect.restore
|
||||
help: coreprotect.help
|
||||
# Default information used when a value in Database_Names is blank ("")
|
||||
# Please ensure that all three of the databases you intend to use have already been configured by your logger and creative manager.
|
||||
defaultconnection:
|
||||
|
||||
# All database config for the database of paramnestic
|
||||
Database:
|
||||
# Database type
|
||||
driver: Sqlite
|
||||
# Database location
|
||||
address: localhost
|
||||
# Port used by your db.
|
||||
port: 3306
|
||||
# Username with which to connect to the db.
|
||||
user: 'root'
|
||||
# Password for that username.
|
||||
password: 'pass'
|
||||
# Databases for us to send specific requests to.
|
||||
# Paramnestic requires all three databases to be running, set up, and seperate to function.
|
||||
Database_Names:
|
||||
# The database for Paramnestic to store its own data.
|
||||
# (ParamnesticCure)
|
||||
paramnestic:
|
||||
database: "paramnestic"
|
||||
location: ""
|
||||
driver: ""
|
||||
address: ""
|
||||
port: ""
|
||||
user: ""
|
||||
password: ""
|
||||
# The name for the database
|
||||
databasename: "paramnestic"
|
||||
|
||||
|
||||
Plugin_settings:
|
||||
# The time between the ocurence of the action and when it's going to be logged
|
||||
# Keep it high if you dont want any issues to arise
|
||||
wait_time: 100
|
||||
# For development
|
||||
debug: false
|
||||
@@ -0,0 +1,6 @@
|
||||
#Paramnestic Hikari Datasource Properties for advanced database Configuration
|
||||
dataSource.user=default
|
||||
dataSource.password=pas
|
||||
dataSource.cachePrepStmts=true
|
||||
dataSource.prepStmtCacheSize=250
|
||||
dataSource.prepStmtCacheSqlLimit=2048
|
||||
Reference in new issue
Block a user