Get the friends update working

This commit is contained in:
Sam 2018-08-05 20:04:10 +01:00 committed by Alexander Meech
parent 4207364798
commit 723dd4110d
8 changed files with 346 additions and 23 deletions

View File

@ -7,6 +7,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
@ -17,6 +18,7 @@ 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;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin;
@ -24,19 +26,24 @@ import mineplex.core.account.permissions.Permission;
import mineplex.core.account.permissions.PermissionGroup;
import mineplex.core.common.util.C;
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.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.portal.Portal;
import mineplex.core.preferences.Preference;
import mineplex.core.preferences.PreferencesManager;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.serverdata.commands.ServerCommandManager;
import mineplex.serverdata.data.PlayerStatus;
@ReflectivelyCreateMiniPlugin
@ -102,6 +109,27 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
_repository = new FriendRepository();
generatePermissions();
ServerCommandManager.getInstance().registerCommandType(FriendAddMessage.class, command ->
{
Player target = UtilPlayer.searchExact(command.getTarget());
if (target == null)
{
return;
}
for (FriendStatus status : Get(target).getFriends())
{
if (status.Name.equals(command.getAccepter()))
{
target.sendMessage(F.main(getName(), F.name(status.Name) + " has accepted your friend request."));
return;
}
}
onFriendAdd(target, command.getAccepter());
});
}
private void generatePermissions()
@ -126,6 +154,8 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
addCommand(new AddFriend(this));
addCommand(new DeleteFriend(this));
addCommand(new FriendsDisplay(this));
addCommand(new FriendVisibilityCommand(this));
addCommand(new FriendFavouriteCommand(this));
}
@Override
@ -157,6 +187,34 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
if (newPlayerData != null)
{
List<UUID> online = playerData.getFriends().stream()
.filter(FriendStatus::isOnline)
.map(friendStatus -> friendStatus.UUID)
.collect(Collectors.toList());
List<UUID> offline = playerData.getFriends().stream()
.filter(friendStatus -> !friendStatus.isOnline())
.map(friendStatus -> friendStatus.UUID)
.collect(Collectors.toList());
newPlayerData.getFriends().forEach(friendStatus ->
{
if (!friendStatus.Favourite)
{
return;
}
// Offline -> Online
if (friendStatus.isOnline() && offline.contains(friendStatus.UUID))
{
player.sendMessage(F.main(getName(), F.name(friendStatus.Name) + " joined the network."));
}
// Online -> Offline
else if (!friendStatus.isOnline() && online.contains(friendStatus.UUID))
{
player.sendMessage(F.main(getName(), F.name(friendStatus.Name) + " left the network."));
}
});
playerData.setFriends(newPlayerData.getFriends());
}
else
@ -168,6 +226,36 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
});
}
@EventHandler
public void playerJoin(PlayerJoinEvent event)
{
Player player = event.getPlayer();
if (!_preferenceManager.get(player).isActive(Preference.PENDING_FRIEND_REQUESTS))
{
return;
}
FriendData data = Get(event.getPlayer());
int pending = 0;
for (FriendStatus status : data.getFriends())
{
if (status.Status == FriendStatusType.Pending)
{
pending++;
}
}
if (pending > 0)
{
player.spigot().sendMessage(new ComponentBuilder(F.main(getName(), "You have " + F.count(pending) + " pending friend request" + (pending == 1 ? "" : "s") + "."))
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(C.cGray + "Click to view your requests.").create()))
.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + AddFriend.COMMAND))
.create());
}
}
public void addFriend(final Player caller, final String name)
{
if (caller.getName().equalsIgnoreCase(name))
@ -245,6 +333,8 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
});
}
new FriendAddMessage(caller.getName(), name).publish();
runSync(() ->
{
if (updateFinal)
@ -282,6 +372,75 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
});
}
public void setVisibility(Player player, FriendVisibility visibility)
{
int accountId = ClientManager.getAccountId(player);
runAsync(() ->
{
if (_repository.updateVisibility(accountId, visibility))
{
runSync(() -> player.sendMessage(F.main(getName(), "Updated your friend visibility to " + F.elem(visibility.getName()) + ".")));
}
});
}
public void toggleFavourite(Player player, String target)
{
for (FriendStatus status : Get(player).getFriends())
{
if (status.Name.equals(target))
{
runAsync(() ->
{
if (_repository.updateFavourite(player.getName(), status.Name, !status.Favourite))
{
runSync(() -> player.sendMessage(F.main(getName(), F.name(status.Name) + " is " + (status.Favourite ? "no longer" : "now") + " on your favourite friends.")));
}
});
return;
}
}
}
public void onFriendAdd(Player viewer, String friend)
{
if (!_preferenceManager.get(viewer).isActive(Preference.PENDING_FRIEND_REQUESTS))
{
return;
}
TextComponent message = new TextComponent("");
TextComponent text = new TextComponent(F.main(getName(), F.name(friend) + " send you a friend request! "));
TextComponent accept = new TextComponent("ACCEPT");
accept.setColor(ChatColor.GREEN);
accept.setBold(true);
accept.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Accept " + friend + "'s friendship request")
.create()));
accept.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + AddFriend.COMMAND + " " + friend));
TextComponent deny = new TextComponent("DENY");
deny.setColor(ChatColor.RED);
deny.setBold(true);
deny.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Deny " + friend + "'s friendship request")
.create()));
deny.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + DeleteFriend.COMMAND + " " + friend));
TextComponent exclamation = new TextComponent("!");
exclamation.setColor(ChatColor.GRAY);
message.addExtra(text);
message.addExtra(accept);
message.addExtra(" ");
message.addExtra(deny);
message.addExtra(exclamation);
viewer.spigot().sendMessage(message);
}
public void showFriends(Player caller)
{
boolean isStaff = ClientManager.Get(caller).hasPermission(Perm.JOIN_STAFF);
@ -294,7 +453,8 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
// Use a LinkedHashMap so we maintain insertion order
Map<String, TextComponent> messages = new LinkedHashMap<>();
String joinCommand = "/server ", friendCommand = "/" + AddFriend.COMMAND + " ", unfriendCommand = "/" + DeleteFriend.COMMAND + " ", favouriteCommand = "/Hello";
String joinCommand = "/server ", friendCommand = "/" + AddFriend.COMMAND + " ", unfriendCommand = "/" + DeleteFriend.COMMAND + " ";
String favouriteCommand = "/" + FriendFavouriteCommand.COMMAND + " ", visiblityCommand = "/" + FriendVisibilityCommand.COMMAND + " ";
for (FriendStatus friend : friendStatuses)
{
@ -306,12 +466,13 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
}
TextComponent message = new TextComponent("");
boolean online = friend.Online && friend.Visibility != FriendVisibility.INVISIBLE;
boolean canJoin = canJoin(friend.ServerName, isStaff) && friend.Visibility == FriendVisibility.SHOWN;
switch (type)
{
case Accepted:
if (friend.Online)
if (online)
{
if (canJoin)
{
@ -352,7 +513,7 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
{
name.setColor(ChatColor.YELLOW);
}
else if (friend.Online)
else if (online)
{
name.setColor(ChatColor.GREEN);
}
@ -361,15 +522,14 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
name.setColor(ChatColor.GRAY);
}
name.setColor(friend.Online ? ChatColor.GREEN : ChatColor.GRAY);
name.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(friend.Favourite ? ("Add " + friend.Name + " to") : ("Remove " + friend.Name + " from") + " your favourite friends")
name.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder((friend.Favourite ? "Remove " + friend.Name + " from" : "Add " + friend.Name + " to") + " your favourite friends")
.create()));
name.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, favouriteCommand + friend.Name));
message.addExtra(name);
message.addExtra(" - ");
if (friend.Online && friend.Visibility != FriendVisibility.INVISIBLE)
if (online)
{
if (canJoin)
{
@ -379,9 +539,9 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
}
else if (friend.Visibility == FriendVisibility.PRESENCE)
{
TextComponent server = new TextComponent("Hidden");
TextComponent server = new TextComponent(friend.Visibility.getName());
server.setColor(ChatColor.DARK_GREEN);
server.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(friend.Name + " is in hidden mode")
server.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(friend.Name + " is in " + friend.Visibility.getName().toLowerCase() + " mode")
.create()));
message.addExtra(server);
}
@ -460,7 +620,28 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
}
else
{
messages.values().forEach(textComponent -> caller.spigot().sendMessage(textComponent));
messages.values().forEach(message -> caller.spigot().sendMessage(message));
TextComponent message = new TextComponent("");
for (FriendVisibility visibility : FriendVisibility.values())
{
TextComponent vis = new TextComponent(visibility.getName().toUpperCase());
vis.setColor(visibility.getColour());
vis.setBold(true);
vis.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Set your visibility to " + visibility.getName())
.create()));
vis.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, visiblityCommand + visibility));
if (message.getExtra() != null)
{
message.addExtra(" - ");
}
message.addExtra(vis);
}
caller.spigot().sendMessage(message);
}
TextComponent toggle = new TextComponent("");
@ -489,14 +670,12 @@ public class FriendManager extends MiniDbClientPlugin<FriendData>
return false;
}
boolean staff = serverName.startsWith("Staff"), cust = serverName.startsWith("CUST");
if (staff)
if (serverName.startsWith("Staff-"))
{
return isPlayerStaff;
}
return !cust;
return !serverName.startsWith("CUST-");
}
public void updatePlayerStatus(UUID playerUUID, PlayerStatus status)

