#luckperms-api

1 messages · Page 17 of 1

hollow grotto
#

Maybe I'm biased because I'm a C# dev, but I'm not a big fan of Optional<T>. Then again, Java doesn't have ?., so null checks have to be done manually (or through the Optional).

#

?. only performs the operation on the right if the result of the value on the left is not null.

// This statement assigns someValue to the value returned by GetSomeBool(). If myPossiblyNullInstance is null, then the ?? operator kicks in.
// The ?? operator returns the value of the left side unless it is null; otherwise, the right side.
bool someValue = myPossiblyNullInstance?.GetSomeBool() ?? false;
crystal sonnet
#

That’s essentially what Optional is for

#

@nocturne elbow make sure your plugin depends on LP/loads after it

gloomy linden
#

how get specific perms from a user?

crystal sonnet
#

@gloomy linden do you want to check if a player has a permission?

gloomy linden
#

yes

crystal sonnet
#

Then just use the platform’s method for that @gloomy linden

signal seal
#

Can someone help me with Commodore?

#

@thorny echo know anything about Commodore?

frank driftBOT
#

Hey PerryPlaysMC! Please don't tag staff members.

signal seal
#

@jaunty pecan, Why won't Commodore work?

frank driftBOT
#

Hey PerryPlaysMC! Please don't tag staff members.

proud crypt
#

maybe try explaining your issue? no one is going to help when you don't supply information

signal seal
#

well, I followed his tut exactly

#

but it does nothing

#

commands still do what they did before

proud crypt
#

you need to explain HOW it doesn't work

#

maybe some code samples?

#

i can't actually help because i'm not a developer but this is generally required information

#

and stop tagging staff, it's against our #rules

signal seal
#

I pre register all my commands,

if (CommodoreProvider.isSupported()) {

            // get a commodore instance
            Commodore commodore = CommodoreProvider.getCommodore(this);

            // register your completions.
            registerCompletions(commodore, Miniverse.parseCmdFull("teleport"));
        }``` and I get the command with Miniverse.parseCMD
#

That is shown in the tut

#

I had a Debug in it saying "registered"

#

but it doesn't work

#

hello?

crystal sonnet
#

Patience. Not everyone can help

clever charm
#

Also Brainstone on a cruise so any development process is halted for me currently but once I get back I'll start looking over everything. Got my new computer setup and the plugins I was interested pulled :)

crystal sonnet
#

Cool 😃

minor hare
#

api

proud sentinel
#

Alright so my question is not completely related to LP but in a way it still is

#

I need to send a message when the Join event is called but that message needs to contain the players name and their prefix/suffix so it needs to be loaded after luck perms have assigned them their prefix/suffix

#

I’ve tested my plugin and the message is sent with only their name and no prefix but the leave message does contain the prefix. So I believe it’s just not loaded when the message is sent on join

gilded bane
#

What priority are you using?

proud sentinel
#

I tried Monitor, high and low

gilded bane
#

Are you using Vault or the LP API?

wide hare
#

Hello, I use this method to implment a simple permission system for some reason, but LP seemed removed my permission attachment, after I delete LP, it works

#

Is there any way to solve the problem?

jaunty pecan
#

no it should be working fine

#

what permissions are you setting?

obtuse rapids
#

So I've added LuckPerms API to my plugin using maven, and did LuckPermsApi api = LuckPerms.getApi();. Everything compiles but when I start the server with the plugin, it says that API is not loaded (I do have LuckPerms installed on the server). What am I doing wrong?

crystal sonnet
#

@obtuse rapids make sure that you're not shading the API in and that your plugin loads after

obtuse rapids
#

I added softdepend: [LuckPerms], it didn't work, depend: [LuckPerms] didn't work either

#

And all I'm doing with the API right now is
LuckPermsApi api = LuckPerms.getApi();
and
api.getUser(event.getPlayer().getName()).getPrimaryGroup()

crystal sonnet
#

@obtuse rapids How are you building your plugin?

obtuse rapids
#

I am not quite sure if I understood the question correctly, but here are the building dependencies

#

and here's a screenshot of the artifacts tab in project structure settings

gilded bane
#

What are you using to build the jar? Maven or Gradle? The "build" button in your IDE?

obtuse rapids
#

oh

#

I mean, yes I do press the build button to build my plugin

gilded bane
#

It looks like Maven

obtuse rapids
#

it is maven

jaunty pecan
#

where are you calling getApi from?

obtuse rapids
#

main class

jaunty pecan
#

where abouts in the main class

obtuse rapids
jaunty pecan
#

move it to inside of onEnable

#

the reason it's throwing that exception is because the main classes of all plugins are initialised before the process of enabling them starts

#

so the constructor of your plugin (which is effectively what you're initialising in) is called before LP enables

obtuse rapids
#

oh I see

obtuse rapids
#

Thanks, it finally works

obtuse rapids
#

Also, is there no way to get group's display name?

sudden kelp
#

Maybe via Vault?

#

@obtuse rapids

soft edge
#

Are there any limits on group names?

polar cargo
#

Hey, how i should do to get number of home count with LP api ? its metaData ? Thanks !

String homecountS = metaData.getMeta().get("home-count");
int homecount = Integer.valueOf(homecountS);
int totalhome = homecount + Integer.valueOf(args[1]);
metaData.getMeta().replace("home-count",String.valueOf(totalhome));```

Isnt correct ? thats return me an error :p
```java.lang.RuntimeException: java.lang.UnsupportedOperationException``` i got this 🤔
proud crypt
#

@obtuse rapids late reply but i think the method you are looking for is getFriendlyName()

crystal sonnet
#

@polar cargo setting meta values works differently

#

There should be examples on the wiki

polar cargo
#

i didnt find the example <w<

crystal sonnet
#

Try put instead of replace

#

And be sure to save the changes

polar cargo
#

already tried it i think

#
            {
                String key = entry.getKey();
                if (key.equalsIgnoreCase("home-count")){
                    //String value = entry.getValue();
                    entry.setValue(String.valueOf(totalhome));
                }
            }```
#

that too

crystal sonnet
#

I’m not really sure how it’s done.

#

Might have to wait for Luck

polar cargo
#

yeah thatss a bit weird for me, i dont use this api often^^

polar cargo
#

I'm not sure to understand, i created a class that have LP Event

public class LuckPermEvent {  
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance().getServer();
    public void onUserPromote(UserTrackEvent event)
    {
    //
    }
}```
How i can register it ?
```Java
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
     LuckPermsApi api = LuckPerms.getApi();
     api.getEventBus().subscribe(UserTrackEvent.class, ?);
}

Not sure to understand, its not like forge/sponge <w<

nocturne elbow
#

How would I check if a group exists?

nocturne elbow
#

Ok so this code is throwing a null pointer exception

#

And here is the error I get:

08.04 22:16:32 [Server] ERROR Error occurred while enabling CommandCheckerBlocker v1.0 (Is it up to date?)
08.04 22:16:32 [Server] INFO java.lang.NullPointerException: null
08.04 22:16:32 [Server] INFO at me.ase.CommandCheckerBlocker.Main.onEnable(Main.java:27) ~[?:?]
08.04 22:16:32 [Server] INFO at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:254) ~[spigot-1.13.2.jar:git-Spigot-518206a-c4a67ee]
08.04 22:16:32 [Server] INFO at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) ~[spigot-1.13.2.jar:git-Spigot-518206a-```
#

And line 27 is me registering the GiveRank command

polar cargo
#

🤔

shadow fjord
#

@nocturne elbow use their lp editor on web, or just download an add-on named lp gui for lp

gilded bane
cunning halo
#

hi i have luck perms on my network and wen i do /lp networksync it seys it worked bet on the other servers it dus not work wat do i do ??

#

using plugin manger

marble shore
#

How'd you set the prefix of a player programatically?

cunning halo
#

use essenshalsx

neat jackal
#

Why? He wants to know how to set a prefix of a user using the LuckPerms API. What has EssentialsX have to do with that?

marble shore
#

I've never really used LP before (At least not the API), and there seems to be no documentation at first glance. Maybe documentation could be added on how to edit prefixes and suffixes on the JavaDoc for getPrefixes on MetaData. Still leaves me wondering how to actually set a prefix with a specific weight on a player

gilded bane
#

If there's no obvious method, you could construct the node yourself and add it

#

API equivalent of giving the player/group prefix.<weight>.<prefix>: true

#

I don't actually know of any "add prefix" method in the API

marble shore
#

Alright

#

I looked at the command but sadly that depends on common which is not included in api

crystal sonnet
#

@marble shore the wiki has plenty of expamples

#

@cunning halo check these two guides:

#

!bungee

frank driftBOT
crystal sonnet
#

!sync

frank driftBOT
crystal sonnet
#

Also #support-1 is the right place for normal support

cunning halo
#

thanks

