[WIP] Current progress

This commit is contained in:
Focusvity 2024-03-06 22:28:16 +11:00
parent da2260586d
commit 8dc456c43e
No known key found for this signature in database
GPG Key ID: FC3BE6D52CCDB38F
37 changed files with 1677 additions and 1120 deletions

View File

@ -2,21 +2,22 @@ package dev.plex;
import dev.plex.command.GuildCommand; import dev.plex.command.GuildCommand;
import dev.plex.config.ModuleConfig; import dev.plex.config.ModuleConfig;
import dev.plex.data.SQLGuildManager; import dev.plex.data.GuildData;
import dev.plex.data.SQLManager; import dev.plex.data.MemberData;
import dev.plex.guild.GuildHolder; import dev.plex.listener.ChatListener;
import dev.plex.listener.JoinListener;
import dev.plex.module.PlexModule; import dev.plex.module.PlexModule;
import dev.plex.util.PlexLog; import dev.plex.util.PlexLog;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit;
@Getter @Getter
public class Guilds extends PlexModule public class Guilds extends PlexModule
{ {
private static Guilds module; private static Guilds module;
private final GuildHolder guildHolder = new GuildHolder(); private final SQLManager sqlManager = new SQLManager();
private final GuildData guildData = new GuildData();
private SQLGuildManager sqlGuildManager; private final MemberData memberData = new MemberData();
private ModuleConfig config; private ModuleConfig config;
@Override @Override
@ -30,38 +31,37 @@ public class Guilds extends PlexModule
@Override @Override
public void enable() public void enable()
{ {
SQLManager.makeTables();
sqlGuildManager = new SQLGuildManager();
sqlGuildManager.getGuilds().whenComplete((guilds, throwable) ->
{
PlexLog.debug("Finished loading {0} guilds", guilds.size());
guilds.forEach(guildHolder::addGuild);
this.registerCommand(new GuildCommand());
});
//Plex.get().setChat(new ChatHandlerImpl());
addDefaultMessage("guildsHelpCommand", "<gradient:gold:yellow>======</gradient>Guild Menu<gradient:gold:yellow>======</gradient><newline><newline>{0}", "0 - The commands list"); addDefaultMessage("guildsHelpCommand", "<gradient:gold:yellow>======</gradient>Guild Menu<gradient:gold:yellow>======</gradient><newline><newline>{0}", "0 - The commands list");
addDefaultMessage("guildsCommandDisplay", "<gold>{0} <yellow>{1}", "0 - The command name", "1 - The command description"); addDefaultMessage("guildsCommandDisplay", "<gold>{0} <yellow>{1}", "0 - The command name", "1 - The command description");
addDefaultMessage("guildCommandNotFound", "<red>'<gold>{0}</gold>'<red> is not a valid sub command!", "0 - The sub command"); addDefaultMessage("guildCommandNotFound", "<red>'<gold>{0}</gold>'<red> is not a valid sub command!", "0 - The sub command");
addDefaultMessage("guildNotFound", "<red>You're currently not a part of a guild!"); addDefaultMessage("guildNotFound", "<red>You're currently not a part of a guild!");
addDefaultMessage("guildNotExist", "<red>A guild doesn't exist with the name '<gold>{0}</gold>'", "0 - Name used to find a guild");
addDefaultMessage("guildInThis", "<red>You're currently a part of this guild!"); addDefaultMessage("guildInThis", "<red>You're currently a part of this guild!");
addDefaultMessage("alreadyInGuild", "<red>You're currently in a guild. Please do <gold>/guild leave<red> if you're a member, or if you're an owner with members, <gold>/guild promote <player><red> then <gold>/guild leave<red>, or just an owner, <gold>/guild disband<red>."); addDefaultMessage("alreadyInGuild", "<red>You're currently in a guild. Please do <gold>/guild leave<red> if you're a member, or if you're an owner with members, <gold>/guild promote <player><red> then <gold>/guild leave<red>, or just an owner, <gold>/guild disband<red>.");
addDefaultMessage("guildNotOwner", "<red>You're not the owner of this guild!"); addDefaultMessage("guildNotOwner", "<red>You're not the owner of this guild!");
addDefaultMessage("guildNotMod", "<red>You're not a moderator of this guild!");
addDefaultMessage("guildMemberNotFound", "<red>This guild member could not be found!"); addDefaultMessage("guildMemberNotFound", "<red>This guild member could not be found!");
addDefaultMessage("guildAlphanumericName", "<red>Guild names may only be alphanumeric!");
addDefaultMessage("guildOwnerSet", "<green>You have successfully promoted <dark_green>{0}<green> to be the new guild owner. You have been set to a default guild member."); addDefaultMessage("guildOwnerSet", "<green>You have successfully promoted <dark_green>{0}<green> to be the new guild owner. You have been set to a default guild member.");
addDefaultMessage("guildPrefixSet", "<green>You have changed the guild prefix to '<gold>{0}</gold><green>'", "0 - The new prefix"); addDefaultMessage("guildPrefixSet", "<green>You have changed the guild prefix to '<gold>{0}</gold><green>'", "0 - The new prefix");
addDefaultMessage("guildPrefixCleared", "<green>Your guild's prefix has been cleared."); addDefaultMessage("guildPrefixCleared", "<green>Your guild's prefix has been cleared.");
addDefaultMessage("guildMotdSet", "<green>You have changed the guild prefix to '<gold>{0}</gold><green>'", "0 - The new MOTD");
addDefaultMessage("guildMotdCleared", "<green>Your guild's MOTD has been cleared.");
addDefaultMessage("guildMotdExceededLimit", "<red>The MOTD character limit is 256 characters!");
addDefaultMessage("guildWarpAlphanumeric", "<red>Warp names may only contain alphabetical and/or numerical characters."); addDefaultMessage("guildWarpAlphanumeric", "<red>Warp names may only contain alphabetical and/or numerical characters.");
addDefaultMessage("guildWarpExists", "<red>'<gold>{0}</gold>'<red> is already an existing warp!", "0 - The warp name"); addDefaultMessage("guildWarpExists", "<red>'<gold>{0}</gold>'<red> is already an existing warp!", "0 - The warp name");
addDefaultMessage("guildWarpNotFound", "<red>'<gold>{0}</gold>'<red> is not a valid warp!", "0 - The warp name"); addDefaultMessage("guildWarpNotFound", "<red>'<gold>{0}</gold>'<red> is not a valid warp!", "0 - The warp name");
addDefaultMessage("guildWarpCreated", "<green>You have created a warp called '<dark_green>{0}</dark_green><green>'", "0 - The warp name"); addDefaultMessage("guildWarpCreated", "<green>You have created a warp called '<dark_green>{0}</dark_green><green>'", "0 - The warp name");
addDefaultMessage("guildWarpSuccess", "<green>You have warped to '<dark_green>{0}<green>'", "0 - The warp name");
addDefaultMessage("guildWarpRemoved", "<green>You have removed the '<dark_green>{0}<green>' warp!", "0 - The warp name");
addDefaultMessage("guildHomeRemoved", "<green>You have removed the guild's home!"); addDefaultMessage("guildHomeRemoved", "<green>You have removed the guild's home!");
addDefaultMessage("guildHomeSet", "<green>You have changed the guild's home!"); addDefaultMessage("guildHomeSet", "<green>You have changed the guild's home!");
addDefaultMessage("guildHomeNotFound", "<red>This guild currently has no home set."); addDefaultMessage("guildHomeNotFound", "<red>This guild currently has no home set.");
addDefaultMessage("guildHomeTeleport", "<green>You have teleported to the guild's home!");
addDefaultMessage("guildChatMessage", "<blue>[GUILD] <aqua>{0} <yellow>{1}", "0 - The player name", "1 - The message"); addDefaultMessage("guildChatMessage", "<blue>[GUILD] <aqua>{0} <yellow>{1}", "0 - The player name", "1 - The message");
addDefaultMessage("guildChatToggled", "<green>Your chat has been toggled {0}", "0 - On / Off"); addDefaultMessage("guildChatToggled", "<green>Your chat has been toggled {0}", "0 - On / Off");
@ -74,20 +74,35 @@ public class Guilds extends PlexModule
addDefaultMessage("guildInviteReceived", "<gold>You have received an invite from <yellow>{0}<gold> for the guild <yellow>{1}<newline><newline><green><bold><click:run_command:/guild invite accept {1}>[ACCEPT]<newline><newline><!bold><gold>You may also run <yellow>/guild invite accept {1}<gold> to accept this invite. It will expire in 5 minutes", "0 - The inviter", "1 - The guild name"); addDefaultMessage("guildInviteReceived", "<gold>You have received an invite from <yellow>{0}<gold> for the guild <yellow>{1}<newline><newline><green><bold><click:run_command:/guild invite accept {1}>[ACCEPT]<newline><newline><!bold><gold>You may also run <yellow>/guild invite accept {1}<gold> to accept this invite. It will expire in 5 minutes", "0 - The inviter", "1 - The guild name");
addDefaultMessage("guildMemberJoined", "<green>{0} has joined the guild!", "0 - The player who joined"); addDefaultMessage("guildMemberJoined", "<green>{0} has joined the guild!", "0 - The player who joined");
addDefaultMessage("guildMemberLeft", "<green>{0} has left the guild!", "0 - The player who left"); addDefaultMessage("guildMemberLeft", "<green>{0} has left the guild!", "0 - The player who left");
addDefaultMessage("guildLeft", "<green>Successfully left the guild");
addDefaultMessage("guildDisbandNeeded", "<red>You need to disband your guild using <gold>/guild disband<red> or promote a new owner using <gold>/guild owner <player>"); addDefaultMessage("guildDisbandNeeded", "<red>You need to disband your guild using <gold>/guild disband<red> or promote a new owner using <gold>/guild owner <player>");
addDefaultMessage("guildDisbanded", "<green>Your guild has been disbanded.");
addDefaultMessage("guildAutoDisbanded", "<green>Auto-disbanding your guild since there were no members"); addDefaultMessage("guildAutoDisbanded", "<green>Auto-disbanding your guild since there were no members");
addDefaultMessage("guildActionConfirmation", "<gold>Are you sure you want to {0}? Type <yellow>/guild {0}</yellow> to confirm.", "0 - Action to confirm");
sqlManager.createTables();
sqlManager.getMembers().forEach(memberData::addMember);
sqlManager.getGuilds().forEach(guildData::addGuild);
PlexLog.log("GUILD SIZE: {0}", guildData.getGuilds().size());
registerListener(new JoinListener());
registerListener(new ChatListener());
registerCommand(new GuildCommand());
} }
@Override @Override
public void disable() public void disable()
{ {
// Unregistering listeners / commands is handled by Plex guildData.getGuilds().forEach(sqlManager::updateGuild);
this.getGuildHolder().getGuilds().forEach(sqlGuildManager::updateGuild); memberData.getMembers().forEach(sqlManager::updateMember);
//this.getPlex().setChat(new ChatListener.PlexChatRenderer());
} }
public static Guilds get() public static Guilds get()
{ {
return module; return module;
} }
public static void logException(Throwable t)
{
Bukkit.getScheduler().runTask(get().getPlex(), () -> t.printStackTrace());
}
} }

