Skip to content

Commit 670e6c8

Browse files
committed
差がない場合に保存しないように改良
1 parent 9b9e5d4 commit 670e6c8

File tree

5 files changed

+525
-379
lines changed

5 files changed

+525
-379
lines changed

src/main/java/dev/felnull/Data/GroupData.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.felnull.Data;
22

3+
import dev.felnull.DataIO.DataIO;
34
import dev.felnull.DataIO.GroupManager;
45
import org.bukkit.OfflinePlayer;
56
import org.jetbrains.annotations.NotNull;
@@ -61,37 +62,33 @@ public GroupData(@NotNull OfflinePlayer player, StorageData storageData, String
6162
// === GroupManagerラッパー ===
6263
// ===============================
6364

64-
/** groupName → UUID(キャッシュから) */
65+
/** groupName → UUID */
6566
public static @Nullable UUID resolveUUID(String groupName) {
66-
return GroupManager.resolveUUID(groupName);
67+
GroupData data = DataIO.loadGroupData(groupName);
68+
return data != null ? data.groupUUID : null;
6769
}
6870

69-
/** groupUUID → groupName(キャッシュから) */
71+
/** groupUUID → groupName */
7072
public static @Nullable String resolveName(UUID groupUUID) {
71-
return GroupManager.resolveName(groupUUID);
73+
GroupData data = DataIO.loadGroupData(groupUUID);
74+
return data != null ? data.groupName : null;
7275
}
7376

74-
/** groupUUID → GroupData(キャッシュから) */
77+
/** groupUUID → GroupData */
7578
public static @Nullable GroupData resolveByUUID(UUID groupUUID) {
76-
return GroupManager.getGroupByUUID(groupUUID);
79+
return DataIO.loadGroupData(groupUUID);
7780
}
7881

79-
/** groupName → GroupData(キャッシュから) */
82+
/** groupName → GroupData */
8083
public static @Nullable GroupData resolveByName(String groupName) {
81-
return GroupManager.getGroupByName(groupName);
84+
return DataIO.loadGroupData(groupName);
8285
}
8386

84-
/** プレイヤーが属している全GroupDataを取得(キャッシュから) */
85-
public static @NotNull List<GroupData> resolveByPlayer(OfflinePlayer player) {
86-
List<String> groupNames = GroupManager.getGroupsForPlayer(player);
87-
List<GroupData> result = new ArrayList<>();
88-
for (String name : groupNames) {
89-
GroupData gd = resolveByName(name);
90-
if (gd != null) {
91-
result.add(gd);
92-
}
93-
}
94-
return result;
87+
/**
88+
* 指定されたプレイヤーが所属している全 GroupData を返すラッパー(DataIOベース)。
89+
*/
90+
public static List<GroupData> getGroupsOfPlayer(OfflinePlayer player) {
91+
return DataIO.loadGroupsByPlayer(player);
9592
}
9693

9794
public GroupData deepClone(StorageData storageData) {

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

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.bukkit.Material;
1212
import org.bukkit.OfflinePlayer;
1313
import org.bukkit.inventory.ItemStack;
14+
import org.jetbrains.annotations.NotNull;
1415
import org.jetbrains.annotations.Nullable;
1516

1617
import java.io.File;
@@ -74,6 +75,11 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
7475
return false;
7576
}
7677

78+
if (isInventoryDataSame(conn, g, pageId, inv)) {
79+
Bukkit.getLogger().info("[BetterStorage][debug] データが変更されていないため更新しません。");
80+
return true; // データが一致していれば更新しない
81+
}
82+
7783
// ✅ 楽観ロック:保存前に version を進める
7884
inv.version++;
7985

@@ -172,6 +178,8 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
172178
ps.executeBatch();
173179
}
174180

181+
182+
175183
// ---------- tag_table ----------
176184
String tagSql = "REPLACE INTO tag_table (group_uuid, plugin_name, page_id, user_tag) VALUES (?, ?, ?, ?)";
177185
try (PreparedStatement ps = conn.prepareStatement(tagSql)) {
@@ -190,6 +198,87 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
190198
return true;
191199
}
192200

201+
// 新しいデータとDB上のデータが同じかチェック
202+
private static boolean isInventoryDataSame(Connection conn, GroupData g, String pageId, InventoryData inv) throws SQLException {
203+
// DBから現在のデータを取得
204+
String sql = "SELECT display_name, row_count, require_permission, version FROM inventory_table WHERE group_uuid = ? AND page_id = ?";
205+
try (PreparedStatement ps = conn.prepareStatement(sql)) {
206+
ps.setString(1, g.groupUUID.toString());
207+
ps.setString(2, pageId);
208+
try (ResultSet rs = ps.executeQuery()) {
209+
if (rs.next()) {
210+
String dbDisplayName = rs.getString("display_name");
211+
int dbRowCount = rs.getInt("row_count");
212+
String dbRequirePermission = rs.getString("require_permission");
213+
long dbVersion = rs.getLong("version");
214+
215+
// displayNameの比較(nullでも比較できる)
216+
if ((inv.displayName == null && dbDisplayName != null) || (inv.displayName != null && !inv.displayName.equals(dbDisplayName))) {
217+
return false;
218+
}
219+
220+
if (dbRowCount != inv.rows) {
221+
return false;
222+
}
223+
224+
// require_permissionの比較(必要に応じてJSON解析)
225+
if (!dbRequirePermission.equals(gson.toJson(inv.requirePermission))) {
226+
return false;
227+
}
228+
229+
// バージョンチェック
230+
if (dbVersion != inv.version) {
231+
return false;
232+
}
233+
234+
// アイテムスロットの比較(インベントリ内容の差異をチェック)
235+
String fetchItemsSql = "SELECT slot, itemstack FROM inventory_item_table WHERE group_uuid = ? AND page_id = ?";
236+
Map<Integer, String> dbItemsMap = new HashMap<>();
237+
try (PreparedStatement psItems = conn.prepareStatement(fetchItemsSql)) {
238+
psItems.setString(1, g.groupUUID.toString());
239+
psItems.setString(2, pageId);
240+
try (ResultSet rsItems = psItems.executeQuery()) {
241+
while (rsItems.next()) {
242+
dbItemsMap.put(rsItems.getInt("slot"), rsItems.getString("itemstack"));
243+
}
244+
}
245+
}
246+
247+
// 現在のアイテムスロットとDBのアイテムスロットを比較
248+
if (!compareInventoryItems(dbItemsMap, inv.itemStackSlot)) {
249+
return false;
250+
}
251+
252+
return true;
253+
}
254+
}
255+
}
256+
return false;
257+
}
258+
259+
// アイテムの比較メソッド
260+
private static boolean compareInventoryItems(Map<Integer, String> dbItems, Map<Integer, ItemStack> clientItems) {
261+
// アイテムの数が違う場合は即座に差異あり
262+
if (dbItems.size() != clientItems.size()) {
263+
return false;
264+
}
265+
266+
// スロットごとにアイテムを比較
267+
for (Map.Entry<Integer, ItemStack> clientEntry : clientItems.entrySet()) {
268+
int slot = clientEntry.getKey();
269+
ItemStack clientItem = clientEntry.getValue();
270+
String dbItemBase64 = dbItems.get(slot);
271+
272+
// DBアイテムとクライアントアイテムが異なる場合
273+
String clientItemBase64 = ItemSerializer.serializeToBase64(clientItem);
274+
if (!clientItemBase64.equals(dbItemBase64)) {
275+
return false;
276+
}
277+
}
278+
279+
return true;
280+
}
281+
193282

194283

195284

@@ -664,6 +753,31 @@ public static long getInventoryPageVersion(Connection conn, UUID groupUUID, Stri
664753
}
665754
}
666755