marble shore
#
        ProviderRegistration<LuckPermsApi> provider =
                Sponge.getServiceManager().getRegistration(LuckPermsApi.class).orElseThrow(NullPointerException::new);
        LuckPermsApi api = provider.getProvider();

        User user = api.getUser(player.getUniqueId());
        if (user == null) {
            player.sendMessage(Text.of(TextColors.RED, "LuckPerms profile not found."));
            return;
        }

        DataMutateResult result = user.setPermission(api.getNodeFactory().makePrefixNode(1000, text).setValue(true).build());
        System.out.println(result);``` results in "SUCCESS"
#

But the prefix was not set

crystal sonnet
#

@marble shore you need to save the changes

#

And also you can just pass the player instance. No need to get the UUID

marble shore
#

I see

#

Oh I completely missed that part in the API

#

Let me make some changes

crystal sonnet
#

👍🏻

#

That’s why there are examples on the wiki 😉

marble shore
#

Also passing Player does not work with Sponge on API version 4.4

crystal sonnet
#

Really? That’s a bug then

marble shore
#

Probably not, as it's a shared library

crystal sonnet
#

I mean did you try?

marble shore
#

Yeah, Intellij does not recognize it as valid

crystal sonnet
#

Hm. There should be a method that accepts an object

marble shore
#

I see

crystal sonnet
#

Which is used to accept native player instances

marble shore
crystal sonnet
#

Would be very surprised if that was gone

marble shore
#

No such method in getUserManager either

crystal sonnet
#

Weird. I’ll ask Luck

#

But anyways. The saving part is important

marble shore
#

So getting an user returns a mutable version that is not linked to the storage

crystal sonnet
#

In essence

nocturne elbow
#

@shadow fjord I asked how to do it with the API, not the editor

crystal sonnet
#

@nocturne elbow the error is being thrown in your onEnable. Not in the command handler

#

Having a look at the stack trace usually helps 😉

nocturne elbow
#

Yes I figured that out already

#

But I have a question with something else now

#
                    if (!api.isGroupLoaded(args[0])) {
                        api.getGroupManager().createAndLoadGroup(args[0]);
                        Group group = api.getGroupManager().getGroup(args[0]);
                    }```
#

Apparantly group is not loaded

#

It brings an error null

#

even though I just created and loaded it

rapid osprey
#

Guys, I'm having issues with the setPrimary group within the API.
I've checked the API but it doesn't seem to work.

Could you guys give an example on how it would work, this would be amazing! 😃

polar cargo
#

Can you send the part of the code you use

#

?

#

Also, if aanyone can help me for event LP that can be cool xD

rapid osprey
#

@polar cargo we used this

#

before we used the api but it doesnt work.
also that does apply as quick as we hope

rapid osprey
#

Anyone?

polar cargo
#

if you use command, use switchprimarygroup ?

rapid osprey
#

but its a prison server

#

will that add?

polar cargo
#

i mean, what you want to do ?

rapid osprey
#

i want to remove the group Z

#

and then add the group A

#

I know EzRanksPro does it but how?

polar cargo
#

I dont use bukkit plugin so i cant says for it
if you have only one group, you can do parent set A ?

rapid osprey
#

im doing Java...

polar cargo
#

But you use command in your plugin so

#

¯_(ツ)_/¯

rapid osprey
#

Yes but I wan't to switch to the API but it doesn't work..

polar cargo
#

I want the error or the part of the code you tried to use

#

for group you have something like user.setPrimayGroup(string)

rapid osprey
#

?

#

@polar cargo do you even know Java?

polar cargo
#

Yeah, but i just started to use LP as API

rapid osprey
#

And that works for you?

#

That user.setPrimaryGroup(string)

crystal sonnet
#

The primary group has nothing to do with the actual groups

polar cargo
#

i just successfully use Event, and for setPrimary group i didnt test but pretty sure it work

rapid osprey
#

Oh hello.

polar cargo
#

but you need to add the group first

crystal sonnet
#

With the default settings it can’t even be set

polar cargo
#

i think

crystal sonnet
#

As it’s calculated automatically

#

You need to assign the groups

#

Or the permission for it

#

There are examples on the wiki for that

rapid osprey
#

Brain, is there not anyway to add the group to the user without it lagging?

#

EzRanksPro does it and I don't know how.

crystal sonnet
#

Of course it doesn’t lag

#

As I said. Check the wiki

#

There are plenty of examples

rapid osprey
#

Stone, the thing is, I have.
It takes a while and it can glitch EzRanksPro.

crystal sonnet
#

If you’re using the API and it takes a while, then you’re doing it wrong. And if it glitches out ERP, then that’s not on LP

rapid osprey
#

No we're now using the commands.

#

Due to the API not working for us.

#

If you could give us an example, this would be amazing 😃

crystal sonnet
#

W I K I

rapid osprey
#

Send us a link please.

crystal sonnet
#

I don’t know how many more times I have to mention that

#

!wiki

frank driftBOT
rapid osprey
#

Thank you 😃

crystal sonnet
#

You’re welcome

rapid osprey
#

I'll contact if I need anymore help.
Sorry for wasting your time.

crystal sonnet
#

Be sure to read people’s responses next time. Though all good

#

I’ll be off btw

#

Just so you know

rapid osprey
#

@crystal sonnet sorry for the tag.
How would you make it so you can add a group?

Please help me.

frank driftBOT
#

Hey kyle! Please don't tag staff members.

crystal sonnet
#

If I’m not entirely mistaken, there’s an example for that

rapid osprey
#

I can't see one.

crystal sonnet
#

In essence you need to add the group node

rapid osprey
#

Never mind.

Is it Modifying user/group data?

crystal sonnet
#

Told you

rapid osprey
#

I can't see though.

#

Like I can't see it.

crystal sonnet
#

Oh. I misread

#

My bad

#

In any case you need to add the group node

#

And there’s a node builder for that

rapid osprey
#

Where?

crystal sonnet
#

It’s a class

#

...

rapid osprey
#

Please tell me where..

proud crypt
#

you really should read the documentation...

rapid osprey
#

I started Java not that long ago.

#

I'm doing a prestige plugin.

crystal sonnet
#

Then this is the wrong place to start

#

Minecraft plugins are not suitable for beginners

rapid osprey
#

I need to add A group
and then remove Z group without no lagg.

proud crypt
#

and? I don't even know Java but I know that reading the documentation is important before asking questions

crystal sonnet
#

Especially when using external APIs

rapid osprey
#

@upper blaze do you understand any of this?

#

one of my devs

#

he struggling with the API as you just say reAd TRhe WiKi

crystal sonnet
#

Because most things are documented there...

#

Docs exist for a reason

proud crypt
#

Sounds like you need a better understanding of Java, not the LuckPerms API

crystal sonnet
#

And then there are also the super useful javadocs

rapid osprey
#

Turbo I just need help and an example.

#

I know docs are here for a reason

#

I've been trying for hours no with no luck.

crystal sonnet
#

Then read them

rapid osprey
#

fSJKBFDSJHNFQDJMK,LMSFNKJGFPHDFGJKL

crystal sonnet
#

The thing is even if I wanted to provide an example or more details, I can’t

#

I’m on my phone in bed

rapid osprey
#
protected void execute(Event e) {
    Optional<LuckPermsApi> api = LuckPerms.getApiSafe();
    for (Group g : api.get().getGroups()) {
        if (g.getName().equals(group.getSingle(e))) {
            api.get().getStorage().deleteGroup(g).thenAcceptAsync(wasSuccessful -> {
                if (!wasSuccessful) {
                    return;
                }

                api.get().getStorage().loadAllGroups();

            }, api.get().getStorage().getAsyncExecutor());
            break;
        }
    }
}
#

what would that do?

crystal sonnet
#

And I know I figured that stuff out easily with the wiki and javadocs

rapid osprey
#

I literally need

Remove group
and then add group.

hallow aspen
#

hey

#

%luckperms_groups% have placeholder

#

but

#

%luckperms_groups_prefix%

#

😦

#

no

#

no have

#

&7[&aDefault&7] &7[&aSilver1&7] nickname: hi

#

sample

#

please

proud crypt
hallow aspen
#

okey sorry

rapid osprey
#

@proud crypt I'm still having issues, man please give me the way to do it.

frank driftBOT
#

Hey kyle! Please don't tag staff members.

proud crypt
#

I already told you I don't know Java, so I can't.

rapid osprey
#

😦

sudden kelp
fierce dew
#

how do i add/remove groups from the player ?

midnight wren
vagrant dome
#

Check If plugin is loaded If not send message if it is use that bit of code

midnight wren
#

Thanks

#

Wait.. so where would I put the if statement? In the onEnable?

neat jackal
#

I'm not working quite much with Plugins, but I think this could work:

public void onEnable() {
    if(Bukkit.getServer().getPluginManager().isPluginEnabled("LuckPerms")) {
            // do stuff
        }
}
midnight wren
#

Tried that

#

Didn't give an error, but didn't enable the plugin I'm working on

gilded bane
#

Did you mark LuckPerms as a dependency in your plugin.yml?

midnight wren
#

yeah

#

depend: [LuckPerms]

soft edge
#

does LP fully support SubjectCollections besides users and groups? I'm wanting a separate collection to store a town's permission groups in

soft edge
#

I can create alternative collections and subjects through the sponge permissions service, but it won't let me add the subjects as a user's parent

vagrant dome
#

sorry for late reply @midnight wren i have the chat muted so didnt see your messageJAVA if (getServer().getPluginManager().isPluginEnabled("LuckPerms")) { LuckPermsApi api = LuckPerms.getApi(); } else { getLogger().info("LuckPerms was not found."); getLogger().info("API will not be used."); }

midnight wren
#

That's perfectly okay

#

But do you put that in the onEnable()?

vagrant dome
#

yes

midnight wren
#

Thank you SO much

vagrant dome
#

np

midnight wren
#

How do you get a user's group?

#
String group = plugin.lapi.getUser(p.getName()).getPrimaryGroup();
#

that's sending me a nullpointexception

long moon
#

NPEs are caused by the assumption that something isn't null

#

We can't really say from a singular line of code, pretty much anything could be null there, but methods like getUser should generally always be checked for a null return

crystal sonnet
#

My guess that either plugin or plugin.lapi is null

