Files
netease-bedrock-wiki/mcguide/27-手机网络游戏/课程12:使用Allay开服/3-NetAllay常用接口文档.md
daoge fb9586cf5d feat: 添加Allay相关教程 (#48)
* feat: 添加Allay相关教程

* feat: 添加 3-NetAllay常用接口文档.md

* docs: 更新NetAllay支持说明,添加常用接口文档链接
2026-03-25 15:13:35 +08:00

400 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
front:
hard: 进阶
time: 30分钟
---
# NetAllay常用接口文档
本文整理了`NetAllay`项目中最常用、最适合插件开发直接使用的接口方便您在Allay服务器中调用网易版独有能力例如PyRpc通信与商城能力。
如果您尚未安装NetAllay请先阅读[启用网易支持](1-启用网易支持.md)。
## 获取NetAllay实例
调用接口前,先拿到`NetAllay`插件实例:
```java
import org.allaymc.api.server.Server;
import org.allaymc.netallay.NetAllay;
// 方式一:直接获取静态实例
NetAllay netAllay = NetAllay.getInstance();
// 方式二:通过插件管理器获取
NetAllay netAllay = (NetAllay) Server.getInstance()
.getPluginManager()
.getPlugin("NetAllay");
```
## PyRpc事件监听
### 监听客户端发来的事件
最常用的入口是`listenForEvent`用于监听网易客户端发送到服务端的PyRpc事件。
```java
netAllay.listenForEvent(
"MyMod",
"MySystemCS",
"OnButtonClick",
(player, data) -> {
String buttonId = (String) data.get("buttonId");
plugin.getPluginLogger().info("玩家点击了按钮: {}", buttonId);
}
);
```
参数说明:
- `namespace`命名空间一般对应客户端Mod命名空间
- `systemName`:客户端系统名
- `eventName`:事件名
- `handler`:回调函数,参数为`Player``Map<String, Object>`
### 取消事件监听
如果您不再需要某个监听器,可以调用以下接口:
```java
boolean removed = netAllay.unlistenForEvent(namespace, systemName, eventName, handler);
netAllay.unlistenAllForEvent(namespace, systemName, eventName);
```
其中:
- `unlistenForEvent`:取消一个具体处理器
- `unlistenAllForEvent`:取消某个事件下的全部处理器
## 向客户端发送PyRpc事件
### 发送给单个玩家
```java
Map<String, Object> data = new LinkedHashMap<>();
data.put("message", "Hello from server!");
data.put("timestamp", System.currentTimeMillis());
boolean success = netAllay.notifyToClient(
player,
"MyMod",
"MySystemSS",
"ServerMessage",
data
);
```
该方法返回`boolean`,表示是否发送成功。若玩家不是网易客户端,则会返回`false`
### 立即发送
若您希望不经过缓冲立即下发,可以使用:
```java
boolean success = netAllay.notifyToClientImmediately(
player,
"MyMod",
"MySystemSS",
"ServerMessage",
data
);
```
### 发送给多个玩家
```java
int successCount = netAllay.notifyToMultiClients(
players,
"MyMod",
"MySystemSS",
"Announcement",
Map.of("content", "服务器公告")
);
```
返回值为成功发送的玩家数量。
### 发送给附近玩家
```java
var center = player.getControlledEntity().getLocation();
int count = netAllay.notifyToClientsNearby(
null,
center,
50.0,
"MyMod",
"MySystemSS",
"NearbyEvent",
Map.of("type", "explosion")
);
```
参数中的`except`可用于排除某个玩家;若不需要排除,传`null`即可。
### 广播到世界、维度或全服
广播接口统一为`broadcastToAllClient`,但有三个重载版本:
```java
// 广播到指定世界
int worldCount = netAllay.broadcastToAllClient(
null,
world,
"MyMod",
"MySystemSS",
"WorldEvent",
data
);
// 广播到指定维度
int dimensionCount = netAllay.broadcastToAllClient(
null,
dimension,
"MyMod",
"MySystemSS",
"DimensionEvent",
data
);
// 广播到整个服务器
int serverCount = netAllay.broadcastToAllClient(
null,
"MyMod",
"MySystemSS",
"GlobalEvent",
data
);
```
## 工具接口
### 判断玩家是否为网易客户端
```java
boolean netease = netAllay.isNetEasePlayer(player);
```
### 获取当前注册的事件数量
```java
int count = netAllay.getRegisteredEventCount();
```
## 特殊常量
### `LOCAL_PLAYER_ENTITY_ID`
```java
int entityId = NetAllay.LOCAL_PLAYER_ENTITY_ID; // -2
```
这个常量表示“接收消息的玩家自己”。常见用法是把实体ID传给客户端时使用`-2`代表当前玩家自身实体。
```java
netAllay.notifyToClient(
player,
"MyMod",
"MySystemSS",
"Welcome",
Map.of("entityId", NetAllay.LOCAL_PLAYER_ENTITY_ID)
);
```
注意:`-2`只能在单播接口`notifyToClient``notifyToClientImmediately`中使用,不要在多播或广播接口中使用。
## 事件数据支持的类型
`NetAllay`的事件数据类型为`Map<String, Object>`,其中值通常支持以下类型:
- `null`
- `Boolean`
- `Integer``Long`
- `Float``Double`
- `String`
- `byte[]`
- `Map<String, Object>`
- `List<?>``Iterable<?>`
一个常见示例:
```java
Map<String, Object> data = new LinkedHashMap<>();
data.put("title", "测试标题");
data.put("count", 1);
data.put("extra", Map.of("flag", true));
data.put("list", List.of("a", "b", "c"));
```
## 商城接口
`NetAllay`内置了商城管理器`ShopManager`,用于控制网易商城界面与监听商城事件。
### 获取商城管理器
```java
var shopManager = netAllay.getShopManager();
```
### 控制商城入口与界面
```java
// 是否启用自定义商城入口
netAllay.enableCustomShopEntry(true);
// 打开商城
netAllay.openShop(player);
// 关闭商城
netAllay.closeShop(player);
// 显示一行提示
netAllay.showHint(player, "购买成功");
// 显示两行提示
netAllay.showHint(player, "购买成功", "奖励已发放");
```
这些方法本质上是对`ShopManager`的便捷封装。
### 监听商城事件
商城常见事件定义在`ShopEvent`中:
- `ShopEvent.PLAYER_BUY_ITEM_SUCCESS`:玩家购买成功
- `ShopEvent.PLAYER_URGE_SHIP`:玩家催发货
- `ShopEvent.CLIENT_LOAD_ADDON_FINISH`客户端加载Addon完成
注册示例:
```java
shopManager.listenForShopEvent(ShopEvent.PLAYER_BUY_ITEM_SUCCESS, (player, data) -> {
plugin.getPluginLogger().info("玩家 {} 完成了一笔购买", player.getOriginName());
});
shopManager.listenForShopEvent(ShopEvent.PLAYER_URGE_SHIP, (player, data) -> {
plugin.getPluginLogger().info("玩家 {} 请求催发货", player.getOriginName());
});
```
取消监听:
```java
boolean removed = shopManager.unlistenForShopEvent(ShopEvent.PLAYER_BUY_ITEM_SUCCESS, handler);
```
### 按玩家覆盖商城配置
如果您希望不同玩家拿到不同的商城参数,可以为玩家设置单独配置:
```java
ShopManager.PlayerShopConfig config = new ShopManager.PlayerShopConfig();
config.setGameId("123456");
config.setUseCustomShop(true);
config.setTestServer(false);
config.setCacheTime(1);
config.setUid(0L);
config.setPlatformUid("");
shopManager.setPlayerConfig(player, config);
```
获取和移除配置:
```java
ShopManager.PlayerShopConfig config = shopManager.getPlayerConfig(player);
shopManager.removePlayerConfig(player);
```
## 配置文件
NetAllay会在插件目录生成`config.json`。当前源码中的默认配置如下:
```json
{
"shop": {
"gameId": "",
"gameKey": "",
"testGameKey": "",
"testServer": false,
"useCustomShop": false,
"cacheTime": 1,
"shopServerUrl": "",
"webServerUrl": ""
}
}
```
其中商城相关字段含义如下:
- `gameId`资源数字ID
- `gameKey`:正式服签名密钥
- `testGameKey`:测试服签名密钥
- `testServer`:是否使用测试服模式
- `useCustomShop`:是否隐藏默认商城按钮并改为自定义入口
- `cacheTime`:商城配置缓存时间,单位为秒
- `shopServerUrl`:自定义订单服务地址,可留空
- `webServerUrl`自定义Web服务地址可留空
如果您在运行中修改了配置,也可以调用以下接口:
```java
netAllay.reloadConfig();
netAllay.saveConfig();
```
## 完整示例
```java
import org.allaymc.api.player.Player;
import org.allaymc.netallay.NetAllay;
import org.allaymc.netallay.shop.ShopEvent;
import java.util.Map;
public final class DemoService {
public void register() {
NetAllay netAllay = NetAllay.getInstance();
netAllay.listenForEvent("MyMod", "MySystemCS", "RequestData", (player, data) -> {
netAllay.notifyToClient(
player,
"MyMod",
"MySystemSS",
"ResponseData",
Map.of(
"success", true,
"playerName", player.getOriginName()
)
);
});
netAllay.getShopManager().listenForShopEvent(ShopEvent.PLAYER_BUY_ITEM_SUCCESS, (player, data) -> {
netAllay.showHint(player, "购买成功", "请及时发货");
});
}
public void welcome(Player player) {
NetAllay.getInstance().notifyToClient(
player,
"MyMod",
"MySystemSS",
"Welcome",
Map.of(
"entityId", NetAllay.LOCAL_PLAYER_ENTITY_ID,
"message", "欢迎来到服务器"
)
);
}
}
```
## 注意事项
- `NetAllay`只会向网易客户端发送数据,非网易玩家会被自动跳过
- 广播、多播、附近广播时不要使用`NetAllay.LOCAL_PLAYER_ENTITY_ID`
- 插件禁用时,建议取消自己注册的事件监听
- 单次发送的数据不宜过大避免发送过大的PyRpc包