|
1 | 1 | package dev.felnull.DataIO; |
2 | 2 |
|
3 | 3 | import com.google.gson.Gson; |
| 4 | +import com.google.gson.JsonObject; |
| 5 | +import com.google.gson.JsonParser; |
4 | 6 | import dev.felnull.BetterStorage; |
5 | 7 | import dev.felnull.Data.*; |
6 | 8 | import org.bukkit.Bukkit; |
|
22 | 24 | import java.util.zip.GZIPInputStream; |
23 | 25 | import java.util.zip.GZIPOutputStream; |
24 | 26 |
|
| 27 | +import static dev.felnull.DataIO.DataIO.db; |
| 28 | + |
25 | 29 | public class UnifiedLogManager { |
26 | 30 | private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
27 | 31 | private static final Gson gson = new Gson(); |
@@ -252,6 +256,72 @@ public static boolean applyForwardDiffs(GroupData groupData, LocalDateTime from, |
252 | 256 | UUID groupUUID = groupData.groupUUID; |
253 | 257 |
|
254 | 258 | 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 | + |
255 | 325 | // ----- アイテムの差分適用 ----- |
256 | 326 | Set<LocalDateTime> appliedTimestamps = new LinkedHashSet<>(); |
257 | 327 | 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, |
331 | 401 | } |
332 | 402 | } |
333 | 403 |
|
| 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 | + } |
334 | 416 |
|
335 | 417 | public static void saveDiffLogs(DatabaseManager db, GroupData groupData) { |
336 | 418 | try (Connection conn = db.getConnection()) { |
@@ -695,5 +777,42 @@ public static boolean logTagDiffsForPage(Connection conn, GroupData groupData, |
695 | 777 | .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); |
696 | 778 | return saveTagDiffs(conn, groupData, inv, pageId, now); |
697 | 779 | } |
| 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 | + } |
698 | 817 | } |
699 | 818 |
|
0 commit comments