#

The rest shouldn’t be null ever

midnight wren
#

It's the getPrimaryGroup() that's causing the error

#

The plugin and lapi are variables

#

lapi is for LuckPermsAPI

#

and plugin is the instance to my main class where I have a few other functions stored that I use

#

Do I have to check to make sure it isn't null?

midnight wren
#

Like to make sure the player actually has a group?

bitter gulch
#

How do I add or remove a user's parent groups?

bitter gulch
#

nvm figured it out

fierce dew
#

how do i add/remove groups from/to the player

#

@proud crypt

frank driftBOT
#

Hey MrIvanPlays! Please don't tag staff members.

proud crypt
#

Why tag me? I don't even know java

crystal sonnet
#

@fierce dew you might want to ask @bitter gulch

#

Or have a look at the wiki

fierce dew
#

i looked and found nothing

bitter gulch
#

Using the api you set or unset the permission node group.RANKNAME

#

then luckpermsapi.getusermamaner.save(user);

#

@fierce dew

bold charm
#

Which Luckperm version I need for Minecraft 1.12.2?

neat jackal
#

The normal one?

bold charm
#

Yes

neat jackal
#

I mean the normal one should just work fine

bold charm
#

I can't open the online editor

nocturne elbow
#

How do I change the "permissions message", (ex. you dont have the permission blah blah..... missing -mutliverse.tp to you dont have that permission.)?

proud crypt
#

that would be up to the plugin that throws that error

nocturne elbow
#

oh well I do belive it is lp

#

ill check

proud crypt
#

luckperms doesn't tell users the permissions they are lacking.

nocturne elbow
#

oh it does not

proud crypt
#

unless you are using verbose mode.

nocturne elbow
#

dont think so

neat jackal
#

There is a normal vanilla message in spigot.yml or the plugin specified one

commands:
   some-command:
       permission-message: No perm
       permission: some.perm

This can be used in plugin.yml or a simply

if(Player.hasPermissiin("some.perm")) {
     // do stuff
} else {
     Player.sendMessage("No perm");
}
crystal sonnet
#

It’s always the plugin itself that sends the lacking permissions message

#

I’ve yet to see a single exception

neat jackal
#

You may be able to set a no-permission message in the config of the plugin, but not all plugins have to support this

nocturne elbow
#

ah okay, well thanks for the fast support!

crystal sonnet
#

You’re welcome

neat jackal
#

I know I'm a little bit late, but why was this even asked in #luckperms-api?

proud crypt
#

in case of multiverse, it looks like the 'no permission' prompts are hard coded and not configurable.

nocturne elbow
#

hello

#

can anyone help me with luckperms?

#

i need to connect this two queries:

#
SELECT 
    username, 
  FROM_UNIXTIME(lastlogin/1000) 
  
FROM 
  `accounts` 

WHERE 
    FROM_UNIXTIME(lastlogin/1000) < NOW() - INTERVAL 1 MONTH
#

and

#
SELECT count(*)
FROM 
    `luckperms_players` as player, 
    `luckperms_user_permissions` as perm 

WHERE 
    `username` = '{PLAYER}' AND 
    `player`.`uuid` = `perm`.`uuid` AND
    `perm`.`permission` != 'group.default' AND
    `perm`.`permission` LIKE 'group.%';
#

i want to delete accounts where lastlogin is greater than 30 days

#

and player doesn't have any group

teal tartan
#

@nocturne elbow use api it's there for reason

nocturne elbow
#

hmm

#

i want to do it in php

#

and use cron

crystal sonnet
#

If you can setup cron jobs directly, do it with bash

#

But I’ll help you in a bit

pliant ocean
#

Hey,
I wanted to make my own BungeeCord Command and wanted to do the command / ranginfo for users where the player can see how long his rank is. Is that possible? (I do not mean the / lp user <name> info Commad)

teal tartan
#

Yes

crystal sonnet
#

You can pretty much get all info from the API

pliant ocean
#

Have you a code?

#

Can you send me the code?

crystal sonnet
#

There’s a section on the API in the wiki

#

@pliant ocean

#

Using the API is not meant for programming beginners

#

And neither is plugin programming

jaunty pecan
#

It's not that it's not meant for beginners - everyone has to start somewhere :p

#

It's more just that you're not going to learn how to do things yourself by just asking other people to write the code for you 😉

gilded bane
#

People have to start from somewhere :p

jaunty pecan
#

Indeeeed

crystal sonnet
#

And Minecraft plugins and mods proof to be a terrible choice for (absolute) programming beginners every time

#

You really need a solid grasp of the language and programming itself to not get stuck on literally everything when making plugins or mods

hollow grotto
#

Very true

#

Figure out how the console works, then play around with things like basic math or maybe random numbers if you're feeling up for a challenge. But game design is not the place to start.

We run into people all the time in a general C# community I'm in that have no coding experience at all but decide that developing a game in Unity is definitely the best way to learn how to code.

gilded bane
#

You say that, but I was that beginner once

#

I imagine there's still logs of me not knowing what a field was in Forge's IRC from many years ago

#

Also somehow I completely missed Luck's first message that was 90% the same as what I posted shh I can read

crystal sonnet
#

Never said it can’t be done. Just that it’s by far not the best place to get started @gilded bane

pliant ocean
#

Have you the methode to do this? -> I wanted to make my own BungeeCord Command and wanted to do the command / ranginfo for users where the player can see how long his rank is. Is that possible? (I do not mean the / lp user <name> info Commad)

crystal sonnet
#

As mentioned before; it is

#

And trivial to do so too

hollow grotto
#

I might sit down with Helper and come up with a plugin that lets people develop their own commands through a text file. Make it a bit more flexible than Bukkit's commands.yml (and x-plat). Probably just some sort of macro-like system which allows you to define commands, typed strongly named arguments, and a few method-like commands. I may format it something similar to how appveyor does their script files https://github.com/LuzFaltex/docs/blob/master/appveyor.yml

#

Unless you guys think that's not a good idea. ¯_(ツ)_/¯

fallow grotto
#

Currently I'm using lpUser.hasPermission(permissionNode).asBoolean();

#

and it doesnt seem like it takes into account inheritance

#

am I doing this wrong?

crystal sonnet
#

@fallow grotto if you're just doing a permission check, use the platform's permission methods

#

And the Javadocs should tell you if it does or doesn't

fallow grotto
#

in my case the player is offline

#

so I cannot

crystal sonnet
#

Then refer to the Javadocs

fallow grotto
#

🤷

#

i just want to know how to take into account groups, inheritance

#

ect.

proud crypt
#

you want inheritsPermission()

sonic flare
#

is there an event that I can listen for when someone's groups/permissions change?

gilded bane
#

Foxtrek: I mean, there's already projects like helper-js, Denizen and Skript

#

What you're describing sounds closest to Denizen to me, though I found Denizen is pretty hard to understand

primal eagle
#

How do we use the bungeecord version of this plugin?

crystal sonnet
#

@primal eagle API wise or just normally?

unique olive
#

hey can i get the patreon tag :3

#

also is there a way to get a player's player permissions (not group)

jaunty pecan
#

You caaan!

#

Thanks for contributing 😃

#

There is a way, what were you trying to accomplish though?

unique olive
#

check if a player has a specific player permission, and if so, give an item & revoke perm

#

and np, glad to support this amazing project 😃

jaunty pecan
#

You can use user.hasPermission for that

crystal sonnet
#

If it’s a LP user that should only check directly assigned permissions

unique olive
#

tyvm

drowsy moon
#

How do I obtain the metadata?

hollow grotto
#

Get nodes for a user and apply a stream filter for Node::isMetaNode

sudden kelp
#

it works when applying to a user though

#

Nevermind, used the wrong setExpiry overload

hollow grotto
#

```java
// Your code here
Some.Java.method(argument);
```

// Your code here
Some.Java.method(argument):
eager lark
#

which api method to call which would return builder? In bungee instance

eager lark
#

any help?

hollow grotto
#

When in doubt, RTFM. It may be from a bungee server, but that group is cached in the local server's memory, so the methodology for retrieving the value doesn't change.

heady valley
#

how do i make it so people are automatically in default group?

crystal sonnet
#

@heady valley people automatically end up the group called default. And for more possibilities, read this page:

#

!default

frank driftBOT
heady valley
#

@crystal sonnet im having trouble with perm working with slashwarp

frank driftBOT
#

Hey cOOM! Please don't tag staff members.

eager lark
#

@hollow grotto i would get primary group of lp

hollow grotto
#

Have you tried the link I sent you?

eager lark
#

I sent link to dev, im not a dev

#

The plugin is TAB reborn

#

And if it on bungee dont return lp primary group if player have a server context

hollow grotto
#

On that same page there's an entire section talking about context.

#

And how to work with it within the context of the API.

eager lark
#

he would like to know the method, I believe he has already read it

hollow grotto
#

I don't know off the top of my head.

#

That said, if he has questions about the API, bring him in. We may be able to help him better if we're not communicating through a proxy.

crystal sonnet
#

@heady valley no idea why you’re asking here, but that belongs in #general

heady valley
#

oh ok

stray dock
#

String group = ChatHandlers.api.getUserSafe(player.getUniqueId()).get().getPrimaryGroup().toUpperCase();

#

I can't getUser as getOfflinePlayer() ?

crystal sonnet
#

@stray dock you need to load offline players

#

The wiki has an example on how to do that

vagrant rose
#

