I don't need it anymore but maybe you can post it for the others
Okay.
There are some ways of making a chest menu, But I found this one to be effective.
First things first, You need to add this line of code. You can rename It, but don't put it in any functions.
Code:
private Int2ObjectOpenHashMap<Item> chest;
Next thing is to register a function that will put the items into the chest like this
Code:
private void chestItems() {
this.chest = new Int2ObjectOpenHashMap(); //Adds the chest items to this array
int i = -1; //Starts at -1 so items don't skip the first chest slot.
Item q = Item.get(360).setCustomName("nothing");
q.addEnchantment(new Enchantment[] { Enchantment.get(0) } );
chest.put(++i, q); //Sets the item in the chest
}
Don't forget to call the function in your constructor. My class name is called game so this is what my constructor should look like.
Code:
public game() {
chestItems();
}
Now to create the chest menu
Code:
private void menu(Player player) {
UpdateBlockPacket pk = new UpdateBlockPacket();
pk.x = (int)player.x + 1;
pk.y = (int)player.y + 1;
pk.z = (int)player.z + 1;
pk.flags = 0;
pk.blockRuntimeId = GlobalBlockPalette.getOrCreateRuntimeId(54, 0);
BlockEntityDataPacket pk2 = new BlockEntityDataPacket();
pk2.x = pk.x;
pk2.y = pk.y;
pk2.z = pk.z;
try {
pk2.namedTag = NBTIO.write((new CompoundTag())
.putString("CustomName", "Cosmetics")
.putInt("x", pk.x)
.putInt("y", pk.y)
.putInt("z", pk.z)
.putString("id", "Chest"), ByteOrder.LITTLE_ENDIAN, true);
} catch (Exception exception) {}
player.dataPacket(pk);
player.dataPacket(pk2);
final holder h = new holder(new Vector3(pk.x, pk.y, pk.z));
final FI fi = new FI(h);
fi.setContents(this.chest);
player.addWindow(fi);
}
Most important part is to create an additional class for holder and Fi like this.
Code:
import cn.nukkit.inventory.Inventory;
import cn.nukkit.inventory.InventoryHolder;
import cn.nukkit.math.Vector3;
public class holder extends Vector3 implements InventoryHolder {
public holder(final Vector3 pos) {
this.x = pos.x;
this.y = pos.y;
this.z = pos.z;
}
public Inventory getInventory() {
return null;
}
}
And . . .
Code:
package --;
import cn.nukkit.inventory.CustomInventory;
import cn.nukkit.inventory.InventoryType;
public class FI extends CustomInventory {
public FI(holder holder) {
super(holder, InventoryType.CHEST);
}
}
Now the last part is to interact with the item in the menu. There's many ways to do this. By creating the event InventoryTransactionEvent you can do what you can do. But below is code examples for everyone.
//Setting the items in the chest to cancelled so the items can't be taken out of chest.
Code:
@EventHandler
public void onChest(InventoryTransactionEvent e) {
Player pl = e.getTransaction().getSource();
if (!(pl.getLevel() == Server.getInstance().getDefaultLevel())) {
return;
}
for (final InventoryAction action : e.getTransaction().getActions()) {
if (this.interact(action.getSourceItem().getId(), e.getTransaction().getSource(), e.getTransaction().getInventories()) || this.interact(action.getTargetItem().getId(), e.getTransaction().getSource(), e.getTransaction().getInventories())) {
e.setCancelled();
return;
}
}
e.setCancelled();
}
Creating a Boolean function to allow code to run when the item is clicked in the chest menu
Code:
private boolean interact(int id, Player player, Set<Inventory> inv) {
switch (id) {
case 360: {
player.sendMessage("test");
}
}
return false;
}
That should be it.
If I missed anything or anyone has questions let me know.