1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-09-09 22:00:40 +02:00

Fix memory leak in Fabric MixinUser (#3931)

This commit is contained in:
Drex
2024-07-07 22:15:41 +02:00
committed by GitHub
parent 9e7a3d26e4
commit 55440cac01
5 changed files with 31 additions and 33 deletions

View File

@@ -59,7 +59,7 @@ public class FabricContextManager extends ContextManager<ServerPlayerEntity, Ser
throw new NullPointerException("subject"); throw new NullPointerException("subject");
} }
return ((MixinUser) subject).getQueryOptionsCache(this); return ((MixinUser) subject).luckperms$getQueryOptionsCache(this);
} }
@Override @Override

View File

@@ -125,7 +125,7 @@ public class FabricConnectionListener extends AbstractConnectionListener {
} }
// init permissions handler // init permissions handler
((MixinUser) player).initializePermissions(user); ((MixinUser) player).luckperms$initializePermissions(user);
this.plugin.getContextManager().signalContextUpdate(player); this.plugin.getContextManager().signalContextUpdate(player);
} }

View File

@@ -111,7 +111,7 @@ public class FabricPermissionsApiListener {
} }
private TriState playerPermissionCheck(ServerPlayerEntity player, String permission) { private TriState playerPermissionCheck(ServerPlayerEntity player, String permission) {
return fabricTristate(((MixinUser) player).hasPermission(permission)); return fabricTristate(((MixinUser) player).luckperms$hasPermission(permission));
} }
private TriState otherPermissionCheck(CommandSource source, String permission) { private TriState otherPermissionCheck(CommandSource source, String permission) {
@@ -127,7 +127,7 @@ public class FabricPermissionsApiListener {
} }
private Optional<String> playerGetOption(ServerPlayerEntity player, String key) { private Optional<String> playerGetOption(ServerPlayerEntity player, String key) {
return Optional.ofNullable(((MixinUser) player).getOption(key)); return Optional.ofNullable(((MixinUser) player).luckperms$getOption(key));
} }
private Optional<String> otherGetOption(CommandSource source, String key) { private Optional<String> otherGetOption(CommandSource source, String key) {

View File

@@ -39,6 +39,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -53,29 +54,26 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class ServerPlayerEntityMixin implements MixinUser { public abstract class ServerPlayerEntityMixin implements MixinUser {
/** Cache a reference to the LP {@link User} instance loaded for this player */ /** Cache a reference to the LP {@link User} instance loaded for this player */
@Unique
private User luckperms$user; private User luckperms$user;
/** /**
* Hold a QueryOptionsCache instance on the player itself, so we can just cast instead of * Hold a QueryOptionsCache instance on the player itself, so we can just cast instead of
* having to maintain a map of Player->Cache. * having to maintain a map of Player->Cache.
*/ */
@Unique
private QueryOptionsCache<ServerPlayerEntity> luckperms$queryOptions; private QueryOptionsCache<ServerPlayerEntity> luckperms$queryOptions;
// Used by PlayerChangeWorldCallback hook below. // Used by PlayerChangeWorldCallback hook below.
@Shadow public abstract ServerWorld getServerWorld(); @Shadow public abstract ServerWorld getServerWorld();
@Override @Override
public User getLuckPermsUser() { public User luckperms$getUser() {
return this.luckperms$user; return this.luckperms$user;
} }
@Override @Override
public QueryOptionsCache<ServerPlayerEntity> getQueryOptionsCache() { public QueryOptionsCache<ServerPlayerEntity> luckperms$getQueryOptionsCache(FabricContextManager contextManager) {
return this.luckperms$queryOptions;
}
@Override
public QueryOptionsCache<ServerPlayerEntity> getQueryOptionsCache(FabricContextManager contextManager) {
if (this.luckperms$queryOptions == null) { if (this.luckperms$queryOptions == null) {
this.luckperms$queryOptions = contextManager.newQueryOptionsCache((ServerPlayerEntity) (Object) this); this.luckperms$queryOptions = contextManager.newQueryOptionsCache((ServerPlayerEntity) (Object) this);
} }
@@ -83,17 +81,21 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
} }
@Override @Override
public void initializePermissions(User user) { public void luckperms$initializePermissions(User user) {
if (user == null) {
return;
}
this.luckperms$user = user; this.luckperms$user = user;
// ensure query options cache is initialised too. // ensure query options cache is initialised too.
if (this.luckperms$queryOptions == null) { if (this.luckperms$queryOptions == null) {
this.getQueryOptionsCache((FabricContextManager) user.getPlugin().getContextManager()); this.luckperms$getQueryOptionsCache((FabricContextManager) user.getPlugin().getContextManager());
} }
} }
@Override @Override
public Tristate hasPermission(String permission) { public Tristate luckperms$hasPermission(String permission) {
if (permission == null) { if (permission == null) {
throw new NullPointerException("permission"); throw new NullPointerException("permission");
} }
@@ -101,11 +103,11 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
// "fake" players will have our mixin, but won't have been initialised. // "fake" players will have our mixin, but won't have been initialised.
return Tristate.UNDEFINED; return Tristate.UNDEFINED;
} }
return hasPermission(permission, this.luckperms$queryOptions.getQueryOptions()); return luckperms$hasPermission(permission, this.luckperms$queryOptions.getQueryOptions());
} }
@Override @Override
public Tristate hasPermission(String permission, QueryOptions queryOptions) { public Tristate luckperms$hasPermission(String permission, QueryOptions queryOptions) {
if (permission == null) { if (permission == null) {
throw new NullPointerException("permission"); throw new NullPointerException("permission");
} }
@@ -124,7 +126,7 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
} }
@Override @Override
public String getOption(String key) { public String luckperms$getOption(String key) {
if (key == null) { if (key == null) {
throw new NullPointerException("key"); throw new NullPointerException("key");
} }
@@ -132,11 +134,11 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
// "fake" players will have our mixin, but won't have been initialised. // "fake" players will have our mixin, but won't have been initialised.
return null; return null;
} }
return getOption(key, this.luckperms$queryOptions.getQueryOptions()); return luckperms$getOption(key, this.luckperms$queryOptions.getQueryOptions());
} }
@Override @Override
public String getOption(String key, QueryOptions queryOptions) { public String luckperms$getOption(String key, QueryOptions queryOptions) {
if (key == null) { if (key == null) {
throw new NullPointerException("key"); throw new NullPointerException("key");
} }
@@ -155,15 +157,13 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
} }
@Inject(at = @At("TAIL"), method = "copyFrom") @Inject(at = @At("TAIL"), method = "copyFrom")
private void luckperms_copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) { private void luckperms$copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) {
MixinUser oldMixin = (MixinUser) oldPlayer; MixinUser oldMixin = (MixinUser) oldPlayer;
this.luckperms$user = oldMixin.getLuckPermsUser(); luckperms$initializePermissions(oldMixin.luckperms$getUser());
this.luckperms$queryOptions = oldMixin.getQueryOptionsCache();
this.luckperms$queryOptions.invalidate();
} }
@Inject(at = @At("TAIL"), method = "worldChanged") @Inject(at = @At("TAIL"), method = "worldChanged")
private void luckperms_onChangeDimension(ServerWorld targetWorld, CallbackInfo ci) { private void luckperms$onChangeDimension(ServerWorld targetWorld, CallbackInfo ci) {
PlayerChangeWorldCallback.EVENT.invoker().onChangeWorld(this.getServerWorld(), targetWorld, (ServerPlayerEntity) (Object) this); PlayerChangeWorldCallback.EVENT.invoker().onChangeWorld(this.getServerWorld(), targetWorld, (ServerPlayerEntity) (Object) this);
} }
} }