Hello, I'm writing my own permission manager and I'd like to use LuckPerms' API for this purpose, but for only adding permissions to players. Since LuckPerms doesn't work if the server is in offline mode I can't use the API either. So is there any way to use the API's permission manager functions in offline mode?

teal tartan
#

@vagrant rose lp works on offline mode servers but i don't think you can do that

vagrant rose
#

That's sad, but thanks for the reply.

crystal sonnet
#

@vagrant rose I don’t see a reason why you wouldn’t be able to do that in offline mode

vagrant rose
#

Because I can't join to the server if the plugin is loaded and if the plugin isn't loaded then my plugin can't use the API

crystal sonnet
#

Well if you’re using Craftbukkit, then offline mode doesn’t work

#

In fact that should be in the join message

#

It works fine with Spigot @vagrant rose

vagrant rose
#

I will give it a try, but I had some trouble with Spigot last time, this is why I still using CraftBukkit

crystal sonnet
#

And if there really wasn’t an error message telling you to use Spigot if you want to use offline mode, then I’d be quite surprised tbh

#

As that would mean you have a very old version of LP

vagrant rose
#

I got the message, but I just wanted to know that is it possible with CraftBukkit offline mode

vagrant rose
#

I switched to spigot and everything looks fine

crystal sonnet
#

Think about it

#

If there is a message explicitly telling you, you need x to be able to y, what on earth makes you think it’s possible to do it without it?

vagrant rose
#

Because the AsyncPlayerJoinEvent was the problem I tought that there is a way to ignore this and only use the working part. Now the permissions works with Spigot and LP but the command auto complete doesn't. What can I do to fix it? The player has the permission but the command is red when typing and auto complete doesn't show some command.

untold oriole
#

Is the latest version LuckPerms compatible with 1.14?

hollow grotto
#

Possibly? I read 1.13 was supposed to have some big changes in how mods were supposed to attach so version upgrades would have less of an impact, though that was on Sponge's side. Idk what Bukkit is doing.

gilded bane
#

Sponge for 1.13 and 1.14 isn't even out yet, so you can't run LuckPerms on Sponge on those versions

#

From what I've heard, LP runs as-is on Bukkit/Spigot

hollow grotto
#

Ok that's true

lethal sigil
teal tartan
#

It should work, i don't see something wrong in code

verbal terrace
#

Hey together 😃 I have a question: Is it possible to stop or pause the time from a temp permission?
Thanks for help 😃

opaque apex
#

Hi everyone, I have got a question: How can I set the user prefix with the api?

verbal terrace
#

Try:
Node prefix = api.getNodeFactory().makePrefixNode(100, "[Some Prefix]").build();
user.setPermission(prefix);

opaque apex
#

i'll try

#

and how can I check if the user has the prefix now?

#

cause I want to check if it works with my nick system

#

[16:17:38 INFO]: [LP] - Prefix: None
[16:17:38 INFO]: [LP] - Suffix: None

#

uhm

#

@verbal terrace ?

verbal terrace
#

Have you saved the user?
"api.getUserManager().saveUser(user);"

#

After add or remove somthing you must save the changes

opaque apex
#

oh ok

#

sprichst du deutsch?

#

now it worked! thx 😃

verbal terrace
#

Ja spreche ich ^^

opaque apex
#

danke 😄

verbal terrace
#

Kein Problem. da muss man auch erstmal richtig durchblicken ^^

opaque apex
#

ja xD

verbal terrace
#

Can someone help me? How can i pause the time from a temp permission?

crystal sonnet
#

No real way

#

As the permission saves the end time

#

So my best idea would be to constantly push the end time back

#

Like once every second

#

@verbal terrace

teal tartan
#

Or once hour push it for hour 😉

crystal sonnet
#

Depends on how long the freeze will be

#

But in any case, you’ll need to push the end timestamp further

verbal terrace
#

Ok thank you 😃

grim echo
#

Heyy, I am using the API for changing a suffix.
But when a player logs off & on it disappears.

#
                p.sendMessage(chatutils.format("&8[&4Supreme&8] &7Je hebt succesvol de tag " + tagname + " &7geselecteerd!"));
                playerUser.clearMatching(n -> n.isSuffix() && n.getSuffix().getKey() == 50);
                playerUser.setPermission(prefix);
                api.getUserManager().saveUser(playerUser);
                p.closeInventory();
#

This is what I got rn.

crystal sonnet
#

How are you getting the playerUser?

grim echo
#
        LuckPermsApi api = LuckPerms.getApi();
        User playerUser = api.getUser(p.getUniqueId());
crystal sonnet
#

That’s odd. What LP Version? @grim echo

grim echo
#

Its for 1.7

#

But I already found it. There is nothing wrong with the code.
The server is hosting the database in NA. So its to slow.

crystal sonnet
#

Ok

#

And well, that doesn’t answer the which LP question

#

Funnily enough I was gonna suggest to see if normal commands work

grim echo
#

4.3.39 bukkit legacy is the one we are using.

crystal sonnet
#

You really could update. That’s half a year old

grim echo
#

Is that better?

#

Might that fix the issue as well?

dull rover
#

Quick question, so I handle permissions in my plugin via Vault. Some users are getting an issue with it running sync. Is there something I need to do special for luck perms to tell it to run async?

crystal sonnet
#

@grim echo well since the issue is a slow database, I’d say no

#

But there are several other improvements and fixes

#

@dull rover LuckPerms does everything async. But when you change something through the vault API while you’re in a sync context, it’ll block your current thread. As the Vault API demands that methods wait until doing the change is finished

#

That’s why you need to make the calls async.

runic bolt
#

Is there a list of groups obtainable? Trying to do a for loop with for (String g : lp.groups)

crystal sonnet
#

Pretty sure there’s a list

teal tartan
#

<GroupManager>.getLoadedGroups()

#

it's Set and not list but it will work

#

nevermind

crystal sonnet
#

You can use a set in such a for loop

#

You can use a set in such a for loop

dull rover
#

Yeah I figured so I should be able to just run it via TaskChain async and have no issues.

runic bolt
#

It gives me an error when I created the set @teal tartan

teal tartan
#

Hm?

runic bolt
#

It wants me to remove the set in the ()

teal tartan
#

You can use set in for

runic bolt
#

When I’m doing List<Group> list = ArrayList<Group>(Set) wants me to remove the (set) and replace with ()

teal tartan
#

You can use Set in for loop you don't need that

sick elbow
#

Getting a weird issue

#

i’m giving a player a permission in first join, and it works

#

but when i do /lp user (username) permission info

#

it says the player has no permissions and the perm gets deleted

crystal sonnet
#

Do you save the player after adding the permission?

sick elbow
#

ooooo

#

you're right

#

always forget that part 😅

fierce dew
#

how to use commondore?

crystal sonnet
#

Did you check the Javadocs?

fierce dew
#

where ? @crystal sonnet

frank driftBOT
#

Hey MrIvanPlays! Please don't tag staff members.

fierce dew
#

@frank drift stfu

crystal sonnet
#

Then I think it's time you learn how to add a library to your project so your IDE has the source and Javadocs

#

I personally would recommend gradle

fierce dew
#

ik how to use maven

#

but i dont know how to use that brigadier

crystal sonnet
#

Though I've heard people saying maven is easier

fierce dew
#

i hate gradle

crystal sonnet
#

In any case use maven then to include the library and make sure your IDE pulls sources and javadocs

fierce dew
#

how do i check on what argument i am ?

#

for example i need that on argument 2 on the command

#

i have the others made already via the bukkit tab completion for example

#

@crystal sonnet

frank driftBOT
#

Hey MrIvanPlays! Please don't tag staff members.

crystal sonnet
#

I know nothing about that library

wary dock
#

i got a little problem

#

if any1 can help me?

frank driftBOT
#

Hey MarinusX! Please don't tag staff members.

runic bolt
#

Hey, how can I get all groups that are active on the server? Api.getGroupManager.getLoadedGroups doesn’t work...

crystal sonnet
#

What do you even mean by that?

runic bolt
#

I need to do a for loop

#

But I can’t get a list of groups

crystal sonnet
#

So you want all groups?

runic bolt
#

yep

crystal sonnet
#

Did you check the other methods of group manager?

#

The Javadocs are typically pretty helpful

runic bolt
#

I checked...

teal tartan
#

I think you will have to load all groups first

crystal sonnet
#

Groups are loaded by default

#

And even if not, there’s a way to get all existing groups

runic bolt
#

Okay? may I get that way?

crystal sonnet
#

Don't know it

#

Though the Javadocs should be clear

lime python
gilded bane
#

From a quick glance, you could iterate over all groups then check which ones user inherits?

zenith linden
#

have a question about the api

#

i need to getmeta but idk how

crystal sonnet
#

@zenith linden did you check the wiki? There are plenty of usage examples

zenith linden
#

i figured it out

#

thanks though ❤

bright tapir
#

Hi there.

#

