Adds UI to create/manage/invite players to parties.
Includes an Anvil UI library from WesJD.
This commit is contained in:
James Peters 2020-10-21 23:44:47 +01:00
parent 3a0c0e23c1
commit 1c153db2e3
21 changed files with 908 additions and 173 deletions

View File

@ -40,6 +40,11 @@
<id>sytm-nexus</id>
<url>https://repo.sytm.de/repository/maven-hosted/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
@ -75,6 +80,12 @@
<version>1.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.WesJD.AnvilGUI</groupId>
<artifactId>anvilgui</artifactId>
<version>f227dcbf2f</version>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
@ -127,6 +138,7 @@
<artifactSet>
<includes>
<include>fr.minuskube.inv*:*</include>
<include>com.github.WesJD.AnvilGUI*:*</include>
<include>org.bstats*:*</include>
<include>com.jamesdpeters.minecraft.chests</include>
</includes>
@ -141,6 +153,10 @@
<pattern>fr.minuskube.inv</pattern>
<shadedPattern>com.jamesdpeters.minecraft.chests</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.WesJD.AnvilGUI</pattern>
<shadedPattern>com.jamesdpeters.minecraft.chests</shadedPattern>
</relocation>
</relocations>
</configuration>

View File

@ -30,7 +30,6 @@ import fr.minuskube.inv.InventoryManager;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.java.JavaPlugin;

View File

@ -1,7 +1,7 @@
package com.jamesdpeters.minecraft.chests.commands;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.inventories.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.menus.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.lang.Message;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Permissions;

View File

@ -2,14 +2,13 @@ package com.jamesdpeters.minecraft.chests.commands;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.api.ApiSpecific;
import com.jamesdpeters.minecraft.chests.inventories.PartyMenu;
import com.jamesdpeters.minecraft.chests.menus.PartyMenu;
import com.jamesdpeters.minecraft.chests.lang.Message;
import com.jamesdpeters.minecraft.chests.maventemplates.BuildConstants;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.party.PartyUtils;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
@ -25,7 +24,6 @@ public class ChestsPlusPlusCommand extends ServerCommand {
private enum OPTIONS {
VERSION("/chestsplusplus version", "Display the current version of the plugin."),
PARTY("/chestsplusplus party <create/delete/invite/remove-member/list>", "Create, delete or manage members of your party"),
PARTY_MENU("/chestsplusplus party <create/delete/invite/remove-member/list>", "Create, delete or manage members of your party"),
RELOAD("/chestsplusplus reload", "Reloads the plugin.");
String description, commandHelp;
@ -72,71 +70,34 @@ public class ChestsPlusPlusCommand extends ServerCommand {
ChestsPlusPlus.PLUGIN.onEnable();
return true;
case PARTY_MENU:
PartyMenu.getMenu(player).getMenu().open(player);
return true;
case PARTY:
if (args.length > 1) {
if (sender.hasPermission(Permissions.PARTY_ACCEPT_INVITE)) {
if (args[1].toLowerCase().equals("accept-invite")) {
PartyUtils.acceptInvite(player);
return true;
}
} else {
Messages.NO_PERMISSION(player);
return true;
}
if (args[1].toLowerCase().equals("list")) {
// TODO Print list of owned parties.
return true;
}
}
if (args.length > 2) {
if(sender.hasPermission(Permissions.PARTY_CREATE)){
if (args[1].toLowerCase().equals("create")){
String partyName = args[2];
boolean result = PartyUtils.createParty(player, partyName);
if (result){
sender.sendMessage(ChatColor.GREEN+Message.PARTY_CREATED.getString(ChatColor.WHITE+partyName+ChatColor.GREEN));
} else {
sender.sendMessage(ChatColor.RED+Message.PARTY_ALREADY_EXISTS.getString(ChatColor.WHITE+partyName+ChatColor.RED));
}
return true;
}
if (args[1].toLowerCase().equals("delete")){
String partyName = args[2];
boolean result = PartyUtils.deleteParty(player, partyName);
if (result){
sender.sendMessage(ChatColor.GREEN+Message.PARTY_DELETED.getString(ChatColor.WHITE+partyName+ChatColor.GREEN));
} else {
sender.sendMessage(ChatColor.RED+Message.PARTY_DOESNT_EXIST.getString(ChatColor.WHITE+partyName+ChatColor.RED));
}
return true;
}
} else {
Messages.NO_PERMISSION(player);
return true;
}
if (args.length > 3) {
if (sender.hasPermission(Permissions.PARTY_INVITE)) {
if (args[1].toLowerCase().equals("invite")) {
String partyName = args[2];
String playerToInvite = args[3];
PartyUtils.invitePlayer(player, Bukkit.getOfflinePlayer(playerToInvite), partyName);
return true;
}
} else {
Messages.NO_PERMISSION(player);
return true;
}
if (args[1].toLowerCase().equals("remove-member")) {
String partyName = args[2];
String playerToInvite = args[3];
PartyUtils.removePlayer(player, Bukkit.getOfflinePlayer(playerToInvite), partyName);
return true;
}
switch (args[1].toLowerCase()) {
case "menu":
PartyMenu.getMenu(player).getMenu().open(player);
break;
case "create":
PartyMenu.getMenu(player).create(player);
break;
case "invite":
PartyMenu.getMenu(player).invite(player);
break;
case "remove-member":
PartyMenu.getMenu(player).removePlayer(player);
break;
case "list":
PartyMenu.getMenu(player).listParties(player);
break;
case "delete":
PartyMenu.getMenu(player).deleteParty(player);
break;
case "view-invites":
PartyMenu.getMenu(player).partyInvites(player);
break;
default:
return false;
}
return true;
}
default:
@ -161,7 +122,7 @@ public class ChestsPlusPlusCommand extends ServerCommand {
try {
switch (OPTIONS.valueOf(args[0].toUpperCase())) {
case PARTY:
return Stream.of("create", "invite", "delete", "remove-member", "accept-invite", "list").filter(s -> s.contains(args[1])).collect(Collectors.toList());
return Stream.of("menu", "create", "invite", "delete", "remove-member", "view-invites", "list").filter(s -> s.contains(args[1])).collect(Collectors.toList());
}
} catch (IllegalArgumentException ignored) {
}

View File

@ -1,73 +0,0 @@
package com.jamesdpeters.minecraft.chests.inventories;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import fr.minuskube.inv.content.Pagination;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
public class PartyMenu implements InventoryProvider {
public static HashMap<Player, PartyMenu> menus;
private final SmartInventory menu;
private ClickableItem CREATE = ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.ANVIL), "Create a Party"), itemClickData -> {itemClickData.getPlayer().sendMessage("CREATE");});
private ClickableItem INVITE = ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.WRITABLE_BOOK), "Invite a Player to a Party"), itemClickData -> {itemClickData.getPlayer().sendMessage("INVITE");});
private ClickableItem REMOVE_PLAYER = ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.SKELETON_SKULL), "Remove a Player from a Party"), itemClickData -> {itemClickData.getPlayer().sendMessage("INVITE");});
private ClickableItem LIST = ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.MAP), "List all your parties"), itemClickData -> {itemClickData.getPlayer().sendMessage("LIST");});
private ClickableItem DELETE = ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.BARRIER), "Delete a Party"), itemClickData -> {itemClickData.getPlayer().sendMessage("DELETE");});
private List<ClickableItem> itemList = Arrays.asList(CREATE, INVITE, LIST, DELETE);
private PartyMenu() {
menu = SmartInventory.builder()
.id("partyMenu")
.title("Party Menu")
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(3, 9)
.build();
//menu.setInsertable(true);
}
public static PartyMenu getMenu(Player player) {
if (menus == null) menus = new HashMap<>();
if (!menus.containsKey(player)) {
menus.put(player, new PartyMenu());
}
return menus.get(player);
}
@Override
public void init(Player player, InventoryContents contents) {
contents.fillBorders(ClickableItem.empty(Utils.getNamedItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " ")));
for (ClickableItem item : itemList) {
contents.add(item);
}
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
return menu;
}
}

