Skip to content

Commit 2a6f451

Browse files
committed
redesign guilds
1 parent f11860e commit 2a6f451

52 files changed

Lines changed: 2177 additions & 2184 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎src/main/java/dev/plex/Guilds.java‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
import dev.plex.handler.GuildWorldAccessListener;
1313
import dev.plex.handler.GuildWorldProtectionListener;
1414
import dev.plex.handler.GuildWorldEntityProtectionListener;
15-
import dev.plex.handler.RankPermissionMenuListener;
1615
import dev.plex.module.PlexModule;
1716
import dev.plex.api.storage.ModuleStorage;
1817
import dev.plex.storage.GuildRepository;
1918
import dev.plex.storage.JdbiGuildRepository;
19+
import dev.plex.util.DurationParser;
2020
import dev.plex.world.GuildWorldService;
2121
import dev.plex.world.AspGuildWorldService;
2222
import lombok.Getter;
@@ -27,6 +27,7 @@
2727
import org.bukkit.entity.Player;
2828

2929
import java.sql.SQLException;
30+
import java.time.Duration;
3031
import java.time.ZoneId;
3132
import java.util.Set;
3233
import java.util.stream.Collectors;
@@ -47,7 +48,6 @@ public class Guilds extends PlexModule
4748
private final GuildMenuListener guildMenuListener = new GuildMenuListener(this, guildMutationService);
4849
private final GuildWorldProtectionListener guildWorldProtectionListener = new GuildWorldProtectionListener(this);
4950
private final GuildWorldAccessListener guildWorldAccessListener = new GuildWorldAccessListener(this);
50-
private final RankPermissionMenuListener rankPermissionMenuListener = new RankPermissionMenuListener(this);
5151

5252
private GuildWorldService guildWorldService;
5353

@@ -56,6 +56,8 @@ public class Guilds extends PlexModule
5656

5757
private ModuleConfiguration config;
5858
private ZoneId zoneId;
59+
private Duration guestDefaultDuration;
60+
private Duration guestMaxDuration;
5961
private volatile boolean ready;
6062
private volatile boolean loadFailed;
6163

@@ -65,6 +67,12 @@ public void load()
6567
config = api().moduleConfigs().create(this, "config.yml");
6668
config.load();
6769
zoneId = ZoneId.of(api().configuration().mainConfig().getString("server.timezone", "Etc/UTC"));
70+
guestDefaultDuration = DurationParser.parse(config.getString("guilds.guests.default-duration", "24h"));
71+
guestMaxDuration = DurationParser.parse(config.getString("guilds.guests.max-duration", "30d"));
72+
if (guestDefaultDuration == null || guestMaxDuration == null || guestDefaultDuration.compareTo(guestMaxDuration) > 0)
73+
{
74+
throw new IllegalArgumentException("Guest durations must use <number>m, <number>h, or <number>d, and the default must not exceed the maximum");
75+
}
6876
loadMessages("messages.yml");
6977
this.registerCommand(new GuildCommand(this));
7078
}
@@ -104,7 +112,6 @@ public void enable()
104112
registerListener(new GuildWorldEntityProtectionListener(this));
105113
registerListener(guildWorldAccessListener);
106114
guildWorldAccessListener.startGuestExpiry();
107-
registerListener(rankPermissionMenuListener);
108115
}
109116

110117
@Override

‎src/main/java/dev/plex/command/GuildCommand.java‎

Lines changed: 131 additions & 140 deletions
Large diffs are not rendered by default.
Lines changed: 31 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
package dev.plex.command.sub;
22

3-
import com.google.common.collect.ImmutableList;
43
import dev.plex.Guilds;
54
import dev.plex.command.source.RequiredCommandSource;
65
import dev.plex.guild.Guild;
7-
import dev.plex.guild.data.GuildRole;
86
import dev.plex.storage.entity.GuildInviteEntity;
7+
import java.time.Instant;
8+
import java.util.List;
9+
import java.util.UUID;
910
import net.kyori.adventure.text.Component;
1011
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
1112
import org.bukkit.command.CommandSender;
1213
import org.bukkit.entity.Player;
1314
import org.jetbrains.annotations.NotNull;
1415
import org.jetbrains.annotations.Nullable;
1516

