+ update MenuStored

+ update MenuBuilder
+ update ItemStacker
+ update TMap
This commit is contained in:
sky 2019-12-03 20:04:06 +08:00
parent 52376cd15e
commit c7573226a5
13 changed files with 513 additions and 2 deletions

View File

@ -56,4 +56,8 @@ public enum Version {
return vNull; return vNull;
} }
} }
public static int getCurrentVersionInt() {
return getCurrentVersion().versionInt;
}
} }

View File

@ -1,7 +1,11 @@
package io.izzel.taboolib.util; package io.izzel.taboolib.util;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import io.izzel.taboolib.util.item.ItemBuilder;
import io.izzel.taboolib.util.item.Items;
import io.izzel.taboolib.util.lite.Numbers; import io.izzel.taboolib.util.lite.Numbers;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.NumberConversions; import org.bukkit.util.NumberConversions;
import java.util.Arrays; import java.util.Arrays;
@ -82,6 +86,24 @@ public class TMap {
return new String[] {v[0], r.toString().replace("`", "")}; return new String[] {v[0], r.toString().replace("`", "")};
} }
public static ItemStack parseItem(String source) {
TMap map = TMap.parse(source);
ItemBuilder builder = new ItemBuilder(Items.asMaterial(map.get("material", "m", "type", "t")))
.amount(map.getInt(new String[]{"amount", "a"}, 1))
.damage(map.getInt("damage", "data", "d"))
.name(map.get("displayname", "display", "name", "n"));
if (map.getBoolean("shiny", "glowing", "glow")) {
builder.shiny();
}
if (map.get("lore", "l") != null) {
builder.lore(map.get("lore", "l").split("\\n"));
}
if (map.get("flag", "f") != null) {
builder.flags(Arrays.stream(map.get("flag", "f").split("\\n")).map(Items::asItemFlag).filter(Objects::nonNull).toArray(ItemFlag[]::new));
}
return builder.colored().build();
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {

View File

@ -0,0 +1,165 @@
package io.izzel.taboolib.util.item;
import io.izzel.taboolib.util.ArrayUtil;
import org.bukkit.entity.Player;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
/**
* @Author 坏黑
* @Since 2019-02-07 23:53
*/
public class ItemStacker {
/**
* 从箱子里移动物品到玩家背包
* 如果溢出则丢弃
*/
public static void moveItemFromChest(ItemStack item, Player player) {
AddResult result = addItemAndMerge(item, player.getInventory(), new Integer[0]);
if (result.countOut > 0) {
item.setAmount(result.countOut);
if (!addItemAndSplit(item, player.getInventory(), 0, true)) {
player.getWorld().dropItem(player.getLocation(), item);
}
}
}
public static boolean addItemAndSplit(ItemStack item, Inventory inventory, int start) {
return addItemAndSplit(item, inventory, start, false);
}
/**
* 添加并拆分但不合并
* 返回值为是否添加完成
*
* desc = 快捷栏逆向添加用于工作台拟真会忽略 start 参数
*/
public static boolean addItemAndSplit(ItemStack item, Inventory inventory, int start, boolean desc) {
int size = inventory instanceof PlayerInventory || inventory instanceof CraftingInventory ? 36 : inventory.getSize();
if (desc) {
// 8 ~ 0
for (int i = 8; i >= 0; i--) {
if (check(item, inventory, i)) {
return true;
}
}
}
// 9 ~ 36
for (int i = desc ? start + 9 : start; i < size; i++) {
if (check(item, inventory, i)) {
return true;
}
}
return false;
}
public static boolean addItemFromChestToPlayer(ItemStack item, Inventory inventory) {
for (int i = 8; i >= 0; i--) {
if (Items.isNull(inventory.getItem(i))) {
if (item.getAmount() > item.getType().getMaxStackSize()) {
ItemStack itemClone = item.clone();
itemClone.setAmount(item.getType().getMaxStackSize());
inventory.setItem(i, itemClone);
item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
} else {
ItemStack itemClone = item.clone();
itemClone.setAmount(item.getAmount());
inventory.setItem(i, itemClone);
item.setAmount(0);
return true;
}
}
}
for (int i = 35; i >= 9; i--) {
if (Items.isNull(inventory.getItem(i))) {
if (item.getAmount() > item.getType().getMaxStackSize()) {
ItemStack itemClone = item.clone();
itemClone.setAmount(item.getType().getMaxStackSize());
inventory.setItem(i, itemClone);
item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
} else {
ItemStack itemClone = item.clone();
itemClone.setAmount(item.getAmount());
inventory.setItem(i, itemClone);
item.setAmount(0);
return true;
}
}
}
return false;
}
/**
* 合并物品不新增
*/
public static AddResult addItemAndMerge(ItemStack item, Inventory inventory, Integer[] ignore) {
boolean changed = false;
int count = item.getAmount();
int size = inventory instanceof PlayerInventory || inventory instanceof CraftingInventory ? 36 : inventory.getSize();
for (int i = 0; i < size; i++) {
if (ArrayUtil.contains(ignore, i)) {
continue;
}
ItemStack inventoryItem = inventory.getItem(i);
if (!item.isSimilar(inventoryItem)) {
continue;
}
while (count > 0 && inventoryItem.getAmount() < item.getType().getMaxStackSize()) {
changed = true;
inventoryItem.setAmount(inventoryItem.getAmount() + 1);
count--;
}
if (count == 0) {
return new AddResult(count, changed);
}
}
return new AddResult(count, changed);
}
private static boolean check(ItemStack item, Inventory inventory, int i) {
if (Items.isNull(inventory.getItem(i))) {
// 如果物品数量过多
if (item.getAmount() > item.getType().getMaxStackSize()) {
ItemStack itemClone = item.clone();
itemClone.setAmount(item.getType().getMaxStackSize());
inventory.setItem(i, itemClone);
item.setAmount(item.getAmount() - item.getType().getMaxStackSize());
} else {
inventory.setItem(i, item.clone());
item.setAmount(0);
return true;
}
}
return false;
}
public static class AddResult {
private int countOut;
private boolean changed;
public AddResult(int countOut, boolean changed) {
this.countOut = countOut;
this.changed = changed;
}
public int getCountOut() {
return countOut;
}
public boolean isChanged() {
return changed;
}
@Override
public String toString() {
return "AddResult{" +
"countOut=" + countOut +
", changed=" + changed +
'}';
}
}
}

View File

@ -0,0 +1,13 @@
package io.izzel.taboolib.util.item.inventory;
import org.bukkit.inventory.Inventory;
/**
* @Author 坏黑
* @Since 2019-05-21 18:14
*/
public interface BuildTask {
void run(Inventory event);
}

View File

@ -7,7 +7,9 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryEvent;
import org.bukkit.event.inventory.InventoryInteractEvent; import org.bukkit.event.inventory.InventoryInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
@ -28,6 +30,10 @@ public class ClickEvent {
this.slot = slot; this.slot = slot;
} }
public List<ItemStack> getAffectItems() {
return clickType == ClickType.CLICK ? Servers.getAffectItemInClickEvent((InventoryClickEvent) event) : Lists.newArrayList();
}
public InventoryClickEvent castClick() { public InventoryClickEvent castClick() {
return (InventoryClickEvent) event; return (InventoryClickEvent) event;
} }
@ -52,8 +58,8 @@ public class ClickEvent {
return (Player) ((InventoryInteractEvent) event).getWhoClicked(); return (Player) ((InventoryInteractEvent) event).getWhoClicked();
} }
public List<ItemStack> getAffectItems() { public Inventory getInventory() {
return clickType == ClickType.CLICK ? Servers.getAffectItemInClickEvent((InventoryClickEvent) event) : Lists.newArrayList(); return ((InventoryEvent) event).getInventory();
} }
public void setCancelled(boolean c) { public void setCancelled(boolean c) {
@ -63,4 +69,14 @@ public class ClickEvent {
public boolean isCancelled() { public boolean isCancelled() {
return ((Cancellable) event).isCancelled(); return ((Cancellable) event).isCancelled();
} }
public ItemStack getCurrentItem() {
return clickType == ClickType.CLICK ? castClick().getCurrentItem() : null;
}
public void setCurrentItem(ItemStack item) {
if (clickType == ClickType.CLICK) {
castClick().setCurrentItem(item);
}
}
} }

View File

@ -13,6 +13,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.event.server.PluginDisableEvent;
@ -32,6 +33,14 @@ class ClickListener implements Listener {
Bukkit.getOnlinePlayers().stream().filter(player -> player.getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && e.getPlugin().equals(((MenuHolder) player.getOpenInventory().getTopInventory().getHolder()).getBuilder().getPlugin())).forEach(HumanEntity::closeInventory); Bukkit.getOnlinePlayers().stream().filter(player -> player.getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && e.getPlugin().equals(((MenuHolder) player.getOpenInventory().getTopInventory().getHolder()).getBuilder().getPlugin())).forEach(HumanEntity::closeInventory);
} }
@EventHandler
public void e(InventoryOpenEvent e) {
if (e.getInventory().getHolder() instanceof MenuHolder) {
Bukkit.getScheduler().runTask(TabooLib.getPlugin(), () -> ((MenuHolder) e.getInventory().getHolder()).getBuilder().open((OpenTask) -> e.getInventory()));
Bukkit.getScheduler().runTaskAsynchronously(TabooLib.getPlugin(), () -> ((MenuHolder) e.getInventory().getHolder()).getBuilder().openAsync((OpenTask) -> e.getInventory()));
}
}
@EventHandler @EventHandler
public void e(InventoryClickEvent e) { public void e(InventoryClickEvent e) {
if (e.getInventory().getHolder() instanceof MenuHolder) { if (e.getInventory().getHolder() instanceof MenuHolder) {

View File

@ -5,6 +5,7 @@ import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.util.Ref; import io.izzel.taboolib.util.Ref;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@ -24,6 +25,8 @@ public class MenuBuilder {
private char[][] items = new char[0][0]; private char[][] items = new char[0][0];
private ClickTask clickTask; private ClickTask clickTask;
private CloseTask closeTask; private CloseTask closeTask;
private BuildTask buildTask;
private BuildTask buildTaskAsync;
private boolean lockHand; private boolean lockHand;
public MenuBuilder(Plugin plugin) { public MenuBuilder(Plugin plugin) {
@ -43,6 +46,11 @@ public class MenuBuilder {
return this; return this;
} }
public MenuBuilder lockHand(boolean value) {
this.lockHand = value;
return this;
}
public MenuBuilder event(ClickTask clickTask) { public MenuBuilder event(ClickTask clickTask) {
this.clickTask = clickTask; this.clickTask = clickTask;
return this; return this;
@ -53,6 +61,16 @@ public class MenuBuilder {
return this; return this;
} }
public MenuBuilder build(BuildTask buildTask) {
this.buildTask = buildTask;
return this;
}
public MenuBuilder buildAsync(BuildTask buildTask) {
this.buildTaskAsync = buildTask;
return this;
}
public MenuBuilder title(String title) { public MenuBuilder title(String title) {
this.title = title; this.title = title;
return this; return this;
@ -76,6 +94,10 @@ public class MenuBuilder {
return this; return this;
} }
public void open(Player player) {
player.openInventory(build());
}
public Inventory build() { public Inventory build() {
Inventory inventory = Bukkit.createInventory(new MenuHolder(this), rows, String.valueOf(title)); Inventory inventory = Bukkit.createInventory(new MenuHolder(this), rows, String.valueOf(title));
for (int i = 0; i < items.length && i < rows; i++) { for (int i = 0; i < items.length && i < rows; i++) {

View File

@ -0,0 +1,13 @@
package io.izzel.taboolib.util.item.inventory.stored;
import io.izzel.taboolib.util.item.inventory.ClickEvent;
import org.bukkit.inventory.ItemStack;
public abstract class Action {
public abstract ItemStack getCurrent(ClickEvent e);
public abstract void setCurrent(ClickEvent e, ItemStack item);
public abstract int getCurrentSlot(ClickEvent e);
}

View File

@ -0,0 +1,26 @@
package io.izzel.taboolib.util.item.inventory.stored;
import io.izzel.taboolib.util.item.inventory.ClickEvent;
import org.bukkit.inventory.ItemStack;
/**
* @Author sky
* @Since 2019-12-03 19:17
*/
public class ActionClick extends Action{
@Override
public ItemStack getCurrent(ClickEvent e) {
return e.getClicker().getItemOnCursor();
}
@Override
public void setCurrent(ClickEvent e, ItemStack item) {
e.getClicker().setItemOnCursor(item);
}
@Override
public int getCurrentSlot(ClickEvent e) {
return e.getRawSlot();
}
}

View File

@ -0,0 +1,26 @@
package io.izzel.taboolib.util.item.inventory.stored;
import io.izzel.taboolib.util.item.inventory.ClickEvent;
import org.bukkit.inventory.ItemStack;
/**
* @Author sky
* @Since 2019-12-03 19:20
*/
public class ActionKeyboard extends Action {
@Override
public ItemStack getCurrent(ClickEvent e) {
return e.getClicker().getInventory().getItem(e.castClick().getHotbarButton());
}
@Override
public void setCurrent(ClickEvent e, ItemStack item) {
e.getClicker().getInventory().setItem(e.castClick().getHotbarButton(), item);
}
@Override
public int getCurrentSlot(ClickEvent e) {
return e.getRawSlot();
}
}

View File

@ -0,0 +1,30 @@
package io.izzel.taboolib.util.item.inventory.stored;
import io.izzel.taboolib.util.item.ItemStacker;
import io.izzel.taboolib.util.item.inventory.ClickEvent;
import org.bukkit.inventory.ItemStack;
/**
* @Author sky
* @Since 2019-12-03 19:20
*/
public class ActionQuickTake extends Action {
@Override
public ItemStack getCurrent(ClickEvent e) {
return e.getClicker().getItemOnCursor();
}
@Override
public void setCurrent(ClickEvent e, ItemStack item) {
if (item != null) {
ItemStacker.moveItemFromChest(item, e.getClicker());
}
e.getClicker().setItemOnCursor(null);
}
@Override
public int getCurrentSlot(ClickEvent e) {
return e.getRawSlot();
}
}

View File

@ -0,0 +1,164 @@
package io.izzel.taboolib.util.item.inventory.stored;
import io.izzel.taboolib.util.item.Items;
import io.izzel.taboolib.util.item.inventory.ClickEvent;
import io.izzel.taboolib.util.item.inventory.ClickType;
import io.izzel.taboolib.util.item.inventory.MenuBuilder;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
/**
* @Author sky
* @Since 2019-12-03 13:24
*/
public abstract class MenuStored {
protected Player player;
public MenuStored(Player player) {
this.player = player;
}
public void open() {
MenuBuilder.builder()
.lockHand(isLockHand())
.title(getTitle())
.rows(getRows())
.event(this::onClick)
.close(this::onClose)
.build(this::refresh)
.buildAsync(this::refreshAsync)
.open(player);
}
public boolean isLockHand() {
return false;
}
public String getTitle() {
return player.getName();
}
public int getRows() {
return 1;
}
public void onClick(ClickEvent e) {
if (e.getClickType() == ClickType.CLICK) {
// 自动装填
if (e.castClick().getClick().isShiftClick() && e.getRawSlot() >= e.getInventory().getSize() && Items.nonNull(e.getCurrentItem())) {
e.setCancelled(true);
// 获取有效位置
int validSlot = getIntoSlot(e.getInventory(), e.getCurrentItem());
if (validSlot >= 0) {
// 设置物品
intoItem(e.getInventory(), e.getCurrentItem(), validSlot);
// 移除物品
e.setCurrentItem(null);
onClicked();
}
}
// 手动装填
else {
Action action = null;
if (e.castClick().getClick().isShiftClick() && e.getRawSlot() >= 0 && e.getRawSlot() < e.getInventory().getSize()) {
action = new ActionQuickTake();
} else if (e.castClick().getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY) {
action = new ActionKeyboard();
} else {
action = new ActionClick();
}
// 点击有效位置
if (isIntoSlot(e.getInventory(), action.getCurrent(e), action.getCurrentSlot(e))) {
e.setCancelled(true);
// 提取动作
if (Items.isNull(action.getCurrent(e)) && !existsItem(e.getInventory(), action.getCurrentSlot(e))) {
// 提取物品
action.setCurrent(e, getItem(e.getInventory(), action.getCurrentSlot(e)));
// 删除物品
intoItem(e.getInventory(), null, action.getCurrentSlot(e));
onClicked();
}
// 合法的位置
else if (shouldIntoSlot(e.getInventory(), action.getCurrent(e), action.getCurrentSlot(e))) {
ItemStack current = action.getCurrent(e);
// 提取物品
action.setCurrent(e, getItem(e.getInventory(), action.getCurrentSlot(e)));
// 写入物品
intoItem(e.getInventory(), current, action.getCurrentSlot(e));
onClicked();
}
}
}
}
}
/**
* 当点击动作完成时
*/
public void onClicked() {
}
/**
* 当界面关闭时
*/
public void onClose(InventoryCloseEvent e) {
}
/**
* 当界面刷新时
*/
public void refresh(Inventory inventory) {
}
/**
* 当界面刷新时异步
*/
public void refreshAsync(Inventory inventory) {
}
/**
* 物品是否可以放入该位置
*/
public boolean shouldIntoSlot(Inventory inventory, ItemStack item, int slot) {
return false;
}
/**
* 是否为有效的位置
*/
public boolean isIntoSlot(Inventory inventory, ItemStack item, int slot) {
return false;
}
/**
* 获取界面中有效的位置
* 用于 shift 点击时的自动装填
*/
public int getIntoSlot(Inventory inventory, ItemStack item) {
return -1;
}
/**
* 物品存入界面
*/
public void intoItem(Inventory inventory, ItemStack item, int slot) {
inventory.setItem(slot, item);
}
/**
* 是否存在物品
*/
public boolean existsItem(Inventory inventory, int slot) {
return false;
}
/**
* 获取物品
*/
public ItemStack getItem(Inventory inventory, int slot) {
return inventory.getItem(slot);
}
}

View File

@ -1,3 +1,4 @@
package io.izzel.taboolib.util.lite; package io.izzel.taboolib.util.lite;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;