9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-31 21:06:31 +00:00

Merge pull request #521 from jhqwqmc/dev

空安全以及交互权限判断
This commit is contained in:
XiaoMoMi
2025-12-30 22:08:40 +08:00
committed by GitHub
27 changed files with 78 additions and 30 deletions

View File

@@ -16,10 +16,7 @@ import net.momirealms.craftengine.core.block.properties.BooleanProperty;
import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.entity.player.InteractionResult;
import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.HorizontalDirection;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.context.UseOnContext;
import javax.annotation.Nullable;
@@ -198,13 +195,13 @@ public class ButtonBlockBehavior extends BukkitBlockBehavior {
private static class Factory implements BlockBehaviorFactory<ButtonBlockBehavior> {
@SuppressWarnings({"unchecked", "DuplicatedCode"})
@SuppressWarnings("DuplicatedCode")
@Override
public ButtonBlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
BooleanProperty powered = (BooleanProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("powered"), "warning.config.block.behavior.button.missing_powered");
int ticksToStayPressed = ResourceConfigUtils.getAsInt(arguments.getOrDefault("ticks-to-stay-pressed", 30), "ticks-to-stay-pressed");
boolean canButtonBeActivatedByArrows = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-activated-by-arrows", true), "can-be-activated-by-arrows");
Map<String, Object> sounds = (Map<String, Object>) arguments.get("sounds");
Map<String, Object> sounds = MiscUtils.castToMap(arguments.get("sounds"), true);
SoundData buttonClickOnSound = null;
SoundData buttonClickOffSound = null;
if (sounds != null) {

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.block.behavior;
import io.papermc.paper.event.entity.EntityInsideBlockEvent;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntitySelectors;
@@ -15,13 +16,13 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.PressurePlateSensitivity;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldEvents;
import org.bukkit.GameEvent;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import javax.annotation.Nullable;
@@ -92,10 +93,16 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
@Override
@SuppressWarnings("UnstableApiUsage")
public void entityInside(Object thisBlock, Object[] args, Callable<Object> superMethod) {
EntityInsideBlockEvent event = new EntityInsideBlockEvent(FastNMS.INSTANCE.method$Entity$getBukkitEntity(args[3]), FastNMS.INSTANCE.method$CraftBlock$at(args[1], args[2]));
Entity entity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(args[3]);
Block block = FastNMS.INSTANCE.method$CraftBlock$at(args[1], args[2]);
EntityInsideBlockEvent event = new EntityInsideBlockEvent(entity, block);
if (EventUtils.fireAndCheckCancel(event)) {
return;
}
boolean cannotInteract = entity instanceof Player p && !BukkitCraftEngine.instance().antiGriefProvider().canInteract(p, block.getLocation());
if (cannotInteract) {
return;
}
Object state = args[0];
int signalForState = this.getSignalForState(state);
if (signalForState == 0) {
@@ -221,13 +228,13 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
private static class Factory implements BlockBehaviorFactory<PressurePlateBlockBehavior> {
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "DuplicatedCode"})
@Override
public PressurePlateBlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
Property<Boolean> powered = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("powered"), "warning.config.block.behavior.pressure_plate.missing_powered");
PressurePlateSensitivity pressurePlateSensitivity = PressurePlateSensitivity.byName(arguments.getOrDefault("sensitivity", "everything").toString());
int pressedTime = ResourceConfigUtils.getAsInt(arguments.getOrDefault("pressed-time", 20), "pressed-time");
Map<String, Object> sounds = (Map<String, Object>) arguments.get("sounds");
Map<String, Object> sounds = MiscUtils.castToMap(arguments.get("sounds"), true);
SoundData onSound = null;
SoundData offSound = null;
if (sounds != null) {

View File

@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
@@ -112,8 +113,8 @@ public class SimpleStorageBlockEntity extends BlockEntity {
}
}
public void onPlayerClose(Player player) {
if (!isValidContainer()) return;
public void onPlayerClose(@Nullable Player player) {
if (player == null || !isValidContainer()) return;
if (!player.isSpectatorMode()) {
// 有非观察者的人,那么就不触发关闭音效和事件
for (HumanEntity viewer : this.inventory.getViewers()) {
@@ -187,7 +188,9 @@ public class SimpleStorageBlockEntity extends BlockEntity {
int validViewers = 0;
for (HumanEntity viewer : viewers) {
if (viewer instanceof org.bukkit.entity.Player player) {
maxInteractionDistance = Math.max(BukkitAdaptors.adapt(player).getCachedInteractionRange(), maxInteractionDistance);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
maxInteractionDistance = Math.max(serverPlayer.getCachedInteractionRange(), maxInteractionDistance);
if (player.getGameMode() != GameMode.SPECTATOR) {
validViewers++;
}

View File

@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.entity.furniture.*;
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
@@ -122,7 +123,9 @@ public class BukkitFurniture extends Furniture {
this.location = LocationUtils.toLocation(position);
Object removePacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(MiscUtils.init(new IntArrayList(), l -> l.add(itemDisplay.getEntityId())));
for (Player player : itemDisplay.getTrackedPlayers()) {
BukkitAdaptors.adapt(player).sendPacket(removePacket, false);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
serverPlayer.sendPacket(removePacket, false);
}
itemDisplay.teleportAsync(this.location).thenAccept(result -> {
if (result) {
@@ -132,7 +135,9 @@ public class BukkitFurniture extends Furniture {
Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(),
itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0);
for (Player player : itemDisplay.getTrackedPlayers()) {
BukkitAdaptors.adapt(player).sendPacket(addPacket, false);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
serverPlayer.sendPacket(addPacket, false);
}
future.complete(true);
} else {
@@ -151,8 +156,10 @@ public class BukkitFurniture extends Furniture {
Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(),
itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0);
for (Player player : itemDisplay.getTrackedPlayers()) {
BukkitAdaptors.adapt(player).sendPacket(removePacket, false);
BukkitAdaptors.adapt(player).sendPacket(addPacket, false);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
serverPlayer.sendPacket(removePacket, false);
serverPlayer.sendPacket(addPacket, false);
}
}

View File

@@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
@@ -271,7 +272,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
// 补发一次包,修复
for (Player player : entity.getTrackedPlayers()) {
BukkitAdaptors.adapt(player).sendPacket(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
serverPlayer.sendPacket(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entity.getEntityId(), entity.getUniqueId(), location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw(),
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
), false);

View File

@@ -128,6 +128,7 @@ public class FurnitureEventListener implements Listener {
public void onFurniturePreBreak(FurnitureAttemptBreakEvent event) {
Player bukkitPlayer = event.getPlayer();
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
if (player == null) return;
Item<ItemStack> itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND);
if (!BukkitItemUtils.isDebugStick(itemInHand)) return;
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
@@ -159,6 +160,7 @@ public class FurnitureEventListener implements Listener {
public void onInteractFurniture(FurnitureInteractEvent event) {
Player bukkitPlayer = event.getPlayer();
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
if (player == null) return;
Item<ItemStack> itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND);
if (!BukkitItemUtils.isDebugStick(itemInHand)) return;
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {

View File

@@ -230,7 +230,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
changed = true;
}
}
if (Config.allowEmojiChat() && !Config.disableChatReport()) {
if (Config.allowEmojiChat()/* && !Config.disableChatReport()*/) {
EmojiTextProcessResult result = replaceJsonEmoji(rawJsonMessage, BukkitAdaptors.adapt(player));
if (result.replaced()) {
rawJsonMessage = result.text();

View File

@@ -192,6 +192,11 @@ public class ItemEventListener implements Listener {
boolean flag = player.isSneaking() && hasItem;
if (!flag) {
if (immutableBlockState.behavior() instanceof AbstractBlockBehavior behavior) {
if (!BukkitCraftEngine.instance().antiGriefProvider().canInteract(player, block.getLocation())) {
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
event.setCancelled(true);
return;
}
InteractionResult result = behavior.useOnBlock(useOnContext, immutableBlockState);
if (result.success()) {
serverPlayer.updateLastSuccessfulInteractionTick(serverPlayer.gameTicks());
@@ -373,8 +378,9 @@ public class ItemEventListener implements Listener {
return;
Player player = event.getPlayer();
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer.isSpectatorMode())
if (serverPlayer == null || serverPlayer.isSpectatorMode()) {
return;
}
// Gets the item in hand
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
// prevents duplicated events

View File

@@ -481,7 +481,9 @@ public class RecipeEventListener implements Listener {
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
if (finalCost >= maxRepairCost && !BukkitAdaptors.adapt(player).canInstabuild()) {
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
if (finalCost >= maxRepairCost && !serverPlayer.canInstabuild()) {
hasResult = false;
}
@@ -663,6 +665,7 @@ public class RecipeEventListener implements Listener {
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
// 对低版本nothing不全的兼容
if (!VersionHelper.isOrAbove1_20_5() && LegacyInventoryUtils.isHotBarSwapAndReadd(action)) {
@@ -878,6 +881,7 @@ public class RecipeEventListener implements Listener {
org.bukkit.inventory.Recipe recipe = inventory.getRecipe();
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
if (recipe instanceof SmithingTransformRecipe transformRecipe) {
Key recipeId = KeyUtils.namespacedKey2Key(transformRecipe.getKey());

View File

@@ -73,7 +73,7 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
if (VersionHelper.isOrAbove1_20_5()) {
if (event.getDamageSource().getCausingEntity() instanceof Player player) {
optionalPlayer = BukkitAdaptors.adapt(player);
builder.withParameter(DirectContextParameters.PLAYER, optionalPlayer);
builder.withOptionalParameter(DirectContextParameters.PLAYER, optionalPlayer);
}
}
ContextHolder contextHolder = builder.build();

View File

@@ -48,10 +48,10 @@ import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.Nullable;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URL;
@@ -424,8 +424,9 @@ public class BukkitCraftEngine extends CraftEngine {
}
}
public BukkitServerPlayer adapt(@NotNull org.bukkit.entity.Player player) {
Objects.requireNonNull(player, "player cannot be null");
@Nullable
public BukkitServerPlayer adapt(@Nullable Player player) {
if (player == null) return null;
return (BukkitServerPlayer) networkManager().getOnlineUser(player);
}

View File

@@ -4,6 +4,7 @@ import net.kyori.adventure.util.Index;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.command.feature.*;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.core.plugin.command.AbstractCommandManager;
import net.momirealms.craftengine.core.plugin.command.CommandFeature;
import net.momirealms.craftengine.core.plugin.command.sender.Sender;
@@ -87,7 +88,9 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
@Override
protected Locale getLocale(CommandSender sender) {
if (sender instanceof Player player) {
return BukkitAdaptors.adapt(player).selectedLocale();
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return null;
return serverPlayer.selectedLocale();
}
return null;
}

View File

@@ -21,6 +21,7 @@ public class DebugClearCooldownCommand extends BukkitCommandFeature<CommandSende
.required("player", PlayerParser.playerParser())
.handler(context -> {
BukkitServerPlayer serverPlayer = plugin().adapt(context.get("player"));
if (serverPlayer == null) return;
serverPlayer.cooldown().clearCooldowns();
plugin().senderFactory().wrap(context.sender()).sendMessage(Component.text("Done clearing cooldowns!"));
});

View File

@@ -23,6 +23,7 @@ public class DebugFurnitureCommand extends BukkitCommandFeature<CommandSender> {
.senderType(Player.class)
.handler(context -> {
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(context.sender());
if (serverPlayer == null) return;
boolean b = !serverPlayer.enableFurnitureDebug();
serverPlayer.setEnableFurnitureDebug(b);
serverPlayer.sendMessage(Component.text("Furniture Debug Mode: ").append(Component.text(b ? "ON" : "OFF").color(b ? NamedTextColor.GREEN : NamedTextColor.RED)), false);

View File

@@ -24,6 +24,7 @@ public class ItemBrowserAdminCommand extends BukkitCommandFeature<CommandSender>
MultiplePlayerSelector selector = context.get("players");
for (Player player : selector.values()) {
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) return;
plugin().itemBrowserManager().open(serverPlayer);
}
});

View File

@@ -21,6 +21,7 @@ public class ItemBrowserPlayerCommand extends BukkitCommandFeature<CommandSender
.handler(context -> {
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) return;
plugin().itemBrowserManager().open(serverPlayer);
});
}

View File

@@ -46,6 +46,7 @@ public class SearchRecipeAdminCommand extends BukkitCommandFeature<CommandSender
NamespacedKey namespacedKey = context.get("id");
for (Player player : players) {
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) continue;
Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value());
List<Recipe<Object>> inRecipes = plugin().recipeManager().recipeByResult(itemId);
if (!inRecipes.isEmpty()) {

View File

@@ -30,6 +30,7 @@ public class SearchRecipePlayerCommand extends BukkitCommandFeature<CommandSende
.handler(context -> {
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) return;
Item<?> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (ItemUtils.isEmpty(item)) {
handleFeedback(context, MessageConstants.COMMAND_SEARCH_RECIPE_NO_ITEM);

View File

@@ -46,6 +46,7 @@ public class SearchUsageAdminCommand extends BukkitCommandFeature<CommandSender>
NamespacedKey namespacedKey = context.get("id");
for (Player player : players) {
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) continue;
Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value());
List<Recipe<Object>> inRecipes = plugin().recipeManager().recipeByIngredient(itemId);
if (!inRecipes.isEmpty()) {

View File

@@ -30,6 +30,7 @@ public class SearchUsagePlayerCommand extends BukkitCommandFeature<CommandSender
.handler(context -> {
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
if (serverPlayer == null) return;
Item<?> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (ItemUtils.isEmpty(item)) {
handleFeedback(context, MessageConstants.COMMAND_SEARCH_USAGE_NO_ITEM);

View File

@@ -30,6 +30,7 @@ public class SetDisplayEntityViewDistanceScaleCommand extends BukkitCommandFeatu
Player player = context.get("player");
double scale = context.get("scale");
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
serverPlayer.setDisplayEntityViewDistanceScale(scale);
handleFeedback(context, MessageConstants.COMMAND_DISPLAY_ENTITY_VIEW_DISTANCE_SCALE_SET_SUCCESS, Component.text(scale), Component.text(player.getName()));
});

View File

@@ -30,6 +30,7 @@ public class SetEntityCullingDistanceScaleCommand extends BukkitCommandFeature<C
Player player = context.get("player");
double scale = context.get("scale");
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
serverPlayer.setEntityCullingDistanceScale(scale);
handleFeedback(context, MessageConstants.COMMAND_ENTITY_CULLING_DISTANCE_SCALE_SET_SUCCESS, Component.text(scale), Component.text(player.getName()));
});

View File

@@ -49,6 +49,7 @@ public class SetLocaleCommand extends BukkitCommandFeature<CommandSender> {
return;
}
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
serverPlayer.setSelectedLocale(locale);
handleFeedback(context, MessageConstants.COMMAND_LOCALE_SET_SUCCESS, Component.text(TranslationManager.formatLocale(locale)), Component.text(player.getName()));
});

View File

@@ -37,6 +37,7 @@ public class ToggleEntityCullingCommand extends BukkitCommandFeature<CommandSend
}
Player player = context.get("player");
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
Optional<Boolean> state = context.optional("state");
boolean isEnabled = serverPlayer.enableEntityCulling();
if (state.isPresent()) {

View File

@@ -93,6 +93,7 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
Collection<Player> players = selector.values();
for (Player player : players) {
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) continue;
Item<ItemStack> item = customItem.buildItem(serverPlayer);
if (VersionHelper.isOrAbove1_21_2()) {
item.setJavaComponent(DataComponentTypes.DEATH_PROTECTION, Map.of());

View File

@@ -27,6 +27,7 @@ public class UnsetLocaleCommand extends BukkitCommandFeature<CommandSender> {
.handler(context -> {
Player player = context.get("player");
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (serverPlayer == null) return;
serverPlayer.setSelectedLocale(null);
handleFeedback(context, MessageConstants.COMMAND_LOCALE_UNSET_SUCCESS, Component.text(player.getName()));
});

View File

@@ -38,6 +38,7 @@ public final class PlayerUtils {
}
public static void giveItem(Player player, Item<ItemStack> original, Item<ItemStack> item) {
if (player == null) return;
Object serverPlayer = player.serverPlayer();
Object inventory = FastNMS.INSTANCE.method$Player$getInventory(serverPlayer);
boolean flag = FastNMS.INSTANCE.method$Inventory$add(inventory, item.getLiteralObject());