本文最后更新于 995 天前,其中的信息可能已经有所发展或是发生改变。
简介
前几天接到一个小单子,需求就是要实现一个物品绑定的功能,被绑定的物品不能从容器中转移(例如丢出、放入/拿出箱子),也就是只能在玩家身上使用。
实现思路
给物品添加特殊的lore标记物品,当物品发生容器转移时检测物品是否含有特殊的lore,若有则取消操作。
核心代码
给物品添加标记lore
if(sender instanceof Player) {
int selectedLore = Integer.parseInt(args[1]);
if(selectedLore > _Bind_Lores.size() - 1 || selectedLore < 0) {
sendMsg(sender, "&c请输入正确的lore编号");
return;
}
String selectedLoreStr = _Bind_Lores.get(selectedLore);
Player player = (Player) sender;
ItemStack itemStack = player.getInventory().getItemInMainHand();
ItemMeta newMeta = itemStack.getItemMeta();
if(itemStack.getType().equals(Material.AIR)) {
sendMsg(player, "&c不能绑定空气");
return;
}
List < String > Itemlores = itemStack.getItemMeta().getLore();
if(Itemlores == null) Itemlores = new ArrayList < > ();
if(!Itemlores.contains(selectedLoreStr)) Itemlores.add(selectedLoreStr);
else {
sendMsg(player, "&c请不要重复绑定");
return;
}
newMeta.setLore(Itemlores);
itemStack.setItemMeta(newMeta);
player.getInventory().setItemInMainHand(itemStack);
sendMsg(sender, "&a物品已绑定");
} else {
sendMsg(sender, "&c此命令只有玩家可使用");
}
上面的_Bind_Lores
是一个存储标记lore的列表。
取消绑定
if(sender instanceof Player) {
Player player = (Player) sender;
ItemStack itemStack = player.getInventory().getItemInMainHand();
ItemMeta newMeta = itemStack.getItemMeta();
if(itemStack.getType().equals(Material.AIR)) {
sendMsg(sender, "&c不能解绑定空气");
return;
}
List < String > Itemlores = itemStack.getItemMeta().getLore();
if(Itemlores == null) Itemlores = new ArrayList < > ();
Itemlores.removeAll(_Bind_Lores);
newMeta.setLore(Itemlores);
itemStack.setItemMeta(newMeta);
player.getInventory().setItemInMainHand(itemStack);
sendMsg(sender, "&a物品已解除绑定");
} else {
sendMsg(sender, "&c此命令只有玩家可使用");
}
事件监听
isIntersection(List<String> o1, List<String> o2)
函数用于检测两个列表是否有交集。
丢出物品
@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent event) {
Player player = event.getPlayer();
boolean cantBeDropped = isIntersection(_Bind_Lores, event.getItemDrop().getItemStack().getItemMeta().getLore());
if(cantBeDropped && !player.isOp()) {
// 允许管理员任意操作被标记的物品
event.setCancelled(true);
sendMsg(player, _Anti_Tips);
}
}
容器转移
// 检查操作
public static boolean checkInventoryAction(InventoryAction action) {
InventoryAction[] shouldBeChecked = new InventoryAction[] {
InventoryAction.PICKUP_ALL,
InventoryAction.PICKUP_HALF,
InventoryAction.PICKUP_ONE,
InventoryAction.PICKUP_SOME,
InventoryAction.PLACE_ALL,
InventoryAction.PLACE_ONE,
InventoryAction.PLACE_SOME,
InventoryAction.MOVE_TO_OTHER_INVENTORY,
InventoryAction.DROP_ALL_CURSOR,
InventoryAction.DROP_ONE_CURSOR,
InventoryAction.DROP_ALL_SLOT,
InventoryAction.DROP_ONE_SLOT,
InventoryAction.SWAP_WITH_CURSOR
};
for(InventoryAction a: shouldBeChecked) {
if(a.equals(action)) {
return true;
}
}
return false;
}
// 事件监听
@EventHandler
public void onInventoryItemMoved(InventoryClickEvent event) {
InventoryAction action = event.getAction();
if(event.getCurrentItem() == null || event.getCurrentItem().getItemMeta() == null) return;
boolean cantBeDropped = checkInventoryAction(action) && isIntersection(_Bind_Lores, event.getCurrentItem().getItemMeta().getLore());
if(cantBeDropped && !event.getWhoClicked().isOp()) {
// 允许管理员任意操作被标记的物品
event.setCancelled(true);
sendMsg(event.getWhoClicked(), _Anti_Tips);
}
}