Index: .gitattributes IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/.gitattributes b/.gitattributes --- a/.gitattributes (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/.gitattributes (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -1,6 +1,5 @@ +*.md text=auto encoding=UTF-8 *.png binary *.jpg binary *.jpeg binary -*.gif binary -*.ico binary -*.bmp binary \ No newline at end of file +*.gif binary \ No newline at end of file Index: src/main/java/Sdf1_login/ConfigManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/ConfigManager.java b/src/main/java/Sdf1_login/ConfigManager.java --- a/src/main/java/Sdf1_login/ConfigManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/ConfigManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -312,6 +312,14 @@ requesterPointsReward = parseInt( m.getOrDefault("报单人积分奖励", "10"), 10); + garbageEnabled = Boolean.parseBoolean( + m.getOrDefault("垃圾站_启用", "true")); + garbageInterval = parseInt( + m.getOrDefault("垃圾站_清理间隔秒", + "300"), 300); + garbageMaxRounds = parseInt( + m.getOrDefault("垃圾站_保留轮数", + "1"), 1); } @@ -331,12 +339,10 @@ L.add("挂机超时秒数=" + afkTimeout); // 垃圾站设置 L.add("# ---- 垃圾站 ----"); - L.add("垃圾站_启用: " - + garbageEnabled); - L.add("垃圾站_清理间隔秒: " - + garbageInterval); - L.add("垃圾站_保留轮数: " - + garbageMaxRounds); + L.add("垃圾站_启用=" + garbageEnabled); + L.add("垃圾站_清理间隔秒=" + garbageInterval); + L.add("垃圾站_保留轮数=" + garbageMaxRounds); + writeLines(file, L); } @@ -364,6 +370,11 @@ L.add("基础经济奖励=" + baseEconomyReward); L.add("经济奖励每评分=" + providerEconomyPerScore); L.add("报单人积分奖励=" + requesterPointsReward); + L.add("# ---- 垃圾站 ----"); + L.add("垃圾站_启用=true"); + L.add("垃圾站_清理间隔秒=300"); + L.add("垃圾站_保留轮数=1"); + writeLines(f, L); } Index: src/main/java/Sdf1_login/DatabaseManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/DatabaseManager.java b/src/main/java/Sdf1_login/DatabaseManager.java --- a/src/main/java/Sdf1_login/DatabaseManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/DatabaseManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -201,7 +201,18 @@ + "active INTEGER DEFAULT 1," + "join_time INTEGER DEFAULT 0" + ")"); - + // 垃圾回收站物品表 + st.execute("CREATE TABLE IF NOT EXISTS " + + "items (" + + "id INTEGER PRIMARY KEY " + + "AUTOINCREMENT," + + "player_name TEXT NOT NULL," + + "item_data TEXT DEFAULT ''," + + "amount INTEGER DEFAULT 1," + + "create_time INTEGER DEFAULT 0" + + ")"); + safeAdd(st, "menu_snowball", + "INTEGER DEFAULT 1"); st.close(); logger.info("[Sdf1_login] 数据库初始化完成"); } catch (Exception e) { Index: src/main/java/Sdf1_login/GUIManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/GUIManager.java b/src/main/java/Sdf1_login/GUIManager.java --- a/src/main/java/Sdf1_login/GUIManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/GUIManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -489,6 +489,12 @@ "§e设置密码")); g.setItem(16, mkItem(Material.BARRIER, "§c删除用户", "§7二次验证删除")); + // 雪球菜单检测(slot 14) + g.setItem(14, mkItem( + Material.SNOWBALL, + "§e§l雪球菜单", + "§7点击为该玩家发放菜单雪球")); + g.setItem(22, mkItem(Material.ARROW, "§7返回")); p.openInventory(g); } Index: src/main/java/Sdf1_login/GarbageManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/GarbageManager.java b/src/main/java/Sdf1_login/GarbageManager.java --- a/src/main/java/Sdf1_login/GarbageManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/GarbageManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -231,26 +231,26 @@ public void saveItem(ItemStack stack) { { - try { - String data = - stackToBase64(stack); - if (data.isEmpty()) return; - PreparedStatement ps = db.prepareStatement( - "INSERT INTO items " - + "(item_data, amount, " - + "round, create_time) " - + "VALUES (?,?,?,?)"); - ps.setString(1, data); - ps.setInt(2, stack.getAmount()); - ps.setInt(3, currentRound); - ps.setLong(4, - System.currentTimeMillis()); - ps.executeUpdate(); - ps.close(); - } catch (Exception e) { - e.printStackTrace(); - } - }} + try { + String data = + stackToBase64(stack); + if (data.isEmpty()) return; + PreparedStatement ps = db.prepareStatement( + "INSERT INTO items " + + "(item_data, amount, " + + "round, create_time) " + + "VALUES (?,?,?,?)"); + ps.setString(1, data); + ps.setInt(2, stack.getAmount()); + ps.setInt(3, currentRound); + ps.setLong(4, + System.currentTimeMillis()); + ps.executeUpdate(); + ps.close(); + } catch (Exception e) { + e.printStackTrace(); + } + }} private int deleteOldItems(int beforeRound) { try { @@ -381,6 +381,38 @@ .get("amount")).intValue(); ItemStack stack = base64ToStack(data); if (stack != null) { + try { + byte[] bytes = + stack.serializeAsBytes(); + String b64 = java.util.Base64 + .getEncoder() + .encodeToString(bytes); + int len = b64.length(); + String f = len > 15 + ? b64.substring(10, 15) : "短"; + String m = len >= 5 + ? b64.substring(len / 2, + Math.min(len / 2 + 5, len)) + : "短"; + String b = len > 10 + ? b64.substring(len - 10, len - 5) + : "短"; + plugin.getLogger().info( + "[垃圾站加载] ID#" + id + + " " + stack.getType() + + " x" + amount + + " base64[" + len + "]" + + " 前=" + f + + " 中=" + m + + " 后=" + b); + } catch (Exception ex) { + plugin.getLogger().warning( + "[垃圾站加载] 序列化异常: " + + ex.getMessage()); + } + } + + if (stack != null) { stack.setAmount(amount); ItemMeta im = stack.getItemMeta(); @@ -431,6 +463,10 @@ g.setItem(51, mk(Material.ARROW, "§7已是最后一页")); } + // 52格:返回按钮 + g.setItem(52, mk(Material.ARROW, + "§7返回", + "§7返回主菜单")); p.openInventory(g); } @@ -459,6 +495,12 @@ openRecyclePage(p, page + 1); return true; } + // 52:返回 + if (slot == 52) { + plugin.getGui().openMain(p); + return true; + } + // 50/52/53:不处理 if (slot >= 49 && slot <= 53) return true; Index: src/main/java/Sdf1_login/GiftManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/GiftManager.java b/src/main/java/Sdf1_login/GiftManager.java --- a/src/main/java/Sdf1_login/GiftManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/GiftManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -155,55 +155,18 @@ } public boolean canClaim(Player p, int stage) { - Map user = plugin.getDb() - .getUser(p.getName()); - if (user.isEmpty()) return false; - int curStage = ((Number) user.getOrDefault( - "gift_stage", 0)).intValue(); - if (stage > curStage + 1) return false; - if (stage < 1 || stage > stages.size()) - return false; - String claimed = (String) user.getOrDefault( - "gift_claimed", ""); - if (claimed.contains("[" + stage + "]")) - return false; - - // debug 绕过:检查 tasks_completed - String completed = (String) user.getOrDefault( - "tasks_completed", ""); - if (completed.contains("[" + stage + "]")) - return true; - - // 正常条件检查 - long dbTime = ((Number) user.getOrDefault( - "total_online_time", 0L)).longValue(); - long sessionTime = 0; - Object lastObj = plugin.getDb().getField( - p.getName(), "last_online_check"); - if (lastObj != null && plugin.getLoggedIn() - .contains(p.getName())) { - long last = ((Number) lastObj).longValue(); - if (last > 0) { - sessionTime = - System.currentTimeMillis() - last; - } - } - long onlineTime = dbTime + sessionTime; - int broken = ((Number) user.getOrDefault( - "blocks_broken", 0)).intValue(); - int placed = ((Number) user.getOrDefault( - "blocks_placed", 0)).intValue(); + String name = p.getName(); + int curStage = ((Number) plugin.getDb() + .getField(name, "gift_stage")) + .intValue(); + String claimed = (String) plugin.getDb() + .getField(name, "gift_claimed"); + if (claimed == null) claimed = ""; + return curStage >= stage + && !claimed.contains( + String.valueOf(stage)); + } - switch (stage) { - case 1: return true; - case 2: return onlineTime >= 3600000; - case 3: return broken >= 100 - && onlineTime >= 86400000L; - case 4: return (broken + placed) >= 300 - && onlineTime >= 604800000L; - default: return false; - } - } public void claimReward(Player p, int stage) { if (!canClaim(p, stage)) return; Index: src/main/java/Sdf1_login/Main.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java --- a/src/main/java/Sdf1_login/Main.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/Main.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -196,6 +196,8 @@ getCommand("sdf1debug").setExecutor(this); if (getCommand("oa") != null) getCommand("oa").setExecutor(this); + if (getCommand("menu") != null) + getCommand("menu").setExecutor(this); getServer().getPluginManager() @@ -1099,6 +1101,9 @@ return; } } + if (isFrozen(p)) { + p.setAllowFlight(true); + } if (!"manual".equals(config.approvalMode) && !db.userExists(name)) { @@ -1238,36 +1243,82 @@ private static final String MENU_SNOWBALL_TAG = "sdf1_menu"; + // 雪球菜单 public void giveMenuSnowball(Player p) { - // 检查背包里是否已有菜单雪球 + // 检查开关 + Object val = db.getField( + p.getName(), "menu_snowball"); + if (val != null) { + int on = val instanceof Number + ? ((Number) val).intValue() + : 1; + if (on == 0) { + return; // 开关关了,不发放 + } + } + // 检查是否已有 for (ItemStack it : p.getInventory() .getContents()) { if (isMenuSnowball(it)) { - return; // 已有,不重复发 + return; } } - // 没有则发放 + // 发放 ItemStack snow = new ItemStack( Material.SNOWBALL); ItemMeta im = snow.getItemMeta(); if (im != null) { im.setDisplayName( "§e§l[菜单] §f右键打开主菜单"); - List lore = new ArrayList<>(); + List lore = + new ArrayList<>(); lore.add("§7右键点击打开功能菜单"); lore.add("§8" + MENU_SNOWBALL_TAG); im.setLore(lore); snow.setItemMeta(im); } - // 放到最后一个空格,避免覆盖 - int emptySlot = - p.getInventory() - .firstEmpty(); - if (emptySlot >= 0) { + int slot = p.getInventory() + .firstEmpty(); + if (slot >= 0) { + p.getInventory().setItem( + slot, snow); + } else { + p.getWorld().dropItemNaturally( + p.getLocation(), snow); + } + } + + /** + * 手动发放雪球菜单(绕过开关检查) + */ + public void forceGiveMenuSnowball( + Player p) { + // 只检查是否已有 + for (ItemStack it : p.getInventory() + .getContents()) { + if (isMenuSnowball(it)) { + return; + } + } + ItemStack snow = new ItemStack( + Material.SNOWBALL); + ItemMeta im = snow.getItemMeta(); + if (im != null) { + im.setDisplayName( + "§e§l[菜单] §f右键打开主菜单"); + List lore = + new ArrayList<>(); + lore.add("§7右键点击打开功能菜单"); + lore.add("§8" + MENU_SNOWBALL_TAG); + im.setLore(lore); + snow.setItemMeta(im); + } + int slot = p.getInventory() + .firstEmpty(); + if (slot >= 0) { p.getInventory().setItem( - emptySlot, snow); + slot, snow); } else { - // 背包满,丢在地上 p.getWorld().dropItemNaturally( p.getLocation(), snow); } @@ -1296,21 +1347,24 @@ @EventHandler public void onMove(PlayerMoveEvent e) { Player p = e.getPlayer(); + if (!isFrozen(p)) return; + Location from = e.getFrom(); Location to = e.getTo(); - if (isFrozen(p)) { - if (to != null && (from.getX() != to.getX() - || from.getY() != to.getY() - || from.getZ() != to.getZ())) { - e.setTo(e.getFrom()); - } + if (to == null) return; + + // 允许转头(无位移) + if (from.getBlockX() == to.getBlockX() + && from.getBlockY() == to.getBlockY() + && from.getBlockZ() == to.getBlockZ()) { return; } - if (to != null && (from.getX() != to.getX() - || from.getY() != to.getY() - || from.getZ() != to.getZ())) { - afk.recordAction(p.getUniqueId()); - } + + // 有位移 → 取消 + e.setCancelled(true); + + // 防止"服务器未启用飞行"踢出 + p.setAllowFlight(true); } @EventHandler @@ -1484,7 +1538,8 @@ - // ===== Inventory Click ===== + // ===== Inventory Click ===== + // ===== Inventory Click ===== @EventHandler public void onInvClick(InventoryClickEvent e) { if (!(e.getWhoClicked() instanceof Player)) @@ -1494,12 +1549,41 @@ e.setCancelled(true); return; } - String title = - e.getView().getTitle(); + String title = e.getView().getTitle(); int slot = e.getRawSlot(); - if (needsPasswordChange.contains(p.getName()) - && !title.equals("§6§l任务面板")) { + // Shift+点击背包物品 → 存入垃圾箱 + if (e.isShiftClick() + && e.getClickedInventory() != null + && e.getClickedInventory() + == p.getInventory() + && e.getCurrentItem() != null + && e.getCurrentItem().getType() + != Material.AIR + && !isMenuSnowball( + e.getCurrentItem()) + && title.equals( + "§6§l垃圾回收站")) { + e.setCancelled(true); + ItemStack clicked = + e.getCurrentItem().clone(); + garbage.saveItem(clicked); + e.getInventory().setItem( + e.getSlot(), null); + Bukkit.getScheduler() + .runTaskLater(this, + () -> { + garbage.openRecyclePage(p, + garbage.getRecyclePage( + p.getName())); + }, 1L); + return; + } + + if (needsPasswordChange + .contains(p.getName()) + && !title.equals( + "§6§l任务面板")) { e.setCancelled(true); p.sendMessage("§c请先修改密码!"); return; @@ -1516,12 +1600,15 @@ TicketManager.T_TICKET_ADMIN) || title.equals( TicketManager.T_TICKET_DETAIL) - || title.equals("§d§l服务商面板") - || title.equals("§6§l抢单大厅") + || title.equals( + "§d§l服务商面板") + || title.equals( + "§6§l抢单大厅") || title.equals( "§b§l我处理中的工单")) { e.setCancelled(true); - ticket.handleClick(p, title, slot); + ticket.handleClick( + p, title, slot); return; } @@ -1539,96 +1626,67 @@ ItemStack inSlot = e.getInventory().getItem(slot); - ItemStack onCursor = e.getCursor(); + ItemStack cursor = e.getCursor(); - // 1. 格子里是垃圾站物品 → 取出 - if (isTrashDisplayItem(inSlot)) { - e.setCancelled(true); - try { - List lore = - inSlot.getItemMeta() - .getLore(); - String numStr = - lore.get(0) - .replace( - "§7ID: #", "") - .trim(); - int dbId = Integer - .parseInt(numStr); - // 先从DB删除 - if (garbage.removeItem( - dbId)) { - // 再给玩家(去掉ID lore) - ItemStack give = - inSlot.clone(); - ItemMeta gm = - give.getItemMeta(); - if (gm != null) { - List newLore = - new ArrayList<>(); - // 保留原始lore(跳过ID和数量行) - if (lore.size() > 2) { - for (int li = 2; - li < lore - .size(); - li++) { - newLore.add( - lore.get( - li)); - } - } - gm.setLore( - newLore.isEmpty() - ? null - : newLore); + // ===== 取出 ===== + if (inSlot != null + && inSlot.hasItemMeta() + && inSlot.getItemMeta().hasLore()) { + List lore = + inSlot.getItemMeta().getLore(); + if (lore != null && !lore.isEmpty() + && lore.get(0) + .startsWith("§7ID: #")) { + e.setCancelled(true); + try { + String numStr = lore.get(0) + .replace("§7ID: #", "") + .trim(); + int dbId = + Integer.parseInt(numStr); + if (garbage.removeItem(dbId)) { + ItemStack give = + inSlot.clone(); + ItemMeta gm = + give.getItemMeta(); + gm.setLore(null); give.setItemMeta(gm); - } - p.getInventory() - .addItem(give); - // 清空格子 - e.getInventory() - .setItem(slot, - null); - } - } catch (Exception ex) { - p.sendMessage("§c取出失败"); - } - return; + p.getInventory() + .addItem(give); + e.getInventory() + .setItem(slot, null); + } + } catch (Exception ex) { + p.sendMessage("§c取出失败"); + } + return; + } } - // 2. 格子空 + 手上有物品 → 放入 - if ((inSlot == null - || inSlot.getType() - == Material.AIR) - && onCursor != null - && onCursor.getType() + // ===== 光标存入 ===== + if (cursor != null + && cursor.getType() != Material.AIR - && !isMenuSnowball( - onCursor)) { - // 不取消!让物品自然进入格子 - Bukkit.getScheduler() - .runTaskLater(this, - () -> { - ItemStack after = - e.getInventory() - .getItem( - slot); - if (after != null - && after.getType() - != Material.AIR) { - garbage.saveItem( - after - .clone()); - e.getInventory() - .setItem( - slot, - null); - } - }, 1L); + && !isMenuSnowball(cursor)) { + ItemStack toSave = cursor.clone(); + getLogger().info( + "[垃圾站] 存入: " + + toSave.getType() + + " x" + toSave.getAmount()); + garbage.saveItem(toSave); + e.setCancelled(true); + Bukkit.getScheduler().runTaskLater( + this, () -> { + p.getOpenInventory() + .setCursor(null); + garbage.openRecyclePage(p, + garbage.getRecyclePage( + p.getName())); + }, 1L); return; } - // 3. 其他情况 + // 默认取消 e.setCancelled(true); return; } @@ -1806,6 +1864,7 @@ p.closeInventory(); p.sendMessage("§e请输入邀请码:"); } + return; } @@ -1828,6 +1887,7 @@ .replace("§e", "") .replace("§a", "")); } + return; } @@ -1856,7 +1916,18 @@ p.closeInventory(); p.sendMessage("§e输入" + tgt + "的临时密码:"); - } else if (slot == 16) { + } else if (slot == 14) { + Player tp = Bukkit.getPlayer(tgt); + if (tp != null && tp.isOnline()) { + forceGiveMenuSnowball(tp); + p.sendMessage("§a已发放雪球菜单给 " + + tgt); + } else { + p.sendMessage("§c玩家不在线"); + } + + + } else if (slot == 16) { chatInput.getState(p).type = ChatInputManager.InputType .ADMIN_DELETE_CONFIRM; @@ -1866,8 +1937,11 @@ p.sendMessage(config.msg( "admin_delete_confirm")); } + return; + } + // 积分商城 if (title.startsWith("§d§l积分商城")) { @@ -1958,43 +2032,45 @@ // 回收站拖拽 if (t.equals("§6§l垃圾回收站")) { - for (int rawSlot : e.getRawSlots()) { - if (rawSlot >= 49 - && rawSlot <= 53) { + for (int rawSlot : + e.getRawSlots()) { + if (rawSlot >= 49) { e.setCancelled(true); return; } } - // 0-48:不取消,延迟存DB + // 0-48允许拖入,不取消 + // 延迟2tick后扫描格子 + final Player fp = p; Bukkit.getScheduler() - .runTaskLater(this, () -> { - for (int rawSlot : - e.getRawSlots()) { - if (rawSlot < 0 - || rawSlot >= 49) - continue; - ItemStack item = - e.getInventory() - .getItem( - rawSlot); - if (item != null - && item.getType() - != Material.AIR - && !isMenuSnowball( - item)) { - garbage.saveItem( - item.clone()); - e.getInventory() - .setItem( - rawSlot, - null); - } - } - }, 1L); + .runTaskLater(this, + () -> { + Inventory top = fp + .getOpenInventory() + .getTopInventory(); + for (int rawSlot : + e.getRawSlots()) { + if (rawSlot < 0 + || rawSlot >= 49) + continue; + ItemStack item = + top.getItem(rawSlot); + if (item != null + && item.getType() + != Material.AIR + && !isMenuSnowball( + item)) { + garbage.saveItem( + item.clone()); + top.setItem( + rawSlot, null); + } + } + }, 2L); return; } - + //服务商工单系统 if (t.equals(TicketManager.T_TICKET_MAIN) || t.equals( TicketManager.T_TICKET_CREATE) @@ -2050,6 +2126,38 @@ + count + " 个掉落物"); return true; } + // /menu 开关雪球菜单 + if (cmdName.equals("menu")) { + if (!(sender instanceof Player)) { + sender.sendMessage( + "§c仅玩家可用"); + return true; + } + Player p2 = (Player) sender; + if (args.length == 0) { + p2.sendMessage( + "§e用法: /menu <开/关>"); + return true; + } + String arg = args[0]; + if (arg.equals("开")) { + db.setField(p2.getName(), + "menu_snowball", 1); + p2.sendMessage( + "§a雪球菜单已开启," + + "下次进入将发放"); + } else if (arg.equals("关")) { + db.setField(p2.getName(), + "menu_snowball", 0); + p2.sendMessage( + "§c雪球菜单已关闭," + + "下次进入不再发放"); + } else { + p2.sendMessage( + "§e用法: /menu <开/关>"); + } + return true; + } if (cmdName.equals("reg") || cmdName.equals("注册")) { @@ -2461,9 +2569,9 @@ sender.sendMessage( "§e§l================================"); } - } + } - // pw / password + // pw / password if (sub.equals("pw") || sub.equals("password")) { if (!(sender instanceof Player)) { @@ -2790,6 +2898,29 @@ } return true; } + // give - 手动发放雪球菜单 + if (sub.equals("give")) { + if (args.length < 2) { + sender.sendMessage( + "§e用法: /sdf1_login give <玩家名>"); + return true; + } + Player tp = Bukkit.getPlayer( + args[1]); + if (tp == null || !tp.isOnline()) { + sender.sendMessage( + "§c玩家不在线: " + + args[1]); + return true; + } + forceGiveMenuSnowball(tp); + tp.sendMessage( + "§a管理员已为您发放菜单雪球"); + sender.sendMessage( + "§a已发放雪球菜单给 " + + args[1]); + return true; + } // shopadd if (sub.equals("shopadd")) { @@ -3052,4 +3183,4 @@ return list; } -} +} \ No newline at end of file Index: src/main/java/Sdf1_login/TicketManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/Sdf1_login/TicketManager.java b/src/main/java/Sdf1_login/TicketManager.java --- a/src/main/java/Sdf1_login/TicketManager.java (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/java/Sdf1_login/TicketManager.java (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -1014,39 +1014,27 @@ openDetail(p, id); return true; } - // 管理员:标记完结(自己在处理) - if (adm(p) && "processing".equals(st) + // 管理员:标记完结(已回复状态) + if (adm(p) && "replied".equals(st) && asg.equals("admin")) { - Map tk = - plugin.getDb().getTicket(id); - String tkType = sv(tk, "type"); - if (TYPE_DELETE.equals(tkType)) { - approveDeleteTicket(p, id); - return true; - } - plugin.getDb().completeTicket(id); - p.sendMessage("§a工单 #" + id - + " 已标记完结"); - openDetail(p, id); - return true; - } - // 管理员:标记完结(已回复状态) - if (adm(p) && "replied".equals(st) - && asg.equals("admin")) { - Map tk = - plugin.getDb().getTicket(id); - String tkType = sv(tk, "type"); - if (TYPE_DELETE.equals(tkType)) { - approveDeleteTicket(p, id); - return true; - } - plugin.getDb().completeTicket(id); - p.sendMessage("§a工单 #" + id - + " 已标记完结"); - openDetail(p, id); - return true; + + // 管理员:标记完结(已回复状态) + if (adm(p) && "replied".equals(st) + && asg.equals("admin")) { + Map tk = + plugin.getDb().getTicket(id); + String tkType = sv(tk, "type"); + if (TYPE_DELETE.equals(tkType)) { + approveDeleteTicket(p, id); + return true; + } + plugin.getDb().completeTicket(id); + p.sendMessage("§a工单 #" + id + + " 已标记完结"); + openDetail(p, id); + return true; + } } - // 服务商:抢单 if (plugin.getDb() .isServiceProvider(p.getName()) Index: src/main/resources/plugin.yml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml --- a/src/main/resources/plugin.yml (revision 145b392112786b20534254a7a38d716657c962ab) +++ b/src/main/resources/plugin.yml (revision 87de2e12c81f5a5e04825113e7835aca09e0fd09) @@ -84,3 +84,6 @@ 垃圾清理: description: 手动清理掉落物 usage: /垃圾清理 + menu: + description: 雪球菜单开关控制 + usage: /menu <开/关> \ No newline at end of file