I used to use Vault to interact with LuckPerms' API but I figured it's time to just fully integrate with LuckPerms (this is a private plugin so there's no worry about compatibility)

#

I used to use vaultChat.getPlayerPrefix(player) to get a players prefix. I took a peek at LuckPerms' API usage and I just wanted to doublecheck that this is the correct way to get a prefix.

#

main.getLuckPermsApi().getUserManager().getUser(player.getUniqueId()).getCachedData().getMetaData(Contexts.allowAll()).getMeta().getOrDefault("prefix", "ERROR")

bright tapir
#

Or should I just use main.getLuckPermsApi().getUserManager().getUser(player.getUniqueId()).getCachedData().getMetaData(Contexts.allowAll()).getPrefix()?

crystal sonnet
#

@bright tapir I’d recommend you read the code InsideIntel posted

#

And the wiki has good examples too

bright tapir
#

Isn't that basically what I'm doing but with more variables?

#

Or is there something I'm missing..

crystal sonnet
#

The major difference is that he gets the players contexts

#

Which means per server groups and and prefixes are considered correctly

lime python
#

anyone knwo how to use User Track Event api barely says anything

crystal sonnet
#

The Javadocs explain it fairly well iirc

lime python
#

Sorry thats what I meant, the docs dont show any examples or anything

bright tapir
#

Okay, hi there.

#
public static String getPlayerPrefix(Player player) {
        Contexts contexts = luckPermsApi.getContextManager().getApplicableContexts(player);
        return luckPermsApi.getUserManager().getUser(player.getUniqueId()).getCachedData().getMetaData(contexts).getPrefix();
    }
#

I'm using this little snippet of code to get a player's prefix, but for some reason it's throwing a nullpointerexception.

#

Do I have to load the user first?

#

Or check if the user is null and then getCachedData()?

crystal sonnet
#

If a method can return null, there really isn't a way to prevent that

#

Only thing you can do is error handling

#

Or checking if it returns null

#

Also you should get the user instance first, and use it in getApplicableContexts instead of the player

#

@bright tapir

bright tapir
#

Thanks for the ping, wasn't sure if anyone responded

#

getApplicableContexts takes in an Object so it might implicitly need to to take in a User and not a Player, or else it'll error?

#

That's probably why it wasn't saying anything was wrong.

#

@crystal sonnet is this looking a bit better:

public static String getPlayerPrefix(Player player) {
        User user = luckPermsApi.getUserManager().getUser(player.getUniqueId());
        Contexts contexts = luckPermsApi.getContextManager().getApplicableContexts(user);
        return user.getCachedData().getMetaData(contexts).getPrefix();
    }
frank driftBOT
#

Hey TehBrian! Please don't tag staff members.

bright tapir
#

Sorry ;/

crystal sonnet
#

I'm pretty sure it would've worked that way

#

But doing that is more efficient and safer

bright tapir
#

Okay I'll try that.

crystal sonnet
#

And your IDE can't do code analysis that deep

bright tapir
#

I'm going to bet it's going to work now, it probably just needed user passed in rather than player.

crystal sonnet
#

As I said, I think it would've worked either way

bright tapir
#

Hmm, here's to hoping.

#

Before it was just throwing NullPointerExceptions so I guess we'll see.

crystal sonnet
#

Was it throwing or were you getting a warning?

#

That's a huge difference

bright tapir
#

Throwing.

crystal sonnet
#

Ok. Then yeah

bright tapir
#

Like, I'd get an error in my console and my entire Event wouldn't work (it's for playerchat event.)

#

Said, exception NullPointerException occurred and gave me a stack trace.

crystal sonnet
#

Yeah

bright tapir
#

Restarting server now, here's to hoping.

#

It's still not working.

#

It's giving a different exception now! Which is good!

#
public static String getPlayerPrefix(Player player) {
        User user = luckPermsApi.getUserManager().getUser(player.getUniqueId());
        Contexts contexts = luckPermsApi.getContextManager().getApplicableContexts(user);
        return user.getCachedData().getMetaData(contexts).getPrefix();
    }
``` using this code, I'm getting this stack trace:
#

oh..

#

I think I need to use a player..

crystal sonnet
#

Which is line 19?

bright tapir
#

The line where I get contexts from.

#

And that's the line we just changed from player to user.

crystal sonnet
#

Yeah.

#

Check the Javadocs, but looks like that's the issue

bright tapir
#

So it needs to be a player, but a player returns a nullpointerexception.

crystal sonnet
#

Where does it throw the NPE?

bright tapir
crystal sonnet
#

If you don't know, store the return value of each function in a variable

bright tapir
#

That's my chat event handler.

#

If I replace LuckPermsUtils.getPlayerPrefix(player) and the suffix variant aswell, to say, "Prefix" and "Suffix", it works fine.

#

Of course it literally shows up in chat as "Prefix" and "Suffix" but that just shows it's not a problem with that.

#

.. seems to just be inside the getPlayerPrefix/Suffix methods, but the methods are doing everything that the Usage in the Wiki seems to say..

#

Seems to say to give it a Player not a User so I suppose I'll put that back to player..

#

And then combining that with this..

#

it seems like I'm doing everything perfectly by the book

#

it just won't work

#

I'm going to take a further peek into getCachedData, that seems to be the best bet.

#

This is infuriating.

#

OK I've devised a little test, it's possible that we're getting a null user somehow.

#

It's

#

so the user isn't null??

crystal sonnet
#

Try using the debugger to step through the code to find out what throws null

#

Alternatively print out every return value of every method

bright tapir
#

I'm going to try that.

#

Alright first I'm trying this:

#
public static String getPlayerPrefix(Player player) {
        User user = luckPermsApi.getUserManager().getUser(player.getUniqueId());
        Contexts contexts = luckPermsApi.getContextManager().getApplicableContexts(player);
        if (user == null) {
            return "User was null.";
        }
        MetaData metaData = user.getCachedData().getMetaData(contexts);
        return metaData.getPrefix();
    }
#

Being used by this:

@EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        Player player = event.getPlayer();
        if (player.hasPermission("tfcplugin.chatcolor")) {
            event.setMessage(MiscUtils.color(event.getMessage()));
        }
        event.setFormat(MiscUtils.color(main.getConfig().getString("chat_format")
                .replace("{prefix}", LuckPermsUtils.getPlayerPrefix(player))
                .replace("{suffix}", LuckPermsUtils.getPlayerSuffix(player))));
    }
#

I know that EventHandler works with regular strings.

#

Is it possible that getPrefix() is returning null?

#

Alright, using that, I'm getting this stacktrace:

#

I'm going to try with this event now:

#
@EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {
        Player player = event.getPlayer();
        if (player.hasPermission("tfcplugin.chatcolor")) {
            event.setMessage(MiscUtils.color(event.getMessage()));
        }
        event.setFormat(MiscUtils.color(main.getConfig().getString("chat_format")
                .replace("{prefix}", LuckPermsUtils.getPlayerPrefix(player) == null ? "NOLL" : LuckPermsUtils.getPlayerPrefix(player))
                .replace("{suffix}", LuckPermsUtils.getPlayerSuffix(player) == null ? "NULE" : LuckPermsUtils.getPlayerSuffix(player))));
    }
#

Simple difference, hopefully I get NOLL TehBrianNULE in chat.

#

And based on the stack trace, I'm going to HIGHLY guess that it's just returning null. Let's see.

#

OH

#

I GOT IT

#

That's so simple.

#

Prefix was working fine, it's just since I don't have a suffix, it's returning null.

#

I feel so silly now, that makes sense.

#

Simple fix:
return metaData.getPrefix() == null ? "" : metaData.getPrefix();
instead of
return metaData.getPrefix();

#

Do the same thing with suffix counterpart and there you go.

crystal sonnet
#

Yup

#

That's why you always check where it throws

bright tapir
#

Alright. Thanks a bunch haha. Perhaps on the wiki there should be "Note: Will return null if the player doesn't have one." or something like that.

crystal sonnet
#

That's to be assumed

#

nothing = null

#

And I'm pretty sure the Javadocs say so too

bright tapir
#

Huh.

#

Mainly just for people coming from Vault.

#

With Vault it just returns an empty string.

crystal sonnet
#

Well, there's you're issue. You've committed one of the deadly sins of programming:
Because API x does y, I'm assuming API y does so too

#

Especially atrocious when applied to different (but similar (sounding)) programming languages

bright tapir
#

Yeah, issue, I suppose.

lyric solstice
#

okay I had a question about the plugin luck perms how would I get it to work on 1.7.10 if It's not loading into the server what version do I need??

lyric solstice
#

Okay thanks

jaunty pecan
#

@bright tapir glad you worked it out eventually! :p

#

just a small pointer for future reference - you're likely to be able to apply this to other projects too

#

All of the API methods are annotated with @Nullable and @NonNull labels

#

These show up in the source code, and also in the javadocs

#

Nullable means a method could return null, NonNull means it never will

#

your IDE, if it's smart enough, should warn you about it too 😉

bright tapir
#

Oh I've seen those around, I've never really thought to look into them much. That makes a lot of sense haha.

#

Thanks a bunch! :)

jaunty pecan
#

this is what I mean about your IDE warning you

#

:p

#

pretty neat

#

it detects that getPrefix might return null, so realises that could throw an NPE

#

has saved me many times 😃

bright tapir
#

Oh, that makes so much sense. I was looking at that and thinking that, in your example, it was saying that because .length() itself could return null.

#

I just need to look at what it's referring to instead. Nonnull and Nullable make a lot more sense now, thank you so much haha.

jaunty pecan
#

cool! no worries 😃

lyric solstice
#

So The legacy link for 1.7.10 dose not work or load

#

okay I had a question about the plugin luck perms how would I get it to work on 1.7.10 if It's not loading into the server what version do I need?? The Link too 4.4.19 does not work and legacy 4.4.21 will not load

lime python
#

Hey guys, so in my plugin I'm setting the player's primary group but when i check the player's info it says that their primary group is the same then i try to change it by command and it says that their group is already what i tried to change it to? the prefix stays the same throughout

crystal sonnet
#

@lyric solstice I’ve asked you before and I will again. Please check the startup logs for errors

#

And send them here

#

And you want 4.4.21

lyric solstice
#

okay sorry I didn't see that okay will do sorry

crystal sonnet
#

You’re using KCauldron? @lyric solstice

#

Or something similar?

crystal sonnet
lone fiber
#

can someone help me set luckyperms up?

crystal sonnet
lyric solstice
#

Okay

simple karma
#

Hello, here can help me with problem solving Lp

#

?

lavish bear
#

Explain ur problem.

lime python
jaunty pecan
#

Yes

#

However this is probably more appropriate

sudden kelp
#
        Node cooldown = LuckpermsBridge.getPermission().getNodeFactory().newBuilder(permissionString).setNegated(negated).setServer("gta").setExpiry(length, TimeUnit.MINUTES).build();
        Group group = permission.getGroup("il");
        group.setPermission(cooldown);
        LuckpermsBridge.getPermission().getGroupManager().saveGroup(group);
        group.refreshCachedData();
    }```
Using this code to set temp perms. I have a mysql backend. The perm shows up in the db instanntly, but a Vault perm check only "registers" the perms after /lp sync. Any ideas? Didnt have the problem with yaml backend
#
[03:20:54 INFO]: [LP] -  Platform: Bukkit
[03:20:54 INFO]: [LP] -  Server Brand: Paper
[03:20:54 INFO]: [LP] -  Server Version:
[03:20:54 INFO]: [LP] -  git-Paper-624 (MC: 1.13.2) - 1.13.2-R0.1-SNAPSHOT
[03:20:54 INFO]: [LP] -  Storage:
[03:20:54 INFO]: [LP] -     Type: MariaDB
[03:20:54 INFO]: [LP] -     Ping: 16ms
[03:20:54 INFO]: [LP] -     Connected: true
[03:20:54 INFO]: [LP] -  Messaging: Redis
[03:20:54 INFO]: [LP] -  Instance:
[03:20:54 INFO]: [LP] -     Static contexts: server=gta
[03:20:54 INFO]: [LP] -     Online Players: 1 (1 unique)
[03:20:54 INFO]: [LP] -     Uptime: 10m 5s
[03:20:54 INFO]: [LP] -     Local Data: 1 users, 15 groups, 0 tracks
#

Might be also an issue though. But maybe I have to do something special when using remote database + messaging service when using the api

sudden kelp
#

Oh well, happens with yaml aswell, no idea why I didn't catch that before

hollow grotto
#

In Bukkit, the correct way to abort loading your plugin was to return. What is the proper way to do so in Sponge?

@Listener
public void onServerStart(GameStartedServerEvent event) {
    lpTools = new LuckPermsTools();

    if (!lpTools.GetLuckPermsApi().isPresent())
        return;
}```
#

LuckPermsTools#GetLuckPermsApi just puts the LuckPermsApi instance in a Nullable. The tools class is provided for other things though - it's where I'll stick my methods for interfacing with LuckPerms.

#

Essentially though, LP is a hard dependency, so I need to abort loading my plugin should LP not be present.

hollow grotto
#

Or is that what the dependencies block of the plugin annotation is for?

jaunty pecan
#

@sudden kelp Would you mind creating a GitHub issue for that 😃

hollow grotto
#

Barring the fact that this isn't world- or server-sensitive, does anyone have any problems with the way I'm doing this? Dove into CompletableFutures for the first time today.

@Override
public CompletableFuture<String> getMeta(UUID uuid, String key) {
    if (_tools.GetLuckPermsApi().isPresent()) {
        LuckPermsApi api = _tools.GetLuckPermsApi().get();

        return api.getUserManager().loadUser(uuid)
                .thenApplyAsync(user -> user.getOwnNodes().stream()
                        .filter(Node::isMeta)
                        .filter(n -> n.getMeta().getKey().equals(key))
                        .collect(Collectors.toList())
                        .get(0))
                .thenApplyAsync(Node::getMeta)
                .thenApplyAsync(Map.Entry::getValue);
    } else return CompletableFuture.completedFuture("");
}```
#

On my to-do list for now is to change the key comparison to be case-insensitive, but otherwise I'm pretty happy with it.

hollow grotto
#

I can then call it like this:

CompletableFuture<String> titleFuture =
        luckPermsService.getMeta(player.getUniqueId(), SelectedTitle);```
#

SelectedTitle is a const string with a value of "selectedtitle", the name of the meta key for this item.

#

Er, const being a C# keyword roughly analogous to static final

late pike
#

Is it possible to get all users in a group including offline ones?

hollow grotto
#

Yup! Though I don't know whether you'll want to get all users and get a stream going that filters by group membership or if you can get a list by getting a handle on the group and asking it for its members.

#

And I don't have an IDE open currently to poke at it.

crystal sonnet
#

The way to do it is by loading all players and checking if they are in the group you want

stoic rock
#
    return player.hasPermission("group." + group);
}```
This doesn't work for me :c
crystal sonnet
#

@stoic rock What's happening?

#

Also make sure that the group is lowercase

stoic rock
#

I already checked that but It doesn't work.

#

Like I don't have any result

#

But the group exists. And my player has it in parent groups

crystal sonnet
#

So always false?

stoic rock
#

Yeah

#

I have to add manually the perm to the group?

crystal sonnet
#

And keep in mind that way of checking for a player being in a group ownership is a LP only thing

stoic rock
#

Okay, and there is no method to get all groups of a player?

crystal sonnet
#

You have to use the API directly

stoic rock
#

Which method?

crystal sonnet
#

Get all permission nodes a player has and check if they are group nodes

stoic rock
#

Alright ty 😃

delicate wren
#

I need help

#

Anyone free?

crystal sonnet
#

Just ask your question @delicate wren

delicate wren
#

How do I make it so all players on my server can use the plug ins? So far only OPs can use them and not people that don't have OP

crystal sonnet
zinc nymph
#

hey hal luckperms eine placeholder api z.b. das ich mir den rang namen anzeigen lassen kann z.b. auf nem scoreboad

crystal sonnet
#

Ja

zinc nymph
#

wo finde ich eine liste der placeholder apis?

crystal sonnet
#

In deren Liste der Erweiterungen

zinc nymph
#

kannst du mir nen link schicken? pls

crystal sonnet
#

Nein, weil
a) ich bin nicht dein Link Buttler
b) ich bin mir ziemlich sicher Google funktioniert auch für dich
c) Ich benutze PAPI nicht, weiß somit nicht, wo die Dokumentationen liegen