View File

@ -0,0 +1,474 @@
package dev.plex;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import dev.plex.guild.Guild;
import dev.plex.guild.GuildMember;
import dev.plex.guild.GuildRank;
import dev.plex.guild.GuildWarp;
import dev.plex.util.PlexLog;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class SQLManager
{
private final Gson GSON = new Gson();
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final String SELECT_ALL_GUILDS = "select * from guild";
private final String INSERT_GUILD = "insert into guild (uuid, name, owner_id) values (?, ?, ?)";
private final String UPDATE_GUILD = "update guild set name = ?, display_name = ?, owner_id = ?, prefix = ?, prefix_enabled = ?, home = ?, motd = ?, privacy = ?, members = ?, moderators = ?, default_rank = ? where uuid = ?";
private final String DELETE_GUILD_UUID = "delete from guild where uuid = ?";
private final String DELETE_GUILD_OWNER = "delete from guild where owner_id = ?";
private final String UPDATE_MEMBER = "update member set chat = ?, prefix = ? where player_uuid = ?";
private final String[] CREATE_TABLES = new String[]
{
"""
create table if not exists guild (
uuid varchar(46) primary key,
name text not null,
display_name varchar,
owner_id int not null,
created_at datetime not null default current_timestamp,
prefix varchar(3000),
prefix_enabled boolean default false,
home varchar,
motd varchar,
privacy not null default 'PUBLIC',
members varchar,
moderators varchar,
default_rank text
);""",
"""
create table if not exists member (
id int auto_increment primary key,
player_uuid varchar(46) not null,
chat boolean default false,
prefix boolean default true
);""",
"""
create table if not exists rank (
name text not null,
members varchar,
guild_uuid varchar(46) not null
);""",
"""
create table if not exists warp (
name text not null,
location text not null,
guild_uuid varchar(46) not null
);
"""
};
public void createTables()
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
Arrays.stream(CREATE_TABLES).forEach(table ->
{
try
{
connection.prepareStatement(table).execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
}
public CompletableFuture<GuildMember> insertMember(GuildMember member)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("insert into member (player_uuid) values (?)");
statement.setString(1, member.getUuid().toString());
statement.execute();
PreparedStatement getId = connection.prepareStatement("select id from member where player_uuid = ?");
getId.setString(1, member.getUuid().toString());
ResultSet set = getId.executeQuery();
if (set.next())
{
member.setId(set.getInt("id"));
}
else
{
throw new RuntimeException("Missing member id for %s".formatted(member.getPlayer().getName()));
}
return member;
}
catch (SQLException ex)
{
Guilds.logException(ex);
return null;
}
});
}
public void insertGuild(Guild guild)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(INSERT_GUILD);
statement.setString(1, guild.getUuid().toString());
statement.setString(2, guild.getName());
statement.setInt(3, guild.getOwner().getId());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void insertWarp(Guild guild, GuildWarp warp)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("insert into warp values (?, ?, ?)");
statement.setString(1, warp.getName());
String location = GSON.toJson(warp.getLocation().serialize(), new TypeToken<Map<String, Object>>()
{
}.getType());
statement.setString(2, location);
statement.setString(3, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void deleteWarp(Guild guild, GuildWarp warp)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("delete from warp where name = ? and guild_uuid = ?");
statement.setString(1, warp.getName());
statement.setString(2, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void insertRank(Guild guild, GuildRank rank)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("insert into rank (name, guild_uuid) values (?, ?)");
statement.setString(1, rank.getName());
statement.setString(2, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void deleteRank(Guild guild, GuildRank rank)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("delete from rank where name = ? and guild_uuid = ?");
statement.setString(1, rank.getName());
statement.setString(2, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void updateDefaultRank(Guild guild, GuildRank rank)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("update guild set default_rank = ? where uuid = ?");
statement.setString(1, rank.getName());
statement.setString(2, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void updateGuild(Guild guild)
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(UPDATE_GUILD);
statement.setString(1, guild.getName());
statement.setString(2, guild.getDisplayName());
statement.setInt(3, guild.getOwner().getId());
statement.setString(4, guild.getPrefix());
statement.setBoolean(5, guild.isPrefixEnabled());
if (guild.getHome() != null)
{
String home = GSON.toJson(guild.getHome().serialize(), new TypeToken<Map<String, Object>>()
{
}.getType());
statement.setString(6, home);
}
statement.setString(7, guild.getMotd());
statement.setString(8, guild.getPrivacy().name());
String members = GSON.toJson(guild.getMemberIDs(), new TypeToken<List<Integer>>()
{
}.getType());
statement.setString(9, members);
String moderators = GSON.toJson(guild.getModeratorIDs(), new TypeToken<List<Integer>>()
{
}.getType());
statement.setString(10, moderators);
if (guild.getDefaultRank() != null)
{
statement.setString(11, guild.getDefaultRank().getName());
}
else
{
statement.setString(11, null);
}
statement.setString(12, guild.getUuid().toString());
statement.executeUpdate();
guild.getRanks().forEach(rank ->
{
try
{
PreparedStatement rankStatement = connection.prepareStatement("update rank set members = ? where guild_uuid = ? and name = ?");
String rankMembers = GSON.toJson(rank.getMemberIDs(), new TypeToken<List<Integer>>()
{
}.getType());
rankStatement.setString(1, rankMembers);
rankStatement.setString(2, guild.getUuid().toString());
rankStatement.setString(3, rank.getName());
rankStatement.executeUpdate();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
}
public void updateMember(GuildMember member)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(UPDATE_MEMBER);
statement.setBoolean(1, member.isChat());
statement.setBoolean(2, member.isPrefix());
statement.setString(3, member.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void deleteGuild(Guild guild)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(DELETE_GUILD_UUID);
statement.setString(1, guild.getUuid().toString());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public void deleteGuild(Player player)
{
CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(DELETE_GUILD_OWNER);
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
statement.setInt(1, member.getId());
statement.execute();
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
});
}
public List<Guild> getGuilds()
{
List<Guild> guilds = Lists.newArrayList();
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement guildStatement = connection.prepareStatement(SELECT_ALL_GUILDS);
PreparedStatement rankStatement = connection.prepareStatement("select * from rank where guild_uuid = ?");
ResultSet set = guildStatement.executeQuery();
while (set.next())
{
Guild guild = new Guild(UUID.fromString(set.getString("uuid")), DATE_FORMAT.parse(set.getString("created_at")));
guild.setName(set.getString("name"));
guild.setDisplayName(set.getString("display_name"));
guild.setOwner(Guilds.get().getMemberData().getMemberByID(set.getInt("owner_id")).orElseThrow());
List<Integer> memberIds = GSON.fromJson(set.getString("members"), new TypeToken<List<Integer>>()
{
}.getType());
if (memberIds != null)
{
guild.setMembers(memberIds.stream().map(i -> Guilds.get().getMemberData().getMemberByID(i).orElseThrow()).toList());
}
List<Integer> moderatorIds = GSON.fromJson(set.getString("moderators"), new TypeToken<List<Integer>>()
{
}.getType());
if (moderatorIds != null)
{
guild.setModerators(moderatorIds.stream().map(i -> Guilds.get().getMemberData().getMemberByID(i).orElseThrow()).collect(Collectors.toList()));
}
List<GuildRank> ranks = Lists.newArrayList();
rankStatement.setString(1, guild.getUuid().toString());
ResultSet rankSet = rankStatement.executeQuery();
while (rankSet.next())
{
GuildRank rank = new GuildRank(rankSet.getString("name"));
if (rank.getName().equals(set.getString("default_rank")))
{
guild.setDefaultRank(rank);
break;
}
List<Integer> rankMemberIds = GSON.fromJson(rankSet.getString("members"), new TypeToken<List<Integer>>()
{
}.getType());
if (rankMemberIds != null)
{
rank.setMembers(rankMemberIds.stream().map(i -> Guilds.get().getMemberData().getMemberByID(i).orElseThrow()).collect(Collectors.toList()));
}
ranks.add(rank);
}
guild.setRanks(ranks);
List<GuildWarp> warps = Lists.newArrayList();
PreparedStatement warpStatement = connection.prepareStatement("select * from warp where guild_uuid = ?");
warpStatement.setString(1, guild.getUuid().toString());
ResultSet warpSet = warpStatement.executeQuery();
while (warpSet.next())
{
GuildWarp warp = new GuildWarp(warpSet.getString("name"),
Location.deserialize(GSON.fromJson(warpSet.getString("location"),
new TypeToken<Map<String, Object>>()
{
}.getType())));
warps.add(warp);
}
guild.setWarps(warps);
guild.setPrefix(set.getString("prefix"));
guild.setPrefixEnabled(set.getBoolean("prefix_enabled"));
guild.setMotd(set.getString("motd"));
Map<String, Object> serializedLocation = GSON.fromJson(set.getString("home"), new TypeToken<Map<String, Object>>()
{
}.getType());
if (serializedLocation != null)
{
guild.setHome(Location.deserialize(serializedLocation));
}
guild.setPrivacy(Guild.Privacy.valueOf(set.getString("privacy")));
guilds.add(guild);
}
}
catch (SQLException | ParseException ex)
{
Guilds.logException(ex);
}
return guilds;
}
public List<GuildMember> getMembers()
{
List<GuildMember> members = Lists.newArrayList();
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement("select * from member");
ResultSet set = statement.executeQuery();
while (set.next())
{
GuildMember member = new GuildMember(UUID.fromString(set.getString("player_uuid")));
member.setId(set.getInt("id"));
member.setChat(set.getBoolean("chat"));
member.setPrefix(set.getBoolean("prefix"));
members.add(member);
}
}
catch (SQLException ex)
{
Guilds.logException(ex);
}
return members;
}
}

View File

@ -1,165 +1,117 @@
package dev.plex.command; package dev.plex.command;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.command.sub.*;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.command.sub.*;
import dev.plex.util.GuildUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
@CommandParameters(name = "guild", description = "Guild menu", aliases = "guilds,g") @CommandParameters(name = "guild", description = "Main guild command", aliases = "guilds,g")
@CommandPermissions(permission = "plex.guilds.guild") @CommandPermissions(permission = "plex.guilds.guild")
public class GuildCommand extends PlexCommand public class GuildCommand extends PlexCommand
{ {
private final List<PlexCommand> subCommands = Lists.newArrayList(); private final List<SubCommand> subcommands = Lists.newArrayList();
public GuildCommand() public GuildCommand()
{ {
try try
{ {
this.registerSubCommand(new CreateSubCommand()); subcommands.add(new CreateSubCommand());
this.registerSubCommand(new InfoSubCommand()); subcommands.add(new DeleteWarpSubCommand());
this.registerSubCommand(new PrefixSubCommand()); subcommands.add(new DisbandSubCommand());
this.registerSubCommand(new SetWarpSubCommand()); subcommands.add(new HomeSubCommand());
this.registerSubCommand(new WarpSubCommand()); subcommands.add(new InfoSubCommand());
this.registerSubCommand(new WarpListSubCommand()); subcommands.add(new MotdSubCommand());
this.registerSubCommand(new ChatSubCommand()); subcommands.add(new PrefixSubCommand());
this.registerSubCommand(new SetHomeSubCommand()); subcommands.add(new SetHomeSubCommand());
this.registerSubCommand(new HomeSubCommand()); subcommands.add(new SetOwnerSubCommand());
this.registerSubCommand(new OwnerSubCommand()); subcommands.add(new SetWarpSubCommand());
this.registerSubCommand(new InviteSubCommand()); subcommands.add(new WarpSubCommand());
} }
catch (Exception e) catch (Exception ex)
{ {
GuildUtil.throwExceptionSync(e); Guilds.logException(ex);
} }
} }
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) protected Component execute(@NotNull CommandSender sender, @Nullable Player player, @NotNull String[] args)
{ {
if (args.length == 0) if (args.length == 0)
{ {
return getSubs(); return getSubs();
} }
if (args[0].equalsIgnoreCase("help"))
{ SubCommand subCommand = getSubCommand(args[0]);
if (args.length < 2)
{
return usage("/guild help <subcommand>");
}
PlexCommand subCommand = getSubCommand(args[1]);
if (subCommand == null)
{
return messageComponent("guildCommandNotFound", args[1]);
}
CommandPermissions permissions = subCommand.getClass().getDeclaredAnnotation(CommandPermissions.class);
return mmString("<gradient:gold:yellow>========<newline>").append(mmString("<gold>Command Name: <yellow>" + subCommand.getName())).append(Component.newline())
.append(mmString("<gold>Command Aliases: <yellow>" + StringUtils.join(subCommand.getAliases(), ", "))).append(Component.newline())
.append(mmString("<gold>Description: <yellow>" + subCommand.getDescription())).append(Component.newline())
.append(mmString("<gold>Permission: <yellow>" + permissions.permission())).append(Component.newline())
.append(mmString("<gold>Required Source: <yellow>" + permissions.source().name()));
}
PlexCommand subCommand = getSubCommand(args[0]);
if (subCommand == null) if (subCommand == null)
{ {
return messageComponent("guildCommandNotFound", args[0]); return messageComponent("guildCommandNotFound", args[0]);
} }
CommandPermissions permissions = subCommand.getClass().getDeclaredAnnotation(CommandPermissions.class); CommandPermissions permissions = subCommand.getClass().getDeclaredAnnotation(CommandPermissions.class);
if (permissions.source() == RequiredCommandSource.CONSOLE && commandSender instanceof Player) if (permissions.source() == RequiredCommandSource.CONSOLE && sender instanceof Player)
{ {
return messageComponent("noPermissionInGame"); return messageComponent("noPermissionInGame");
} }
if (permissions.source() == RequiredCommandSource.IN_GAME && commandSender instanceof ConsoleCommandSender) if (permissions.source() == RequiredCommandSource.IN_GAME && isConsole(sender))
{ {
return messageComponent("noPermissionConsole"); return messageComponent("noPermissionConsole");
} }
checkPermission(player, permissions.permission()); checkPermission(sender, permissions.permission());
return subCommand.run(sender, player, Arrays.copyOfRange(args, 1, args.length));
return subCommand.execute(commandSender, player, Arrays.copyOfRange(args, 1, args.length));
}
private PlexCommand getSubCommand(String label)
{
return subCommands.stream().filter(cmd ->
{
CommandParameters commandParameters = cmd.getClass().getDeclaredAnnotation(CommandParameters.class);
return commandParameters.name().equalsIgnoreCase(label) || Arrays.stream(commandParameters.aliases().split(",")).anyMatch(s -> s.equalsIgnoreCase(label));
}).findFirst().orElse(null);
}
private void registerSubCommand(PlexCommand subCommand)
{
if (!subCommand.getClass().isAnnotationPresent(CommandPermissions.class))
{
throw new RuntimeException("CommandPermissions annotation for guild sub command " + subCommand.getName() + " could not be found!");
}
if (!subCommand.getClass().isAnnotationPresent(CommandParameters.class))
{
throw new RuntimeException("CommandParameters annotation for guild sub command " + subCommand.getName() + " could not be found!");
}
this.subCommands.add(subCommand);
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
if (args.length == 1) if (args.length == 1 && silentCheckPermission(sender, this.getPermission()))
{ {
List<String> possibleCommands = Lists.newArrayList(); return subcommands.stream().map(PlexCommand::getName).toList();
if (!args[0].isEmpty())
{
subCommands.forEach(plexCommand ->
{
plexCommand.getAliases().stream().filter(s -> s.toLowerCase(Locale.ROOT).startsWith(args[0].toLowerCase(Locale.ROOT))).forEach(possibleCommands::add);
if (plexCommand.getName().toLowerCase(Locale.ROOT).startsWith(args[0].toLowerCase(Locale.ROOT)))
{
possibleCommands.add(plexCommand.getName());
}
});
}
return possibleCommands;
} }
if (args.length >= 2) else if (args.length >= 2)
{ {
PlexCommand subCommand = getSubCommand(args[0]); PlexCommand subCommand = getSubCommand(args[0]);
if (subCommand != null) if (subCommand != null && silentCheckPermission(sender, subCommand.getPermission()))
{ {
return subCommand.tabComplete(sender, alias, Arrays.copyOfRange(args, 1, args.length)); return subCommand.smartTabComplete(sender, s, Arrays.copyOfRange(args, 1, args.length));
} }
} }
return ImmutableList.of(); return Collections.emptyList();
}
private SubCommand getSubCommand(String label)
{
return subcommands.stream().filter(cmd ->
{
CommandParameters parameters = cmd.getClass().getDeclaredAnnotation(CommandParameters.class);
return parameters.name().equalsIgnoreCase(label) || Arrays.stream(parameters.aliases().split(",")).anyMatch(s -> s.equalsIgnoreCase(label));
}).findFirst().orElse(null);
} }
public Component getSubs() public Component getSubs()
{ {
Component commands = Component.empty(); Component commands = Component.empty();
for (int i = 0; i < this.subCommands.size(); i++) for (int i = 0; i < this.subcommands.size(); i++)
{ {
commands = commands.append(messageComponent("guildsCommandDisplay", "/guild " + this.subCommands.get(i).getName(), this.subCommands.get(i).getDescription()).clickEvent(ClickEvent.suggestCommand("/guild help " + this.subCommands.get(i).getName()))); commands = commands.append(messageComponent("guildsCommandDisplay", "/guild " + this.subcommands.get(i).getName(), this.subcommands.get(i).getDescription()).clickEvent(ClickEvent.suggestCommand("/guild help " + this.subcommands.get(i).getName())));
if (i < this.subCommands.size() - 1) if (i < this.subcommands.size() - 1)
{ {
commands = commands.append(Component.newline()); commands = commands.append(Component.newline());
} }
} }
return messageComponent("guildsHelpCommand", commands); return messageComponent("guildsHelpCommand", commands);
} }
} }

View File

@ -0,0 +1,35 @@
package dev.plex.command;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SubCommand extends PlexCommand
{
public SubCommand()
{
super(false);
if (!getClass().isAnnotationPresent(CommandParameters.class))
{
throw new RuntimeException("CommandParameters annotation for guild sub command " + getName() + " could not be found!");
}
if (!getClass().isAnnotationPresent(CommandPermissions.class))
{
throw new RuntimeException("CommandPermissions annotation for guild sub command " + getName() + " could not be found!");
}
}
@Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] strings)
{
return null;
}
public abstract Component run(CommandSender sender, Player player, String[] args);
}

