33import org .bukkit .Bukkit ;
44import org .bukkit .Material ;
55import org .bukkit .Sound ;
6- import org .bukkit .command .CommandSender ;
76import org .bukkit .configuration .file .FileConfiguration ;
87import org .bukkit .entity .Player ;
98import org .bukkit .event .EventHandler ;
9+ import org .bukkit .event .EventPriority ;
1010import org .bukkit .event .Listener ;
1111import org .bukkit .event .inventory .ClickType ;
12+ import org .bukkit .event .inventory .InventoryAction ;
1213import org .bukkit .event .inventory .InventoryClickEvent ;
1314import org .bukkit .event .inventory .InventoryCloseEvent ;
1415import org .bukkit .inventory .Inventory ;
@@ -22,6 +23,9 @@ public class GUIManager implements Listener {
2223 private final Map <UUID , SettingSession > sessions = new HashMap <>();
2324 private final Map <UUID , String > activeGuiId = new HashMap <>();
2425
26+ // インベントリ切り替え中にCloseEventを無視するためのフラグ
27+ private final Set <UUID > switchingPlayers = new HashSet <>();
28+
2529 public GUIManager (SimplePointPlugin plugin ) {
2630 this .plugin = plugin ;
2731 }
@@ -32,14 +36,15 @@ private static class SettingSession {
3236 }
3337
3438 public void openRewardGUI (Player player , String pointName , boolean isAdmin ) {
39+ switchingPlayers .add (player .getUniqueId ()); // 切り替えフラグON
40+
3541 String displayName = plugin .getPointManager ().getDisplayName (pointName );
3642 String title = displayName + (isAdmin ? "§r:編集" : "§r:受け取り" );
3743 Inventory gui = Bukkit .createInventory (null , 54 , title );
3844
3945 activeGuiId .put (player .getUniqueId (), pointName );
4046
4147 FileConfiguration config = plugin .getRewardManager ().getRewardConfig (pointName );
42-
4348 if (config != null ) {
4449 for (String key : config .getKeys (false )) {
4550 try {
@@ -59,38 +64,34 @@ public void openRewardGUI(Player player, String pointName, boolean isAdmin) {
5964 if (stock == 0 ) isSoldOut = true ;
6065 }
6166 }
62-
6367 if (isAdmin ) isSoldOut = false ;
6468
6569 ItemMeta meta = item .getItemMeta ();
6670 if (price != -1 && meta != null ) {
6771 List <String > lore = meta .hasLore () ? meta .getLore () : new ArrayList <>();
6872 lore .add ("§8----------" );
69-
7073 if (isSoldOut ) {
7174 item .setType (Material .BARRIER );
7275 lore .add ("§c§l在庫切れ / 購入不可" );
7376 } else {
7477 lore .add ("§e価格: §f" + price + " pt" );
7578 }
76-
7779 if (isPersonal ) {
7880 int bought = getPersonalBoughtCount (player , pointName , slot );
7981 lore .add ("§b個人在庫: §f" + (stock == -1 ? "なし" : bought + " / " + stock ));
8082 } else {
8183 lore .add ("§b共有在庫: §f" + (stock == -1 ? "無限" : stock ));
8284 }
83-
8485 if (req > 0 ) lore .add ("§6必要解放pt: §f" + req );
8586 meta .setLore (lore );
8687 }
87-
8888 item .setItemMeta (meta );
8989 gui .setItem (slot , item );
9090 } catch (Exception ignored ) {}
9191 }
9292 }
9393 player .openInventory (gui );
94+ switchingPlayers .remove (player .getUniqueId ()); // 切り替えフラグOFF
9495 }
9596
9697 @ EventHandler
@@ -107,7 +108,12 @@ public void onInventoryClick(InventoryClickEvent event) {
107108 else if (title .contains (":編集" )) {
108109 if (event .getRawSlot () < 0 || event .getRawSlot () >= 54 ) return ;
109110 event .setCancelled (true );
110- if (pId == null ) return ;
111+
112+ // pIdがnullの場合、タイトルから復元を試みる(最終防衛ライン)
113+ if (pId == null ) {
114+ pId = title .split (":" )[0 ].replace ("§r" , "" );
115+ activeGuiId .put (player .getUniqueId (), pId );
116+ }
111117
112118 ItemStack cursor = event .getCursor ();
113119 ItemStack clicked = event .getCurrentItem ();
@@ -126,16 +132,20 @@ else if (title.startsWith("報酬設定:")) {
126132 }
127133 }
128134
129- @ EventHandler
135+ @ EventHandler ( priority = EventPriority . LOWEST )
130136 public void onInventoryClose (InventoryCloseEvent event ) {
131- activeGuiId .remove (event .getPlayer ().getUniqueId ());
137+ UUID uuid = event .getPlayer ().getUniqueId ();
138+ // 画面切り替え中でなければ、データを削除する
139+ if (!switchingPlayers .contains (uuid )) {
140+ activeGuiId .remove (uuid );
141+ }
132142 }
133143
134144 private void startSetting (Player player , String pId , int slot , ItemStack item ) {
135145 SettingSession s = new SettingSession ();
136146 s .pointName = pId ; s .slot = slot ; s .item = item ;
137147 FileConfiguration config = plugin .getRewardManager ().getRewardConfig (pId );
138- if (config .contains (String .valueOf (slot ))) {
148+ if (config != null && config .contains (String .valueOf (slot ))) {
139149 s .price = config .getInt (slot + ".price" );
140150 s .stock = config .getInt (slot + ".stock" , -1 );
141151 s .isPersonal = config .getBoolean (slot + ".is_personal" , false );
@@ -146,6 +156,9 @@ private void startSetting(Player player, String pId, int slot, ItemStack item) {
146156
147157 public void openSettingGUI (Player player ) {
148158 SettingSession s = sessions .get (player .getUniqueId ());
159+ if (s == null ) return ;
160+
161+ switchingPlayers .add (player .getUniqueId ());
149162 String displayName = plugin .getPointManager ().getDisplayName (s .pointName );
150163 Inventory inv = Bukkit .createInventory (null , 27 , "報酬設定: " + displayName );
151164 inv .setItem (4 , s .item );
@@ -166,6 +179,7 @@ public void openSettingGUI(Player player) {
166179 inv .setItem (13 , createGuiItem (Material .GOLD_BLOCK , "§e§l保存" , "§7スロット: " + s .slot ));
167180 inv .setItem (22 , createGuiItem (Material .BARRIER , "§4§l削除" , "" ));
168181 player .openInventory (inv );
182+ switchingPlayers .remove (player .getUniqueId ());
169183 }
170184
171185 private void handleSetting (Player player , int slot , ClickType click ) {
@@ -191,14 +205,18 @@ else if (slot == 15) {
191205 else if (slot == 18 ) s .price = (s .price == -1 ) ? 100 : -1 ;
192206 else if (slot == 19 ) s .isPersonal = !s .isPersonal ;
193207 else if (slot == 22 ) {
194- plugin .getRewardManager ().deleteReward (s .pointName , s .slot );
195- player .closeInventory ();
208+ String pId = s .pointName ;
209+ plugin .getRewardManager ().deleteReward (pId , s .slot );
210+ sessions .remove (player .getUniqueId ());
211+ openRewardGUI (player , pId , true );
196212 return ;
197213 }
198214 else if (slot == 13 ) {
199- plugin .getRewardManager ().saveReward (s .pointName , s .slot , s .item , s .price , s .stock , s .isPersonal );
215+ String pId = s .pointName ;
216+ plugin .getRewardManager ().saveReward (pId , s .slot , s .item , s .price , s .stock , s .isPersonal );
200217 player .playSound (player .getLocation (), Sound .ENTITY_EXPERIENCE_ORB_PICKUP , 1.0f , 1.0f );
201- player .closeInventory ();
218+ sessions .remove (player .getUniqueId ());
219+ openRewardGUI (player , pId , true );
202220 return ;
203221 }
204222 openSettingGUI (player );
@@ -233,9 +251,7 @@ private void handlePurchase(Player player, String pointName, int slot) {
233251 }
234252
235253 int balance = plugin .getPointManager ().getPoint (pointName , player .getUniqueId ());
236-
237254 if (balance >= price ) {
238- // ✨ ログ用にアイテム名を取得
239255 ItemStack rewardItem = config .getItemStack (slot + ".item" );
240256 String itemName = (rewardItem != null && rewardItem .hasItemMeta () && rewardItem .getItemMeta ().hasDisplayName ())
241257 ? rewardItem .getItemMeta ().getDisplayName ()
@@ -249,8 +265,6 @@ private void handlePurchase(Player player, String pointName, int slot) {
249265
250266 plugin .getPointManager ().addPoint (pointName , player .getUniqueId (), -price );
251267 if (rewardItem != null ) player .getInventory ().addItem (rewardItem .clone ());
252-
253- // ✨ 購入ログの記録
254268 plugin .getLogManager ().logRewardPurchase (player .getName (), pointName , itemName , price );
255269
256270 player .sendMessage ("§a購入完了!" );
0 commit comments