zinc nymph
#

ok sorry das ich frage

crystal sonnet
#

Das hat nichts mit Fragen an sich zu tun. Sondern eher mit einer Erwartungshaltung und eigener Faulheit.
Und außerdem sollte der Server-Admin in der Lage sein Plugin-Dokumentationen zu finden und zu verstehen können

late pike
#

I wanted to know if its possible to get the users in like a list from a group name but not getting every single user on the server and checking if they have the group.groupname permission. The server I'm on has a bunch of unique users

crystal sonnet
#

Not that I’m aware of

#

@late pike

late pike
#

Alright, thanks

wet yacht
#

hi anyone knows how to install tool Main items in version 1.8.8?

crystal sonnet
hollow grotto
#

Screaming, probably.

wispy harness
#

Hi, is there an event for the changes of an player's nodes? (Also Offlineplayers)

#

Mention me 😉

crystal sonnet
#

There’s is an event for when nodes change @wispy harness

wispy harness
#

how can i use that event?

#

@crystal sonnet thinksup

frank driftBOT
#

Hey iFlyinq! Please don't tag staff members.

crystal sonnet
#

Don't know by heart

#

Check the Javadocs

clever plank
#

Hey

#

Kann wer mir helfen wenn ich die LuckPermsAPI nutzen will geht sie net (will es mit meaven machen) kann wer mir die pom.xml schicken ?

#

?

neat jackal
#

Sollte im Wiki sein, lass mich mal nachschauen

sick elbow
#

How can I check if a user is in a specific group?

#

is it literally just the permission group.GROUP

crystal sonnet
#

@sick elbow yes

sick elbow
#

sweet

#

thanks

crystal sonnet
#

@clever plank Tobi hat dir den Link gegeben

atomic elbow
#

/lp is not working for my 3.0.14 vershen

atomic elbow
#

they only work in console

#

i did the thing to give me all perms

#

every time i do a /lp it tells me running luckperms v 3.0.14

nocturne elbow
#

do /lp help

proud crypt
#

This shouldn't be in the API channel btw. Use #support-1 please

clever plank
#

eine eine frage ich kann die api net nutzen xD

clever plank
#

ist egal xD

nocturne elbow
#

Polish helppp

crystal sonnet
#

@clever plank Details bitte

#

Und Englisch erhöht die Chancen extrem

clever plank
#

Hat sich erledigt

sinful cove
#

Hi, I'm trying to use the API to read out how long a player has a particular group that has been set with "addtemp". Does anyone happen to have an example?

crystal sonnet
#

I don’t think you can

sinful cove
crystal sonnet
#

The remaining time, yes

#

But not when it was added

sinful cove
#

The players should be able to read it out via ingame command /ranginfo

#

also yes the remaining time

crystal sonnet
#

Then you need to track that part yourself

wispy harness
#

