Skip to content

Commit 4820de8

Browse files
committed
Update to 1.21.9 and fix deprecations
1 parent f68610d commit 4820de8

8 files changed

Lines changed: 133 additions & 35 deletions

File tree

build.gradle.kts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ dependencies {
3838
// optional dependency
3939
compileOnlyApi(libs.spark.api)
4040
compileOnly(libs.floodgate.api)
41+
compileOnly(libs.luckperms.api)
4142

4243
// integrated metrics
4344
implementation(libs.bstats)
@@ -72,7 +73,7 @@ paper {
7273
main = "$group.cloudbot.CloudBotMain"
7374
loader = "$group.cloudbot.CloudBotLoader"
7475

75-
apiVersion = "1.20"
76+
apiVersion = "1.21.7"
7677
authors = listOf("booky10")
7778
load = BukkitPluginDescription.PluginLoadOrder.POSTWORLD
7879

@@ -88,6 +89,10 @@ paper {
8889
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
8990
required = false
9091
}
92+
register("LuckPerms") {
93+
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
94+
required = false
95+
}
9196
}
9297
}
9398

gradle/libs.versions.toml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
[versions]
22
pluginyml = "0.6.0"
3-
runtask = "2.3.1"
4-
shadow = "8.3.3"
3+
runtask = "3.0.0"
4+
shadow = "8.3.9"
55

6-
minecraft = "1.21.1"
7-
paperapi = "1.21.1-R0.1-SNAPSHOT"
6+
minecraft = "1.21.9"
7+
paperapi = "1.21.9-R0.1-SNAPSHOT"
88

99
cloudcore = "1.1.0-SNAPSHOT"
10-
configurate = "4.1.2"
10+
configurate = "4.2.0"
1111
bstats = "3.1.0"
1212

13-
discord4j = "3.3.0-RC1"
13+
discord4j = "3.3.0-RC3"
1414
spark-api = "0.1-SNAPSHOT"
15-
floodgate = "2.2.3-SNAPSHOT"
15+
floodgate = "2.2.5-SNAPSHOT"
16+
luckperms = "5.5-SNAPSHOT"
1617

1718
[plugins]
1819
pluginyml-paper = { id = "net.minecrell.plugin-yml.paper", version.ref = "pluginyml" }
@@ -29,3 +30,4 @@ cloudcore = { module = "dev.booky:cloudcore", version.ref = "cloudcore" }
2930
discord4j-core = { module = "com.discord4j:discord4j-core", version.ref = "discord4j" }
3031
spark-api = { module = "me.lucko:spark-api", version.ref = "spark-api" }
3132
floodgate-api = { module = "org.geysermc.floodgate:api", version.ref = "floodgate" }
33+
luckperms-api = { module = "net.luckperms:api", version.ref = "luckperms" }

src/main/java/dev/booky/cloudbot/commands/MessageCommand.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import discord4j.core.object.component.Button;
2020
import discord4j.core.object.component.SelectMenu;
2121
import discord4j.core.object.component.TextInput;
22+
import discord4j.core.object.emoji.Emoji;
2223
import discord4j.core.object.entity.Message;
2324
import discord4j.core.object.entity.User;
2425
import discord4j.core.object.entity.channel.GuildMessageChannel;
25-
import discord4j.core.object.reaction.ReactionEmoji;
2626
import discord4j.core.spec.EmbedCreateFields;
2727
import discord4j.core.spec.EmbedCreateSpec;
2828
import discord4j.core.spec.InteractionPresentModalSpec;
@@ -139,28 +139,28 @@ private Mono<Void> runSelection(ChatInputInteractionEvent event, Translator i18n
139139
SelectMenu selectMenu = SelectMenu.of(SELECTION_ID,
140140
SelectMenu.Option.of(i18n.apply("command.message.selection.message.name"), SELECT_MESSAGE)
141141
.withDescription(i18n.apply("command.message.selection.message.desc"))
142-
.withEmoji(ReactionEmoji.unicode("\uD83D\uDCE7")),
142+
.withEmoji(Emoji.unicode("\uD83D\uDCE7")),
143143
SelectMenu.Option.of(i18n.apply("command.message.selection.embed.name"), SELECT_EMBED)
144144
.withDescription(i18n.apply("command.message.selection.embed.desc"))
145-
.withEmoji(ReactionEmoji.unicode("\uD83D\uDCDC")))
145+
.withEmoji(Emoji.unicode("\uD83D\uDCDC")))
146146
.withPlaceholder(i18n.apply("command.message.selection.hint"));
147147
return event.reply()
148148
.withEphemeral(true)
149149
.withComponents(ActionRow.of(selectMenu));
150150
}
151151