756+
/** プレイヤーが属しているすべてのGroupDataを取得(group_member_tableベース) */
757+
public static @NotNull List<GroupData> loadGroupsByPlayer(OfflinePlayer player) {
758+
List<GroupData> result = new ArrayList<>();
759+
UUID playerUUID = player.getUniqueId();
760+
761+
try (Connection conn = db.getConnection()) {
762+
String sql = "SELECT DISTINCT group_uuid FROM group_member_table WHERE member_uuid = ?";
763+
try (PreparedStatement ps = conn.prepareStatement(sql)) {
764+
ps.setString(1, playerUUID.toString());
765+
try (ResultSet rs = ps.executeQuery()) {
766+
while (rs.next()) {
767+
UUID groupUUID = UUID.fromString(rs.getString("group_uuid"));
768+
GroupData gd = loadGroupData(groupUUID);
769+
if (gd != null) {
770+
result.add(gd);
771+
}
772+
}
773+
}
774+
}
775+
} catch (SQLException e) {
776+
Bukkit.getLogger().warning("プレイヤー所属グループ取得に失敗: " + e.getMessage());
777+
}
778+
779+
return result;
780+
}
667781

668782
// ===========================================================
669783
// ===== 3. DELETE ==========================================
@@ -672,9 +786,9 @@ public static long getInventoryPageVersion(Connection conn, UUID groupUUID, Stri
672786
public static void deletePageData(Connection conn, UUID groupUUID, String pluginName, String pageId, String executedBy) throws SQLException {
673787

674788
// 差分ログを削除前に保存
675-
GroupData group = GroupManager.getGroupByUUID(groupUUID);
789+
GroupData group = loadGroupData(groupUUID);
676790
if (group != null) {
677-
UnifiedLogManager.saveDiffLogs(BetterStorage.BSPlugin.getDatabaseManager(), group);
791+
UnifiedLogManager.saveBackupSnapshot(group);
678792
}
679793

680794
String[] sqls = {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ public static void initTables() {
152152
");"
153153
);
154154

155+
// ロールバック用の完全バックアップ
156+
stmt.executeUpdate(
157+
"CREATE TABLE IF NOT EXISTS rollback_log (" +
158+
"group_uuid VARCHAR(255) NOT NULL, " + // 所属グループ
159+
"timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + // バックアップ時刻
160+
"json_data LONGBLOB NOT NULL, " + // グループ全体のシリアライズJSON(※圧縮バイナリ対応のためLONGBLOBに変更)
161+
"PRIMARY KEY (group_uuid, timestamp)" + // 時刻単位で識別
162+
");"
163+
);
164+
155165
LOGGER.info("[BetterStorage] 全テーブルの初期化が完了しました。");
156166

157167
} catch (SQLException e) {

0 commit comments

Comments
 (0)