Skip to content

Commit ab2c8f6

Browse files
committed
ロールバック時にページの増減が考慮されていなかった問題を修正
1 parent ba476d4 commit ab2c8f6

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

src/main/java/dev/felnull/DataIO/OperationType.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ public enum OperationType {
55
REMOVE,
66
UPDATE,
77
CLEAR,
8-
MOVE;
8+
MOVE,
9+
PAGE_CREATE,
10+
PAGE_DELETE,
11+
PAGE_META,
12+
PAGE_RENAME;
913

1014
/**
1115
* データベースに保存する文字列形式を取得(必要なら小文字にしても可)

src/main/java/dev/felnull/DataIO/TableInitializer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public static void initTables() {
9999
addColumnIfNotExists(conn, "diff_log_inventory_items", "amount", "INT");
100100
addColumnIfNotExists(conn, "diff_log_inventory_items", "operation_type", "VARCHAR(32)");
101101
addColumnIfNotExists(conn, "diff_log_inventory_items", "timestamp", "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
102+
addColumnIfNotExists(conn, "diff_log_inventory_items", "meta_json", "TEXT");
102103

103104
// diff_log_tags
104105
addColumnIfNotExists(conn, "diff_log_tags", "plugin_name", "VARCHAR(255) NOT NULL");

src/main/java/dev/felnull/DataIO/UnifiedLogManager.java

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dev.felnull.DataIO;
22

33
import com.google.gson.Gson;
4+
import com.google.gson.JsonObject;
5+
import com.google.gson.JsonParser;
46
import dev.felnull.BetterStorage;
57
import dev.felnull.Data.*;
68
import org.bukkit.Bukkit;
@@ -22,6 +24,8 @@
2224
import java.util.zip.GZIPInputStream;
2325
import java.util.zip.GZIPOutputStream;
2426

27+
import static dev.felnull.DataIO.DataIO.db;
28+
2529
public class UnifiedLogManager {
2630
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
2731
private static final Gson gson = new Gson();
@@ -252,6 +256,72 @@ public static boolean applyForwardDiffs(GroupData groupData, LocalDateTime from,
252256
UUID groupUUID = groupData.groupUUID;
253257

254258
try (Connection conn = db.getConnection()) {
259+
260+
// ===== 0) 構造イベント(先にページ集合を正す)=====
261+
try (PreparedStatement ps = conn.prepareStatement(
262+
"SELECT page_id, operation_type, meta_json, timestamp " +
263+
"FROM diff_log_inventory_items " +
264+
"WHERE group_uuid=? AND plugin_name=? AND timestamp > ? AND timestamp <= ? " +
265+
"AND operation_type IN ('PAGE_CREATE','PAGE_DELETE','PAGE_META','PAGE_RENAME') " +
266+
"ORDER BY timestamp ASC")) {
267+
268+
ps.setString(1, groupUUID.toString());
269+
ps.setString(2, groupData.ownerPlugin);
270+
ps.setString(3, from.format(FORMATTER));
271+
ps.setString(4, to.format(FORMATTER));
272+
273+
try (ResultSet rs = ps.executeQuery()) {
274+
while (rs.next()) {
275+
String pageId = rs.getString("page_id");
276+
String op = rs.getString("operation_type");
277+
String metaJson = null;
278+
try { metaJson = rs.getString("meta_json"); } catch (SQLException ignore) {}
279+
280+
switch (op) {
281+
case "PAGE_CREATE": {
282+
ensurePagePresentOrCreate(groupData, pageId);
283+
break;
284+
}
285+
case "PAGE_DELETE": {
286+
groupData.storageData.storageInventory.remove(pageId);
287+
break;
288+
}
289+
case "PAGE_META": { // 任意:rows は final なら再生成 or 後でDBから拾う
290+
InventoryData inv = ensurePagePresentOrCreate(groupData, pageId);
291+
if (metaJson != null) {
292+
try {
293+
JsonObject m = new JsonParser().parse(metaJson).getAsJsonObject();
294+
if (m.has("displayName")) inv.displayName = m.get("displayName").getAsString();
295+
if (m.has("requirePermission")) {
296+
String csv = m.get("requirePermission").getAsString();
297+
inv.requirePermission = csv.isEmpty()
298+
? new HashSet<>()
299+
: new HashSet<>(Arrays.asList(csv.split(",")));
300+
}
301+
if (m.has("version")) inv.version = m.get("version").getAsLong();
302+
// rows は inv.rows が final なら、新しい InventoryData を作って置き換える
303+
} catch (Exception ignore) {}
304+
}
305+
break;
306+
}
307+
case "PAGE_RENAME": { // 任意
308+
if (metaJson != null) {
309+
try {
310+
JsonObject rn = new JsonParser().parse(metaJson).getAsJsonObject();
311+
String oldId = rn.get("old").getAsString();
312+
String newId = rn.get("new").getAsString();
313+
InventoryData inv = groupData.storageData.storageInventory.remove(oldId);
314+
if (inv == null) inv = ensurePagePresentOrCreate(groupData, oldId);
315+
groupData.storageData.storageInventory.put(newId, inv);
316+
} catch (Exception ignore) {}
317+
}
318+
break;
319+
}
320+
}
321+
}
322+
}
323+
}
324+
255325
// ----- アイテムの差分適用 -----
256326
Set<LocalDateTime> appliedTimestamps = new LinkedHashSet<>();
257327
String itemSql = "SELECT page_id, slot, itemstack, timestamp FROM diff_log_inventory_items " +
@@ -331,6 +401,18 @@ public static boolean applyForwardDiffs(GroupData groupData, LocalDateTime from,
331401
}
332402
}
333403

404+
// ★ 追加:存在しなければ最小メタで作る(inventory_table から拾えるならそこで埋めてOK)
405+
private static InventoryData ensurePagePresentOrCreate(GroupData groupData, String pageId) {
406+
Map<String, InventoryData> map = groupData.storageData.storageInventory;
407+
InventoryData inv = map.get(pageId);
408+
if (inv != null) return inv;
409+
410+
// 既知のメタがあれば取ってくる(簡易版:行数6・空権限でプレースホルダ)
411+
inv = new InventoryData(pageId, 6, new HashSet<>(), new HashMap<>());
412+
inv.setFullyLoaded(true);
413+
map.put(pageId, inv);
414+
return inv;
415+
}
334416

335417
public static void saveDiffLogs(DatabaseManager db, GroupData groupData) {
336418
try (Connection conn = db.getConnection()) {
@@ -695,5 +777,42 @@ public static boolean logTagDiffsForPage(Connection conn, GroupData groupData,
695777
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
696778
return saveTagDiffs(conn, groupData, inv, pageId, now);
697779
}
780+
781+
private static void logPageEvent(UUID groupUUID, String pluginName,
782+
String pageId, OperationType op, @Nullable String metaJson) throws SQLException {
783+
try (PreparedStatement ps = db.getConnection().prepareStatement(
784+
"INSERT INTO diff_log_inventory_items " +
785+
"(group_uuid, plugin_name, page_id, slot, operation_type, itemstack, old_itemstack, meta_json, timestamp) " +
786+
"VALUES (?,?,?,?,?,NULL,NULL,?,CURRENT_TIMESTAMP)")) {
787+
ps.setString(1, groupUUID.toString());
788+
ps.setString(2, pluginName);
789+
ps.setString(3, pageId);
790+
ps.setInt(4, -1); // 構造イベントの印
791+
ps.setString(5, op.toDbString()); // 'PAGE_CREATE' / 'PAGE_DELETE' / 'PAGE_META' / 'PAGE_RENAME'
792+
ps.setString(6, metaJson);
793+
ps.executeUpdate();
794+
}
795+
}
796+
/*
797+
logPageEvent(conn, groupUUID, group.ownerPlugin, pageId, "PAGE_CREATE", null);
798+
logPageEvent(conn, groupUUID, group.ownerPlugin, pageId, "PAGE_DELETE", null);
799+
diffCreateLogMeta
800+
diffRename
801+
を適切に呼ぶこと
802+
*/
803+
public static void diffCreateLogMeta(UUID groupUUID, String pluginName, String pageID, String displayName, int rows, Set<String> requirePermission) throws SQLException {
804+
JsonObject meta = new JsonObject();
805+
meta.addProperty("displayName", displayName);
806+
meta.addProperty("rows", rows);
807+
meta.addProperty("requirePermission", String.join(",", requirePermission));
808+
logPageEvent(groupUUID, pluginName, pageID, OperationType.PAGE_META, meta.toString());
809+
}
810+
811+
public static void diffRename(UUID groupUUID, String pluginName, String pageID, String oldId, String newId) throws SQLException {
812+
JsonObject rn = new JsonObject();
813+
rn.addProperty("old", oldId);
814+
rn.addProperty("new", newId);
815+
logPageEvent(groupUUID, pluginName, pageID, OperationType.PAGE_RENAME, rn.toString());
816+
}
698817
}
699818

src/main/java/dev/felnull/commands/BetterStorageCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,10 +525,12 @@ public void run() {
525525
default:
526526
sender.sendMessage("使用可能なコマンド:");
527527
sender.sendMessage("/bstorage rollback <groupName/playerName> <yyyy-MM-dd HH:mm:ss> - 指定した時点に巻き戻す");
528-
sender.sendMessage("/bstorage list <groupName/playerName> - 利用可能なログ日時を表示");
528+
sender.sendMessage("/bstorage rollbacklist <groupName/playerName> - 利用可能なログ日時を表示");
529529
sender.sendMessage("/bstorage diff <groupName/playerName> <yyyy-MM-dd HH:mm:ss> - 差分ログから状態を復元");
530530
sender.sendMessage("/bstorage difflist <groupName/playerName> - 差分ログの日時一覧を表示");
531531
sender.sendMessage("/bstorage backup <groupName/playerName> - 現在の状態で強制バックアップ");
532+
sender.sendMessage("/bstorage recover <groupUUID> 削除済みのグループを復旧");
533+
sender.sendMessage("/bstorage wipedata <GroupName/PlayerName> グループを削除");
532534
break;
533535

534536
}

0 commit comments

Comments
 (0)