Make FakePlayerFactory respect the given ServerLevel (#9479)

This commit is contained in:
Technici4n authored and GitHub committed 2023-05-05 10:03:55 -07:00
1 parent 3de22ffba3
commit ae05036bb3
1 file changed
+8 -27
@@ -5,7 +5,6 @@
package net.minecraftforge.common.util;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.UUID;
@@ -17,48 +16,30 @@ import net.minecraft.server.level.ServerLevel;
//To be expanded for generic Mod fake players?
public class FakePlayerFactory
{
private static GameProfile MINECRAFT = new GameProfile(UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77"), "[Minecraft]");
private static final GameProfile MINECRAFT = new GameProfile(UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77"), "[Minecraft]");
// Map of all active fake player usernames to their entities
private static Map<GameProfile, FakePlayer> fakePlayers = Maps.newHashMap();
private static WeakReference<FakePlayer> MINECRAFT_PLAYER = null;
private static final Map<FakePlayerKey, FakePlayer> fakePlayers = Maps.newHashMap();
private record FakePlayerKey(ServerLevel level, GameProfile username) { }
public static FakePlayer getMinecraft(ServerLevel level)
{
FakePlayer ret = MINECRAFT_PLAYER != null ? MINECRAFT_PLAYER.get() : null;
if (ret == null)
{
ret = FakePlayerFactory.get(level, MINECRAFT);
MINECRAFT_PLAYER = new WeakReference<FakePlayer>(ret);
}
return ret;
return get(level, MINECRAFT);
}
/**
* Get a fake player with a given username,
* Mods should either hold weak references to the return value, or listen for a
* WorldEvent.Unload and kill all references to prevent worlds staying in memory.
* WorldEvent.Unload and kill all references to prevent worlds staying in memory,
* or call this function every time and let Forge take care of the cleanup.
*/
public static FakePlayer get(ServerLevel level, GameProfile username)
{
if (!fakePlayers.containsKey(username))
{
FakePlayer fakePlayer = new FakePlayer(level, username);
fakePlayers.put(username, fakePlayer);
}
return fakePlayers.get(username);
FakePlayerKey key = new FakePlayerKey(level, username);
return fakePlayers.computeIfAbsent(key, k -> new FakePlayer(k.level(), k.username()));
}
public static void unloadLevel(ServerLevel level)
{
fakePlayers.entrySet().removeIf(entry -> entry.getValue().level == level);
if (MINECRAFT_PLAYER != null && MINECRAFT_PLAYER.get() != null && MINECRAFT_PLAYER.get().level == level) // This shouldn't be strictly necessary, but lets be aggressive.
{
FakePlayer mc = MINECRAFT_PLAYER.get();
if (mc != null && mc.level == level)
{
MINECRAFT_PLAYER = null;
}
}
}
}