View File

@ -1,60 +0,0 @@
package dev.plex.command.sub;
import dev.plex.Guilds;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.data.Member;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "chat", usage = "/guild <command> [message]", description = "Toggles guild chat or sends a guild chat message")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.chat")
public class ChatSubCommand extends PlexCommand
{
public ChatSubCommand()
{
super(false);
}
@Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
{
assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
{
if (args.length == 0)
{
Member member = guild.getMember(player.getUniqueId());
member.setChat(!member.isChat());
send(player, messageComponent("guildChatToggled", BooleanUtils.toStringOnOff(member.isChat())));
return;
}
guild.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(player1 ->
{
send(player1, messageComponent("guildChatMessage", player.getName(), StringUtils.join(args, " ")));
});
if (Guilds.get().getConfig().isBoolean("guilds.log-chat-message"))
{
send(Bukkit.getConsoleSender(), messageComponent("guildChatConsoleLog", guild.getName(), guild.getGuildUuid(), player.getName(), StringUtils.join(args, " ")));
}
}, () -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException
{
return Collections.emptyList();
}
}

View File

@ -2,12 +2,12 @@ package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.Guild; import dev.plex.guild.Guild;
import java.util.Collections; import dev.plex.guild.GuildMember;
import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -15,37 +15,40 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "create", aliases = "make", usage = "/guild <command> <name>", description = "Creates a guild with a specified name") import java.util.Collections;
import java.util.List;
@CommandParameters(name = "create", usage = "/guild <command> <name>", description = "Create a brand new guild")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.create") @CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.create")
public class CreateSubCommand extends PlexCommand public class CreateSubCommand extends SubCommand
{ {
public CreateSubCommand() @Override
public Component run(@NotNull CommandSender sender, @Nullable Player player, @NotNull String[] args)
{ {
super(false); if (args.length > 0)
{
assert player != null;
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
if (member.getGuild().isPresent())
{
return messageComponent("alreadyInGuild");
}
String name = StringUtils.join(args, " ");
if (!StringUtils.isAlphanumericSpace(name))
{
return messageComponent("guildAlphanumericName");
}
Guild guild = Guild.create(member, name);
return mmString("Successfully created guild named " + guild.getName());
}
return usage();
} }
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{
if (args.length == 0)
{
return usage();
}
assert player != null;
if (Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).isPresent())
{
return messageComponent("alreadyInGuild");
}
Guilds.get().getSqlGuildManager().insertGuild(Guild.create(player, StringUtils.join(args, " "))).whenComplete((guild, throwable) ->
{
Guilds.get().getGuildHolder().addGuild(guild);
send(player, mmString("Created guild named " + guild.getName()));
});
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException
{ {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -0,0 +1,65 @@
package dev.plex.command.sub;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.GuildMember;
import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
@CommandParameters(name = "deletewarp", aliases = "delwarp,removewarp", usage = "/guild <command> <name>", description = "Deletes a guild warp")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.deletewarp")
public class DeleteWarpSubCommand extends SubCommand
{
@Override
public Component run(CommandSender sender, Player player, String[] args)
{
if (args.length == 0)
{
return usage();
}
assert player != null;
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
member.getGuild().ifPresentOrElse(guild ->
{
if (!guild.isModerator(member))
{
send(player, messageComponent("guildNotMod"));
return;
}
String name = StringUtils.join(args, " ").toLowerCase();
guild.getWarp(name).ifPresentOrElse(guildWarp ->
{
guild.deleteWarp(guildWarp);
send(player, messageComponent("guildWarpRemoved", name));
},
() -> send(player, messageComponent("guildWarpNotFound", name)));
},
() -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{
if (args.length == 1 && silentCheckPermission(sender, getPermission()))
{
GuildMember member = Guilds.get().getMemberData().getMember((Player) sender).orElseThrow();
List<String> names = Lists.newArrayList();
member.getGuild().ifPresent(guild -> names.addAll(guild.getWarpNames()));
return names;
}
return Collections.emptyList();
}
}

View File

@ -0,0 +1,59 @@
package dev.plex.command.sub;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.Guild;
import dev.plex.guild.GuildMember;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
@CommandParameters(name = "disband", usage = "/guild <command>", description = "Disband your guild")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.disband")
public class DisbandSubCommand extends SubCommand
{
private final List<CommandSender> confirm = Lists.newArrayList();
@Override
public Component run(CommandSender sender, Player player, String[] args)
{
assert player != null;
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
if (member.getGuild().isEmpty())
{
return messageComponent("guildNotFound");
}
Guild guild = member.getGuild().get();
if (!guild.isOwner(member))
{
return messageComponent("guildNotOwner");
}
if (!confirm.contains(sender))
{
confirm.add(sender);
Bukkit.getScheduler().runTaskLater(Guilds.get().getPlex(), () -> confirm.remove(sender), 20 * 10);
return messageComponent("guildActionConfirmation", "disband");
}
Guilds.get().getGuildData().deleteGuild(member);
confirm.remove(sender);
return messageComponent("guildDisbanded");
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException
{
return Collections.emptyList();
}
}

View File

@ -1,45 +1,45 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import java.util.Collections; import dev.plex.guild.GuildMember;
import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "home", aliases = "spawn", usage = "/guild <command>", description = "Teleports to the guild home") import java.util.Collections;
import java.util.List;
@CommandParameters(name = "home", usage = "/guild <command>", description = "Teleport to your guild's home location")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.home") @CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.home")
public class HomeSubCommand extends PlexCommand public class HomeSubCommand extends SubCommand
{ {
public HomeSubCommand()
{
super(false);
}
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public Component run(CommandSender sender, Player player, String[] args)
{ {
assert player != null; assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
{ member.getGuild().ifPresentOrElse(guild ->
if (guild.getHome() == null) {
{ if (guild.getHome() == null)
send(player, messageComponent("guildHomeNotFound")); {
return; send(player, messageComponent("guildHomeNotFound"));
} return;
player.teleportAsync(guild.getHome().toLocation()); }
}, () -> send(player, messageComponent("guildNotFound")));
player.teleportAsync(guild.getHome());
send(player, messageComponent("guildHomeTeleport"));
},
() -> send(player, messageComponent("guildNotFound")));
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,63 +1,105 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.cache.DataUtils; import dev.plex.command.SubCommand;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.guild.Guild;
import java.time.format.DateTimeFormatter; import dev.plex.guild.GuildMember;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "info", aliases = "information", usage = "/guild <command>", description = "Shows the guild's information") import java.text.SimpleDateFormat;
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.info") import java.util.Collections;
public class InfoSubCommand extends PlexCommand import java.util.List;
import java.util.Optional;
@CommandParameters(name = "info", usage = "/guild <command> [name]", description = "Shows your or a specified guild's information")
@CommandPermissions(permission = "plex.guilds.info")
public class InfoSubCommand extends SubCommand
{ {
public InfoSubCommand() private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
{
super(false);
}
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a");
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] strings) public Component run(CommandSender sender, Player player, String[] args)
{ {
assert player != null; if (args.length == 0)
CompletableFuture.runAsync(() ->
{ {
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> if (isConsole(sender))
{ {
send(player, mmString("<gradient:yellow:gold>====<aqua>" + guild.getName() + "<gradient:yellow:gold>====")); return messageComponent("noPermissionConsole");
send(player, mmString("")); }
try
{ assert player != null;
send(player, mmString("<gold>Owner: <yellow>" + DataUtils.getPlayer(guild.getOwner().getUuid(), false).getName())); GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
} member.getGuild().ifPresentOrElse(guild ->
catch (NullPointerException e) {
{ Component info = Component.empty()
send(player, mmString("<gold>Owner: <yellow>Unable to load cache...")); .append(mmString("<gradient:yellow:gold>====<aqua>" + guild.getName() + "<gradient:yellow:gold>===="))
} .appendNewline()
List<String> members = guild.getMembers().stream().filter(member -> !member.getUuid().equals(guild.getOwner().getUuid())).map(member -> DataUtils.getPlayer(member.getUuid(), false).getName()).toList(); .append(mmString("<gold>UUID: <yellow>" + guild.getUuid().toString()))
send(player, mmString("<gold>Members (" + members.size() + "): " + StringUtils.join(members, ", "))); .appendNewline()
send(player, mmString("<gold>Moderators (" + guild.getModerators().size() + "): " + StringUtils.join(guild.getModerators().stream().map(uuid -> DataUtils.getPlayer(uuid, false).getName()).toList(), ", "))); .append(mmString("<gold>Display Name:</gold> " + guild.getDisplayName()))
send(player, mmString("<gold>Prefix: " + (guild.getPrefix() == null ? "N/A" : guild.getPrefix()))); .appendNewline()
send(player, mmString("<gold>Created At: " + formatter.format(guild.getCreatedAt()))); .append(mmString("<gold>Owner: <yellow>" + guild.getOwner().getPlayer().getName()))
}, () -> send(player, messageComponent("guildNotFound"))); .appendNewline()
}); .append(mmString("<gold>Members (" + guild.getMemberNames().size() + "): <yellow>" + StringUtils.join(guild.getMemberNames(), ", ")))
.appendNewline()
.append(mmString("<gold>Moderators (" + guild.getModerators().size() + "): <yellow>" + StringUtils.join(guild.getModeratorNames(), ", ")))
.appendNewline()
.append(mmString("<gold>Privacy: <yellow>" + guild.getPrivacy().toString()))
.appendNewline()
.append(mmString("<gold>Created At: <yellow>" + dateFormat.format(guild.getCreatedAt())));
send(player, info);
},
() -> send(player, messageComponent("guildNotFound")));
}
else
{
String name = StringUtils.join(args, " ");
Optional<Guild> optionalGuild;
Player target = Bukkit.getPlayer(name);
if (target != null)
{
optionalGuild = Guilds.get().getMemberData().getMember(target).orElseThrow().getGuild();
}
else
{
optionalGuild = Guilds.get().getGuildData().getGuildByName(name);
}
optionalGuild.ifPresentOrElse(guild ->
{
Component info = Component.empty()
.append(mmString("<gradient:yellow:gold>====<aqua>" + guild.getName() + "<gradient:yellow:gold>===="))
.appendNewline()
.append(mmString("<gold>UUID: <yellow>" + guild.getUuid().toString()))
.appendNewline()
.append(mmString("<gold>Display Name:</gold> " + guild.getDisplayName()))
.appendNewline()
.append(mmString("<gold>Owner: <yellow>" + guild.getOwner().getPlayer().getName()))
.appendNewline()
.append(mmString("<gold>Members (" + guild.getMemberNames().size() + "): <yellow>" + StringUtils.join(guild.getMemberNames(), ", ")))
.appendNewline()
.append(mmString("<gold>Moderators (" + guild.getModerators().size() + "): <yellow>" + StringUtils.join(guild.getModeratorNames(), ", ")))
.appendNewline()
.append(mmString("<gold>Privacy: <yellow>" + guild.getPrivacy().toString()))
.appendNewline()
.append(mmString("<gold>Created At: <yellow>" + dateFormat.format(guild.getCreatedAt())));
send(sender, info);
},
() -> send(sender, messageComponent("guildNotExist", name)));
}
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,140 +0,0 @@
package dev.plex.command.sub;
import com.google.common.collect.ImmutableList;
import dev.plex.Guilds;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.Guild;
import dev.plex.guild.GuildHolder;
import dev.plex.guild.data.Member;
import dev.plex.util.PlexLog;
import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
// TODO: 5/9/2022 5 minute timeout for invites
// TODO: 5/9/2022 deny command maybe?
// TODO: 5/9/2022 deny members from inviting themselves or existing members in the current guild
@CommandParameters(name = "invite", aliases = "inv", usage = "/guild <command> <player name>", description = "Invites a player to the guild")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.invite")
public class InviteSubCommand extends PlexCommand
{
public InviteSubCommand()
{
super(false);
}
@Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
{
if (args.length == 0)
{
return usage();
}
assert player != null;
if (args[0].equalsIgnoreCase("accept"))
{
if (!GuildHolder.PENDING_INVITES.containsKey(player.getUniqueId()))
{
return messageComponent("guildNoInvite");
}
String guildName = StringUtils.join(args, " ", 1, args.length);
GuildHolder.PENDING_INVITES.get(player.getUniqueId()).stream().filter(guild -> guild.getName().equalsIgnoreCase(guildName)).findFirst().ifPresentOrElse(guild ->
{
AtomicBoolean continueCheck = new AtomicBoolean(true);
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresent(guild1 ->
{
if (guild1.getGuildUuid().equals(guild.getGuildUuid()))
{
send(player, messageComponent("guildInThis"));
continueCheck.set(false);
return;
}
if (guild1.getOwner().getUuid().equals(player.getUniqueId()))
{
if (guild1.getMembers().size() - 1 > 0)
{
send(player, messageComponent("guildDisbandNeeded"));
continueCheck.set(false);
return;
}
else
{
Guilds.get().getSqlGuildManager().deleteGuild(guild1.getGuildUuid()).whenComplete((unused, throwable) ->
{
send(player, messageComponent("guildAutoDisbanded"));
});
}
}
guild1.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(player1 ->
{
send(player1, messageComponent("guildMemberLeft", player.getName()));
});
guild1.getMembers().removeIf(member -> member.getUuid().equals(player.getUniqueId()));
});
if (!continueCheck.get())
{
return;
}
GuildHolder.PENDING_INVITES.remove(player.getUniqueId());
guild.addMember(player.getUniqueId());
guild.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(player1 ->
{
send(player1, messageComponent("guildMemberJoined", player.getName()));
});
}, () -> send(player, messageComponent("guildNotValidInvite")));
return null;
}
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
{
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
{
send(player, messageComponent("guildNotOwner"));
return;
}
Player target = getNonNullPlayer(args[0]);
boolean invite = GuildHolder.sendInvite(target.getUniqueId(), guild);
if (!invite)
{
send(player, messageComponent("guildInviteExists"));
return;
}
send(player, messageComponent("guildInviteSent", target.getName()));
send(target, messageComponent("guildInviteReceived", player.getName(), guild.getName()));
}, () -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException
{
if (!(sender instanceof Player player))
{
return ImmutableList.of();
}
if (args.length == 0)
{
return ImmutableList.of();
}
if (args[0].equalsIgnoreCase("accept") && args.length == 2)
{
if (!GuildHolder.PENDING_INVITES.containsKey(player.getUniqueId()))
{
return ImmutableList.of();
}
PlexLog.debug("Tab Completing moment");
return GuildHolder.PENDING_INVITES.get(player.getUniqueId()).stream().map(Guild::getName).collect(Collectors.toList());
}
return ImmutableList.of();
}
}

View File

@ -0,0 +1,69 @@
package dev.plex.command.sub;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.GuildMember;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
@CommandParameters(name = "leave", usage = "/guild <command>", description = "Leave the guild you are currently in")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.leave")
public class LeaveSubCommand extends SubCommand
{
private final List<CommandSender> confirm = Lists.newArrayList();
@Override
public Component run(CommandSender sender, Player player, String[] args)
{
assert player != null;
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
member.getGuild().ifPresentOrElse(guild ->
{
if (guild.isOwner(member) && guild.getMembers().size() > 1)
{
send(player, messageComponent("guildDisbandNeeded"));
return;
}
if (!confirm.contains(sender))
{
confirm.add(sender);
Bukkit.getScheduler().runTaskLater(Guilds.get().getPlex(), () -> confirm.remove(sender), 20 * 10);
send(player, messageComponent("guildActionConfirmation", "leave"));
return;
}
confirm.remove(sender);
if (guild.isOwner(member) && guild.getMembers().size() == 1)
{
Guilds.get().getGuildData().deleteGuild(member);
send(player, messageComponent("guildAutoDisbanded"));
return;
}
guild.removeMember(member);
send(player, messageComponent("guildLeft"));
guild.getMembers().stream().map(GuildMember::getPlayer).filter(OfflinePlayer::isOnline).map(OfflinePlayer::getPlayer).forEach(p -> send(p, messageComponent("guildMemberLeft", player.getName())));
},
() -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{
return Collections.emptyList();
}
}

View File

@ -0,0 +1,74 @@
package dev.plex.command.sub;
import dev.plex.Guilds;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.Guild;
import dev.plex.guild.GuildMember;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@CommandParameters(name = "motd", usage = "/g <command> <set <message> | clear>", description = "Set or clear your guild's MOTD")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.motd")
public class MotdSubCommand extends SubCommand
{
@Override
public Component run(CommandSender sender, Player player, String[] args)
{
assert player != null;
if (args.length > 0)
{
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
if (member.getGuild().isEmpty())
{
return messageComponent("guildNotFound");
}
Guild guild = member.getGuild().get();
if (!guild.isModerator(member))
{
return messageComponent("guildNotMod");
}
if (args.length == 1 && args[0].equalsIgnoreCase("clear"))
{
guild.setMotd(null);
return messageComponent("guildMotdCleared");
}
if (args.length > 1 && args[0].equalsIgnoreCase("set"))
{
String message = StringUtils.join(args, " ", 1, args.length);
if (MiniMessage.miniMessage().stripTags(message).length() > 256)
{
return messageComponent("guildMotdExceededLimit");
}
guild.setMotd(message);
return messageComponent("guildMotdSet", mmString(message));
}
}
return usage();
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{
if (args.length == 1)
{
return Arrays.asList("set", "clear");
}
return Collections.emptyList();
}
}

View File

@ -1,69 +0,0 @@
package dev.plex.command.sub;
import dev.plex.Guilds;
import dev.plex.cache.DataUtils;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.data.Member;
import dev.plex.player.PlexPlayer;
import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "owner", aliases = "setowner", usage = "/guild <command> <player name>", description = "Sets the guild owner")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.owner")
public class OwnerSubCommand extends PlexCommand
{
public OwnerSubCommand()
{
super(false);
}
@Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
{
if (args.length == 0)
{
return usage();
}
assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
{
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
{
send(player, messageComponent("guildNotOwner"));
return;
}
Member memberSender = guild.getMember(player.getUniqueId());
PlexPlayer plexPlayer = DataUtils.getPlayer(args[0], false);
if (plexPlayer == null)
{
send(player, messageComponent("playerNotFound"));
return;
}
Member member = guild.getMember(plexPlayer.getUuid());
if (member == null)
{
send(player, messageComponent("guildMemberNotFound"));
return;
}
guild.setOwner(member);
guild.getMembers().remove(member);
guild.getMembers().add(memberSender);
send(player, messageComponent("guildOwnerSet", plexPlayer.getName()));
}, () -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException
{
return Collections.emptyList();
}
}

View File

@ -1,58 +1,62 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.GuildMember;
import dev.plex.util.minimessage.SafeMiniMessage; import dev.plex.util.minimessage.SafeMiniMessage;
import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "prefix", aliases = "tag,settag,setprefix", usage = "/guild <command> <prefix>", description = "Sets the guild's default prefix") import java.util.Collections;
import java.util.List;
@CommandParameters(name = "prefix", aliases = "tag,settag,setprefix", usage = "/guild <command> <clear | prefix>", description = "Sets the guild's default prefix")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.prefix") @CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.prefix")
public class PrefixSubCommand extends PlexCommand public class PrefixSubCommand extends SubCommand
{ {
public PrefixSubCommand()
{
super(false);
}
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public Component run(CommandSender sender, Player player, String[] args)
{ {
if (args.length == 0) if (args.length == 0)
{ {
return usage(); return usage();
} }
assert player != null; assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
{ member.getGuild().ifPresentOrElse(guild ->
if (!guild.getOwner().getUuid().equals(player.getUniqueId())) {
{ if (!guild.isModerator(member))
send(player, messageComponent("guildNotOwner")); {
return; send(player, messageComponent("guildNotMod"));
} return;
if (args[0].equalsIgnoreCase("clear") || args[0].equalsIgnoreCase("off")) }
{
guild.setPrefix(null); if (args[0].equalsIgnoreCase("clear"))
send(player, messageComponent("guildPrefixCleared")); {
return; guild.setPrefix(null);
} send(player, messageComponent("guildPrefixCleared"));
guild.setPrefix(StringUtils.join(args, " ")); return;
send(player, messageComponent("guildPrefixSet", SafeMiniMessage.mmDeserializeWithoutEvents(guild.getPrefix()))); }
}, () -> send(player, messageComponent("guildNotFound")));
String prefix = StringUtils.join(args, " ");
guild.setPrefix(prefix);
prefix = prefix.replace("%rank%", guild.getDefaultRank().getName()).replace("%name%", guild.getDisplayName());
send(player, messageComponent("guildPrefixSet", SafeMiniMessage.mmDeserializeWithoutEvents(prefix)));
},
() -> send(player, messageComponent("guildNotFound")));
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,59 +1,64 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.util.CustomLocation; import dev.plex.guild.GuildMember;
import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "sethome", aliases = "setspawn", usage = "/guild <command>", description = "Sets the guild's home") import java.util.Collections;
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.sethome") import java.util.List;
public class SetHomeSubCommand extends PlexCommand
{
public SetHomeSubCommand()
{
super(false);
}
@CommandParameters(name = "sethome", usage = "/guild <command> [clear]", description = "Set or clear your guild's home location")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.sethome")
public class SetHomeSubCommand extends SubCommand
{
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public Component run(@NotNull CommandSender sender, @Nullable Player player, @NotNull String[] args)
{ {
assert player != null; assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
{ member.getGuild().ifPresentOrElse(guild ->
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
{
send(player, messageComponent("guildNotOwner"));
return;
}
if (args.length > 0 && (args[0].equalsIgnoreCase("remove") || args[0].equalsIgnoreCase("unset") || args[0].equalsIgnoreCase("clear")))
{
if (guild.getHome() == null)
{ {
send(player, messageComponent("guildHomeNotFound")); if (!guild.isOwner(member))
return; {
} send(player, messageComponent("guildNotOwner"));
guild.setHome(null); return;
send(player, messageComponent("guildHomeRemoved")); }
return;
} if (args.length == 1 && args[0].equalsIgnoreCase("clear"))
guild.setHome(CustomLocation.fromLocation(player.getLocation())); {
send(player, messageComponent("guildHomeSet")); if (guild.getHome() == null)
}, () -> send(player, messageComponent("guildNotFound"))); {
send(player, messageComponent("guildHomeNotFound"));
return;
}
guild.setHome(null);
send(player, messageComponent("guildHomeRemoved"));
return;
}
guild.setHome(player.getLocation());
send(player, messageComponent("guildHomeSet"));
},
() -> send(player, messageComponent("guildNotFound")));
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
if (args.length == 1 && silentCheckPermission(sender, getPermission()))
{
return Collections.singletonList("clear");
}
return Collections.emptyList(); return Collections.emptyList();
} }
} }

View File

@ -0,0 +1,65 @@
package dev.plex.command.sub;
import dev.plex.Guilds;
import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.GuildMember;
import dev.plex.util.PlexUtils;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
@CommandParameters(name = "setowner", usage = "/guild <command> <player>", description = "Transfer the ownership of your guild to another player")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.setowner")
public class SetOwnerSubCommand extends SubCommand
{
@Override
public Component run(CommandSender sender, Player player, String[] args)
{
if (args.length != 1)
{
return usage();
}
assert player != null;
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
member.getGuild().ifPresentOrElse(guild ->
{
if (!guild.isOwner(member))
{
send(player, messageComponent("guildNotOwner"));
return;
}
Player target = getNonNullPlayer(args[0]);
GuildMember targetMember = Guilds.get().getMemberData().getMember(target).orElseThrow();
if (targetMember.getGuild().isEmpty() || !targetMember.getGuild().get().equals(guild))
{
send(player, messageComponent("guildMemberNotFound"));
return;
}
guild.setOwner(targetMember);
send(player, messageComponent("guildOwnerSet", target.getName()));
},
() -> send(player, messageComponent("guildNotFound")));
return null;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{
if (args.length == 1 && silentCheckPermission(sender, getPermission()))
{
return PlexUtils.getPlayerNameList();
}
return Collections.emptyList();
}
}

View File

@ -1,69 +1,68 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.util.CustomLocation; import dev.plex.guild.GuildMember;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "setwarp", aliases = "makewarp,createwarp", usage = "/guild <command> <name>", description = "Creates a new warp at player's location with a specified name") import java.util.Collections;
import java.util.List;
@CommandParameters(name = "setwarp", aliases = "createwarp", usage = "/guild <command> <name>", description = "Creates a new guild warp at your location with a specified name")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.setwarp") @CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.setwarp")
public class SetWarpSubCommand extends PlexCommand public class SetWarpSubCommand extends SubCommand
{ {
public SetWarpSubCommand()
{
super(false);
}
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public Component run(CommandSender sender, Player player, String[] args)
{ {
if (args.length == 0) if (args.length == 0)
{ {
return usage(); return usage();
} }
assert player != null; assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
{ member.getGuild().ifPresentOrElse(guild ->
if (!guild.getOwner().getUuid().equals(player.getUniqueId())) {
{ if (!guild.isModerator(member))
send(player, messageComponent("guildNotOwner")); {
return; send(player, messageComponent("guildNotMod"));
} return;
String warpName = StringUtils.join(args, " "); }
if (warpName.length() > 16)
{ String name = StringUtils.join(args, " ").toLowerCase();
send(player, mmString("<red>The max length of a warp name is 16 characters!")); if (name.length() > 16)
return; {
} send(player, mmString("<red>The max length of a warp name is 16 characters!"));
if (guild.getWarps().containsKey(warpName.toLowerCase())) return;
{ }
send(player, messageComponent("guildWarpExists", warpName));
return; if (!StringUtils.isAlphanumericSpace(name))
} {
if (!StringUtils.isAlphanumericSpace(warpName.toLowerCase(Locale.ROOT))) send(player, messageComponent("guildWarpAlphanumeric"));
{ return;
send(player, messageComponent("guildWarpAlphanumeric")); }
return;
} guild.getWarp(name).ifPresentOrElse(guildWarp -> send(player, messageComponent("guildWarpExists", name)),
guild.getWarps().put(warpName.toLowerCase(), CustomLocation.fromLocation(player.getLocation())); () ->
send(player, messageComponent("guildWarpCreated", warpName)); {
}, () -> send(player, messageComponent("guildNotFound"))); guild.createWarp(name, player.getLocation());
send(player, messageComponent("guildWarpCreated", name));
});
},
() -> send(player, messageComponent("guildNotFound")));
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,62 +0,0 @@
package dev.plex.command.sub;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import dev.plex.guild.Guild;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "warps", aliases = "listwarps", usage = "/guild <command>", description = "Displays a clickable list of warps")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.warps")
public class WarpListSubCommand extends PlexCommand
{
public WarpListSubCommand()
{
super(false);
}
@Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
{
assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
{
send(player, getWarps(guild));
}, () -> send(player, messageComponent("guildNotFound")));
return null;
}
public Component getWarps(Guild guild)
{
Set<String> warps = guild.getWarps().keySet();
List<Component> components = Lists.newArrayList();
warps.forEach(s -> components.add(mmString("<click:suggest_command:/guild warp " + s + ">" + s)));
Component parent = mmString("<gold>Warps (" + warps.size() + "): ");
for (int i = 0; i < components.size(); i++)
{
parent = parent.append(components.get(i));
if (i < components.size() - 1)
{
parent = parent.append(mmString(", "));
}
}
return parent;
}
@Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException
{
return Collections.emptyList();
}
}

View File

@ -1,52 +1,60 @@
package dev.plex.command.sub; package dev.plex.command.sub;
import com.google.common.collect.Lists;
import dev.plex.Guilds; import dev.plex.Guilds;
import dev.plex.command.PlexCommand; import dev.plex.command.SubCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import java.util.Collections; import dev.plex.guild.GuildMember;
import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "warp", aliases = "goto", usage = "/guild <command> <name>", description = "Warps to a specified guild warp") import java.util.Collections;
import java.util.List;
@CommandParameters(name = "warp", usage = "/guild <command> [name]", description = "List existing warps under your guild or warp to a specified guild warp location")
@CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.warp") @CommandPermissions(source = RequiredCommandSource.IN_GAME, permission = "plex.guilds.warp")
public class WarpSubCommand extends PlexCommand public class WarpSubCommand extends SubCommand
{ {
public WarpSubCommand()
{
super(false);
}
@Override @Override
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args) public Component run(CommandSender sender, Player player, String[] args)
{ {
if (args.length == 0)
{
return usage();
}
assert player != null; assert player != null;
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild -> GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
{ member.getGuild().ifPresentOrElse(guild ->
String warpName = StringUtils.join(args, " "); {
if (!guild.getWarps().containsKey(warpName.toLowerCase())) if (args.length == 0)
{ {
send(player, messageComponent("guildWarpNotFound", warpName)); send(player, guild.getWarps());
return; return;
} }
player.teleportAsync(guild.getWarps().get(warpName.toLowerCase()).toLocation());
}, () -> send(player, messageComponent("guildNotFound"))); String name = StringUtils.join(args, " ").toLowerCase();
guild.getWarp(name).ifPresentOrElse(warp ->
{
player.teleportAsync(warp.getLocation());
send(player, messageComponent("guildWarpSuccess", name));
},
() -> send(player, messageComponent("guildWarpNotFound", name)));
},
() -> send(player, messageComponent("guildNotFound")));
return null; return null;
} }
@Override @Override
public @NotNull List<String> smartTabComplete(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) throws IllegalArgumentException public @NotNull List<String> smartTabComplete(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args) throws IllegalArgumentException
{ {
if (args.length == 1 && silentCheckPermission(sender, getPermission()))
{
GuildMember member = Guilds.get().getMemberData().getMember((Player) sender).orElseThrow();
List<String> names = Lists.newArrayList();
member.getGuild().ifPresent(guild -> names.addAll(guild.getWarpNames()));
return names;
}
return Collections.emptyList(); return Collections.emptyList();
} }
} }

View File

@ -0,0 +1,45 @@
package dev.plex.data;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.guild.Guild;
import dev.plex.guild.GuildMember;
import lombok.Getter;
import java.util.List;
import java.util.Optional;
@Getter
public class GuildData
{
private final List<Guild> guilds = Lists.newArrayList();
public void addGuild(Guild guild)
{
guilds.add(guild);
}
public void addNewGuild(Guild guild)
{
Guilds.get().getSqlManager().insertGuild(guild);
addGuild(guild);
}
public void deleteGuild(GuildMember player)
{
if (guilds.removeIf(g -> g.getOwner().getUuid().equals(player.getUuid())))
{
Guilds.get().getSqlManager().deleteGuild(player.getPlayer().getPlayer());
}
}
public Optional<Guild> getGuildByName(String name)
{
return guilds.stream().filter(g -> g.getName().equalsIgnoreCase(name)).findFirst();
}
public Optional<Guild> getGuildByMember(GuildMember member)
{
return guilds.stream().filter(g -> g.getMembers().contains(member)).findFirst();
}
}

View File

@ -0,0 +1,54 @@
package dev.plex.data;
import com.google.common.collect.Lists;
import dev.plex.Guilds;
import dev.plex.guild.GuildMember;
import lombok.Getter;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
@Getter
public class MemberData
{
private final List<GuildMember> members = Lists.newArrayList();
public void addMember(GuildMember member)
{
members.add(member);
}
public GuildMember addNewMember(Player player)
{
AtomicReference<GuildMember> memberReference = new AtomicReference<>(new GuildMember(player.getUniqueId()));
Guilds.get().getSqlManager().insertMember(memberReference.get()).whenComplete((m, throwable) ->
{
memberReference.set(m);
addMember(m);
});
return memberReference.get();
}
public Optional<GuildMember> getMemberByName(String name)
{
return members.stream().filter(p -> p.getPlayer().getName().equalsIgnoreCase(name)).findFirst();
}
public Optional<GuildMember> getMemberByUUID(UUID uuid)
{
return members.stream().filter(p -> p.getUuid().equals(uuid)).findFirst();
}
public Optional<GuildMember> getMemberByID(int id)
{
return members.stream().filter(p -> p.getId() == id).findFirst();
}
public Optional<GuildMember> getMember(Player player)
{
return getMemberByUUID(player.getUniqueId());
}
}

View File

@ -1,162 +0,0 @@
package dev.plex.data;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import dev.plex.Plex;
import dev.plex.guild.Guild;
import dev.plex.guild.data.Member;
import dev.plex.util.CustomLocation;
import dev.plex.util.GuildUtil;
import dev.plex.util.PlexLog;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class SQLGuildManager
{
private static final Gson GSON = new Gson();
private static final String SELECT_GUILD = "SELECT * FROM `guilds`";
private static final String INSERT_GUILD = "INSERT INTO `guilds` (`guildUuid`, `name`, `owner`, `createdAt`, `members`, `moderators`, `prefix`, `motd`, `ranks`, `defaultRank`, `warps`, `home`, `tagEnabled`, `isPublic`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String DELETE_GUILD = "DELETE FROM `guilds` WHERE guildUuid=?";
private static final String UPDATE_GUILD = "UPDATE `guilds` SET name=?, owner=?, members=?, moderators=?, prefix=?, motd=?, ranks=?, defaultRank=?, home=?, warps=?, tagEnabled=?, isPublic=? WHERE guildUuid=?";
public CompletableFuture<Guild> insertGuild(Guild guild)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(INSERT_GUILD);
statement.setString(1, guild.getGuildUuid().toString());
statement.setString(2, guild.getName());
statement.setString(3, GSON.toJson(guild.getOwner()));
statement.setLong(4, guild.getCreatedAt().toInstant().toEpochMilli());
statement.setString(5, GSON.toJson(guild.getMembers()));
statement.setString(6, GSON.toJson(guild.getModerators().stream().map(UUID::toString).collect(Collectors.toList())));
statement.setString(7, guild.getPrefix());
statement.setString(8, guild.getMotd());
statement.setString(9, GSON.toJson(guild.getRanks()));
statement.setString(10, GSON.toJson(guild.getDefaultRank()));
statement.setString(11, GSON.toJson(guild.getWarps()));
statement.setString(12, GSON.toJson(guild.getHome()));
statement.setBoolean(13, guild.isTagEnabled());
statement.setBoolean(14, guild.isPublic());
statement.execute();
return guild;
}
catch (SQLException e)
{
GuildUtil.throwExceptionSync(e);
return null;
}
});
}
public CompletableFuture<Void> deleteGuild(UUID uuid)
{
return CompletableFuture.runAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(DELETE_GUILD);
statement.setString(1, uuid.toString());
statement.execute();
}
catch (SQLException e)
{
GuildUtil.throwExceptionSync(e);
}
});
}
public CompletableFuture<Guild> updateGuild(Guild guild)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(UPDATE_GUILD);
statement.setString(1, guild.getName());
statement.setString(2, GSON.toJson(guild.getOwner()));
statement.setString(3, GSON.toJson(guild.getMembers()));
statement.setString(4, GSON.toJson(guild.getModerators().stream().map(UUID::toString).collect(Collectors.toList())));
statement.setString(5, guild.getPrefix());
statement.setString(6, guild.getMotd());
statement.setString(7, GSON.toJson(guild.getRanks()));
statement.setString(8, GSON.toJson(guild.getDefaultRank()));
statement.setString(9, GSON.toJson(guild.getHome()));
statement.setString(10, GSON.toJson(guild.getWarps()));
statement.setBoolean(11, guild.isTagEnabled());
statement.setBoolean(12, guild.isPublic());
statement.setString(13, guild.getGuildUuid().toString());
statement.executeUpdate();
return guild;
}
catch (SQLException e)
{
GuildUtil.throwExceptionSync(e);
return null;
}
});
}
private List<Guild> getGuildsSync()
{
List<Guild> guilds = Lists.newArrayList();
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
PreparedStatement statement = connection.prepareStatement(SELECT_GUILD);
ResultSet set = statement.executeQuery();
while (set.next())
{
Guild guild = new Guild(UUID.fromString(set.getString("guildUuid")),
ZonedDateTime.ofInstant(Instant.ofEpochMilli(set.getLong("createdAt")), ZoneId.of(Plex.get().config.getString("server.timezone")).getRules().getOffset(Instant.now())));
guild.setName(set.getString("name"));
guild.setOwner(GSON.fromJson(set.getString("owner"), Member.class));
List<Member> members = new Gson().fromJson(set.getString("members"), new TypeToken<List<Member>>()
{
}.getType());
members.forEach(guild::addMember);
guild.getModerators().addAll(new Gson().fromJson(set.getString("moderators"), new TypeToken<List<String>>()
{
}.getType()));
guild.setPrefix(set.getString("prefix"));
guild.setMotd(set.getString("motd"));
guild.setHome(GSON.fromJson(set.getString("home"), CustomLocation.class));
guild.setTagEnabled(set.getBoolean("tagEnabled"));
Map<String, CustomLocation> warps = GSON.fromJson(set.getString("warps"), new TypeToken<Map<String, CustomLocation>>()
{
}.getType());
PlexLog.debug("Loaded {0} warps for {1} guild", warps.size(), guild.getName());
guild.getWarps().putAll(GSON.fromJson(set.getString("warps"), new TypeToken<Map<String, CustomLocation>>()
{
}.getType()));
guild.setPublic(set.getBoolean("isPublic"));
guilds.add(guild);
}
}
catch (SQLException e)
{
GuildUtil.throwExceptionSync(e);
}
return guilds;
}
public CompletableFuture<List<Guild>> getGuilds()
{
return CompletableFuture.supplyAsync(this::getGuildsSync);
}
}

