Skip to content

Commit

Permalink
Additional Inventory API
Browse files Browse the repository at this point in the history
  • Loading branch information
fullwall committed May 7, 2021
1 parent ee340c9 commit 20b7cf8
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 67 deletions.
146 changes: 79 additions & 67 deletions src/main/java/net/citizensnpcs/api/gui/InventoryMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
Expand Down Expand Up @@ -62,6 +63,7 @@
*/
public class InventoryMenu implements Listener, Runnable {
private final List<Runnable> closeCallbacks = Lists.newArrayList();
private boolean manualClose;
private PageContext page;
private int pickupAmount = -1;
private final Queue<PageContext> stack = Queues.newArrayDeque();
Expand Down Expand Up @@ -93,22 +95,29 @@ private void addCloseCallback(Runnable run) {
*/
public void close() {
HandlerList.unregisterAll(this);
manualClose = true;
for (InventoryView view : views) {
page.page.onClose(view.getPlayer());
view.close();
}
views.clear();
manualClose = false;
}

/**
* Closes the GUI for just a specific Player.
*/
public void close(Player player) {
for (InventoryView view : views) {
Iterator<InventoryView> itr = views.iterator();
manualClose = true;
while (itr.hasNext()) {
InventoryView view = itr.next();
if (view.getPlayer() == player) {
page.page.onClose(player);
view.close();
itr.remove();
}
}
manualClose = false;
}

private InventoryMenuSlot createSlot(int pos, MenuSlot slotInfo) {
Expand Down Expand Up @@ -186,19 +195,55 @@ private int getInventorySize(InventoryType type, int[] dim) {
}
}

public void transitionBack() {
if (page == null)
return;
Map<String, Object> data = page.ctx.data();
page = stack.poll();
if (page != null) {
page.ctx.data().putAll(data);
}
data.clear();
transitionViewersToInventory(page == null ? null : page.ctx.getInventory());
if (page == null) {
for (Runnable callback : closeCallbacks) {
callback.run();
private void handleShiftClick(InventoryClickEvent event, Inventory dest, boolean toNPC) {
int amount = event.getCurrentItem().getAmount();
ItemStack merging = new ItemStack(event.getCurrentItem().clone());
ItemStack[] contents = dest.getContents();
for (int i = 0; i < contents.length; i++) {
if (contents[i] == null || contents[i].getType() == Material.AIR) {
merging.setAmount(amount);
if (toNPC) {
event.getView().setCursor(merging);
}
InventoryClickEvent e = new InventoryClickEvent(event.getView(), event.getSlotType(),
toNPC ? i : event.getRawSlot(), event.getClick(),
toNPC ? InventoryAction.PLACE_ALL : InventoryAction.PICKUP_ALL);
onInventoryClick(e);
if (toNPC) {
event.getView().setCursor(null);
}
if (!e.isCancelled() && e.getResult() != Result.DENY) {
dest.setItem(i, merging);
event.setCurrentItem(null);
break;
}
} else if (contents[i].getType() == event.getCurrentItem().getType()) {
ItemStack stack = contents[i].clone();
merging.setAmount(Math.min(amount, stack.getType().getMaxStackSize() - stack.getAmount()));
InventoryAction action;
if (toNPC) {
event.getView().setCursor(merging);
action = amount - merging.getAmount() <= 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_SOME;
} else {
action = amount - merging.getAmount() <= 0 ? InventoryAction.PICKUP_ALL
: InventoryAction.PICKUP_SOME;
pickupAmount = merging.getAmount();
}
InventoryClickEvent e = new InventoryClickEvent(event.getView(), event.getSlotType(),
toNPC ? i : event.getRawSlot(), event.getClick(), action);
onInventoryClick(e);
if (toNPC) {
event.getView().setCursor(null);
}
if (!e.isCancelled() && e.getResult() != Result.DENY) {
stack.setAmount(stack.getAmount() + merging.getAmount());
dest.setItem(i, stack);
amount -= merging.getAmount();
event.getCurrentItem().setAmount(amount);
if (amount <= 0) {
break;
}
}
}
}
}
Expand All @@ -215,57 +260,7 @@ public void onInventoryClick(InventoryClickEvent event) {
: event.getInventory();
boolean toNPC = dest == page.ctx.getInventory();
if ((event.getCursor() == null || event.getCursor().getType() == Material.AIR)) {
int amount = event.getCurrentItem().getAmount();
ItemStack merging = new ItemStack(event.getCurrentItem().clone());
ItemStack[] contents = dest.getContents();
for (int i = 0; i < contents.length; i++) {
if (contents[i] == null || contents[i].getType() == Material.AIR) {
merging.setAmount(amount);
if (toNPC) {
event.getView().setCursor(merging);
}
InventoryClickEvent e = new InventoryClickEvent(event.getView(), event.getSlotType(),
toNPC ? i : event.getRawSlot(), event.getClick(),
toNPC ? InventoryAction.PLACE_ALL : InventoryAction.PICKUP_ALL);
onInventoryClick(e);
if (toNPC) {
event.getView().setCursor(null);
}
if (!e.isCancelled() && e.getResult() != Result.DENY) {
dest.setItem(i, merging);
event.setCurrentItem(null);
break;
}
} else if (contents[i].getType() == event.getCurrentItem().getType()) {
ItemStack stack = contents[i].clone();
merging.setAmount(Math.min(amount, stack.getType().getMaxStackSize() - stack.getAmount()));
InventoryAction action;
if (toNPC) {
event.getView().setCursor(merging);
action = amount - merging.getAmount() <= 0 ? InventoryAction.PLACE_ALL
: InventoryAction.PLACE_SOME;
} else {
action = amount - merging.getAmount() <= 0 ? InventoryAction.PICKUP_ALL
: InventoryAction.PICKUP_SOME;
pickupAmount = merging.getAmount();
}
InventoryClickEvent e = new InventoryClickEvent(event.getView(), event.getSlotType(),
toNPC ? i : event.getRawSlot(), event.getClick(), action);
onInventoryClick(e);
if (toNPC) {
event.getView().setCursor(null);
}
if (!e.isCancelled() && e.getResult() != Result.DENY) {
stack.setAmount(stack.getAmount() + merging.getAmount());
dest.setItem(i, stack);
amount -= merging.getAmount();
event.getCurrentItem().setAmount(amount);
if (amount <= 0) {
break;
}
}
}
}
handleShiftClick(event, dest, toNPC);
return;
}
}
Expand Down Expand Up @@ -318,7 +313,7 @@ public void onInventoryClick(InventoryClickEvent event) {

@EventHandler(ignoreCancelled = true)
public void onInventoryClose(InventoryCloseEvent event) {
if (page == null || !event.getInventory().equals(page.ctx.getInventory()))
if (page == null || !event.getInventory().equals(page.ctx.getInventory()) || manualClose)
return;
page.page.onClose(event.getPlayer());
transitionBack();
Expand Down Expand Up @@ -490,6 +485,23 @@ public void transition(InventoryMenuPage instance, Map<String, Object> context)
transition(info, instance, context);
}

public void transitionBack() {
if (page == null)
return;
Map<String, Object> data = page.ctx.data();
page = stack.poll();
if (page != null) {
page.ctx.data().putAll(data);
}
data.clear();
transitionViewersToInventory(page == null ? null : page.ctx.getInventory());
if (page == null) {
for (Runnable callback : closeCallbacks) {
callback.run();
}
}
}

private void transitionViewersToInventory(Inventory inventory) {
Collection<InventoryView> old = views;
views = Lists.newArrayListWithExpectedSize(old.size());
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/net/citizensnpcs/api/gui/InventoryMenuSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ void onClick(CitizensInventoryClickEvent event) {
}
}

public void setDescription(String description) {
ItemStack item = inventory.getItem(index);
ItemMeta meta = item.getItemMeta();
meta.setLore(Arrays.asList(Colorizer.parseColors(description).split("\n")));
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
item.setItemMeta(meta);
inventory.setItem(index, item);
}

/**
* Sets a new {@link ClickType} filter that will only accept clicks with the given type. An empty set is equivalent
* to allowing all click types.
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/net/citizensnpcs/api/gui/ModalMenuInput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.citizensnpcs.api.gui;

import java.util.function.Consumer;

import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.conversations.Prompt;
import org.bukkit.conversations.StringPrompt;
import org.bukkit.entity.Player;

import net.citizensnpcs.api.CitizensAPI;

public class ModalMenuInput {
private ModalMenuInput() {
}

public static void captureInput(Player player, InventoryMenu menu, Consumer<String> input) {
menu.close(player);
player.beginConversation(
new ConversationFactory(CitizensAPI.getPlugin()).addConversationAbandonedListener((evt) -> {
menu.present(player);
}).withLocalEcho(false).withEscapeSequence("exit").withModality(false).withTimeout(60)
.withFirstPrompt(new StringPrompt() {
@Override
public Prompt acceptInput(ConversationContext ctx, String text) {
input.accept(text);
menu.present(player);
return null;
}

@Override
public String getPromptText(ConversationContext ctx) {
return "";
}
}).buildConversation(player));
}
}

0 comments on commit 20b7cf8

Please sign in to comment.