22
33import org .bukkit .Bukkit ;
44import org .bukkit .Material ;
5+ import org .bukkit .Sound ;
56import org .bukkit .configuration .file .FileConfiguration ;
67import org .bukkit .entity .Player ;
78import org .bukkit .event .EventHandler ;
@@ -24,32 +25,66 @@ public GUIManager(SimplePointPlugin plugin) {
2425
2526 private static class SettingSession {
2627 String pointName ; int slot ; ItemStack item ; int price = 100 ; int stock = -1 ;
28+ boolean isPersonal = false ; // ✨追加
2729 }
2830
2931 public void openRewardGUI (Player player , String pointName , boolean isAdmin ) {
3032 String title = pointName + (isAdmin ? ":編集" : ":受け取り" );
3133 Inventory gui = Bukkit .createInventory (null , 54 , title );
3234 FileConfiguration config = plugin .getRewardManager ().getRewardConfig (pointName );
35+
3336 if (config != null ) {
3437 for (String key : config .getKeys (false )) {
3538 try {
3639 int slot = Integer .parseInt (key );
3740 ItemStack item = config .getItemStack (slot + ".item" ).clone ();
3841 int price = config .getInt (slot + ".price" );
3942 int stock = config .getInt (slot + ".stock" , -1 );
43+ boolean isPersonal = config .getBoolean (slot + ".is_personal" , false );
4044 int req = config .getInt (slot + ".requirement" , 0 );
4145
42- ItemMeta meta = item .getItemMeta ();
43- // ✨ 装飾モード(price: -1)でない場合のみ、SPPの要素を追加表示
46+ // 在庫切れ判定
47+ boolean isSoldOut = false ;
48+ if (price != -1 ) {
49+ if (isPersonal ) {
50+ int bought = getPersonalBoughtCount (player , pointName , slot );
51+ if (stock != -1 && bought >= stock ) isSoldOut = true ;
52+ } else {
53+ if (stock == 0 ) isSoldOut = true ;
54+ }
55+ }
56+
57+ // --- 編集モード時のみの特別処理 ---
58+ // 編集モードならバリアに変えず、かつ在庫情報をそのまま出す
59+ if (isAdmin ) isSoldOut = false ;
60+
61+ ItemMeta meta = item .getItemMeta (); // 元の名前・説明文を保持したメタを取得
62+
4463 if (price != -1 ) {
4564 List <String > lore = meta .hasLore () ? meta .getLore () : new ArrayList <>();
4665 lore .add ("§8----------" );
47- lore .add ("§e価格: §f" + price + " pt" );
48- lore .add ("§b在庫: §f" + (stock == -1 ? "無限" : stock ));
66+
67+ if (isSoldOut ) {
68+ // 在庫切れ時の演出
69+ item .setType (Material .BARRIER ); // ✨ 見た目だけをバリアに変更
70+ lore .add ("§c§l在庫切れ / 購入不可" );
71+ } else {
72+ lore .add ("§e価格: §f" + price + " pt" );
73+ }
74+
75+ // 在庫状況の表示
76+ if (isPersonal ) {
77+ int bought = getPersonalBoughtCount (player , pointName , slot );
78+ lore .add ("§b個人在庫: §f" + (stock == -1 ? "なし" : bought + " / " + stock ));
79+ } else {
80+ lore .add ("§b共有在庫: §f" + (stock == -1 ? "無限" : stock ));
81+ }
82+
4983 if (req > 0 ) lore .add ("§6必要解放pt: §f" + req );
50- meta .setLore (lore );
84+ meta .setLore (lore ); // SPPの情報を追加したLoreをセット
5185 }
52- item .setItemMeta (meta );
86+
87+ item .setItemMeta (meta ); // バリアになったアイテムに元のメタを上書き
5388 gui .setItem (slot , item );
5489 } catch (Exception ignored ) {}
5590 }
@@ -70,7 +105,6 @@ public void onInventoryClick(InventoryClickEvent event) {
70105 else if (title .contains (":編集" )) {
71106 if (event .getRawSlot () < 0 || event .getRawSlot () >= 54 ) return ;
72107 event .setCancelled (true );
73-
74108 String pName = title .split (":" )[0 ];
75109 ItemStack cursor = event .getCursor ();
76110 ItemStack clicked = event .getCurrentItem ();
@@ -96,6 +130,7 @@ private void startSetting(Player player, String pName, int slot, ItemStack item)
96130 if (config .contains (String .valueOf (slot ))) {
97131 s .price = config .getInt (slot + ".price" );
98132 s .stock = config .getInt (slot + ".stock" , -1 );
133+ s .isPersonal = config .getBoolean (slot + ".is_personal" , false ); // ✨追加
99134 }
100135 sessions .put (player .getUniqueId (), s );
101136 openSettingGUI (player );
@@ -106,20 +141,19 @@ public void openSettingGUI(Player player) {
106141 Inventory inv = Bukkit .createInventory (null , 27 , "報酬設定: " + s .pointName );
107142 inv .setItem (4 , s .item );
108143
109- // ボタン配置
110144 inv .setItem (10 , createGuiItem (Material .RED_STAINED_GLASS_PANE , "§c価格 -100" , "§7現在: " + (s .price == -1 ? "装飾中" : s .price )));
111145 inv .setItem (16 , createGuiItem (Material .LIME_STAINED_GLASS_PANE , "§a価格 +100" , "§7現在: " + (s .price == -1 ? "装飾中" : s .price )));
112146
113147 String stockDisplay = (s .stock == -1 ) ? "§b無限" : "§f" + s .stock ;
114148 inv .setItem (11 , createGuiItem (Material .PINK_STAINED_GLASS_PANE , "§c在庫 -1" , "§7現在: " + stockDisplay ));
115149 inv .setItem (15 , createGuiItem (Material .LIGHT_BLUE_STAINED_GLASS_PANE , "§b在庫 +1" , "§7現在: " + stockDisplay ));
116150
117- // 在庫トグルボタン (無限/有限切り替え)
118151 inv .setItem (12 , createGuiItem (Material .COMPARATOR , "§f在庫設定切替" , "§7クリックで §b無限 §7と §e数値 §7を切り替え" ));
152+ inv .setItem (18 , createGuiItem (Material .PAINTING , "§d§l装飾モード切替" , "§7現在: " + (s .price == -1 ? "§aON" : "§cOFF" )));
119153
120- // ✨ 装飾モードトグルボタン
121- inv .setItem (18 , createGuiItem (Material .PAINTING , "§d§l装飾モード切替 " ,
122- "§7現在: " + (s .price == - 1 ? "§aON (表示のみ) " : "§cOFF (販売用) " ) + "\n §8ONにすると価格・在庫が表示されません " ));
154+ // ✨在庫モード切替ボタン
155+ inv .setItem (19 , createGuiItem (Material .PLAYER_HEAD , "§6§l在庫モード切替 " ,
156+ "§7現在: " + (s .isPersonal ? "§a個人制限 " : "§e共有在庫 " ) + "\n §8クリックで切り替え " ));
123157
124158 inv .setItem (13 , createGuiItem (Material .GOLD_BLOCK , "§e§l保存" , "§7スロット: " + s .slot ));
125159 inv .setItem (22 , createGuiItem (Material .BARRIER , "§4§l削除" , "" ));
@@ -145,20 +179,18 @@ else if (slot == 15) {
145179 if (s .stock == -1 ) s .stock = 1 ;
146180 else s .stock += (click .isRightClick () ? 10 : 1 );
147181 }
148- else if (slot == 12 ) { // 在庫トグル
149- s .stock = (s .stock == -1 ) ? 1 : -1 ;
150- }
151- else if (slot == 18 ) { // ✨ 装飾モードトグル
152- s .price = (s .price == -1 ) ? 100 : -1 ;
153- }
182+ else if (slot == 12 ) s .stock = (s .stock == -1 ) ? 1 : -1 ;
183+ else if (slot == 18 ) s .price = (s .price == -1 ) ? 100 : -1 ;
184+ else if (slot == 19 ) s .isPersonal = !s .isPersonal ; // ✨追加
154185 else if (slot == 22 ) {
155186 plugin .getRewardManager ().deleteReward (s .pointName , s .slot );
156187 player .closeInventory ();
157188 return ;
158189 }
159190 else if (slot == 13 ) {
160- plugin .getRewardManager ().saveReward (s .pointName , s .slot , s .item , s .price , s .stock );
161- player .playSound (player .getLocation (), org .bukkit .Sound .ENTITY_EXPERIENCE_ORB_PICKUP , 1.0f , 1.0f );
191+ // ✨引数に s.isPersonal を追加
192+ plugin .getRewardManager ().saveReward (s .pointName , s .slot , s .item , s .price , s .stock , s .isPersonal );
193+ player .playSound (player .getLocation (), Sound .ENTITY_EXPERIENCE_ORB_PICKUP , 1.0f , 1.0f );
162194 player .closeInventory ();
163195 return ;
164196 }
@@ -170,25 +202,44 @@ private void handlePurchase(Player player, String pointName, int slot) {
170202 if (config == null || !config .contains (String .valueOf (slot ))) return ;
171203
172204 int price = config .getInt (slot + ".price" );
173-
174- // ✨ 装飾用アイテムなら購入処理を中断
175205 if (price == -1 ) return ;
176206
177207 int stock = config .getInt (slot + ".stock" , -1 );
208+ boolean isPersonal = config .getBoolean (slot + ".is_personal" , false ); // ✨追加
178209 int req = config .getInt (slot + ".requirement" , 0 );
179210
211+ // ✨解放条件チェック
180212 int total = pointName .startsWith ("TEAMREWARD_" ) ?
181213 plugin .getTeamManager ().getTeamPoints (pointName .replace ("TEAMREWARD_" , "" )) :
182214 plugin .getPointManager ().getTotalPoint (pointName , player .getUniqueId ());
183-
184215 if (total < req ) { player .sendMessage ("§c解放条件未達成 (" + total + "/" + req + ")" ); return ; }
185- if (stock == 0 ) { player .sendMessage ("§c在庫切れ" ); return ; }
216+
217+ // ✨在庫チェックの分岐
218+ if (isPersonal ) {
219+ if (stock != -1 && getPersonalBoughtCount (player , pointName , slot ) >= stock ) {
220+ player .sendMessage ("§cこれ以上購入できません" );
221+ player .playSound (player .getLocation (), Sound .ENTITY_VILLAGER_NO , 1.0f , 1.0f );
222+ return ;
223+ }
224+ } else {
225+ if (stock == 0 ) {
226+ player .sendMessage ("§c在庫切れ" );
227+ player .playSound (player .getLocation (), Sound .ENTITY_VILLAGER_NO , 1.0f , 1.0f );
228+ return ;
229+ }
230+ }
186231
187232 String pKey = pointName .startsWith ("TEAMREWARD_" ) ? pointName .replace ("TEAMREWARD_" , "" ) : pointName ;
188233 int balance = plugin .getPointManager ().getPoint (pKey , player .getUniqueId ());
189234
190235 if (balance >= price ) {
191- if (stock > 0 ) plugin .getRewardManager ().updateStock (pointName , slot , stock - 1 );
236+ // ✨減算処理の分岐
237+ if (isPersonal ) {
238+ addPersonalBoughtCount (player , pointName , slot );
239+ } else if (stock > 0 ) {
240+ plugin .getRewardManager ().updateStock (pointName , slot , stock - 1 );
241+ }
242+
192243 plugin .getPointManager ().addPoint (pKey , player .getUniqueId (), -price );
193244 player .getInventory ().addItem (config .getItemStack (slot + ".item" ).clone ());
194245
@@ -200,15 +251,27 @@ private void handlePurchase(Player player, String pointName, int slot) {
200251
201252 plugin .getLogManager ().logPurchase (player .getName (), pointName , price , slot );
202253 player .sendMessage ("§a購入完了!" );
203- player .playSound (player .getLocation (), org . bukkit . Sound .ENTITY_PLAYER_LEVELUP , 1.0f , 1.2f );
254+ player .playSound (player .getLocation (), Sound .ENTITY_PLAYER_LEVELUP , 1.0f , 1.2f );
204255 openRewardGUI (player , pointName , false );
205256 } else {
206257 player .sendMessage ("§cポイント不足" );
207-
208- player .playSound (player .getLocation (), org .bukkit .Sound .ENTITY_VILLAGER_NO , 1.0f , 1.0f );
258+ player .playSound (player .getLocation (), Sound .ENTITY_VILLAGER_NO , 1.0f , 1.0f );
209259 }
210260 }
211261
262+ // ✨個人データの管理用ヘルパー
263+ private int getPersonalBoughtCount (Player p , String pointName , int slot ) {
264+ FileConfiguration cfg = plugin .getPointManager ().getPointConfig (pointName );
265+ return cfg .getInt (p .getUniqueId () + ".purchased." + slot , 0 );
266+ }
267+
268+ private void addPersonalBoughtCount (Player p , String pointName , int slot ) {
269+ FileConfiguration cfg = plugin .getPointManager ().getPointConfig (pointName );
270+ int current = cfg .getInt (p .getUniqueId () + ".purchased." + slot , 0 );
271+ cfg .set (p .getUniqueId () + ".purchased." + slot , current + 1 );
272+ plugin .getPointManager ().savePointConfig (pointName );
273+ }
274+
212275 private ItemStack createGuiItem (Material m , String name , String lore ) {
213276 ItemStack item = new ItemStack (m ); ItemMeta meta = item .getItemMeta ();
214277 meta .setDisplayName (name ); meta .setLore (Collections .singletonList (lore ));
0 commit comments