Skip to content

Commit

Permalink
Fix: Weak player referencing (#102)
Browse files Browse the repository at this point in the history
* fix: use weak references for player caching

* chore: add relogging
  • Loading branch information
Thatsmusic99 committed Apr 10, 2023
1 parent da0950b commit bace4d2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
Expand All @@ -54,7 +55,9 @@
public class ATPlayer {

private static final @NotNull HashMap<String, ATPlayer> players = new HashMap<>();
protected @NotNull WeakReference<OfflinePlayer> player;
protected @NotNull UUID uuid;
protected @NotNull String name;
private final @NotNull PendingData<LinkedHashMap<String, @NotNull Home>> homes;
private final @NotNull PendingData<HashMap<UUID, @NotNull BlockInfo>> blockedUsers;
private final @NotNull PendingData<Boolean> isTeleportationEnabled;
Expand All @@ -65,18 +68,21 @@ public class ATPlayer {
* Internal use only.
*/
public ATPlayer(@NotNull Player player) {
this(player.getUniqueId(), player.getName());
this(player, player.getName(), player.getUniqueId());
}

/**
* Internal use only.
*/
@ApiStatus.Internal
public ATPlayer(
@NotNull final UUID uuid,
@NotNull final String name
@NotNull final OfflinePlayer player,
@NotNull final String name,
@NotNull final UUID uuid
) {
this.player = new WeakReference<>(player);
this.uuid = uuid;
this.name = name;

// Set up homes data
this.homes = new PendingData<>(CompletableFuture.supplyAsync(() -> HomeSQLManager.get().getHomes(uuid.toString()), CoreClass.async)
Expand Down Expand Up @@ -121,7 +127,7 @@ public ATPlayer(
*/
@Contract(pure = true)
public @NotNull OfflinePlayer getOfflinePlayer() {
return Bukkit.getOfflinePlayer(uuid);
return Objects.requireNonNullElseGet(player.get(), () -> Bukkit.getOfflinePlayer(uuid));
}

/*
Expand Down Expand Up @@ -205,7 +211,9 @@ public boolean isTeleportationEnabled() {
*/
@Contract(pure = true)
public @Nullable Player getPlayer() {
return Bukkit.getPlayer(uuid);
OfflinePlayer offlinePlayer = player.get();
if (offlinePlayer == null) return Bukkit.getPlayer(uuid);
return offlinePlayer.getPlayer();
}

/**
Expand Down Expand Up @@ -849,7 +857,10 @@ public boolean canSetMoreHomes() {
public static @NotNull ATPlayer getPlayer(@NotNull final Player player) {

// If the player is cached, return the cached player
if (players.containsKey(player.getName().toLowerCase())) return players.get(player.getName().toLowerCase());
if (players.containsKey(player.getName().toLowerCase())) {

return players.get(player.getName().toLowerCase());
}

// If floodgate is on the server, see if they're a Bedrock player - if so, initiate them as a Floodgate player
if (PluginHookManager.get().floodgateEnabled()) {
Expand Down Expand Up @@ -879,7 +890,7 @@ public boolean canSetMoreHomes() {

// If the player is cached, get the cached object, otherwise create a new one.
return players.containsKey(name.toLowerCase()) ? players.get(name.toLowerCase()) :
new ATPlayer(player.getUniqueId(), name);
new ATPlayer(player, name, player.getUniqueId());
}

/**
Expand All @@ -896,7 +907,7 @@ public boolean canSetMoreHomes() {
}

// Create the player object on an alternative thread
AdvancedTeleportAPI.getOfflinePlayer(name).whenComplete((player, err) -> new ATPlayer(player.getUniqueId(), name));
AdvancedTeleportAPI.getOfflinePlayer(name).whenComplete((player, err) -> new ATPlayer(player, name, player.getUniqueId()));

return null;
}
Expand All @@ -916,7 +927,19 @@ public boolean canSetMoreHomes() {
}

// Create the player object on an alternative thread
return AdvancedTeleportAPI.getOfflinePlayer(name).thenApplyAsync(player -> new ATPlayer(player.getUniqueId(), name), CoreClass.sync);
return AdvancedTeleportAPI.getOfflinePlayer(name).thenApplyAsync(player -> new ATPlayer(player, name, player.getUniqueId()), CoreClass.sync);
}

public static void relog(@NotNull Player player) {

// If the player is cached, just return it
if (players.containsKey(player.getName())) {
players.get(player.getName()).player = new WeakReference<>(player);
return;
}

// Create a new player
new ATPlayer(player);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public void onPlayerJoin(@NotNull final PlayerJoinEvent event) {
// Don't track if the player is an NPC
if (event.getPlayer().hasMetadata("NPC")) return;

// This will load the associated player data
ATPlayer.getPlayer(event.getPlayer());
// This will load/relog the associated player data
ATPlayer.relog(event.getPlayer());

// Update their username if it has been changed
PlayerSQLManager.get().updatePlayerData(event.getPlayer());
Expand Down

0 comments on commit bace4d2

Please sign in to comment.