replace with toggle + add aliases
This commit is contained in:
@@ -14,6 +14,7 @@ import net.kewwbec.social.command.dm.ChatCommand;
|
||||
import net.kewwbec.social.command.dm.MsgCommand;
|
||||
import net.kewwbec.social.command.dm.ReplyCommand;
|
||||
import net.kewwbec.social.command.friend.FriendCommand;
|
||||
import net.kewwbec.social.command.friend.FriendListCommand;
|
||||
import net.kewwbec.social.command.guild.GuildCommand;
|
||||
import net.kewwbec.social.command.privacy.PrivacyCommand;
|
||||
import net.kewwbec.social.config.SocialConfig;
|
||||
@@ -106,6 +107,13 @@ public final class SocialPlugin extends JavaPlugin {
|
||||
FriendService friends = new FriendService(friendRepo, privacy, bus, config, core.getServerId());
|
||||
GuildService guilds = new GuildService(guildRepo, rankRepo, memberRepo, inviteRepo, privacy, bus, config, core.getServerId());
|
||||
|
||||
core.registerService(net.kewwbec.networkcore.api.guilds.GuildLookup.class, uuid -> {
|
||||
GuildService.GuildContext gc = guilds.contextFor(uuid);
|
||||
if (gc == null) return null;
|
||||
return new net.kewwbec.networkcore.api.guilds.GuildInfo(
|
||||
gc.guild().id(), gc.guild().name(), gc.guild().tag(), gc.rank().name());
|
||||
});
|
||||
|
||||
this.guildChat = new GuildChatService(bus, memberRepo, config, core.getServerId());
|
||||
guildChat.start();
|
||||
|
||||
@@ -123,9 +131,10 @@ public final class SocialPlugin extends JavaPlugin {
|
||||
getEventRegistry().registerGlobal(PlayerDisconnectEvent.class, disconnect::onDisconnect);
|
||||
|
||||
getCommandRegistry().registerCommand(new FriendCommand(friends, resolver));
|
||||
getCommandRegistry().registerCommand(new FriendListCommand(friends));
|
||||
getCommandRegistry().registerCommand(new GuildCommand(guilds, resolver, chatTargets));
|
||||
getCommandRegistry().registerCommand(new MsgCommand(chatTargets, resolver, dms));
|
||||
getCommandRegistry().registerCommand(new ReplyCommand(chatTargets, dms, presence));
|
||||
getCommandRegistry().registerCommand(new MsgCommand(resolver, dms));
|
||||
getCommandRegistry().registerCommand(new ReplyCommand(dms, presence));
|
||||
getCommandRegistry().registerCommand(new ChatCommand(chatTargets));
|
||||
getCommandRegistry().registerCommand(new PrivacyCommand(privacy));
|
||||
getCommandRegistry().registerCommand(new SocialCommand(new SocialUIContext(friends, guilds, privacy)));
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
|
||||
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
|
||||
@@ -12,8 +11,6 @@ import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import net.kewwbec.networkcore.api.PlayerLocation;
|
||||
import net.kewwbec.social.SocialPermissionsNodes;
|
||||
import net.kewwbec.social.service.ChatTargetService;
|
||||
import net.kewwbec.social.service.DmRoutingService;
|
||||
import net.kewwbec.social.util.PlayerResolver;
|
||||
|
||||
@@ -21,28 +18,20 @@ import javax.annotation.Nonnull;
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* /msg <name> [message...]
|
||||
*
|
||||
* If a message body is supplied, sends it once and leaves chat mode alone.
|
||||
* If only a name is supplied, enters one-shot DM mode for the caller - the next chat message they
|
||||
* send is routed as a DM to that target, then the mode reverts to NORMAL.
|
||||
* /msg <name> <message...> - send a DM to an online player.
|
||||
*/
|
||||
public final class MsgCommand extends AbstractPlayerCommand {
|
||||
|
||||
private final ChatTargetService targets;
|
||||
private final PlayerResolver resolver;
|
||||
private final DmRoutingService dms;
|
||||
private final RequiredArg<String> nameArg = withRequiredArg("name", "Recipient", ArgTypes.STRING);
|
||||
private final OptionalArg<String> bodyArg = withOptionalArg("message", "Message body (optional)", ArgTypes.GREEDY_STRING);
|
||||
private final RequiredArg<String> bodyArg = withRequiredArg("message", "Message body", ArgTypes.GREEDY_STRING);
|
||||
|
||||
public MsgCommand(@Nonnull ChatTargetService targets,
|
||||
@Nonnull PlayerResolver resolver,
|
||||
@Nonnull DmRoutingService dms) {
|
||||
super("msg", "Send a one-shot DM (or enter DM mode if no message given)");
|
||||
this.targets = targets;
|
||||
public MsgCommand(@Nonnull PlayerResolver resolver, @Nonnull DmRoutingService dms) {
|
||||
super("msg", "Send a DM to a player");
|
||||
this.resolver = resolver;
|
||||
this.dms = dms;
|
||||
requirePermission(SocialPermissionsNodes.DM_USE);
|
||||
// requirePermission(SocialPermissionsNodes.DM_USE);
|
||||
}
|
||||
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@@ -50,8 +39,9 @@ public final class MsgCommand extends AbstractPlayerCommand {
|
||||
@Override
|
||||
protected void execute(@Nonnull CommandContext ctx, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef sender, @Nonnull World world) {
|
||||
String name = nameArg.get(ctx);
|
||||
if (name == null) {
|
||||
ctx.sendMessage(Message.raw("Usage: /msg <name> [message...]").color(Color.YELLOW));
|
||||
String body = bodyArg.get(ctx);
|
||||
if (name == null || body == null || body.isBlank()) {
|
||||
ctx.sendMessage(Message.raw("Usage: /msg <name> <message...>").color(Color.YELLOW));
|
||||
return;
|
||||
}
|
||||
PlayerLocation target = resolver.resolve(name);
|
||||
@@ -59,18 +49,10 @@ public final class MsgCommand extends AbstractPlayerCommand {
|
||||
ctx.sendMessage(Message.raw(name + " is not online.").color(Color.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
String body = bodyArg.get(ctx);
|
||||
if (body != null && !body.isBlank()) {
|
||||
DmRoutingService.Result r = dms.send(sender, target.username(), body.trim());
|
||||
if (r != DmRoutingService.Result.OK) {
|
||||
ctx.sendMessage(Message.raw(errorText(r, target.username())).color(Color.RED));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
targets.setDm(sender.getUuid(), target.uuid(), target.username());
|
||||
ctx.sendMessage(Message.raw("DM mode -> " + target.username() + ". Type your next chat to send.").color(Color.LIGHT_GRAY));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
|
||||
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
|
||||
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
@@ -12,8 +12,6 @@ import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import net.kewwbec.networkcore.api.PlayerLocation;
|
||||
import net.kewwbec.networkcore.api.PlayerPresence;
|
||||
import net.kewwbec.social.SocialPermissionsNodes;
|
||||
import net.kewwbec.social.service.ChatTargetService;
|
||||
import net.kewwbec.social.service.DmRoutingService;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -21,33 +19,30 @@ import java.awt.Color;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* /r [message...]
|
||||
*
|
||||
* If a body is supplied, sends it once to whoever DMed you last.
|
||||
* If no body, enters one-shot DM mode targeting that player - the next chat message you send goes
|
||||
* to them, then mode reverts to NORMAL.
|
||||
* /r <message...> - send a DM to whoever DMed you last.
|
||||
*/
|
||||
public final class ReplyCommand extends AbstractPlayerCommand {
|
||||
|
||||
private final ChatTargetService targets;
|
||||
private final DmRoutingService dms;
|
||||
private final PlayerPresence presence;
|
||||
private final OptionalArg<String> bodyArg = withOptionalArg("message", "Message body (optional)", ArgTypes.GREEDY_STRING);
|
||||
private final RequiredArg<String> bodyArg = withRequiredArg("message", "Message body", ArgTypes.GREEDY_STRING);
|
||||
|
||||
public ReplyCommand(@Nonnull ChatTargetService targets,
|
||||
@Nonnull DmRoutingService dms,
|
||||
@Nonnull PlayerPresence presence) {
|
||||
super("r", "Reply to your last DM sender (one-shot send, or enter DM mode if no body given)");
|
||||
this.targets = targets;
|
||||
public ReplyCommand(@Nonnull DmRoutingService dms, @Nonnull PlayerPresence presence) {
|
||||
super("r", "Reply to your last DM sender");
|
||||
this.dms = dms;
|
||||
this.presence = presence;
|
||||
requirePermission(SocialPermissionsNodes.DM_USE);
|
||||
// requirePermission(SocialPermissionsNodes.DM_USE);
|
||||
}
|
||||
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@Override
|
||||
protected void execute(@Nonnull CommandContext ctx, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef sender, @Nonnull World world) {
|
||||
String body = bodyArg.get(ctx);
|
||||
if (body == null || body.isBlank()) {
|
||||
ctx.sendMessage(Message.raw("Usage: /r <message...>").color(Color.YELLOW));
|
||||
return;
|
||||
}
|
||||
UUID last = dms.getLastSender(sender.getUuid());
|
||||
if (last == null) {
|
||||
ctx.sendMessage(Message.raw("No one has DMed you recently.").color(Color.RED));
|
||||
@@ -58,18 +53,10 @@ public final class ReplyCommand extends AbstractPlayerCommand {
|
||||
ctx.sendMessage(Message.raw("That person is offline.").color(Color.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
String body = bodyArg.get(ctx);
|
||||
if (body != null && !body.isBlank()) {
|
||||
DmRoutingService.Result r = dms.send(sender, target.username(), body.trim());
|
||||
if (r != DmRoutingService.Result.OK) {
|
||||
ctx.sendMessage(Message.raw(errorText(r, target.username())).color(Color.RED));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
targets.setDm(sender.getUuid(), target.uuid(), target.username());
|
||||
ctx.sendMessage(Message.raw("Reply -> " + target.username() + ". Type your next chat to send.").color(Color.LIGHT_GRAY));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -11,7 +11,11 @@ import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayer
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import net.kewwbec.networkcore.NetworkCore;
|
||||
import net.kewwbec.networkcore.api.PlayerLocation;
|
||||
import net.kewwbec.networkcore.api.PlayerPresence;
|
||||
import net.kewwbec.networkcore.api.ranks.RankInfo;
|
||||
import net.kewwbec.networkcore.api.ranks.RankLookup;
|
||||
import net.kewwbec.social.SocialPermissionsNodes;
|
||||
import net.kewwbec.social.model.Friendship;
|
||||
import net.kewwbec.social.service.FriendService;
|
||||
@@ -27,6 +31,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
|
||||
public FriendCommand(@Nonnull FriendService service, @Nonnull PlayerResolver resolver) {
|
||||
super("friend", "Manage friends (add, accept, reject, remove, list)");
|
||||
addAliases("f");
|
||||
addSubCommand(new Add(service, resolver));
|
||||
addSubCommand(new Accept(service, resolver));
|
||||
addSubCommand(new Reject(service, resolver));
|
||||
@@ -46,7 +51,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
super("add", "Send a friend request");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -83,7 +88,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
super("accept", "Accept an incoming friend request");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -118,7 +123,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
super("reject", "Reject an incoming friend request");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -151,7 +156,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
super("remove", "Remove a friend");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -185,24 +190,78 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
public ListAll(@Nonnull FriendService service) {
|
||||
super("list", "Show your friends");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@Override
|
||||
protected void execute(@Nonnull CommandContext ctx, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef sender, @Nonnull World world) {
|
||||
render(ctx, service, sender);
|
||||
}
|
||||
|
||||
public static void render(@Nonnull CommandContext ctx, @Nonnull FriendService service, @Nonnull PlayerRef sender) {
|
||||
try {
|
||||
List<Friendship> all = service.list(sender.getUuid());
|
||||
if (all.isEmpty()) { ctx.sendMessage(Message.raw("You have no friends yet.").color(Color.GRAY)); return; }
|
||||
ctx.sendMessage(Message.raw("=== Friends (" + all.size() + ") ===").color(Color.YELLOW));
|
||||
|
||||
PlayerPresence presence = NetworkCore.getInstance().getPlayerPresence();
|
||||
RankLookup ranks = NetworkCore.getInstance().getRankLookup();
|
||||
|
||||
int online = 0;
|
||||
for (Friendship f : all) {
|
||||
String other = f.fromUuid().equals(sender.getUuid()) ? f.toName() : f.fromName();
|
||||
ctx.sendMessage(Message.raw("- " + other).color(Color.WHITE));
|
||||
UUID otherUuid = f.fromUuid().equals(sender.getUuid()) ? f.toUuid() : f.fromUuid();
|
||||
if (presence != null && presence.getLocation(otherUuid) != null) online++;
|
||||
}
|
||||
ctx.sendMessage(Message.raw("=== Friends (" + online + "/" + all.size() + " online) ===").color(Color.YELLOW));
|
||||
|
||||
for (Friendship f : all) {
|
||||
UUID otherUuid = f.fromUuid().equals(sender.getUuid()) ? f.toUuid() : f.fromUuid();
|
||||
String otherName = f.fromUuid().equals(sender.getUuid()) ? f.toName() : f.fromName();
|
||||
PlayerLocation loc = (presence == null) ? null : presence.getLocation(otherUuid);
|
||||
String status = (loc == null) ? "offline" : "online on " + loc.serverId();
|
||||
RankInfo rank = (ranks == null) ? null : safeLookup(ranks, otherUuid);
|
||||
ctx.sendMessage(buildRow(rank, otherName, status, loc != null));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ctx.sendMessage(Message.raw("DB error: " + e.getMessage()).color(Color.RED));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static Message buildRow(@javax.annotation.Nullable RankInfo rank,
|
||||
@Nonnull String name,
|
||||
@Nonnull String status,
|
||||
boolean isOnline) {
|
||||
String prefix = (rank == null || rank.prefix() == null || rank.prefix().isBlank())
|
||||
? "" : rank.prefix() + " ";
|
||||
Color rankColor = (rank == null) ? null : parseHex(rank.color());
|
||||
Color statusColor = isOnline ? Color.GREEN : Color.GRAY;
|
||||
|
||||
Message line = Message.empty();
|
||||
if (!prefix.isEmpty()) {
|
||||
Message prefixMsg = Message.raw(prefix);
|
||||
line = line.insert(rankColor == null ? prefixMsg.color(Color.WHITE) : prefixMsg.color(rankColor));
|
||||
}
|
||||
Message nameMsg = Message.raw(name);
|
||||
line = line.insert(rankColor == null ? nameMsg.color(Color.WHITE) : nameMsg.color(rankColor));
|
||||
line = line.insert(Message.raw(" - " + status).color(statusColor));
|
||||
return line;
|
||||
}
|
||||
|
||||
@javax.annotation.Nullable
|
||||
private static RankInfo safeLookup(@Nonnull RankLookup ranks, @Nonnull UUID uuid) {
|
||||
try { return ranks.getPrimaryRank(uuid); }
|
||||
catch (RuntimeException ignored) { return null; }
|
||||
}
|
||||
|
||||
@javax.annotation.Nullable
|
||||
private static Color parseHex(@javax.annotation.Nullable String hex) {
|
||||
if (hex == null || hex.isBlank()) return null;
|
||||
String s = hex.startsWith("#") ? hex.substring(1) : hex;
|
||||
if (s.length() != 6) return null;
|
||||
try { return new Color(Integer.parseInt(s, 16)); }
|
||||
catch (NumberFormatException ignored) { return null; }
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Pending extends AbstractPlayerCommand {
|
||||
@@ -211,7 +270,7 @@ public final class FriendCommand extends AbstractCommandCollection {
|
||||
public Pending(@Nonnull FriendService service) {
|
||||
super("pending", "Show pending friend requests (incoming + outgoing)");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
// requirePermission(SocialPermissionsNodes.FRIEND_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.kewwbec.social.command.friend;
|
||||
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
||||
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.World;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import net.kewwbec.social.service.FriendService;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* /fl - top-level alias of /friend list. Same render logic via {@link FriendCommand.ListAll#render}.
|
||||
*/
|
||||
public final class FriendListCommand extends AbstractPlayerCommand {
|
||||
|
||||
private final FriendService service;
|
||||
|
||||
public FriendListCommand(@Nonnull FriendService service) {
|
||||
super("fl", "Show your friends (alias of /friend list)");
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@Override
|
||||
protected void execute(@Nonnull CommandContext ctx,
|
||||
@Nonnull Store<EntityStore> store,
|
||||
@Nonnull Ref<EntityStore> ref,
|
||||
@Nonnull PlayerRef sender,
|
||||
@Nonnull World world) {
|
||||
FriendCommand.ListAll.render(ctx, service, sender);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
@Nonnull PlayerResolver resolver,
|
||||
@Nonnull ChatTargetService chatTargets) {
|
||||
super("guild", "Guild commands: create, invite, leave, etc.");
|
||||
addAliases("g");
|
||||
addSubCommand(new Create(service));
|
||||
addSubCommand(new Disband(service));
|
||||
addSubCommand(new Invite(service, resolver));
|
||||
@@ -56,7 +57,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Create(@Nonnull GuildService service) {
|
||||
super("create", "Create a new guild");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_CREATE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_CREATE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -80,7 +81,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Disband(@Nonnull GuildService service) {
|
||||
super("disband", "Disband your guild (owner only)");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
@@ -104,7 +105,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
super("invite", "Invite a player to your guild");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -136,7 +137,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Accept(@Nonnull GuildService service) {
|
||||
super("accept", "Accept a pending guild invite");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -162,7 +163,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Leave(@Nonnull GuildService service) {
|
||||
super("leave", "Leave your current guild");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
@@ -186,7 +187,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
super("kick", "Kick a guild member");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -221,7 +222,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
super("promote", "Promote a member to a higher rank");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -258,7 +259,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
super("demote", "Demote a member to a lower rank");
|
||||
this.service = service;
|
||||
this.resolver = resolver;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -292,7 +293,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Motd(@Nonnull GuildService service) {
|
||||
super("motd", "Set the guild MOTD");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -315,7 +316,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public Info(@Nonnull GuildService service) {
|
||||
super("info", "Show your guild");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
@@ -334,7 +335,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public RosterCmd(@Nonnull GuildService service) {
|
||||
super("roster", "Show all guild members");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
@@ -358,7 +359,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
public RanksCmd(@Nonnull GuildService service) {
|
||||
super("ranks", "Show your guild's ranks");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
@@ -388,7 +389,7 @@ public final class GuildCommand extends AbstractCommandCollection {
|
||||
super("chat", "Toggle guild chat mode (your chat goes to your guild)");
|
||||
this.service = service;
|
||||
this.chatTargets = chatTargets;
|
||||
requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
// requirePermission(SocialPermissionsNodes.GUILD_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
@Override
|
||||
|
||||
@@ -36,7 +36,7 @@ public final class PrivacyCommand extends AbstractCommandCollection {
|
||||
public Show(@Nonnull PrivacyService service) {
|
||||
super("show", "Show your current privacy settings");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.PRIVACY_USE);
|
||||
// requirePermission(SocialPermissionsNodes.PRIVACY_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
@@ -63,7 +63,7 @@ public final class PrivacyCommand extends AbstractCommandCollection {
|
||||
public SetCmd(@Nonnull PrivacyService service) {
|
||||
super("set", "Change one of your privacy settings");
|
||||
this.service = service;
|
||||
requirePermission(SocialPermissionsNodes.PRIVACY_USE);
|
||||
// requirePermission(SocialPermissionsNodes.PRIVACY_USE);
|
||||
}
|
||||
@Override protected boolean canGeneratePermission() { return false; }
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@ import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.Message;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.Universe;
|
||||
import net.kewwbec.networkcore.NetworkCore;
|
||||
import net.kewwbec.networkcore.api.MessageBus;
|
||||
import net.kewwbec.networkcore.api.PlayerLocation;
|
||||
import net.kewwbec.networkcore.api.PlayerPresence;
|
||||
import net.kewwbec.networkcore.api.ranks.RankInfo;
|
||||
import net.kewwbec.networkcore.api.ranks.RankLookup;
|
||||
import net.kewwbec.social.config.SocialConfig;
|
||||
import net.kewwbec.social.model.PrivacyKey;
|
||||
import net.kewwbec.social.service.payload.DmPayload;
|
||||
@@ -21,10 +24,10 @@ import java.util.logging.Level;
|
||||
/**
|
||||
* Cross-server DM routing.
|
||||
*
|
||||
* Sender side: validate privacy, then publish a DmPayload on the dm channel.
|
||||
* Each server's subscription checks whether the recipient is on its local universe; if so, it
|
||||
* delivers the message; otherwise it ignores. This means recipient privacy is checked on the
|
||||
* sender's server.
|
||||
* Each delivered/echoed line is composed as: [optional colored rank prefix] [from/to NAME] body.
|
||||
* The rank prefix uses the SENDER's primary rank (so the recipient sees who, with rank, sent it,
|
||||
* and the sender's echo also shows their own prefix as confirmation). If no RankLookup service is
|
||||
* registered (e.g. Ranks plugin not installed) or the sender has no rank, the prefix is omitted.
|
||||
*/
|
||||
public final class DmRoutingService {
|
||||
|
||||
@@ -90,12 +93,12 @@ public final class DmRoutingService {
|
||||
body, serverId);
|
||||
bus.publish(config.channels.dm, p);
|
||||
|
||||
// Local echo to the sender
|
||||
Universe u = Universe.get();
|
||||
if (u != null) {
|
||||
RankInfo recipientRank = lookupRank(target.uuid());
|
||||
for (PlayerRef ref : u.getPlayers()) {
|
||||
if (ref.getUuid().equals(sender.getUuid())) {
|
||||
ref.sendMessage(Message.raw(formatTo(target.username(), body)).color(Color.LIGHT_GRAY));
|
||||
ref.sendMessage(buildLine("To", recipientRank, target.username(), body));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -126,19 +129,56 @@ public final class DmRoutingService {
|
||||
}
|
||||
for (PlayerRef ref : u.getPlayers()) {
|
||||
if (!ref.getUuid().equals(recipientUuid)) continue;
|
||||
ref.sendMessage(Message.raw(formatFrom(p.senderName, p.body)).color(Color.WHITE));
|
||||
RankInfo senderRank = lookupRank(senderUuid);
|
||||
ref.sendMessage(buildLine("From", senderRank, p.senderName, p.body));
|
||||
lastSender.put(recipientUuid, senderUuid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String formatTo(@Nonnull String name, @Nonnull String body) {
|
||||
return config.dms.prefix_to.replace("{name}", name) + " " + body;
|
||||
@Nullable
|
||||
private RankInfo lookupRank(@Nonnull UUID uuid) {
|
||||
try {
|
||||
RankLookup ranks = NetworkCore.getInstance().getRankLookup();
|
||||
return ranks == null ? null : ranks.getPrimaryRank(uuid);
|
||||
} catch (RuntimeException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Color GOLD = new Color(0xFFAA00);
|
||||
|
||||
@Nonnull
|
||||
private String formatFrom(@Nonnull String name, @Nonnull String body) {
|
||||
return config.dms.prefix_from.replace("{name}", name) + " " + body;
|
||||
private static Message buildLine(@Nonnull String leadWord,
|
||||
@Nullable RankInfo otherRank,
|
||||
@Nonnull String otherName,
|
||||
@Nonnull String body) {
|
||||
String prefix = (otherRank == null || otherRank.prefix() == null || otherRank.prefix().isBlank())
|
||||
? "" : otherRank.prefix();
|
||||
Color nameColor = (otherRank == null) ? null : parseHex(otherRank.color());
|
||||
|
||||
Message line = Message.empty()
|
||||
.insert(Message.raw(leadWord + " ").color(GOLD));
|
||||
if (!prefix.isEmpty()) {
|
||||
Message prefixMsg = Message.raw(prefix + " ");
|
||||
line = line.insert(nameColor == null ? prefixMsg : prefixMsg.color(nameColor));
|
||||
}
|
||||
Message nameMsg = Message.raw(otherName);
|
||||
line = line.insert(nameColor == null ? nameMsg : nameMsg.color(nameColor));
|
||||
line = line.insert(Message.raw(": ").color(GOLD));
|
||||
line = line.insert(Message.raw(body).color(Color.WHITE));
|
||||
return line;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Color parseHex(@Nullable String hex) {
|
||||
if (hex == null || hex.isBlank()) return null;
|
||||
String s = hex.startsWith("#") ? hex.substring(1) : hex;
|
||||
if (s.length() != 6) return null;
|
||||
try {
|
||||
return new Color(Integer.parseInt(s, 16));
|
||||
} catch (NumberFormatException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import net.kewwbec.networkcore.NetworkCore;
|
||||
import net.kewwbec.networkcore.api.PlayerLocation;
|
||||
import net.kewwbec.networkcore.api.PlayerPresence;
|
||||
import net.kewwbec.networkcore.api.ranks.RankInfo;
|
||||
import net.kewwbec.networkcore.api.ranks.RankLookup;
|
||||
import net.kewwbec.social.model.Friendship;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -99,13 +101,15 @@ public final class FriendsListPage {
|
||||
return sb.toString();
|
||||
}
|
||||
PlayerPresence presence = NetworkCore.getInstance().getPlayerPresence();
|
||||
RankLookup ranks = NetworkCore.getInstance().getRankLookup();
|
||||
int i = 0;
|
||||
for (Friendship f : friends) {
|
||||
UUID otherUuid = f.fromUuid().equals(playerRef.getUuid()) ? f.toUuid() : f.fromUuid();
|
||||
String otherName = f.fromUuid().equals(playerRef.getUuid()) ? f.toName() : f.fromName();
|
||||
PlayerLocation loc = (presence == null) ? null : presence.getLocation(otherUuid);
|
||||
String status = (loc == null) ? "offline" : "on " + loc.serverId();
|
||||
sb.append("<p>").append(escape(otherName)).append(" (").append(escape(status)).append(")</p>");
|
||||
String status = (loc == null) ? "offline" : "online on " + loc.serverId();
|
||||
RankInfo rank = (ranks == null) ? null : safeLookup(ranks, otherUuid);
|
||||
sb.append(renderNameRow(rank, otherName, status));
|
||||
String removeId = "removeFriend" + i;
|
||||
sb.append("<button id=\"").append(removeId).append("\" class=\"secondary-button\">Remove ").append(escape(otherName)).append("</button>");
|
||||
UUID finalOther = otherUuid;
|
||||
@@ -118,6 +122,21 @@ public final class FriendsListPage {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static String renderNameRow(@javax.annotation.Nullable RankInfo rank, @Nonnull String name, @Nonnull String status) {
|
||||
String prefix = (rank == null || rank.prefix() == null || rank.prefix().isBlank()) ? "" : rank.prefix() + " ";
|
||||
String hex = (rank == null) ? null : rank.color();
|
||||
String styleAttr = (hex == null || hex.isBlank()) ? "" : " style=\"color: " + escape(hex) + ";\"";
|
||||
return "<p" + styleAttr + ">" + escape(prefix) + escape(name) + "</p>"
|
||||
+ "<p>" + escape(status) + "</p>";
|
||||
}
|
||||
|
||||
@javax.annotation.Nullable
|
||||
private static RankInfo safeLookup(@Nonnull RankLookup ranks, @Nonnull UUID uuid) {
|
||||
try { return ranks.getPrimaryRank(uuid); }
|
||||
catch (RuntimeException e) { return null; }
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String renderIncoming(@Nonnull List<RowAction> actions) throws SQLException {
|
||||
List<Friendship> incoming = ctx.friends.incomingPending(playerRef.getUuid());
|
||||
@@ -127,11 +146,13 @@ public final class FriendsListPage {
|
||||
sb.append("<p>No one has sent you a friend request.</p>");
|
||||
return sb.toString();
|
||||
}
|
||||
RankLookup ranks = NetworkCore.getInstance().getRankLookup();
|
||||
int i = 0;
|
||||
for (Friendship f : incoming) {
|
||||
UUID fromUuid = f.fromUuid();
|
||||
String fromName = f.fromName();
|
||||
sb.append("<p>from ").append(escape(fromName)).append("</p>");
|
||||
RankInfo rank = (ranks == null) ? null : safeLookup(ranks, fromUuid);
|
||||
sb.append(renderNameRow(rank, fromName, "wants to be your friend"));
|
||||
String acceptId = "accept" + i;
|
||||
String rejectId = "reject" + i;
|
||||
sb.append("<button id=\"").append(acceptId).append("\">Accept ").append(escape(fromName)).append("</button>");
|
||||
@@ -156,11 +177,13 @@ public final class FriendsListPage {
|
||||
sb.append("<p>No outgoing requests.</p>");
|
||||
return sb.toString();
|
||||
}
|
||||
RankLookup ranks = NetworkCore.getInstance().getRankLookup();
|
||||
int i = 0;
|
||||
for (Friendship f : outgoing) {
|
||||
UUID toUuid = f.toUuid();
|
||||
String toName = f.toName();
|
||||
sb.append("<p>to ").append(escape(toName)).append("</p>");
|
||||
RankInfo rank = (ranks == null) ? null : safeLookup(ranks, toUuid);
|
||||
sb.append(renderNameRow(rank, toName, "waiting for them to accept"));
|
||||
String cancelId = "cancel" + i;
|
||||
sb.append("<button id=\"").append(cancelId).append("\" class=\"secondary-button\">Cancel request to ").append(escape(toName)).append("</button>");
|
||||
actions.add(new RowAction(cancelId, () ->
|
||||
|
||||
Reference in New Issue
Block a user