附魔书NBT:移除空壳兜底,解析失败则整单取消并退款(含单笔购买退款)

This commit is contained in:
2026-07-09 13:32:50 +08:00
parent e4e74f1cb8
commit 626fbcd591
2 changed files with 38 additions and 11 deletions
+8 -3
View File
@@ -1449,20 +1449,25 @@ public class ShopManager implements Listener {
/**
* 若传入的附魔书是“空壳”(无存储附魔),则尝试用商品ID权威重建附魔NBT。
* 用于 Web 商城发放附魔书兜底,避免显示名解析失败/ENCHANT_MAP 为空导致空壳。
* ★ 若 ID 重建也失败(解析失败),返回 null —— 由上层整单取消并退款,绝不发放空壳。
*/
public ItemStack ensureEnchantedBookNbt(ItemStack itemStack, String itemId, int amount) {
if (itemStack == null || itemStack.getType() != Material.ENCHANTED_BOOK) return itemStack;
if (itemStack == null) return null;
if (itemStack.getType() != Material.ENCHANTED_BOOK) return itemStack;
ItemMeta m = itemStack.getItemMeta();
boolean empty = !(m instanceof EnchantmentStorageMeta)
|| ((EnchantmentStorageMeta) m).getStoredEnchants().isEmpty();
if (!empty) return itemStack;
if (!empty) return itemStack; // 已是带附魔的有效书
// 空壳 → 用商品ID权威重建
ItemStack rebuilt = buildEnchantedBookFromId(itemId);
if (rebuilt != null) {
rebuilt.setAmount(amount);
plugin.getLogger().info("[Shop] 附魔书空壳已用ID重建NBT: " + itemId);
return rebuilt;
}
return itemStack;
// ★ 解析失败:不再发放空壳,返回 null 交由上层整单取消/退款
plugin.getLogger().warning("[Shop] 附魔书无法由ID重建(解析失败),取消发放: " + itemId);
return null;
}
private int parseEnchantLevel(String name, String keyword) {
+30 -8
View File
@@ -5918,7 +5918,18 @@ public class WebManager {
// ★ 通知玩家购买成功
player.sendMessage("§6[商城] §fWeb购买 §e" + itemId + " x" + itemCount + " §f成功!§c-" + amount + "§f 债券");
player.sendMessage("§6[债券] §f余额: §e" + (newBal + amount) + " §7→ §a" + newBal);
dispatchItemByMaterialOrId(player, itemId, itemCount);
boolean delivered = dispatchItemByMaterialOrId(player, itemId, itemCount);
if (!delivered) {
// ★ 发放失败(附魔书解析失败等)→ 整笔不确认 + 写退款,避免玩家付了钱拿不到东西
plugin.getLogger().warning("[Web交易] 单笔购买发放失败,发起退款: " + itemId + " 交易#" + txId);
player.sendMessage("§c[商城] §f商品发放失败,已自动退款:§e" + itemId);
try {
writeRefundTransaction(playerName, amount, txId, "单笔购买发放失败:" + itemId, "bond");
} catch (Exception ex) {
plugin.getLogger().warning("[Web交易] 写入退款记录失败: " + ex.getMessage());
}
return; // 不 confirm,PHP 端退款
}
} else {
plugin.getLogger().info("[Web交易] 玩家离线,保存到离线邮件");
saveOfflineItem(playerName, itemId, itemCount);
@@ -6052,8 +6063,13 @@ public class WebManager {
} else {
for (CartEntry ce : entries) {
try {
dispatchItemByMaterialOrId(player, ce.itemId, ce.amount, ce.name);
okItems.add(ce.name != null ? ce.name : ce.itemId);
boolean delivered = dispatchItemByMaterialOrId(player, ce.itemId, ce.amount, ce.name);
if (delivered) {
okItems.add(ce.name != null ? ce.name : ce.itemId);
} else {
// ★ 发放失败(含附魔书解析失败)→ 计入失败列表,触发整单取消+退款
failedItems.add(ce.itemId);
}
} catch (Exception ex) {
failedItems.add(ce.itemId);
plugin.getLogger().warning("[Web交易] 发放商品异常: " + ce.itemId + " → " + ex.getMessage());
@@ -6232,15 +6248,15 @@ public class WebManager {
/**
* 通过Material名称或商品ID发放商品(兼容PHP传Material名称的情况)
*/
private void dispatchItemByMaterialOrId(Player player, String itemId, int amount) {
dispatchItemByMaterialOrId(player, itemId, amount, null);
private boolean dispatchItemByMaterialOrId(Player player, String itemId, int amount) {
return dispatchItemByMaterialOrId(player, itemId, amount, null);
}
/**
* 发放单个商品(支持按购物车携带的真实显示名重建附魔书等带NBT物品)。
* name 为 PHP 购物车携带的真实显示名(含附魔关键词),用于修正材质匹配取到裸附魔书的问题。
*/
private void dispatchItemByMaterialOrId(Player player, String itemId, int amount, String name) {
private boolean dispatchItemByMaterialOrId(Player player, String itemId, int amount, String name) {
try {
plugin.getLogger().info("[Web交易] 发放商品(材料匹配): " + itemId + " x" + amount + " 给 " + player.getName());
@@ -6313,6 +6329,7 @@ public class WebManager {
// ★ 附魔书空壳兜底(ID权威重建):若上面任一路径给出无附魔的附魔书
// (显示名解析失败、ENCHANT_MAP 为空等),用商品ID(MENDING_I 等)重建NBT。
// 若重建也失败,ensureEnchantedBookNbt 返回 null —— 不发放空壳,返回 false 触发整单取消/退款。
itemStack = plugin.getShopManager().ensureEnchantedBookNbt(itemStack, itemId, amount);
if (itemStack != null) {
@@ -6331,16 +6348,21 @@ public class WebManager {
}
player.sendMessage("§a[Web商城] §f成功购买商品: " + displayName + " x" + amount);
plugin.getLogger().info("[Web交易] 商品发放成功");
return true;
} else {
plugin.getLogger().warning("[Web交易] 商品不存在: " + itemId + "(Material或ID均无匹配)");
player.sendMessage("§c[Web商城] §f商品不存在: " + itemId);
// ★ 发放失败:附魔书解析失败或商品不存在 → 返回 false,由上层整单取消/退款
plugin.getLogger().warning("[Web交易] 商品无法发放(附魔书解析失败或商品不存在): " + itemId);
player.sendMessage("§c[Web商城] §f商品发放失败(解析失败): " + itemId);
return false;
}
} else {
plugin.getLogger().warning("[Web交易] ShopManager未初始化");
return false;
}
} catch (Exception e) {
plugin.getLogger().warning("[Web交易] 发放商品失败: " + e.getMessage());
e.printStackTrace();
return false;
}
}