minuskube / smartinvs Goto Github PK
View Code? Open in Web Editor NEWAdvanced Inventory API for your Minecraft Bukkit plugins.
Home Page: https://minuskube.gitbook.io/smartinvs/
License: Apache License 2.0
Advanced Inventory API for your Minecraft Bukkit plugins.
Home Page: https://minuskube.gitbook.io/smartinvs/
License: Apache License 2.0
The start and the end slots of the inventory are added with the SlotIterator even if they are blacklisted or if they are not empty and the "no override mode" is enabled.
It would be nice to allow to use ClickableItems outside of GUIs, inside of the player inventory and in the hotbar with right click, this would add some benefits to the API.
By using the shortcut number keys, it seems you can manage to move the items outside of a SmartInvs inventory.
When you use the same SmartInventory for different players, the page system will be common to all the players and it will be broken.
After the small discussion in #20, I think we should add a way to clone a ClickableItem with a new ItemStack, so we can keep the same Consumer, but with a different ItemStack, maybe the ClickableItem's ItemStack should also be immutable so we have to clone the ClickableItem in order to change the ItemStack.
Example code:
contents.get(0, 0).ifPresent(item -> {
ClickableItem newItem = item.clone(new ItemStack(Material.DIRT));
contents.set(0, 0, newItem);
}
Add some methods to remove items from the inventory, with different methods for:
#removeFirst(item)
)#removeAmount(item, amount)
)#removeAll(item)
)These methods would all ask an ItemStack
and would ignore the amount
property of the given ItemStack to avoid confusions.
We can also make overload of these methods with ClickableItem
s instead of ItemStack
s, but it's maybe not worth it.
Since I didn't find anything in the documentation, I'll open a ticket here.
Could you explain to me how to add a listener? I need to execute some code once a SmartInventory was closed. I know the builder has a listener method, but I don't understand how to use it properly.
A small example would be really helpful.
What I'm trying to do:
The player opens the GUI -> ItemStack from his main hand goes to slot 0 in the GUI -> When the player closes the GUI it should be returned to their main hand. But I don't get how to use the listener method inside the builder.
Thanks for implementing my feature requests so incredible fast, thats awesome!
The allowOverride method from last commit does not work properly. It does still override already existing (the fillBorder items) items inside the inventory.
`
private static final ItemStack fill = new ItemBuilder(Material.STAINED_GLASS_PANE).durability(15).name(" ").build();
@Override
public void init(Player player, InventoryContents contents) {
contents.fillBorders(ClickableItem.empty(fill));
Pagination pagination = contents.pagination();
ArrayList<ClickableItem> items = new ArrayList<ClickableItem>();
for (int i = 0; i < 20; i++) {
ItemStack item = new ItemBuilder(Material.PAPER).name("§fDebug" + i).build();
items.add(ClickableItem.of(item, e -> {
UtilPlayer.playSound(player, Sound.BLOCK_LEVER_CLICK);
player.sendMessage("Just a debug code");
}));
}
contents.set(4, 6, ClickableItem.of(new ItemBuilder(Material.MAP).name("Next page").build(), e -> {
contents.inventory().open(player, pagination.next().getPage());
}));
contents.set(4, 2, ClickableItem.of(new ItemBuilder(Material.MAP).name("Previous page").build(), e -> {
contents.inventory().open(player, pagination.previous().getPage());
}));
ClickableItem[] c = new ClickableItem[items.size()];
c = items.toArray(c);
pagination.setItems(c);
pagination.setItemsPerPage(18);
SlotIterator slotIterator = contents.newIterator(Type.HORIZONTAL, 1, 0);
slotIterator = slotIterator.allowOverride(false);
pagination.addToIterator(slotIterator);
}
`
Is there anything I'm doing wrong? The border shouldn't be filled with the override setting but it doesn't seem to work.
This is kinda a critical bug, since it totally breaks the whole api/plugin.
I have a static variable of the SmartInventory:
public static final SmartInventory REGION_HOME = SmartInventory.builder().id("regiongui.home") .provider(new LandHomeMenu()) .size(6, 9) .title(Language.INTERFACE_HOME_TITLE.toString()) .build();
InventoryProvider for the REGION_HOME: https://pastebin.com/ihtNr7He
I'm using REGION_HOME.open(player) -> Each player should see their own instance/inventory.
But:
Player 1 opens their home gui -> Works
If player2 opens their home gui while player1 has still the inventory open -> Player 1 sees the content from player2 and has all ClickableItems from player2.
Same for more than 2 players.
Video: https://www.youtube.com/watch?v=0-_J4GE8oxw
All players will only see the contents from the last opened inventory, that makes it impossible to add per-player icons/text or whatever to the ClickableItems
I guess that relates to: #35
Since this is a kinda critical bug, I hope that it's fixed as soon as possible, because I'm using this in more than 40+ private and public plugins.
There is currently no official way to replace the existing Inventory Openers. I think we should add a kind of priority system, and the manager would take the opener which supports the inventory type which has the highest priority.
No way to close inventory on Inventory GUI Provider
So I was few versions behind (1.1.3) and I have updated and added the new InventoryManager, however I still can't get it to work.
The GUI loads fine and doesn't override the borders (thanks for that) but there is no response from the icons or the pagination prev, next.
I guess I am missing something obvious and need it spelt out for me -_-.
I had added a .gif below and a snippet of code (just basic pagination).
https://i.gyazo.com/3fab7832db51e9c1b745fd3c70e9be20.gif
https://pastebin.com/ehXMFUyM
Thanks!
We should add a way to get and set items using the slot number instead of using the row and column, that would be especially be useful when using loops.
This could be done by modifying the SlotPos
to add a static fromIndex
method.
Hello there,
Can SmartInventory add custom content?
For example: InventoryContents.setProperty (k, v);
public static final SmartInventory inv_task = SmartInventory.builder()
.id("Task_task")
.title("§9task")
.size(4, 9)
.provider(new Inv_Task())
.build();
class Inv_Task implements InventoryProvider {
public void init(Player p, InvetoryContents inv) {
System.out.print(inv.get(k));
}
public void onChat(AsyncPlayerChatEvent evt) {
inv_task.setProperty(k,v);
}
found
Hello, I had a big problem with Inventory per player, when I updating a inventory and somebody open the inventory on same time. He sees same contents as I.
Can you repair this thing, please ?
Currently I am working on a market system and I tried to to something likes this: You do something to open a inventory. In this inventory you can select the amount of money you want for the items. On ther other side you can put the items in. Problem is: I can't put stuff in, event when I use this:
ClickableItem.of(STACK, event -> event.setCancelled(false));
It just wouldn't work, so I decided to have a look into the event handling and got the idea to override the result of the event manually in one of my listener classes. Everything seemed fine when its about detecting the correct slots. BUT If I tried to put/take Items out of that area the just bugged out and graphical glitches were all over the place. So would it be possible to change some stuff to make it possible to go around this piece of code?
if (e.getAction() == InventoryAction.COLLECT_TO_CURSOR
|| e.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY
|| e.getAction() == InventoryAction.NOTHING) {
e.setCancelled(true);
return;
}
(Its from InventoryManager.InvListener the method onInventoryClick() )
When I click something, it doesn't respond. (even though I have an action assigned)
Seems when I click next, close the inventory, and reopen, it shows the next page.
Used the latest version of SmartInvs on the repository (manually built)
Using Spigot b1638 for 1.12.2
It would be nice to have a method that adds a item to the next free slot of the InventoryContents
something like addItem(ClickableItem item) - Adds the clickable item to the next free slot in the inventory.
I've hit a few limitations of your API that I feel should be adjusted to enhance usability and customization of title in menus.
Add ability to set menu title in the same line you open the menu for the player instead of being forced to set it inside the builder method in the menu with limits customization.
what I'm proposing is instead of lets say
SettingsMenu.INVENTORY.open(player)
to open the inventory for player with a set title that cannot have input from player in the title to
SettingsMenu.INVENTORY.open(player, "Settings of "+player.getName())
that way you can have more expand-ability in the menu title department cause it's severely lacking. Cause this is not possible in your current API without making a map and setting to before you open menu, and it runs into some weird issues I'm not sure if menu titles are cached or something but it refused to change once initially set even though variable was clearly changing.
It would be nice to allow to use SmartInvs without having to use it as a plugin.
Since the 1.7 version doesn't have the Apache Commons Lang3 library, a ClassNotFoundException is generated when using SlotPos which use this library for the equals and hashCode methods.
Hello MinusKube!
I'm now using your inventory API, but I got an error by opening GUI.
I use it as a library so I have initialised it in my main class (Core).
This is the error:
https://hastebin.com/jepimamapo.apache
This is my Core class:
https://hastebin.com/hehujipile.java
And I'm using the exact same class on your tutorial SimpleInventory.
I hope you could help me!
Regards,
Rndstad
Do you know how to change the 'closeable' to true, I had set it to false but when a player press on the green or red wool block I want to set the closeable boolean to true to close the inventory from the player.
It would be nice to have a pattern system, where we can define patterns using Strings, with already predefined patterns in SmartInvs (like crosses, ...), the patterns will be defined like that :
Pattern<ClickableItem> pattern = new Pattern<>(
"XOOOOOOOX",
"XOOOXOOOX",
"XOOOOOOOX"
);
Then we can attach items to each character, or just put nothing so they are ignored :
pattern.attach('X', ClickableItem.of(...));
Then we can fill an inventory using this pattern: contents.fillPattern(pattern)
, or with a pattern smaller than the inventory size and a position: contents.fillPattern(pattern, row, column)
.
But then, we could use these patterns for telling the SlotIterator which slots can be used or not, so it would be the same thing, but with booleans:
Pattern<Boolean> pattern = new Pattern<>(
"XXXXOXXXX",
"XXXOOOXXX",
"XXXXOXXXX"
);
pattern.attach('X', true);
iterator.withPattern(pattern);
// or iterator.withPattern(pattern, row, column)
// or iterator.blacklistPattern(pattern)
// or iterator.blacklistPattern(pattern, row, column)
(by default everything would be false)
Caused by: java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;I)V
at fr.minuskube.inv.opener.ChestInventoryOpener.open(ChestInventoryOpener.java:15) ~[?:?]
at fr.minuskube.inv.SmartInventory.open(SmartInventory.java:56) ~[?:?]
at fr.minuskube.inv.SmartInventory.open(SmartInventory.java:35) ~[?:?]
I tried shading Guava, and everything I could.
But I am still getting this error.
I hope the next version can enhance the players under the inventory of interactive
When I want to use this API to create a warehouse for players to store items
I can not start
Should be given developer close event and Cancelled processing
This is by far the best inventory api I've worked with, but I have already another feature request.
A feature, like a boolean when creating a pagination to disable overriding existing items in the menu.
So the pagination inserts the item on the next free slot.
Example:
Create a border with fillBorders -> Create a pagination -> The pagination will override the borders
But I miss a way to fill the items inside the borders.
So in this example, it should only fill the slots inside the red area, but it replaced the black stained class that previously was set as a border.
A method like:
pagination.setOverride(false/true) would be great to ignore already existing items and place the item to the next free slot.
Method to get position of item in inventory example:
getPositionOfItem(clickableitem or ItemStack); >> returns SlotPos: row and index
The InventoryOpener#open method should throw an exception when it tries to open an inventory with the wrong size. To avoid getting weird bugs.
Example when you open a 9 rows and 1 column chest inventory, it shows 1 row and 9 columns, and only the first slot can be filled because of the rows/columns checks.
When we double-click on an item in an inventory, the ClickableItem's consumer is called three times instead of two.
I currently stuck with a problem using the update method from the InventoryProvider.
I have a cooldown running on my kits that are displayed inside the GUI, now I want a visual countdown, but somehow I didn't figure out how to update the lore or ItemMeta in general for a ClickableItem without replacing it completely.
Is there some way to update the ItemMeta for a specific slot without replacing the item completely?
That's what I've tried so far:
@Override
public void update(Player player, InventoryContents contents) {
int state = contents.property("state", 0);
contents.setProperty("state", state + 1);
if(state % 10 != 0)
return;
CorePlayer cp = Core.getPlugin().getCorePlayer(player);
contents.get(1, 2).ifPresent(item -> {
Optional<Kit> kit = addon.getKit(item.getItem().getItemMeta().getDisplayName());
if (!kit.isPresent()) {
return;
}
ItemStack i = item.getItem();
ItemMeta meta = i.getItemMeta();
List<String> lore = meta.getLore();
if (lore.size() > 0 && lore.get(0) != null && lore.get(0).startsWith("§7Cooldown")) {
lore.set(0, "§7Cooldown: " + UtilTime.convertString(cp.getRemaingKitTime(kit.get().getName()), 2, net.crytec.api.util.UtilTime.TimeUnit.FIT));
meta.setLore(lore);
i.setItemMeta(meta);
System.out.println("Lore Updated");
}
});
}
The debug messages shows up, also the ItemMeta inside the Clickable Item does get changed, but it's not updating in the inventory view
04.02 20:16:48 [Server] ERROR Error occurred while enabling networkreportgui v1.0 (Is it up to date?)
04.02 20:16:48 [Server] INFO java.lang.StackOverflowError: null
04.02 20:16:48 [Server] INFO at fr.minuskube.inv.SmartInventory$Builder.<init>(SmartInventory.java:94) ~[?:?]
04.02 20:16:48 [Server] INFO at fr.minuskube.inv.SmartInventory.builder(SmartInventory.java:92) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:21) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
04.02 20:16:48 [Server] INFO at me.rndstad.networkreportgui.report.menus.ReportReasonInventory.<init>(ReportReasonInventory.java:22) ~[?:?]
The pagination system goes one page too far when the item count is a multiple of the amount of items per page.
And another feature request for that lovely lib:
For some advanced inventories it would be awesome to open inventory with already defined properties in the open() method, so we can call the .property(String) method during the init method of the InventoryProvider.
So a new method inside the SmartInventory class, something like
open(Player player, int page, String[] property, Object[] value) that puts keys + objects to the properties map, so we are able to directly use these objects during the init method.
I've added this a way back myself via this code, but an official implementation would be awesome!
`
public Inventory open(Player player, String[] property, Object[] value) {
InventoryManager manager = SmartInvsPlugin.manager();
Optional<SmartInventory> oldInv = manager.getInventory(player);
oldInv.ifPresent(inv -> {
inv.getListeners().stream().filter(listener -> listener.getType() == InventoryCloseEvent.class).forEach(listener -> ((InventoryListener<InventoryCloseEvent>) listener).accept(new InventoryCloseEvent(player.getOpenInventory())));
manager.setInventory(player, null);
});
InventoryContents contents = new InventoryContents.Impl(this);
contents.pagination().page(0);
manager.setContents(player, contents);
if (property.length != value.length) {
throw new IllegalStateException("property does not have a assinged object value. Cannot open inventory.");
}
for (int i = 0; i < property.length; i++) {
contents.setProperty(property[i], value[i]);
}
provider.init(player, contents);
InventoryOpener opener = manager.findOpener(type).orElseThrow(() -> new IllegalStateException("No opener found for the inventory type " + type.name()));
Inventory handle = opener.open(this, player);
manager.setInventory(player, this);
return handle;
}
public Inventory open(Player player, int page, String[] property, Object[] value) {
InventoryManager manager = SmartInvsPlugin.manager();
Optional<SmartInventory> oldInv = manager.getInventory(player);
oldInv.ifPresent(inv -> {
inv.getListeners().stream().filter(listener -> listener.getType() == InventoryCloseEvent.class).forEach(listener -> ((InventoryListener<InventoryCloseEvent>) listener).accept(new InventoryCloseEvent(player.getOpenInventory())));
manager.setInventory(player, null);
});
InventoryContents contents = new InventoryContents.Impl(this);
contents.pagination().page(page);
manager.setContents(player, contents);
if (property.length != value.length) {
throw new IllegalStateException("property does not have a assinged object value. Cannot open inventory.");
}
for (int i = 0; i < property.length; i++) {
contents.setProperty(property[i], value[i]);
}
provider.init(player, contents);
InventoryOpener opener = manager.findOpener(type).orElseThrow(() -> new IllegalStateException("No opener found for the inventory type " + type.name()));
Inventory handle = opener.open(this, player);
manager.setInventory(player, this);
return handle;
}
`
The title says it all, just some unit testing for the API.
I am creating a towny GUI and I would love a way to open the last inventory they had open on the default command to open the towny GUI
I run command
GUIManager.mainGUI.open(p);
when user uses specific command.
Once first player execute this command, it will open GUI for him. Inside this GUI I have item and its name is set to:
System.currentTimeMillis()
.
For example, its number 98465984654.
When another player execute command so it opens menu for him (while first one still have his one opened),
new player can see inventory also but first players GUI gets updated (init function is once again ran so he no longer see number 98465984654, he now see new value so for example 98465988654.
Code snippet: https://pastebin.com/DrQDiAsZ
when I use: e.getClick() == ClickType.SHIFT_LEFT nothing happens..
Hey! So many modpacks have a mod called MouseTweaks which allows you to use shortcuts to transfer items around inventories.
In this mod, you can hold space and click to transfer a whole inventory into another inventory (e.g. A chest into an inventory). In 1.12 Sponge, the clickable GUIs you make are not affected by this and 'space clicking' doesn't take the inventory.
However in Spigot/Bukkit/Thermos (Using 1.7.10), when I 'space click' the inventory, all of the items are moved from the GUI into the inventory and are still there after closing. I have even tested relogging or dying and the items still persist.
Thank you!
Ally.
Suggestion for the upcoming 1.3 version:
Add a optional constructor to ClickableItem that accepts two Strings. A permission to view the clickable Item and a permission to click the clickable item. What these permissions do is basically self-explanatory.
Don't show the item if the player is missing the required permission and don't let the player click the item if its missing.
This makes it easier to handle the content and reduces the init method alot.
Hello, i have this error when remove last item in inventory:
[SmartInvs] Task #6 for SmartInvs v1.2.4 generated an exception
java.util.ConcurrentModificationException
at java.base/java.util.HashMap.forEach(Unknown Source) ~[?:?]
at fr.minuskube.inv.InventoryManager$InvTask.run(InventoryManager.java:244) ~[?:?]
at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:71) ~[spigot.jar:git-Spigot-c3c767f-33d5de3]
at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:350) [spigot.jar:git-Spigot-c3c767f-33d5de3]
at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:709) [spigot.jar:git-Spigot-c3c767f-33d5de3]
at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:316) [spigot.jar:git-Spigot-c3c767f-33d5de3]
at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:634) [spigot.jar:git-Spigot-c3c767f-33d5de3]
at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:537) [spigot.jar:git-Spigot-c3c767f-33d5de3]
It only happens when you only have one item in inventory and it is removed
The SlotIterator's started() method returns false after a previous()
when the start position is 0/0, or after a next()
when the start position is at the end, example code:
SlotIterator iterator = contents.newIterator(SlotIterator.Type.HORIZONTAL, 0, 0);
iterator.previous();
System.out.println(iterator.started());
Inventories are for all players.
For example: One player opens the inventory, then another opens the same inventory, the second player controls the forward and backward pages of all players
So:
SmartInv.open (player, pagination) not working
Only works if I do a HashMap <Player, SmartInventory>
It would be nice to have a method to make that
This project is missing some javadoc...
When using the constructor of the InventoryManager: new InventoryManager(this)
in the onEnable()
method of my plugin. I get a NoClassDefFoundError.
I'm using PaperSpigot build #773 for 1.9.4. I already contacted the Paper support team and they do not know what is going on. Other plugins work fine too, only my plugin with SmartInvs produces this error.
Edit: The same error occurs when using the SmartInvs standalone plugin.
When we open a new inventory in 1.7, the mouse resets to the center of the screen, this is due to the 1.7, but there is a possible workaround if we replace the current inventory contents instead of opening a new one.
It would be nice to allow to set the end slot position of the SlotIterator, by default it would still be the last slot of the inventory, but the end position would be settable using a method like endPosition(row, column)
/endPosition(SlotPos)
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.