Why isn't this working? ```Java
public EventBusListener(LuckPermsApi api) {
EventBus eventBus = api.getEventBus();

    eventBus.subscribe(NodeMutateEvent.class, (e) -> {
        System.out.println("Event triggered, NodeMutateEvent");
        System.out.println(e.getTarget().getFriendlyName());
    });
}```

When i do /lp user [player] parent add [group] it's not triggering (Bungee)

crystal sonnet
#

Are you getting any errors during startup?

#

Also make sure the object doesn't get destroyed/gc'ed

wispy harness
#

Not working and no errors & not garbage collected.

crystal sonnet
#

Have you doubled check that the subscribe method is called?

hollow grotto
#

Using LocalizedNode#getPrefix returns an Entry<Integer, String>. The String is clearly the text of the prefix, but what does the Integer represent?

crystal sonnet
#

Probably the priority

hollow grotto
#

That's what I would guess, but I thought I'd triple check.

crystal sonnet
#

Did you check the Javadocs of the method?

hollow grotto
#

...that would be a good idea, wouldn't it?

crystal sonnet
#

I mean I certainly don’t know for sure.

#

And Javadocs exist for a reason

#

Always a good idea to make sure the IDE has them included

hollow grotto
#

So the wiki says it's the weight. I'll hang onto those.

crystal sonnet
#

Or the source. So it can show the docs in the tooltips

hollow grotto
#

And normally they are, but IntelliJ isn't happy with me currently and isn't showing any of the javadocs.

crystal sonnet
#

That’s something you should fix

hollow grotto
#

Yeah, I'll knock that out now. Just got this method finished that's been a headache for a bit.

@Override
public CompletableFuture<List<Map.Entry<Integer, String>>> getUserEvaluatedPrefixes(UUID uuid, Contexts contexts) {
    if (_tools.getLuckPermsApi().isPresent()) {
        LuckPermsApi api = _tools.getLuckPermsApi().get();

        return api.getUserManager().loadUser(uuid)
                .thenApplyAsync(user -> user.getAllNodes(contexts).stream()
                    .filter(Node::isPrefix)
                    .map(Node::getPrefix)
                    .collect(Collectors.toList()));
    } else return CompletableFuture.completedFuture(Collections.EMPTY_LIST);
}```
#

I assume Collections.EMPTY_LIST does some compiler magic to find the type of list... I hope

hollow grotto
#

Reee

api.getUserManager.loadUser(uuid); // CompletableFuture<User>
api.getGroupManager.loadGroup(groupName); // CompletableFuture<Optional<Group>>```
#

This code seem sane enough?

@Override
public CompletableFuture<String> getGroupPrefix(String groupName) {
    if (_tools.getLuckPermsApi().isPresent()) {
        LuckPermsApi api = _tools.getLuckPermsApi().get();

        return api.getGroupManager().loadGroup(groupName)
                .thenApplyAsync(group -> {
                    if (group.isPresent()) {
                        Group g = group.get();
                        return g.getOwnNodes().stream()
                                .filter(Node::isPrefix)
                                .collect(Collectors.toList())
                                .get(0);
                    } else {
                        return api.getNodeFactory().makePrefixNode(0, "").build();
                    }
                })
                .thenApplyAsync(Node::getPrefix)
                .thenApplyAsync(Map.Entry::getValue);
    } else return CompletableFuture.completedFuture("");
}```
obsidian lintel
#

@hollow grotto isn't there also Vault? to collect the prefix from?

#

Idk I don't really dev but my dev guy said something along those lines

hollow grotto
#

This is a Sponge plugin. Sponge might have a way to get user prefixes, but groups are an unknown concept to Sponge that LP owns.

obsidian lintel
#

Ah fair enough

hollow grotto
#

Is there a limit to the amount of text that I can store in a meta node? My plan is to serialize a List<Entry<Integer, String>> into json and store that under a meta node.

#

Actually, let me re-think this. If this were a static list, this would be easy to deal with, but it's dynamic. I may need to approach this from a different angle.

crystal sonnet
#

@hollow grotto the limit depends on the storage type

hollow grotto
#

I'm using the default h2 database. But what I've decided to do instead is since the integer part of that entry represents a unique id, it'd be much easier just to use a database of my own and just set up a key column that automatically generates itself.

#

Then I can just rely on the database to keep track of those details and I don't have to code it myself.

hollow grotto
#

I'm working with a SQLite database to store titles for a Minecraft server. Titles are a cosmetic chat feature which shows up before the person's name, like so: [Title] Name: Hello World!

Titles, at their most basic level, have two properties: a unique id and the text of the title. This is pretty easy - just an integer key field that auto-increments and a string value.

This is where it gets a bit more complicated though. Not all titles are available to everyone. This falls under two conditions:

  1. Titles owned by the player (e.g. players can donate to get custom titles)
  2. Titles owned by a group (e.g. staff members playing as DMs can have special titles for gods, etc.)

To complicate things further, players are stored using a unique Guid but groups are stored by a name.

What's the best way to handle keeping track of ownership? I figure there are two options for this, but I'm interested to see if you guys have any ideas.


+---------------+---------------+---------------+------------------------+
| Id (key, int) | Text (string) | Type (string) |     Owner (string)     |
+---------------+---------------+---------------+------------------------+
|             0 | Peasant       | Group         | some-random-guid-value |
|             1 | Acolyte       | Player        | Foxtrek_64             |
+---------------+---------------+---------------+------------------------+
+---------------+---------------+
| Id (key, int) | Text (string) |
+---------------+---------------+
|             0 | Peasant       |
|             1 | Acolyte       |
+---------------+---------------+
+---------------+----------------+
| Id (key, int) | Owner (string) |
+---------------+----------------+
|             1 | Admin        |
+---------------+----------------+
+---------------+------------------------+
| Id (key, int) |      Owner (Guid)      |
+---------------+------------------------+
|             0 | Some-random-guid-value |
+---------------+------------------------+```
#

The Type column in the first example would be mapped to an enum and would determine how to parse the owner bit.

#

Another idea would be to create a master table holding all titles (named "Titles") and then create a database for each user and each group, but I could see that becoming unmanageable pretty quickly.

#

Fortunately though, one saving grace would be that titles would only ever have one owner.

#

Also, I know I'll catch flak for using sqlite instead of h2, but I need this to interop with C#, and there's no good way to do that with an h2 database.

hollow grotto
#

I ended up going with the separate tables option.

hollow grotto
#

... and now I'm questioning that decision.

tribal swallow
#

I would have 3 tables
Titles: id, prefix
Players: player_guid, title_id, other player data fields.....
Groups: id, title_id, other group data fields

hollow grotto
#

So what I ended up doing was to have a single table:


+---------------+----------------+---------------------+
| Id (key, int) | Title (string) | TitleGroup (string) |
+---------------+----------------+---------------------+
|             0 | Traveler       | admin               |
|             1 | Merchant       | Foxtrek_64          |
+---------------+----------------+---------------------+```
This `TitleGroup` is then mapped to a permission node and the permission node is applied either to the user or the group.
#

This gives me a common "owner" no matter what the end result is, and it makes it so that the database does not care about the underlying data type of the owner itself.

#

So my permission node would look something like titles.group.admin or titles.group.foxtrek_64

hollow grotto
#

What should I be returning here instead of CompletableFuture<?>? It feels like I should be explicit in my return type, but thenApplyAsync(user -> user.setPermission(metaNode)); doesn't have a return type.

@Override
public CompletableFuture<?> setUserMeta(UUID uuid, String key, String value) {
    if (getLuckPermsApi().isPresent()) {
        Node metaNode = api.getNodeFactory().makeMetaNode(key, value).build();
        return api.getUserManager().loadUser(uuid)
                .thenApplyAsync(user -> user.setPermission(metaNode));
    } else return CompletableFuture.completedFuture(null);
}```
#

And CompletableFuture<null> isn't allowed

tribal swallow
#

Does it have to return a value?

#

Can you not just use your own method for setting the data, without the override. Sorry not a sponge person

hollow grotto
#

user.setPermission(node) is a void method. .thenApplyAsync gets its return type from the lambda, and with a void lambda, the return type is... ¯_(ツ)_/¯

#

What do you mean by "without the override?"

wispy harness
#
[00:51:25 INFO]: Registering EventBus
[00:51:25 INFO]: Done registering EventBus true```
#
    public EventBusListener(LuckPermsApi api) {
        System.out.println("Registering EventBus");

        EventBus eventBus = api.getEventBus();

        boolean isSubscribed = eventBus.subscribe(NodeMutateEvent.class, (e) -> {
            System.out.println("Event triggered, NodeMutateEvent");
            System.out.println(e.getTarget().getFriendlyName());
        }).isActive();

        System.out.println("Done registering EventBus " + isSubscribed);
    }```
#

And as said, i'm using bungee maybe its not supported or something idk. (Mention me when you answer)

nocturne elbow
#

How do I add a user to a group with the API?

#

Not the primary group

#

as in /lp user <user> group add <group>

#

but programatically

sudden kelp
#

Create a group node with the nodebuilder and apply it to the LP user instance

#

More info in the lp wiki under usage

nocturne elbow
#

First time using the API, any docs anywhere, apart from the brief page on GH?

#

ah

#

missed that one

#

cheers

sudden kelp
#

Missed that the first time too😄

#

Only saw the general lp api page

