我想实现让玩家右击一下任意方块(除了空气),就可以像用床一样睡觉,不是简单的躺下,而是让玩家进入睡眠状态(与床一样都得晚上),和床的功能一模一样,该怎么做?(判定右键点击没有问题,问题就是如何让玩家进入睡眠状态)
我之前去spigot或者bukkit的论坛里看到类似的问题,他们都说要用到数据包,然后我看到他们给出的代码都有用到PacketPlayOutBed这个类,但是我把他们给出的代码复制进去,运行的时候什么也没出现……
为什么要用到数据包呢?没有一个函数直接调用就让玩家睡觉?
我之前去spigot或者bukkit的论坛里看到类似的问题,他们都说要用到数据包,然后我看到他们给出的代码都有用到PacketPlayOutBed这个类,但是我把他们给出的代码复制进去,运行的时候什么也没出现……
为什么要用到数据包呢?没有一个函数直接调用就让玩家睡觉?
用ProtocolLib发数据包
Use Bed
This packet tells that a player goes to bed.
The client with the matching Entity ID will go into bed mode.
This Packet is sent to all nearby players including the one sent to bed.
Any packets sent with a location not currently occupied by a bed will be ignored by clients.
Packet ID State Bound To Field Name Field Type Notes
0x2F Play Client Entity ID VarInt Sleeping player's EID
Location Position Block location of the head part of the bed
转自wiki.vg
好了,构造包吧
This packet tells that a player goes to bed.
The client with the matching Entity ID will go into bed mode.
This Packet is sent to all nearby players including the one sent to bed.
Any packets sent with a location not currently occupied by a bed will be ignored by clients.
Packet ID State Bound To Field Name Field Type Notes
0x2F Play Client Entity ID VarInt Sleeping player's EID
Location Position Block location of the head part of the bed
转自wiki.vg
好了,构造包吧
DefineEvil 发表于 2017-6-21 21:44
Use Bed
This packet tells that a player goes to bed.
虽然说是找到用法了,但是按实例代码的步骤来弄,出现了Field index out of bounds. (Index: 1, Size: 1)的异常,而且把实例代码放进去测试一样出现这个异常。
我换了不同的protocollib版本,还是会抛出异常。
这是实例代码,原地址:https://gist.github.com/aadnk/8611384
第56,57,58行会抛出Field index out of bounds. (Index: 1, Size: 1)异常
我是在1.8.3spigot上测试的,protocol版本是3.6.4
复制代码
第56,57,58行会抛出Field index out of bounds. (Index: 1, Size: 1)异常
我是在1.8.3spigot上测试的,protocol版本是3.6.4
- package com.comphenix.example;
 
 
- import java.lang.reflect.InvocationTargetException;
 
- import java.util.Collections;
 
- import java.util.Set;
 
- import java.util.WeakHashMap;
 
 
- import org.bukkit.Location;
 
- import org.bukkit.command.Command;
 
- import org.bukkit.command.CommandSender;
 
- import org.bukkit.entity.Player;
 
- import org.bukkit.plugin.java.JavaPlugin;
 
 
- import com.comphenix.protocol.PacketType;
 
- import com.comphenix.protocol.ProtocolLibrary;
 
- import com.comphenix.protocol.ProtocolManager;
 
- import com.comphenix.protocol.events.PacketContainer;
 
 
- public class SleepingAnimation extends JavaPlugin {
 
-     private ProtocolManager manager;
 
-     
 
-     // Just a way to record if a player is asleep
 
-     private Set<Player> sleeping = Collections.newSetFromMap(new WeakHashMap<Player, Boolean>());
 
-     
 
-     @Override
 
-     public void onEnable() {
 
-         manager = ProtocolLibrary.getProtocolManager();
 
-     }
 
-     
 
-     @Override
 
-     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 
-         if (sender instanceof Player) {
 
-             Player player = (Player) sender;
 
-             
 
-             if (sleeping.add(player)) {
 
-                 playSleepAnimation(player);
 
-             } else {
 
-                 stopSleepAnimation(player);
 
-                 sleeping.remove(player);
 
-             }
 
-         }
 
-         return true;
 
-     }
 
-     
 
-     /**
 
-      * Play the sleep animation for every nearby player.
 
-      * @param alseep - the player asleep.
 
-      */
 
-     private void playSleepAnimation(Player asleep) {
 
-         final PacketContainer bedPacket = manager.createPacket(PacketType.Play.Server.BED, false);
 
-         final Location loc = asleep.getLocation();
 
-         
 
-         // http://wiki.vg/Protocol#Use_Bed
 
-         bedPacket.getEntityModifier(asleep.getWorld()).
 
-             write(0, asleep);
 
-         bedPacket.getIntegers().
 
-             write(1, loc.getBlockX()).
 
-             write(2, loc.getBlockY() + 1).
 
-             write(3, loc.getBlockZ());
 
-         
 
-         broadcastNearby(asleep, bedPacket);
 
-     }
 
-     
 
-     private void stopSleepAnimation(Player sleeping) {
 
-         final PacketContainer animation = manager.createPacket(PacketType.Play.Server.ANIMATION, false);
 
-         
 
-         // http://wiki.vg/Protocol#Animation
 
-         animation.getEntityModifier(sleeping.getWorld()).
 
-             write(0, sleeping);
 
-         animation.getIntegers().
 
-             write(1, 2);
 
-         
 
-         broadcastNearby(sleeping, animation);
 
-     }
 
 
-     private void broadcastNearby(Player asleep, PacketContainer bedPacket) {
 
-         for (Player observer : manager.getEntityTrackers(asleep)) {
 
-             try {
 
-                 manager.sendServerPacket(observer, bedPacket);
 
-             } catch (InvocationTargetException e) {
 
-                 throw new RuntimeException("Cannot send packet.", e);
 
-             }
 
-         }
 
-     }
 
- }