View File

@ -1,39 +0,0 @@
package dev.plex.data;
import dev.plex.Plex;
import java.sql.Connection;
import java.sql.SQLException;
public class SQLManager
{
public static void makeTables()
{
try (Connection connection = Plex.get().getSqlConnection().getCon())
{
connection.prepareStatement(
"CREATE TABLE IF NOT EXISTS `guilds` (" +
"`guildUuid` VARCHAR(46) NOT NULL, " +
"`name` VARCHAR(2000) NOT NULL, " +
"`owner` LONGTEXT NOT NULL, " +
"`createdAt` BIGINT NOT NULL, " +
"`prefix` VARCHAR(2000), " +
"`motd` VARCHAR(3000), " +
"`home` VARCHAR(1000)," +
"`members` LONGTEXT, " +
"`moderators` LONGTEXT, " +
"`ranks` LONGTEXT, " +
"`defaultRank` LONGTEXT, " +
"`warps` LONGTEXT, " +
"`tagEnabled` BOOLEAN, " +
"`isPublic` BOOLEAN, " +
"PRIMARY KEY (`guildUuid`)" +
");"
).execute();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}

View File

@ -1,72 +1,229 @@
package dev.plex.guild; package dev.plex.guild;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import dev.plex.Guilds;
import dev.plex.Plex; import dev.plex.util.PlexUtils;
import dev.plex.guild.data.Member;
import dev.plex.guild.data.Rank;
import dev.plex.util.CustomLocation;
import dev.plex.util.minimessage.SafeMiniMessage;
import lombok.Data; import lombok.Data;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.time.ZoneId; import java.util.*;
import java.time.ZonedDateTime; import java.util.stream.Collectors;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Data @Data
public class Guild public class Guild
{ {
private final UUID guildUuid; private final UUID uuid;
private final ZonedDateTime createdAt; private final Date createdAt;
private final List<Member> members = Lists.newArrayList();
private final List<UUID> moderators = Lists.newArrayList();
private final List<Rank> ranks = Lists.newArrayList();
private final Map<String, CustomLocation> warps = Maps.newHashMap();
private String name; private String name;
private Member owner; private String displayName = null;
private String prefix; private GuildMember owner;
private String motd; private List<GuildMember> members = Lists.newArrayList();
private CustomLocation home; private List<GuildMember> moderators = Lists.newArrayList();
private boolean tagEnabled; private List<GuildRank> ranks = Lists.newArrayList();
private Rank defaultRank = new Rank("default", null); private List<GuildWarp> warps = Lists.newArrayList();
private boolean isPublic = false; private GuildRank defaultRank = null;
private String prefix = null;
private boolean prefixEnabled = false;
private String motd = null;
private Location home;
private Privacy privacy = Privacy.PUBLIC;
private List<GuildMember> pendingInvites = Lists.newArrayList();
public static Guild create(GuildMember member, String name)
public static Guild create(Player player, String guildName)
{ {
Guild guild = new Guild(UUID.randomUUID(), ZonedDateTime.now(ZoneId.of(Plex.get().config.getString("server.timezone")))); Guild guild = new Guild(UUID.randomUUID(), new Date());
guild.setName(PlainTextComponentSerializer.plainText().serialize(SafeMiniMessage.mmDeserialize(guildName))); guild.setName(name);
guild.setOwner(new Member(player.getUniqueId())); guild.setOwner(member);
Guilds.get().getGuildData().addNewGuild(guild);
return guild; return guild;
} }
public Member getMember(UUID uuid) public void chat(Player player, Component message)
{ {
if (owner.getUuid().equals(uuid)) getMembers().stream().map(GuildMember::getPlayer).filter(OfflinePlayer::isOnline).map(OfflinePlayer::getPlayer).forEach(p -> p.sendMessage(PlexUtils.messageComponent("guildChatMessage", player.getName(), message)));
if (Guilds.get().getConfig().getBoolean("guilds.log-chat-message"))
{ {
return owner; Bukkit.getConsoleSender().sendMessage(PlexUtils.messageComponent("guildChatConsoleLog", name, uuid, player.getName(), PlainTextComponentSerializer.plainText().serialize(message)));
} }
return members.stream().filter(m -> m.getUuid().equals(uuid)).findFirst().orElse(null);
} }
public void addMember(UUID uuid) public String getDisplayName()
{ {
addMember(new Member(uuid)); return displayName != null ? displayName : name;
} }
public void addMember(Member member) public boolean isOwner(GuildMember member)
{ {
this.members.add(member); return owner.equals(member);
} }
public List<Member> getMembers() public void setOwner(GuildMember member)
{ {
List<Member> allMembers = Lists.newArrayList(members); members.add(owner);
allMembers.add(owner); members.remove(member);
return allMembers; owner = member;
}
public boolean isMember(GuildMember member)
{
return getMembers().contains(member);
}
public void addMember(GuildMember member)
{
members.add(member);
}
public void removeMember(GuildMember member)
{
members.remove(member);
moderators.remove(member);
}
public void setMemberRank(GuildMember member, GuildRank rank)
{
rank.addMember(member);
}
public boolean isModerator(GuildMember member)
{
return moderators.contains(member) || owner.equals(member);
}
public void addModerator(GuildMember member)
{
moderators.add(member);
}
public void removeModerator(GuildMember member)
{
moderators.remove(member);
}
public void createRank(String name)
{
GuildRank rank = new GuildRank(name);
Guilds.get().getSqlManager().insertRank(this, rank);
ranks.add(rank);
}
public void deleteRank(GuildRank rank)
{
if (rank.equals(defaultRank))
{
defaultRank = null;
}
Guilds.get().getSqlManager().deleteRank(this, rank);
ranks.remove(rank);
}
public void setDefaultRank(GuildRank rank)
{
Guilds.get().getSqlManager().updateDefaultRank(this, rank);
defaultRank = rank;
}
public List<GuildRank> getRanks()
{
List<GuildRank> tempRanks = Lists.newArrayList();
if (defaultRank != null)
{
tempRanks.add(defaultRank);
}
return tempRanks;
}
public Optional<GuildRank> getRankByName(String name)
{
return ranks.stream().filter(rank -> rank.getName().equalsIgnoreCase(name)).findFirst();
}
public Optional<GuildRank> getRankByMember(GuildMember member)
{
return ranks.stream().filter(rank -> rank.getMembers().contains(member)).findFirst().or(() -> Optional.of(defaultRank));
}
public List<String> getRankNames()
{
return getRanks().stream().map(GuildRank::getName).toList();
}
public void createWarp(String name, Location location)
{
GuildWarp warp = new GuildWarp(name, location);
Guilds.get().getSqlManager().insertWarp(this, warp);
warps.add(warp);
}
public void deleteWarp(GuildWarp warp)
{
if (warps.removeIf(w -> w.getName().equals(warp.getName())))
{
Guilds.get().getSqlManager().deleteWarp(this, warp);
}
}
public Optional<GuildWarp> getWarp(String name)
{
return warps.stream().filter(warp -> warp.getName().equalsIgnoreCase(name)).findFirst();
}
public Component getWarps()
{
List<Component> components = Lists.newArrayList();
getWarpNames().forEach(s -> components.add(PlexUtils.mmDeserialize("<click:suggest_command:/guild warp " + s + ">" + s)));
Component parent = PlexUtils.mmDeserialize("<gold>Warps (" + warps.size() + "): ");
for (int i = 0; i < components.size(); i++)
{
parent = parent.append(components.get(i));
if (i < components.size() - 1)
{
parent = parent.append(PlexUtils.mmDeserialize(", "));
}
}
return parent;
}
public List<String> getWarpNames()
{
return warps.stream().map(GuildWarp::getName).toList();
}
public List<GuildMember> getMembers()
{
List<GuildMember> temp = Lists.newArrayList(members);
temp.add(owner);
return temp;
}
public List<String> getMemberNames()
{
return members.stream().map(p -> p.getPlayer().getName()).toList();
}
public List<Integer> getMemberIDs()
{
return members.stream().map(GuildMember::getId).collect(Collectors.toList());
}
public List<String> getModeratorNames()
{
return moderators.stream().map(p -> p.getPlayer().getName()).toList();
}
public List<Integer> getModeratorIDs()
{
return moderators.stream().map(GuildMember::getId).toList();
}
public enum Privacy
{
PUBLIC, PRIVATE, INVITE_ONLY
} }
} }

View File

@ -1,51 +0,0 @@
package dev.plex.guild;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import dev.plex.guild.data.Member;
import java.util.*;
public class GuildHolder
{
public static final Map<UUID, List<Guild>> PENDING_INVITES = Maps.newHashMap();
private static final List<Guild> GUILDS = Lists.newArrayList();
public static boolean sendInvite(UUID uuid, Guild guild)
{
if (PENDING_INVITES.containsKey(uuid) && PENDING_INVITES.get(uuid).stream().anyMatch(guild1 -> guild1.getGuildUuid().equals(guild.getGuildUuid())))
{
return false;
}
if (PENDING_INVITES.containsKey(uuid))
{
PENDING_INVITES.get(uuid).add(guild);
}
else
{
PENDING_INVITES.put(uuid, Lists.newArrayList(guild));
}
return true;
}
public void addGuild(Guild guild)
{
GUILDS.add(guild);
}
public void deleteGuild(UUID owner)
{
GUILDS.removeIf(guild -> guild.getOwner().getUuid().equals(owner));
}
public Optional<Guild> getGuild(UUID uuid)
{
return GUILDS.stream().filter(guild -> (guild.getOwner() != null && guild.getOwner().getUuid().equals(uuid)) || guild.getMembers().stream().map(Member::getUuid).toList().contains(uuid)).findFirst();
}
public Collection<Guild> getGuilds()
{
return GUILDS.stream().toList();
}
}

View File

@ -0,0 +1,28 @@
package dev.plex.guild;
import dev.plex.Guilds;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.util.Optional;
import java.util.UUID;
@Data
public class GuildMember
{
private final UUID uuid;
private int id = 0;
private boolean chat = false;
private boolean prefix = true;
public OfflinePlayer getPlayer()
{
return Bukkit.getOfflinePlayer(uuid);
}
public Optional<Guild> getGuild()
{
return Guilds.get().getGuildData().getGuildByMember(this);
}
}

View File

@ -0,0 +1,29 @@
package dev.plex.guild;
import com.google.common.collect.Lists;
import lombok.Data;
import java.util.List;
import java.util.stream.Collectors;
@Data
public class GuildRank
{
private final String name;
private List<GuildMember> members = Lists.newArrayList();
public void addMember(GuildMember member)
{
members.add(member);
}
public List<String> getMemberNames()
{
return getMembers().stream().map(p -> p.getPlayer().getName()).collect(Collectors.toList());
}
public List<Integer> getMemberIDs()
{
return getMembers().stream().map(GuildMember::getId).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,11 @@
package dev.plex.guild;
import lombok.Data;
import org.bukkit.Location;
@Data
public class GuildWarp
{
private final String name;
private final Location location;
}

View File

@ -1,20 +0,0 @@
package dev.plex.guild.data;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.UUID;
@Data
public class Member
{
private final UUID uuid;
private Rank rank;
private boolean chat, prefix;
public Player getPlayer()
{
return Bukkit.getPlayer(this.uuid);
}
}

View File

@ -1,6 +0,0 @@
package dev.plex.guild.data;
public enum Permission
{
SET_WARP, WARPS, DELETE_WARP, WARP
}

View File

@ -1,5 +0,0 @@
package dev.plex.guild.data;
public record Rank(String name, String prefix)
{
}

View File

@ -1,96 +0,0 @@
package dev.plex.handler;
import dev.plex.Guilds;
import dev.plex.Plex;
import dev.plex.guild.data.Member;
import dev.plex.hook.VaultHook;
import dev.plex.player.PlexPlayer;
import dev.plex.util.PlexUtils;
import dev.plex.util.minimessage.SafeMiniMessage;
import io.papermc.paper.chat.ChatRenderer;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.minimessage.tag.standard.StandardTags;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class ChatHandlerImpl
{
private final static TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder().match("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]").replacement((matchResult, builder) -> Component.empty().content(matchResult.group()).clickEvent(ClickEvent.openUrl(matchResult.group()))).build();
private final PlexChatRenderer renderer = new PlexChatRenderer();
@EventHandler
public void doChat(AsyncChatEvent event)
{
event.renderer(renderer);
Player player = event.getPlayer();
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresent(guild ->
{
Member member = guild.getMember(player.getUniqueId());
if (member == null)
{
return;
}
if (!member.isChat())
{
return;
}
guild.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(player1 ->
{
player1.sendMessage(PlexUtils.messageComponent("guildChatMessage", player.getName(), PlainTextComponentSerializer.plainText().serialize(event.message())));
});
if (Guilds.get().getConfig().isBoolean("guilds.log-chat-message"))
{
Bukkit.getConsoleSender().sendMessage(PlexUtils.messageComponent("guildChatConsoleLog", guild.getName(), guild.getGuildUuid(), player.getName(), PlainTextComponentSerializer.plainText().serialize(event.message())));
}
event.setCancelled(true);
});
}
public static class PlexChatRenderer implements ChatRenderer
{
@Override
public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer)
{
String text = PlexUtils.getTextFromComponent(message);
PlexPlayer plexPlayer = Plex.get().getPlayerCache().getPlexPlayerMap().get(source.getUniqueId());
Component prefix = VaultHook.getPrefix(plexPlayer);
AtomicBoolean guildPrefix = new AtomicBoolean(false);
AtomicReference<Component> component = new AtomicReference<>(Component.empty());
Guilds.get().getGuildHolder().getGuild(source.getUniqueId()).ifPresent(guild ->
{
if (guild.getPrefix() != null)
{
component.set(component.get().append(SafeMiniMessage.mmDeserializeWithoutEvents(guild.getPrefix())));
guildPrefix.set(true);
}
});
if (prefix != null)
{
if (guildPrefix.get())
{
component.set(component.get().append(Component.space()));
}
component.set(component.get().append(prefix));
}
return component.get().append(Component.space()).append(PlexUtils.mmDeserialize(Plex.get().config.getString("chat.name-color", "<white>") + MiniMessage.builder().tags(TagResolver.resolver(StandardTags.color(), StandardTags.rainbow(), StandardTags.decorations(), StandardTags.gradient(), StandardTags.transition())).build().serialize(sourceDisplayName))).append(Component.space()).append(Component.text("»").color(NamedTextColor.GRAY)).append(Component.space()).append(SafeMiniMessage.mmDeserializeWithoutEvents(text)).replaceText(URL_REPLACEMENT_CONFIG);
}
}
}

View File

@ -0,0 +1,80 @@
package dev.plex.listener;
import dev.plex.Guilds;
import dev.plex.guild.GuildMember;
import dev.plex.util.minimessage.SafeMiniMessage;
import io.papermc.paper.chat.ChatRenderer;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicReference;
public class ChatListener extends PlexListener
{
private GuildChatRenderer guildChatRenderer = null;
@EventHandler(priority = EventPriority.HIGHEST)
public void onAsyncChat(AsyncChatEvent event)
{
if (event.isCancelled())
{
return;
}
if (guildChatRenderer == null)
{
guildChatRenderer = new GuildChatRenderer(event.renderer());
}
event.renderer(guildChatRenderer);
final Player player = event.getPlayer();
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
member.getGuild().ifPresent(guild ->
{
if (member.isChat())
{
guild.chat(player, event.message());
event.setCancelled(true);
}
});
}
private record GuildChatRenderer(ChatRenderer renderer) implements ChatRenderer
{
@Override
public @NotNull Component render(@NotNull Player player, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience audience)
{
Component outcome = Component.empty();
GuildMember member = Guilds.get().getMemberData().getMember(player).orElseThrow();
AtomicReference<String> atomicPrefix = new AtomicReference<>(null);
member.getGuild().ifPresent(guild ->
{
if (guild.isPrefixEnabled())
{
String rankName = "";
if (guild.getRankByMember(member).isPresent())
{
rankName = guild.getRankByMember(member).get().getName();
}
atomicPrefix.set(guild.getPrefix().replace("%rank%", rankName).replace("%name%", guild.getDisplayName()));
}
});
if (atomicPrefix.get() != null && member.isPrefix())
{
outcome = outcome.append(SafeMiniMessage.mmDeserializeWithoutEvents(atomicPrefix.get())).append(Component.space());
}
outcome = outcome.append(renderer.render(player, sourceDisplayName, message, audience));
return outcome;
}
}
}

View File

@ -0,0 +1,31 @@
package dev.plex.listener;
import dev.plex.Guilds;
import dev.plex.guild.GuildMember;
import dev.plex.util.PlexUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerJoinEvent;
public class JoinListener extends PlexListener
{
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerJoin(PlayerJoinEvent event)
{
final Player player = event.getPlayer();
GuildMember member = Guilds.get().getMemberData().getMember(player).orElse(Guilds.get().getMemberData().addNewMember(player));
if (member == null)
{
throw new RuntimeException("Unable to obtain member data for %s".formatted(player.getName()));
}
member.getGuild().ifPresent(guild ->
{
if (guild.getMotd() != null)
{
player.sendMessage(PlexUtils.mmDeserialize(guild.getMotd()));
}
});
}
}

View File

@ -1,23 +0,0 @@
package dev.plex.util;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@Data
public class CustomLocation
{
private final String worldName;
private final double x, y, z;
private final float yaw, pitch;
public static CustomLocation fromLocation(Location location)
{
return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
public Location toLocation()
{
return new Location(Bukkit.getWorld(worldName), x, y, z, yaw, pitch);
}
}

View File

@ -1,14 +0,0 @@
package dev.plex.util;
import dev.plex.Plex;
import org.bukkit.Bukkit;
public class GuildUtil
{
public static void throwExceptionSync(Throwable throwable)
{
Bukkit.getScheduler().runTask(Plex.get(), () -> throwable.printStackTrace());
}
}