Skip to content

Commit f276329

Browse files
authored
refactor: internal user maps, add /husktowns status (#561)
* feat: begin implementing new user provider * refactor: finish refactoring user caching for perf * feat: add `/husktowns status` command, refactor meta system * test: add an assertion to make sure * build: bump gson * build: bump runtime dependencies
1 parent 04c39de commit f276329

34 files changed

+833
-431
lines changed

bukkit/src/main/java/net/william278/husktowns/BukkitHuskTowns.java

+38-28
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import net.roxeez.advancement.display.BackgroundType;
3232
import net.roxeez.advancement.display.FrameType;
3333
import net.roxeez.advancement.trigger.TriggerType;
34+
import net.william278.cloplib.listener.OperationListener;
3435
import net.william278.desertwell.util.Version;
3536
import net.william278.husktowns.advancement.Advancement;
3637
import net.william278.husktowns.api.BukkitHuskTownsAPI;
@@ -52,6 +53,7 @@
5253
import net.william278.husktowns.town.Invite;
5354
import net.william278.husktowns.town.Town;
5455
import net.william278.husktowns.user.BukkitUser;
56+
import net.william278.husktowns.user.BukkitUserProvider;
5557
import net.william278.husktowns.user.OnlineUser;
5658
import net.william278.husktowns.user.Preferences;
5759
import net.william278.husktowns.user.User;
@@ -83,25 +85,28 @@
8385
import java.io.File;
8486
import java.nio.file.Path;
8587
import java.util.*;
88+
import java.util.concurrent.ConcurrentMap;
8689
import java.util.logging.Level;
8790

8891
@NoArgsConstructor
8992
@Getter
9093
public class BukkitHuskTowns extends JavaPlugin implements HuskTowns, BukkitTask.Supplier,
91-
PluginMessageListener, BukkitEventDispatcher {
92-
94+
BukkitUserProvider, PluginMessageListener, BukkitEventDispatcher {
9395

9496
private AudienceProvider audiences;
9597
private MorePaperLib paperLib;
9698
private AsynchronousScheduler asyncScheduler;
9799
private RegionalScheduler regionalScheduler;
100+
private OperationListener operationListener;
98101
private final Set<Town> towns = Sets.newConcurrentHashSet();
99102
private final Map<String, ClaimWorld> claimWorlds = Maps.newConcurrentMap();
100103
private final Map<UUID, Deque<Invite>> invites = Maps.newConcurrentMap();
101104
private final Map<UUID, Preferences> userPreferences = Maps.newConcurrentMap();
102105
private final Map<UUID, Visualizer> visualizers = Maps.newConcurrentMap();
103106
private final Map<String, List<User>> globalUserList = Maps.newConcurrentMap();
107+
private final ConcurrentMap<UUID, OnlineUser> onlineUserMap = Maps.newConcurrentMap();
104108
private final Validator validator = new Validator(this);
109+
105110
@Setter
106111
private boolean loaded = false;
107112
@Setter
@@ -214,14 +219,16 @@ public void onEnable() {
214219
this.registerCommands();
215220

216221
// Register event listener
217-
new BukkitListener(this).register();
222+
final BukkitListener listener = new BukkitListener(this);
223+
this.operationListener = listener;
224+
listener.register();
218225

219226
// Register API
220227
BukkitHuskTownsAPI.register(this);
221228

222229
// Register metrics
223230
initializeMetrics();
224-
log(Level.INFO, "Enabled HuskTowns v" + getVersion());
231+
log(Level.INFO, "Enabled HuskTowns v" + getPluginVersion());
225232
checkForUpdates();
226233
}
227234

@@ -232,7 +239,7 @@ public void onDisable() {
232239
}
233240
visualizers.values().forEach(Visualizer::cancel);
234241
getMessageBroker().ifPresent(Broker::close);
235-
log(Level.INFO, "Disabled HuskTowns v" + getVersion());
242+
log(Level.INFO, "Disabled HuskTowns v" + getPluginVersion());
236243
}
237244

238245
@Override
@@ -262,20 +269,37 @@ public Optional<Broker> getMessageBroker() {
262269
return hookManager;
263270
}
264271

272+
@Override
273+
public Version getPluginVersion() {
274+
return Version.fromString(getDescription().getVersion());
275+
}
276+
277+
@Override
278+
@NotNull
279+
public String getServerType() {
280+
return String.format("%s/%s", getServer().getName(), getServer().getVersion());
281+
}
282+
283+
@Override
284+
@NotNull
285+
public Version getMinecraftVersion() {
286+
return Version.fromString(getServer().getBukkitVersion());
287+
}
288+
265289
@Override
266290
@NotNull
267291
public List<World> getWorlds() {
268292
return Bukkit.getWorlds().stream()
269-
.map(world -> World.of(
270-
world.getUID(), world.getName(),
271-
world.getEnvironment().name().toLowerCase())
272-
).toList();
293+
.map(world -> World.of(
294+
world.getUID(), world.getName(),
295+
world.getEnvironment().name().toLowerCase())
296+
).toList();
273297
}
274298

275299
@Override
276-
public void log(@NotNull Level level, @NotNull String message, @NotNull Throwable... throwable) {
277-
if (throwable.length > 0) {
278-
getLogger().log(level, message, throwable[0]);
300+
public void log(@NotNull Level level, @NotNull String message, @NotNull Throwable... exceptions) {
301+
if (exceptions.length > 0) {
302+
getLogger().log(level, message, exceptions[0]);
279303
return;
280304
}
281305
getLogger().log(level, message);
@@ -302,20 +326,6 @@ public void initializePluginChannels() {
302326
getServer().getMessenger().registerOutgoingPluginChannel(this, PluginMessageBroker.BUNGEE_CHANNEL_ID);
303327
}
304328

305-
@Override
306-
@NotNull
307-
public Version getVersion() {
308-
return Version.fromString(getDescription().getVersion(), "-");
309-
}
310-
311-
@Override
312-
@NotNull
313-
public List<? extends OnlineUser> getOnlineUsers() {
314-
return Bukkit.getOnlinePlayers().stream()
315-
.map(p -> BukkitUser.adapt(p, this))
316-
.toList();
317-
}
318-
319329
@Override
320330
public double getHighestYAt(double x, double z, @NotNull World world) {
321331
final org.bukkit.World bukkitWorld = Bukkit.getWorld(world.getName()) == null
@@ -339,7 +349,7 @@ public void dispatchCommand(@NotNull String command) {
339349
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte[] message) {
340350
if (broker != null && broker instanceof PluginMessageBroker pluginMessenger
341351
&& getSettings().getCrossServer().getBrokerType() == Broker.Type.PLUGIN_MESSAGE) {
342-
pluginMessenger.onReceive(channel, BukkitUser.adapt(player, this), message);
352+
pluginMessenger.onReceive(channel, getOnlineUser(player), message);
343353
}
344354
}
345355

@@ -488,4 +498,4 @@ public BukkitHuskTowns getPlugin() {
488498
return this;
489499
}
490500

491-
}
501+
}

bukkit/src/main/java/net/william278/husktowns/api/BukkitHuskTownsAPI.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import net.william278.husktowns.map.ClaimMap;
2727
import net.william278.husktowns.town.Member;
2828
import net.william278.husktowns.town.Town;
29-
import net.william278.husktowns.user.BukkitUser;
3029
import net.william278.husktowns.user.OnlineUser;
3130
import net.william278.husktowns.user.Preferences;
3231
import org.bukkit.Location;
@@ -88,7 +87,7 @@ public static void register(@NotNull BukkitHuskTowns plugin) {
8887
* @since 2.0
8988
*/
9089
public Optional<ClaimWorld> getClaimWorld(@NotNull org.bukkit.World world) {
91-
return plugin.getClaimWorld(getWorld(world));
90+
return getPlugin().getClaimWorld(getWorld(world));
9291
}
9392

9493
/**
@@ -469,7 +468,7 @@ public Preferences getUserPreferences(@NotNull Player player) {
469468
*/
470469
@NotNull
471470
public OnlineUser getOnlineUser(@NotNull Player player) {
472-
return BukkitUser.adapt(player, plugin);
471+
return getPlugin().getOnlineUser(player);
473472
}
474473

475474
/**
@@ -498,4 +497,9 @@ public World getWorld(@NotNull org.bukkit.World world) {
498497
return World.of(world.getUID(), world.getName(), world.getEnvironment().name().toLowerCase());
499498
}
500499

500+
@NotNull
501+
private BukkitHuskTowns getPlugin() {
502+
return (BukkitHuskTowns) plugin;
503+
}
504+
501505
}

bukkit/src/main/java/net/william278/husktowns/command/BukkitCommand.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package net.william278.husktowns.command;
2121

2222
import net.william278.husktowns.BukkitHuskTowns;
23-
import net.william278.husktowns.user.BukkitUser;
2423
import org.bukkit.command.CommandSender;
2524
import org.bukkit.entity.Player;
2625
import org.bukkit.permissions.Permission;
@@ -46,7 +45,7 @@ public BukkitCommand(@NotNull Command command, @NotNull BukkitHuskTowns plugin)
4645
@Override
4746
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
4847
this.command.execute(
49-
sender instanceof Player player ? BukkitUser.adapt(player, plugin) : plugin.getConsole(), args
48+
sender instanceof Player player ? plugin.getOnlineUser(player) : plugin.getConsole(), args
5049
);
5150
return true;
5251
}
@@ -56,7 +55,7 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLab
5655
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias,
5756
@NotNull String[] args) throws IllegalArgumentException {
5857
return this.command.getSuggestions(
59-
sender instanceof Player player ? BukkitUser.adapt(player, plugin) : plugin.getConsole(), args
58+
sender instanceof Player player ? plugin.getOnlineUser(player) : plugin.getConsole(), args
6059
);
6160
}
6261

bukkit/src/main/java/net/william278/husktowns/hook/LuckPermsHook.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import net.luckperms.api.LuckPerms;
2323
import net.luckperms.api.context.*;
2424
import net.william278.cloplib.operation.OperationType;
25+
import net.william278.husktowns.BukkitHuskTowns;
2526
import net.william278.husktowns.HuskTowns;
2627
import net.william278.husktowns.claim.Position;
2728
import net.william278.husktowns.claim.Rules;
@@ -65,7 +66,7 @@ public void onEnable() {
6566
this.calculators.forEach(contextCalculator -> this.contexts.unregisterCalculator(contextCalculator));
6667
this.calculators.clear();
6768
this.registerCalculator(() -> new ClaimContextCalculator(plugin));
68-
this.registerCalculator(() -> new TownContextCalculator(plugin));
69+
this.registerCalculator(() -> new TownContextCalculator((BukkitHuskTowns) plugin));
6970
plugin.log(Level.INFO, "Enabled LuckPerms context provider hook");
7071
}
7172

@@ -92,7 +93,7 @@ public void calculate(@NotNull Player target, @NotNull ContextConsumer consumer)
9293
}
9394

9495
final TownClaim townClaim = claim.get();
95-
final Optional<Member> member = plugin.getUserTown(BukkitUser.adapt(target, plugin));
96+
final Optional<Member> member = plugin.getUserTown(((BukkitHuskTowns) plugin).getOnlineUser(target));
9697
if (member.isPresent() && member.get().town().equals(townClaim.town())) {
9798
final Member user = member.get();
9899
consumer.accept(ContextKey.STANDING_IN_OWN_TOWN.getKey(plugin), "true");
@@ -153,10 +154,10 @@ private void setContextsFromRules(@NotNull ContextConsumer consumer, Rules wilde
153154
}
154155
}
155156

156-
private record TownContextCalculator(@NotNull HuskTowns plugin) implements ContextCalculator<Player> {
157+
private record TownContextCalculator(@NotNull BukkitHuskTowns plugin) implements ContextCalculator<Player> {
157158
@Override
158159
public void calculate(@NotNull Player target, @NotNull ContextConsumer consumer) {
159-
final Optional<Member> userTown = plugin.getUserTown(BukkitUser.adapt(target, plugin));
160+
final Optional<Member> userTown = plugin.getUserTown(plugin.getOnlineUser(target));
160161
if (userTown.isEmpty()) {
161162
consumer.accept(ContextKey.PLAYER_IS_TOWN_MEMBER.getKey(plugin), "false");
162163
return;

bukkit/src/main/java/net/william278/husktowns/hook/PlaceholderAPIHook.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ public String onRequest(@Nullable OfflinePlayer offlinePlayer, @NotNull String p
9797
}
9898

9999
// Return the requested placeholder
100-
final OnlineUser player = BukkitUser.adapt(offlinePlayer.getPlayer(), plugin);
101-
100+
final OnlineUser player = plugin.getOnlineUser(offlinePlayer.getUniqueId());
102101
if (params.startsWith("town_")) {
103102
if (params.length() == 5) {
104103
return null;
@@ -346,7 +345,7 @@ public String getAuthor() {
346345
@Override
347346
@NotNull
348347
public String getVersion() {
349-
return plugin.getVersion().toStringWithoutMetadata();
348+
return plugin.getPluginVersion().toStringWithoutMetadata();
350349
}
351350

352351
@NotNull

bukkit/src/main/java/net/william278/husktowns/listener/BukkitListener.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,18 @@ public void onMobSpawnBoosted(@NotNull CreatureSpawnEvent e) {
8686

8787
@EventHandler(ignoreCancelled = true)
8888
public void onPlayerJoin(@NotNull PlayerJoinEvent e) {
89-
getPlugin().handlePlayerJoin(BukkitUser.adapt(e.getPlayer(), plugin));
89+
getPlugin().getOnlineUserMap().remove(e.getPlayer().getUniqueId());
90+
getPlugin().handlePlayerJoin(plugin.getOnlineUser(e.getPlayer()));
9091
}
9192

9293
@EventHandler(ignoreCancelled = true)
9394
public void onPlayerQuit(@NotNull PlayerQuitEvent e) {
94-
getPlugin().handlePlayerQuit(BukkitUser.adapt(e.getPlayer(), plugin));
95+
getPlugin().handlePlayerQuit(plugin.getOnlineUser(e.getPlayer()));
9596
}
9697

9798
@EventHandler(ignoreCancelled = true)
9899
public void onPlayerChat(@NotNull AsyncPlayerChatEvent e) {
99-
if (getPlugin().handlePlayerChat(BukkitUser.adapt(e.getPlayer(), plugin), e.getMessage())) {
100+
if (getPlugin().handlePlayerChat(plugin.getOnlineUser(e.getPlayer()), e.getMessage())) {
100101
e.setCancelled(true);
101102
}
102103
}
@@ -127,7 +128,8 @@ public void onBlockGrowBoosted(@NotNull BlockGrowEvent e) {
127128

128129
@EventHandler(ignoreCancelled = true)
129130
public void onPlayerDeath(@NotNull PlayerDeathEvent e) {
130-
getPlugin().getManager().wars().ifPresent(wars -> wars.handlePlayerDeath(BukkitUser.adapt(e.getEntity(), plugin)));
131+
getPlugin().getManager().wars()
132+
.ifPresent(wars -> wars.handlePlayerDeath(plugin.getOnlineUser(e.getEntity())));
131133
}
132134

133135

@@ -164,7 +166,7 @@ public OperationPosition getPosition(@NotNull Location location) {
164166

165167
@NotNull
166168
public OperationUser getUser(@NotNull Player player) {
167-
return BukkitUser.adapt(player, plugin);
169+
return plugin.getOnlineUser(player);
168170
}
169171

170172
@Override

bukkit/src/main/java/net/william278/husktowns/user/BukkitUser.java

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.bukkit.Particle;
3434
import org.bukkit.entity.Player;
3535
import org.bukkit.inventory.ItemStack;
36+
import org.jetbrains.annotations.ApiStatus;
3637
import org.jetbrains.annotations.NotNull;
3738

3839
public final class BukkitUser extends OnlineUser {
@@ -46,6 +47,7 @@ private BukkitUser(@NotNull Player player, @NotNull HuskTowns plugin) {
4647
}
4748

4849
@NotNull
50+
@ApiStatus.Internal
4951
public static BukkitUser adapt(@NotNull Player player, @NotNull HuskTowns plugin) {
5052
return new BukkitUser(player, plugin);
5153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* This file is part of HuskTowns, licensed under the Apache License 2.0.
3+
*
4+
* Copyright (c) William278 <will27528@gmail.com>
5+
* Copyright (c) contributors
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
package net.william278.husktowns.user;
21+
22+
23+
import net.william278.husktowns.BukkitHuskTowns;
24+
import org.bukkit.entity.Player;
25+
import org.jetbrains.annotations.NotNull;
26+
import org.jetbrains.annotations.Nullable;
27+
28+
import java.util.UUID;
29+
30+
public interface BukkitUserProvider extends UserProvider {
31+
32+
@Override
33+
@NotNull
34+
default OnlineUser getOnlineUser(@NotNull UUID uuid) {
35+
return getOnlineUser(getPlugin().getServer().getPlayer(uuid));
36+
}
37+
38+
@NotNull
39+
default BukkitUser getOnlineUser(@Nullable Player player) {
40+
if (player == null) {
41+
throw new IllegalArgumentException("Player is not online");
42+
}
43+
BukkitUser user = (BukkitUser) getOnlineUserMap().get(player.getUniqueId());
44+
if (user == null) {
45+
user = BukkitUser.adapt(player, getPlugin());
46+
getOnlineUserMap().put(player.getUniqueId(), user);
47+
return user;
48+
}
49+
return user;
50+
}
51+
52+
@NotNull
53+
BukkitHuskTowns getPlugin();
54+
55+
}

0 commit comments

Comments
 (0)