mirror of
https://github.com/plexusorg/Module-Guilds.git
synced 2026-06-04 02:36:54 +00:00
Update Guilds
This commit is contained in:
@@ -21,7 +21,6 @@ dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
||||
implementation("org.apache.commons:commons-lang3:3.20.0")
|
||||
compileOnly("dev.plex:api:2.0-SNAPSHOT")
|
||||
compileOnly("org.json:json:20251224")
|
||||
implementation("org.jetbrains:annotations:26.1.0")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,24 @@ package dev.plex;
|
||||
|
||||
import dev.plex.command.GuildCommand;
|
||||
import dev.plex.config.ModuleConfig;
|
||||
import dev.plex.data.SQLGuildManager;
|
||||
import dev.plex.data.SQLManager;
|
||||
import dev.plex.guild.GuildHolder;
|
||||
import dev.plex.handler.ChatHandlerImpl;
|
||||
import dev.plex.module.PlexModule;
|
||||
import dev.plex.api.storage.ModuleStorage;
|
||||
import dev.plex.storage.GuildRepository;
|
||||
import dev.plex.storage.OrmGuildRepository;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class Guilds extends PlexModule
|
||||
{
|
||||
private static Guilds module;
|
||||
private final GuildHolder guildHolder = new GuildHolder();
|
||||
|
||||
private SQLGuildManager sqlGuildManager;
|
||||
private GuildRepository guildRepository;
|
||||
|
||||
private ModuleConfig config;
|
||||
|
||||
@@ -31,9 +36,17 @@ public class Guilds extends PlexModule
|
||||
@Override
|
||||
public void enable()
|
||||
{
|
||||
SQLManager.makeTables();
|
||||
sqlGuildManager = new SQLGuildManager();
|
||||
sqlGuildManager.getGuilds().whenComplete((guilds, throwable) ->
|
||||
ModuleStorage storage = api().storage().forModule(this);
|
||||
try
|
||||
{
|
||||
storage.migrations().run(List.of("001_initial_schema"));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to run Guilds migrations", e);
|
||||
}
|
||||
guildRepository = new OrmGuildRepository(storage);
|
||||
guildRepository.loadGuilds().whenComplete((guilds, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
@@ -46,18 +59,15 @@ public class Guilds extends PlexModule
|
||||
return;
|
||||
}
|
||||
api().logging().debug("Finished loading {0} guilds", guilds.size());
|
||||
guilds.forEach(guildHolder::addGuild);
|
||||
guildHolder.replaceAll(guilds);
|
||||
});
|
||||
registerListener(new ChatHandlerImpl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable()
|
||||
{
|
||||
// Unregistering listeners / commands is handled by Plex
|
||||
if (sqlGuildManager != null)
|
||||
{
|
||||
this.getGuildHolder().getGuilds().forEach(sqlGuildManager::updateGuild);
|
||||
}
|
||||
guildHolder.clear();
|
||||
}
|
||||
|
||||
public static Guilds get()
|
||||
|
||||
@@ -30,6 +30,8 @@ public class GuildCommand extends SimplePlexCommand
|
||||
.permission("plex.guilds.guild")
|
||||
.build());
|
||||
this.registerSubCommand(new CreateSubCommand());
|
||||
this.registerSubCommand(new DisbandSubCommand());
|
||||
this.registerSubCommand(new LeaveSubCommand());
|
||||
this.registerSubCommand(new InfoSubCommand());
|
||||
this.registerSubCommand(new PrefixSubCommand());
|
||||
this.registerSubCommand(new SetWarpSubCommand());
|
||||
@@ -40,6 +42,8 @@ public class GuildCommand extends SimplePlexCommand
|
||||
this.registerSubCommand(new HomeSubCommand());
|
||||
this.registerSubCommand(new OwnerSubCommand());
|
||||
this.registerSubCommand(new InviteSubCommand());
|
||||
this.registerSubCommand(new AcceptSubCommand());
|
||||
this.registerSubCommand(new DenySubCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package dev.plex.command.sub;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.guild.Guild;
|
||||
import dev.plex.guild.data.GuildRole;
|
||||
import dev.plex.guild.data.Member;
|
||||
import dev.plex.storage.entity.GuildInviteEntity;
|
||||
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;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AcceptSubCommand extends SimplePlexCommand
|
||||
{
|
||||
public AcceptSubCommand()
|
||||
{
|
||||
super(command("accept")
|
||||
.description("Accepts a guild invite")
|
||||
.usage("/guild <command> <guild>")
|
||||
.permission("plex.guilds.accept")
|
||||
.source(RequiredCommandSource.IN_GAME)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
return usage();
|
||||
}
|
||||
assert player != null;
|
||||
Guilds.get().getGuildRepository().invitesFor(player.getUniqueId()).whenComplete((invites, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
GuildInviteEntity invite = findInvite(invites, String.join(" ", args));
|
||||
if (invite == null)
|
||||
{
|
||||
send(player, messageComponent("guildNotValidInvite"));
|
||||
return;
|
||||
}
|
||||
if (invite.getExpiresAt() < Instant.now().toEpochMilli())
|
||||
{
|
||||
Guilds.get().getGuildRepository().deleteInvite(UUID.fromString(invite.getGuildUuid()), player.getUniqueId());
|
||||
send(player, messageComponent("guildInviteExpired"));
|
||||
return;
|
||||
}
|
||||
Guild target = Guilds.get().getGuildHolder().guildById(UUID.fromString(invite.getGuildUuid())).orElse(null);
|
||||
if (target == null)
|
||||
{
|
||||
send(player, messageComponent("guildNotValidInvite"));
|
||||
return;
|
||||
}
|
||||
leaveCurrentIfNeeded(player, target, invite);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
private GuildInviteEntity findInvite(List<GuildInviteEntity> invites, String guildName)
|
||||
{
|
||||
return invites.stream()
|
||||
.filter(invite -> Guilds.get().getGuildHolder().guildById(UUID.fromString(invite.getGuildUuid()))
|
||||
.map(guild -> guild.getName().equalsIgnoreCase(guildName))
|
||||
.orElse(false))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private void leaveCurrentIfNeeded(Player player, Guild target, GuildInviteEntity invite)
|
||||
{
|
||||
Guilds.get().getGuildHolder().guild(player.getUniqueId()).ifPresentOrElse(current ->
|
||||
{
|
||||
if (current.getGuildUuid().equals(target.getGuildUuid()))
|
||||
{
|
||||
send(player, messageComponent("guildInThis"));
|
||||
return;
|
||||
}
|
||||
if (current.isOwner(player.getUniqueId()) && current.getMembers().size() > 1)
|
||||
{
|
||||
send(player, messageComponent("guildOwnerLeaveBlocked"));
|
||||
return;
|
||||
}
|
||||
if (current.isOwner(player.getUniqueId()))
|
||||
{
|
||||
Guilds.get().getGuildRepository().deleteGuild(current.getGuildUuid()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildHolder().removeGuild(current.getGuildUuid());
|
||||
joinTarget(player, target, invite);
|
||||
});
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().removeMember(current.getGuildUuid(), player.getUniqueId()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
current.getMembers().removeIf(member -> member.getUuid().equals(player.getUniqueId()));
|
||||
Guilds.get().getGuildHolder().unindexMember(player.getUniqueId());
|
||||
current.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(memberPlayer ->
|
||||
send(memberPlayer, messageComponent("guildMemberLeft", player.getName())));
|
||||
joinTarget(player, target, invite);
|
||||
});
|
||||
}, () -> joinTarget(player, target, invite));
|
||||
}
|
||||
|
||||
private void joinTarget(Player player, Guild guild, GuildInviteEntity invite)
|
||||
{
|
||||
UUID guildUuid = guild.getGuildUuid();
|
||||
Guilds.get().getGuildRepository().addMember(guildUuid, player.getUniqueId(), GuildRole.MEMBER)
|
||||
.thenCompose(unused -> Guilds.get().getGuildRepository().deleteInvite(guildUuid, player.getUniqueId()))
|
||||
.whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.addMember(player.getUniqueId());
|
||||
Guilds.get().getGuildHolder().indexMember(guildUuid, player.getUniqueId());
|
||||
guild.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(memberPlayer ->
|
||||
send(memberPlayer, messageComponent("guildMemberJoined", player.getName())));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<String> suggestions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException
|
||||
{
|
||||
if (!(sender instanceof Player player) || args.length != 1)
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
try
|
||||
{
|
||||
return Guilds.get().getGuildRepository().invitesFor(player.getUniqueId()).join().stream()
|
||||
.map(invite -> Guilds.get().getGuildHolder().guildById(UUID.fromString(invite.getGuildUuid())).orElse(null))
|
||||
.filter(Objects::nonNull)
|
||||
.map(Guild::getName)
|
||||
.toList();
|
||||
}
|
||||
catch (RuntimeException ignored)
|
||||
{
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,10 +38,15 @@ public class CreateSubCommand extends SimplePlexCommand
|
||||
{
|
||||
return messageComponent("alreadyInGuild");
|
||||
}
|
||||
Guilds.get().getSqlGuildManager().insertGuild(Guild.create(player, StringUtils.join(args, " "))).whenComplete((guild, throwable) ->
|
||||
Guilds.get().getGuildRepository().createGuild(player, StringUtils.join(args, " ")).whenComplete((guild, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildHolder().addGuild(guild);
|
||||
send(player, mmString("Created guild named " + guild.getName()));
|
||||
send(player, messageComponent("guildCreated", guild.getName()));
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package dev.plex.command.sub;
|
||||
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.storage.entity.GuildInviteEntity;
|
||||
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;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class DenySubCommand extends SimplePlexCommand
|
||||
{
|
||||
public DenySubCommand()
|
||||
{
|
||||
super(command("deny")
|
||||
.description("Denies a guild invite")
|
||||
.usage("/guild <command> <guild>")
|
||||
.permission("plex.guilds.deny")
|
||||
.source(RequiredCommandSource.IN_GAME)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
return usage();
|
||||
}
|
||||
assert player != null;
|
||||
Guilds.get().getGuildRepository().invitesFor(player.getUniqueId()).whenComplete((invites, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
GuildInviteEntity invite = invites.stream()
|
||||
.filter(candidate -> Guilds.get().getGuildHolder().guildById(UUID.fromString(candidate.getGuildUuid()))
|
||||
.map(guild -> guild.getName().equalsIgnoreCase(String.join(" ", args)))
|
||||
.orElse(false))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (invite == null)
|
||||
{
|
||||
send(player, messageComponent("guildNotValidInvite"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().deleteInvite(UUID.fromString(invite.getGuildUuid()), player.getUniqueId()).whenComplete((unused, deleteThrowable) ->
|
||||
{
|
||||
if (deleteThrowable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
send(player, messageComponent("guildInviteDenied"));
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.plex.command.sub;
|
||||
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
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 class DisbandSubCommand extends SimplePlexCommand
|
||||
{
|
||||
public DisbandSubCommand()
|
||||
{
|
||||
super(command("disband")
|
||||
.description("Disbands your guild")
|
||||
.usage("/guild <command>")
|
||||
.permission("plex.guilds.disband")
|
||||
.source(RequiredCommandSource.IN_GAME)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||
{
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().guild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().deleteGuild(guild.getGuildUuid()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildHolder().removeGuild(guild.getGuildUuid());
|
||||
send(player, messageComponent("guildDisbanded"));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import dev.plex.Guilds;
|
||||
import dev.plex.api.player.PlexPlayerView;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.guild.Guild;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -31,29 +32,51 @@ public class InfoSubCommand extends SimplePlexCommand
|
||||
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a");
|
||||
|
||||
@Override
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] strings)
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||
{
|
||||
assert player != null;
|
||||
CompletableFuture.runAsync(() ->
|
||||
{
|
||||
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
Guild guild = resolveGuild(player, args);
|
||||
if (guild == null)
|
||||
{
|
||||
send(player, messageComponent("guildNotFound"));
|
||||
return;
|
||||
}
|
||||
{
|
||||
send(player, mmString("<gradient:yellow:gold>====<aqua>" + guild.getName() + "<gradient:yellow:gold>===="));
|
||||
send(player, mmString(""));
|
||||
send(player, mmString("<gold>Owner: <yellow>" + playerName(guild.getOwner().getUuid())));
|
||||
List<String> members = guild.getMembers().stream().filter(member -> !member.getUuid().equals(guild.getOwner().getUuid())).map(member -> playerName(member.getUuid())).toList();
|
||||
send(player, mmString("<gold>Owner: <yellow>" + playerName(guild.getOwnerUuid())));
|
||||
List<String> members = guild.getMembers().stream().filter(member -> !member.getUuid().equals(guild.getOwnerUuid())).map(member -> playerName(member.getUuid())).toList();
|
||||
send(player, mmString("<gold>Members (" + members.size() + "): " + StringUtils.join(members, ", ")));
|
||||
send(player, mmString("<gold>Moderators (" + guild.getModerators().size() + "): " + StringUtils.join(guild.getModerators().stream().map(this::playerName).toList(), ", ")));
|
||||
send(player, mmString("<gold>Prefix: " + (guild.getPrefix() == null ? "N/A" : guild.getPrefix())));
|
||||
send(player, mmString("<gold>Created At: " + formatter.format(guild.getCreatedAt())));
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
}
|
||||
}, Guilds.get().api().scheduler().asyncExecutor());
|
||||
return null;
|
||||
}
|
||||
|
||||
private Guild resolveGuild(Player sender, String[] args)
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
return Guilds.get().getGuildHolder().guild(sender.getUniqueId()).orElse(null);
|
||||
}
|
||||
PlexPlayerView player = api().players().byName(args[0]).orElse(null);
|
||||
if (player != null)
|
||||
{
|
||||
Guild guild = Guilds.get().getGuildHolder().guild(player.uuid()).orElse(null);
|
||||
if (guild != null)
|
||||
{
|
||||
return guild;
|
||||
}
|
||||
}
|
||||
return Guilds.get().getGuildHolder().guildByName(StringUtils.join(args, " ")).orElse(null);
|
||||
}
|
||||
|
||||
private String playerName(java.util.UUID uuid)
|
||||
{
|
||||
return api().players().byUuid(uuid).map(PlexPlayerView::name).orElse("Unable to load cache...");
|
||||
return api().players().player(uuid).map(PlexPlayerView::name).orElse(uuid.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,23 +4,15 @@ import com.google.common.collect.ImmutableList;
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.guild.Guild;
|
||||
import dev.plex.guild.GuildHolder;
|
||||
import dev.plex.guild.data.Member;
|
||||
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.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
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
|
||||
|
||||
public class InviteSubCommand extends SimplePlexCommand
|
||||
{
|
||||
@@ -43,75 +35,34 @@ public class InviteSubCommand extends SimplePlexCommand
|
||||
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()))
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
}
|
||||
Player target = getNonNullPlayer(args[0]);
|
||||
boolean invite = GuildHolder.sendInvite(target.getUniqueId(), guild);
|
||||
if (!invite)
|
||||
if (target.getUniqueId().equals(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildInviteExists"));
|
||||
send(player, messageComponent("guildCannotInviteSelf"));
|
||||
return;
|
||||
}
|
||||
send(player, messageComponent("guildInviteSent", target.getName()));
|
||||
send(target, messageComponent("guildInviteReceived", player.getName(), guild.getName()));
|
||||
if (guild.getMember(target.getUniqueId()) != null || Guilds.get().getGuildHolder().guild(target.getUniqueId()).isPresent())
|
||||
{
|
||||
send(player, messageComponent("guildTargetAlreadyInGuild"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().createInvite(guild.getGuildUuid(), player.getUniqueId(), target.getUniqueId(), Instant.now().plus(5, ChronoUnit.MINUTES)).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
send(player, messageComponent("guildInviteSent", target.getName()));
|
||||
send(target, messageComponent("guildInviteReceived", player.getName(), guild.getName()));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
@@ -119,23 +70,6 @@ public class InviteSubCommand extends SimplePlexCommand
|
||||
@Override
|
||||
protected @NotNull List<String> suggestions(@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();
|
||||
}
|
||||
api().logging().debug("Completing pending guild invites");
|
||||
return GuildHolder.PENDING_INVITES.get(player.getUniqueId()).stream().map(Guild::getName).collect(Collectors.toList());
|
||||
}
|
||||
return ImmutableList.of();
|
||||
return args.length == 1 ? onlinePlayerNames() : ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.plex.command.sub;
|
||||
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.guild.data.Member;
|
||||
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;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class LeaveSubCommand extends SimplePlexCommand
|
||||
{
|
||||
public LeaveSubCommand()
|
||||
{
|
||||
super(command("leave")
|
||||
.description("Leaves your guild")
|
||||
.usage("/guild <command>")
|
||||
.permission("plex.guilds.leave")
|
||||
.source(RequiredCommandSource.IN_GAME)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||
{
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().guild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
if (guild.getMembers().size() > 1)
|
||||
{
|
||||
send(player, messageComponent("guildOwnerLeaveBlocked"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().deleteGuild(guild.getGuildUuid()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildHolder().removeGuild(guild.getGuildUuid());
|
||||
send(player, messageComponent("guildAutoDisbanded"));
|
||||
});
|
||||
return;
|
||||
}
|
||||
Guilds.get().getGuildRepository().removeMember(guild.getGuildUuid(), player.getUniqueId()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.getMembers().removeIf(member -> member.getUuid().equals(player.getUniqueId()));
|
||||
Guilds.get().getGuildHolder().unindexMember(player.getUniqueId());
|
||||
guild.getMembers().stream().map(Member::getPlayer).filter(Objects::nonNull).forEach(memberPlayer ->
|
||||
send(memberPlayer, messageComponent("guildMemberLeft", player.getName())));
|
||||
send(player, messageComponent("guildLeft"));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import dev.plex.Guilds;
|
||||
import dev.plex.api.player.PlexPlayerView;
|
||||
import dev.plex.command.SimplePlexCommand;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import dev.plex.guild.data.GuildRole;
|
||||
import dev.plex.guild.data.Member;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -20,7 +21,7 @@ public class OwnerSubCommand extends SimplePlexCommand
|
||||
super(command("owner")
|
||||
.description("Sets the guild owner")
|
||||
.usage("/guild <command> <player name>")
|
||||
.aliases("setowner")
|
||||
.aliases("setowner,promote")
|
||||
.permission("plex.guilds.owner")
|
||||
.source(RequiredCommandSource.IN_GAME)
|
||||
.build());
|
||||
@@ -36,7 +37,7 @@ public class OwnerSubCommand extends SimplePlexCommand
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
@@ -54,10 +55,21 @@ public class OwnerSubCommand extends SimplePlexCommand
|
||||
send(player, messageComponent("guildMemberNotFound"));
|
||||
return;
|
||||
}
|
||||
guild.setOwner(member);
|
||||
guild.getMembers().remove(member);
|
||||
guild.getMembers().add(memberSender);
|
||||
send(player, messageComponent("guildOwnerSet", plexPlayer.name()));
|
||||
Guilds.get().getGuildRepository().transferOwner(guild.getGuildUuid(), member.getUuid(), player.getUniqueId()).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.setOwnerUuid(member.getUuid());
|
||||
member.setRole(GuildRole.OWNER);
|
||||
if (memberSender != null)
|
||||
{
|
||||
memberSender.setRole(GuildRole.MEMBER);
|
||||
}
|
||||
send(player, messageComponent("guildOwnerSet", plexPlayer.name()));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -36,19 +36,36 @@ public class PrefixSubCommand extends SimplePlexCommand
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
}
|
||||
if (args[0].equalsIgnoreCase("clear") || args[0].equalsIgnoreCase("off"))
|
||||
{
|
||||
guild.setPrefix(null);
|
||||
send(player, messageComponent("guildPrefixCleared"));
|
||||
Guilds.get().getGuildRepository().updatePrefix(guild.getGuildUuid(), null).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.setPrefix(null);
|
||||
send(player, messageComponent("guildPrefixCleared"));
|
||||
});
|
||||
return;
|
||||
}
|
||||
guild.setPrefix(StringUtils.join(args, " "));
|
||||
send(player, messageComponent("guildPrefixSet", GuildUtil.miniMessageWithoutEvents(guild.getPrefix())));
|
||||
String prefix = StringUtils.join(args, " ");
|
||||
Guilds.get().getGuildRepository().updatePrefix(guild.getGuildUuid(), prefix).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.setPrefix(prefix);
|
||||
send(player, messageComponent("guildPrefixSet", GuildUtil.miniMessageWithoutEvents(guild.getPrefix())));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SetHomeSubCommand extends SimplePlexCommand
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
@@ -43,12 +43,29 @@ public class SetHomeSubCommand extends SimplePlexCommand
|
||||
send(player, messageComponent("guildHomeNotFound"));
|
||||
return;
|
||||
}
|
||||
guild.setHome(null);
|
||||
send(player, messageComponent("guildHomeRemoved"));
|
||||
Guilds.get().getGuildRepository().updateHome(guild.getGuildUuid(), null).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.setHome(null);
|
||||
send(player, messageComponent("guildHomeRemoved"));
|
||||
});
|
||||
return;
|
||||
}
|
||||
guild.setHome(CustomLocation.fromLocation(player.getLocation()));
|
||||
send(player, messageComponent("guildHomeSet"));
|
||||
CustomLocation home = CustomLocation.fromLocation(player.getLocation());
|
||||
Guilds.get().getGuildRepository().updateHome(guild.getGuildUuid(), home).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.setHome(home);
|
||||
send(player, messageComponent("guildHomeSet"));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class SetWarpSubCommand extends SimplePlexCommand
|
||||
assert player != null;
|
||||
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||
{
|
||||
if (!guild.getOwner().getUuid().equals(player.getUniqueId()))
|
||||
if (!guild.isOwner(player.getUniqueId()))
|
||||
{
|
||||
send(player, messageComponent("guildNotOwner"));
|
||||
return;
|
||||
@@ -48,18 +48,23 @@ public class SetWarpSubCommand extends SimplePlexCommand
|
||||
send(player, mmString("<red>The max length of a warp name is 16 characters!"));
|
||||
return;
|
||||
}
|
||||
if (guild.getWarps().containsKey(warpName.toLowerCase()))
|
||||
{
|
||||
send(player, messageComponent("guildWarpExists", warpName));
|
||||
return;
|
||||
}
|
||||
if (!StringUtils.isAlphanumericSpace(warpName.toLowerCase(Locale.ROOT)))
|
||||
{
|
||||
send(player, messageComponent("guildWarpAlphanumeric"));
|
||||
return;
|
||||
}
|
||||
guild.getWarps().put(warpName.toLowerCase(), CustomLocation.fromLocation(player.getLocation()));
|
||||
send(player, messageComponent("guildWarpCreated", warpName));
|
||||
CustomLocation location = CustomLocation.fromLocation(player.getLocation());
|
||||
String localName = warpName.toLowerCase(Locale.ROOT);
|
||||
Guilds.get().getGuildRepository().upsertWarp(guild.getGuildUuid(), localName, location).whenComplete((unused, throwable) ->
|
||||
{
|
||||
if (throwable != null)
|
||||
{
|
||||
send(player, messageComponent("guildStorageFailed"));
|
||||
return;
|
||||
}
|
||||
guild.getWarps().put(localName, location);
|
||||
send(player, messageComponent("guildWarpCreated", warpName));
|
||||
});
|
||||
}, () -> send(player, messageComponent("guildNotFound")));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
package dev.plex.data;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import dev.plex.Guilds;
|
||||
import com.google.gson.Gson;
|
||||
import dev.plex.guild.Guild;
|
||||
import dev.plex.guild.data.Member;
|
||||
import dev.plex.util.CustomLocation;
|
||||
import dev.plex.util.GuildUtil;
|
||||
|
||||
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 supplyStorageAsync(connection ->
|
||||
{
|
||||
try (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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> deleteGuild(UUID uuid)
|
||||
{
|
||||
return supplyStorageAsync(connection ->
|
||||
{
|
||||
try (PreparedStatement statement = connection.prepareStatement(DELETE_GUILD))
|
||||
{
|
||||
statement.setString(1, uuid.toString());
|
||||
statement.execute();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Guild> updateGuild(Guild guild)
|
||||
{
|
||||
return supplyStorageAsync(connection ->
|
||||
{
|
||||
try (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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<Guild> getGuildsSync(Connection connection) throws SQLException
|
||||
{
|
||||
List<Guild> guilds = Lists.newArrayList();
|
||||
try (PreparedStatement statement = connection.prepareStatement(SELECT_GUILD);
|
||||
ResultSet set = statement.executeQuery())
|
||||
{
|
||||
while (set.next())
|
||||
{
|
||||
String timezone = Guilds.get().api().configuration().mainConfig().getString("server.timezone", "Etc/UTC");
|
||||
Guild guild = new Guild(UUID.fromString(set.getString("guildUuid")),
|
||||
ZonedDateTime.ofInstant(Instant.ofEpochMilli(set.getLong("createdAt")), ZoneId.of(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());
|
||||
if (members != null)
|
||||
{
|
||||
members.forEach(guild::addMember);
|
||||
}
|
||||
List<String> moderators = new Gson().fromJson(set.getString("moderators"), new TypeToken<List<String>>()
|
||||
{
|
||||
}.getType());
|
||||
if (moderators != null)
|
||||
{
|
||||
moderators.stream().map(UUID::fromString).forEach(guild.getModerators()::add);
|
||||
}
|
||||
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());
|
||||
if (warps != null)
|
||||
{
|
||||
Guilds.get().api().logging().debug("Loaded {0} warps for {1} guild", warps.size(), guild.getName());
|
||||
guild.getWarps().putAll(warps);
|
||||
}
|
||||
guild.setPublic(set.getBoolean("isPublic"));
|
||||
guilds.add(guild);
|
||||
}
|
||||
}
|
||||
return guilds;
|
||||
}
|
||||
|
||||
public CompletableFuture<List<Guild>> getGuilds()
|
||||
{
|
||||
return supplyStorageAsync(this::getGuildsSync);
|
||||
}
|
||||
|
||||
private <T> CompletableFuture<T> supplyStorageAsync(dev.plex.api.storage.StorageApi.SqlFunction<T> function)
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return Guilds.get().api().storage().withConnection(function);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
GuildUtil.throwExceptionSync(e);
|
||||
return null;
|
||||
}
|
||||
}, Guilds.get().api().scheduler().asyncExecutor());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package dev.plex.data;
|
||||
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.util.GuildUtil;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class SQLManager
|
||||
{
|
||||
public static void makeTables()
|
||||
{
|
||||
try
|
||||
{
|
||||
Guilds.get().api().storage().withConnection(connection ->
|
||||
{
|
||||
try (PreparedStatement statement = 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`)" +
|
||||
");"))
|
||||
{
|
||||
statement.execute();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
GuildUtil.throwExceptionSync(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package dev.plex.guild;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.guild.data.GuildRole;
|
||||
import dev.plex.guild.data.Member;
|
||||
import dev.plex.guild.data.Rank;
|
||||
import dev.plex.util.CustomLocation;
|
||||
import dev.plex.util.GuildUtil;
|
||||
import lombok.Data;
|
||||
@@ -23,51 +23,43 @@ public class Guild
|
||||
private final UUID guildUuid;
|
||||
private final ZonedDateTime 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 Member owner;
|
||||
private UUID ownerUuid;
|
||||
private String prefix;
|
||||
private String motd;
|
||||
private CustomLocation home;
|
||||
private boolean tagEnabled;
|
||||
private Rank defaultRank = new Rank("default", null);
|
||||
private boolean isPublic = false;
|
||||
|
||||
private boolean tagEnabled = true;
|
||||
private boolean isPublic;
|
||||
|
||||
public static Guild create(Player player, String guildName)
|
||||
{
|
||||
String timezone = Guilds.get().api().configuration().mainConfig().getString("server.timezone", "Etc/UTC");
|
||||
Guild guild = new Guild(UUID.randomUUID(), ZonedDateTime.now(ZoneId.of(timezone)));
|
||||
guild.setName(PlainTextComponentSerializer.plainText().serialize(GuildUtil.miniMessageWithoutEvents(guildName)));
|
||||
guild.setOwner(new Member(player.getUniqueId()));
|
||||
guild.setOwnerUuid(player.getUniqueId());
|
||||
guild.addMember(new Member(player.getUniqueId(), GuildRole.OWNER));
|
||||
return guild;
|
||||
}
|
||||
|
||||
public Member getMember(UUID uuid)
|
||||
{
|
||||
if (owner.getUuid().equals(uuid))
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
return members.stream().filter(m -> m.getUuid().equals(uuid)).findFirst().orElse(null);
|
||||
return members.stream().filter(member -> member.getUuid().equals(uuid)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public void addMember(UUID uuid)
|
||||
{
|
||||
addMember(new Member(uuid));
|
||||
addMember(new Member(uuid, GuildRole.MEMBER));
|
||||
}
|
||||
|
||||
public void addMember(Member member)
|
||||
{
|
||||
this.members.add(member);
|
||||
members.removeIf(existing -> existing.getUuid().equals(member.getUuid()));
|
||||
members.add(member);
|
||||
}
|
||||
|
||||
public List<Member> getMembers()
|
||||
public boolean isOwner(UUID uuid)
|
||||
{
|
||||
List<Member> allMembers = Lists.newArrayList(members);
|
||||
allMembers.add(owner);
|
||||
return allMembers;
|
||||
return ownerUuid != null && ownerUuid.equals(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,84 @@
|
||||
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.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class GuildHolder
|
||||
{
|
||||
public static final Map<UUID, List<Guild>> PENDING_INVITES = Maps.newHashMap();
|
||||
private static final List<Guild> GUILDS = Lists.newArrayList();
|
||||
private final Map<UUID, Guild> guildsById = new ConcurrentHashMap<>();
|
||||
private final Map<UUID, UUID> guildByPlayer = new ConcurrentHashMap<>();
|
||||
|
||||
public static boolean sendInvite(UUID uuid, Guild guild)
|
||||
public void replaceAll(Collection<Guild> guilds)
|
||||
{
|
||||
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;
|
||||
guildsById.clear();
|
||||
guildByPlayer.clear();
|
||||
guilds.forEach(this::addGuild);
|
||||
}
|
||||
|
||||
public Optional<Guild> guild(UUID playerUuid)
|
||||
{
|
||||
UUID guildUuid = guildByPlayer.get(playerUuid);
|
||||
return guildUuid == null ? Optional.empty() : Optional.ofNullable(guildsById.get(guildUuid));
|
||||
}
|
||||
|
||||
public Optional<Guild> guildById(UUID guildUuid)
|
||||
{
|
||||
return Optional.ofNullable(guildsById.get(guildUuid));
|
||||
}
|
||||
|
||||
public Optional<Guild> guildByName(String name)
|
||||
{
|
||||
return guildsById.values().stream().filter(guild -> guild.getName().equalsIgnoreCase(name)).findFirst();
|
||||
}
|
||||
|
||||
public Collection<Guild> guilds()
|
||||
{
|
||||
return guildsById.values();
|
||||
}
|
||||
|
||||
public void addGuild(Guild guild)
|
||||
{
|
||||
GUILDS.add(guild);
|
||||
guildsById.put(guild.getGuildUuid(), guild);
|
||||
guild.getMembers().stream().map(Member::getUuid).forEach(playerUuid -> indexMember(guild.getGuildUuid(), playerUuid));
|
||||
}
|
||||
|
||||
public void deleteGuild(UUID owner)
|
||||
public void removeGuild(UUID guildUuid)
|
||||
{
|
||||
GUILDS.removeIf(guild -> guild.getOwner().getUuid().equals(owner));
|
||||
Guild removed = guildsById.remove(guildUuid);
|
||||
if (removed != null)
|
||||
{
|
||||
removed.getMembers().stream().map(Member::getUuid).forEach(guildByPlayer::remove);
|
||||
}
|
||||
}
|
||||
|
||||
public void indexMember(UUID guildUuid, UUID playerUuid)
|
||||
{
|
||||
guildByPlayer.put(playerUuid, guildUuid);
|
||||
}
|
||||
|
||||
public void unindexMember(UUID playerUuid)
|
||||
{
|
||||
guildByPlayer.remove(playerUuid);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
guildsById.clear();
|
||||
guildByPlayer.clear();
|
||||
}
|
||||
|
||||
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();
|
||||
return guild(uuid);
|
||||
}
|
||||
|
||||
public Collection<Guild> getGuilds()
|
||||
{
|
||||
return GUILDS.stream().toList();
|
||||
return guilds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.plex.guild.data;
|
||||
|
||||
public enum GuildRole
|
||||
{
|
||||
OWNER,
|
||||
MEMBER
|
||||
}
|
||||
@@ -10,8 +10,19 @@ import java.util.UUID;
|
||||
public class Member
|
||||
{
|
||||
private final UUID uuid;
|
||||
private Rank rank;
|
||||
private boolean chat, prefix;
|
||||
private GuildRole role;
|
||||
private boolean chat;
|
||||
|
||||
public Member(UUID uuid)
|
||||
{
|
||||
this(uuid, GuildRole.MEMBER);
|
||||
}
|
||||
|
||||
public Member(UUID uuid, GuildRole role)
|
||||
{
|
||||
this.uuid = uuid;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package dev.plex.guild.data;
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
SET_WARP, WARPS, DELETE_WARP, WARP
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package dev.plex.guild.data;
|
||||
|
||||
public record Rank(String name, String prefix)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.plex.storage;
|
||||
|
||||
import dev.plex.guild.Guild;
|
||||
import dev.plex.guild.data.GuildRole;
|
||||
import dev.plex.storage.entity.GuildInviteEntity;
|
||||
import dev.plex.util.CustomLocation;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface GuildRepository
|
||||
{
|
||||
CompletableFuture<List<Guild>> loadGuilds();
|
||||
|
||||
CompletableFuture<Guild> createGuild(Player owner, String name);
|
||||
|
||||
CompletableFuture<Void> deleteGuild(UUID guildUuid);
|
||||
|
||||
CompletableFuture<Void> addMember(UUID guildUuid, UUID playerUuid, GuildRole role);
|
||||
|
||||
CompletableFuture<Void> removeMember(UUID guildUuid, UUID playerUuid);
|
||||
|
||||
CompletableFuture<Void> transferOwner(UUID guildUuid, UUID newOwnerUuid, UUID oldOwnerUuid);
|
||||
|
||||
CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix);
|
||||
|
||||
CompletableFuture<Void> updateHome(UUID guildUuid, CustomLocation home);
|
||||
|
||||
CompletableFuture<Void> upsertWarp(UUID guildUuid, String name, CustomLocation location);
|
||||
|
||||
CompletableFuture<Void> deleteWarp(UUID guildUuid, String name);
|
||||
|
||||
CompletableFuture<Void> createInvite(UUID guildUuid, UUID inviterUuid, UUID inviteeUuid, Instant expiresAt);
|
||||
|
||||
CompletableFuture<Void> deleteInvite(UUID guildUuid, UUID inviteeUuid);
|
||||
|
||||
CompletableFuture<List<GuildInviteEntity>> invitesFor(UUID inviteeUuid);
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package dev.plex.storage;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.stmt.DeleteBuilder;
|
||||
import dev.plex.Guilds;
|
||||
import dev.plex.api.storage.ModuleStorage;
|
||||
import dev.plex.guild.Guild;
|
||||
import dev.plex.guild.data.GuildRole;
|
||||
import dev.plex.guild.data.Member;
|
||||
import dev.plex.storage.entity.GuildEntity;
|
||||
import dev.plex.storage.entity.GuildInviteEntity;
|
||||
import dev.plex.storage.entity.GuildMemberEntity;
|
||||
import dev.plex.storage.entity.GuildWarpEntity;
|
||||
import dev.plex.util.CustomLocation;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class OrmGuildRepository implements GuildRepository
|
||||
{
|
||||
private final ModuleStorage moduleStorage;
|
||||
private final Executor executor;
|
||||
private final Dao<GuildEntity, String> guilds;
|
||||
private final Dao<GuildMemberEntity, Long> members;
|
||||
private final Dao<GuildWarpEntity, Long> warps;
|
||||
private final Dao<GuildInviteEntity, Long> invites;
|
||||
|
||||
public OrmGuildRepository(ModuleStorage moduleStorage)
|
||||
{
|
||||
this.moduleStorage = moduleStorage;
|
||||
this.executor = Guilds.get().api().scheduler().asyncExecutor();
|
||||
try
|
||||
{
|
||||
this.guilds = moduleStorage.orm().dao(GuildEntity.class, "guilds");
|
||||
this.members = moduleStorage.orm().dao(GuildMemberEntity.class, "members");
|
||||
this.warps = moduleStorage.orm().dao(GuildWarpEntity.class, "warps");
|
||||
this.invites = moduleStorage.orm().dao(GuildInviteEntity.class, "invites");
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to create guild DAOs", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<Guild>> loadGuilds()
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return guilds.queryForAll().stream().map(this::toGuild).toList();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to load guilds", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Guild> createGuild(Player owner, String name)
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
Guild guild = Guild.create(owner, name);
|
||||
moduleStorage.transaction(() ->
|
||||
{
|
||||
guilds.create(toEntity(guild));
|
||||
members.create(memberEntity(guild.getGuildUuid(), owner.getUniqueId(), GuildRole.OWNER));
|
||||
return null;
|
||||
});
|
||||
return guild;
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to create guild", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteGuild(UUID guildUuid)
|
||||
{
|
||||
return runAsync(() -> moduleStorage.transaction(() ->
|
||||
{
|
||||
deleteByGuild(members, guildUuid);
|
||||
deleteByGuild(warps, guildUuid);
|
||||
deleteByGuild(invites, guildUuid);
|
||||
guilds.deleteById(guildUuid.toString());
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addMember(UUID guildUuid, UUID playerUuid, GuildRole role)
|
||||
{
|
||||
return runAsync(() -> upsertMember(guildUuid, playerUuid, role));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeMember(UUID guildUuid, UUID playerUuid)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
DeleteBuilder<GuildMemberEntity, Long> delete = members.deleteBuilder();
|
||||
delete.where().eq("guild_uuid", guildUuid.toString()).and().eq("player_uuid", playerUuid.toString());
|
||||
delete.delete();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> transferOwner(UUID guildUuid, UUID newOwnerUuid, UUID oldOwnerUuid)
|
||||
{
|
||||
return runAsync(() -> moduleStorage.transaction(() ->
|
||||
{
|
||||
GuildEntity guild = guilds.queryForId(guildUuid.toString());
|
||||
if (guild != null)
|
||||
{
|
||||
guild.setOwnerUuid(newOwnerUuid.toString());
|
||||
guilds.update(guild);
|
||||
}
|
||||
upsertMember(guildUuid, oldOwnerUuid, GuildRole.MEMBER);
|
||||
upsertMember(guildUuid, newOwnerUuid, GuildRole.OWNER);
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
GuildEntity guild = guilds.queryForId(guildUuid.toString());
|
||||
if (guild != null)
|
||||
{
|
||||
guild.setPrefix(prefix);
|
||||
guilds.update(guild);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> updateHome(UUID guildUuid, CustomLocation home)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
GuildEntity guild = guilds.queryForId(guildUuid.toString());
|
||||
if (guild != null)
|
||||
{
|
||||
setHome(guild, home);
|
||||
guilds.update(guild);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> upsertWarp(UUID guildUuid, String name, CustomLocation location)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
GuildWarpEntity entity = warps.queryBuilder().where()
|
||||
.eq("guild_uuid", guildUuid.toString()).and().eq("name", name.toLowerCase(Locale.ROOT))
|
||||
.queryForFirst();
|
||||
if (entity == null)
|
||||
{
|
||||
entity = new GuildWarpEntity();
|
||||
entity.setGuildUuid(guildUuid.toString());
|
||||
entity.setName(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
setWarpLocation(entity, location);
|
||||
warps.createOrUpdate(entity);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteWarp(UUID guildUuid, String name)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
DeleteBuilder<GuildWarpEntity, Long> delete = warps.deleteBuilder();
|
||||
delete.where().eq("guild_uuid", guildUuid.toString()).and().eq("name", name.toLowerCase(Locale.ROOT));
|
||||
delete.delete();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createInvite(UUID guildUuid, UUID inviterUuid, UUID inviteeUuid, Instant expiresAt)
|
||||
{
|
||||
return runAsync(() ->
|
||||
{
|
||||
deleteInviteSync(guildUuid, inviteeUuid);
|
||||
GuildInviteEntity invite = new GuildInviteEntity();
|
||||
invite.setGuildUuid(guildUuid.toString());
|
||||
invite.setInviterUuid(inviterUuid.toString());
|
||||
invite.setInviteeUuid(inviteeUuid.toString());
|
||||
invite.setExpiresAt(expiresAt.toEpochMilli());
|
||||
invites.create(invite);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteInvite(UUID guildUuid, UUID inviteeUuid)
|
||||
{
|
||||
return runAsync(() -> deleteInviteSync(guildUuid, inviteeUuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<GuildInviteEntity>> invitesFor(UUID inviteeUuid)
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
long now = Instant.now().toEpochMilli();
|
||||
return invites.queryForEq("invitee_uuid", inviteeUuid.toString()).stream()
|
||||
.filter(invite -> invite.getExpiresAt() >= now)
|
||||
.toList();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to load guild invites", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
private Guild toGuild(GuildEntity entity)
|
||||
{
|
||||
String timezone = Guilds.get().api().configuration().mainConfig().getString("server.timezone", "Etc/UTC");
|
||||
Guild guild = new Guild(UUID.fromString(entity.getGuildUuid()), ZonedDateTime.ofInstant(Instant.ofEpochMilli(entity.getCreatedAt()), ZoneId.of(timezone)));
|
||||
guild.setName(entity.getName());
|
||||
guild.setOwnerUuid(UUID.fromString(entity.getOwnerUuid()));
|
||||
guild.setPrefix(entity.getPrefix());
|
||||
guild.setMotd(entity.getMotd());
|
||||
guild.setTagEnabled(entity.isTagEnabled());
|
||||
guild.setPublic(entity.isPublicGuild());
|
||||
guild.setHome(toLocation(entity));
|
||||
try
|
||||
{
|
||||
members.queryForEq("guild_uuid", entity.getGuildUuid()).forEach(member -> guild.addMember(toMember(member)));
|
||||
warps.queryForEq("guild_uuid", entity.getGuildUuid()).forEach(warp -> guild.getWarps().put(warp.getName(), toLocation(warp)));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Failed to load guild relations", e);
|
||||
}
|
||||
return guild;
|
||||
}
|
||||
|
||||
private GuildEntity toEntity(Guild guild)
|
||||
{
|
||||
GuildEntity entity = new GuildEntity();
|
||||
entity.setGuildUuid(guild.getGuildUuid().toString());
|
||||
entity.setName(guild.getName());
|
||||
entity.setOwnerUuid(guild.getOwnerUuid().toString());
|
||||
entity.setCreatedAt(guild.getCreatedAt().toInstant().toEpochMilli());
|
||||
entity.setPrefix(guild.getPrefix());
|
||||
entity.setMotd(guild.getMotd());
|
||||
entity.setTagEnabled(guild.isTagEnabled());
|
||||
entity.setPublicGuild(guild.isPublic());
|
||||
setHome(entity, guild.getHome());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private Member toMember(GuildMemberEntity entity)
|
||||
{
|
||||
return new Member(UUID.fromString(entity.getPlayerUuid()), GuildRole.valueOf(entity.getRole()));
|
||||
}
|
||||
|
||||
private GuildMemberEntity memberEntity(UUID guildUuid, UUID playerUuid, GuildRole role)
|
||||
{
|
||||
GuildMemberEntity entity = new GuildMemberEntity();
|
||||
entity.setGuildUuid(guildUuid.toString());
|
||||
entity.setPlayerUuid(playerUuid.toString());
|
||||
entity.setRole(role.name());
|
||||
entity.setJoinedAt(Instant.now().toEpochMilli());
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void upsertMember(UUID guildUuid, UUID playerUuid, GuildRole role) throws SQLException
|
||||
{
|
||||
GuildMemberEntity entity = members.queryBuilder().where()
|
||||
.eq("guild_uuid", guildUuid.toString()).and().eq("player_uuid", playerUuid.toString())
|
||||
.queryForFirst();
|
||||
if (entity == null)
|
||||
{
|
||||
members.create(memberEntity(guildUuid, playerUuid, role));
|
||||
return;
|
||||
}
|
||||
entity.setRole(role.name());
|
||||
members.update(entity);
|
||||
}
|
||||
|
||||
private void deleteInviteSync(UUID guildUuid, UUID inviteeUuid) throws SQLException
|
||||
{
|
||||
DeleteBuilder<GuildInviteEntity, Long> delete = invites.deleteBuilder();
|
||||
delete.where().eq("guild_uuid", guildUuid.toString()).and().eq("invitee_uuid", inviteeUuid.toString());
|
||||
delete.delete();
|
||||
}
|
||||
|
||||
private <T> void deleteByGuild(Dao<T, Long> dao, UUID guildUuid) throws SQLException
|
||||
{
|
||||
DeleteBuilder<T, Long> delete = dao.deleteBuilder();
|
||||
delete.where().eq("guild_uuid", guildUuid.toString());
|
||||
delete.delete();
|
||||
}
|
||||
|
||||
private void setHome(GuildEntity entity, CustomLocation home)
|
||||
{
|
||||
entity.setHomeWorld(home == null ? null : home.getWorldName());
|
||||
entity.setHomeX(home == null ? null : home.getX());
|
||||
entity.setHomeY(home == null ? null : home.getY());
|
||||
entity.setHomeZ(home == null ? null : home.getZ());
|
||||
entity.setHomeYaw(home == null ? null : home.getYaw());
|
||||
entity.setHomePitch(home == null ? null : home.getPitch());
|
||||
}
|
||||
|
||||
private CustomLocation toLocation(GuildEntity entity)
|
||||
{
|
||||
if (entity.getHomeWorld() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new CustomLocation(entity.getHomeWorld(), entity.getHomeX(), entity.getHomeY(), entity.getHomeZ(), entity.getHomeYaw(), entity.getHomePitch());
|
||||
}
|
||||
|
||||
private void setWarpLocation(GuildWarpEntity entity, CustomLocation location)
|
||||
{
|
||||
entity.setWorld(location.getWorldName());
|
||||
entity.setX(location.getX());
|
||||
entity.setY(location.getY());
|
||||
entity.setZ(location.getZ());
|
||||
entity.setYaw(location.getYaw());
|
||||
entity.setPitch(location.getPitch());
|
||||
}
|
||||
|
||||
private CustomLocation toLocation(GuildWarpEntity entity)
|
||||
{
|
||||
return new CustomLocation(entity.getWorld(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> runAsync(SqlRunnable runnable)
|
||||
{
|
||||
return CompletableFuture.runAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
runnable.run();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Guild storage operation failed", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface SqlRunnable
|
||||
{
|
||||
void run() throws SQLException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package dev.plex.storage.entity;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@DatabaseTable
|
||||
public class GuildEntity
|
||||
{
|
||||
@DatabaseField(id = true, columnName = "guild_uuid", width = 46)
|
||||
private String guildUuid;
|
||||
|
||||
@DatabaseField(columnName = "name", width = 64, canBeNull = false)
|
||||
private String name;
|
||||
|
||||
@DatabaseField(columnName = "prefix", width = 64)
|
||||
private String prefix;
|
||||
|
||||
@DatabaseField(columnName = "owner_uuid", width = 46, canBeNull = false)
|
||||
private String ownerUuid;
|
||||
|
||||
@DatabaseField(columnName = "created_at")
|
||||
private long createdAt;
|
||||
|
||||
@DatabaseField(columnName = "home_world", width = 128)
|
||||
private String homeWorld;
|
||||
|
||||
@DatabaseField(columnName = "home_x")
|
||||
private Double homeX;
|
||||
|
||||
@DatabaseField(columnName = "home_y")
|
||||
private Double homeY;
|
||||
|
||||
@DatabaseField(columnName = "home_z")
|
||||
private Double homeZ;
|
||||
|
||||
@DatabaseField(columnName = "home_yaw")
|
||||
private Float homeYaw;
|
||||
|
||||
@DatabaseField(columnName = "home_pitch")
|
||||
private Float homePitch;
|
||||
|
||||
@DatabaseField(columnName = "motd", width = 3000)
|
||||
private String motd;
|
||||
|
||||
@DatabaseField(columnName = "tag_enabled")
|
||||
private boolean tagEnabled = true;
|
||||
|
||||
@DatabaseField(columnName = "public")
|
||||
private boolean publicGuild;
|
||||
|
||||
public GuildEntity()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.plex.storage.entity;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@DatabaseTable
|
||||
public class GuildInviteEntity
|
||||
{
|
||||
@DatabaseField(generatedId = true, columnName = "id")
|
||||
private long id;
|
||||
|
||||
@DatabaseField(columnName = "guild_uuid", width = 46, canBeNull = false)
|
||||
private String guildUuid;
|
||||
|
||||
@DatabaseField(columnName = "inviter_uuid", width = 46, canBeNull = false)
|
||||
private String inviterUuid;
|
||||
|
||||
@DatabaseField(columnName = "invitee_uuid", width = 46, canBeNull = false)
|
||||
private String inviteeUuid;
|
||||
|
||||
@DatabaseField(columnName = "expires_at")
|
||||
private long expiresAt;
|
||||
|
||||
public GuildInviteEntity()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.plex.storage.entity;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@DatabaseTable
|
||||
public class GuildMemberEntity
|
||||
{
|
||||
@DatabaseField(generatedId = true, columnName = "id")
|
||||
private long id;
|
||||
|
||||
@DatabaseField(columnName = "guild_uuid", width = 46, canBeNull = false)
|
||||
private String guildUuid;
|
||||
|
||||
@DatabaseField(columnName = "player_uuid", width = 46, canBeNull = false)
|
||||
private String playerUuid;
|
||||
|
||||
@DatabaseField(columnName = "role", width = 20, canBeNull = false)
|
||||
private String role;
|
||||
|
||||
@DatabaseField(columnName = "joined_at")
|
||||
private long joinedAt;
|
||||
|
||||
public GuildMemberEntity()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.plex.storage.entity;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@DatabaseTable
|
||||
public class GuildWarpEntity
|
||||
{
|
||||
@DatabaseField(generatedId = true, columnName = "id")
|
||||
private long id;
|
||||
|
||||
@DatabaseField(columnName = "guild_uuid", width = 46, canBeNull = false)
|
||||
private String guildUuid;
|
||||
|
||||
@DatabaseField(columnName = "name", width = 16, canBeNull = false)
|
||||
private String name;
|
||||
|
||||
@DatabaseField(columnName = "world", width = 128, canBeNull = false)
|
||||
private String world;
|
||||
|
||||
@DatabaseField(columnName = "x")
|
||||
private double x;
|
||||
|
||||
@DatabaseField(columnName = "y")
|
||||
private double y;
|
||||
|
||||
@DatabaseField(columnName = "z")
|
||||
private double z;
|
||||
|
||||
@DatabaseField(columnName = "yaw")
|
||||
private float yaw;
|
||||
|
||||
@DatabaseField(columnName = "pitch")
|
||||
private float pitch;
|
||||
|
||||
public GuildWarpEntity()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
CREATE TABLE IF NOT EXISTS {{table:guilds}} (
|
||||
`guild_uuid` VARCHAR(46) NOT NULL,
|
||||
`name` VARCHAR(64) NOT NULL,
|
||||
`prefix` VARCHAR(64),
|
||||
`owner_uuid` VARCHAR(46) NOT NULL,
|
||||
`created_at` BIGINT NOT NULL,
|
||||
`home_world` VARCHAR(128),
|
||||
`home_x` DOUBLE,
|
||||
`home_y` DOUBLE,
|
||||
`home_z` DOUBLE,
|
||||
`home_yaw` FLOAT,
|
||||
`home_pitch` FLOAT,
|
||||
`motd` VARCHAR(3000),
|
||||
`tag_enabled` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`public` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (`guild_uuid`),
|
||||
UNIQUE KEY `uq_guilds_name` (`name`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:members}} (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`guild_uuid` VARCHAR(46) NOT NULL,
|
||||
`player_uuid` VARCHAR(46) NOT NULL,
|
||||
`role` VARCHAR(20) NOT NULL,
|
||||
`joined_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_members_guild_player` (`guild_uuid`, `player_uuid`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:warps}} (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`guild_uuid` VARCHAR(46) NOT NULL,
|
||||
`name` VARCHAR(16) NOT NULL,
|
||||
`world` VARCHAR(128) NOT NULL,
|
||||
`x` DOUBLE NOT NULL,
|
||||
`y` DOUBLE NOT NULL,
|
||||
`z` DOUBLE NOT NULL,
|
||||
`yaw` FLOAT NOT NULL,
|
||||
`pitch` FLOAT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_warps_guild_name` (`guild_uuid`, `name`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:invites}} (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`guild_uuid` VARCHAR(46) NOT NULL,
|
||||
`inviter_uuid` VARCHAR(46) NOT NULL,
|
||||
`invitee_uuid` VARCHAR(46) NOT NULL,
|
||||
`expires_at` BIGINT NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_invites_guild_invitee` (`guild_uuid`, `invitee_uuid`)
|
||||
);
|
||||
@@ -0,0 +1,47 @@
|
||||
CREATE TABLE IF NOT EXISTS {{table:guilds}} (
|
||||
guild_uuid VARCHAR(46) NOT NULL PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL UNIQUE,
|
||||
prefix VARCHAR(64),
|
||||
owner_uuid VARCHAR(46) NOT NULL,
|
||||
created_at BIGINT NOT NULL,
|
||||
home_world VARCHAR(128),
|
||||
home_x DOUBLE PRECISION,
|
||||
home_y DOUBLE PRECISION,
|
||||
home_z DOUBLE PRECISION,
|
||||
home_yaw REAL,
|
||||
home_pitch REAL,
|
||||
motd VARCHAR(3000),
|
||||
tag_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
public BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:members}} (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
player_uuid VARCHAR(46) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
joined_at BIGINT NOT NULL,
|
||||
CONSTRAINT uq_members_guild_player UNIQUE (guild_uuid, player_uuid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:warps}} (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
name VARCHAR(16) NOT NULL,
|
||||
world VARCHAR(128) NOT NULL,
|
||||
x DOUBLE PRECISION NOT NULL,
|
||||
y DOUBLE PRECISION NOT NULL,
|
||||
z DOUBLE PRECISION NOT NULL,
|
||||
yaw REAL NOT NULL,
|
||||
pitch REAL NOT NULL,
|
||||
CONSTRAINT uq_warps_guild_name UNIQUE (guild_uuid, name)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:invites}} (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
inviter_uuid VARCHAR(46) NOT NULL,
|
||||
invitee_uuid VARCHAR(46) NOT NULL,
|
||||
expires_at BIGINT NOT NULL,
|
||||
CONSTRAINT uq_invites_guild_invitee UNIQUE (guild_uuid, invitee_uuid)
|
||||
);
|
||||
@@ -0,0 +1,47 @@
|
||||
CREATE TABLE IF NOT EXISTS {{table:guilds}} (
|
||||
guild_uuid VARCHAR(46) NOT NULL PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL UNIQUE,
|
||||
prefix VARCHAR(64),
|
||||
owner_uuid VARCHAR(46) NOT NULL,
|
||||
created_at BIGINT NOT NULL,
|
||||
home_world VARCHAR(128),
|
||||
home_x DOUBLE,
|
||||
home_y DOUBLE,
|
||||
home_z DOUBLE,
|
||||
home_yaw FLOAT,
|
||||
home_pitch FLOAT,
|
||||
motd VARCHAR(3000),
|
||||
tag_enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||
public BOOLEAN NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:members}} (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
player_uuid VARCHAR(46) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
joined_at BIGINT NOT NULL,
|
||||
UNIQUE (guild_uuid, player_uuid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:warps}} (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
name VARCHAR(16) NOT NULL,
|
||||
world VARCHAR(128) NOT NULL,
|
||||
x DOUBLE NOT NULL,
|
||||
y DOUBLE NOT NULL,
|
||||
z DOUBLE NOT NULL,
|
||||
yaw FLOAT NOT NULL,
|
||||
pitch FLOAT NOT NULL,
|
||||
UNIQUE (guild_uuid, name)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS {{table:invites}} (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
guild_uuid VARCHAR(46) NOT NULL,
|
||||
inviter_uuid VARCHAR(46) NOT NULL,
|
||||
invitee_uuid VARCHAR(46) NOT NULL,
|
||||
expires_at BIGINT NOT NULL,
|
||||
UNIQUE (guild_uuid, invitee_uuid)
|
||||
);
|
||||
@@ -4,6 +4,7 @@ guildCommandNotFound: "<red>'<gold>{0}</gold>'<red> is not a valid sub command!"
|
||||
guildNotFound: "<red>You're currently not a part of a guild!"
|
||||
guildInThis: "<red>You're currently a part of this guild!"
|
||||
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>."
|
||||
guildCreated: "<green>Created guild named <dark_green>{0}<green>."
|
||||
guildNotOwner: "<red>You're not the owner of this guild!"
|
||||
guildMemberNotFound: "<red>This guild member could not be found!"
|
||||
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."
|
||||
@@ -23,8 +24,16 @@ guildNoInvite: "<red>You don't have any pending invitations!"
|
||||
guildNotValidInvite: "<red>You don't have an invite from this guild!"
|
||||
guildInviteExists: "<red>You've already sent an invite to this person!"
|
||||
guildInviteSent: "<green>You have sent an invite to <dark_green>{0}"
|
||||
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"
|
||||
guildInviteReceived: "<gold>You have received an invite from <yellow>{0}<gold> for the guild <yellow>{1}<newline><newline><green><bold><click:run_command:/guild accept {1}>[ACCEPT]<newline><newline><!bold><gold>You may also run <yellow>/guild accept {1}<gold> to accept this invite. It will expire in 5 minutes"
|
||||
guildMemberJoined: "<green>{0} has joined the guild!"
|
||||
guildMemberLeft: "<green>{0} has left the guild!"
|
||||
guildDisbandNeeded: "<red>You need to disband your guild using <gold>/guild disband<red> or promote a new owner using <gold>/guild owner <player>"
|
||||
guildAutoDisbanded: "<green>Auto-disbanding your guild since there were no members"
|
||||
guildDisbanded: "<green>Your guild has been disbanded."
|
||||
guildLeft: "<green>You have left the guild."
|
||||
guildOwnerLeaveBlocked: "<red>You must transfer ownership before leaving this guild."
|
||||
guildInviteDenied: "<green>You denied the guild invite."
|
||||
guildInviteExpired: "<red>This guild invite has expired."
|
||||
guildTargetAlreadyInGuild: "<red>That player is already in a guild."
|
||||
guildCannotInviteSelf: "<red>You cannot invite yourself."
|
||||
guildStorageFailed: "<red>The guild storage operation failed."
|
||||
|
||||
Reference in New Issue
Block a user