Custom ContextCalculator does not work with permissions
Closed this issue ยท 9 comments
luckperms info:
Running LuckPerms v5.0.83 by Luck.
- Platform: Sponge
- Server Brand: SpongeForge
- Server Version:
- SpongeAPI: 7.1.0-ea50f0c2 - SpongeForge: 1.12.2-2838-7.1.9
- Storage:
- Type: H2
- File Size: 0.03MB
- Messaging: None
- Instance:
- Static contexts: None
- Online Players: 1 (1 unique)
- Uptime: 4m 22s
- Local Data: 1 users, 1 groups, 0 tracks
How to reproduce
I create a fresh installation of the server with the details above. Plugins: LuckPerms and my Test Plugin.
This test plugin was made only to register a custom ContextCalculator defined like this:
public class CustomCalculator implements ContextCalculator<Subject> {
@Override
public void calculate(Subject subject, ContextConsumer contextConsumer) {
if (subject instanceof Identifiable) {
contextConsumer.accept("test", "0");
System.out.println("calculated context test=0");
}
}
@Override
public ContextSet estimatePotentialContexts() {
ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
builder.add("test", "0");
builder.add("test", "1");
return builder.build();
}
}
This ContextCalculator is registered in the main plugin class like this:
@Listener
public void onStarted(GameStartedServerEvent event) {
LuckPermsProvider.get().getContextManager().registerCalculator(new CustomCalculator());
}
/lp user KaiNoMood info
:
> User Info: kainomood
- UUID: a54a7884-9ea4-4d54-ac35-1623d70ffbe1 (type: mojang)
- Status: Online
- Primary Group: default
- Parent Groups:
- > default
- Contextual Data:
- Has contextual data: true
- Applicable contexts: (test=0) (world=world) (dimension=minecraft.overworld) (remoteip=**redacted**) (localip=**redacted**) (localport=25566) (localhost=**redacted**)
- Prefix: None
- Suffix: None
- Meta: None
When I do /lp user KaiNoMood info
, the console shows calculated context test=0
, so my custom ContextCalculator is "working" there. My context shows in the list of "Applicable contexts".
Added a permission that I did not have with /lp user KaiNoMood perm set minecraft.command.effect test=0
/lp user KaiNoMood perm info
:
kainomood's Permissions: (page 1 of 1 - 2 entries)
> minecraft.command.effect (true) (test=0)
> luckperms (true)
The error:
I enabled verbose with /lp verbose on minecraft.command.effect
, then used the /effect
command:
Console does not show calculated context test=0
as specified on my context calculator.
What I expected:
The /effect command should work because the user has the "test" context set to "0".
More details:
/lp user KaiNoMood perm checkinherits minecraft.command.effect
:
kainomood has permission minecraft.command.effect set to undefined in context global. (inherited from self)
/lp user KaiNoMood perm checkinherits minecraft.command.effect test=0
:
kainomood has permission minecraft.command.effect set to true in context test=0. (inherited from self)
Console does not show calculated context test=0
when I run the 2 commands above.
I am following the instructions provided in the wiki here. I can't make it work no matter what. Changing the name of the context, the value, registering it during GameInitializationEvent, or using a "custom" permission like "test.permission" and using it with something like player.hasPermission("test.permission")
still does not produce any positive result.
Any help is appreciated! Thank you for reading!
Could you run /lp verbose paste
after attempting to run the effect command and send the link here.
That contains IP addresses. Can I DM it to you on Discord or somewhere else privately? Sorry.
Yes, you can send the link privately if you like.
- Go to https://keybase.io/encrypt
- Set the recipient to
luck
- Copy "the secret messge" plaintext and post it here.
Sorry to be a pain - I have discord DMs disabled & ^^ is probably the easiest / most secure way if you're worried about that.
-----BEGIN PGP MESSAGE-----
Version: Keybase OpenPGP v2.1.13
Comment: https://keybase.io/crypto
wcFMAxavkAf6LzVtARAAjcqvGYbbB6RynPvrSR612NPLuOHuJNY4RhMHcgE8ajIi
sxFeHTqvA66c8ZZTaCc30+kaHI1YG8dUJ3lgerNhDjiJUJmF5udlWiNAxi/Umzqf
hHHx1P/sLT+jvFzZj7gtobok51t2pzT7rNobZOPl3gRH1j5iy3f+3/DiIYXfDSxR
cUKtDSxIO1/skw6d2Fdme/QvawQNspRinFRnyvT6b1PZUPb/hD/HHiA627lHnH4O
/MWlc/xVb/6S91VooVvxEK3iSgv5LVM/940D8DWWBZHcdIsPEIDQr7H+Pi1G2W7M
37IV2ME5Ub+Zhizv9KamRRccXtuH9mFR5TdEAt9LQnA01nHlv/jE0wdUO3fUcELK
Mrm2Sbru3ptqKaU2d/629lpFJjHo06dQEHyNW0fyh8JXNxjTLPqaHDjYmDvKQ/th
qnLRHN7S0MHkbkCbyRFVX8Mo4RgPxf0DnS1ABmTO6oWVljb8s/rFzQweVhB4wH2O
QagOTkgBUfbWEOfY9Ep5n7efwIpakUAuuBO3P2ZMInd/HC6dgxHxm+Aej0w4ern/
T4i2GPlugjFCvrUuGe5er4//MkHoj1Mu32nwECTBDXb66j3c7Epauc14r8h6LUjY
+YonaUDYSUWU9GzzYNTtZHjVdGND6fyGp+p0w4C22a0n2qu7+4SWALsADyc30JHS
ZQF3FNkmYN4ub1jbYbSviLLQxdXOgTbZBQyN0PxwSSQgkdqMzGB4C1YXwFXtOHRi
D/lMMIspj5J708hrCb0KUi/RpFU36bj2SR//XG1TalrigGcM6Gj0EUJ7dJv48TCn
0CFQ/f/O
=NpZS
-----END PGP MESSAGE-----
That's actually smart, I'll keep it in mind!
Hmm ok interesting.
I suspect the issue is with this line:
if (subject instanceof Identifiable)
Could you try removing that from your test to see if it works?
Yeah, that works.
The reason I added if (subject instanceof Identifiable)
is because in my actual code, also used in Spigot, I actually need the UUID object.
I didn't want to use UUID.fromString(subject.getIdentifier())
for performance optimization.
The Player interface in Sponge extends both Subject and Identifiable, and I just needed the UUID object, so I used Identifiable.
Is there any reason the Subject is not actually the Player object (or at least User)?
Do you have any suggestion other than deserializing the subject identifier? Thank you for your quick help!
Is there any reason the Subject is not actually the Player object (or at least User)?
Yes - there are (usually) two implementations of Subject
for a given unique player present at runtime.
- One is the actual
Player
Minecraft object - the one Sponge mixes into to implement it's API - this object will implement Identifiable and other interfaces. - The other is an object provided by the Permission Service (LuckPerms in this case) which actually implements the permission methods.
Sponge proxies the permission related methods from the actual Player object to the LuckPerms one automagically at runtime with Mixin.
Do you have any suggestion other than deserializing the subject identifier? Thank you for your quick help!
If you want to guarantee that you'll end up with a "player like" object every time, you need to use Subject#getCommandSource
.
Something like this should work:
@Override
public void calculate(@NonNull Subject subject, @NonNull ContextConsumer consumer) {
Identifiable identifiable;
if (subject instanceof Identifiable) {
identifiable = (Identifiable) subject;
} else {
Optional<CommandSource> commandSource = subject.getCommandSource();
if (commandSource.isPresent() && commandSource.get() instanceof Identifiable) {
identifiable = (Identifiable) commandSource.get();
} else {
return;
}
}
// TODO: do something with identifiable to calculate contexts
}
Or even just this will work for Players:
@Override
public void calculate(@NonNull Subject subject, @NonNull ContextConsumer consumer) {
CommandSource commandSource = subject.getCommandSource().orElse(null);
if (!(commandSource instanceof Identifiable)) {
return; // not a command source or identifiable
}
Identifiable identifiable = (Identifiable) commandSource;
// TODO: do something with identifiable to calculate contexts
}