Skip to content

Commit 731488e

Browse files
增加翻页
1 parent 73c9933 commit 731488e

2 files changed

Lines changed: 190 additions & 64 deletions

File tree

src/main/java/ict/minesunshineone/landmark/gui/LandmarkMenu.java

Lines changed: 129 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,27 @@
2727
public class LandmarkMenu implements InventoryHolder {
2828

2929
private static final String LANDMARK_KEY = "landmark_name";
30+
private static final String NAVIGATION_KEY = "landmark_nav";
31+
private static final String NAV_PREVIOUS = "previous";
32+
private static final String NAV_NEXT = "next";
3033
private static final int INVENTORY_COLUMNS = 9;
31-
private static final int MAX_MENU_COLUMNS = 7;
34+
private static final int MENU_COLUMNS = 7;
3235
private final LandmarkPlugin plugin;
3336
private final UUID playerId;
3437
private Inventory inventory;
3538
private final MiniMessage miniMessage = MiniMessage.miniMessage();
3639
private final NamespacedKey landmarkKey;
40+
private final NamespacedKey navigationKey;
41+
private int currentPage = 0;
42+
private int rowsPerPage;
43+
private int slotsPerPage;
44+
private int totalPages = 1;
3745

3846
public LandmarkMenu(LandmarkPlugin plugin, Player player) {
3947
this.plugin = plugin;
4048
this.playerId = player.getUniqueId();
4149
this.landmarkKey = new NamespacedKey(plugin, LANDMARK_KEY);
50+
this.navigationKey = new NamespacedKey(plugin, NAVIGATION_KEY);
4251
}
4352

4453
@Override
@@ -50,14 +59,24 @@ public void open() {
5059
Component title = plugin.getConfigManager().getMessage("gui.title", "<gold>锚点传送菜单</gold>");
5160
int size = plugin.getConfigManager().getConfig().getInt("gui.size", 54);
5261
this.inventory = Bukkit.createInventory(this, size, title);
62+
this.currentPage = 0;
5363
initializeItems();
5464
getPlayer().openInventory(inventory);
5565
}
5666

5767
private void initializeItems() {
68+
if (inventory == null) {
69+
return;
70+
}
71+
72+
inventory.clear();
5873
setupBorder();
74+
75+
List<Map.Entry<String, Landmark>> orderedLandmarks = plugin.getLandmarkManager().getOrderedLandmarks();
76+
recomputePagination(orderedLandmarks.size());
77+
setupLandmarks(orderedLandmarks);
78+
setupNavigationControls();
5979
setupCurrentLocation();
60-
setupLandmarks();
6180
}
6281

6382
private void setupBorder() {
@@ -95,12 +114,17 @@ private ItemStack createBorderItem() {
95114
}
96115

97116
private void setupCurrentLocation() {
117+
Player player = getPlayer();
118+
if (player == null) {
119+
return;
120+
}
121+
98122
Landmark currentLandmark = null;
99123
boolean isAtAnyLandmark = false;
100124

101125
for (Map.Entry<String, Landmark> entry : plugin.getLandmarkManager().getLandmarks().entrySet()) {
102-
if (plugin.getLandmarkManager().isLandmarkUnlocked(getPlayer(), entry.getKey())
103-
&& plugin.getLandmarkManager().isPlayerNearLandmark(getPlayer(), entry.getValue().getLocation())) {
126+
if (plugin.getLandmarkManager().isLandmarkUnlocked(player, entry.getKey())
127+
&& plugin.getLandmarkManager().isPlayerNearLandmark(player, entry.getValue().getLocation())) {
104128
isAtAnyLandmark = true;
105129
currentLandmark = entry.getValue();
106130
break;
@@ -115,26 +139,34 @@ private void setupCurrentLocation() {
115139
}
116140
}
117141

118-
private void setupLandmarks() {
119-
int maxMenuRow = Math.max(1, (inventory.getSize() / INVENTORY_COLUMNS) - 2);
120-
for (Map.Entry<String, Landmark> entry : plugin.getLandmarkManager().getLandmarks().entrySet()) {
142+
private void setupLandmarks(List<Map.Entry<String, Landmark>> orderedLandmarks) {
143+
if (slotsPerPage <= 0) {
144+
return;
145+
}
146+
147+
Player player = getPlayer();
148+
if (player == null) {
149+
return;
150+
}
151+
152+
int startIndex = currentPage * slotsPerPage;
153+
int endIndex = Math.min(startIndex + slotsPerPage, orderedLandmarks.size());
154+
155+
for (int index = startIndex; index < endIndex; index++) {
156+
Map.Entry<String, Landmark> entry = orderedLandmarks.get(index);
121157
Landmark landmark = entry.getValue();
122-
int row = landmark.getMenuRow();
123-
int col = landmark.getMenuColumn();
124158

125-
// 确保位置在有效范围内(第2-倒数第二行,即索引1-maxMenuRow,列1-7)
126-
if (row < 1 || row > maxMenuRow || col < 1 || col > MAX_MENU_COLUMNS) {
127-
plugin.getSLF4JLogger().warn("锚点 {} 的位置 ({}, {}) 超出有效范围,将在下次加载时自动修复",
128-
landmark.getName(), row, col);
159+
int offset = index - startIndex;
160+
int row = (offset / MENU_COLUMNS) + 1;
161+
int col = (offset % MENU_COLUMNS) + 1;
162+
int slot = (row * INVENTORY_COLUMNS) + col;
163+
if (slot < 0 || slot >= inventory.getSize()) {
129164
continue;
130165
}
131166

132-
// 计算实际槽位(row 为去除边框后的行索引)
133-
int slot = (row * INVENTORY_COLUMNS) + col;
134-
boolean isUnlocked = plugin.getLandmarkManager().isLandmarkUnlocked(getPlayer(), entry.getKey());
167+
boolean isUnlocked = plugin.getLandmarkManager().isLandmarkUnlocked(player, entry.getKey());
135168
ItemStack item = createLandmarkItem(landmark, isUnlocked);
136169

137-
// 存储锚点名称到物品中
138170
ItemMeta meta = item.getItemMeta();
139171
if (meta != null) {
140172
PersistentDataContainer container = meta.getPersistentDataContainer();
@@ -146,6 +178,70 @@ private void setupLandmarks() {
146178
}
147179
}
148180

181+
private void recomputePagination(int totalLandmarks) {
182+
rowsPerPage = Math.max(1, (inventory.getSize() / INVENTORY_COLUMNS) - 2);
183+
slotsPerPage = Math.max(1, rowsPerPage * MENU_COLUMNS);
184+
totalPages = Math.max(1, (int) Math.ceil(totalLandmarks / (double) slotsPerPage));
185+
if (currentPage >= totalPages) {
186+
currentPage = totalPages - 1;
187+
}
188+
}
189+
190+
private void setupNavigationControls() {
191+
int bottomRowStart = inventory.getSize() - INVENTORY_COLUMNS;
192+
if (bottomRowStart < 0) {
193+
return;
194+
}
195+
196+
ItemStack indicator = createPageIndicatorItem();
197+
inventory.setItem(bottomRowStart + (INVENTORY_COLUMNS - 1), indicator);
198+
199+
if (totalPages <= 1) {
200+
return;
201+
}
202+
203+
ItemStack previous = createNavigationItem(
204+
"<#c7a3ed><bold>上一页</bold>",
205+
"<gray><bold>已是第一页</bold>",
206+
NAV_PREVIOUS,
207+
currentPage > 0);
208+
ItemStack next = createNavigationItem(
209+
"<#c7a3ed><bold>下一页</bold>",
210+
"<gray><bold>已是最后一页</bold>",
211+
NAV_NEXT,
212+
currentPage < totalPages - 1);
213+
214+
inventory.setItem(bottomRowStart + 1, previous);
215+
inventory.setItem(bottomRowStart + (INVENTORY_COLUMNS - 2), next);
216+
}
217+
218+
private ItemStack createNavigationItem(String activeName, String inactiveName, String action, boolean enabled) {
219+
Material material = enabled ? Material.ARROW : Material.GRAY_STAINED_GLASS_PANE;
220+
String displayName = enabled ? activeName : inactiveName;
221+
222+
ItemStack item = new ItemStack(material);
223+
ItemMeta meta = item.getItemMeta();
224+
if (meta != null) {
225+
meta.displayName(miniMessage.deserialize(displayName));
226+
if (enabled) {
227+
meta.getPersistentDataContainer().set(navigationKey, PersistentDataType.STRING, action);
228+
}
229+
item.setItemMeta(meta);
230+
}
231+
return item;
232+
}
233+
234+
private ItemStack createPageIndicatorItem() {
235+
ItemStack item = new ItemStack(Material.PAPER);
236+
ItemMeta meta = item.getItemMeta();
237+
if (meta != null) {
238+
String title = String.format("<#c7a3ed><bold>第 %d / %d 页</bold>", currentPage + 1, totalPages);
239+
meta.displayName(miniMessage.deserialize(title));
240+
item.setItemMeta(meta);
241+
}
242+
return item;
243+
}
244+
149245
private ItemStack createCurrentLocationItem(boolean isAtAnyLandmark, Landmark currentLandmark) {
150246
Material material = isAtAnyLandmark
151247
? Material.valueOf(Objects.requireNonNull(plugin.getConfigManager().getConfig().getString("gui.items.current.material", "CONDUIT")))
@@ -319,6 +415,12 @@ private void handleItemClick(ItemStack item, Player player) {
319415
}
320416

321417
PersistentDataContainer container = meta.getPersistentDataContainer();
418+
String navigationAction = container.get(navigationKey, PersistentDataType.STRING);
419+
if (navigationAction != null) {
420+
handleNavigationClick(navigationAction);
421+
return;
422+
}
423+
322424
String landmarkName = container.get(landmarkKey, PersistentDataType.STRING);
323425

324426
if (landmarkName != null && plugin.getLandmarkManager().isLandmarkUnlocked(player, landmarkName)) {
@@ -329,6 +431,16 @@ private void handleItemClick(ItemStack item, Player player) {
329431
}
330432
}
331433

434+
private void handleNavigationClick(String action) {
435+
if (NAV_PREVIOUS.equals(action) && currentPage > 0) {
436+
currentPage--;
437+
initializeItems();
438+
} else if (NAV_NEXT.equals(action) && currentPage < totalPages - 1) {
439+
currentPage++;
440+
initializeItems();
441+
}
442+
}
443+
332444
private Player getPlayer() {
333445
return Bukkit.getPlayer(playerId);
334446
}

0 commit comments

Comments
 (0)