mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-23 08:59:27 +00:00
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.BlockTags;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||||
@@ -13,47 +14,51 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.incendo.cloud.Command;
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.bukkit.data.BlockPredicate;
|
||||||
|
import org.incendo.cloud.bukkit.parser.BlockPredicateParser;
|
||||||
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
|
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
|
||||||
import org.incendo.cloud.context.CommandContext;
|
import org.incendo.cloud.context.CommandContext;
|
||||||
import org.incendo.cloud.context.CommandInput;
|
import org.incendo.cloud.context.CommandInput;
|
||||||
|
import org.incendo.cloud.parser.standard.BooleanParser;
|
||||||
import org.incendo.cloud.parser.standard.ByteParser;
|
import org.incendo.cloud.parser.standard.ByteParser;
|
||||||
import org.incendo.cloud.parser.standard.StringParser;
|
import org.incendo.cloud.parser.standard.StringParser;
|
||||||
import org.incendo.cloud.suggestion.Suggestion;
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||||
|
public static final Collection<Suggestion> TARGET_BLOCK_SUGGESTIONS = new HashSet<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (Material material : Material.values()) {
|
||||||
|
TARGET_BLOCK_SUGGESTIONS.add(Suggestion.suggestion(material.getKey().toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TestCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
public TestCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||||
super(commandManager, plugin);
|
super(commandManager, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||||
return builder
|
return builder
|
||||||
.senderType(Player.class)
|
.senderType(Player.class)
|
||||||
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
.required("reset", BooleanParser.booleanParser())
|
||||||
|
.required("setTag", NamespacedKeyParser.namespacedKeyParser())
|
||||||
|
.required("targetBlock", StringParser.stringComponent(StringParser.StringMode.GREEDY_FLAG_YIELDING).suggestionProvider(new SuggestionProvider<>() {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
|
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
|
||||||
return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions());
|
return CompletableFuture.completedFuture(TARGET_BLOCK_SUGGESTIONS);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.required("displayType", ByteParser.byteParser((byte) 0, (byte) 8))
|
|
||||||
.required("translation", StringParser.stringParser())
|
|
||||||
.required("rotation", StringParser.stringParser())
|
|
||||||
.handler(context -> {
|
.handler(context -> {
|
||||||
Player player = context.sender();
|
Player player = context.sender();
|
||||||
NamespacedKey namespacedKey = context.get("id");
|
player.sendMessage("开始测试");
|
||||||
ItemStack item = new ItemStack(Material.TRIDENT);
|
NamespacedKey key = context.get("setTag");
|
||||||
item.editMeta((meta) -> {
|
BlockTags.test(plugin().adapt(player), context.get("reset"), context.get("targetBlock"), key.asString());
|
||||||
Item<ItemStack> ceItem = BukkitItemManager.instance().createWrappedItem(Key.of(namespacedKey.asString()), null);
|
player.sendMessage("结束测试");
|
||||||
Optional<Integer> customModelData = ceItem.customModelData();
|
|
||||||
customModelData.ifPresent(meta::setCustomModelData);
|
|
||||||
});
|
|
||||||
player.getInventory().addItem(item);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1998,6 +1998,7 @@ public class PacketConsumers {
|
|||||||
EntityPacketHandler handler = user.entityPacketHandlers().get(id);
|
EntityPacketHandler handler = user.entityPacketHandlers().get(id);
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.handleSetEntityData(user, event);
|
handler.handleSetEntityData(user, event);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (Config.interceptEntityName()) {
|
if (Config.interceptEntityName()) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
package net.momirealms.craftengine.bukkit.util;
|
package net.momirealms.craftengine.bukkit.util;
|
||||||
|
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class BlockTags {
|
public class BlockTags {
|
||||||
private static final Map<Key, Object> CACHE = new HashMap<>();
|
private static final Map<Key, Object> CACHE = new HashMap<>();
|
||||||
@@ -24,4 +31,80 @@ public class BlockTags {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于测试下面的 buildFakeUpdateTagsPacket 方法
|
||||||
|
*
|
||||||
|
* @param player CraftEngine玩家对象
|
||||||
|
* @param reset 是否重置标签
|
||||||
|
* @param targetBlock 测试添加标签的目标方块
|
||||||
|
* @param setTag 测试添加的标签
|
||||||
|
*/
|
||||||
|
public static void test(Player player, boolean reset, String targetBlock, String setTag) {
|
||||||
|
Map<Object, Map<String, IntList>> addTags = new HashMap<>();
|
||||||
|
if (!reset) {
|
||||||
|
Object registries = Reflections.instance$BuiltInRegistries$BLOCK;
|
||||||
|
Object key = FastNMS.INSTANCE.method$Registry$key(registries);
|
||||||
|
Map<String, IntList> blockTags = new HashMap<>();
|
||||||
|
IntList blockId = new IntArrayList();
|
||||||
|
Object blockKey = KeyUtils.toResourceLocation(Key.of(targetBlock));
|
||||||
|
Object block = FastNMS.INSTANCE.method$Registry$get(registries, blockKey);
|
||||||
|
Optional<Integer> optionalBlockId = FastNMS.INSTANCE.method$BuiltInRegistries$getId(registries, block);
|
||||||
|
optionalBlockId.ifPresent(integer -> blockId.add(integer.intValue()));
|
||||||
|
blockTags.put(setTag, blockId);
|
||||||
|
addTags.put(key, blockTags);
|
||||||
|
}
|
||||||
|
Object packet = buildFakeUpdateTagsPacket(addTags);
|
||||||
|
player.sendPacket(packet, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建模拟标签更新数据包(用于向客户端添加虚拟标签)
|
||||||
|
*
|
||||||
|
* @param addTags 需要添加的标签数据,结构为嵌套映射:
|
||||||
|
* <pre>{@code
|
||||||
|
* Map结构示例:
|
||||||
|
* {
|
||||||
|
* 注册表键1 (如BuiltInRegistries.ITEM.key) -> {
|
||||||
|
* "命名空间:值1" -> IntList.of(1, 2, 3), // 该命名空间下生效的物品ID列表
|
||||||
|
* "命名空间:值2" -> IntList.of(5, 7)
|
||||||
|
* },
|
||||||
|
* 注册表键2 (如BuiltInRegistries.BLOCK.key) -> {
|
||||||
|
* "minecraft:beacon_base_blocks" -> IntList.of(1024, 2048)
|
||||||
|
* },
|
||||||
|
* ....
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
* 其中:</br>
|
||||||
|
* - 外层键:注册表对象(如物品/方块注册表)</br>
|
||||||
|
* - 中间层键:标签的命名空间:值(字符串)</br>
|
||||||
|
* - 值:包含注册表内项目数字ID的IntList
|
||||||
|
*
|
||||||
|
* @return 可发送给客户端的 ClientboundUpdateTagsPacket 数据包对象
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Object buildFakeUpdateTagsPacket(Map<Object, Map<String, IntList>> addTags) {
|
||||||
|
Map<Object, Object> registriesNetworkPayload = (Map<Object, Object>) FastNMS.INSTANCE.method$TagNetworkSerialization$serializeTagsToNetwork();
|
||||||
|
for (Map.Entry<Object, Map<String, IntList>> entry : addTags.entrySet()) {
|
||||||
|
Object registryKey = entry.getKey();
|
||||||
|
Map<String, IntList> tagsToAdd = entry.getValue();
|
||||||
|
Object existingPayload = registriesNetworkPayload.get(registryKey);
|
||||||
|
if (existingPayload == null) continue;
|
||||||
|
FriendlyByteBuf deserializeBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
|
FastNMS.INSTANCE.method$TagNetworkSerialization$NetworkPayload$write(existingPayload, deserializeBuf);
|
||||||
|
Map<String, IntList> combinedTags = deserializeBuf.readMap(
|
||||||
|
FriendlyByteBuf::readUtf,
|
||||||
|
FriendlyByteBuf::readIntIdList
|
||||||
|
);
|
||||||
|
combinedTags.putAll(tagsToAdd);
|
||||||
|
FriendlyByteBuf serializeBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
|
serializeBuf.writeMap(combinedTags,
|
||||||
|
FriendlyByteBuf::writeUtf,
|
||||||
|
FriendlyByteBuf::writeIntIdList
|
||||||
|
);
|
||||||
|
Object mergedPayload = FastNMS.INSTANCE.method$TagNetworkSerialization$NetworkPayload$read(serializeBuf);
|
||||||
|
registriesNetworkPayload.put(registryKey, mergedPayload);
|
||||||
|
}
|
||||||
|
return FastNMS.INSTANCE.constructor$ClientboundUpdateTagsPacket(registriesNetworkPayload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
|||||||
ahocorasick_version=0.6.3
|
ahocorasick_version=0.6.3
|
||||||
snake_yaml_version=2.4
|
snake_yaml_version=2.4
|
||||||
anti_grief_version=0.15
|
anti_grief_version=0.15
|
||||||
nms_helper_version=0.65.19
|
nms_helper_version=0.65.20
|
||||||
evalex_version=3.5.0
|
evalex_version=3.5.0
|
||||||
reactive_streams_version=1.0.4
|
reactive_streams_version=1.0.4
|
||||||
amazon_awssdk_version=2.31.23
|
amazon_awssdk_version=2.31.23
|
||||||
|
|||||||
Reference in New Issue
Block a user