mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 01:49:30 +00:00
@@ -32,6 +32,8 @@ dependencies {
|
||||
// MMOItems
|
||||
compileOnly("net.Indyuce:MMOItems-API:6.10-SNAPSHOT")
|
||||
compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT")
|
||||
// LuckPerms
|
||||
compileOnly("net.luckperms:api:5.4")
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.permission;
|
||||
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.event.EventBus;
|
||||
import net.luckperms.api.event.EventSubscription;
|
||||
import net.luckperms.api.event.group.GroupDataRecalculateEvent;
|
||||
import net.luckperms.api.event.user.UserDataRecalculateEvent;
|
||||
import net.luckperms.api.model.user.User;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LuckPermsEventListeners {
|
||||
private final JavaPlugin plugin;
|
||||
private final LuckPerms luckPerms;
|
||||
private final BiConsumer<UUID, Boolean> consumer;
|
||||
private final SchedulerAdapter<World> scheduler;
|
||||
private final List<EventSubscription<?>> subscriptions = new ArrayList<>();
|
||||
|
||||
public LuckPermsEventListeners(JavaPlugin plugin, BiConsumer<UUID, Boolean> consumer, SchedulerAdapter<World> scheduler) {
|
||||
this.plugin = plugin;
|
||||
this.consumer = consumer;
|
||||
this.scheduler = scheduler;
|
||||
RegisteredServiceProvider<LuckPerms> provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class);
|
||||
if (provider != null) {
|
||||
this.luckPerms = provider.getProvider();
|
||||
this.registerEventListeners();
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to hook into LuckPerms");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerEventListeners() {
|
||||
EventBus eventBus = this.luckPerms.getEventBus();
|
||||
this.subscriptions.add(eventBus.subscribe(this.plugin, UserDataRecalculateEvent.class, this::onUserPermissionChange));
|
||||
this.subscriptions.add(eventBus.subscribe(this.plugin, GroupDataRecalculateEvent.class, this::onGroupPermissionChange));
|
||||
}
|
||||
|
||||
public void unregisterListeners() {
|
||||
this.subscriptions.forEach(subscription -> {
|
||||
try {
|
||||
subscription.close();
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLogger().log(Level.WARNING, "Failed to close event subscription", e);
|
||||
}
|
||||
});
|
||||
this.subscriptions.clear();
|
||||
}
|
||||
|
||||
private void onUserPermissionChange(UserDataRecalculateEvent event) {
|
||||
this.consumer.accept(event.getUser().getUniqueId(), true);
|
||||
}
|
||||
|
||||
private void onGroupPermissionChange(GroupDataRecalculateEvent event) {
|
||||
this.scheduler.asyncLater(() -> {
|
||||
String groupName = event.getGroup().getName();
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
UUID uuid = player.getUniqueId();
|
||||
User user = luckPerms.getUserManager().getUser(uuid);
|
||||
if (user == null) return;
|
||||
boolean inGroup = user.getInheritedGroups(user.getQueryOptions()).stream()
|
||||
.anyMatch(g -> g.getName().equals(groupName));
|
||||
if (inGroup) {
|
||||
this.consumer.accept(uuid, false);
|
||||
}
|
||||
});
|
||||
}, 1L, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ bukkit {
|
||||
name = "CraftEngine"
|
||||
apiVersion = "1.20"
|
||||
authors = listOf("XiaoMoMi")
|
||||
contributors = listOf("jhqwqmc", "iqtesterrr")
|
||||
softDepend = listOf("PlaceholderAPI", "WorldEdit", "FastAsyncWorldEdit")
|
||||
foliaSupported = true
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.google.gson.JsonObject;
|
||||
import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
|
||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
||||
@@ -14,7 +14,6 @@ import net.momirealms.craftengine.core.font.*;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.CharacterUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -32,10 +31,13 @@ import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.view.AnvilView;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
private LuckPermsEventListeners luckPermsEventListeners;
|
||||
|
||||
public BukkitFontManager(BukkitCraftEngine plugin) {
|
||||
super(plugin);
|
||||
@@ -44,6 +46,11 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
if (this.plugin.isPluginEnabled("LuckPerms")) {
|
||||
luckPermsEventListeners = new LuckPermsEventListeners(
|
||||
plugin.bootstrap(), this::refreshEmojiSuggestions, plugin.scheduler()
|
||||
);
|
||||
}
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.bootstrap());
|
||||
}
|
||||
|
||||
@@ -51,6 +58,9 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
public void disable() {
|
||||
super.disable();
|
||||
HandlerList.unregisterAll(this);
|
||||
if (luckPermsEventListeners != null && this.plugin.isPluginEnabled("LuckPerms")) {
|
||||
luckPermsEventListeners.unregisterListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,23 +74,39 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
this.addEmojiSuggestions(player);
|
||||
plugin.scheduler().async().execute(() -> {
|
||||
Player player = event.getPlayer();
|
||||
this.addEmojiSuggestions(player);
|
||||
});
|
||||
}
|
||||
|
||||
public void refreshEmojiSuggestions(UUID playerUUID, boolean isAsync) {
|
||||
if (isAsync) {
|
||||
plugin.scheduler().async().execute(() -> {
|
||||
Player player = Bukkit.getPlayer(playerUUID);
|
||||
if (player == null) return;
|
||||
player.removeCustomChatCompletions(oldCachedEmojiSuggestions);
|
||||
this.addEmojiSuggestions(player);
|
||||
});
|
||||
} else {
|
||||
Player player = Bukkit.getPlayer(playerUUID);
|
||||
if (player == null) return;
|
||||
player.removeCustomChatCompletions(oldCachedEmojiSuggestions);
|
||||
this.addEmojiSuggestions(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void addEmojiSuggestions(Player player) {
|
||||
List<String> hasPermissions = new ArrayList<>();
|
||||
List<String> cachedEmojiSuggestions = this.cachedEmojiSuggestions();
|
||||
for (String keyword : cachedEmojiSuggestions) {
|
||||
Emoji emoji = super.emojiMapper.get(keyword);
|
||||
if (emoji == null) continue;
|
||||
if (emoji.permission() != null && !player.hasPermission(Objects.requireNonNull(emoji.permission()))) {
|
||||
continue;
|
||||
}
|
||||
hasPermissions.add(keyword);
|
||||
}
|
||||
List<String> hasPermissions = cachedEmojiSuggestions().stream()
|
||||
.filter(keyword -> {
|
||||
Emoji emoji = super.emojiMapper.get(keyword);
|
||||
if (emoji == null) return false;
|
||||
String permission = emoji.permission();
|
||||
return permission == null || player.hasPermission(permission);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
player.addCustomChatCompletions(hasPermissions);
|
||||
}
|
||||
|
||||
|
||||
@@ -443,7 +443,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
NMSPacketEvent event = new NMSPacketEvent(packet);
|
||||
onNMSPacketSend(player, event, packet);
|
||||
if (event.isCancelled()) return;
|
||||
super.write(context, packet, channelPromise);
|
||||
if (!event.hasNewPacket()) {
|
||||
super.write(context, packet, channelPromise);
|
||||
} else {
|
||||
super.write(context, event.getNewPacket(), channelPromise);
|
||||
}
|
||||
channelPromise.addListener((p) -> {
|
||||
for (Runnable task : event.getDelayedTasks()) {
|
||||
task.run();
|
||||
@@ -460,7 +464,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
NMSPacketEvent event = new NMSPacketEvent(packet);
|
||||
onNMSPacketReceive(player, event, packet);
|
||||
if (event.isCancelled()) return;
|
||||
super.channelRead(context, packet);
|
||||
if (!event.hasNewPacket()) {
|
||||
super.channelRead(context, packet);
|
||||
} else {
|
||||
super.channelRead(context, event.getNewPacket());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Cancellable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -9,8 +10,10 @@ import java.util.Optional;
|
||||
|
||||
public class NMSPacketEvent implements Cancellable {
|
||||
private boolean cancelled;
|
||||
private boolean hasNewPacket;
|
||||
private List<Runnable> delayedTasks = null;
|
||||
private final Object packet;
|
||||
private Object newPacket;
|
||||
|
||||
public NMSPacketEvent(Object packet) {
|
||||
this.packet = packet;
|
||||
@@ -20,6 +23,20 @@ public class NMSPacketEvent implements Cancellable {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void setNewPacket(Object newPacket) {
|
||||
hasNewPacket = true;
|
||||
this.newPacket = newPacket;
|
||||
}
|
||||
|
||||
public boolean hasNewPacket() {
|
||||
return hasNewPacket;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getNewPacket() {
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
public void addDelayedTask(Runnable task) {
|
||||
if (delayedTasks == null) {
|
||||
delayedTasks = new ArrayList<>();
|
||||
|
||||
@@ -339,8 +339,8 @@ public class PacketConsumers {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isChanged = false;
|
||||
List<Object> newEntries = new MarkedArrayList<>();
|
||||
Reflections.field$ClientboundPlayerInfoUpdatePacket$entries.set(packet, newEntries);
|
||||
for (Object entry : entries) {
|
||||
Object mcComponent = FastNMS.INSTANCE.field$ClientboundPlayerInfoUpdatePacket$Entry$displayName(entry);
|
||||
if (mcComponent == null) {
|
||||
@@ -359,6 +359,10 @@ public class PacketConsumers {
|
||||
}
|
||||
Object newEntry = FastNMS.INSTANCE.constructor$ClientboundPlayerInfoUpdatePacket$Entry(entry, ComponentUtils.adventureToMinecraft(component));
|
||||
newEntries.add(newEntry);
|
||||
isChanged = true;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setNewPacket(FastNMS.INSTANCE.constructor$ClientboundPlayerInfoUpdatePacket(enums, newEntries));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundPlayerInfoUpdatePacket", e);
|
||||
@@ -1769,18 +1773,12 @@ public class PacketConsumers {
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (VersionHelper.isVersionNewerThan1_20_5()) {
|
||||
event.setCancelled(true);
|
||||
Object newPacket = Reflections.constructor$ServerboundEditBookPacket.newInstance(
|
||||
Reflections.field$ServerboundEditBookPacket$slot.get(packet),
|
||||
newPages,
|
||||
newTitle
|
||||
);
|
||||
user.receivePacket(newPacket);
|
||||
} else {
|
||||
Reflections.field$ServerboundEditBookPacket$pages.set(packet, newPages);
|
||||
Reflections.field$ServerboundEditBookPacket$title.set(packet, newTitle);
|
||||
}
|
||||
Object newPacket = Reflections.constructor$ServerboundEditBookPacket.newInstance(
|
||||
Reflections.field$ServerboundEditBookPacket$slot.get(packet),
|
||||
newPages,
|
||||
newTitle
|
||||
);
|
||||
event.setNewPacket(newPacket);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundEditBookPacket", e);
|
||||
|
||||
Reference in New Issue
Block a user