azure latch
#
Node node = api.getNodeFactory().makeGroupNode(x).build();``` what do i put where x is? or am i missing something. first time using the API as well, so learning a lot
crystal sonnet
#

That’s the group name @azure latch

#

In case it’s not the case, make sure your IDE has the API’s Javadocs or Source

azure latch
#

it does, thanks

azure latch
#

how do i add a group to a player/player to a group?

#

ive got an instance of a player, i just cant find a way to add a player to a group

crystal sonnet
#

Check the wiki

#

It has a lot of examples @azure latch

azure latch
#

the github one?

#

ive looked about 5 times, ive got to be blind

crystal sonnet
#

Yes

#

It's under the developer section

#

Click on that and then more navigation should be expanded/extended

azure latch
#

im looking at the usage and cant see anything to do with adding groups. ive looked at modifying group data already

#

sorry about this, but if you have a second can you link me?

crystal sonnet
azure latch
#

so i would use user.setPermission(thegroupnode)?

crystal sonnet
#

Yes

azure latch
#

huh ok. thanks. clearly didnt read that right

azure latch
#

Using that command from earlier, no group gets assigned to me, and im not in the groups listmembers command. My code for this is here https://hastebin.com/osogokowuf.cs and there are no errors in the console or eclipse. Also, i know the worldguard API isnt the problem since the sendMessage works.

#

the tabbing on that looks really weird, but in eclipse its perfectly fine

crystal sonnet
azure latch
#

i am so dumb. this is my last one today, i promise

drowsy moon
azure latch
#

im looking

#

honestly, i have never used this with bungeecord before, but it looks like it could be from around for (ProxiedPlayer players: ProxyServer.getInstance().getPlayers()) { BaseComponent[] mes = TextComponent.fromLegacyText(format); players.sendMessage(mes); to me

#

but dont take my word for it, look for examples if you can find them, and see if any of the more experienced people will answer

crystal sonnet
#

@azure latch what?

azure latch
#

not trying to lead extreme unlucky down the completely wrong path, so wanted to see if people like you could help him

crystal sonnet
#

Ahh

#

That’s why it doesn’t make sense

azure latch
#

yup

azure latch
#
    public void PlayerEnterRegion(RegionEnterEvent e) {
        LuckPermsApi api = LuckPerms.getApi();
        Node node = api.getNodeFactory().makeGroupNode("grinder_game").build();
        if (e.getRegion().getId().equals("grinder0")) {
            loadUser(e.getPlayer()).setPermission(node);
            api.getUserManager().saveUser(e.getPlayer());
            e.getPlayer().sendMessage(ChatColor.AQUA +"Welcome to the Grinder Minigame!");

        }``` can anyone tell me why .saveUser isnt working? it says it is not acceptable parameters for player
crystal sonnet
#

@azure latch you need to pass a User instance

azure latch
#
``` will this work? the error highlighting is gone but want to be sure
crystal sonnet
#

No

#

You need to save the instance loadUser(e.getPlayer()) returns in a variable

#

Though I'm not gonna lie, this isn't programming 101 course here

azure latch
#

im completely new to java

crystal sonnet
#

Then MC is the wrong place

#

And the LP API even more so

azure latch
#

never touched it before this morning

#

i know, but i need this making for my server and thought id give it a shot

crystal sonnet
#

If you need Java help, check out the TogetherJava discord

azure latch
#

ok

#

so would User user = loadUser(e.getPlayer()); and api.getUserManager().saveUser((user)); work? sorry to keep bothering you, but id be completely lost with the console errors

crystal sonnet
#

Yes

#

As I said, best to ask for general Java help on TogetherJava

#

And well best to learn Java before

#

I hope you have at least some programming experience

azure latch
#

i know python very well, but had a mental block when i looked at the syntax

crystal sonnet
#

They hardly share any syntax

#

They come from two unrelated syntax families

azure latch
#

i know

hollow grotto
#

Actually, that may not work, since these Sponge plugins don't have a base class for their main class. I'd have to provide my own framework for that.

#

Ah well

dreamy jasper
#

Hey. I'm trying to get the prefix of a player while the player is offline, but I'm having trouble doing so.

This is the code:

                api.getUserManager().loadUser(pair.getKey().getUniqueId()); // Loads user from Entry key
                User luckPlayer = api.getUserManager().getUser(pair.getKey().getUniqueId()); // Get User using Entry key

                BungeeLogger.getGlobal().info(luckPlayer.getName()); //This prints out the correct username

                Contexts contexts = api.getContextManager().lookupApplicableContexts(luckPlayer).get(); // Error occurs here
                MetaData metaData = luckPlayer.getCachedData().getMetaData(contexts);

                String prefix = metaData.getPrefix();```

This is the error:
```15:06:04 [WARNING] Error in dispatching command
java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at commands.social.Friends.execute(Friends.java:77)

How do I solve this?

dreamy jasper
#

Nevermind I solved it (using deprecated methods unfortunately)

hollow grotto
#

@dreamy jasper Take a look at the link I sent above.

#

Or just this block:

#
@Override
public CompletableFuture<String> getUserPrefix(UUID uuid) {
    if (getLuckPermsApi().isPresent()) {
        return api.getUserManager().loadUser(uuid)
                .thenApplyAsync(user -> user.getOwnNodes().stream()
                    .filter(Node::isPrefix)
                    .collect(Collectors.toList())
                    .get(0))
                .thenApplyAsync(Node::getPrefix)
                .thenApplyAsync(Map.Entry::getValue);
    } else return CompletableFuture.completedFuture("");
}```
dreamy jasper
#

I managed to fix the issue, it just uses a deprecated method

#

But it works so

hollow grotto
#

You should avoid developing new code using deprecated methods.

#

The code sample there works using up-to-date code

dreamy jasper
#

The server is 1.8 Bungee and won't be moving from that, so if the deprecated method works right now, it'll be fine for use

#

As I don't have plans to run anything higher than 1.8

hollow grotto
#

Fair. Still poor practice.

dreamy jasper
#

I know, but in my eyes, if it works, why bother replacing it?

hollow grotto
#

"Deprecated" is another way of saying "not maintained." Should you run into any issues with the code later, any dev worth his salt will tell you to update the code to the current standard.

#

Also, in the event that things go against your plan and you end up needing it on later versions, the old code may not have a comparable version in the new API, causing you to need to rewrite that code anyways.

#

Generally, you should only use deprecated code when it either already exists or there is no code available that you should be using instead (though I would argue that in the latter case it shouldn't be deprecated).

#

Up to you though, really. It's your code.

dreamy jasper
#

Is there a simpler way of doing it without using that giant block of code you sent?

#

Or something that is just more readable?

hollow grotto
#

It's really not that bad. The worst part is that it's using a CompletableFuture.

#

Though that's an API choice, not mine.

#

And idk, I'd call that pretty legible.

#

I put in a new line break each time the operation changes so it's clear what's going on.

dreamy jasper
#

The code I'm using is much more clearer. However deprecated, it's still easier to tell what is exactly going on

hollow grotto
#

loadUser(uuid).join() might cause the if check to block, depending on how long it takes to retrieve the user. contexts doesn't need to exist, you can just call .getMetaData(Contexts.allowAll()); Beyond those housecleaning changes and the excess of line returns, I'd say that block is mostly okay.

#

Also, no point in calling .loadUser(uuid).join() if you're not going to do anything with the returned value. It's an expensive operation.

dreamy jasper
#

So how else do I get the user?

#

I need to load it from the storage in case the user is offline

hollow grotto
#

api.getUserManager().loadUser(uuid);

#

Where api is an instance of LuckPermsApi

#

My code will retrieve the prefix of the user regardless of whether they're on or offline, and it does it in three lines of code.

dreamy jasper
#

Yea but yours is extremely hard to read in my eyes

hollow grotto
#

In my defense, I'm a C# developer, not a Java developer.
Also, I put in those line breaks to make it easier to read.

#
@Override
public CompletableFuture<String> getUserPrefix(UUID uuid) {
    if (getLuckPermsApi().isPresent()) {
        return api.getUserManager().loadUser(uuid).thenApplyAsync(user -> user.getOwnNodes().stream().filter(Node::isPrefix).collect(Collectors.toList()).get(0)).thenApplyAsync(Node::getPrefix).thenApplyAsync(Map.Entry::getValue);
    } else return CompletableFuture.completedFuture("");
}```
dreamy jasper
#

It's still way too much in just one call

hollow grotto
#

That's what it looks like if you put it all in one line

#

Welcome to CompletableFutures and streaming?

#

I'm not sure what to tell you there.

#

If you look at code for professional products like what Google writes, that's exactly how it looks.

#

Well, the first example, not this abomination.

#

When you get into reading it, it's not terrible to look at

dreamy jasper
hollow grotto
#

User metadata is stored as a KeyValuePair in a Map.Entry<K, V>

#

iow I don't think your method would do much of anything... unless you're trying to get all of their meta items?

dreamy jasper
#

Nevermind it works

#

For offline and online

hollow grotto
#
@Override
public CompletableFuture<String> getUserMeta(UUID uuid, String key) {
    if (getLuckPermsApi().isPresent()) {
        return api.getUserManager().loadUser(uuid)
                .thenApplyAsync(user -> user.getOwnNodes().stream()
                        .filter(Node::isMeta)
                        .filter(n -> n.getMeta().getKey().equals(key))
                        .collect(Collectors.toList())
                        .get(0))
                .thenApplyAsync(Node::getMeta)
                .thenApplyAsync(Map.Entry::getValue);
    } else return CompletableFuture.completedFuture("");
}```
#

Any time you call user.get() or user.join(), you run the risk of blocking.

#

So you should keep it as a CompletableFuture<String> until the last possible moment.

#

And then you should pass it off to a threading service.

dreamy jasper
#

uh well so far this has been working with no problems

hollow grotto
#

You've been lucky then. Blocking = lag.

dreamy jasper
#

The database for luck perms has 4 players in it atm

hollow grotto
#

That's likely why. You will find that as your playerbase and groups grow, your version of the method will grow slower and slower.

#

Especially if it has to a bunch of joins on the back end, aggregating data from several sources.