View File

@ -1,10 +1,30 @@
package mineplex.core.friend;
import net.md_5.bungee.api.ChatColor;
public enum FriendVisibility
{
SHOWN,
PRESENCE,
INVISIBLE
SHOWN("Visible", ChatColor.GREEN),
PRESENCE("Semi-Visible", ChatColor.YELLOW),
INVISIBLE("Invisible", ChatColor.RED);
private final String _name;
private final ChatColor _colour;
FriendVisibility(String name, ChatColor colour)
{
_name = name;
_colour = colour;
}
public String getName()
{
return _name;
}
public ChatColor getColour()
{
return _colour;
}
}

View File

@ -0,0 +1,35 @@
package mineplex.core.friend.command;
import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.FriendManager.Perm;
public class FriendFavouriteCommand extends CommandBase<FriendManager>
{
public static final String COMMAND = "friendfavourite";
public FriendFavouriteCommand(FriendManager plugin)
{
super(plugin, Perm.FRIEND_COMMAND, COMMAND);
}
@Override
public void Execute(final Player caller, final String[] args)
{
if (args.length == 0)
{
return;
}
_commandCenter.GetClientManager().checkPlayerName(caller, args[0], result ->
{
if (result != null)
{
Plugin.toggleFavourite(caller, result);
}
});
}
}