View File

@ -81,7 +81,7 @@ public enum Message {
PARTY_INVITE_OWNER("You have invited {0} to join your party: {1}", Tag.PLAYER_NAME, Tag.PARTY_NAME),
PARTY_JOINED("You have joined {0}''s party: {1}", Tag.PLAYER_NAME, Tag.PARTY_NAME),
PARTY_NO_INVITE("You currently have no pending party invites!"),
PARTY_ACCEPT_INVITE("Use "+ ChatColor.GREEN+ChatColor.BOLD+"/chestsplusplus party accept-invite"+ChatColor.RESET+" or "+ ChatColor.GREEN+ChatColor.BOLD+"'/c++ party accept-invite'"+ChatColor.RESET+" to accept the invite!");
PARTY_ACCEPT_INVITE("Click Here to accept the invite!");
String message;

View File

@ -0,0 +1,76 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.lang.Message;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.party.PartyUtils;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.ItemClickData;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import net.wesjd.anvilgui.AnvilGUI;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
public class AcceptDialogMenu implements InventoryProvider {
private final SmartInventory menu;
private Consumer<Boolean> booleanConsumer;
private String acceptString, rejectString;
private AcceptDialogMenu(String dialogTitle) {
menu = SmartInventory.builder()
.id("partyMenu")
.title(dialogTitle)
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(3, 9)
.build();
//menu.setInsertable(true);
}
public static void open(Player player, String dialogTitle, String acceptString, String rejectString, Consumer<Boolean> booleanConsumer) {
AcceptDialogMenu acceptDialogMenu = new AcceptDialogMenu(dialogTitle);
acceptDialogMenu.booleanConsumer = booleanConsumer;
acceptDialogMenu.acceptString = acceptString;
acceptDialogMenu.rejectString = rejectString;
acceptDialogMenu.getMenu().open(player);
}
@Override
public void init(Player player, InventoryContents contents) {
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fill(ClickableItem.empty(border));
// Accept button
ItemStack diamond = ItemBuilder.getInstance(Material.DIAMOND).setName(acceptString).get();
ClickableItem accept = ClickableItem.from(diamond, itemClickData -> booleanConsumer.accept(true));
contents.set(1, 3, accept);
// Accept button
ItemStack barrier = ItemBuilder.getInstance(Material.BARRIER).setName(rejectString).get();
ClickableItem reject = ClickableItem.from(barrier, itemClickData -> booleanConsumer.accept(false));
contents.set(1, 5, reject);
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
return menu;
}
}

View File

@ -1,6 +1,7 @@
package com.jamesdpeters.minecraft.chests.inventories;
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
@ -68,17 +69,21 @@ public class ChestLinkMenu implements InventoryProvider {
pagination.setItems(itemList.toArray(new ClickableItem[0]));
pagination.setItemsPerPage(28);
contents.fillBorders(ClickableItem.empty(Utils.getNamedItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " ")));
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fillBorders(ClickableItem.empty(border));
for (ClickableItem item : pagination.getPageItems()) {
contents.add(item);
}
contents.set(5, 2, ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.ARROW), "Previous"),
ItemStack previous = ItemBuilder.getInstance(Material.ARROW).setName("Previous").get();
contents.set(5, 2, ClickableItem.from(previous,
e -> {
lastPage = pagination.previous().getPage();
menu.open(player, lastPage);
}));
contents.set(5, 6, ClickableItem.from(Utils.getNamedItem(new ItemStack(Material.ARROW), "Next"),
ItemStack next = ItemBuilder.getInstance(Material.ARROW).setName("Next").get();
contents.set(5, 6, ClickableItem.from(next,
e -> {
lastPage = pagination.next().getPage();
menu.open(player, lastPage);

View File

@ -0,0 +1,99 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.party.PartyInvite;
import com.jamesdpeters.minecraft.chests.party.PartyUtils;
import com.jamesdpeters.minecraft.chests.party.PlayerParty;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import fr.minuskube.inv.content.Pagination;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
public class InvitesMenu implements InventoryProvider {
private final SmartInventory menu;
BiConsumer<PartyInvite, SmartInventory> onPlayerSelect;
private int lastPage; // Store the last page the player was on.
private SmartInventory previousInv;
private InvitesMenu() {
menu = SmartInventory.builder()
.id("partyMenu")
.title("Select an invite to accept!")
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(6, 9)
.build();
//menu.setInsertable(true);
}
public static void open(Player player, SmartInventory previousInventory, BiConsumer<PartyInvite, SmartInventory> onPlayerSelect) {
InvitesMenu playerSelectorMenu = new InvitesMenu();
playerSelectorMenu.onPlayerSelect = onPlayerSelect;
playerSelectorMenu.menu.open(player);
playerSelectorMenu.previousInv = previousInventory;
}
@Override
public void init(Player player, InventoryContents contents) {
Pagination pagination = contents.pagination();
List<ClickableItem> itemList = new ArrayList<>();
for (PartyInvite invite : PartyUtils.getPartyInvites(player)){
// Pass through click to the menus onPlayerSelect function.
ItemStack inviteBook = ItemBuilder.getInstance(Material.ENCHANTED_BOOK).setName(invite.getParty().getPartyName()).get();
ClickableItem clickableItem = ClickableItem.from(inviteBook, itemClickData -> onPlayerSelect.accept(invite, menu));
itemList.add(clickableItem);
}
pagination.setItems(itemList.toArray(new ClickableItem[0]));
pagination.setItemsPerPage(28);
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fillBorders(ClickableItem.empty(border));
for (ClickableItem item : pagination.getPageItems()) {
contents.add(item);
}
ItemStack previous = ItemBuilder.getInstance(Material.ARROW).setName("Previous").get();
contents.set(5, 2, ClickableItem.from(previous,
e -> {
lastPage = pagination.previous().getPage();
menu.open(player, lastPage);
}));
ItemStack next = ItemBuilder.getInstance(Material.ARROW).setName("Next").get();
contents.set(5, 6, ClickableItem.from(next,
e -> {
lastPage = pagination.next().getPage();
menu.open(player, lastPage);
}));
ItemStack ret = ItemBuilder.getInstance(Material.BARRIER).setName("Return").get();
contents.set(5, 4, ClickableItem.from(ret, itemClickData -> {
if (previousInv != null) {
previousInv.open(player);
}
}));
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
return menu;
}
}

View File

@ -0,0 +1,229 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.lang.Message;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.party.PartyUtils;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import net.wesjd.anvilgui.AnvilGUI;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class PartyMenu implements InventoryProvider {
public static HashMap<Player, PartyMenu> menus;
private SmartInventory menu;
ClickableItem CREATE;
ClickableItem INVITE;
ClickableItem REMOVE_PLAYER;
ClickableItem LIST;
ClickableItem DELETE;
ClickableItem INVITES;
ClickableItem LEAVE_PARTY;
private List<ClickableItem> itemList;
private final Player player;
private PartyMenu(Player player) {
this.player = player;
updateIcons();
rebuildMenu();
}
public void rebuildMenu() {
menu = SmartInventory.builder()
.id("partyMenu")
.title("Party Menu")
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(3, 9)
.build();
}
public void updateIcons() {
// Enchant invites icon if player has invites to accept.
ItemStack INVITES_ICON = ItemBuilder
.getInstance(Material.FILLED_MAP)
.setEnchanted(PartyUtils.hasInvites(player))
.setName("Party Invites")
.get();
INVITES = ClickableItem.from(INVITES_ICON, itemClickData -> partyInvites(itemClickData.getPlayer()));
CREATE = ClickableItem.from(ItemBuilder
.getInstance(Material.ANVIL)
.setName("Create a party").get(),
itemClickData -> create(itemClickData.getPlayer()));
INVITE = ClickableItem.from(ItemBuilder
.getInstance(Material.WRITABLE_BOOK)
.setName( "Invite a player to a party").get(),
itemClickData -> invite(itemClickData.getPlayer()));
REMOVE_PLAYER = ClickableItem.from(ItemBuilder
.getInstance(Material.SKELETON_SKULL)
.setName( "Remove a player from a party").get(),
itemClickData -> removePlayer(itemClickData.getPlayer()));
LIST = ClickableItem.from(ItemBuilder
.getInstance(Material.MAP)
.setName("List all parties you're a member of").get(),
itemClickData -> listParties(itemClickData.getPlayer()));
DELETE = ClickableItem.from(ItemBuilder
.getInstance(Material.BARRIER)
.setName( "Delete a party").get(),
itemClickData -> deleteParty(itemClickData.getPlayer()));
LEAVE_PARTY = ClickableItem.from(ItemBuilder
.getInstance(Material.WITHER_SKELETON_SKULL)
.setName("Leave party").get(), itemClickData -> leaveParty(player)
);
itemList = Arrays.asList(CREATE, INVITE, REMOVE_PLAYER, LEAVE_PARTY, LIST, DELETE, INVITES);
}
public static PartyMenu getMenu(Player player) {
if (menus == null) menus = new HashMap<>();
if (!menus.containsKey(player)) {
menus.put(player, new PartyMenu(player));
}
return menus.get(player);
}
@Override
public void init(Player player, InventoryContents contents) {
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fillBorders(ClickableItem.empty(border));
for (ClickableItem item : itemList) {
contents.add(item);
}
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
updateIcons();
rebuildMenu();
return menu;
}
/*
* Party Methods
*/
public void create(Player player) {
TextInputUI.getInput(player, "Enter a Party Name", (p, partyName) -> {
boolean result = PartyUtils.createParty(player, partyName);
if (result){
player.sendMessage(ChatColor.GREEN+ Message.PARTY_CREATED.getString(ChatColor.WHITE+partyName+ChatColor.GREEN));
getMenu().open(player);
return AnvilGUI.Response.close();
} else {
player.sendMessage(ChatColor.RED+Message.PARTY_ALREADY_EXISTS.getString(ChatColor.WHITE+partyName+ChatColor.RED));
return AnvilGUI.Response.text("Already exists!");
}
});
}
public void invite(Player player) {
PartySelectorMenu.open(player, getMenu(), PartySelectorMenu.Type.OWNED, (party, menu) -> {
List<OfflinePlayer> inviteablePlayers = Utils.getOnlinePlayersNotInList(party.getMembers());
inviteablePlayers.remove(party.getOwner());
PlayerSelectorMenu.open(player, "Choose a player to invite!", menu, inviteablePlayers, (player1, itemStack) -> itemStack, (playerToInvite, menu2) -> {
PartyUtils.invitePlayer(party, playerToInvite);
getMenu().open(player);
});
});
}
public void removePlayer(Player player) {
PartySelectorMenu.open(player, getMenu(), PartySelectorMenu.Type.OWNED, (party, menu) -> {
PlayerSelectorMenu.open(player, "Choose a player to remove!", menu, party.getMembers(), (player1, itemStack) -> itemStack, (selectedPlayer, menu2) -> {
AcceptDialogMenu.open(player, "Remove player \""+selectedPlayer.getName()+"\"?", "Yes", "No", aBoolean -> {
if (aBoolean) {
party.removeMember(selectedPlayer);
}
getMenu().open(player);
});
});
});
}
public void listParties(Player player) {
PartySelectorMenu.open(player, getMenu(), PartySelectorMenu.Type.ALL, (party, smartInventory) -> {
PlayerSelectorMenu.open(player, party.getPartyName()+" members", smartInventory, party.getAllPlayers(),
// Change player head to enchanted if owner.
(offlinePlayer, itemStack) -> {
if (party.getOwner().getUniqueId().equals(offlinePlayer.getUniqueId())) return ItemBuilder.fromInstance(itemStack).addLore("Owner").get();
return itemStack;
} ,
(playerSelected, smartInventory1) -> {
// Do nothing.
});
});
}
public void deleteParty(Player player) {
PartySelectorMenu.open(player, getMenu(), PartySelectorMenu.Type.OWNED, (party, smartInventory) -> {
AcceptDialogMenu.open(player, "Delete Party \""+party.getPartyName()+"\"?", "Yes", "No", aBoolean -> {
// If user accepts
if (aBoolean) {
boolean result = PartyUtils.deleteParty(party);
if (result) {
player.sendMessage(ChatColor.GREEN + Message.PARTY_DELETED.getString(ChatColor.WHITE + party.getPartyName() + ChatColor.GREEN));
} else {
player.sendMessage(ChatColor.RED+Message.PARTY_DOESNT_EXIST.getString(ChatColor.WHITE+party.getPartyName()+ChatColor.RED));
}
// Call deleteParty() to refresh party list.
deleteParty(player);
} else {
// If select no return to last menu
smartInventory.open(player);
}
});
});
}
public void partyInvites(Player player) {
InvitesMenu.open(player, getMenu(), (invite, smartInventory) -> {
AcceptDialogMenu.open(player, "Join "+invite.getParty().getOwner().getName()+"'s party \""+invite.getParty().getPartyName()+"\"", "Yes", "No", aBoolean -> {
if (aBoolean) {
PartyUtils.acceptInvite(player, invite);
getMenu().open(player);
} else {
PartyUtils.rejectInvite(player, invite);
getMenu().open(player);
}
});
});
}
public void leaveParty(Player player) {
PartySelectorMenu.open(player, getMenu(), PartySelectorMenu.Type.MEMBER_OF, (party, smartInventory) -> {
AcceptDialogMenu.open(player, "Leave party: "+party.getPartyName()+"?", "Yes", "No", aBoolean -> {
if (aBoolean) {
party.removeMember(player);
}
smartInventory.open(player);
});
});
}
}

View File

@ -0,0 +1,127 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.party.PartyUtils;
import com.jamesdpeters.minecraft.chests.party.PlayerParty;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import fr.minuskube.inv.content.Pagination;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class PartySelectorMenu implements InventoryProvider {
private final SmartInventory menu;
BiConsumer<PlayerParty, SmartInventory> onPlayerSelect;
private int lastPage; // Store the last page the player was on.
private SmartInventory previousInv;
private Type type;
private PartySelectorMenu() {
menu = SmartInventory.builder()
.id("partyMenu")
.title("Select a Party!")
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(6, 9)
.build();
//menu.setInsertable(true);
}
public enum Type {
ALL,
MEMBER_OF,
OWNED
}
public static void open(Player player, SmartInventory previousInventory, Type type, BiConsumer<PlayerParty, SmartInventory> onPlayerSelect) {
PartySelectorMenu playerSelectorMenu = new PartySelectorMenu();
playerSelectorMenu.onPlayerSelect = onPlayerSelect;
playerSelectorMenu.type = type;
playerSelectorMenu.previousInv = previousInventory;
playerSelectorMenu.menu.open(player);
}
@Override
public void init(Player player, InventoryContents contents) {
Pagination pagination = contents.pagination();
List<ClickableItem> itemList = new ArrayList<>();
for (PlayerParty playerParty : getParties(player)){
// Pass through click to the menus onPlayerSelect function.
ItemStack partyBook = ItemBuilder
.getInstance(Material.ENCHANTED_BOOK)
.setName(playerParty.getPartyName())
.addLore("Owner: "+playerParty.getOwner().getName())
.get();
ClickableItem clickableItem = ClickableItem.from(partyBook, itemClickData -> onPlayerSelect.accept(playerParty, menu));
itemList.add(clickableItem);
}
pagination.setItems(itemList.toArray(new ClickableItem[0]));
pagination.setItemsPerPage(28);
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fillBorders(ClickableItem.empty(border));
for (ClickableItem item : pagination.getPageItems()) {
contents.add(item);
}
ItemStack previous = ItemBuilder.getInstance(Material.ARROW).setName("Previous").get();
contents.set(5, 2, ClickableItem.from(previous,
e -> {
lastPage = pagination.previous().getPage();
menu.open(player, lastPage);
}));
ItemStack next = ItemBuilder.getInstance(Material.ARROW).setName("Next").get();
contents.set(5, 6, ClickableItem.from(next,
e -> {
lastPage = pagination.next().getPage();
menu.open(player, lastPage);
}));
ItemStack ret = ItemBuilder.getInstance(Material.BARRIER).setName("Return").get();
contents.set(5, 4, ClickableItem.from(ret, itemClickData -> {
if (previousInv != null) {
previousInv.open(player);
}
}));
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
return menu;
}
private List<PlayerParty> getParties(OfflinePlayer player) {
switch (type) {
case ALL:
return PartyUtils.getPlayerPartyStorage(player).getAllParties();
case OWNED:
return PartyUtils.getPlayerPartyStorage(player).getOwnedPartiesList();
case MEMBER_OF:
return PartyUtils.getPlayerPartyStorage(player).getPartiesMemberOf();
default:
return new ArrayList<>();
}
}
}

View File

@ -0,0 +1,106 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.ItemBuilder;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import fr.minuskube.inv.content.Pagination;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
public class PlayerSelectorMenu implements InventoryProvider {
private final SmartInventory menu;
BiConsumer<OfflinePlayer, SmartInventory> onPlayerSelect;
BiFunction<OfflinePlayer, ItemStack, ItemStack> onPlayerHeadCreation;
private List<OfflinePlayer> players;
private int lastPage; // Store the last page the player was on.
private SmartInventory previousInv;
private PlayerSelectorMenu(String title) {
menu = SmartInventory.builder()
.id("partyMenu")
.title(title)
.provider(this)
.manager(ChestsPlusPlus.INVENTORY_MANAGER)
.size(6, 9)
.build();
//menu.setInsertable(true);
}
public static void open(Player player, String title, SmartInventory previousInv, List<OfflinePlayer> players, BiFunction<OfflinePlayer, ItemStack, ItemStack> onPlayerHeadCreation, BiConsumer<OfflinePlayer, SmartInventory> onPlayerSelect) {
PlayerSelectorMenu playerSelectorMenu = new PlayerSelectorMenu(title);
playerSelectorMenu.players = players;
playerSelectorMenu.onPlayerHeadCreation = onPlayerHeadCreation;
playerSelectorMenu.onPlayerSelect = onPlayerSelect;
playerSelectorMenu.previousInv = previousInv;
playerSelectorMenu.menu.open(player);
}
@Override
public void init(Player player, InventoryContents contents) {
Pagination pagination = contents.pagination();
List<ClickableItem> itemList = new ArrayList<>();
for (OfflinePlayer offlinePlayer : players) {
// Generate player heads
ItemStack skull = ItemBuilder.getPlayerHead(offlinePlayer).setName(offlinePlayer.getName()).get();
skull = onPlayerHeadCreation.apply(offlinePlayer, skull);
// Pass through click to the menus onPlayerSelect function.
ClickableItem clickableItem = ClickableItem.from(skull, itemClickData -> onPlayerSelect.accept(offlinePlayer, menu));
itemList.add(clickableItem);
}
pagination.setItems(itemList.toArray(new ClickableItem[0]));
pagination.setItemsPerPage(28);
ItemStack border = ItemBuilder.getInstance(Material.GRAY_STAINED_GLASS_PANE).setName(" ").get();
contents.fillBorders(ClickableItem.empty(border));
for (ClickableItem item : pagination.getPageItems()) {
contents.add(item);
}
ItemStack previous = ItemBuilder.getInstance(Material.ARROW).setName("Previous").get();
contents.set(5, 2, ClickableItem.from(previous,
e -> {
lastPage = pagination.previous().getPage();
menu.open(player, lastPage);
}));
ItemStack next = ItemBuilder.getInstance(Material.ARROW).setName("Next").get();
contents.set(5, 6, ClickableItem.from(next,
e -> {
lastPage = pagination.next().getPage();
menu.open(player, lastPage);
}));
ItemStack ret = ItemBuilder.getInstance(Material.BARRIER).setName("Return").get();
contents.set(5, 4, ClickableItem.from(ret, itemClickData -> {
if (previousInv != null) {
previousInv.open(player);
}
}));
}
@Override
public void update(Player player, InventoryContents contents) {
}
public SmartInventory getMenu() {
return menu;
}
}

View File

@ -0,0 +1,19 @@
package com.jamesdpeters.minecraft.chests.menus;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import net.wesjd.anvilgui.AnvilGUI;
import org.bukkit.entity.Player;
import java.util.function.BiFunction;
public class TextInputUI {
public static void getInput(Player player, String title, BiFunction<Player, String, AnvilGUI.Response> responseBiFunction) {
new AnvilGUI.Builder()
.onComplete(responseBiFunction)
.title(title)
.plugin(ChestsPlusPlus.PLUGIN)
.open(player);
}
}

View File

@ -0,0 +1,88 @@
package com.jamesdpeters.minecraft.chests.misc;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import java.util.ArrayList;
import java.util.List;
public class ItemBuilder {
List<String> lore;
Material material;
boolean enchanted;
String name;
OfflinePlayer skullOwner;
ItemStack itemStack;
private ItemBuilder() { }
// Material must be provided for every item.
public static ItemBuilder getInstance(Material material) {
ItemBuilder builder = new ItemBuilder();
builder.setMaterial(material);
return builder;
}
public static ItemBuilder fromInstance(ItemStack itemStack) {
ItemBuilder builder = new ItemBuilder();
builder.itemStack = itemStack;
return builder;
}
public static ItemBuilder getPlayerHead(OfflinePlayer skullOwner) {
ItemBuilder builder = getInstance(Material.PLAYER_HEAD);
builder.skullOwner = skullOwner;
return builder;
}
public ItemBuilder setName(String name) {
this.name = name;
return this;
}
public ItemBuilder setMaterial(Material material) {
this.material = material;
return this;
}
public ItemBuilder addLore(String lore){
if (this.lore == null) this.lore = new ArrayList<>();
this.lore.add(lore);
return this;
}
public ItemBuilder setEnchanted(boolean enchanted) {
this.enchanted = enchanted;
return this;
}
public ItemStack get() {
if (itemStack == null) itemStack = new ItemStack(material);
ItemMeta meta = itemStack.getItemMeta();
if (meta != null) {
if (name != null) meta.setDisplayName(name);
if (lore != null) meta.setLore(lore);
if (enchanted) {
itemStack.addUnsafeEnchantment(Enchantment.LURE, 1);
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
}
if (skullOwner != null && meta instanceof SkullMeta) {
SkullMeta skullMeta = (SkullMeta) meta;
skullMeta.setOwningPlayer(skullOwner);
}
itemStack.setItemMeta(meta);
}
return itemStack;
}
}

View File

@ -20,11 +20,13 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Container;
import org.bukkit.block.Hopper;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
@ -131,15 +133,6 @@ public class Utils {
return hopperMove(from, amount, to, null);
}
public static ItemStack getNamedItem(ItemStack item, String name) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
item.setItemMeta(meta);
}
return item;
}
public static List<String> getOnlinePlayers() {
return getPlayersAsNameList(Bukkit.getOnlinePlayers());
}
@ -313,4 +306,14 @@ public class Utils {
e.printStackTrace();
}
}
public static List<OfflinePlayer> getOnlinePlayersNotInList(List<OfflinePlayer> players) {
List<OfflinePlayer> list = new ArrayList<>();
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (!players.contains(onlinePlayer)){
list.add(onlinePlayer);
}
}
return list;
}
}

