本帖最后由 William_Shi 于 2021-8-6 15:53 编辑
测试代码如下(1.16.5 paper环境):
复制代码
大概效果是对穿上装备的实体附加一个发光效果。
测试效果图片见下:
经测试发现,实体生成时如果穿戴装备(盔.甲、弓)会发包
如果把装备扔给实体,实体穿上了也会触发
但是,当玩家自己穿上装备时没监听到这个包(创造、生存都没有)
现在可能的猜测是
我测试的时候只有一个玩家,这个包不会发给自己?
因为我尝试过发一个PacketPlayOutEntityEquipment给玩家,可以做到穿上假装备的效果,所以数据包本身应该是没问题的。
(这个数据包的结构也相当有意思,是一个单项 ArrayList,元素是 Pair<EnumItemSlot, ItemStack>
已解决。参见置顶回复。感谢大佬不吝赐教。
测试代码如下(1.16.5 paper环境):
- ProtocolManager manager = ProtocolLibrary.getProtocolManager();
- manager.addPacketListener(new PacketAdapter(
- PacketAdapter.params().plugin(Test.getProvidingPlugin(Test.class))
- .serverSide().
- gamePhase(GamePhase.PLAYING)
- .options(ListenerOptions.SKIP_PLUGIN_VERIFIER)
- .types(PacketType.Play.Server.ENTITY_EQUIPMENT)
- ) {
- @Override
- public void onPacketSending(PacketEvent packetEvent) {
- PacketContainer packet = packetEvent.getPacket();
- if (packetEvent.getPacketType() == PacketType.Play.Server.ENTITY_EQUIPMENT) {
- net.minecraft.server.v1_16_R3.WorldServer world =
- ((org.bukkit.craftbukkit.v1_16_R3.CraftWorld) packetEvent.getPlayer().getWorld()).getHandle();
- net.minecraft.server.v1_16_R3.Entity entity =
- world.getEntity(packet.getIntegers().getValues().get(0));
- if (entity.getBukkitEntity() instanceof LivingEntity) {
- ((LivingEntity) entity.getBukkitEntity()).addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 12000, 2));
- System.out.println(entity.getBukkitEntity());
- }
- }
- }
- @Override
- public void onPacketReceiving(PacketEvent packetEvent) {
- }
- });
大概效果是对穿上装备的实体附加一个发光效果。
测试效果图片见下:
经测试发现,实体生成时如果穿戴装备(盔.甲、弓)会发包
如果把装备扔给实体,实体穿上了也会触发
但是,当玩家自己穿上装备时没监听到这个包(创造、生存都没有)
现在可能的猜测是
我测试的时候只有一个玩家,这个包不会发给自己?
因为我尝试过发一个PacketPlayOutEntityEquipment给玩家,可以做到穿上假装备的效果,所以数据包本身应该是没问题的。
(这个数据包的结构也相当有意思,是一个单项 ArrayList,元素是 Pair<EnumItemSlot, ItemStack>
已解决。参见置顶回复。感谢大佬不吝赐教。
本帖最后由 Rothes 于 2021-8-6 01:56 编辑
玩家自己穿上装备用的可能是
WINDOW_CLICK(客户端发送给服务端 将物品放入某槽位, 可以是装备槽)
SET_SLOT(服务端发送给客户端 确认)
以及刷新库存的时候服务端发送给客户端的WINDOW_ITEMS 这里面包含所有的槽位,但是要先判断是不是玩家库存
玩家自己穿上装备用的可能是
WINDOW_CLICK(客户端发送给服务端 将物品放入某槽位, 可以是装备槽)
SET_SLOT(服务端发送给客户端 确认)
以及刷新库存的时候服务端发送给客户端的WINDOW_ITEMS 这里面包含所有的槽位,但是要先判断是不是玩家库存
Rothes 发表于 2021-8-6 01:54
玩家自己穿上装备用的可能是
WINDOW_CLICK(客户端发送给服务端 将物品放入某槽位, 可以是装备槽)
SET_SLOT( ...
但是这样的话还是有一个问题
比如说 ZombieEntity (以下均用mcp反混淆方便理解) 捡起物品的方法是MobEntity#pickUpItem
而玩家捡起物品则是在 ServerPlayNetHandler(craftbukkit反混淆的PlayerConnection)
其中发了三个包,两个SetSlot 和一个 HeldItemChange
而EntityEquipment包则是在
LivingEntity#tick中调用了detectEquipmentUpdates,detectEquipmentUpdates再调用handleEquipmentChanges
从而发送的
那么 玩家的物品更新就不会被检测到吗?还是玩家的tick方法有所不同?或者玩家没有记录上一个手持物品的字段?
William_Shi 发表于 2021-8-6 11:10
但是这样的话还是有一个问题
比如说 ZombieEntity (以下均用mcp反混淆方便理解) 捡起物品的方法是MobEnti ...
SET_SLOT是发给玩家自己的,只有自己接收,因为用SET_SLOT发送了槽位所以就不需要发送ENTITY_EQUIPMENT 也就监听不到,发送别的玩家的装备槽才用ENTITY_EQUIPMENT
本帖最后由 William_Shi 于 2021-8-6 15:53 编辑
两个玩家测试。结果见下。
参见置顶回复。
玩家穿戴装备、更改手中物品,服务端不会向这个玩家发送EntityEquipment包,但是会向其他玩家发送对应的EntityEquipment包更新装备。
再次感谢大佬。
两个玩家测试。结果见下。
参见置顶回复。
玩家穿戴装备、更改手中物品,服务端不会向这个玩家发送EntityEquipment包,但是会向其他玩家发送对应的EntityEquipment包更新装备。
再次感谢大佬。