Skip to content
This repository was archived by the owner on Aug 24, 2024. It is now read-only.

Commit 3aa99bc

Browse files
author
KocTu4eK
committed
Rollback 1.1.0
1 parent 2f23ae8 commit 3aa99bc

File tree

5 files changed

+112
-63
lines changed

5 files changed

+112
-63
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ This is an incomplete port of CoreProtect written in NodeJS with few features. M
88
## Capabilities
99
— Write (only) in SQLite
1010
— Paginated log output
11-
— Permission for the command
11+
— Permission for the command
12+
— Rollback of all actions
1213
## Commands
1314
— /coreprotect <inspect|i>
1415
⠀⠀/coreprotect <l|lookup> <page>
16+
⠀⠀/coreprotect <rollback|r> <radius: int> [time: float] [user: string]
1517
⠀⠀/co — alias
1618
— /coperms <player: target>

command.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
const { isInspector, setInspector, lookupPage, clearUserPos } = require("./database.js");
1+
const { isInspector, setInspector, lookupPage, clearUserPos, rollback } = require("./database.js");
22

33
mc.listen("onServerStarted", () => {
44
let command = mc.newCommand("coreprotect", "CoreProtect by KocTu4eK.", PermType.Any);
55
command.setAlias("co");
6+
67
command.setEnum("Inspect", ["inspect", "i"]);
78
command.setEnum("Lookup", ["lookup", "l"]);
9+
command.setEnum("Rollback", ["rollback", "r"]);
10+
811
command.mandatory("inspect", ParamType.Enum, "Inspect", 1);
912
command.mandatory("lookup", ParamType.Enum, "Lookup", 1);
1013
command.mandatory("page", ParamType.Int);
14+
command.mandatory("rollback", ParamType.Enum, "Rollback", 1);
15+
command.mandatory("radius", ParamType.Int);
16+
command.optional("time", ParamType.Float);
17+
command.optional("user", ParamType.String);
18+
1119
command.overload(["inspect"]);
1220
command.overload(["lookup", "page"]);
21+
command.overload(["rollback", "radius", "time", "user"]);
1322

1423
command.setCallback((_cmd, ori, out, res) => {
1524
if (ori.player === undefined) return out.error("You are not a player!");
@@ -30,6 +39,11 @@ mc.listen("onServerStarted", () => {
3039
if (res.page < 1) return out.error("Invalid integer specified!");
3140
return lookupPage(ori.player, res.page, out);
3241
}
42+
43+
if (res.rollback !== undefined) {
44+
if (res.radius > 128) return out.success("§3CoreProtect §r- The maximum rollback radius is 128.");
45+
return rollback(ori.player, res.radius, res.time, res.user, out);
46+
}
3347
}
3448

3549
return out.error("You don't have permission for this!");

database.js

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,11 @@ function initDatabase() {
55

66
session.exec("CREATE TABLE IF NOT EXISTS co_art_map (id INTEGER PRIMARY KEY AUTOINCREMENT, block TEXT UNIQUE)");
77
session.exec("CREATE TABLE IF NOT EXISTS co_user (id INTEGER PRIMARY KEY AUTOINCREMENT, nickname TEXT UNIQUE, inspector INT DEFAULT 0, wid INT DEFAULT -1, x INT DEFAULT 0, y INT DEFAULT -256, z INT DEFAULT 0)");
8-
session.exec("CREATE TABLE IF NOT EXISTS co_item (id INTEGER PRIMARY KEY AUTOINCREMENT, item TEXT UNIQUE)");
9-
session.exec("CREATE TABLE IF NOT EXISTS co_block (time TIMESTAMP DEFAULT (CAST (((julianday('now') - 2440587.5) * 86400.0 * 1000) AS INT)), block INT, user INT, action INT, wid INT, x INT, y INT, z INT)");
8+
session.exec("CREATE TABLE IF NOT EXISTS co_block (time TIMESTAMP DEFAULT (CAST (((julianday('now') - 2440587.5) * 86400.0 * 1000) AS INT)), block INT, user INT, action INT, wid INT, x INT, y INT, z INT, data INT, count INT, slot INT, rollback INT DEFAULT 0)");
109
}
1110

12-
function getUserId(playerName) {
13-
let userId = session.query(`SELECT id FROM co_user WHERE nickname = "${playerName}"`);
14-
15-
if (userId === undefined) {
16-
session.exec(`INSERT INTO co_user (nickname) VALUES ("${playerName}")`);
17-
return session.query(`SELECT id FROM co_user WHERE nickname = "${playerName}"`)[1][0];
18-
}
19-
20-
return userId[1][0];
21-
}
22-
23-
function getUserName(userId) {
24-
return session.query(`SELECT nickname FROM co_user WHERE id = ${userId}`)[1][0];
25-
}
26-
27-
function getBlockId(blockName) {
28-
blockName = blockName.replace("minecraft:", "");
29-
let blockId = session.query(`SELECT id FROM co_art_map WHERE block = "${blockName}"`);
30-
31-
if (blockId === undefined) {
32-
session.exec(`INSERT INTO co_art_map (block) VALUES ("${blockName}")`);
33-
return session.query(`SELECT id FROM co_art_map WHERE block = "${blockName}"`)[1][0];
34-
}
35-
36-
return blockId[1][0];
37-
}
38-
39-
function getBlockName(blockId) {
40-
return session.query(`SELECT block FROM co_art_map WHERE id = ${blockId}`)[1][0];
41-
}
42-
43-
function logBlock(pl, blockName, wid, x, y, z, action) {
44-
if (!isInspector(pl.realName)) session.exec(`INSERT INTO co_block (block, user, action, wid, x, y, z) VALUES (${getBlockId(blockName)}, ${getUserId(pl.realName)}, ${action}, ${wid}, ${x}, ${y}, ${z})`);
11+
function logBlock(pl, blockName, wid, x, y, z, action, tileData, count = -1, slot = -1) {
12+
if (!isInspector(pl.realName)) session.exec(`INSERT INTO co_block (block, user, action, wid, x, y, z, data, count, slot) VALUES (${getBlockId(blockName)}, ${getUserId(pl.realName)}, ${action}, ${wid}, ${x}, ${y}, ${z}, ${tileData}, ${count}, ${slot})`);
4513
else {
4614
if (action === 1) mc.setBlock(x, y, z, wid, "minecraft:air", 0);
4715
let pageCount = getPageCount(wid, x, y, z);
@@ -51,13 +19,14 @@ function logBlock(pl, blockName, wid, x, y, z, action) {
5119

5220
let blockPage = getBlockPage(wid, x, y, z, 0);
5321
for (i = 1; i < blockPage.length; i++) {
54-
output += `§7${timeFormat(blockPage[i][0])} ago§r - §3${getUserName(blockPage[i][1])} §r${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? "add" : blockPage[i][3] === 4 ? "remove" : "?"} §3${getBlockName(blockPage[i][2])}§r.\n`;
22+
if (blockPage[i][5] !== 1) output += `§7${timeFormat(blockPage[i][0])} ago§r - §3${getUserName(blockPage[i][1])} §r${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? `remove §3x${blockPage[i][4]}` : blockPage[i][3] === 4 ? `add §3x${blockPage[i][4]}` : "?"} §3${getBlockName(blockPage[i][2])}§r.\n`;
23+
else output += `§o§7${timeFormat(blockPage[i][0])} ago§r§o - §3${getUserName(blockPage[i][1])} §r§o${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? `remove §3x${blockPage[i][4]}` : blockPage[i][3] === 4 ? `add §3x${blockPage[i][4]}` : "?"} §3${getBlockName(blockPage[i][2])}§r§o.§r\n`;
5524
}
5625

5726
if (pageCount > 1) output += `-----\nPage 1/${pageCount}. View older data by typing "§3/co l <page>§r".`;
5827
pl.tell(output);
5928
}
60-
else pl.tell(action ? `§3CoreProtect §r- No data found at this location.` : `§3CoreProtect §r- No data found at §o${blockName.replace("minecraft:", "")}§r.`);
29+
else pl.tell(action ? "§3CoreProtect §r- No data found at this location." : `§3CoreProtect §r- No data found at §o${blockName.replace("minecraft:", "")}§r.`);
6130

6231
session.exec(`UPDATE co_user SET x = ${x}, y = ${y}, z = ${z}, wid = ${wid} WHERE id = ${getUserId(pl.realName)}`);
6332

@@ -80,27 +49,44 @@ function lookupPage(pl, page, out) {
8049

8150
let blockPage = getBlockPage(userData[0], userData[1], userData[2], userData[3], (page - 1) * 7);
8251
for (i = 1; i < blockPage.length; i++) {
83-
output += `§7${timeFormat(blockPage[i][0])} ago§r - §3${getUserName(blockPage[i][1])} §r${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? "add" : blockPage[i][3] === 4 ? "remove" : "?"} §3${getBlockName(blockPage[i][2])}§r.\n`;
52+
if (blockPage[i][5] !== 1) output += `§7${timeFormat(blockPage[i][0])} ago§r - §3${getUserName(blockPage[i][1])} §r${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? `remove x${blockPage[i][4]}` : blockPage[i][3] === 4 ? `add x${blockPage[i][4]}` : "?"} §3${getBlockName(blockPage[i][2])}§r.\n`;
53+
else output += `§o§7${timeFormat(blockPage[i][0])} ago§r§o - §3${getUserName(blockPage[i][1])} §r§o${blockPage[i][3] === 0 ? "broke" : blockPage[i][3] === 1 ? "placed" : blockPage[i][3] === 2 ? "clicked" : blockPage[i][3] === 3 ? `remove x${blockPage[i][4]}` : blockPage[i][3] === 4 ? `add x${blockPage[i][4]}` : "?"} §3${getBlockName(blockPage[i][2])}§r§o.§r\n`;
8454
}
8555

8656
if (pageCount > 1) output += `-----\nPage ${page}/${pageCount}. View older data by typing "§3/co l <page>§r".`;
8757
return out.success(output);
8858
}
8959

90-
function isInspector(playerName) {
91-
return session.query(`SELECT inspector FROM co_user WHERE id = ${getUserId(playerName)}`)[1][0];
92-
}
93-
94-
function setInspector(playerName, inspector) {
95-
session.exec(`UPDATE co_user SET inspector = ${inspector} WHERE id = ${getUserId(playerName)}`);
96-
}
60+
function rollback(pl, radius, time, user, out) {
61+
let blockData = session.query(`SELECT block, action, wid, x, y, z, data, count, slot FROM co_block WHERE ((x - ${pl.blockPos.x}) * (x - ${pl.blockPos.x}) + (y - ${pl.blockPos.y}) * (y - ${pl.blockPos.y}) + (z - ${pl.blockPos.z}) * (z - ${pl.blockPos.z}) <= ${radius ** 2}) and time > ${time !== undefined ? Date.now() - time * 3600000 : 0} and rollback == 0 and action != 2 ${user !== undefined ? `and user = ${getUserId(user)} ` : ""}ORDER BY time DESC`);
62+
if (blockData === undefined) return out.success("§3CoreProtect §r- No rollback data found at this location.");
63+
session.exec(`UPDATE co_block SET rollback = 1 WHERE ((x - ${pl.blockPos.x}) * (x - ${pl.blockPos.x}) + (y - ${pl.blockPos.y}) * (y - ${pl.blockPos.y}) + (z - ${pl.blockPos.z}) * (z - ${pl.blockPos.z}) <= ${radius ** 2}) and time > ${time !== undefined ? Date.now() - time * 3600000 : 0} and action != 2`);
64+
65+
for (i = 1; i < blockData.length; i++) {
66+
switch (blockData[i][1]) {
67+
case 0: // break
68+
let blockName = getBlockName(blockData[i][0]);
69+
mc.setBlock(blockData[i][3], blockData[i][4], blockData[i][5], blockData[i][2], `minecraft:${blockName === "water" || blockName === "lava" ? "flowing_" + blockName : blockName}`, blockData[i][6]);
70+
break;
71+
case 1: // place
72+
mc.setBlock(blockData[i][3], blockData[i][4], blockData[i][5], blockData[i][2], "minecraft:air", 0);
73+
break;
74+
case 3: // take out
75+
let ct = mc.getBlock(blockData[i][3], blockData[i][4], blockData[i][5], blockData[i][2]).getContainer();
76+
let it = mc.newItem(`minecraft:${getBlockName(blockData[i][0])}`, blockData[i][7] + ct.getAllItems()[blockData[i][8]].count);
77+
it.setAux(blockData[i][6]);
78+
ct.setItem(blockData[i][8], it);
79+
break;
80+
case 4: // put
81+
mc.getBlock(blockData[i][3], blockData[i][4], blockData[i][5], blockData[i][2]).getContainer().removeItem(blockData[i][8], blockData[i][7]);
82+
}
83+
}
9784

98-
function clearUserPos(playerName) {
99-
session.exec(`UPDATE co_user SET y = -256 WHERE id = ${getUserId(playerName)}`);
85+
return out.success("§3CoreProtect §r- Rollback completed.");
10086
}
10187

10288
function getBlockPage(wid, x, y, z, offset) {
103-
return session.query(`SELECT time, user, block, action FROM co_block WHERE wid = ${wid} AND x = ${x} AND y = ${y} AND z = ${z} ORDER BY time DESC LIMIT ${offset}, 7`);
89+
return session.query(`SELECT time, user, block, action, count, rollback FROM co_block WHERE wid = ${wid} AND x = ${x} AND y = ${y} AND z = ${z} ORDER BY time DESC LIMIT ${offset}, 7`);
10490
}
10591

10692
function getPageCount(wid, x, y, z) {
@@ -111,11 +97,55 @@ function timeFormat(time) {
11197
return `${((Date.now() - time) / 3600000).toFixed(2)}/h`.replace(".", ",");
11298
}
11399

100+
function getUserId(playerName) {
101+
let userId = session.query(`SELECT id FROM co_user WHERE nickname = "${playerName}"`);
102+
103+
if (userId === undefined) {
104+
session.exec(`INSERT INTO co_user (nickname) VALUES ("${playerName}")`);
105+
return session.query(`SELECT id FROM co_user WHERE nickname = "${playerName}"`)[1][0];
106+
}
107+
108+
return userId[1][0];
109+
}
110+
111+
function getUserName(userId) {
112+
return session.query(`SELECT nickname FROM co_user WHERE id = ${userId}`)[1][0];
113+
}
114+
115+
function getBlockId(blockName) {
116+
blockName = blockName.replace("minecraft:", "");
117+
let blockId = session.query(`SELECT id FROM co_art_map WHERE block = "${blockName}"`);
118+
119+
if (blockId === undefined) {
120+
session.exec(`INSERT INTO co_art_map (block) VALUES ("${blockName}")`);
121+
return session.query(`SELECT id FROM co_art_map WHERE block = "${blockName}"`)[1][0];
122+
}
123+
124+
return blockId[1][0];
125+
}
126+
127+
function getBlockName(blockId) {
128+
return session.query(`SELECT block FROM co_art_map WHERE id = ${blockId}`)[1][0];
129+
}
130+
131+
function isInspector(playerName) {
132+
return session.query(`SELECT inspector FROM co_user WHERE id = ${getUserId(playerName)}`)[1][0];
133+
}
134+
135+
function setInspector(playerName, inspector) {
136+
session.exec(`UPDATE co_user SET inspector = ${inspector} WHERE id = ${getUserId(playerName)}`);
137+
}
138+
139+
function clearUserPos(playerName) {
140+
session.exec(`UPDATE co_user SET y = -256 WHERE id = ${getUserId(playerName)}`);
141+
}
142+
114143
module.exports = {
115144
initDatabase,
116145
logBlock,
117146
isInspector,
118147
setInspector,
119148
lookupPage,
120-
clearUserPos
149+
clearUserPos,
150+
rollback
121151
};

listener.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
const { logBlock } = require("./database.js");
1+
const { logBlock, isInspector } = require("./database.js");
22

3-
mc.listen("onDestroyBlock", (pl, bl) => logBlock(pl, bl.name, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 0));
4-
mc.listen("afterPlaceBlock", (pl, bl) => logBlock(pl, bl.name, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 1));
5-
mc.listen("onBlockInteracted", (pl, bl) => logBlock(pl, bl.name, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 2));
3+
mc.listen("onDestroyBlock", (pl, bl) => logBlock(pl, bl.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 0, bl.tileData));
4+
mc.listen("afterPlaceBlock", (pl, bl) => logBlock(pl, bl.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 1, bl.tileData));
5+
mc.listen("onBlockInteracted", (pl, bl) => logBlock(pl, bl.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 2, bl.tileData));
6+
mc.listen("onOpenContainer", (pl) => isInspector(pl.realName) ? false : true);
67

78
mc.listen("onUseItemOn", (pl, it, bl, side, pos) => {
89
if (it.type === "minecraft:bucket" && (bl.type === "minecraft:powder_snow" || bl.type === "minecraft:water" || bl.type === "minecraft:flowing_water" || bl.type === "minecraft:lava" || bl.type === "minecraft:flowing_lava")) {
9-
return logBlock(pl, bl.type.replace("flowing_", ""), bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 0);
10+
return logBlock(pl, bl.type.replace("flowing_", ""), bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 0, bl.tileData);
1011
}
1112

1213
let x = bl.pos.x, y = bl.pos.y, z = bl.pos.z;
@@ -32,7 +33,7 @@ mc.listen("onUseItemOn", (pl, it, bl, side, pos) => {
3233
bl = mc.getBlock(x, y, z, bl.pos.dimid);
3334

3435
if (it.type !== "minecraft:bucket" && it.type.includes("_bucket") && (bl.type === "minecraft:air" || bl.type === "minecraft:powder_snow" || bl.type === "minecraft:water" || bl.type === "minecraft:flowing_water" || bl.type === "minecraft:lava" || bl.type === "minecraft:flowing_lava")) {
35-
if (!logBlock(pl, it.type.replace("_bucket", ""), bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 1)) {
36+
if (!logBlock(pl, it.type.replace("_bucket", ""), bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 1, bl.tileData)) {
3637
mc.setBlock(bl.pos, bl.type, bl.tileData);
3738
return false;
3839
}
@@ -42,13 +43,15 @@ mc.listen("onUseItemOn", (pl, it, bl, side, pos) => {
4243
});
4344

4445
mc.listen("onContainerChange", (pl, bl, slotNum, oldIt, newIt) => {
45-
if (!oldIt.isNull() && newIt.isNull()) logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 3); // take out
46+
if (!oldIt.isNull() && newIt.isNull()) return logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 3, oldIt.aux, oldIt.count, slotNum); // take out
47+
if (oldIt.isNull() && !newIt.isNull()) return logBlock(pl, newIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 4, newIt.aux, newIt.count, slotNum); // put
4648

47-
if (oldIt.isNull() && !newIt.isNull()) logBlock(pl, newIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 4); // put
49+
if (oldIt.type === newIt.type && oldIt.count > newIt.count) return logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 3, oldIt.aux, oldIt.count - newIt.count, slotNum); // -
50+
if (oldIt.type === newIt.type && oldIt.count < newIt.count) return logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 4, oldIt.aux, newIt.count - oldIt.count, slotNum); // +
4851

49-
if (!oldIt.isNull() && !newIt.isNull()) { // replace
50-
logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 3);
51-
logBlock(pl, newIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 4);
52+
if (oldIt.type !== newIt.type && !oldIt.isNull() && !newIt.isNull()) { // replace
53+
logBlock(pl, oldIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 3, oldIt.aux, oldIt.count, slotNum);
54+
return logBlock(pl, newIt.type, bl.pos.dimid, bl.pos.x, bl.pos.y, bl.pos.z, 4, newIt.aux, newIt.count, slotNum);
5255
}
5356
});
5457

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "coreprotectmini",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Stripped down version of CoreProtect",
55
"main": "main.js",
66
"author": "KocTu4eK",

0 commit comments

Comments
 (0)