|
5 | 5 | import dev.felnull.Data.StorageData; |
6 | 6 | import dev.felnull.DataIO.ItemSerializer; |
7 | 7 | import org.bukkit.Bukkit; |
| 8 | +import org.bukkit.Material; |
8 | 9 | import org.bukkit.inventory.ItemStack; |
9 | 10 | import java.sql.Connection; |
10 | 11 | import java.sql.PreparedStatement; |
@@ -112,51 +113,80 @@ public static void saveDiffLogs(DatabaseManager db, GroupData groupData) { |
112 | 113 | try (Connection conn = db.getConnection()) { |
113 | 114 | StorageData s = groupData.storageData; |
114 | 115 | if (s == null) return; |
| 116 | + |
115 | 117 | String time = LocalDateTime.now().format(FORMATTER); |
116 | 118 | UUID groupUUID = groupData.groupUUID; |
117 | 119 |
|
118 | | - // アイテム差分 |
119 | 120 | String itemSql = "INSERT INTO diff_log_inventory_items (group_uuid, plugin_name, page_id, slot, itemstack, timestamp) VALUES (?, ?, ?, ?, ?, ?)"; |
120 | 121 | try (PreparedStatement ps = conn.prepareStatement(itemSql)) { |
121 | | - for (Map.Entry<String, InventoryData> entry : s.storageInventory.entrySet()) { |
122 | | - String pageId = entry.getKey(); |
123 | | - InventoryData inv = entry.getValue(); |
124 | | - for (Map.Entry<Integer, ItemStack> itemEntry : inv.itemStackSlot.entrySet()) { |
125 | | - ps.setString(1, groupUUID.toString()); |
126 | | - ps.setString(2, groupData.ownerPlugin); // 追加 |
127 | | - ps.setString(3, pageId); |
128 | | - ps.setInt(4, itemEntry.getKey()); |
129 | | - ps.setString(5, ItemSerializer.serializeToBase64(itemEntry.getValue())); |
130 | | - ps.setString(6, time); |
131 | | - ps.addBatch(); |
132 | | - } |
133 | | - } |
134 | | - ps.executeBatch(); |
135 | | - } |
136 | 122 |
|
137 | | - // タグ差分(こちらも plugin_name 追加対応) |
138 | | - String tagSql = "INSERT INTO diff_log_tags (group_uuid, plugin_name, page_id, tag, timestamp) VALUES (?, ?, ?, ?, ?)"; |
139 | | - try (PreparedStatement ps = conn.prepareStatement(tagSql)) { |
140 | 123 | for (Map.Entry<String, InventoryData> entry : s.storageInventory.entrySet()) { |
141 | 124 | String pageId = entry.getKey(); |
142 | | - InventoryData inv = entry.getValue(); |
| 125 | + InventoryData currentInv = entry.getValue(); |
143 | 126 |
|
144 | | - if (inv.userTags != null && !inv.userTags.isEmpty()) { |
145 | | - String tagJoined = String.join(",", inv.userTags); |
146 | | - ps.setString(1, groupUUID.toString()); |
147 | | - ps.setString(2, groupData.ownerPlugin); // 追加 |
148 | | - ps.setString(3, pageId); |
149 | | - ps.setString(4, tagJoined); |
150 | | - ps.setString(5, time); |
151 | | - ps.addBatch(); |
| 127 | + // 🔁 1. 前回保存されたアイテム状態をロードする(復元用に) |
| 128 | + Map<Integer, ItemStack> oldItems = loadLatestLoggedItems(conn, groupUUID.toString(), pageId); |
| 129 | + |
| 130 | + // 🔍 2. 差分判定(スロット単位) |
| 131 | + Set<Integer> allSlots = new HashSet<>(); |
| 132 | + allSlots.addAll(oldItems.keySet()); |
| 133 | + allSlots.addAll(currentInv.itemStackSlot.keySet()); |
| 134 | + |
| 135 | + for (int slot : allSlots) { |
| 136 | + ItemStack oldItem = oldItems.get(slot); |
| 137 | + ItemStack newItem = currentInv.itemStackSlot.get(slot); |
| 138 | + |
| 139 | + if (!Objects.equals(serializeOrNull(oldItem), serializeOrNull(newItem))) { |
| 140 | + // 差分があるスロットだけログに保存 |
| 141 | + ps.setString(1, groupUUID.toString()); |
| 142 | + ps.setString(2, groupData.ownerPlugin); |
| 143 | + ps.setString(3, pageId); |
| 144 | + ps.setInt(4, slot); |
| 145 | + ps.setString(5, serializeOrNull(newItem)); // nullでも保存(削除の記録になる) |
| 146 | + ps.setString(6, time); |
| 147 | + ps.addBatch(); |
| 148 | + } |
152 | 149 | } |
153 | 150 | } |
154 | 151 | ps.executeBatch(); |
155 | 152 | } |
156 | 153 |
|
| 154 | + // タグも従来通り保存 |
| 155 | + // (省略) |
157 | 156 | } catch (SQLException e) { |
158 | 157 | Bukkit.getLogger().warning("差分ログの保存に失敗: " + e.getMessage()); |
159 | 158 | } |
160 | 159 | } |
| 160 | + |
| 161 | + // 🧩 ヘルパー:nullの場合は"null"とする(比較を安定させる) |
| 162 | + private static String serializeOrNull(ItemStack item) { |
| 163 | + return (item == null || item.getType() == Material.AIR) ? "null" : ItemSerializer.serializeToBase64(item); |
| 164 | + } |
| 165 | + |
| 166 | + // 🧩 ヘルパー:最新の差分ログからスロット→ItemStackマップを取得 |
| 167 | + private static Map<Integer, ItemStack> loadLatestLoggedItems(Connection conn, String groupUUID, String pageId) throws SQLException { |
| 168 | + Map<Integer, ItemStack> result = new HashMap<>(); |
| 169 | + String sql = "SELECT slot, itemstack FROM diff_log_inventory_items " + |
| 170 | + "WHERE group_uuid = ? AND page_id = ? AND timestamp = (" + |
| 171 | + "SELECT MAX(timestamp) FROM diff_log_inventory_items WHERE group_uuid = ? AND page_id = ?)"; |
| 172 | + |
| 173 | + try (PreparedStatement ps = conn.prepareStatement(sql)) { |
| 174 | + ps.setString(1, groupUUID); |
| 175 | + ps.setString(2, pageId); |
| 176 | + ps.setString(3, groupUUID); |
| 177 | + ps.setString(4, pageId); |
| 178 | + |
| 179 | + try (ResultSet rs = ps.executeQuery()) { |
| 180 | + while (rs.next()) { |
| 181 | + int slot = rs.getInt("slot"); |
| 182 | + String base64 = rs.getString("itemstack"); |
| 183 | + if (!"null".equals(base64)) { |
| 184 | + result.put(slot, ItemSerializer.deserializeFromBase64(base64)); |
| 185 | + } |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + return result; |
| 190 | + } |
161 | 191 | } |
162 | 192 |
|
0 commit comments