View File

@ -21,7 +21,8 @@ public class PartyInvite {
Player onlinePlayer = player.getPlayer();
if(onlinePlayer != null) {
onlinePlayer.sendMessage(ChatColor.GREEN+Message.PARTY_INVITE.getString(ChatColor.WHITE+player.getName()+ChatColor.GREEN, ChatColor.WHITE+party.getPartyName()+ChatColor.GREEN));
onlinePlayer.sendMessage(Message.PARTY_ACCEPT_INVITE.getString());
String tellraw = "tellraw @p {\"text\":\""+Message.PARTY_ACCEPT_INVITE.getString()+"\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/c++ party view-invites\"}}";
onlinePlayer.performCommand(tellraw);
}
Player onlineOwner = owner.getPlayer();
if (onlineOwner != null){
@ -40,4 +41,14 @@ public class PartyInvite {
pending = false;
}
}
public void rejectInvite(){
if (pending) {
pending = false;
}
}
public PlayerParty getParty() {
return party;
}
}

View File

@ -6,7 +6,10 @@ import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
public class PartyUtils {
@ -16,8 +19,19 @@ public class PartyUtils {
PARTY_CREATED
}
// Stores the last party invite sent to this player.
private static HashMap<UUID, PartyInvite> latestPartyInvite = new HashMap<>();
// Stores party invites sent to this player.
// Only stored in memory
private static final HashMap<UUID, List<PartyInvite>> partyInvites = new HashMap<>();
public static boolean hasInvites(OfflinePlayer player) {
List<PartyInvite> invites = partyInvites.get(player.getUniqueId());
if (invites == null) return false;
return invites.size() > 0;
}
public static List<PartyInvite> getPartyInvites(OfflinePlayer player) {
return partyInvites.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>());
}
/**
* Invites a player to the owners given party. The last pending invite is overwritten.
@ -37,9 +51,17 @@ public class PartyUtils {
return;
}
PartyInvite invite = new PartyInvite(owner, playerToInvite, storage.getOwnedParties().get(partyName));
latestPartyInvite.put(playerToInvite.getUniqueId(), invite);
invitePlayer(party, playerToInvite);
}
private static void addPlayerInvite(OfflinePlayer player, PartyInvite invite) {
List<PartyInvite> invites = partyInvites.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>());
invites.add(invite);
}
public static void invitePlayer(PlayerParty party, OfflinePlayer playerToInvite) {
PartyInvite invite = new PartyInvite(party.getOwner(), playerToInvite, party);
addPlayerInvite(playerToInvite, invite);
invite.sendInvite();
}
@ -62,24 +84,27 @@ public class PartyUtils {
* Accepts the current pending invite for this player.
* @param player
*/
public static void acceptInvite(OfflinePlayer player){
PartyInvite invite = latestPartyInvite.get(player.getUniqueId());
if (invite == null) {
Player onlinePlayer = player.getPlayer();
if (onlinePlayer != null) {
onlinePlayer.sendMessage(Message.PARTY_NO_INVITE.getString());
}
return;
public static void acceptInvite(OfflinePlayer player, PartyInvite invite){
List<PartyInvite> invites = partyInvites.get(player.getUniqueId());
if (invite != null) {
invite.acceptInvite();
invites.remove(invite);
}
}
public static void rejectInvite(OfflinePlayer player, PartyInvite invite) {
List<PartyInvite> invites = partyInvites.get(player.getUniqueId());
if (invite != null) {
invite.rejectInvite();
invites.remove(invite);
}
invite.acceptInvite();
latestPartyInvite.remove(player.getUniqueId());
}
/**
* Creates a party.
* @param owner
* @param partyName
* @return
* @return false if party already exists.
*/
public static boolean createParty(OfflinePlayer owner, String partyName){
PlayerPartyStorage storage = getPlayerPartyStorage(owner);
@ -113,6 +138,10 @@ public class PartyUtils {
return true;
}
public static boolean deleteParty(PlayerParty party){
return deleteParty(party.getOwner(), party.getPartyName());
}
public static PlayerPartyStorage getPlayerPartyStorage(OfflinePlayer owner) {
HashMap<String, PlayerPartyStorage> map = Config.getStore().parties;
PlayerPartyStorage storage = map.get(owner.getUniqueId().toString());

View File

@ -71,6 +71,12 @@ public class PlayerParty implements ConfigurationSerializable {
return members;
}
public List<OfflinePlayer> getAllPlayers() {
List<OfflinePlayer> players = new ArrayList<>(members);
players.add(0, owner);
return players;
}
public void addMember(OfflinePlayer player) {
if (members == null){
members = new ArrayList<>();

View File

@ -13,6 +13,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
@SerializableAs("PlayerPartyStorage")
public class PlayerPartyStorage implements ConfigurationSerializable {
@ -63,6 +64,10 @@ public class PlayerPartyStorage implements ConfigurationSerializable {
return ownedParties;
}
public List<PlayerParty> getOwnedPartiesList() {
return new ArrayList<>(ownedParties.values());
}
public Collection<PlayerParty> getOwnedPartiesCollection() {
return ownedParties.values();
}
@ -72,4 +77,33 @@ public class PlayerPartyStorage implements ConfigurationSerializable {
ownedParties.values().forEach(party -> strings.add(party.getPartyName()));
return strings;
}
/**
* Returns a List of Parties this player is a member of, not including their owned parties.
* @return
*/
public List<PlayerParty> getPartiesMemberOf() {
// Create list containing all owned parties
List<PlayerParty> parties = new ArrayList<>();
Config.getStore().parties.values().forEach(playerPartyStorage -> {
playerPartyStorage.getOwnedPartiesCollection().forEach(party -> {
if (party.isMember(getOwner())) parties.add(party);
});
});
return parties;
}
/**
* Returns ALL parties this player is a member of;.
* @return
*/
public List<PlayerParty> getAllParties() {
// Create list containing all owned parties
List<PlayerParty> parties = getPartiesMemberOf();
parties.addAll(getOwnedPartiesCollection());
return parties;
}
}

View File

@ -2,7 +2,7 @@ package com.jamesdpeters.minecraft.chests.storage.chestlink;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.interfaces.VirtualInventoryHolder;
import com.jamesdpeters.minecraft.chests.inventories.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.menus.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.runnables.VirtualChestToHopper;

View File

@ -60,6 +60,6 @@ UNABLE_TO_REMOVE_MEMBER=Unable to remove player {player_name} from {storage_type
COMMAND_AUTOCRAFT_SETPUBLIC=Set an AutoCraft group to be accessible by anyone.
ALREADY_PART_OF_GROUP=This {storage_type} is already a part of a group\!
INVALID_ID=Invalid {storage_type} ID\! Must not contain a colon '\:' unless you are referencing another players group that you are a member of
PARTY_ACCEPT_INVITE=Use §a§l/chestsplusplus party accept-invite§r or §a§l'/c++ party accept-invite'§r to accept the invite\!
PARTY_ACCEPT_INVITE=Click Here to accept the invite\!
FOUND_UNLINKED_STORAGE=This {storage_type} wasn't linked to your system\! It has been added under the {storage_identifier} group\!
PARTY_DOESNT_EXIST=The party {party_name} doesn't exist\!