diff --git a/.poggit.yml b/.poggit.yml index f18d160b..252a4469 100644 --- a/.poggit.yml +++ b/.poggit.yml @@ -4,7 +4,11 @@ projects: icon: resources/bedcoreprotect_logo.png libs: - src: poggit/libasynql/libasynql - version: ^3.2.0 + version: 3.2.0 - src: JackMD/UpdateNotifier/UpdateNotifier - version: ^1.0.0 + version: 1.0.0 + - src: matcracker/FormLib/FormLib + version: 1.1.0 + - src: SOF3/await-generator/await-generator + version: 2.2.0 ... diff --git a/plugin.yml b/plugin.yml index 8ae59ed7..092bfd3d 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,11 +1,12 @@ name: BedcoreProtect main: matcracker\BedcoreProtect\Main -version: 0.4.2 +version: 0.5.0 api: [3.4.0] mcpe-protcol: - 354 - 361 +softdepend: BlockSniper load: POSTWORLD author: matcracker description: "BedcoreProtect is a fast, efficient, data logging and anti-griefing tool for PocketMine server. Rollback and restore any amount of damage" @@ -32,4 +33,6 @@ permissions: bcp.subcommand.restore: description: "Allows the user to run the sub-command /bedcoreprotect restore" bcp.subcommand.purge: - description: "Allows the user to run the sub-command /bedcoreprotect purge" \ No newline at end of file + description: "Allows the user to run the sub-command /bedcoreprotect purge" + bcp.subcommand.menu: + description: "Allows the user to run the sub-command /bedcoreprotect menu" \ No newline at end of file diff --git a/resources/config.yml b/resources/config.yml index 906eb038..1cfda3c7 100644 --- a/resources/config.yml +++ b/resources/config.yml @@ -1,4 +1,7 @@ -#BedcoreProtect Config +# Plugin language +language: eng + +# Database settings database: # The database type. "sqlite" and "mysql" are supported. type: sqlite @@ -16,6 +19,9 @@ database: password: "" # The database name where plugin stores data. schema: + # The maximum number of simultaneous SQL queries + # Recommended: 1 for sqlite, 2 for MySQL. You may want to further increase this value if your MySQL connection is very slow. + worker-limit: 1 # The timezone where you are located. This is necessary to correctly log the time of events. # To find your timezone, check here: https://www.php.net/manual/en/timezones.php @@ -64,7 +70,7 @@ block-ignite: true # Logs explosions, such as TNT and Creepers. explosions: true -# Track when an entity changes a block, such as an Enderman destroying blocks. (NOT FULLY IMPLEMENTED BY POCKETMINE YET) +# Track when an entity changes a block, such as an Enderman destroying blocks. (NOT FULLY IMPLEMENTED IN POCKETMINE YET) entity-change: true # Logs killed entities, such as killed cows and enderman. @@ -79,13 +85,13 @@ buckets: true # Logs natural tree leaves decay. leaves-decay: true -# Logs tree growth. Trees are linked to the player who planted the sappling. (NOT IMPLEMENTED BY POCKETMINE YET) +# Logs tree growth. Trees are linked to the player who planted the sappling. (NOT IMPLEMENTED IN POCKETMINE YET) tree-growth: true -# Logs mushroom growth. (NOT IMPLEMENTED BY POCKETMINE YET) +# Logs mushroom growth. (NOT IMPLEMENTED IN POCKETMINE YET) mushroom-growth: true -# Logs natural vine growth. (NOT IMPLEMENTED BY POCKETMINE YET) +# Logs natural vine growth. (NOT IMPLEMENTED IN POCKETMINE YET) vine-growth: true # Logs water flow. If water destroys other blocks, such as torches, @@ -108,3 +114,6 @@ item-transactions: true # Track player interactions, such as when a player opens a door, presses # a button, or opens a chest. Player interactions can't be rolled back. player-interactions: true + +# Logs changes made via the plugin "BlockSniper" if it's in use on your server. +blocksniper-hook: true diff --git a/resources/languages/eng.ini b/resources/languages/eng.ini new file mode 100644 index 00000000..53392847 --- /dev/null +++ b/resources/languages/eng.ini @@ -0,0 +1,119 @@ +action.place = placed +action.break = broke +action.click = clicked +action.kill = killed +action.add = added +action.remove = removed +blocksniper.hook.success = BlockSniper properly hooked! +blocksniper.hook.no-hook = Unable to hook BlockSniper. Check if the plugin has been properly enabled. +command.description = It runs the BedcoreProtect commands. +command.usage = Usage: /bcp help to display commands list +command.no-permission = You don't have permission to run this command. +command.reload.success = Plugin configuration reloaded. +command.reload.no-success = Plugin configuration not reloaded due to some errors. Check your console to see the errors. Until you fix them, it will be used the old configuration. +command.status.version = Version: §f{%0} +command.status.database-connection = Database connection: §f{%0} +command.status.database-version = Database version: §f{%0} +command.status.blocksniper-hook = BlockSniper hook: §f{%0} +command.status.author = Author: §f{%0} +command.status.website = Website: §f{%0} +command.error.no-numeric-value = You need to insert a numeric value. +command.error.one-parameter = You must add at least one parameter. +command.error.no-console = You can't run this command from console. +command.purge.started = Data purge started. This may take some time. +command.purge.no-restart = Do not restart your server until completed. +command.purge.success = Data purge successful. +command.purge.deleted-rows = {%0} rows of data deleted. +command.inspect.enabled = Enabled inspector mode. +command.inspect.disabled = Disabled inspector mode. +command.near.range-value = The near value must be between 1 and {%0}! +command.rollback.started = Rollback started on "{%0}". +command.restore.started = Restore started on "{%0}". +command.help.title = Help Page +command.help.help = Display more info for that command. +command.help.help2 = Displays a list of all commands. +command.help.menu = Allows to use commands with a graphic interface. +command.help.inspect = Turns the blocks inspector on or off. +command.help.inspect1 = With the inspector enabled, you can do the following: +command.help.inspect2 = Left-click a block to see who placed that block. +command.help.inspect3 = Right-click a block to see what adjacent block was removed. +command.help.inspect4 = Place a block to see what block was removed at the location. +command.help.inspect5 = Place a block in liquid (etc) to see who placed it. +command.help.inspect6 = Right-click on a door, chest, etc, to see who last used it. +command.help.inspect7 = Tip: You can use just §3"/bcp i"§7 for quicker access. +command.help.parameters1 = Perform the command {%0}. +command.help.parameters2 = Specify the user(s) to {%0}. +command.help.parameters3 = Specify the amount of time to {%0}. +command.help.parameters4 = Specify a radius area to limit the {%0} to. +command.help.parameters5 = Restrict the {%0} to a certain action. +command.help.parameters6 = Restrict the {%0} to certain block types. +command.help.parameters7 = Exclude blocks/users from the {%0}. +command.help.parameters8 = Please see §3"/bcp help "§7 for detailed parameter info. +command.help.radius-example = Only make changes within 10 blocks of you +command.help.rollback = Rollback block data. +command.help.restore = Restore block data. +command.help.lookup = Advanced block data lookup. +command.help.lookup1 = Use after inspecting a block to view different logs pages. +command.help.lookup2 = Use after inspecting a block to view more lines of logs in a page. +command.help.lookup3 = Please see "/bcp help params" for detailed parameters. +command.help.purge = Delete old block data. +command.help.purge1 = Delete data older than specified time. +command.help.purge2 = For example, "/bcp purge t:30d" will delete all data older than one month, and only keep the last 30 days of data. +command.help.reload = Reloads the configuration file. +command.help.status = Displays the plugin status. +command.help.examples = Examples +command.help.shortcut = Command shortcut. +command.help.block-names = Block names +command.help.info-not-found = Information for command "/bcp help {%0}" not found. +database.version.higher = Your database is running a higher version than BedcoreProtect. Please update the plugin if you want to use it. +database.version.updated = Your database is now updated from v{%0} to v{%1}. +database.connection.fail = Could not connect to the database! Check your connection, database settings or plugin configuration file. +form.menu.title = Main Menu +form.menu.option = Select an option: +form.menu.inspector = Enable/Disable inspector mode +form.menu.lookup = Lookup data +form.menu.purge = Purge data +form.menu.reload = Reload plugin +form.menu.status = Show plugin status +form.purge-menu.time = Delete data older than +form.input-menu.required-fields = Required fields: +form.input-menu.optional-fields = Optional fields: +form.input-menu.time = Time +form.input-menu.radius = Radius +form.input-menu.user-entity = User/Entity name +form.input-menu.user-entity-placeholder = Insert player name or #entity +form.input-menu.restrict-blocks = Restrict blocks (accepts ID:meta) +form.input-menu.exclude-blocks = Exclude blocks (accepts ID:meta) +general.action = Action +general.rollback = Rollback +general.restore = Restore +general.lookup = Lookup +generic.yes = Yes +generic.no = No +inspector.no-data = No block data found for this location. +inspector.more-lines = The lines number must be greater than 1. +inspector.page-not-exist = The page §6{%0}§c does not exist! +inspector.page = Page {%0}/{%1} +inspector.view-old-data = View older data by typing +language.name = English +parser.few-many-parameters = You are using too few or too many parameters (Max: {%0}) +parser.invalid-parameter = Please specify a valid parameter. ({%0}). +parser.no-entity = The entity "{%0}" does not exist. (The name is case-sensitive) +parser.no-player = The player "{%0}" does not exist. +parser.invalid-amount-time = Please specify the amount of time. +parser.invalid-amount-radius = Please specify the amount of radius. +parser.invalid-radius = Please specify a valid radius. +parser.invalid-action = Please specify a valid action. +parser.invalid-block-include = Invalid block "{%0}" to include. +parser.invalid-block-exclude = Invalid block "{%0}" to exclude. +parser.missing-parameters = You are missing one of the following parameters: {%0} +rollback.completed = Rollback completed for {%0}. +rollback.date = Rolled back {%0}. +rollback.radius = Radius: {%0} block(s). +rollback.blocks = Approx. {%0} block(s) changed. +rollback.items = Approx. {%0} item(s) changed. +rollback.entities = Approx. {%0} entities(s) changed. +rollback.modified-chunks = Modified {%0} chunk(s). +rollback.time-taken = Time taken: {%0} second(s). +restore.completed = Restore completed for {%0}. +restore.date = Restored {%0}. \ No newline at end of file diff --git a/resources/languages/ita.ini b/resources/languages/ita.ini new file mode 100644 index 00000000..5cab44af --- /dev/null +++ b/resources/languages/ita.ini @@ -0,0 +1,119 @@ +action.place = ha piazzato +action.break = ha rotto +action.click = ha cliccato +action.kill = ha ucciso +action.add = ha aggiunto +action.remove = ha rimosso +blocksniper.hook.success = BlockSniper agganciato correttamente! +blocksniper.hook.no-hook = Non è possibile aggangiare BlockSniper. Controlla se il plugin è abilitato. +command.description = Esegue i comandi di BedcoreProtect. +command.usage = Usa: /bcp help per mostrare la lista di comandi +command.no-permission = Non hai il permesso di eseguire questo comando. +command.reload.success = Configurazione del plugin ricaricate. +command.reload.no-success = Configurazione del plugin non ricaricata a causa di alcuni errori. Controlla la console per vederli. Finchè non li sistemerai, verrà usata la vecchia configurazione. +command.status.version = Versione: §f{%0} +command.status.database-connection = Connessione database: §f{%0} +command.status.database-version = Versione database: §f{%0} +command.status.blocksniper-hook = BlockSniper agganciato: §f{%0} +command.status.author = Autore: §f{%0} +command.status.website = Sito web: §f{%0} +command.error.no-numeric-value = Devi inserire un valore numerico. +command.error.one-parameter = Devi almeno aggiungere un parametro. +command.error.no-console = Non puoi eseguire questo comando dalla console. +command.purge.started = Eliminazione dei dati iniziata. Potrebbe richiedere del tempo. +command.purge.no-restart = Non riavviare il server finchè non sarà completato. +command.purge.success = Eliminazione dei dati eseguita con successo. +command.purge.deleted-rows = {%0} righe di dati eliminati. +command.inspect.enabled = Abilitata modalià ispettore. +command.inspect.disabled = Disabilitata modalità ispettore. +command.near.range-value = IL valore del raggio deve essere compreso tra 1 e {%0}! +command.rollback.started = Rollback iniziato in "{%0}". +command.restore.started = Ripristino iniziato in "{%0}". +command.help.title = Pagina d'aiuto +command.help.help = Mostra più informazioni per questo comando. +command.help.help2 = Mostra una lista di tutti i comandi. +command.help.menu = Permette di usare i comandi con una interfaccia grafica. +command.help.inspect = Attiva/Disattiva l'ispettore dei blocchi. +command.help.inspect1 = Con l'ispettore abilitato, puoi fare le seguenti cose: +command.help.inspect2 = Click sinistro su un blocco per vedere chi ha piazzato quel blocco. +command.help.inspect3 = Click destro su un blocco per vedere il blocco adiacente rimosso. +command.help.inspect4 = Piazza un blocco per vedere quale blocco è stato rimosso in quella posizione. +command.help.inspect5 = Piazza un blocco in un liquido (etc) per vedere chi l'ha piazzato. +command.help.inspect6 = Click destro su una porta, cassa, etc, per vedere chi l'ha usata per ultimo. +command.help.inspect7 = Suggerimento: puoi usare §3"/bcp i"§7 per un accesso rapido. +command.help.parameters1 = Esegue il comando {%0}. +command.help.parameters2 = Specifica l'utente/i da {%0}. +command.help.parameters3 = Specifica la quantità di tempo da {%0}. +command.help.parameters4 = Specifica un raggio per limitare la {%0}. +command.help.parameters5 = Restringe il {%0} in una certa azione. +command.help.parameters6 = Restringe il {%0} in alcuni tipi di blocco. +command.help.parameters7 = Esclude blocchi/utenti dal {%0}. +command.help.parameters8 = Per favore vedi §3"/bcp help "§7 per informazioni dettagliate. +command.help.radius-example = Esegue cambiamenti solo nei 10 blocchi vicini a te +command.help.rollback = Rollback dati dei blocchi. +command.help.restore = Ripristina dati dei blocchi. +command.help.lookup = Consultazione avanzata dei dati dei blocchi. +command.help.lookup1 = Usa dopo aver ispezionato un blocco per vedere pagine di log differenti. +command.help.lookup2 = Usa dopo aver ispezionato un blocco per vedere più righe di log in una pagina. +command.help.lookup3 = Per favore vedi "/bcp help params" per il dettaglio dei parametri. +command.help.purge = Cancella vecchi dati dei blocchi. +command.help.purge1 = Cancella dati più vecchi del tempo specificato. +command.help.purge2 = Per esempio, "/bcp purge t:30d" cancellerà tutti i dati pù vecchi di un mese, e manterrà sono gli ultimi 30 giorni di dati. +command.help.reload = Ricarica la configurazione del plugin. +command.help.status = Mostra lo stato del plugin. +command.help.examples = Esempi +command.help.shortcut = Scorciatoia del comando. +command.help.block-names = Nomi dei blocchi +command.help.info-not-found = Informazioni per il comando "/bcp help {%0}" non trovate. +database.version.higher = Il tuo database sta eseguendo una versione più aggiornata di BedcoreProtect. Per favore aggiorna il tuo plugin se vuoi usarlo. +database.version.updated = Il tuo database è stato aggiornato dalla versione v{%0} alla v{%1}. +database.connection.fail = Impossibile connettersi al database! Controlla la tua connessione, impostazioni del database o la configurazione del plugin. +form.menu.title = Menu principale +form.menu.option = Seleziona un'opzione: +form.menu.inspector = Attiva/Disattiva modalità ispettore +form.menu.lookup = Consulta i dati +form.menu.purge = Elimina dati +form.menu.reload = Ricarica il plugin +form.menu.status = Mostra stato del plugin +form.purge-menu.time = Elimina dati più vecchi di +form.input-menu.required-fields = Campi richiesti: +form.input-menu.optional-fields = Campi opzionali: +form.input-menu.time = Tempo +form.input-menu.radius = Raggio +form.input-menu.user-entity = Nome dell'utente/entità +form.input-menu.user-entity-placeholder = Inserisci nome del giocatore o #entità +form.input-menu.restrict-blocks = Restringi blocks (accetta ID:meta) +form.input-menu.exclude-blocks = Escludi blocchi (accetta ID:meta) +general.action = Azione +general.rollback = Rollback +general.restore = Ripristino +general.lookup = Consulta +generic.yes = Si +generic.no = No +inspector.no-data = Nessun dato trovato in questa posizione. +inspector.more-lines = Il numero di linee deve essere più grande di 1. +inspector.page-not-exist = La pagina §6{%0}§c non esiste! +inspector.page = Pagina {%0}/{%1} +inspector.view-old-data = Vedi i dati vecchi scrivendo +language.name = Italiano +parser.few-many-parameters = You are using too few or too many parameters (Max: {%0}) +parser.invalid-parameter = Per favore specifica un parametro valido. ({%0}). +parser.no-entity = L'entità "{%0}" non esiste (il nome è case-sensitive) +parser.no-player = Il giocatore "{%0}" non esiste. +parser.invalid-amount-time = Per favore specifica la quantità del tempo. +parser.invalid-amount-radius = Per favore specifica la quantità del raggio. +parser.invalid-radius = Per favore specifica un raggio valido. +parser.invalid-action = Per favore specifica un'azione valida. +parser.invalid-block-include = Blocco "{%0}" invalido da includere. +parser.invalid-block-exclude = Blocco "{%0}" invalido da escludere. +parser.missing-parameters = Stai dimenticando uno dei seguenti paramentri: {%0} +rollback.completed = Rollback completato per {%0}. +rollback.date = Rolled back {%0}. +rollback.radius = Raggio: {%0} block(s). +rollback.blocks = Circa {%0} blocco/hi cambiato/i. +rollback.items = Circa. {%0} oggetto/i cambiato/i. +rollback.entities = Circa {%0} entità cambiate. +rollback.modified-chunks = Modificato/i {%0} chunk. +rollback.time-taken = Tempo impiegato: {%0} secondo/i. +restore.completed = Ripristino completato per {%0}. +restore.date = Ripristinato {%0}. \ No newline at end of file diff --git a/resources/mysql.sql b/resources/mysql.sql index fa8f66bb..88622231 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -4,55 +4,44 @@ -- # {entities CREATE TABLE IF NOT EXISTS entities ( - uuid VARCHAR(36) UNIQUE NOT NULL PRIMARY KEY, - entity_name VARCHAR(16) NOT NULL, - entity_classpath TEXT NOT NULL, - address VARCHAR(15) DEFAULT '127.0.0.1' -); --- # } --- # {blocks -CREATE TABLE IF NOT EXISTS blocks -( - id INTEGER UNSIGNED NOT NULL, - meta TINYINT(2) UNSIGNED NOT NULL, - block_name VARCHAR(30) NOT NULL, - PRIMARY KEY (id, meta) + uuid VARCHAR(36) UNIQUE PRIMARY KEY NOT NULL, + entity_name VARCHAR(16) NOT NULL, + entity_classpath TEXT NOT NULL, + address VARCHAR(15) DEFAULT '127.0.0.1' NOT NULL ); -- # } -- # {log_history CREATE TABLE IF NOT EXISTS log_history ( - log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - who VARCHAR(36) NOT NULL, - x BIGINT NOT NULL, - y TINYINT UNSIGNED NOT NULL, - z BIGINT NOT NULL, - world_name VARCHAR(255) NOT NULL, - action TINYINT UNSIGNED NOT NULL, - time TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP, - rollback BOOLEAN DEFAULT FALSE, + log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, + who VARCHAR(36) NOT NULL, + x BIGINT NOT NULL, + y TINYINT UNSIGNED NOT NULL, + z BIGINT NOT NULL, + world_name VARCHAR(255) NOT NULL, + action TINYINT UNSIGNED NOT NULL, + time TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL, + rollback BOOLEAN DEFAULT FALSE NOT NULL, FOREIGN KEY (who) REFERENCES entities (uuid) ); -- # } -- # {blocks_log CREATE TABLE IF NOT EXISTS blocks_log ( - history_id BIGINT UNSIGNED, - old_block_id INTEGER UNSIGNED NOT NULL, - old_block_meta TINYINT(2) UNSIGNED NOT NULL, - old_block_nbt LONGBLOB DEFAULT NULL, - new_block_id INTEGER UNSIGNED NOT NULL, - new_block_meta TINYINT(2) UNSIGNED NOT NULL, - new_block_nbt LONGBLOB DEFAULT NULL, - FOREIGN KEY (history_id) REFERENCES log_history (log_id) ON DELETE CASCADE, - FOREIGN KEY (old_block_id, old_block_meta) REFERENCES blocks (id, meta), - FOREIGN KEY (new_block_id, new_block_meta) REFERENCES blocks (id, meta) + history_id BIGINT UNSIGNED NOT NULL, + old_id INTEGER UNSIGNED NOT NULL, + old_meta TINYINT(2) UNSIGNED NOT NULL, + old_nbt LONGBLOB DEFAULT NULL, + new_id INTEGER UNSIGNED NOT NULL, + new_meta TINYINT(2) UNSIGNED NOT NULL, + new_nbt LONGBLOB DEFAULT NULL, + FOREIGN KEY (history_id) REFERENCES log_history (log_id) ON DELETE CASCADE ); -- # } -- # {entities_log CREATE TABLE IF NOT EXISTS entities_log ( - history_id BIGINT UNSIGNED, + history_id BIGINT UNSIGNED NOT NULL, entityfrom_uuid VARCHAR(36) NOT NULL, entityfrom_id INTEGER UNSIGNED NOT NULL, entityfrom_nbt LONGBLOB DEFAULT NULL, @@ -63,19 +52,28 @@ CREATE TABLE IF NOT EXISTS entities_log -- # {inventories_log CREATE TABLE IF NOT EXISTS inventories_log ( - history_id BIGINT UNSIGNED, - slot TINYINT UNSIGNED NOT NULL, - old_item_id INTEGER UNSIGNED DEFAULT 0, - old_item_meta TINYINT(2) UNSIGNED DEFAULT 0, - old_item_nbt LONGBLOB DEFAULT NULL, - old_item_amount TINYINT UNSIGNED DEFAULT 0, - new_item_id INTEGER UNSIGNED DEFAULT 0, - new_item_meta TINYINT(2) UNSIGNED DEFAULT 0, - new_item_nbt LONGBLOB DEFAULT NULL, - new_item_amount TINYINT UNSIGNED DEFAULT 0, + history_id BIGINT UNSIGNED NOT NULL, + slot TINYINT UNSIGNED NOT NULL, + old_id INTEGER UNSIGNED DEFAULT 0 NOT NULL, + old_meta TINYINT(2) UNSIGNED DEFAULT 0 NOT NULL, + old_nbt LONGBLOB DEFAULT NULL, + old_amount TINYINT UNSIGNED DEFAULT 0 NOT NULL, + new_id INTEGER UNSIGNED DEFAULT 0 NOT NULL, + new_meta TINYINT(2) UNSIGNED DEFAULT 0 NOT NULL, + new_nbt LONGBLOB DEFAULT NULL, + new_amount TINYINT UNSIGNED DEFAULT 0 NOT NULL, FOREIGN KEY (history_id) REFERENCES log_history (log_id) ON DELETE CASCADE ); -- # } +-- # {db_status +CREATE TABLE IF NOT EXISTS status +( + only_one_row BOOLEAN PRIMARY KEY DEFAULT TRUE NOT NULL, + version VARCHAR(20) NOT NULL, + upgraded_on TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL, + CHECK (only_one_row) +); +-- # } -- # } -- # {add -- # {entity @@ -87,14 +85,11 @@ INSERT INTO entities (uuid, entity_name, entity_classpath, address) VALUES (:uuid, :name, :path, :address) ON DUPLICATE KEY UPDATE address=:address; -- # } --- # {block --- # :id int --- # :meta int --- # :name string -INSERT INTO blocks (id, meta, block_name) -VALUES (:id, :meta, :name) -ON DUPLICATE KEY UPDATE id=VALUES(id), - meta=VALUES(meta); +-- # {db_version +-- # :version string +INSERT INTO status (version) +VALUES (:version) +ON DUPLICATE KEY UPDATE version=version; -- # } -- # {log -- # {main @@ -108,60 +103,148 @@ INSERT INTO log_history(who, x, y, z, world_name, action) VALUES ((SELECT uuid FROM entities WHERE uuid = :uuid), :x, :y, :z, :world_name, :action); -- # } --- # {to_block --- # :old_block_id int --- # :old_block_meta int --- # :old_block_nbt ?string --- # :new_block_id int --- # :new_block_meta int --- # :new_block_nbt ?string -INSERT INTO blocks_log(history_id, old_block_id, old_block_meta, old_block_nbt, new_block_id, new_block_meta, - new_block_nbt) -VALUES (LAST_INSERT_ID(), - (SELECT id FROM blocks WHERE blocks.id = :old_block_id AND meta = :old_block_meta), - (SELECT meta FROM blocks WHERE blocks.id = :old_block_id AND meta = :old_block_meta), - :old_block_nbt, - (SELECT id FROM blocks WHERE blocks.id = :new_block_id AND meta = :new_block_meta), - (SELECT meta FROM blocks WHERE blocks.id = :new_block_id AND meta = :new_block_meta), - :new_block_nbt); +-- # {block +-- # :old_id int +-- # :old_meta int +-- # :old_nbt ?string +-- # :new_id int +-- # :new_meta int +-- # :new_nbt ?string +INSERT INTO blocks_log(history_id, old_id, old_meta, old_nbt, new_id, new_meta, + new_nbt) +VALUES (LAST_INSERT_ID(), :old_id, :old_meta, :old_nbt, :new_id, :new_meta, + :new_nbt); -- # } --- # {to_entity +-- # {entity -- # :uuid string -- # :id int -- # :nbt ?string INSERT INTO entities_log(history_id, entityfrom_uuid, entityfrom_id, entityfrom_nbt) VALUES (LAST_INSERT_ID(), (SELECT uuid FROM entities WHERE uuid = :uuid), :id, :nbt); -- # } --- # {to_inventory +-- # {inventory -- # :slot int --- # :old_item_id int 0 --- # :old_item_meta int 0 --- # :old_item_nbt ?string --- # :old_item_amount int 0 --- # :new_item_id int 0 --- # :new_item_meta int 0 --- # :new_item_nbt ?string --- # :new_item_amount int 0 -INSERT INTO inventories_log(history_id, slot, old_item_id, old_item_meta, old_item_nbt, old_item_amount, new_item_id, - new_item_meta, new_item_nbt, new_item_amount) -VALUES (LAST_INSERT_ID(), :slot, :old_item_id, :old_item_meta, :old_item_nbt, :old_item_amount, :new_item_id, - :new_item_meta, :new_item_nbt, :new_item_amount); +-- # :old_id int 0 +-- # :old_meta int 0 +-- # :old_nbt ?string +-- # :old_amount int 0 +-- # :new_id int 0 +-- # :new_meta int 0 +-- # :new_nbt ?string +-- # :new_amount int 0 +INSERT INTO inventories_log(history_id, slot, old_id, old_meta, old_nbt, old_amount, new_id, + new_meta, new_nbt, new_amount) +VALUES (LAST_INSERT_ID(), :slot, :old_id, :old_meta, :old_nbt, :old_amount, :new_id, + :new_meta, :new_nbt, :new_amount); -- # } --- # {update_entity_id --- # :log_id int --- # :entity_id int +-- # } +-- # } +-- # {update +-- # {entity_id +-- # :log_id int +-- # :entity_id int UPDATE entities_log SET entityfrom_id = :entity_id WHERE history_id = :log_id; --- # } +-- # } +-- # {db_version +-- # :version string +UPDATE status +SET version = :version, + upgraded_on = DEFAULT +LIMIT 1; +-- # } +-- # {rollback_status +-- # :rollback bool +-- # :log_ids list:int +UPDATE log_history +SET rollback = :rollback +WHERE log_id IN :log_ids; -- # } -- # } -- # {get +-- # {db_status +SELECT * +FROM status +LIMIT 1; +-- # } -- # {log -- # {last_id SELECT MAX(log_id) AS lastId FROM log_history; -- # } +-- # {old_blocks +-- # :log_ids list:int +SELECT history_id, + bl.old_id, + bl.old_meta, + bl.old_nbt, + x, + y, + z, + world_name +FROM log_history + INNER JOIN blocks_log bl ON log_history.log_id = bl.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {new_blocks +-- # :log_ids list:int +SELECT history_id, + bl.new_id, + bl.new_meta, + bl.new_nbt, + x, + y, + z, + world_name +FROM log_history + INNER JOIN blocks_log bl ON log_history.log_id = bl.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {old_inventories +-- # :log_ids list:int +SELECT history_id, + il.slot, + il.old_id, + il.old_meta, + il.old_nbt, + il.old_amount, + x, + y, + z +FROM log_history + INNER JOIN inventories_log il ON log_history.log_id = il.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {new_inventories +-- # :log_ids list:int +SELECT history_id, + il.slot, + il.new_id, + il.new_meta, + il.new_nbt, + il.new_amount, + x, + y, + z +FROM log_history + INNER JOIN inventories_log il ON log_history.log_id = il.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {entities +-- # :log_ids list:int +SELECT e.entity_classpath, + el.entityfrom_id, + el.entityfrom_nbt, + x, + y, + z, + action +FROM log_history + INNER JOIN entities_log el ON log_history.log_id = el.history_id + INNER JOIN entities e ON e.uuid = el.entityfrom_uuid +WHERE log_id IN :log_ids; +-- # } -- # {block -- # :min_x int -- # :max_x int @@ -170,12 +253,12 @@ FROM log_history; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT bl.old_block_id, - bl.old_block_meta, - bl.old_block_nbt, - bl.new_block_id, - bl.new_block_meta, - bl.new_block_nbt, +SELECT bl.old_id, + bl.old_meta, + bl.old_nbt, + bl.new_id, + bl.new_meta, + bl.new_nbt, e.entity_name AS entity_from, x, y, @@ -230,12 +313,12 @@ ORDER BY time DESC; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT bl.old_block_id, - bl.old_block_meta, - bl.old_block_nbt, - bl.new_block_id, - bl.new_block_meta, - bl.new_block_nbt, +SELECT bl.old_id, + bl.old_meta, + bl.old_nbt, + bl.new_id, + bl.new_meta, + bl.new_nbt, e1.entity_name AS entity_from, e2.entity_name AS entity_to, x, @@ -265,14 +348,14 @@ ORDER BY time DESC; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT il.old_item_id, - il.old_item_meta, - il.old_item_nbt, - il.old_item_amount, - il.new_item_id, - il.new_item_meta, - il.new_item_nbt, - il.new_item_amount, +SELECT il.old_id, + il.old_meta, + il.old_nbt, + il.old_amount, + il.new_id, + il.new_meta, + il.new_nbt, + il.new_amount, e.entity_name AS entity_from, x, y, diff --git a/resources/patches/.patches b/resources/patches/.patches new file mode 100644 index 00000000..07b061ab --- /dev/null +++ b/resources/patches/.patches @@ -0,0 +1 @@ +# !!! DON'T EDIT THIS FILE !!! \ No newline at end of file diff --git a/resources/patches/mysql_patch.sql b/resources/patches/mysql_patch.sql new file mode 100644 index 00000000..5ffac0ec --- /dev/null +++ b/resources/patches/mysql_patch.sql @@ -0,0 +1,3 @@ +-- #!mysql +-- #{patch +-- #} \ No newline at end of file diff --git a/resources/patches/sqlite_patch.sql b/resources/patches/sqlite_patch.sql new file mode 100644 index 00000000..9e6073ff --- /dev/null +++ b/resources/patches/sqlite_patch.sql @@ -0,0 +1,3 @@ +-- #!sqlite +-- #{patch +-- #} \ No newline at end of file diff --git a/resources/sqlite.sql b/resources/sqlite.sql index 6cedb123..333d15f7 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -4,55 +4,44 @@ -- # {entities CREATE TABLE IF NOT EXISTS "entities" ( - uuid VARCHAR(36) UNIQUE NOT NULL PRIMARY KEY, - entity_name VARCHAR(16) NOT NULL, - entity_classpath TEXT NOT NULL, - address VARCHAR(15) DEFAULT '127.0.0.1' -); --- # } --- # {blocks -CREATE TABLE IF NOT EXISTS "blocks" -( - id UNSIGNED INTEGER NOT NULL, - meta UNSIGNED TINYINT(2) NOT NULL, - block_name VARCHAR(30) NOT NULL, - PRIMARY KEY (id, meta) + uuid VARCHAR(36) UNIQUE PRIMARY KEY NOT NULL, + entity_name VARCHAR(16) NOT NULL, + entity_classpath TEXT NOT NULL, + address VARCHAR(15) DEFAULT '127.0.0.1' NOT NULL ); -- # } -- # {log_history CREATE TABLE IF NOT EXISTS "log_history" ( - log_id INTEGER PRIMARY KEY AUTOINCREMENT, - who VARCHAR(36) NOT NULL, - x BIGINT NOT NULL, - y TINYINT UNSIGNED NOT NULL, - z BIGINT NOT NULL, - world_name VARCHAR(255) NOT NULL, - action TINYINT UNSIGNED NOT NULL, - time TIMESTAMP DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'now', 'localtime')), - "rollback" TINYINT(1) DEFAULT 0, + log_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + who VARCHAR(36) NOT NULL, + x BIGINT NOT NULL, + y TINYINT UNSIGNED NOT NULL, + z BIGINT NOT NULL, + world_name VARCHAR(255) NOT NULL, + action TINYINT UNSIGNED NOT NULL, + time TIMESTAMP DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'now', 'localtime')) NOT NULL, + "rollback" TINYINT(1) DEFAULT 0 NOT NULL, FOREIGN KEY (who) REFERENCES "entities" (uuid) ); -- # } -- # {blocks_log CREATE TABLE IF NOT EXISTS "blocks_log" ( - history_id UNSIGNED BIG INT, - old_block_id UNSIGNED INTEGER NOT NULL, - old_block_meta UNSIGNED TINYINT(2) NOT NULL, - old_block_nbt BLOB DEFAULT NULL, - new_block_id UNSIGNED INTEGER NOT NULL, - new_block_meta UNSIGNED TINYINT(2) NOT NULL, - new_block_nbt BLOB DEFAULT NULL, - FOREIGN KEY (history_id) REFERENCES "log_history" (log_id) ON DELETE CASCADE, - FOREIGN KEY (old_block_id, old_block_meta) REFERENCES "blocks" (id, meta), - FOREIGN KEY (new_block_id, new_block_meta) REFERENCES "blocks" (id, meta) + history_id UNSIGNED BIG INT NOT NULL, + old_id UNSIGNED INTEGER NOT NULL, + old_meta UNSIGNED TINYINT(2) NOT NULL, + old_nbt BLOB DEFAULT NULL, + new_id UNSIGNED INTEGER NOT NULL, + new_meta UNSIGNED TINYINT(2) NOT NULL, + new_nbt BLOB DEFAULT NULL, + FOREIGN KEY (history_id) REFERENCES "log_history" (log_id) ON DELETE CASCADE ); -- # } -- # {entities_log CREATE TABLE IF NOT EXISTS "entities_log" ( - history_id UNSIGNED BIG INT, + history_id UNSIGNED BIG INT NOT NULL, entityfrom_uuid VARCHAR(36) NOT NULL, entityfrom_id UNSIGNED INTEGER NOT NULL, entityfrom_nbt BLOB DEFAULT NULL, @@ -63,19 +52,28 @@ CREATE TABLE IF NOT EXISTS "entities_log" -- # {inventories_log CREATE TABLE IF NOT EXISTS "inventories_log" ( - history_id UNSIGNED BIG INT, - slot UNSIGNED TINYINT NOT NULL, - old_item_id UNSIGNED INTEGER DEFAULT 0, - old_item_meta UNSIGNED TINYINT(2) DEFAULT 0, - old_item_nbt BLOB DEFAULT NULL, - old_item_amount UNSIGNED TINYINT DEFAULT 0, - new_item_id UNSIGNED INTEGER DEFAULT 0, - new_item_meta UNSIGNED TINYINT(2) DEFAULT 0, - new_item_nbt BLOB DEFAULT NULL, - new_item_amount UNSIGNED TINYINT DEFAULT 0, + history_id UNSIGNED BIG INT NOT NULL, + slot UNSIGNED TINYINT NOT NULL, + old_id UNSIGNED INTEGER DEFAULT 0 NOT NULL, + old_meta UNSIGNED TINYINT(2) DEFAULT 0 NOT NULL, + old_nbt BLOB DEFAULT NULL, + old_amount UNSIGNED TINYINT DEFAULT 0 NOT NULL, + new_id UNSIGNED INTEGER DEFAULT 0 NOT NULL, + new_meta UNSIGNED TINYINT(2) DEFAULT 0 NOT NULL, + new_nbt BLOB DEFAULT NULL, + new_amount UNSIGNED TINYINT DEFAULT 0 NOT NULL, FOREIGN KEY (history_id) REFERENCES "log_history" (log_id) ON DELETE CASCADE ); -- # } +-- # {db_status +CREATE TABLE IF NOT EXISTS status +( + only_one_row TINYINT(1) PRIMARY KEY DEFAULT 1 NOT NULL, + version VARCHAR(20) NOT NULL, + upgraded_on TIMESTAMP(6) DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'now', 'localtime')) NOT NULL, + CHECK (only_one_row) +); +-- # } -- # } -- # {transaction -- # {begin @@ -96,14 +94,11 @@ REPLACE INTO "entities" (uuid, entity_name, entity_classpath, address) VALUES (:uuid, :name, :path, :address); -- # } --- # {block --- # :id int --- # :meta int --- # :name string -INSERT OR -REPLACE -INTO "blocks" (id, meta, block_name) -VALUES (:id, :meta, :name); +-- # {db_version +-- # :version string +INSERT OR IGNORE +INTO status (version) +VALUES (:version); -- # } -- # {log -- # {main @@ -117,60 +112,147 @@ INSERT INTO "log_history"(who, x, y, z, world_name, action) VALUES ((SELECT uuid FROM entities WHERE uuid = :uuid), :x, :y, :z, :world_name, :action); -- # } --- # {to_block --- # :old_block_id int --- # :old_block_meta int --- # :old_block_nbt ?string --- # :new_block_id int --- # :new_block_meta int --- # :new_block_nbt ?string -INSERT INTO "blocks_log"(history_id, old_block_id, old_block_meta, old_block_nbt, new_block_id, new_block_meta, - new_block_nbt) -VALUES (LAST_INSERT_ROWID(), - (SELECT id FROM "blocks" WHERE blocks.id = :old_block_id AND meta = :old_block_meta), - (SELECT meta FROM "blocks" WHERE blocks.id = :old_block_id AND meta = :old_block_meta), - :old_block_nbt, - (SELECT id FROM "blocks" WHERE blocks.id = :new_block_id AND meta = :new_block_meta), - (SELECT meta FROM "blocks" WHERE blocks.id = :new_block_id AND meta = :new_block_meta), - :new_block_nbt); +-- # {block +-- # :old_id int +-- # :old_meta int +-- # :old_nbt ?string +-- # :new_id int +-- # :new_meta int +-- # :new_nbt ?string +INSERT INTO "blocks_log"(history_id, old_id, old_meta, old_nbt, new_id, new_meta, + new_nbt) +VALUES (LAST_INSERT_ROWID(), :old_id, :old_meta, :old_nbt, :new_id, :new_meta, + :new_nbt); -- # } --- # {to_entity +-- # {entity -- # :uuid string -- # :id int -- # :nbt ?string INSERT INTO "entities_log"(history_id, entityfrom_uuid, entityfrom_id, entityfrom_nbt) VALUES (LAST_INSERT_ROWID(), (SELECT uuid FROM entities WHERE uuid = :uuid), :id, :nbt); -- # } --- # {to_inventory +-- # {inventory -- # :slot int --- # :old_item_id int 0 --- # :old_item_meta int 0 --- # :old_item_nbt ?string --- # :old_item_amount int 0 --- # :new_item_id int 0 --- # :new_item_meta int 0 --- # :new_item_nbt ?string --- # :new_item_amount int 0 -INSERT INTO "inventories_log"(history_id, slot, old_item_id, old_item_meta, old_item_nbt, old_item_amount, new_item_id, - new_item_meta, new_item_nbt, new_item_amount) -VALUES (LAST_INSERT_ROWID(), :slot, :old_item_id, :old_item_meta, :old_item_nbt, :old_item_amount, :new_item_id, - :new_item_meta, :new_item_nbt, :new_item_amount); +-- # :old_id int 0 +-- # :old_meta int 0 +-- # :old_nbt ?string +-- # :old_amount int 0 +-- # :new_id int 0 +-- # :new_meta int 0 +-- # :new_nbt ?string +-- # :new_amount int 0 +INSERT INTO "inventories_log"(history_id, slot, old_id, old_meta, old_nbt, old_amount, new_id, + new_meta, new_nbt, new_amount) +VALUES (LAST_INSERT_ROWID(), :slot, :old_id, :old_meta, :old_nbt, :old_amount, :new_id, + :new_meta, :new_nbt, :new_amount); -- # } --- # {update_entity_id --- # :log_id int --- # :entity_id int +-- # } +-- # } +-- # {update +-- # {entity_id +-- # :log_id int +-- # :entity_id int UPDATE entities_log SET entityfrom_id = :entity_id WHERE history_id = :log_id; --- # } +-- # } +-- # {db_version +-- # :version string +UPDATE status +SET version = :version, + upgraded_on = (STRFTIME('%Y-%m-%d %H:%M:%f', 'now', 'localtime')); +-- # } +-- # {rollback_status +-- # :rollback bool +-- # :log_ids list:int +UPDATE log_history +SET "rollback" = :rollback +WHERE log_id IN :log_ids; -- # } -- # } -- # {get +-- # {db_status +SELECT * +FROM status +LIMIT 1; +-- # } -- # {log -- # {last_id SELECT MAX(log_id) AS lastId FROM "log_history"; -- # } +-- # {old_blocks +-- # :log_ids list:int +SELECT history_id, + bl.old_id, + bl.old_meta, + bl.old_nbt, + x, + y, + z, + world_name +FROM "log_history" + INNER JOIN blocks_log bl ON log_history.log_id = bl.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {new_blocks +-- # :log_ids list:int +SELECT history_id, + bl.new_id, + bl.new_meta, + bl.new_nbt, + x, + y, + z, + world_name +FROM "log_history" + INNER JOIN blocks_log bl ON log_history.log_id = bl.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {old_inventories +-- # :log_ids list:int +SELECT history_id, + il.slot, + il.old_id, + il.old_meta, + il.old_nbt, + il.old_amount, + x, + y, + z +FROM "log_history" + INNER JOIN inventories_log il ON log_history.log_id = il.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {new_inventories +-- # :log_ids list:int +SELECT history_id, + il.slot, + il.new_id, + il.new_meta, + il.new_nbt, + il.new_amount, + x, + y, + z +FROM "log_history" + INNER JOIN inventories_log il ON log_history.log_id = il.history_id +WHERE log_id IN :log_ids; +-- # } +-- # {entities +-- # :log_ids list:int +SELECT e.entity_classpath, + el.entityfrom_id, + el.entityfrom_nbt, + x, + y, + z, + action +FROM "log_history" + INNER JOIN entities_log el ON log_history.log_id = el.history_id + INNER JOIN entities e ON e.uuid = el.entityfrom_uuid +WHERE log_id IN :log_ids; +-- # } -- # {block -- # :min_x int -- # :max_x int @@ -179,12 +261,12 @@ FROM "log_history"; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT bl.old_block_id, - bl.old_block_meta, - bl.old_block_nbt, - bl.new_block_id, - bl.new_block_meta, - bl.new_block_nbt, +SELECT bl.old_id, + bl.old_meta, + bl.old_nbt, + bl.new_id, + bl.new_meta, + bl.new_nbt, e.entity_name AS entity_from, x, y, @@ -239,12 +321,12 @@ ORDER BY time DESC; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT bl.old_block_id, - bl.old_block_meta, - bl.old_block_nbt, - bl.new_block_id, - bl.new_block_meta, - bl.new_block_nbt, +SELECT bl.old_id, + bl.old_meta, + bl.old_nbt, + bl.new_id, + bl.new_meta, + bl.new_nbt, e1.entity_name AS entity_from, e2.entity_name AS entity_to, x, @@ -274,14 +356,14 @@ ORDER BY time DESC; -- # :min_z int -- # :max_z int -- # :world_name string -SELECT il.old_item_id, - il.old_item_meta, - il.old_item_nbt, - il.old_item_amount, - il.new_item_id, - il.new_item_meta, - il.new_item_nbt, - il.new_item_amount, +SELECT il.old_id, + il.old_meta, + il.old_nbt, + il.old_amount, + il.new_id, + il.new_meta, + il.new_nbt, + il.new_amount, e.entity_name AS entity_from, x, y, diff --git a/src/matcracker/BedcoreProtect/Inspector.php b/src/matcracker/BedcoreProtect/Inspector.php index 7085f76b..7f52466f 100644 --- a/src/matcracker/BedcoreProtect/Inspector.php +++ b/src/matcracker/BedcoreProtect/Inspector.php @@ -21,7 +21,7 @@ namespace matcracker\BedcoreProtect; -use matcracker\BedcoreProtect\utils\Action; +use matcracker\BedcoreProtect\enums\Action; use matcracker\BedcoreProtect\utils\Utils; use pocketmine\block\BlockFactory; use pocketmine\command\CommandSender; @@ -77,12 +77,12 @@ public static function removeInspector(CommandSender $inspector): bool */ public static function isInspector(CommandSender $inspector): bool { - return self::$inspectors[self::getSenderUUID($inspector)]["enabled"] ?? false; + return self::$inspectors[self::getSenderUUID($inspector)]['enabled'] ?? false; } public static function cacheLogs(CommandSender $inspector, array $logs = []): void { - self::$inspectors[self::getSenderUUID($inspector)]["logs"] = $logs; + self::$inspectors[self::getSenderUUID($inspector)]['logs'] = $logs; } /** @@ -92,7 +92,7 @@ public static function cacheLogs(CommandSender $inspector, array $logs = []): vo */ public static function getCachedLogs(CommandSender $inspector): array { - return self::$inspectors[self::getSenderUUID($inspector)]["logs"] ?? []; + return self::$inspectors[self::getSenderUUID($inspector)]['logs'] ?? []; } public static function clearCache(): void @@ -110,14 +110,15 @@ public static function clearCache(): void */ public static function parseLogs(CommandSender $inspector, array $logs, int $page = 0, int $lines = 4): void { + $lang = Main::getInstance()->getLanguage(); if (empty($logs)) { - $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cNo block data found for this location.")); + $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $lang->translateString('inspector.no-data'))); return; } if ($lines < 1) { - $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cThe lines number must be greater than 1.")); + $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $lang->translateString('inspector.more-lines'))); return; } @@ -126,12 +127,12 @@ public static function parseLogs(CommandSender $inspector, array $logs, int $pag $maxPages = count($chunkLogs); $fakePage = $page + 1; if (!isset($chunkLogs[$page])) { - $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cThe page &6{$fakePage}&c does not exist!")); + $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $lang->translateString('inspector.page-not-exist', [$fakePage]))); return; } - $inspector->sendMessage(Utils::translateColors("&f-----&3 " . Main::PLUGIN_NAME . " &7(Page {$fakePage}/{$maxPages}) &f-----")); + $inspector->sendMessage(Utils::translateColors('&f-----&3 ' . Main::PLUGIN_NAME . ' &7(' . $lang->translateString('inspector.page', [$fakePage, $maxPages]) . ') &f-----')); foreach ($chunkLogs[$page] as $log) { //Default $from = (string)$log['entity_from']; @@ -144,30 +145,30 @@ public static function parseLogs(CommandSender $inspector, array $logs, int $pag $timeStamp = (is_int($log['time']) ? (int)$log['time'] : strtotime($log['time'])); - $typeColumn = ($action->equals(Action::BREAK()) || $action->equals(Action::REMOVE())) ? "old" : "new"; - if (isset($log["{$typeColumn}_block_id"], $log["{$typeColumn}_block_meta"])) { - $id = (int)$log["{$typeColumn}_block_id"]; - $meta = (int)$log["{$typeColumn}_block_meta"]; - $blockName = BlockFactory::get($id, $meta)->getName(); - - $to = "#{$id}:{$meta} ({$blockName})"; + $typeColumn = ($action->equals(Action::BREAK()) || $action->equals(Action::REMOVE())) ? 'old' : 'new'; + if (isset($log["{$typeColumn}_id"], $log["{$typeColumn}_meta"])) { + $id = (int)$log["{$typeColumn}_id"]; + $meta = (int)$log["{$typeColumn}_meta"]; + if (isset($log["{$typeColumn}_amount"])) { + $amount = (int)$log["{$typeColumn}_amount"]; + + $itemName = ItemFactory::get($id, $meta)->getName(); + $to = "{$amount} x #{$id}:{$meta} ({$itemName})"; + } else { + $blockName = BlockFactory::get($id, $meta)->getName(); + $to = "#{$id}:{$meta} ({$blockName})"; + } } elseif (isset($log['entity_to'])) { $to = "#{$log['entity_to']}"; - } elseif (isset($log["{$typeColumn}_item_meta"], $log["{$typeColumn}_item_amount"])) { - $id = (int)$log["{$typeColumn}_item_id"]; - $meta = (int)$log["{$typeColumn}_item_meta"]; - $amount = (int)$log["{$typeColumn}_item_amount"]; - $itemName = ItemFactory::get($id, $meta)->getName(); - $to = "{$amount} x #{$id}:{$meta} ({$itemName})"; } else { - throw new UnexpectedValueException("Invalid action parsed: {$action->name()}"); + throw new UnexpectedValueException('Unexpected log parsed. Is your database up to date?'); } //TODO: Use strikethrough (&m) when MC fix it. - $inspector->sendMessage(Utils::translateColors(($rollback ? "&o" : "") . "&7" . Utils::timeAgo($timeStamp) + $inspector->sendMessage(Utils::translateColors(($rollback ? '&o' : '') . '&7' . Utils::timeAgo($timeStamp) . "&f - &3{$from} &f{$action->getMessage()} &3{$to} &f - &7(x{$x}/y{$y}/z{$z}/{$worldName})&f.")); } - $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "View older data by typing /bcp l :.")); + $inspector->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $lang->translateString('inspector.view-old-data') . ' /bcp l :.')); } diff --git a/src/matcracker/BedcoreProtect/Main.php b/src/matcracker/BedcoreProtect/Main.php index 00d47b13..b2fd326b 100644 --- a/src/matcracker/BedcoreProtect/Main.php +++ b/src/matcracker/BedcoreProtect/Main.php @@ -24,12 +24,14 @@ use JackMD\UpdateNotifier\UpdateNotifier; use matcracker\BedcoreProtect\commands\BCPCommand; use matcracker\BedcoreProtect\listeners\BlockListener; +use matcracker\BedcoreProtect\listeners\BlockSniperListener; use matcracker\BedcoreProtect\listeners\EntityListener; use matcracker\BedcoreProtect\listeners\PlayerListener; use matcracker\BedcoreProtect\listeners\WorldListener; use matcracker\BedcoreProtect\storage\Database; use matcracker\BedcoreProtect\tasks\SQLiteTransactionTask; use matcracker\BedcoreProtect\utils\ConfigParser; +use pocketmine\lang\BaseLang; use pocketmine\plugin\PluginBase; final class Main extends PluginBase @@ -38,6 +40,9 @@ final class Main extends PluginBase public const PLUGIN_TAG = "[" . self::PLUGIN_NAME . "]"; public const MESSAGE_PREFIX = "&3" . self::PLUGIN_NAME . " &f- "; + /**@var Main $instance */ + private static $instance; + /**@var Database $database */ private $database; @@ -45,6 +50,10 @@ final class Main extends PluginBase private $configParser; /**@var ConfigParser $oldConfigParser */ private $oldConfigParser; + /**@var BaseLang $baseLang */ + private $baseLang; + /**@var boolean $bsHooked */ + private $bsHooked = false; /** * @return Database @@ -73,40 +82,83 @@ public function restoreParsedConfig(): void */ public function reloadPlugin(): bool { - $this->oldConfigParser = clone $this->configParser; + $this->oldConfigParser = $this->configParser; $this->reloadConfig(); + $this->configParser = (new ConfigParser($this->getConfig()))->validate(); + + if ($this->configParser->isValidConfig()) { + $this->baseLang = new BaseLang($this->configParser->getLanguage(), $this->getFile() . 'resources/languages/'); + return true; + } - return $this->configParser->validate()->isValidConfig(); + return false; } - public function onEnable(): void + public static function getInstance(): Main { - $this->database = new Database($this); - - @mkdir($this->getDataFolder()); - $this->saveResource("bedcore_database.db"); + return self::$instance; + } - $this->configParser = (new ConfigParser($this))->validate(); + public function onLoad(): void + { + $this->configParser = (new ConfigParser($this->getConfig()))->validate(); if (!$this->configParser->isValidConfig()) { $this->getServer()->getPluginManager()->disablePlugin($this); return; } + $this->baseLang = new BaseLang($this->configParser->getLanguage(), $this->getFile() . 'resources/languages/'); + + if ($this->configParser->getBlockSniperHook()) { + $bsPlugin = $this->getServer()->getPluginManager()->getPlugin('BlockSniper'); + if ($bsPlugin !== null) { + $this->getLogger()->info($this->baseLang->translateString('blocksniper.hook.success')); + $this->bsHooked = true; + } else { + $this->getLogger()->warning($this->baseLang->translateString('blocksniper.hook.no-hook')); + } + } + + if ($this->configParser->getCheckUpdates()) { + UpdateNotifier::checkUpdate($this, $this->getName(), $this->getDescription()->getVersion()); + } + } + + public function onEnable(): void + { + self::$instance = $this; + $this->database = new Database($this); + + @mkdir($this->getDataFolder()); + $this->saveResource('bedcore_database.db'); + //Database connection if (!$this->database->connect()) { $this->getServer()->getPluginManager()->disablePlugin($this); return; } + $version = $this->getVersion(); + $this->database->getQueries()->init($version); + $dbVersion = $this->database->getVersion(); + if (version_compare($version, $dbVersion) < 0) { + $this->getLogger()->warning($this->baseLang->translateString('database.version.higher')); + $this->getServer()->getPluginManager()->disablePlugin($this); + + return; + } - $this->database->getQueries()->init(); + if ($this->database->getPatchManager()->patch()) { + $this->getLogger()->info($this->baseLang->translateString('database.version.updated', [$dbVersion, $version])); + } if ($this->configParser->isSQLite()) { + $this->database->getQueries()->beginTransaction(); $this->getScheduler()->scheduleDelayedRepeatingTask(new SQLiteTransactionTask($this->database), SQLiteTransactionTask::getTicks(), SQLiteTransactionTask::getTicks()); } - $this->getServer()->getCommandMap()->register("bedcoreprotect", new BCPCommand($this)); + $this->getServer()->getCommandMap()->register('bedcoreprotect', new BCPCommand($this)); //Registering events $events = [ @@ -116,13 +168,32 @@ public function onEnable(): void new WorldListener($this) ]; + if ($this->bsHooked) { + $events[] = new BlockSniperListener($this); + } + foreach ($events as $event) { $this->getServer()->getPluginManager()->registerEvents($event, $this); } + } - if ($this->configParser->getCheckUpdates()) { - UpdateNotifier::checkUpdate($this, $this->getName(), $this->getDescription()->getVersion()); - } + public function isBlockSniperHooked(): bool + { + return $this->bsHooked; + } + + public function getLanguage(): BaseLang + { + return $this->baseLang; + } + + /** + * Returns the plugin version. + * @return string + */ + public function getVersion(): string + { + return $this->getDescription()->getVersion(); } public function onDisable(): void @@ -131,5 +202,8 @@ public function onDisable(): void $this->database->disconnect(); Inspector::clearCache(); + self::$instance = null; + $this->bsHooked = false; + unset($this->database, $this->baseLang, $this->configParser, $this->oldConfigParser); } -} +} \ No newline at end of file diff --git a/src/matcracker/BedcoreProtect/commands/BCPCommand.php b/src/matcracker/BedcoreProtect/commands/BCPCommand.php index a65a1559..e0fe9da0 100644 --- a/src/matcracker/BedcoreProtect/commands/BCPCommand.php +++ b/src/matcracker/BedcoreProtect/commands/BCPCommand.php @@ -21,13 +21,18 @@ namespace matcracker\BedcoreProtect\commands; +use BlockHorizons\BlockSniper\sessions\SessionManager; use matcracker\BedcoreProtect\Inspector; use matcracker\BedcoreProtect\Main; +use matcracker\BedcoreProtect\math\Area; +use matcracker\BedcoreProtect\math\MathUtils; +use matcracker\BedcoreProtect\ui\Forms; use matcracker\BedcoreProtect\utils\Utils; use pocketmine\command\Command; use pocketmine\command\CommandSender; +use pocketmine\math\AxisAlignedBB; use pocketmine\Player; -use poggit\libasynql\SqlError; +use SOFe\AwaitGenerator\Await; final class BCPCommand extends Command { @@ -38,10 +43,10 @@ final class BCPCommand extends Command public function __construct(Main $plugin) { parent::__construct( - "bedcoreprotect", - "It runs the BedcoreProtect commands.", - "Usage: /bcp help to display commands list", - ["core", "co", "bcp"] + 'bedcoreprotect', + $plugin->getLanguage()->translateString('command.description'), + $plugin->getLanguage()->translateString('command.usage'), + ['core', 'co', 'bcp'] ); $this->plugin = $plugin; $this->queries = $plugin->getDatabase()->getQueries(); @@ -56,8 +61,8 @@ public function execute(CommandSender $sender, string $commandLabel, array $args } $subCmd = $this->removeAbbreviation(strtolower($args[0])); - if (!$sender->hasPermission("bcp.command.bedcoreprotect") || !$sender->hasPermission("bcp.subcommand.{$subCmd}")) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou don't have permission to run this command.")); + if (!$sender->hasPermission('bcp.command.bedcoreprotect') || !$sender->hasPermission("bcp.subcommand.{$subCmd}")) { + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.no-permission'))); return false; } @@ -68,28 +73,34 @@ public function execute(CommandSender $sender, string $commandLabel, array $args isset($args[1]) ? BCPHelpCommand::showSpecificHelp($sender, $args[1]) : BCPHelpCommand::showGenericHelp($sender); return true; - case "reload": + case 'reload': if ($this->plugin->reloadPlugin()) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Plugin configuration reloaded.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.reload.success'))); } else { $this->plugin->restoreParsedConfig(); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cPlugin configuration not reloaded due to some errors. Check your console to see the errors.")); - $sender->sendMessage(Utils::translateColors("&cUntil you fix them, it will be used the old configuration.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.reload.no-success'))); } return true; - case "status": - $description = $this->plugin->getDescription(); - $sender->sendMessage(Utils::translateColors("&f----- &3" . Main::PLUGIN_NAME . " &f-----")); - $sender->sendMessage(Utils::translateColors("&3Version:&f " . $description->getVersion())); - $sender->sendMessage(Utils::translateColors("&3Database connection:&f " . $this->plugin->getParsedConfig()->getPrintableDatabaseType())); - $sender->sendMessage(Utils::translateColors("&3Author:&f " . implode(",", $description->getAuthors()))); - $sender->sendMessage(Utils::translateColors("&3Website:&f " . $description->getWebsite())); - + case 'status': + Await::f2c(function () use ($sender) { + $description = $this->plugin->getDescription(); + $lang = $this->plugin->getLanguage(); + $dbVersion = (string)yield $this->plugin->getDatabase()->getStatus()[0]["version"]; + $sender->sendMessage(Utils::translateColors('&f----- &3' . Main::PLUGIN_NAME . ' &f-----')); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.version', [$this->plugin->getVersion()]))); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.database-connection', [$this->plugin->getParsedConfig()->getPrintableDatabaseType()]))); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.database-version', [$dbVersion]))); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.blocksniper-hook', [$this->plugin->isBlockSniperHooked() ? $lang->translateString("generic.yes") : $lang->translateString("generic.no")]))); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.author', [implode(', ', $description->getAuthors())]))); + $sender->sendMessage(Utils::translateColors('&3' . $lang->translateString('command.status.website', [$description->getWebsite()]))); + }, function () { + //NOOP + }); return true; - case "lookup": + case 'lookup': if (isset($args[1])) { - $parser = new CommandParser($this->plugin->getParsedConfig(), $args, ["time"], true); + $parser = new CommandParser($sender->getName(), $this->plugin->getParsedConfig(), $args, ['time'], true); if ($parser->parse()) { $this->queries->requestLookup($sender, $parser); } else { @@ -107,7 +118,7 @@ public function execute(CommandSender $sender, string $commandLabel, array $args } if (!$ctype) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cWrong page/line value inserted!")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.no-numeric-value'))); return true; } @@ -118,19 +129,19 @@ public function execute(CommandSender $sender, string $commandLabel, array $args } } } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou must add at least one parameter.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.one-parameter'))); } return true; - case "purge": + case 'purge': if (isset($args[1])) { - $parser = new CommandParser($this->plugin->getParsedConfig(), $args, ["time"], true); + $parser = new CommandParser($sender->getName(), $this->plugin->getParsedConfig(), $args, ['time'], true); if ($parser->parse()) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Data purge started. This may take some time.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Do not restart your server until completed.")); - $this->queries->purge($parser->getTime(), static function (int $affectedRows) use ($sender) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Data purge successful.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "{$affectedRows} rows of data deleted.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.purge.started'))); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.purge.no-restart'))); + $this->queries->purge($parser->getTime(), function (int $affectedRows) use ($sender): void { + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.purge.success'))); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.purge.deleted-rows', [$affectedRows]))); }); return true; @@ -138,39 +149,46 @@ public function execute(CommandSender $sender, string $commandLabel, array $args $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&c{$parser->getErrorMessage()}")); } } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou must add at least one parameter.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.one-parameter'))); } return true; } if (!($sender instanceof Player)) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou can't run this command from console.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.no-console'))); return false; } //Only players commands. switch ($subCmd) { - case "inspect": - $b = Inspector::isInspector($sender); - $b ? Inspector::removeInspector($sender) : Inspector::addInspector($sender); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . ($b ? "Disabled" : "Enabled") . " inspector mode.")); - + case 'menu': + case 'ui': + $sender->sendForm((new Forms($this->plugin->getParsedConfig()))->getMainMenu()); + return true; + case 'inspect': + if (Inspector::isInspector($sender)) { + Inspector::removeInspector($sender); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.inspect.disabled'))); + } else { + Inspector::addInspector($sender); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.inspect.enabled'))); + } return true; - case "near": + case 'near': $near = 5; if (isset($args[1])) { if (!ctype_digit($args[1])) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cThe near value must be numeric!")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.no-numeric-value'))); return true; } $near = (int)$args[1]; $maxRadius = $this->plugin->getParsedConfig()->getMaxRadius(); if ($near < 1 || $near > $maxRadius) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cThe near value must be between 1 and {$maxRadius}!")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.near.range-value'))); return true; } @@ -179,112 +197,73 @@ public function execute(CommandSender $sender, string $commandLabel, array $args $this->queries->requestNearLog($sender, $sender, $near); return true; - case "rollback": + case 'rollback': if (isset($args[1])) { - $parser = new CommandParser($this->plugin->getParsedConfig(), $args, ["time", "radius"], true); + $parser = new CommandParser($sender->getName(), $this->plugin->getParsedConfig(), $args, ['time', 'radius'], true); if ($parser->parse()) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Starting rollback on \"{$sender->getLevel()->getFolderName()}\".")); - $sender->sendMessage(Utils::translateColors("&f------")); - $start = microtime(true); - - $this->queries->rollback($sender->asPosition(), $parser, - static function (int $blocks, int $items, int $entities) use ($sender, $start, $parser) { //onSuccess - if (($blocks + $items + $entities) > 0) { - $diff = microtime(true) - $start; - $time = time() - $parser->getTime(); - $radius = $parser->getRadius(); - $date = Utils::timeAgo($time); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Rollback completed for \"{$sender->getLevel()->getFolderName()}\".")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Rolled back {$date}.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Radius: {$radius} block(s).")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$blocks} block(s) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$items} item(s) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$entities} entity(ies) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Time taken: " . round($diff, 1) . " second(s).")); - $sender->sendMessage(Utils::translateColors("&f------")); - $y = $sender->getLevel()->getHighestBlockAt((int)$sender->getX(), (int)$sender->getZ()) + 1; - if ((int)$sender->getY() < $y) { - $sender->teleport($sender->setComponents($sender->getX(), $y, $sender->getZ()), $sender->getYaw(), $sender->getPitch()); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Teleported to the top.")); - } - } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cNo data to rollback.")); - } - }, - static function (SqlError $error) use ($sender) { //onError - $this->plugin->getLogger()->alert($error->getErrorMessage()); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cAn error occurred while restoring. Check the console.")); - $sender->sendMessage(Utils::translateColors("&f------")); - } - ); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.rollback.started', [$sender->getLevel()->getName()]))); + + $bb = $this->getSelectionArea($sender) ?? MathUtils::getRangedVector($sender->asVector3(), $parser->getRadius()); + $this->queries->rollback(new Area($sender->getLevel(), $bb), $parser); } else { $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&c{$parser->getErrorMessage()}")); } } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou must add at least one parameter.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.one-parameter'))); } return true; - case "restore": + case 'restore': if (isset($args[1])) { - $parser = new CommandParser($this->plugin->getParsedConfig(), $args, ["time", "radius"], true); + $parser = new CommandParser($sender->getName(), $this->plugin->getParsedConfig(), $args, ['time', 'radius'], true); if ($parser->parse()) { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Restore started on \"{$sender->getLevel()->getFolderName()}\".")); - $sender->sendMessage(Utils::translateColors("&f------")); - $start = microtime(true); - - $this->queries->restore($sender->asPosition(), $parser, - static function (int $blocks, int $items, int $entities) use ($sender, $start, $parser) { //onSuccess - if (($blocks + $items + $entities) > 0) { - $diff = microtime(true) - $start; - $time = time() - $parser->getTime(); - $radius = $parser->getRadius(); - $date = Utils::timeAgo($time); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Restore completed for \"{$sender->getLevel()->getFolderName()}\".")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Restored {$date}.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Radius: {$radius} block(s).")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$blocks} block(s) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$items} item(s) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Approx. {$entities} entity(ies) changed.")); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "Time taken: " . round($diff, 1) . " second(s).")); - $sender->sendMessage(Utils::translateColors("&f------")); - } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cNo data to restore.")); - } - }, - static function (SqlError $error) use ($sender) { //onError - $this->plugin->getLogger()->alert($error->getErrorMessage()); - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cAn error occurred while restoring. Check the console.")); - $sender->sendMessage(Utils::translateColors("&f------")); - } - ); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . $this->plugin->getLanguage()->translateString('command.restore.started', [$sender->getLevel()->getName()]))); + + $bb = $this->getSelectionArea($sender) ?? MathUtils::getRangedVector($sender->asVector3(), $parser->getRadius()); + $this->queries->restore(new Area($sender->getLevel(), $bb), $parser); } else { $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&c{$parser->getErrorMessage()}")); } } else { - $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&cYou must add at least one parameter.")); + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . '&c' . $this->plugin->getLanguage()->translateString('command.error.one-parameter'))); } return true; + default: + $sender->sendMessage(Utils::translateColors(Main::MESSAGE_PREFIX . "&c{$this->getUsage()}")); + return false; } - - return false; } private function removeAbbreviation(string $subCmd): string { - if ($subCmd === "l") { - $subCmd = "lookup"; - } else if ($subCmd === "i") { - $subCmd = "inspect"; - } else if ($subCmd === "rb") { - $subCmd = "rollback"; - } else if ($subCmd === "rs") { - $subCmd = "restore"; + if ($subCmd === 'l') { + $subCmd = 'lookup'; + } else if ($subCmd === 'i') { + $subCmd = 'inspect'; + } else if ($subCmd === 'rb') { + $subCmd = 'rollback'; + } else if ($subCmd === 'rs') { + $subCmd = 'restore'; + } else if ($subCmd === 'ui') { + $subCmd = 'menu'; } return $subCmd; } + private function getSelectionArea(Player $player): ?AxisAlignedBB + { + if ($this->plugin->isBlockSniperHooked()) { + $session = SessionManager::getPlayerSession($player); + if ($session !== null) { + $selection = $session->getSelection(); + if ($selection->ready()) { + return $selection->box(); + } + } + } + return null; + } } \ No newline at end of file diff --git a/src/matcracker/BedcoreProtect/commands/BCPHelpCommand.php b/src/matcracker/BedcoreProtect/commands/BCPHelpCommand.php index f8092a4e..7b45fd28 100644 --- a/src/matcracker/BedcoreProtect/commands/BCPHelpCommand.php +++ b/src/matcracker/BedcoreProtect/commands/BCPHelpCommand.php @@ -34,35 +34,42 @@ private function __construct() public static function showGenericHelp(CommandSender $sender): void { - $sender->sendMessage(Utils::translateColors("&f----- &3" . Main::PLUGIN_NAME . " &3Help Page &f-----")); - $sender->sendMessage(Utils::translateColors("&3/bcp help &7 &f- Display more info for that command.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7inspect &f- Turns the blocks inspector on or off.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7rollback &3 &f- Rollback block data.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7restore &3 &f- Restore block data.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7lookup &3 &f- Advanced block data lookup.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7purge &3 &f- Delete old block data.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7reload &f- Reloads the configuration file.")); - $sender->sendMessage(Utils::translateColors("&3/bcp &7status &f- Displays the plugin status")); + $lang = Main::getInstance()->getLanguage(); + $sender->sendMessage(Utils::translateColors("&f----- &3" . Main::PLUGIN_NAME . " &3" . $lang->translateString("command.help.title") . " &f-----")); + $sender->sendMessage(Utils::translateColors("&3/bcp help &7 &f- " . $lang->translateString("command.help.help"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7menu &f- " . $lang->translateString("command.help.menu"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7inspect &f- " . $lang->translateString("command.help.inspect"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7rollback &3 &f- " . $lang->translateString("command.help.rollback"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7restore &3 &f- " . $lang->translateString("command.help.restore"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7lookup &3 &f- " . $lang->translateString("command.help.lookup"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7purge &3 &f- " . $lang->translateString("command.help.purge"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7reload &f- " . $lang->translateString("command.help.reload"))); + $sender->sendMessage(Utils::translateColors("&3/bcp &7status &f- " . $lang->translateString("command.help.status"))); $sender->sendMessage(Utils::translateColors("&f------")); } public static function showSpecificHelp(CommandSender $sender, string $subCmd): void { + $lang = Main::getInstance()->getLanguage(); $subCmd = strtolower($subCmd); - $sender->sendMessage(Utils::translateColors("&f----- &3" . Main::PLUGIN_NAME . " &3Help Page &f-----")); + $sender->sendMessage(Utils::translateColors("&f----- &3" . Main::PLUGIN_NAME . " &3" . $lang->translateString("command.help.title") . "&f-----")); switch ($subCmd) { case "help": - $sender->sendMessage(Utils::translateColors("&3/bcp help &f- Displays a list of all commands.")); + $sender->sendMessage(Utils::translateColors("&3/bcp help &f- " . $lang->translateString("command.help.help2"))); + break; + case "menu": + case "ui": + $sender->sendMessage(Utils::translateColors("&3/bcp menu &f- " . $lang->translateString("command.help.menu"))); break; case "inspect": case "i": - $sender->sendMessage(Utils::translateColors("&3With the inspector enabled, you can do the following:")); - $sender->sendMessage(Utils::translateColors("&7* Left-click a block to see who placed that block.")); - $sender->sendMessage(Utils::translateColors("&7* Right-click a block to see what adjacent block was removed.")); - $sender->sendMessage(Utils::translateColors("&7* Place a block to see what block was removed at the location.")); - $sender->sendMessage(Utils::translateColors("&7* Place a block in liquid (etc) to see who placed it.")); - $sender->sendMessage(Utils::translateColors("&7* Right-click on a door, chest, etc, to see who last used it.")); - $sender->sendMessage(Utils::translateColors("&7Tip: You can use just &3\"/bcp i\"&7 for quicker access.")); + $sender->sendMessage(Utils::translateColors("&3" . $lang->translateString("command.help.inspect1"))); + $sender->sendMessage(Utils::translateColors("&7* " . $lang->translateString("command.help.inspect2"))); + $sender->sendMessage(Utils::translateColors("&7* " . $lang->translateString("command.help.inspect3"))); + $sender->sendMessage(Utils::translateColors("&7* " . $lang->translateString("command.help.inspect4"))); + $sender->sendMessage(Utils::translateColors("&7* " . $lang->translateString("command.help.inspect5"))); + $sender->sendMessage(Utils::translateColors("&7* " . $lang->translateString("command.help.inspect6"))); + $sender->sendMessage(Utils::translateColors("&7" . $lang->translateString("command.help.inspect7"))); break; case "rollback": case "rb": @@ -76,61 +83,61 @@ public static function showSpecificHelp(CommandSender $sender, string $subCmd): } elseif ($subCmd === "rb") { $subCmd = "rollback"; } - $sender->sendMessage(Utils::translateColors("&3/bcp {$subCmd} &7 &f- Perform the {$subCmd}.")); - $sender->sendMessage(Utils::translateColors("&3| &7u= &f- Specify the user(s) to {$subCmd}.")); - $sender->sendMessage(Utils::translateColors("&3| &7t=