Remake friends UI

This commit is contained in:
Sam 2018-08-07 16:47:01 +01:00 committed by Alexander Meech
parent 723dd4110d
commit ad88c581fd
17 changed files with 491 additions and 1012 deletions

View File

@ -827,13 +827,7 @@ public class CoreClientManager extends MiniPlugin
if (matchedName != null)
{
for (Iterator<String> matchIterator = matches.iterator(); matchIterator.hasNext(); )
{
if (!matchIterator.next().equalsIgnoreCase(playerName))
{
matchIterator.remove();
}
}
matches.removeIf(s -> !s.equalsIgnoreCase(playerName));
}
UtilPlayer.searchOffline(matches, target ->

View File

@ -1,15 +1,15 @@
package mineplex.core.anvilMenu.player;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.anvilMenu.PlayerInputActionMenu;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.party.Party;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
/**
* A wrapped menu that handles looking for players specifically.
@ -17,7 +17,7 @@ import org.bukkit.entity.Player;
public abstract class PlayerNameMenu extends PlayerInputActionMenu
{
protected CoreClientManager _clientManager;
protected final CoreClientManager _clientManager;
public PlayerNameMenu(MiniPlugin plugin, CoreClientManager clientManager, Player player)
{
@ -32,25 +32,33 @@ public abstract class PlayerNameMenu extends PlayerInputActionMenu
@Override
public void inputReceived(String name)
{
if(Bukkit.getPlayer(name) != null)
Player onlinePlayer = UtilPlayer.searchExact(name);
if (onlinePlayer != null)
{
onSuccess(Bukkit.getPlayer(name).getName());
onSuccess(onlinePlayer.getName());
return;
}
_clientManager.checkPlayerName(_player, _itemName, result -> {
_searching = false;
if (result != null)
_clientManager.checkPlayerName(_player, _itemName, result ->
{
_plugin.runSync(() ->
{
onSuccess(result);
} else
{
onFail(name);
_currentInventory.setItem(2, new ItemBuilder(Material.PAPER)
.setTitle(C.cYellow + "0" + C.cGray + " matches for [" + C.cYellow + name + C.cGray + "]")
.build());
_player.playSound(_player.getLocation(), Sound.ITEM_BREAK, 1, .6f);
}
_searching = false;
if (result != null)
{
onSuccess(result);
}
else
{
onFail(name);
_currentInventory.setItem(2, new ItemBuilder(Material.PAPER)
.setTitle(C.cYellow + "0" + C.cGray + " matches for [" + C.cYellow + name + C.cGray + "]")
.build());
_player.playSound(_player.getLocation(), Sound.ITEM_BREAK, 1, .6f);
}
});
});
}
}

View File

@ -2,10 +2,13 @@ package mineplex.core.friend;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@ -15,7 +18,6 @@ import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
@ -29,15 +31,16 @@ import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.donation.DonationManager;
import mineplex.core.friend.command.AddFriend;
import mineplex.core.friend.command.DeleteFriend;
import mineplex.core.friend.command.FriendFavouriteCommand;
import mineplex.core.friend.command.FriendVisibilityCommand;
import mineplex.core.friend.command.FriendsDisplay;
import mineplex.core.friend.data.FriendData;
import mineplex.core.friend.data.FriendRepository;
import mineplex.core.friend.data.FriendStatus;
import mineplex.core.friend.redis.FriendAddMessage;
import mineplex.core.friend.ui.FriendShop;
import mineplex.core.portal.Portal;
import mineplex.core.preferences.Preference;
import mineplex.core.preferences.PreferencesManager;
@ -47,66 +50,70 @@ import mineplex.serverdata.commands.ServerCommandManager;
import mineplex.serverdata.data.PlayerStatus;
@ReflectivelyCreateMiniPlugin
public class FriendManager extends MiniDbClientPlugin<FriendData>
public class FriendManager extends MiniDbClientPlugin<List<FriendStatus>>
{
public enum Perm implements Permission
{
FRIEND_COMMAND,
JOIN_STAFF,
JOIN_STAFF
}
private static final int MAX_FRIENDS = 500;
private static final Comparator<FriendStatus> FRIEND_SORTER = (o1, o2) ->
{
if (o1.Online && !o2.Online)
// If not mutual
if (o1.Status != FriendStatusType.Accepted || o2.Status != FriendStatusType.Accepted)
{
return o1.Name.compareTo(o2.Name);
}
// Favourite
if (o1.Favourite && !o2.Favourite)
{
return -1;
}
else if (!o1.Favourite && o2.Favourite)
{
return 1;
}
if (o2.Online && !o1.Online)
// Online
if (o1.isOnline() && !o2.isOnline())
{
return -1;
}
// If both online we sort by mutual
if (o1.Online)
else if (!o1.isOnline() && o2.isOnline())
{
if (o1.Status == FriendStatusType.Accepted && o2.Status != FriendStatusType.Accepted)
{
return 1;
}
else if (o2.Status == FriendStatusType.Accepted && o1.Status != FriendStatusType.Accepted)
{
return -1;
}
if (o1.Name.compareTo(o2.Name) > 0)
{
return 1;
}
else if (o2.Name.compareTo(o1.Name) > 0)
{
return -1;
}
return 1;
}
return Long.compare(o2.LastSeenOnline, o1.LastSeenOnline);
// Last Seen
return Long.compare(o1.LastSeenOnline, o2.LastSeenOnline);
};
private static final int FRIENDS_PER_CHAT_PAGE = 20;
public static Comparator<FriendStatus> getFriendSorter()
{
return FRIEND_SORTER;
}
private final DonationManager _donationManager;
private final PreferencesManager _preferenceManager;
private final Portal _portal;
private final FriendRepository _repository;
private final FriendShop _shop;
private FriendManager()
{
super("Friends");
_donationManager = require(DonationManager.class);
_preferenceManager = require(PreferencesManager.class);
_portal = require(Portal.class);
_repository = new FriendRepository();
_shop = new FriendShop(this);
generatePermissions();
@ -119,7 +126,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
return;
}
for (FriendStatus status : Get(target).getFriends())
for (FriendStatus status : Get(target))
{
if (status.Name.equals(command.getAccepter()))
{
@ -138,6 +145,11 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
PermissionGroup.TRAINEE.setPermission(Perm.JOIN_STAFF, true, true);
}
public DonationManager getDonationManager()
{
return _donationManager;
}
public PreferencesManager getPreferenceManager()
{
return _preferenceManager;
@ -159,9 +171,14 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
}
@Override
protected FriendData addPlayer(UUID uuid)
protected List<FriendStatus> addPlayer(UUID uuid)
{
return new FriendData();
return Collections.emptyList();
}
public void openShop(Player player)
{
_shop.attemptShopOpen(player);
}
@EventHandler
@ -176,27 +193,27 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
runAsync(() ->
{
final Map<String, FriendData> newData = _repository.getFriendsForAll(onlinePlayers);
final Map<String, Set<FriendStatus>> newData = _repository.getFriendsForAll(onlinePlayers);
runSync(() ->
{
for (Player player : Bukkit.getOnlinePlayers())
for (Player player : onlinePlayers)
{
FriendData playerData = Get(player);
FriendData newPlayerData = newData.get(player.getUniqueId().toString());
List<FriendStatus> playerData = Get(player);
Set<FriendStatus> newPlayerData = newData.get(player.getUniqueId().toString());
if (newPlayerData != null)
{
List<UUID> online = playerData.getFriends().stream()
List<UUID> online = playerData.stream()
.filter(FriendStatus::isOnline)
.map(friendStatus -> friendStatus.UUID)
.collect(Collectors.toList());
List<UUID> offline = playerData.getFriends().stream()
List<UUID> offline = playerData.stream()
.filter(friendStatus -> !friendStatus.isOnline())
.map(friendStatus -> friendStatus.UUID)
.collect(Collectors.toList());
newPlayerData.getFriends().forEach(friendStatus ->
newPlayerData.forEach(friendStatus ->
{
if (!friendStatus.Favourite)
{
@ -215,13 +232,15 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
}
});
playerData.setFriends(newPlayerData.getFriends());
Set(player, new LinkedList<>(newPlayerData));
}
else
{
playerData.getFriends().clear();
playerData.clear();
}
}
_shop.updatePages();
});
});
}
@ -236,10 +255,9 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
return;
}
FriendData data = Get(event.getPlayer());
int pending = 0;
for (FriendStatus status : data.getFriends())
for (FriendStatus status : Get(event.getPlayer()))
{
if (status.Status == FriendStatusType.Pending)
{
@ -264,9 +282,17 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
return;
}
List<FriendStatus> statuses = Get(caller);
if (statuses.size() >= MAX_FRIENDS)
{
caller.sendMessage(F.main(getName(), "You have reached the maximum amount of friends."));
return;
}
boolean update = false;
for (FriendStatus status : Get(caller).getFriends())
for (FriendStatus status : statuses)
{
if (status.Name.equalsIgnoreCase(name))
{
@ -306,7 +332,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
runSync(() ->
{
for (FriendStatus status : Get(caller).getFriends())
for (FriendStatus status : Get(caller))
{
if (status.Name.equalsIgnoreCase(name))
{
@ -322,7 +348,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
runSync(() ->
{
for (FriendStatus status : Get(caller).getFriends())
for (FriendStatus status : Get(caller))
{
if (status.Name.equalsIgnoreCase(name))
{
@ -358,7 +384,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
runSync(() ->
{
for (FriendStatus status : Get(caller).getFriends())
for (FriendStatus status : Get(caller))
{
if (status.Name.equalsIgnoreCase(name))
{
@ -387,7 +413,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
public void toggleFavourite(Player player, String target)
{
for (FriendStatus status : Get(player).getFriends())
for (FriendStatus status : Get(player))
{
if (status.Name.equals(target))
{
@ -446,8 +472,8 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
boolean isStaff = ClientManager.Get(caller).hasPermission(Perm.JOIN_STAFF);
boolean showPending = _preferenceManager.get(caller).isActive(Preference.PENDING_FRIEND_REQUESTS);
List<FriendStatus> friendStatuses = Get(caller).getFriends();
friendStatuses.sort(FRIEND_SORTER);
List<FriendStatus> friendStatuses = Get(caller);
friendStatuses.sort(getFriendSorter().reversed());
caller.sendMessage(C.cAqua + C.Strike + "======================[" + C.cWhiteB + "Friends" + C.cAqua + C.Strike + "]======================");
@ -663,6 +689,11 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
caller.spigot().sendMessage(toggle);
}
public boolean canJoin(String serverName, Player player)
{
return canJoin(serverName, ClientManager.Get(player).hasPermission(Perm.JOIN_STAFF));
}
public boolean canJoin(String serverName, boolean isPlayerStaff)
{
if (serverName == null)

View File

@ -7,7 +7,6 @@ import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.ui.FriendsGUI;
import mineplex.core.preferences.Preference;
public class AddFriend extends CommandBase<FriendManager>
@ -27,7 +26,7 @@ public class AddFriend extends CommandBase<FriendManager>
{
if (Plugin.getPreferenceManager().get(caller).isActive(Preference.FRIENDS_DISPLAY_INVENTORY_UI))
{
new FriendsGUI(Plugin, caller);
Plugin.openShop(caller);
}
else
{

View File

@ -5,7 +5,6 @@ import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.ui.FriendsGUI;
import mineplex.core.preferences.Preference;
import mineplex.core.preferences.UserPreferences;
@ -32,7 +31,7 @@ public class FriendsDisplay extends CommandBase<FriendManager>
if (preferences.isActive(Preference.FRIENDS_DISPLAY_INVENTORY_UI))
{
Plugin.runAsync(() -> new FriendsGUI(Plugin, caller));
}
else
{

View File

@ -1,42 +0,0 @@
package mineplex.core.friend.data;
import java.util.ArrayList;
import java.util.List;
import mineplex.core.friend.ui.FriendsGUI;
public class FriendData
{
private List<FriendStatus> _friends = new ArrayList<>();
private FriendsGUI _friendsPage;
public List<FriendStatus> getFriends()
{
return _friends;
}
public void setFriends(List<FriendStatus> newFriends)
{
_friends = newFriends;
updateGui();
}
private void updateGui()
{
if (_friendsPage != null)
{
_friendsPage.updateGui();
}
}
public void setGui(FriendsGUI friendsPage)
{
_friendsPage = friendsPage;
}
public FriendsGUI getGui()
{
return _friendsPage;
}
}

View File

@ -5,9 +5,13 @@ import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.bukkit.entity.Player;
@ -71,9 +75,9 @@ public class FriendRepository extends RepositoryBase
return false;
}
public Map<String, FriendData> getFriendsForAll(Player... players)
public Map<String, Set<FriendStatus>> getFriendsForAll(Player... players)
{
final Map<String, FriendData> friends = new HashMap<>();
final Map<String, Set<FriendStatus>> friends = new HashMap<>();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(RETRIEVE_MULTIPLE_FRIEND_RECORDS).append("(");
@ -91,8 +95,6 @@ public class FriendRepository extends RepositoryBase
executeQuery(stringBuilder.toString(), resultSet ->
{
Set<FriendData> friendDatas = new HashSet<>();
while (resultSet.next())
{
FriendStatus friend = new FriendStatus();
@ -105,24 +107,19 @@ public class FriendRepository extends RepositoryBase
friend.Visibility = FriendVisibility.values()[resultSet.getByte("visibility")];
friend.Favourite = resultSet.getBoolean("favourite");
FriendData data = friends.computeIfAbsent(uuidSource, k -> new FriendData());
data.getFriends().add(friend);
friendDatas.add(data);
friends.computeIfAbsent(uuidSource, k -> new HashSet<>()).add(friend);
}
// Load the server status of friends for all sources.
for (FriendData friendData : friendDatas)
{
loadFriendStatuses(friendData);
}
friends.values().forEach(this::loadFriendStatuses);
});
return friends;
}
public FriendData loadClientInformation(ResultSet resultSet) throws SQLException
public List<FriendStatus> loadClientInformation(ResultSet resultSet) throws SQLException
{
FriendData friendData = new FriendData();
List<FriendStatus> statuses = new LinkedList<>();
while (resultSet.next())
{
@ -132,46 +129,29 @@ public class FriendRepository extends RepositoryBase
friend.Status = FriendStatusType.valueOf(resultSet.getString(2));
friend.LastSeenOnline = resultSet.getTimestamp(4).getTime() - resultSet.getTimestamp(3).getTime();
friend.UUID = UUID.fromString(resultSet.getString(5));
friend.ServerName = null;
friend.Online = false;
friend.Visibility = FriendVisibility.values()[resultSet.getByte("visibility")];
friend.Favourite = resultSet.getBoolean("favourite");
friendData.getFriends().add(friend);
statuses.add(friend);
}
loadFriendStatuses(friendData);
loadFriendStatuses(statuses);
return friendData;
return statuses;
}
/**
* Load the server status information for a list of {@link FriendStatus}.
*
* @param friendData - the {@link FriendStatus} object friends server status' are to be updated
*/
public void loadFriendStatuses(FriendData friendData)
public void loadFriendStatuses(Collection<FriendStatus> statuses)
{
// Generate a set of all friend names
Set<String> friendUUIDS = new HashSet<>();
for (FriendStatus status : friendData.getFriends())
{
friendUUIDS.add(status.UUID.toString());
}
// Load PlayerStatus' for friends
Collection<PlayerStatus> statuses = _repository.getElements(friendUUIDS);
Set<String> friendUUIDS = statuses.stream()
.map(status -> status.UUID.toString())
.collect(Collectors.toSet());
// Load player statuses into a mapping
Map<UUID, PlayerStatus> playerStatuses = new HashMap<>();
for (PlayerStatus status : statuses)
{
playerStatuses.put(status.getUUID(), status);
}
Map<UUID, PlayerStatus> playerStatuses = _repository.getElements(friendUUIDS).stream()
.collect(Collectors.toMap(PlayerStatus::getUUID, Function.identity()));
// Load status information into friend data.
for (FriendStatus friend : friendData.getFriends())
for (FriendStatus friend : statuses)
{
PlayerStatus status = playerStatuses.get(friend.UUID);
friend.Online = (status != null);

View File

@ -7,20 +7,20 @@ import mineplex.core.friend.FriendVisibility;
public class FriendStatus
{
public String Name;
public UUID UUID;
public String ServerName;
public boolean Online;
/**
* This seems like it should be unmodified without current time subtracted when set
*/
public long LastSeenOnline;
public FriendStatusType Status;
public FriendVisibility Visibility;
public String Name;
public UUID UUID;
public String ServerName;
public boolean Online;
/**
* This seems like it should be unmodified without current time subtracted when set
*/
public long LastSeenOnline;
public FriendStatusType Status;
public FriendVisibility Visibility;
public boolean Favourite;
public boolean isOnline()
{
return Online && Visibility != FriendVisibility.INVISIBLE;
}
{
return Online && Visibility != FriendVisibility.INVISIBLE;
}
}

View File

@ -1,188 +0,0 @@
package mineplex.core.friend.ui;
import net.minecraft.server.v1_8_R3.BlockPosition;
import net.minecraft.server.v1_8_R3.Blocks;
import net.minecraft.server.v1_8_R3.ChatMessage;
import net.minecraft.server.v1_8_R3.ContainerAnvil;
import net.minecraft.server.v1_8_R3.EntityHuman;
import net.minecraft.server.v1_8_R3.EntityPlayer;
import net.minecraft.server.v1_8_R3.PacketPlayOutOpenWindow;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import mineplex.core.command.CommandCenter;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.friend.FriendManager;
import mineplex.core.itemstack.ItemBuilder;
public class AddFriendPage implements Listener
{
private class AnvilContainer extends ContainerAnvil
{
private String n;
public AnvilContainer(EntityHuman entity)
{
super(entity.inventory, entity.world, new BlockPosition(0, 0, 0), entity);
}
@Override
public boolean a(EntityHuman entityhuman)
{
return true;
}
@Override
public void a(String origString)
{
n = origString;
_itemName = origString;
if (getSlot(2).hasItem())
{
net.minecraft.server.v1_8_R3.ItemStack itemstack = getSlot(2).getItem();
if (StringUtils.isBlank(origString))
itemstack.r();
else
{
itemstack.c(this.n);
}
}
e();
}
}
private FriendManager _friends;
private Player _player;
private Inventory _currentInventory;
private String _itemName = "";
private boolean _searching;
public AddFriendPage(FriendManager friends, Player player)
{
_player = player;
_friends = friends;
openInventory();
friends.registerEvents(this);
}
@EventHandler
public void onInventoryClose(InventoryCloseEvent event)
{
if (event.getPlayer() == _player)
{
unregisterListener();
}
}
public void unregisterListener()
{
_currentInventory.clear();
HandlerList.unregisterAll(this);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
if (event.getPlayer() == _player)
{
unregisterListener();
}
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event)
{
if (event.getRawSlot() < 3)
{
event.setCancelled(true);
if (event.getRawSlot() == 2)
{
if (_itemName.length() > 1 && !_searching)
{
_searching = true;
final String name = _itemName;
CommandCenter.Instance.GetClientManager().checkPlayerName(_player, _itemName, result ->
{
// This needs to be run sync otherwise some really dodgy stuff happens.
_friends.runSync(() ->
{
_searching = false;
if (result != null)
{
_friends.addFriend(_player, result);
_player.playSound(_player.getLocation(), Sound.NOTE_PLING, 1, 1.6f);
unregisterListener();
new FriendsGUI(_friends, _player);
}
else
{
_currentInventory.setItem(
2,
new ItemBuilder(Material.PAPER).setTitle(
C.cYellow + "0" + C.cGray + " matches for [" + C.cYellow + name + C.cGray + "]")
.build());
_player.playSound(_player.getLocation(), Sound.ITEM_BREAK, 1, .6f);
}
});
});
}
else
{
_player.playSound(_player.getLocation(), Sound.ITEM_BREAK, 1, .6f);
}
}
}
else if (event.isShiftClick())
{
event.setCancelled(true);
}
}
public void openInventory()
{
_player.closeInventory();
EntityPlayer p = ((CraftPlayer) _player).getHandle();
AnvilContainer container = new AnvilContainer(p);
int c = p.nextContainerCounter();
PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(c, "minecraft:anvil", new ChatMessage(Blocks.ANVIL.a() + ".name", new Object[0]));
UtilPlayer.sendPacket(_player, packet);
// Set their active container to the container
p.activeContainer = container;
// Set their active container window id to that counter stuff
p.activeContainer.windowId = c;
// Add the slot listener
p.activeContainer.addSlotListener(p); // Set the items to the items from the inventory given
_currentInventory = container.getBukkitView().getTopInventory();
_currentInventory.setItem(0, new ItemBuilder(Material.PAPER).setRawTitle("Friend's Name").build());
_currentInventory.setItem(2, new ItemBuilder(Material.PAPER).setRawTitle("Search").build());
}
}

View File

@ -0,0 +1,32 @@
package mineplex.core.friend.ui;
import org.bukkit.entity.Player;
import mineplex.core.anvilMenu.player.PlayerNameMenu;
import mineplex.core.friend.FriendManager;
public class FriendAddPage extends PlayerNameMenu
{
private final FriendManager _manager;
FriendAddPage(FriendManager plugin, Player player)
{
super(plugin, plugin.getClientManager(), player);
_manager = plugin;
}
@Override
public void onSuccess(String name)
{
_player.closeInventory();
_manager.addFriend(_player, name);
}
@Override
public void onFail(String name)
{
}
}

View File

@ -0,0 +1,284 @@
package mineplex.core.friend.ui;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.donation.DonationManager;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.FriendStatusType;
import mineplex.core.friend.FriendVisibility;
import mineplex.core.friend.data.FriendStatus;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.portal.Intent;
import mineplex.core.recharge.Recharge;
import mineplex.core.shop.page.MultiPageManager;
import mineplex.core.shop.page.ShopPageBase;
public class FriendMainPage extends ShopPageBase<FriendManager, FriendShop>
{
enum FriendPageType
{
MAIN(status -> status.Status == FriendStatusType.Accepted, new ItemBuilder(Material.SKULL_ITEM, (byte) 3)
.setTitle(C.cGreenB + "Friends")
.build()),
REQUESTS(status -> status.Status == FriendStatusType.Pending || status.Status == FriendStatusType.Sent, new ItemBuilder(Material.RED_ROSE)
.setTitle(C.cYellowB + "Friend Requests")
.build()),
DELETE(status -> status.Status == FriendStatusType.Accepted, new ItemBuilder(Material.TNT)
.setTitle(C.cRedB + "Delete Friends")
.build());
private final Predicate<FriendStatus> Filter;
private final ItemStack DisplayItem;
FriendPageType(Predicate<FriendStatus> filter, ItemStack displayItem)
{
Filter = filter;
DisplayItem = displayItem;
}
}
private final MultiPageManager<FriendStatus> _pageManager;
private FriendPageType _pageType;
FriendMainPage(FriendManager plugin, FriendShop shop, CoreClientManager clientManager, DonationManager donationManager, Player player)
{
super(plugin, shop, clientManager, donationManager, "Friends", player);
_pageManager = new MultiPageManager<>(this, () -> getPlugin().Get(player).stream()
.filter(_pageType.Filter)
.sorted(FriendManager.getFriendSorter())
.collect(Collectors.toList()), this::buildItem);
_pageType = FriendPageType.MAIN;
buildPage();
}
@Override
protected void buildPage()
{
int slot = 1;
for (FriendPageType pageType : FriendPageType.values())
{
ItemBuilder builder = new ItemBuilder(pageType.DisplayItem);
if (pageType.equals(_pageType))
{
builder.setGlow(true);
}
addButton(slot, builder.build(), (player, clickType) ->
{
if (pageType.equals(_pageType))
{
playDenySound(player);
}
else
{
playAcceptSound(player);
_pageType = pageType;
refresh();
}
});
slot += 2;
}
addButton(slot, new ItemBuilder(Material.BOOK_AND_QUILL)
.setTitle(C.cAquaB + "Add Friends")
.build(), (player, clickType) ->
{
new FriendAddPage(getPlugin(), player)
.openInventory();
});
_pageManager.buildPage();
}
private void buildItem(FriendStatus status, int slot)
{
switch (_pageType)
{
case MAIN:
buildMainItem(status, slot);
break;
case REQUESTS:
buildRequestItem(status, slot);
break;
case DELETE:
buildDeleteItem(status, slot);
break;
}
}
private void buildMainItem(FriendStatus status, int slot)
{
boolean online = status.isOnline();
boolean canJoin = online && status.Visibility == FriendVisibility.SHOWN && !status.ServerName.equals(UtilServer.getServerName()) && getPlugin().canJoin(status.ServerName, getPlayer());
ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM, (byte) (online ? 3 : 0))
.setPlayerHead(status.Name)
.setTitle(getColour(status) + status.Name)
.addLore("");
String statusString;
if (online)
{
if (status.Visibility == FriendVisibility.PRESENCE)
{
statusString = C.cYellow + status.Visibility.getName();
}
else
{
statusString = C.cGreen + status.ServerName;
}
}
else
{
statusString = C.cRed + "Offline";
}
builder.addLore("Where: " + statusString);
if (online)
{
if (canJoin)
{
builder.addLore("", C.cGreen + "Click to join their server.");
}
}
else
{
builder.addLore("Last seen " + UtilTime.MakeStr(status.LastSeenOnline), "");
}
builder.addLore(
"Shift-Click to " + (status.Favourite ? "remove " + status.Name + " from" : "add " + status.Name + " to"),
"your favourite friends."
);
addButton(slot, builder.build(), (player, clickType) ->
{
if (!Recharge.Instance.use(player, "Friends Interact", 500, false, false))
{
playDenySound(player);
return;
}
if (clickType.isShiftClick())
{
playAcceptSound(player);
getPlugin().toggleFavourite(player, status.Name);
}
else
{
if (canJoin)
{
playAcceptSound(player);
getPlugin().getPortal().sendPlayerToServer(player, status.ServerName, Intent.PLAYER_REQUEST);
}
else
{
playDenySound(player);
}
}
});
}
private void buildRequestItem(FriendStatus status, int slot)
{
boolean sent = status.Status == FriendStatusType.Sent;
ItemBuilder builder = new ItemBuilder(sent ? Material.ENDER_PEARL : Material.PAPER)
.setTitle(C.cGray + "Request" + (sent ? C.cGray + " to " + C.cPurple : C.cGray + " from " + C.cAqua) + status.Name)
.addLore("");
if (sent)
{
builder.addLore("Shift-Click to cancel.");
}
else
{
builder.addLore(
"Click to accept.",
"Shift-Click to deny."
);
}
addButton(slot, builder.build(), (player, clickType) ->
{
if (!Recharge.Instance.use(player, "Friends Interact", 500, false, false))
{
playDenySound(player);
return;
}
setItem(slot, null);
if (clickType.isShiftClick())
{
playRemoveSound(player);
getPlugin().removeFriend(player, status.Name);
}
else
{
playAcceptSound(player);
getPlugin().addFriend(player, status.Name);
}
});
}
private void buildDeleteItem(FriendStatus status, int slot)
{
boolean online = status.isOnline();
ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM, (byte) (online ? 3 : 0))
.setPlayerHead(status.Name)
.setTitle((online ? C.cGreen : C.cRed) + status.Name)
.addLore("Shift-Click to remove " + status.Name, "from your friends list.");
addButton(slot, builder.build(), (player, clickType) ->
{
if (!clickType.isShiftClick() || !Recharge.Instance.use(player, "Friends Interact", 500, false, false))
{
playDenySound(player);
return;
}
playRemoveSound(player);
setItem(slot, null);
getPlugin().removeFriend(player, status.Name);
});
}
private String getColour(FriendStatus status)
{
String colour;
if (status.Favourite)
{
colour = C.cYellow;
}
else if (status.isOnline())
{
colour = C.cGreen;
}
else
{
colour = C.cRed;
}
return colour;
}
}

View File

@ -1,40 +0,0 @@
package mineplex.core.friend.ui;
import mineplex.core.common.util.C;
import mineplex.core.itemstack.ItemBuilder;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public enum FriendPage
{
FRIENDS(new ItemBuilder(Material.SKULL_ITEM, 1, (short) 3).setTitle("Friends").build(), "Friends"),
FRIEND_REQUESTS(new ItemBuilder(Material.RED_ROSE).setTitle("Friend Requests").build(), "Friend Requests"),
DELETE_FRIENDS(new ItemBuilder(Material.TNT).setTitle("Delete Friends").build(), "Delete Friends"),
SEND_REQUEST(new ItemBuilder(Material.BOOK_AND_QUILL).setTitle("Send Friend Request").build(), "Send Friend Request"),
TOGGLE_DISPLAY(new ItemBuilder(Material.SIGN).setTitle(C.cGray + "Toggle friends to display in chat").build(),
"Toggle Display");
private ItemStack _icon;
private String _name;
private FriendPage(ItemStack item, String name)
{
_icon = item;
_name = name;
}
public String getName()
{
return _name;
}
public ItemStack getIcon()
{
return _icon;
}
}

View File

@ -0,0 +1,27 @@
package mineplex.core.friend.ui;
import org.bukkit.entity.Player;
import mineplex.core.friend.FriendManager;
import mineplex.core.shop.ShopBase;
import mineplex.core.shop.page.ShopPageBase;
public class FriendShop extends ShopBase<FriendManager>
{
public FriendShop(FriendManager plugin)
{
super(plugin, plugin.getClientManager(), plugin.getDonationManager(), plugin.getName());
}
@Override
protected ShopPageBase<FriendManager, ? extends ShopBase<FriendManager>> buildPagesFor(Player player)
{
return new FriendMainPage(getPlugin(), this, getClientManager(), getDonationManager(), player);
}
public void updatePages()
{
getPageMap().values().forEach(ShopPageBase::refresh);
}
}

View File

@ -1,603 +0,0 @@
package mineplex.core.friend.ui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import mineplex.core.command.CommandCenter;
import mineplex.core.common.util.C;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilTime;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.FriendStatusType;
import mineplex.core.friend.data.FriendData;
import mineplex.core.friend.data.FriendStatus;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.itemstack.ItemLayout;
import mineplex.core.shop.item.IButton;
import net.minecraft.server.v1_8_R3.EntityPlayer;
public class FriendsGUI implements Listener
{
private NautHashMap<Integer, IButton> _buttonMap = new NautHashMap<Integer, IButton>();
private FriendPage _currentPage = FriendPage.FRIENDS;
private FriendPage _previousPage;
private Player _player;
private FriendManager _plugin;
private Inventory _inventory;
private int _page;
private Comparator<FriendStatus> _friendCompare = new Comparator<FriendStatus>()
{
@Override
public int compare(FriendStatus o1, FriendStatus o2)
{
if (o1.Online == o2.Online)
{
return o1.Name.compareToIgnoreCase(o2.Name);
}
if (o1.Online)
{
return -1;
}
return 1;
}
};
public FriendsGUI(FriendManager plugin, Player player)
{
_plugin = plugin;
_player = player;
buildPage();
_plugin.registerEvents(this);
getFriendData().setGui(this);
}
private void AddButton(int slot, ItemStack item, IButton button)
{
_inventory.setItem(slot, item);
_buttonMap.put(slot, button);
}
public void buildDeleteFriends()
{
List<FriendStatus> friends = new ArrayList<>();
for (FriendStatus friend : getFriendData().getFriends())
{
if (friend.Status == FriendStatusType.Accepted)
{
friends.add(friend);
}
}
Collections.sort(friends, _friendCompare);
boolean pages = this.addPages(friends.size(), new Runnable()
{
public void run()
{
buildDeleteFriends();
}
});
for (int i = 0; i < (pages ? 27 : 36); i++)
{
int friendSlot = (_page * 27) + i;
int slot = i + 18;
if (friendSlot >= friends.size())
{
ItemStack item = _inventory.getItem(slot);
if (item == null || item.getType() == Material.AIR)
{
break;
}
else
{
_inventory.setItem(slot, new ItemStack(Material.AIR));
continue;
}
}
FriendStatus friend = friends.get(friendSlot);
ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM, 1, (short) (friend.Online ? 3 : 0));
builder.setTitle(C.cWhite + C.Bold + friend.Name);
builder.setPlayerHead(friend.Name);
builder.addLore(C.cGray + C.Bold + "Status: " + (friend.Online ? C.cDGreen + "Online" : C.cRed + "Offline"));
if (friend.Online)
{
builder.addLore(C.cGray + C.Bold + "Server: " + C.cYellow + friend.ServerName);
}
else
{
builder.addLore(C.cGray + "Last seen " + UtilTime.MakeStr(friend.LastSeenOnline) + " ago");
}
builder.addLore("");
builder.addLore(C.cGray + "Left click to delete from friends");
final String name = friend.Name;
AddButton(slot, builder.build(), new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
if (clickType.isLeftClick())
{
CommandCenter.Instance.onPlayerCommandPreprocess(new PlayerCommandPreprocessEvent(player, "/unfriend "
+ name));
}
}
});
}
}
private boolean addPages(int amount, final Runnable runnable)
{
if (amount > 36)
{
if (_page > 0)
{
AddButton(45, new ItemBuilder(Material.SIGN).setTitle("Previous Page").build(), new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
Iterator<Integer> itel = _buttonMap.keySet().iterator();
while (itel.hasNext())
{
int slot = itel.next();
if (slot > 8)
{
itel.remove();
_inventory.setItem(slot, new ItemStack(Material.AIR));
}
}
_page -= 1;
runnable.run();
}
});
}
if (amount > (_page + 1) * 27)
{
AddButton(53, new ItemBuilder(Material.SIGN).setTitle("Next Page").build(), new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
Iterator<Integer> itel = _buttonMap.keySet().iterator();
while (itel.hasNext())
{
int slot = itel.next();
if (slot > 8)
{
itel.remove();
_inventory.setItem(slot, new ItemStack(Material.AIR));
}
}
_page += 1;
runnable.run();
}
});
}
return true;
}
return false;
}
private void buildFriends()
{
ArrayList<FriendStatus> friends = new ArrayList<FriendStatus>();
for (FriendStatus friend : getFriendData().getFriends())
{
if (friend.Status == FriendStatusType.Accepted)
{
friends.add(friend);
}
}
Collections.sort(friends, _friendCompare);
boolean pages = addPages(friends.size(), new Runnable()
{
@Override
public void run()
{
buildFriends();
}
});
for (int i = 0; i < (pages ? 27 : 36); i++)
{
int friendSlot = (_page * 27) + i;
int slot = i + 18;
if (friendSlot >= friends.size())
{
ItemStack item = _inventory.getItem(slot);
if (item == null || item.getType() == Material.AIR)
{
break;
}
else
{
_inventory.setItem(slot, new ItemStack(Material.AIR));
continue;
}
}
FriendStatus friend = friends.get(friendSlot);
ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM, 1, (short) (friend.Online ? 3 : 0));
builder.setTitle(C.cWhite + C.Bold + friend.Name);
builder.setPlayerHead(friend.Name);
builder.addLore(C.cGray + C.Bold + "Status: " + (friend.Online ? C.cDGreen + "Online" : C.cRed + "Offline"));
if (friend.Online)
{
builder.addLore(C.cGray + C.Bold + "Server: " + C.cYellow + friend.ServerName);
}
else
{
builder.addLore(C.cGray + "Last seen " + UtilTime.MakeStr(friend.LastSeenOnline) + " ago");
}
if (friend.Online)
{
builder.addLore("");
builder.addLore(C.cGray + "Left click to teleport to their server");
final String serverName = friend.ServerName;
AddButton(slot, builder.build(), new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
CommandCenter.Instance.onPlayerCommandPreprocess(new PlayerCommandPreprocessEvent(player, "/server " + serverName));
}
});
}
else
{
_inventory.setItem(slot, builder.build());
}
}
}
public void updateGui()
{
if (_currentPage == FriendPage.FRIENDS)
{
buildFriends();
}
else if (_currentPage == FriendPage.FRIEND_REQUESTS)
{
buildRequests();
}
else if (_currentPage == FriendPage.DELETE_FRIENDS)
{
buildDeleteFriends();
}
}
private void buildPage()
{
if (_currentPage != _previousPage)
{
_inventory = Bukkit.createInventory(null, 54, _currentPage.getName());
}
else
{
_inventory.setItem(53, new ItemStack(Material.AIR));
_inventory.setItem(45, new ItemStack(Material.AIR));
}
_page = 0;
_buttonMap.clear();
ArrayList<Integer> itemSlots = new ItemLayout("OXOXOXOXO").getItemSlots();
for (int i = 0; i < FriendPage.values().length; i++)
{
final FriendPage page = FriendPage.values()[i];
ItemStack icon = page == _currentPage ?
new ItemBuilder(page.getIcon()).addEnchantment(UtilInv.getDullEnchantment(), 1).build()
:
page.getIcon();
this.AddButton(itemSlots.get(i), icon, new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
if (_currentPage != page || _page != 0)
{
_currentPage = page;
buildPage();
}
}
});
}
if (_currentPage == FriendPage.FRIENDS)
{
buildFriends();
}
else if (_currentPage == FriendPage.FRIEND_REQUESTS)
{
buildRequests();
}
else if (_currentPage == FriendPage.DELETE_FRIENDS)
{
buildDeleteFriends();
}
else if (_currentPage == FriendPage.SEND_REQUEST)
{
unregisterListener();
new AddFriendPage(_plugin, _player);
return;
}
else if (_currentPage == FriendPage.TOGGLE_DISPLAY)
{
_player.closeInventory();
CommandCenter.Instance.onPlayerCommandPreprocess(new PlayerCommandPreprocessEvent(_player, "/friendsdisplay"));
return;
}
if (_previousPage != _currentPage)
{
_previousPage = _currentPage;
EntityPlayer nmsPlayer = ((CraftPlayer) _player).getHandle();
if (nmsPlayer.activeContainer != nmsPlayer.defaultContainer)
{
// Do this so that other inventories know their time is over.
CraftEventFactory.handleInventoryCloseEvent(nmsPlayer);
nmsPlayer.m();
}
_player.openInventory(_inventory);
}
}
private void buildRequests()
{
ArrayList<FriendStatus> friends = new ArrayList<FriendStatus>();
for (FriendStatus friend : getFriendData().getFriends())
{
if (friend.Status == FriendStatusType.Sent || friend.Status == FriendStatusType.Pending)
{
friends.add(friend);
}
}
Collections.sort(friends, new Comparator<FriendStatus>()
{
@Override
public int compare(FriendStatus o1, FriendStatus o2)
{
if (o1.Status == o2.Status)
{
return o1.Name.compareToIgnoreCase(o2.Name);
}
if (o1.Status == FriendStatusType.Sent)
{
return -1;
}
return 1;
}
});
boolean pages = addPages(friends.size(), new Runnable()
{
@Override
public void run()
{
buildRequests();
}
});
for (int i = 0; i < (pages ? 27 : 36); i++)
{
int friendSlot = (_page * 27) + i;
final int slot = i + 18;
if (friendSlot >= friends.size())
{
ItemStack item = _inventory.getItem(slot);
if (item == null || item.getType() == Material.AIR)
{
break;
}
else
{
_inventory.setItem(slot, new ItemStack(Material.AIR));
continue;
}
}
FriendStatus friend = friends.get(friendSlot);
ItemBuilder builder;
final boolean isSender = friend.Status == FriendStatusType.Sent;
if (isSender)
{
builder = new ItemBuilder(Material.ENDER_PEARL);
builder.setTitle(C.cGray + "Friend request to " + C.cWhite + C.Bold + friend.Name);
}
else
{
builder = new ItemBuilder(Material.PAPER);
builder.setTitle(C.cGray + "Friend request from " + C.cWhite + C.Bold + friend.Name);
}
builder.addLore("");
builder.addLore(C.cGray + (isSender ? "C" : "Left c") + "lick to " + (isSender ? "cancel" : "accept")
+ " friend request");
if (!isSender)
{
builder.addLore(C.cGray + "Right click to refuse friend request");
}
final String name = friend.Name;
AddButton(slot, builder.build(), new IButton()
{
@Override
public void onClick(Player player, ClickType clickType)
{
if (isSender || clickType.isRightClick())
{
_plugin.removeFriend(_player, name);
// _commandCenter.Instance.onPlayerCommandPreprocess(new PlayerCommandPreprocessEvent(player, "/unfriend "
// + name));
_inventory.setItem(slot, new ItemStack(Material.AIR));
_buttonMap.remove(slot);
}
else if (!isSender && clickType.isLeftClick())
{
_plugin.addFriend(_player, name);
// _commandCenter.Instance.onPlayerCommandPreprocess(new PlayerCommandPreprocessEvent(player, "/friend "
// + name));
_inventory.setItem(slot, new ItemStack(Material.AIR));
_buttonMap.remove(slot);
}
}
});
}
}
private FriendData getFriendData()
{
return _plugin.Get(_player);
}
@EventHandler
public void OnInventoryClick(InventoryClickEvent event)
{
if (_inventory.getTitle().equals(event.getInventory().getTitle()) && event.getWhoClicked() == _player)
{
if (_buttonMap.containsKey(event.getRawSlot()))
{
if (event.getWhoClicked() instanceof Player)
{
IButton button = _buttonMap.get(event.getRawSlot());
button.onClick(((Player) event.getWhoClicked()), event.getClick());
_player.playSound(_player.getLocation(), Sound.NOTE_PLING, 1, 1.6f);
}
}
else
{
_player.playSound(_player.getLocation(), Sound.ITEM_BREAK, 1, .6f);
}
event.setCancelled(true);
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
if (event.getPlayer() == _player)
{
unregisterListener();
}
}
@EventHandler
public void OnInventoryClose(InventoryCloseEvent event)
{
if (_inventory.getTitle().equals(event.getInventory().getTitle()) && event.getPlayer() == _player)
{
unregisterListener();
}
}
private void unregisterListener()
{
FriendData data = getFriendData();
if (data != null && data.getGui() == this)
{
data.setGui(null);
}
HandlerList.unregisterAll(this);
}
}