View File

@ -0,0 +1,38 @@
package mineplex.core.friend.command;
import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.common.util.F;
import mineplex.core.friend.FriendManager;
import mineplex.core.friend.FriendManager.Perm;
import mineplex.core.friend.FriendVisibility;
public class FriendVisibilityCommand extends CommandBase<FriendManager>
{
public static final String COMMAND = "friendvisibility";
public FriendVisibilityCommand(FriendManager plugin)
{
super(plugin, Perm.FRIEND_COMMAND, COMMAND);
}
@Override
public void Execute(final Player caller, final String[] args)
{
if (args.length == 0)
{
return;
}
try
{
Plugin.setVisibility(caller, FriendVisibility.valueOf(args[0]));
}
catch (IllegalArgumentException ex)
{
caller.sendMessage(F.main(Plugin.getName(), "Invalid argument."));
}
}
}

View File

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

View File

@ -18,6 +18,8 @@ import mineplex.serverdata.data.DataRepository;
import mineplex.serverdata.data.PlayerStatus;
import mineplex.serverdata.database.DBPool;
import mineplex.serverdata.database.RepositoryBase;
import mineplex.serverdata.database.column.ColumnBoolean;
import mineplex.serverdata.database.column.ColumnInt;
import mineplex.serverdata.database.column.ColumnVarChar;
import mineplex.serverdata.redis.RedisDataRepository;
@ -30,6 +32,9 @@ public class FriendRepository extends RepositoryBase
private static final String ADD_FRIEND_RECORD = "INSERT INTO accountFriend (uuidSource, uuidTarget, status, created) SELECT fA.uuid AS uuidSource, tA.uuid AS uuidTarget, ?, now() FROM accounts as fA LEFT JOIN accounts AS tA ON tA.name = ? WHERE fA.name = ?;";
private static final String UPDATE_MUTUAL_RECORD = "UPDATE accountFriend AS aF INNER JOIN accounts as fA ON aF.uuidSource = fA.uuid INNER JOIN accounts AS tA ON aF.uuidTarget = tA.uuid SET aF.status = ? WHERE tA.name = ? AND fA.name = ?;";
private static final String DELETE_FRIEND_RECORD = "DELETE aF FROM accountFriend AS aF INNER JOIN accounts as fA ON aF.uuidSource = fA.uuid INNER JOIN accounts AS tA ON aF.uuidTarget = tA.uuid WHERE fA.name = ? AND tA.name = ?;";
private static final String INSERT_VISIBILITY = "INSERT INTO accountFriendData VALUES (?,?);";
private static final String UPDATE_VISIBILITY = "UPDATE accountFriendData SET status=? WHERE accountId=?;";
private static final String UPDATE_FAVOURITE = "UPDATE accountFriend AS aF INNER JOIN accounts as fA ON aF.uuidSource = fA.uuid INNER JOIN accounts AS tA ON aF.uuidTarget = tA.uuid SET aF.favourite = ? WHERE tA.name = ? AND fA.name = ?;";
// Repository holding active PlayerStatus data.
private final DataRepository<PlayerStatus> _repository;
@ -170,7 +175,7 @@ public class FriendRepository extends RepositoryBase
{
PlayerStatus status = playerStatuses.get(friend.UUID);
friend.Online = (status != null);
friend.ServerName = (friend.Online) ? status.getServer() : null;
friend.ServerName = friend.Online ? status.getServer() : null;
}
}
@ -186,8 +191,21 @@ public class FriendRepository extends RepositoryBase
}
}
public PlayerStatus getStatus(UUID playerUUID)
public boolean updateVisibility(int accountId, FriendVisibility visibility)
{
return _repository.getElement(playerUUID.toString());
ColumnInt accountIdColumn = new ColumnInt("accountId", accountId), visibilityColumn = new ColumnInt("status", visibility.ordinal());
if (executeUpdate(UPDATE_VISIBILITY, visibilityColumn, accountIdColumn) > 0)
{
return true;
}
return executeInsert(INSERT_VISIBILITY, null, accountIdColumn, visibilityColumn) > 0;
}
public boolean updateFavourite(String caller, String target, boolean favourite)
{
return executeUpdate(UPDATE_FAVOURITE, new ColumnBoolean("favourite", favourite), new ColumnVarChar("name", 100, target), new ColumnVarChar("name", 100, caller)) > 0;
}
}

View File

@ -18,4 +18,9 @@ public class FriendStatus
public FriendStatusType Status;
public FriendVisibility Visibility;
public boolean Favourite;
public boolean isOnline()
{
return Online && Visibility != FriendVisibility.INVISIBLE;
}
}

View File

@ -0,0 +1,25 @@
package mineplex.core.friend.redis;
import mineplex.serverdata.commands.ServerCommand;
public class FriendAddMessage extends ServerCommand
{
private final String _accepter, _target;
public FriendAddMessage(String accepter, String target)
{
_accepter = accepter;
_target = target;
}
public String getAccepter()
{
return _accepter;
}
public String getTarget()
{
return _target;
}
}