mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-26 12:46:04 +01:00
Work on npc shop; now possible to buy and sell
This commit is contained in:
parent
1f9931fdff
commit
70d7cfa6f2
@ -39,9 +39,16 @@ import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.trait.TraitName;
|
||||
import net.citizensnpcs.api.util.Colorizer;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.trait.shop.ItemAction;
|
||||
import net.citizensnpcs.trait.shop.ItemAction.ItemActionGUI;
|
||||
import net.citizensnpcs.trait.shop.MoneyAction;
|
||||
import net.citizensnpcs.trait.shop.MoneyAction.MoneyActionGUI;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction.GUI;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction.Transaction;
|
||||
import net.citizensnpcs.trait.shop.PermissionAction;
|
||||
import net.citizensnpcs.trait.shop.PermissionAction.PermissionActionGUI;
|
||||
import net.citizensnpcs.util.Util;
|
||||
|
||||
/**
|
||||
* Shop trait for NPC GUI shops.
|
||||
@ -62,7 +69,7 @@ public class ShopTrait extends Trait {
|
||||
|
||||
public static class NPCShop {
|
||||
@Persist(value = "")
|
||||
private final String name;
|
||||
private String name;
|
||||
@Persist(reify = true)
|
||||
private final List<NPCShopPage> pages = Lists.newArrayList();
|
||||
@Persist
|
||||
@ -72,6 +79,9 @@ public class ShopTrait extends Trait {
|
||||
@Persist
|
||||
private String viewPermission;
|
||||
|
||||
private NPCShop() {
|
||||
}
|
||||
|
||||
private NPCShop(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@ -276,13 +286,13 @@ public class ShopTrait extends Trait {
|
||||
@MenuSlot(slot = { 3, 4 }, material = Material.DISPENSER, amount = 1, title = "<f>Place display item below")
|
||||
public static class NPCShopItemEditor extends InventoryMenuPage {
|
||||
@MenuPattern(
|
||||
offset = { 0, 0 },
|
||||
offset = { 0, 6 },
|
||||
slots = { @MenuSlot(pat = 'x', material = Material.AIR) },
|
||||
value = "x x\n x \nx x")
|
||||
private InventoryMenuPattern actionItems;
|
||||
private final Consumer<NPCShopItem> callback;
|
||||
@MenuPattern(
|
||||
offset = { 0, 6 },
|
||||
offset = { 0, 0 },
|
||||
slots = { @MenuSlot(pat = 'x', material = Material.AIR) },
|
||||
value = "x x\n x \nx x")
|
||||
private InventoryMenuPattern costItems;
|
||||
@ -300,30 +310,29 @@ public class ShopTrait extends Trait {
|
||||
public void initialise(MenuContext ctx) {
|
||||
this.ctx = ctx;
|
||||
if (modified.display != null) {
|
||||
ctx.getSlot(9 + 4).setItemStack(modified.display);
|
||||
ctx.getSlot(9 * 4 + 4).setItemStack(modified.display);
|
||||
}
|
||||
int pos = 0;
|
||||
for (GUI template : NPCShopAction.getGUIs()) {
|
||||
ItemStack item = template.createMenuItem();
|
||||
if (item == null)
|
||||
if (template.createMenuItem(null) == null)
|
||||
continue;
|
||||
|
||||
costItems.getSlots().get(pos).setItemStack(item);
|
||||
NPCShopAction oldCost = modified.cost.stream().filter(template::manages).findFirst().orElse(null);
|
||||
costItems.getSlots().get(pos)
|
||||
.setItemStack(Util.editTitle(template.createMenuItem(oldCost), title -> title + " Cost"));
|
||||
costItems.getSlots().get(pos).setClickHandler(event -> {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu()
|
||||
.transition(template.createEditor(
|
||||
modified.cost.stream().filter(template::manages).findFirst().orElse(null),
|
||||
cost -> modified.changeCost(template::manages, cost)));
|
||||
ctx.getMenu().transition(
|
||||
template.createEditor(oldCost, cost -> modified.changeCost(template::manages, cost)));
|
||||
});
|
||||
|
||||
actionItems.getSlots().get(pos).setItemStack(item);
|
||||
actionItems.getSlots().get(pos).addClickHandler(event -> {
|
||||
NPCShopAction oldResult = modified.result.stream().filter(template::manages).findFirst().orElse(null);
|
||||
actionItems.getSlots().get(pos)
|
||||
.setItemStack(Util.editTitle(template.createMenuItem(oldResult), title -> title + " Result"));
|
||||
actionItems.getSlots().get(pos).setClickHandler(event -> {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu()
|
||||
.transition(template.createEditor(
|
||||
modified.result.stream().filter(template::manages).findFirst().orElse(null),
|
||||
result -> modified.changeResult(template::manages, result)));
|
||||
ctx.getMenu().transition(template.createEditor(oldResult,
|
||||
result -> modified.changeResult(template::manages, result)));
|
||||
});
|
||||
|
||||
pos++;
|
||||
@ -400,13 +409,16 @@ public class ShopTrait extends Trait {
|
||||
}
|
||||
|
||||
public static class NPCShopPage {
|
||||
@Persist("")
|
||||
@Persist("$key")
|
||||
private int index;
|
||||
@Persist(keyType = Integer.class, reify = true)
|
||||
private final Map<Integer, NPCShopItem> items = Maps.newHashMap();
|
||||
@Persist
|
||||
private String title;
|
||||
|
||||
private NPCShopPage() {
|
||||
}
|
||||
|
||||
public NPCShopPage(int page) {
|
||||
this.index = page;
|
||||
}
|
||||
@ -475,21 +487,23 @@ public class ShopTrait extends Trait {
|
||||
ctx.getMenu().transition(new NPCShopViewer(shop));
|
||||
});
|
||||
}
|
||||
ctx.getSlot(2).setDescription("<f>Edit shop view permission<br>" + shop.getRequiredPermission());
|
||||
ctx.getSlot(6).setDescription("<f>Edit shop title<br>" + shop.title);
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 4 }, material = Material.FEATHER, amount = 1, title = "Edit shop items")
|
||||
@MenuSlot(slot = { 0, 4 }, material = Material.FEATHER, amount = 1, title = "<f>Edit shop items")
|
||||
public void onEditItems(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu().transition(new NPCShopContentsEditor(shop));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 2 }, material = Material.OAK_SIGN, amount = 1, title = "Edit shop permission")
|
||||
@MenuSlot(slot = { 0, 2 }, material = Material.OAK_SIGN, amount = 1)
|
||||
public void onPermissionChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(shop::getRequiredPermission, shop::setPermission));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 6 }, material = Material.NAME_TAG, amount = 1, title = "Edit shop title")
|
||||
@MenuSlot(slot = { 0, 6 }, material = Material.NAME_TAG, amount = 1)
|
||||
public void onSetTitle(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(() -> shop.title, newTitle -> {
|
||||
@ -497,7 +511,7 @@ public class ShopTrait extends Trait {
|
||||
}));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 0 }, material = Material.BOOK, amount = 1, title = "Edit shop type")
|
||||
@MenuSlot(slot = { 0, 0 }, material = Material.BOOK, amount = 1, title = "<f>Edit shop type")
|
||||
public void onShopTypeChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
event.setCancelled(true);
|
||||
ctx.getMenu().transition(InputMenus.<ShopType> picker("Edit shop type", chosen -> {
|
||||
@ -594,4 +608,9 @@ public class ShopTrait extends Trait {
|
||||
}
|
||||
|
||||
private static StoredShops SAVED = new StoredShops();
|
||||
static {
|
||||
NPCShopAction.register(ItemAction.class, "items", new ItemActionGUI());
|
||||
NPCShopAction.register(PermissionAction.class, "permissions", new PermissionActionGUI());
|
||||
NPCShopAction.register(MoneyAction.class, "money", new MoneyActionGUI());
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.trait.TraitName;
|
||||
@ -88,33 +87,6 @@ public class SkinTrait extends Trait {
|
||||
checkPlaceholder(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void migrate() {
|
||||
boolean update = false;
|
||||
if (npc.data().has(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA)) {
|
||||
textureRaw = npc.data().get(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA);
|
||||
npc.data().remove(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA);
|
||||
update = true;
|
||||
}
|
||||
if (npc.data().has(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA)) {
|
||||
signature = npc.data().get(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA);
|
||||
npc.data().remove(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA);
|
||||
update = true;
|
||||
}
|
||||
if (npc.data().has(NPC.PLAYER_SKIN_UUID_METADATA)) {
|
||||
this.skinName = npc.data().get(NPC.PLAYER_SKIN_UUID_METADATA);
|
||||
npc.data().remove(NPC.PLAYER_SKIN_UUID_METADATA);
|
||||
update = true;
|
||||
}
|
||||
if (npc.data().has(NPC.PLAYER_SKIN_USE_LATEST)) {
|
||||
this.updateSkins = npc.data().get(NPC.PLAYER_SKIN_USE_LATEST);
|
||||
npc.data().remove(NPC.PLAYER_SKIN_USE_LATEST);
|
||||
}
|
||||
if (update) {
|
||||
onSkinChange(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSkinChange(boolean forceUpdate) {
|
||||
if (npc.isSpawned() && npc.getEntity() instanceof SkinnableEntity) {
|
||||
((SkinnableEntity) npc.getEntity()).getSkinTracker().notifySkinChange(forceUpdate);
|
||||
@ -123,7 +95,6 @@ public class SkinTrait extends Trait {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
migrate();
|
||||
if (timer-- > 0)
|
||||
return;
|
||||
timer = Setting.PLACEHOLDER_SKIN_UPDATE_FREQUENCY.asInt();
|
||||
|
159
main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java
Normal file
159
main/src/main/java/net/citizensnpcs/trait/shop/ItemAction.java
Normal file
@ -0,0 +1,159 @@
|
||||
package net.citizensnpcs.trait.shop;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPage;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuSlot;
|
||||
import net.citizensnpcs.api.gui.Menu;
|
||||
import net.citizensnpcs.api.gui.MenuContext;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.util.Util;
|
||||
|
||||
public class ItemAction extends NPCShopAction {
|
||||
@Persist
|
||||
public List<ItemStack> items = Lists.newArrayList();
|
||||
|
||||
public ItemAction() {
|
||||
}
|
||||
|
||||
public ItemAction(ItemStack... items) {
|
||||
this(Arrays.asList(items));
|
||||
}
|
||||
|
||||
public ItemAction(List<ItemStack> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof InventoryHolder))
|
||||
return Transaction.fail();
|
||||
Inventory source = ((InventoryHolder) entity).getInventory();
|
||||
return Transaction.create(() -> {
|
||||
int free = 0;
|
||||
for (ItemStack stack : source.getContents()) {
|
||||
if (stack == null || stack.getType() == Material.AIR) {
|
||||
free++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return free >= items.size();
|
||||
}, () -> {
|
||||
source.addItem(items.toArray(new ItemStack[items.size()]));
|
||||
}, () -> {
|
||||
source.removeItem(items.toArray(new ItemStack[items.size()]));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof InventoryHolder))
|
||||
return Transaction.fail();
|
||||
Inventory source = ((InventoryHolder) entity).getInventory();
|
||||
return Transaction.create(() -> {
|
||||
Map<Material, Integer> required = items.stream()
|
||||
.collect(Collectors.toMap(k -> k.getType(), v -> v.getAmount()));
|
||||
boolean contains = true;
|
||||
for (Map.Entry<Material, Integer> entry : required.entrySet()) {
|
||||
if (!source.contains(entry.getKey(), entry.getValue())) {
|
||||
contains = false;
|
||||
}
|
||||
}
|
||||
for (ItemStack item : items) {
|
||||
if (item.hasItemMeta() && !source.contains(item)) {
|
||||
contains = false;
|
||||
}
|
||||
}
|
||||
return contains;
|
||||
}, () -> {
|
||||
source.removeItem(items.toArray(new ItemStack[items.size()]));
|
||||
}, () -> {
|
||||
source.addItem(items.toArray(new ItemStack[items.size()]));
|
||||
});
|
||||
}
|
||||
|
||||
@Menu(title = "Item editor", dimensions = { 3, 9 })
|
||||
public static class ItemActionEditor extends InventoryMenuPage {
|
||||
private ItemAction base;
|
||||
private Consumer<NPCShopAction> callback;
|
||||
private MenuContext ctx;
|
||||
|
||||
public ItemActionEditor() {
|
||||
}
|
||||
|
||||
public ItemActionEditor(ItemAction base, Consumer<NPCShopAction> callback) {
|
||||
this.base = base;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(MenuContext ctx) {
|
||||
this.ctx = ctx;
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
InventoryMenuSlot slot = ctx.getSlot(i);
|
||||
slot.clear();
|
||||
if (i < base.items.size()) {
|
||||
slot.setItemStack(base.items.get(i).clone());
|
||||
}
|
||||
slot.setClickHandler(event -> {
|
||||
event.setCancelled(true);
|
||||
event.setCurrentItem(event.getCursorNonNull());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(HumanEntity player) {
|
||||
List<ItemStack> items = Lists.newArrayList();
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
if (ctx.getSlot(i).getCurrentItem() != null) {
|
||||
items.add(ctx.getSlot(i).getCurrentItem().clone());
|
||||
}
|
||||
}
|
||||
callback.accept(items.isEmpty() ? null : new ItemAction(items));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemActionGUI implements GUI {
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
return new ItemActionEditor(previous == null ? new ItemAction() : null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem(NPCShopAction previous) {
|
||||
String description = null;
|
||||
if (previous != null) {
|
||||
ItemAction old = (ItemAction) previous;
|
||||
description = old.items.size() + " items";
|
||||
for (int i = 0; i < old.items.size(); i++) {
|
||||
ItemStack item = old.items.get(i);
|
||||
description += "\n" + item.getAmount() + " " + Util.prettyEnum(item.getType());
|
||||
if (i == 3) {
|
||||
description += "...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Util.createItem(Material.CHEST, "Item", description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof ItemAction;
|
||||
}
|
||||
}
|
||||
}
|
100
main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java
Normal file
100
main/src/main/java/net/citizensnpcs/trait/shop/MoneyAction.java
Normal file
@ -0,0 +1,100 @@
|
||||
package net.citizensnpcs.trait.shop;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.citizensnpcs.api.gui.InputMenus;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPage;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.util.Util;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
|
||||
public class MoneyAction extends NPCShopAction {
|
||||
@Persist
|
||||
public double money;
|
||||
|
||||
public MoneyAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof OfflinePlayer))
|
||||
return Transaction.fail();
|
||||
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
|
||||
OfflinePlayer player = (OfflinePlayer) entity;
|
||||
return Transaction.create(() -> {
|
||||
return true;
|
||||
}, () -> {
|
||||
economy.depositPlayer(player, money);
|
||||
}, () -> {
|
||||
economy.withdrawPlayer(player, money);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof OfflinePlayer))
|
||||
return Transaction.fail();
|
||||
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
|
||||
OfflinePlayer player = (OfflinePlayer) entity;
|
||||
return Transaction.create(() -> {
|
||||
return economy.has(player, money);
|
||||
}, () -> {
|
||||
economy.withdrawPlayer(player, money);
|
||||
}, () -> {
|
||||
economy.depositPlayer(player, money);
|
||||
});
|
||||
}
|
||||
|
||||
public static class MoneyActionGUI implements GUI {
|
||||
private Boolean supported;
|
||||
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
final MoneyAction action = previous == null ? new MoneyAction() : (MoneyAction) previous;
|
||||
return InputMenus.filteredStringSetter(() -> Double.toString(action.money), (s) -> {
|
||||
try {
|
||||
double result = Double.parseDouble(s);
|
||||
if (result < 0)
|
||||
return false;
|
||||
action.money = result;
|
||||
} catch (NumberFormatException nfe) {
|
||||
return false;
|
||||
}
|
||||
callback.accept(action);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem(NPCShopAction previous) {
|
||||
if (supported == null) {
|
||||
try {
|
||||
supported = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider() != null;
|
||||
} catch (Throwable t) {
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
if (!supported) {
|
||||
return null;
|
||||
}
|
||||
String description = null;
|
||||
if (previous != null) {
|
||||
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
|
||||
MoneyAction old = (MoneyAction) previous;
|
||||
description = old.money + " " + economy.currencyNamePlural();
|
||||
}
|
||||
return Util.createItem(Material.GOLD_INGOT, "Money", description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof MoneyAction;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +1,16 @@
|
||||
package net.citizensnpcs.trait.shop;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.citizensnpcs.api.gui.InputMenus;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPage;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuSlot;
|
||||
import net.citizensnpcs.api.gui.Menu;
|
||||
import net.citizensnpcs.api.gui.MenuContext;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.api.persistence.PersistenceLoader;
|
||||
import net.citizensnpcs.api.persistence.PersisterRegistry;
|
||||
import net.citizensnpcs.api.util.Placeholders;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction.ItemAction.ItemActionGUI;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction.MoneyAction.MoneyActionGUI;
|
||||
import net.citizensnpcs.trait.shop.NPCShopAction.PermissionAction.PermissionActionGUI;
|
||||
import net.citizensnpcs.util.Util;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
public abstract class NPCShopAction implements Cloneable {
|
||||
@Override
|
||||
@ -52,332 +29,11 @@ public abstract class NPCShopAction implements Cloneable {
|
||||
public static interface GUI {
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback);
|
||||
|
||||
public ItemStack createMenuItem();
|
||||
public ItemStack createMenuItem(NPCShopAction previous);
|
||||
|
||||
public boolean manages(NPCShopAction action);
|
||||
}
|
||||
|
||||
public static class ItemAction extends NPCShopAction {
|
||||
@Persist
|
||||
public List<ItemStack> items = Lists.newArrayList();
|
||||
|
||||
public ItemAction() {
|
||||
}
|
||||
|
||||
public ItemAction(ItemStack... items) {
|
||||
this(Arrays.asList(items));
|
||||
}
|
||||
|
||||
public ItemAction(List<ItemStack> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof InventoryHolder))
|
||||
return Transaction.fail();
|
||||
Inventory source = ((InventoryHolder) entity).getInventory();
|
||||
return Transaction.create(() -> {
|
||||
return source.all(Material.AIR).size() > items.size();
|
||||
}, () -> {
|
||||
source.addItem(items.toArray(new ItemStack[items.size()]));
|
||||
}, () -> {
|
||||
source.removeItem(items.toArray(new ItemStack[items.size()]));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof InventoryHolder))
|
||||
return Transaction.fail();
|
||||
Inventory source = ((InventoryHolder) entity).getInventory();
|
||||
return Transaction.create(() -> {
|
||||
return source.all(Material.AIR).size() > items.size();
|
||||
}, () -> {
|
||||
source.removeItem(items.toArray(new ItemStack[items.size()]));
|
||||
}, () -> {
|
||||
source.addItem(items.toArray(new ItemStack[items.size()]));
|
||||
});
|
||||
}
|
||||
|
||||
@Menu(title = "Item editor", dimensions = { 3, 9 })
|
||||
public static class ItemActionEditor extends InventoryMenuPage {
|
||||
private ItemAction base;
|
||||
private Consumer<NPCShopAction> callback;
|
||||
private MenuContext ctx;
|
||||
|
||||
public ItemActionEditor() {
|
||||
}
|
||||
|
||||
public ItemActionEditor(ItemAction base, Consumer<NPCShopAction> callback) {
|
||||
this.base = base;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(MenuContext ctx) {
|
||||
this.ctx = ctx;
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
InventoryMenuSlot slot = ctx.getSlot(i);
|
||||
slot.clear();
|
||||
if (i < base.items.size()) {
|
||||
slot.setItemStack(base.items.get(i).clone());
|
||||
}
|
||||
slot.setClickHandler(event -> {
|
||||
event.setCancelled(true);
|
||||
event.setCurrentItem(event.getCursorNonNull());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(HumanEntity player) {
|
||||
List<ItemStack> items = Lists.newArrayList();
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
if (ctx.getSlot(i).getCurrentItem() != null) {
|
||||
items.add(ctx.getSlot(i).getCurrentItem().clone());
|
||||
}
|
||||
}
|
||||
callback.accept(items.isEmpty() ? null : new ItemAction(items));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemActionGUI implements GUI {
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
return new ItemActionEditor(previous == null ? new ItemAction() : null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem() {
|
||||
return Util.createItem(Material.CHEST, "Item");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof ItemAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MoneyAction extends NPCShopAction {
|
||||
@Persist
|
||||
public double money;
|
||||
|
||||
public MoneyAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof OfflinePlayer))
|
||||
return Transaction.fail();
|
||||
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
|
||||
OfflinePlayer player = (OfflinePlayer) entity;
|
||||
return Transaction.create(() -> {
|
||||
return true;
|
||||
}, () -> {
|
||||
economy.depositPlayer(player, money);
|
||||
}, () -> {
|
||||
economy.withdrawPlayer(player, money);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof OfflinePlayer))
|
||||
return Transaction.fail();
|
||||
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
|
||||
OfflinePlayer player = (OfflinePlayer) entity;
|
||||
return Transaction.create(() -> {
|
||||
return economy.has(player, money);
|
||||
}, () -> {
|
||||
economy.withdrawPlayer(player, money);
|
||||
}, () -> {
|
||||
economy.depositPlayer(player, money);
|
||||
});
|
||||
}
|
||||
|
||||
public static class MoneyActionGUI implements GUI {
|
||||
private Boolean supported;
|
||||
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
final MoneyAction action = previous == null ? new MoneyAction() : (MoneyAction) previous;
|
||||
return InputMenus.filteredStringSetter(() -> Double.toString(action.money), (s) -> {
|
||||
try {
|
||||
double result = Double.parseDouble(s);
|
||||
if (result < 0)
|
||||
return false;
|
||||
action.money = result;
|
||||
} catch (NumberFormatException nfe) {
|
||||
return false;
|
||||
}
|
||||
callback.accept(action);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem() {
|
||||
if (supported == null) {
|
||||
try {
|
||||
supported = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider() != null;
|
||||
} catch (Throwable t) {
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
if (!supported) {
|
||||
return null;
|
||||
}
|
||||
return Util.createItem(Material.GOLD_INGOT, "Money");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof MoneyAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PermissionAction extends NPCShopAction {
|
||||
@Persist
|
||||
public List<String> permissions = Lists.newArrayList();
|
||||
|
||||
public PermissionAction() {
|
||||
}
|
||||
|
||||
public PermissionAction(List<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof Player))
|
||||
return Transaction.fail();
|
||||
Player player = (Player) entity;
|
||||
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
|
||||
return Transaction.create(() -> {
|
||||
return true;
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerAdd(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerRemove(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof Player))
|
||||
return Transaction.fail();
|
||||
Player player = (Player) entity;
|
||||
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
|
||||
return Transaction.create(() -> {
|
||||
for (String permission : permissions) {
|
||||
if (!perm.playerHas(player, Placeholders.replace(permission, player))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerRemove(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerAdd(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Menu(title = "Permissions editor", dimensions = { 3, 9 })
|
||||
public static class PermissionActionEditor extends InventoryMenuPage {
|
||||
private PermissionAction base;
|
||||
private Consumer<NPCShopAction> callback;
|
||||
|
||||
public PermissionActionEditor() {
|
||||
}
|
||||
|
||||
public PermissionActionEditor(PermissionAction base, Consumer<NPCShopAction> callback) {
|
||||
this.base = base;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(MenuContext ctx) {
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
final int idx = i;
|
||||
ctx.getSlot(i).clear();
|
||||
if (i < base.permissions.size()) {
|
||||
ctx.getSlot(i).setItemStack(new ItemStack(Material.FEATHER), "<f>Set permission",
|
||||
"Right click to remove\nCurrently: " + base.permissions.get(i));
|
||||
}
|
||||
ctx.getSlot(i).setClickHandler(event -> {
|
||||
if (event.isRightClick()) {
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.remove(idx);
|
||||
ctx.getSlot(idx).setItemStack(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(
|
||||
() -> idx < base.permissions.size() ? base.permissions.get(idx) : "", (res) -> {
|
||||
if (res == null) {
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.remove(idx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.set(idx, res);
|
||||
} else {
|
||||
base.permissions.add(res);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(HumanEntity player) {
|
||||
callback.accept(base.permissions.isEmpty() ? null : base);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PermissionActionGUI implements GUI {
|
||||
private Boolean supported;
|
||||
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
return new PermissionActionEditor(
|
||||
previous == null ? new PermissionAction() : (PermissionAction) previous, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem() {
|
||||
if (supported == null) {
|
||||
try {
|
||||
supported = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider() != null;
|
||||
} catch (Throwable t) {
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
if (!supported) {
|
||||
return null;
|
||||
}
|
||||
return Util.createItem(Util.getFallbackMaterial("OAK_SIGN", "SIGN"), "Permission");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof PermissionAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Transaction {
|
||||
private final Runnable execute;
|
||||
private final Supplier<Boolean> possible;
|
||||
@ -424,9 +80,4 @@ public abstract class NPCShopAction implements Cloneable {
|
||||
private static final Map<Class<? extends NPCShopAction>, GUI> GUI = new WeakHashMap<>();
|
||||
private static final PersisterRegistry<NPCShopAction> REGISTRY = PersistenceLoader
|
||||
.createRegistry(NPCShopAction.class);
|
||||
static {
|
||||
register(ItemAction.class, "items", new ItemActionGUI());
|
||||
register(PermissionAction.class, "permissions", new PermissionActionGUI());
|
||||
register(MoneyAction.class, "money", new MoneyActionGUI());
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package net.citizensnpcs.trait.shop;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.citizensnpcs.api.gui.InputMenus;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPage;
|
||||
import net.citizensnpcs.api.gui.Menu;
|
||||
import net.citizensnpcs.api.gui.MenuContext;
|
||||
import net.citizensnpcs.api.persistence.Persist;
|
||||
import net.citizensnpcs.api.util.Placeholders;
|
||||
import net.citizensnpcs.util.Util;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
public class PermissionAction extends NPCShopAction {
|
||||
@Persist
|
||||
public List<String> permissions = Lists.newArrayList();
|
||||
|
||||
public PermissionAction() {
|
||||
}
|
||||
|
||||
public PermissionAction(List<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction grant(Entity entity) {
|
||||
if (!(entity instanceof Player))
|
||||
return Transaction.fail();
|
||||
Player player = (Player) entity;
|
||||
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
|
||||
return Transaction.create(() -> {
|
||||
return true;
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerAdd(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerRemove(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction take(Entity entity) {
|
||||
if (!(entity instanceof Player))
|
||||
return Transaction.fail();
|
||||
Player player = (Player) entity;
|
||||
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
|
||||
return Transaction.create(() -> {
|
||||
for (String permission : permissions) {
|
||||
if (!perm.playerHas(player, Placeholders.replace(permission, player))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerRemove(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
}, () -> {
|
||||
for (String permission : permissions) {
|
||||
perm.playerAdd(player, Placeholders.replace(permission, player));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Menu(title = "Permissions editor", dimensions = { 3, 9 })
|
||||
public static class PermissionActionEditor extends InventoryMenuPage {
|
||||
private PermissionAction base;
|
||||
private Consumer<NPCShopAction> callback;
|
||||
|
||||
public PermissionActionEditor() {
|
||||
}
|
||||
|
||||
public PermissionActionEditor(PermissionAction base, Consumer<NPCShopAction> callback) {
|
||||
this.base = base;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(MenuContext ctx) {
|
||||
for (int i = 0; i < 3 * 9; i++) {
|
||||
final int idx = i;
|
||||
ctx.getSlot(i).clear();
|
||||
if (i < base.permissions.size()) {
|
||||
ctx.getSlot(i).setItemStack(new ItemStack(Material.FEATHER), "<f>Set permission",
|
||||
"Right click to remove\nCurrently: " + base.permissions.get(i));
|
||||
}
|
||||
ctx.getSlot(i).setClickHandler(event -> {
|
||||
if (event.isRightClick()) {
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.remove(idx);
|
||||
ctx.getSlot(idx).setItemStack(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(
|
||||
() -> idx < base.permissions.size() ? base.permissions.get(idx) : "", (res) -> {
|
||||
if (res == null) {
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.remove(idx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (idx < base.permissions.size()) {
|
||||
base.permissions.set(idx, res);
|
||||
} else {
|
||||
base.permissions.add(res);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(HumanEntity player) {
|
||||
callback.accept(base.permissions.isEmpty() ? null : base);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PermissionActionGUI implements GUI {
|
||||
private Boolean supported;
|
||||
|
||||
@Override
|
||||
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
|
||||
return new PermissionActionEditor(previous == null ? new PermissionAction() : (PermissionAction) previous,
|
||||
callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createMenuItem(NPCShopAction previous) {
|
||||
if (supported == null) {
|
||||
try {
|
||||
supported = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider() != null;
|
||||
} catch (Throwable t) {
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
if (!supported) {
|
||||
return null;
|
||||
}
|
||||
String description = null;
|
||||
if (previous != null) {
|
||||
PermissionAction old = (PermissionAction) previous;
|
||||
description = old.permissions.size() + " permissions";
|
||||
for (int i = 0; i < old.permissions.size(); i++) {
|
||||
description += "\n" + old.permissions.get(i);
|
||||
if (i == 3) {
|
||||
description += "...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Util.createItem(Util.getFallbackMaterial("OAK_SIGN", "SIGN"), "Permission", description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manages(NPCShopAction action) {
|
||||
return action instanceof PermissionAction;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import java.util.EnumSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -91,6 +92,13 @@ public class Util {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack editTitle(ItemStack item, Function<String, String> transform) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(transform.apply(meta.hasDisplayName() ? meta.getDisplayName() : ""));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void face(Entity entity, float yaw, float pitch) {
|
||||
double pitchCos = Math.cos(Math.toRadians(pitch));
|
||||
Vector vector = new Vector(Math.sin(Math.toRadians(yaw)) * -pitchCos, -Math.sin(Math.toRadians(pitch)),
|
||||
|
Loading…
Reference in New Issue
Block a user