16-
import java.time.Instant;
17-
import java.util.List;
18-
import java.util.UUID;
19-
2017
public class AcceptSubCommand extends GuildSubCommand
2118
{
2219
public AcceptSubCommand(Guilds module)
2320
{
2421
super(module, command("accept")
25-
.description("Accept an invite")
22+
.description("Accept a guild invite")
2623
.usage("/guild <command> <guild>")
2724
.permission("plex.guilds.accept")
2825
.source(RequiredCommandSource.IN_GAME)
2926
.build());
3027
}
3128

29+
@Override
30+
public boolean isAvailable(@Nullable Player player)
31+
{
32+
return player != null && guildOf(player) == null;
33+
}
34+
3235
@Override
3336
public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullable Player player, @Nullable String first, @Nullable String remaining)
3437
{
@@ -37,12 +40,16 @@ public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullab
3740
return usage();
3841
}
3942
assert player != null;
43+
if (guildOf(player) != null)
44+
{
45+
return messageComponent("alreadyInGuild");
46+
}
4047
UUID playerUuid = player.getUniqueId();
41-
String playerName = player.getName();
4248
module.getGuildRepository().invitesFor(playerUuid).whenComplete((invites, throwable) ->
4349
{
4450
if (throwable != null)
4551
{
52+
module.getLogger().error("Failed to load invites for {}", playerUuid, throwable);
4653
player.sendMessage(messageComponent("guildStorageFailed"));
4754
return;
4855
}
@@ -52,19 +59,14 @@ public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullab
5259
player.sendMessage(messageComponent("guildNotValidInvite"));
5360
return;
5461
}
55-
if (invite.getExpiresAt() < Instant.now().toEpochMilli())
62+
Guild guild = module.getGuildHolder().guildById(UUID.fromString(invite.getGuildUuid())).orElse(null);
63+
if (invite.getExpiresAt() < Instant.now().toEpochMilli() || guild == null)
5664
{
5765
module.getGuildRepository().deleteInvite(UUID.fromString(invite.getGuildUuid()), playerUuid);
5866
player.sendMessage(messageComponent("guildInviteExpired"));
5967
return;
6068
}
61-
Guild target = module.getGuildHolder().guildById(UUID.fromString(invite.getGuildUuid())).orElse(null);
62-
if (target == null)
63-
{
64-
player.sendMessage(messageComponent("guildNotValidInvite"));
65-
return;
66-
}
67-
leaveCurrentIfNeeded(player, playerUuid, playerName, target);
69+
join(player, guild);
6870
});
6971
return null;
7072
}
@@ -79,60 +81,23 @@ private GuildInviteEntity findInvite(List<GuildInviteEntity> invites, String gui
7981
.orElse(null);
8082
}
8183

82-
private void leaveCurrentIfNeeded(Player player, UUID playerUuid, String playerName, Guild target)
84+
private void join(Player player, Guild guild)
8385
{
84-
module.getGuildHolder().guild(playerUuid).ifPresentOrElse(current ->
86+
// The player may have joined or created a guild while the invites loaded.
87+
if (guildOf(player) != null)
8588
{
86-
if (current.getGuildUuid().equals(target.getGuildUuid()))
87-
{
88-
player.sendMessage(messageComponent("guildInThis"));
89-
return;
90-
}
91-
if (current.isOwner(playerUuid) && current.getMembers().size() > 1)
92-
{
93-
player.sendMessage(messageComponent("guildOwnerLeaveBlocked"));
94-
return;
95-
}
96-
if (current.isOwner(playerUuid))
89+
player.sendMessage(messageComponent("alreadyInGuild"));
90+
return;
91+
}
92+
String playerName = player.getName();
93+
module.getGuildMutationService().addMember(guild, player.getUniqueId(), true).whenComplete((unused, throwable) ->
94+
{
95+
if (throwable != null)
9796
{
98-
module.getGuildMutationService().deleteGuild(current).whenComplete((unused, throwable) ->
99-
{
100-
if (throwable != null)
101-
{
102-
player.sendMessage(messageComponent("guildStorageFailed"));
103-
return;
104-
}
105-
joinTarget(player, playerUuid, playerName, target);
106-
});
97+
player.sendMessage(failureMessage(throwable, null));
10798
return;
10899
}
109-
module.getGuildMutationService().removeMember(current, playerUuid).whenComplete((unused, throwable) ->
110-
{
111-
if (throwable != null)
112-
{
113-
player.sendMessage(messageComponent("guildStorageFailed"));
114-
return;
115-
}
116-
module.broadcastToGuild(current, messageComponent("guildMemberLeft", Placeholder.unparsed("player", playerName)))
117-
.thenRun(() -> joinTarget(player, playerUuid, playerName, target));
118-
});
119-
}, () -> joinTarget(player, playerUuid, playerName, target));
120-
}
121-
122-
private void joinTarget(Player player, UUID playerUuid, String playerName, Guild guild)
123-
{
124-
UUID guildUuid = guild.getGuildUuid();
125-
module.getGuildMutationService().addMember(guild, playerUuid, true)
126-
.whenComplete((unused, throwable) ->
127-
{
128-
if (throwable != null)
129-
{
130-
player.sendMessage(messageComponent("guildStorageFailed"));
131-
return;
132-
}
133-
module.broadcastToGuild(guild, messageComponent("guildMemberJoined", Placeholder.unparsed("player", playerName)));
134-
});
100+
module.broadcastToGuild(guild, messageComponent("guildMemberJoined", Placeholder.unparsed("player", playerName)));
101+
});
135102
}
136-
137-
138103
}