View File

@@ -38,9 +38,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
*/ */
public interface MixinUser { public interface MixinUser {
User getLuckPermsUser(); User luckperms$getUser();
QueryOptionsCache<ServerPlayerEntity> getQueryOptionsCache();
/** /**
* Gets (or creates using the manager) the objects {@link QueryOptionsCache}. * Gets (or creates using the manager) the objects {@link QueryOptionsCache}.
@@ -48,23 +46,23 @@ public interface MixinUser {
* @param contextManager the contextManager * @param contextManager the contextManager
* @return the cache * @return the cache
*/ */
QueryOptionsCache<ServerPlayerEntity> getQueryOptionsCache(FabricContextManager contextManager); QueryOptionsCache<ServerPlayerEntity> luckperms$getQueryOptionsCache(FabricContextManager contextManager);
/** /**
* Initialises permissions for this player using the given {@link User}. * Initialises permissions for this player using the given {@link User}.
* *
* @param user the user * @param user the user
*/ */
void initializePermissions(User user); void luckperms$initializePermissions(User user);
// methods to perform permission checks using the User instance initialised on login // methods to perform permission checks using the User instance initialised on login
Tristate hasPermission(String permission); Tristate luckperms$hasPermission(String permission);
Tristate hasPermission(String permission, QueryOptions queryOptions); Tristate luckperms$hasPermission(String permission, QueryOptions queryOptions);
String getOption(String key); String luckperms$getOption(String key);
String getOption(String key, QueryOptions queryOptions); String luckperms$getOption(String key, QueryOptions queryOptions);
} }