View File

@ -27,7 +27,6 @@ import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.FriendStatusType;
import mineplex.core.friend.data.FriendData;
import mineplex.core.friend.data.FriendStatus;
import mineplex.core.ignore.IgnoreManager;
import mineplex.core.incognito.IncognitoManager;
@ -538,12 +537,11 @@ public class MessageManager extends MiniClientPlugin<ClientMessage>
public void sendMessage(final Player sender, final String target, final String message, final boolean isReply,
final boolean adminMessage)
{
FriendData friends = _friendsManager.Get(sender);
FriendStatus friend = null;
if (!adminMessage)
{
for (FriendStatus friendInfo : friends.getFriends())
for (FriendStatus friendInfo : _friendsManager.Get(sender))
{
// Don't consider them "the friend" if their request has not been accepted
if (friendInfo.Status != FriendStatusType.Accepted)

View File

@ -61,7 +61,7 @@ public class MultiPageManager<ItemType>
int endIndex = startIndex + _elementsPerPage;
List<ItemType> items = _getItems.get();
items = items.subList(startIndex, Math.min(endIndex, items.size()));
items = items.subList(Math.min(startIndex, endIndex), Math.min(endIndex, items.size()));
for (ItemType item : items)
{
@ -90,7 +90,7 @@ public class MultiPageManager<ItemType>
});
}
if (endIndex <= _getItems.get().size())
if (endIndex < _getItems.get().size())
{
_shopPage.addButton(53, new ShopItem(Material.ARROW, C.cGreen + "Next Page", new String[0], 1, false), (player, clickType) ->
{

View File

@ -149,7 +149,7 @@ public class GameTeamModule extends Module
}
// Step 3 - Friends
List<Player> friends = friendManager.Get(player).getFriends().stream()
List<Player> friends = friendManager.Get(player).stream()
.filter(friendStatus -> friendStatus.Online)
.map(friendStatus -> UtilPlayer.searchExact(friendStatus.UUID))
.filter(players::contains)