152152
private Button getEditButton(Translator i18n) {
153-
return Button.primary(EDIT_ID, ReactionEmoji.unicode("\u270F\uFE0F"),
153+
return Button.primary(EDIT_ID, Emoji.unicode("\u270F\uFE0F"),
154154
i18n.apply("command.message.edit"));
155155
}
156156

157157
private Button getImportButton(Translator i18n) {
158-
return Button.primary(IMPORT_ID, ReactionEmoji.unicode("\u2B07\uFE0F"),
158+
return Button.primary(IMPORT_ID, Emoji.unicode("\u2B07\uFE0F"),
159159
i18n.apply("command.message.import"));
160160
}
161161

162162
private Button getSendButton(Translator i18n) {
163-
return Button.success(SEND_ID, ReactionEmoji.unicode("\uD83D\uDCE8"),
163+
return Button.success(SEND_ID, Emoji.unicode("\uD83D\uDCE8"),
164164
i18n.apply("command.message.send"));
165165
}
166166

@@ -212,7 +212,7 @@ public InteractionPresentModalSpec createEmbedEditModal(Translator i18n, Message
212212
}
213213

214214
TextInput imageInput = TextInput.small(EE_IMAGE_ID,
215-
i18n.apply("command.message.embed.image"))
215+
i18n.apply("command.message.embed.image"))
216216
.required(false);
217217
if (embed.getImage().isPresent()) {
218218
String imageUrl = embed.getImage().map(Embed.Image::getUrl).orElseThrow();
@@ -283,7 +283,7 @@ public Mono<Void> onButtonInteract(ButtonInteractionEvent event) {
283283
modalSpec = this.createMessageEditModal(i18n, message);
284284
} else {
285285
// more complex embed creation modal
286-
Embed embed = message.getEmbeds().get(0);
286+
Embed embed = message.getEmbeds().getFirst();
287287
modalSpec = this.createEmbedEditModal(i18n, message, embed);
288288
}
289289

src/main/java/dev/booky/cloudbot/dclistener/CommandListener.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import dev.booky.cloudbot.events.custom.MainGuildDataReloadEvent;
2020
import dev.booky.cloudbot.i18n.Translator;
2121
import dev.booky.cloudbot.storage.CloudBotConfig;
22-
import dev.booky.cloudbot.util.ApplicationIdUtil;
2322
import dev.booky.cloudbot.util.CommandStringifier;
2423
import dev.booky.cloudbot.util.MarkdownEscape;
2524
import discord4j.common.util.Snowflake;
@@ -31,6 +30,8 @@
3130
import discord4j.core.object.entity.channel.GuildMessageChannel;
3231
import discord4j.core.spec.EmbedCreateSpec;
3332
import discord4j.discordjson.json.ApplicationCommandRequest;
33+
import discord4j.discordjson.json.ImmutableMessageReferenceData;
34+
import discord4j.discordjson.json.MessageReferenceData;
3435
import discord4j.rest.service.ApplicationService;
3536
import discord4j.rest.util.Color;
3637
import reactor.core.publisher.Mono;
@@ -172,6 +173,11 @@ public Mono<Void> handleException(Throwable throwable,
172173
stacktrace = stacktrace.substring(0, maxSize - 3 /*three dots*/) + "...";
173174
}
174175

176+
ImmutableMessageReferenceData.Builder ref = MessageReferenceData.builder();
177+
msg.getGuildId().ifPresent(guild -> ref.guildId(guild.asLong()));
178+
ref.channelId(msg.getChannelId().asLong());
179+
ref.messageId(msg.getId().asLong());
180+
175181
User user = event.getInteraction().getUser();
176182
logChannel.createMessage()
177183
.withEmbeds(EmbedCreateSpec.builder()
@@ -180,7 +186,7 @@ public Mono<Void> handleException(Throwable throwable,
180186
.timestamp(Instant.now())
181187
.footer(user.getTag(), user.getAvatarUrl())
182188
.build())
183-
.withMessageReference(msg.getId())
189+
.withMessageReference(ref.build())
184190
.subscribe();
185191
});
186192

src/main/java/dev/booky/cloudbot/dclistener/ReactionRoleListener.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
import discord4j.core.event.domain.message.ReactionAddEvent;
1212
import discord4j.core.event.domain.message.ReactionRemoveAllEvent;
1313
import discord4j.core.event.domain.message.ReactionRemoveEvent;
14+
import discord4j.core.object.emoji.Emoji;
15+
import discord4j.core.object.emoji.UnicodeEmoji;
1416
import discord4j.core.object.entity.Guild;
1517
import discord4j.core.object.reaction.Reaction;
16-
import discord4j.core.object.reaction.ReactionEmoji;
1718
import reactor.core.publisher.Mono;
1819

1920
import java.util.Map;
@@ -35,7 +36,7 @@ public Mono<Void> reloadReactionRoles(Guild mainGuild) {
3536
mono = mono.and(entry.getKey().getMessage(mainGuild).flatMap(message -> {
3637
Mono<Void> reactionMono = Mono.empty();
3738
for (CloudBotConfig.ReactionRole role : entry.getValue()) {
38-
ReactionEmoji.Unicode emoji = ReactionEmoji.unicode(role.getEmoji());
39+
UnicodeEmoji emoji = Emoji.unicode(role.getEmoji());
3940
if (message.getReactions().stream().map(Reaction::getEmoji).noneMatch(Predicate.isEqual(emoji))) {
4041
reactionMono = reactionMono.and(message.addReaction(emoji).then());
4142
}

src/main/java/dev/booky/cloudbot/i18n/TranslationManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Created by booky10 in CloudBot (23:24 11.10.22)
33

44
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
5-
import net.kyori.adventure.util.UTF8ResourceBundleControl;
65
import org.bukkit.plugin.Plugin;
76

87
import java.text.AttributedCharacterIterator;
@@ -11,6 +10,8 @@
1110
import java.util.Objects;
1211
import java.util.ResourceBundle;
1312

13+
import static net.kyori.adventure.util.UTF8ResourceBundleControl.utf8ResourceBundleControl;
14+
1415
public final class TranslationManager {
1516

1617
private final Plugin plugin;
@@ -73,7 +74,7 @@ public void reload() {
7374

7475
private void registerBundle(TranslationRegistry registry, Locale locale) {
7576
String baseName = this.plugin.getPluginMeta().getName().toLowerCase(Locale.ROOT);
76-
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, UTF8ResourceBundleControl.get());
77+
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, utf8ResourceBundleControl());
7778
registry.registerAll(locale, bundle, true);
7879
}
7980

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,65 @@
11
package dev.booky.cloudbot.listener;
22
// Created by booky10 in CloudBot (17:39 12.10.22)
33

4+
import com.destroystokyo.paper.profile.PlayerProfile;
45
import dev.booky.cloudbot.CloudBotManager;
56
import dev.booky.cloudbot.util.FloodgateUtil;
7+
import dev.booky.cloudbot.util.LuckPermsUtil;
8+
import io.papermc.paper.connection.PlayerConfigurationConnection;
9+
import io.papermc.paper.connection.PlayerLoginConnection;
10+
import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent;
611
import net.kyori.adventure.text.Component;
712
import net.kyori.adventure.text.format.NamedTextColor;
813
import org.bukkit.event.EventHandler;
914
import org.bukkit.event.EventPriority;
1015
import org.bukkit.event.Listener;
11-
import org.bukkit.event.player.PlayerLoginEvent;
1216

17+
import java.util.Objects;
1318
import java.util.OptionalLong;
1419
import java.util.UUID;
1520

1621
public class LoginListener implements Listener {
1722

23+
private static final UUID NULL_UUID = new UUID(0L, 0L);
24+
1825
private final CloudBotManager manager;
1926

2027
public LoginListener(CloudBotManager manager) {
2128
this.manager = manager;
2229
}
2330

2431
@EventHandler(priority = EventPriority.HIGH)
25-
public void onLogin(PlayerLoginEvent event) {
26-
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
27-
return;
32+
public void onLogin(PlayerConnectionValidateLoginEvent event) {
33+
if (event.getKickMessage() != null) {
34+
return; // already kicked
2835
}
2936
if (!this.manager.getConfig().isWhitelistActive()) {
3037
return;
3138
}
3239

33-
UUID uniqueId = event.getPlayer().getUniqueId();
34-
if (this.manager.getStorage().getWhitelist().containsKey(uniqueId)) {
35-
return;
40+
UUID playerId = switch (event.getConnection()) {
41+
case PlayerConfigurationConnection conn -> {
42+
UUID uuid = conn.getProfile().getId();
43+
yield Objects.requireNonNullElse(uuid, NULL_UUID);
44+
}
45+
case PlayerLoginConnection conn -> {
46+
PlayerProfile prof = conn.getAuthenticatedProfile();
47+
UUID uuid = prof == null ? NULL_UUID : prof.getId();
48+
yield Objects.requireNonNullElse(uuid, NULL_UUID);
49+
}
50+
default -> NULL_UUID;
51+
};
52+
if (this.manager.getStorage().getWhitelist().containsKey(playerId)) {
53+
return; // java player is whitelisted, everything is fine
3654
}
37-
OptionalLong bedrockId = FloodgateUtil.getBedrockId(uniqueId);
55+
56+
OptionalLong bedrockId = FloodgateUtil.getBedrockId(playerId);
3857
if (bedrockId.isPresent() && this.manager.getStorage().getBedrockWhitelist().containsKey(bedrockId.getAsLong())) {
39-
return;
58+
return; // bedrock player is whitelisted, everything is fine
4059
}
41-
if (event.getPlayer().hasPermission("cloudbot.bypass-whitelist")) {
42-
return;
60+
61+
if (LuckPermsUtil.hasPermission(playerId, "cloudbot.bypass-whitelist", false)) {
62+
return; // bypass permission set
4363
}
4464

4565
String inviteLink = this.manager.getConfig().getInviteLink();
@@ -48,7 +68,6 @@ public void onLogin(PlayerLoginEvent event) {
4868
message += "\nYou can join our discord using " + inviteLink + " for whitelisting yourself.";
4969
}
5070

51-
event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST,
52-
Component.text(message, NamedTextColor.RED));
71+
event.kickMessage(Component.text(message, NamedTextColor.RED));
5372
}
5473
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dev.booky.cloudbot.util;
2+
// Created by booky10 in CloudBot (17:55 04.10.2025)
3+
4+
import net.luckperms.api.LuckPerms;
5+
import net.luckperms.api.LuckPermsProvider;
6+
import net.luckperms.api.cacheddata.CachedPermissionData;
7+
import net.luckperms.api.model.user.User;
8+
import net.luckperms.api.query.QueryOptions;
9+
import org.bukkit.Bukkit;
10+
import org.bukkit.entity.Player;
11+
import org.jspecify.annotations.NullMarked;
12+
13+
import java.util.UUID;
14+
15+
@NullMarked
16+
public final class LuckPermsUtil {
17+
18+
private static final boolean LUCKPERMS;
19+
20+
static {
21+
boolean luckperms = false;
22+
try {
23+
Class.forName("net.luckperms.api.LuckPerms");
24+
luckperms = true;
25+
} catch (ClassNotFoundException ignored) {
26+
}
27+
LUCKPERMS = luckperms;
28+
}
29+
30+
private LuckPermsUtil() {
31+
}
32+
33+
public static boolean hasPermission(UUID playerId, String permission, boolean fallback) {
34+
if (LUCKPERMS) {
35+
return Handler.hasPermission(playerId, permission, fallback);
36+
}
37+
Player player = Bukkit.getPlayer(playerId);
38+
if (player != null && player.isPermissionSet(permission)) {
39+
return player.hasPermission(permission);
40+
}
41+
return fallback;
42+
}
43+
44+
private static final class Handler {
45+
46+
private Handler() {
47+
}
48+
49+
public static boolean hasPermission(UUID playerId, String permission, boolean fallback) {
50+
LuckPerms api = LuckPermsProvider.get();
51+
User user = api.getUserManager().getUser(playerId);
52+
if (user == null) {
53+
return fallback;
54+
}
55+
QueryOptions queryOpts = user.getQueryOptions();
56+
CachedPermissionData perms = user.getCachedData().getPermissionData(queryOpts);
57+
return switch (perms.checkPermission(permission)) {
58+
case TRUE -> true;
59+
case FALSE -> false;
60+
default -> fallback;
61+
};
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)