‎src/main/java/dev/plex/command/sub/ChatSubCommand.java‎

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
import dev.plex.Guilds;
44
import dev.plex.command.source.RequiredCommandSource;
5+
import dev.plex.guild.Guild;
56
import dev.plex.guild.data.Member;
6-
import java.util.Collections;
7-
import java.util.List;
87
import net.kyori.adventure.text.Component;
98
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
109
import org.apache.commons.lang3.BooleanUtils;
11-
import org.apache.commons.lang3.StringUtils;
1210
import org.bukkit.command.CommandSender;
1311
import org.bukkit.entity.Player;
1412
import org.jetbrains.annotations.NotNull;
@@ -26,24 +24,28 @@ public ChatSubCommand(Guilds module)
2624
.build());
2725
}
2826

27+
@Override
28+
public boolean isAvailable(@Nullable Player player)
29+
{
30+
return guildOf(player) != null;
31+
}
32+
2933
@Override
3034
public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullable Player player, @Nullable String first, @Nullable String remaining)
3135
{
3236
assert player != null;
33-
module.getGuildHolder().guild(player.getUniqueId()).ifPresentOrElse(guild ->
37+
Guild guild = guildOf(player);
38+
Member member = guild == null ? null : guild.getMember(player.getUniqueId());
39+
if (member == null)
3440
{
35-
if (first == null)
36-
{
37-
Member member = guild.getMember(player.getUniqueId());
38-
member.setChat(!member.isChat());
39-
player.sendMessage(messageComponent("guildChatToggled", Placeholder.unparsed("status", BooleanUtils.toStringOnOff(member.isChat()))));
40-
return;
41-
}
42-
Component message = module.api().messages().playerText(arguments(first, remaining));
43-
module.sendChat(guild, player.getName(), message);
44-
}, () -> player.sendMessage(messageComponent("guildNotFound")));
41+
return messageComponent("guildNotFound");
42+
}
43+
if (first == null)
44+
{
45+
member.setChat(!member.isChat());
46+
return messageComponent("guildChatToggled", Placeholder.unparsed("status", BooleanUtils.toStringOnOff(member.isChat())));
47+
}
48+
module.sendChat(guild, player.getName(), module.api().messages().playerText(arguments(first, remaining)));
4549
return null;
4650
}
47-
48-
4951
}

‎src/main/java/dev/plex/command/sub/CreateSubCommand.java‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
import dev.plex.Guilds;
44
import dev.plex.command.source.RequiredCommandSource;
55
import dev.plex.guild.Guild;
6-
import java.util.Collections;
7-
import java.util.List;
86
import java.util.concurrent.CompletableFuture;
97
import net.kyori.adventure.text.Component;
108
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
119
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
12-
import org.apache.commons.lang3.StringUtils;
1310
import org.bukkit.command.CommandSender;
1411
import org.bukkit.entity.Player;
1512
import org.jetbrains.annotations.NotNull;
@@ -22,12 +19,17 @@ public CreateSubCommand(Guilds module)
2219
super(module, command("create")
2320
.description("Create a guild")
2421
.usage("/guild <command> <name>")
25-
.aliases("make")
2622
.permission("plex.guilds.create")
2723
.source(RequiredCommandSource.IN_GAME)
2824
.build());
2925
}
3026

27+
@Override
28+
public boolean isAvailable(@Nullable Player player)
29+
{
30+
return player != null && guildOf(player) == null;
31+
}
32+
3133
@Override
3234
public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullable Player player, @Nullable String first, @Nullable String remaining)
3335
{
@@ -36,11 +38,19 @@ public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullab
3638
return usage();
3739
}
3840
assert player != null;
39-
if (module.getGuildHolder().guild(player.getUniqueId()).isPresent())
41+
if (guildOf(player) != null)
4042
{
4143
return messageComponent("alreadyInGuild");
4244
}
4345
String name = PlainTextComponentSerializer.plainText().serialize(module.api().messages().playerText(arguments(first, remaining)));
46+
if (name.isBlank())
47+
{
48+
return usage();
49+
}
50+
if (module.getGuildHolder().guildByName(name).isPresent())
51+
{
52+
return messageComponent("guildNameTaken", Placeholder.unparsed("guild", name));
53+
}
4454
Guild guildToCreate = Guild.create(player.getUniqueId(), name, module.getZoneId());
4555
module.getGuildRepository().createGuild(guildToCreate)
4656
.thenCompose(guild -> module.isGuildWorldsEnabled()
@@ -50,6 +60,7 @@ public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullab
5060
{
5161
if (throwable != null)
5262
{
63+
module.getLogger().error("Failed to create guild {}", name, throwable);
5364
player.sendMessage(messageComponent("guildStorageFailed"));
5465
return;
5566
}
@@ -58,6 +69,4 @@ public Component executeSubCommand(@NotNull CommandSender commandSender, @Nullab
5869
});
5970
return null;
6071
}
61-
62-
6372
}

0 commit comments

Comments
 (0)