Files
netease-modsdk-wiki/docs/mcguide/27-网络游戏/课程8:使用Spigot开服/21-Spigot服与客户端python通信.md
2025-03-17 13:24:39 +08:00

6.7 KiB
Raw Blame History

Spigot服与客户端python通信

使用方法

  1. spigot服需要安装SpigotMaster插件插件api文档见SpigotMasterAPI文档

  2. 客户端到spigot

    • 在spigot使用spigotMaster.listenForEvent监听事件。

    • 在客户端使用NotifyToServer发送事件

  3. spigot到客户端

    • 在客户端使用ListenForEvent监听事件

    • 在spigot使用spigotMaster.notifyToClient或其他多播接口发送事件

示例:

  • spigot侧

    public void onEnable() {
    	SpigotMaster spigotMaster = (SpigotMaster) Bukkit.getPluginManager().getPlugin("SpigotMaster");
        if (spigotMaster != null){
            // 监听事件,然后原封不动发回去
            spigotMaster.listenForEvent("MyMod", "MySystemClient", "clientEvent", new PyRpcHandler() {
                @Override
                public void onEvent(Player player, Map<String, Object> map) {
                    spigotMaster.notifyToClient(player, "MyMod", "MySystemServer", "serverEvent", map);
                }
            });
        }
    }
    
  • python侧

    # modMain.py
    @Mod.InitClient()
    def InitClient(self):
        clientApi.RegisterSystem("MyMod", "MySystemClient", client_system_class_path)
    
    # clientSystem
    class MySystemClient(ClientSystem):
        def __init__(self, namespace, systemName):
            ClientSystem.__init__(self, namespace, systemName)
            # 注册事件,在回调函数中打印参数
            self.ListenForEvent("MyMod", "MySystemServer", "serverEvent", self, self.onEvent)
            # 给spigot发一个事件
            self.NotifyToServer("clientEvent", {'a': 1})
    
        def onEvent(self, data):
            # 可以在客户端日志中看到onEvent {"a": 1}
            print 'onEvent', data
    

事件支持的参数类型及映射关系

Java发送给Python

Java类型 Python类型
null None
boolean bool
int int
long long
BigInteger(2^63到2^64-1) long
float float
double float
String str
List<Object> list
Map<String, Object> dict

Python发送给Java

Python类型 Java类型
None null
bool Boolean
int/long-2^31到2^31-1 Integer
int/long-2^63到-2^31-12^31到2^63-1 Long
int/long2^63到2^64-1 BigInteger
float Double
str String
list List<Object>
dictkey必须为str Map<String, Object>

关于entityId的注意事项

  • 客户端侧的非玩家实体的entityId与spigot侧org.bukkit.entity.Entity.getEntityId()获取的实体id相同

  • 请注意spigot获取的实体id类型为int而客户端modsdk接口需要的实体id类型为str

  • 但客户端侧会存在一些负数的实体id会geyser做协议转换时生成的虚拟实体在spigot侧没有对应的实体

  • 每个客户端视角来看,本地玩家的entityId永远为-2其他玩家的entityId与spigot侧getEntityId相同也就是说

    • 客户端使用GetLocalPlayerId永远返回-2。如果将他发给spigot那spigot是不能直接根据这个id获取到玩家的需要做一些特殊处理

      spigotMaster.listenForEvent("MyMod", "MySystemClient", "clientEvent", new PyRpcHandler() {
          @Override
          public void onEvent(Player player, Map<String, Object> map) {
              Player eventPlayer;
              String entityId = (String) map.get("entityId");
              if (entityId.equals("-2")) {
                  eventPlayer = player;
              }
              else {
                  // 将entityId转成int然后去获取对应player
              }
              // 处理eventPlayer的逻辑
          }
      });
      
    • 如果在spigot侧使用getEntityId的返回值发给该玩家那玩家客户端无法根据这个id获取到本地玩家需要做一些特殊处理

      int entityId;
      if (sendPlayer == player) {
      	entityId = -2;
      }
      else {
      	entityId = player.getEntityId()
      }
      map.put("entityId", entityId)
      spigotMaster.notifyToClient(sendPlayer, "MyMod", "MySystemServer", "serverEvent", map);
      

DEMO详解

示例Demo中的PyRpcDemo包含了客户端mod及spigot插件。

进入游戏后会在右侧显示3个按钮

  • 点击“打开窗口”会弹出一个UI再点击“获取随机数”会从spigot获取一个0-9的随机数并显示在ui上。点击x关闭

  • 点击“绑定特效”会通知当前world内所有玩家给发起玩家替换模型并挂接一个特效

  • 点击”广播消息“会在spigot内所有玩家的聊天栏显示一条消息

客户端部分

  1. 在客户端初始化时注册UiInitFinished事件并在UiInitFinished事件中创建三个按钮的ui注册后续将要使用的弹出窗口ui

    注册两个自定义事件:

    • bindEffect给entityId参数对应实体更换模型以及创建特效
    • showMsg在本地显示聊天栏消息

image-20221011175949410

image-20221011181717291

  1. 在为三个按钮注册回调函数

    ”打开窗口“按钮抬起时弹出随机数的ui

    ”绑定特效“和”广播消息“按钮抬起时给spigot发送自定义消息

    image-20221011180653132

  2. 在随机数的ui创建时监听获取随机数的回调事件将参数中的值显示到label控件上

    注册按钮回调”获取随机数“按钮抬起时向spigot发送一个自定义消息关闭按钮抬起时弹出界面

    界面销毁时反监听获取随机数的回调事件

image-20221011180914374

spigot部分

  • 初始化时注册自定义事件,分别为:
    • requestRandom给玩家返回随机数获取回调
    • requestBindEffect给本人返回-2的entityId给world内其他人返回spigot的entityId
    • requestMsg给spigot内所有人返回消息

image-20221011181216699