feat:上传mcguide-开发指南部份
67
mcguide/26-联机大厅/20-联机大厅调试与多人测试文档.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
front: https://mc.163.com/dev/mcmanual/mc-dev/assets/img/20_1.87b71158.png
|
||||
hard: 入门
|
||||
time: 15分钟
|
||||
selection: true
|
||||
---
|
||||
|
||||
# 联机大厅调试与多人测试文档
|
||||
|
||||
联机大厅作品在运行上使用 **远程主机** 托管游戏, **本地玩家** 加入线上的形式进行游戏。考虑到手机游玩与电脑开发上有可能存在实际差异,联机大厅地图作品在本地开发完成后,强烈建议开发者根据所发布的联机地图作品类型,分别在手机版自测开发包和电脑版客户端进行模拟联机大厅的线上自测。
|
||||
|
||||
**在本地测试时,日志窗口只会显示本地客户端的日志** ,这在联机大厅作品测试上是远远不够的。 使用多人上线测试不仅方便发现问题,还可以拉起服务端日志进行日志分析。
|
||||
|
||||
|
||||
|
||||
## 一、房主开启多人测试,建立房间
|
||||
进入 **《我的世界》开发工作台** ,点击 **【作品库】** - **【基岩版组件】** - **【联机地图】** ,点击上线测试以拉起服务端日志。
|
||||
|
||||

|
||||
|
||||
勾选 **【多人测试】** ,点击 **【创建房间】** ,耐心等待房间开启。
|
||||
|
||||
<img src="./images/20_1.png" alt="image-20220706213057813" style="zoom:150%;" />
|
||||
|
||||
房间开启后,可以在 **【房间管理】** 窗口找到服务器日志按钮,点击即可打开服务器日志。
|
||||
|
||||
<img src="./images/20_2.png" alt="未标题-1" style="zoom:150%;" />
|
||||
|
||||
服务器日志如下图。点击进入游戏后,会自动拉起脚本测试日志,两个日志窗口会同时存在,一个显示客户端日志,一个显示服务端日志。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 二、其他玩家加入游戏,进行多人联机测试
|
||||
房间开启完成后,同一个开发者账号下的子账号可以进入房间并进行联机测试,且可以同时允许PC和手机版自测包进入同一个房间,详情如下。
|
||||
|
||||
### 1. 手机版自测包进入多人测试
|
||||
打开手机版开发者自测包,进入联机大厅后使用 **【扫一扫】** 功能扫描服务器日志按钮旁的二维码,进入房间与开发成员进行联机。
|
||||
|
||||
有关手机版开发自测包的下载链接,可以访问[开发者平台网站](https://mcdev.webapp.163.com/#/square)后点击左上角的【手机版测试工具下载】进行下载。
|
||||
|
||||
<img src="./images/20_3.png" alt="未标题-1" style="zoom:150%;" />
|
||||
|
||||
### 2. 电脑版客户端进入多人测试
|
||||
|
||||
在其他电脑启动我的世界开发工作台并登录对应的测试子账号,进入点击 **【作品库】** - **【基岩版组件】** - **【联机测试】** 分页 ,此时可以看见当前主账号和子账号体系下开启的多人测试房间,根据房间号寻找对应测试房间并进入测试。
|
||||

|
||||
|
||||
## 商品购买测试
|
||||
> 当前仅支持在手机版开发自测包内进行商品购买测试,我的世界开发工作台暂不支持商品测试。
|
||||
|
||||
商品位于 **【资源中心联机大厅道具橱窗】** 时:
|
||||
|
||||
- 在联机大厅首页点击搜一搜,找到对应作品。
|
||||
- 点击热门道具,进入商品橱窗进行购买。
|
||||
|
||||

|
||||
|
||||
商品位于 **【游戏内道具橱窗可见】** 时:
|
||||
|
||||
- 点击游戏内左上角的商品按钮。
|
||||
- 在商品页面内进行选购。
|
||||
|
||||
<img src="./images/5_9.png" alt="POPO-screenshot-20220706-164918" style="zoom:41%;" />
|
||||
|
||||
有关联机大厅作品商品编辑与上架,[可查看此文档链接](./5-联机大厅作品与商品上传文档.html)。
|
||||
204
mcguide/26-联机大厅/5-联机大厅作品与商品上传文档.md
Normal file
@@ -0,0 +1,204 @@
|
||||
---
|
||||
front: https://mc.163.com/dev/mcmanual/mc-dev/assets/img/5_5.998edd66.png
|
||||
hard: 入门
|
||||
time: 15分钟
|
||||
selection: true
|
||||
---
|
||||
|
||||
# 联机大厅作品与商品上传文档
|
||||
|
||||
联机大厅作品通常包括一张具有良好联机体验的多人玩法地图,内置附加包或命令方块,并且搭配契合主题的建筑大观。
|
||||
|
||||
玩家可以在联机大厅创建对应作品的 **远程房间** ,这些房间将不会因为创建玩家的离开而被关闭,只要始终有玩家活动,房间就会一直存在。帮助房主玩家最大限度地减少数据带宽与设备负担。
|
||||
|
||||
开发者需在开发者平台上传联机大厅作品,并使用《我的世界》开发者工作台进行作品开发与多人自测。
|
||||
|
||||
|
||||
|
||||
## 联机大厅作品打包
|
||||
|
||||
当前联机大厅作品需要通过本地打包的方式上传至开发者平台,可携带附加包增强游戏体验。作品需要使用ZIP格式进行压缩,绝大部分的电脑系统和手机系统皆支持压缩此类格式。
|
||||
|
||||
打开目标地图作品文件夹,若地图内存在 **【netease_world_behavior_packs.json】** 和 **【netease_world_resource_packs.json】** ,需在文件名称开头去掉 **【netease_】** ,并按照下方规范进行更改:
|
||||
|
||||

|
||||
|
||||
**【world_behavior|resource_packs.json】** 文件内默认接受一个数组,数组内可以传入多个资源包或行为包清单文件信息,以帮助地图可以识别需要加载的包体。其中:
|
||||
|
||||
- pack_id:对应单个资源包或行为包 **【清单文件(manifest.json|pack_manifest.json)】** 下header键对的uuid值。
|
||||
- version:对应单个资源包或行为包 **【清单文件(manifest.json|pack_manifest.json)】** 下header键对的version值。
|
||||
- type:必填项,值为 **【"Addon"】** 。
|
||||
|
||||
```json
|
||||
// behavior_packs/some_behavior/manifest|pack_manifest.json
|
||||
{
|
||||
"format_version": 1,
|
||||
"modules": [
|
||||
{
|
||||
//....
|
||||
}
|
||||
],
|
||||
"header": {
|
||||
"description": "",
|
||||
"name": "behavior_pack",
|
||||
"uuid": "93c89241-3ecb-478f-a16c-c5eb99ceb580", // 对应world_behavior_packs.json的某对pack_id
|
||||
"version": [ 0, 0, 1]// 对应world_behavior_packs.json的某对version
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
// resource_packs/some_resource/manifest|pack_manifest.json
|
||||
{
|
||||
"format_version": 1,
|
||||
"modules": [
|
||||
{
|
||||
//....
|
||||
}
|
||||
],
|
||||
"header": {
|
||||
"description": "",
|
||||
"name": "resource_pack",
|
||||
"uuid": "614ba977-6b46-42da-afb6-50fa5a568ab6",// 对应world_resource_packs.json的某对pack_id
|
||||
"version": [ 0, 0, 1]// 对应world_resource_packs.json的某对version
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
// world_behavior_packs.json
|
||||
[
|
||||
|
||||
{
|
||||
"pack_id" : "93c89241-3ecb-478f-a16c-c5eb99ceb580",
|
||||
"type": "Addon",
|
||||
"version" : [ 0, 0, 1 ]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json
|
||||
// world_resource_packs.json
|
||||
[
|
||||
{
|
||||
"pack_id": "614ba977-6b46-42da-afb6-50fa5a568ab6",
|
||||
"type": "Addon",
|
||||
"version" : [ 0, 0, 1 ]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
并再次确认behavior_packs与resource_packs已携带相应的资源包和附加包。
|
||||
|
||||
<img src="./images/5_1.png" alt="image-20220705225623887" style="zoom:150%;" />
|
||||
|
||||

|
||||
|
||||
右键整个地图文件夹并压缩成zip格式,即可完成打包。地图文件夹即包括了整个地图文件内容的最上级文件夹,下列使用UploadMap名称指代最上级文件夹。
|
||||
|
||||
```yaml
|
||||
UploadMap:"最上级文件夹"
|
||||
内容:
|
||||
- "behavior_packs"
|
||||
- "db"
|
||||
- "resource_packs"
|
||||
- "level.dat"
|
||||
- "level.dat_old"
|
||||
- "levelname.txt"
|
||||
- "world_behavior_packs.json"
|
||||
- "world_resource_packs.json"
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 联机大厅作品上传
|
||||
|
||||
进入开发者平台,点击 **【作品管理】** - **【上架与资源管理】** ,选择发布一个新的 **【手机版】** 新资源。
|
||||
|
||||

|
||||
|
||||
填写联机大厅作品的基本信息,其中付费类型选择 **【multiplayer world】** 。
|
||||
|
||||

|
||||
|
||||
资源类型选择 **【联机大厅】** 。根据实际需要选择是否打开 **【商业化内购】** 功能。最后选填至多3个联机大厅专区分类并上传包体,提供辅助审核与玩家了解的作品简介和视频信息即可完成资源编辑操作。
|
||||
|
||||
**注意:开启【商业化内购功能】后将不支持同时上架地图至资源中心-地图分区。已上架联机大厅但未支持商业化内购功能的,同时未设置过同步上架至资源中心地图分区的作品,支持重新开启【商业化内购功能】。**
|
||||
|
||||
|
||||

|
||||
|
||||
> 1. 【是否支持反作弊】选项是指是否开启原生游戏自带的反作弊功能,会限制玩家的非常规行为,默认为不支持,即关闭反作弊选项;
|
||||
> 2. 若开启反作弊选项可能会导致玩家的镜头和动作出现抽搐和卡帧现象。
|
||||
> 3. 建议开发者根据作品是否包含强制修改玩家镜头、动作,以及游戏类型是否需要开启反作弊保证公平性两个方面来决定是否开启反作弊选项。
|
||||
|
||||
|
||||
|
||||
|
||||
## 联机大厅作品商品编辑
|
||||
|
||||
在 **【上架与资源管理】** 页选择 **【手机版平台】** - **【联机大厅商品】** ,可以对已保存的联机大厅作品进行商品创建、编辑与上架。
|
||||
|
||||

|
||||
|
||||
### 商品创建
|
||||
|
||||
点击 **【库存编辑】** ,再点击 **【添加商品】** 创建联机大厅内购商品。
|
||||
|
||||

|
||||
|
||||
填写商品的基本信息,其中:
|
||||
|
||||
- 商品简介:展示于商品
|
||||
- 商品定价:玩家购买需要消费的货币数额,支持钻石、绿宝石或免费定价。
|
||||
- 购买次数:玩家可购买内购商品的次数,若填写-1代表可无限次购买,其余购买次数请将数字设置大等于1。
|
||||
- 购买场景:需至少在 **【游戏内道具橱窗可见】** 和 **【资源中心联机大厅道具橱窗可见】** 选择一个购买入口,也可在两处同时展示。 **自测作品期间,商品可选择提审后在《我的世界》基岩版手机自测开发端相应的购买场景找到,方便开发者进行商品测试。**
|
||||
|
||||
| 展示类型 | 示例图片 |
|
||||
| -------------------------------- | ------------------------------------------------------------ |
|
||||
| 【游戏内道具橱窗可见】 | <img src="./images/5_9.png" alt="POPO-screenshot-20220706-164918" style="zoom:42%;" /> |
|
||||
| 【资源中心联机大厅道具橱窗可见】 |  |
|
||||
|
||||
- 商品分类:可自定义商品分类,需要选择其中一个分类。 **每个联机大厅作品自带一个商品分类,可自定义默认分类显示第一个分类名称,后续新的分类点击添加分类即可再次自定义新的名称和分类。**
|
||||
- 付费类型:默认选择 **【multiplayer world commodity】** 即可。
|
||||
- 付费备注:主要用于审核时进行信息备注。
|
||||
- 实现指令:使用<a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#QueryLobbyUserItem">QueryLobbyUserItem</a>获取玩家未发货的商品信息后,可在返回字典内获取到的cmdStr字段值。常用来判断发货的商品类型,或者搭配Python内置的Json模块为业务提供可被反序列化的结构,进而协助完成商品发放。
|
||||
|
||||

|
||||
|
||||
详情信息内的文字将显示在对应商品的详情信息区域内。进入购买场景,每个商品分类下会显示不同商品的商品封面,轮播图则只会在资资源中心联机大厅道具橱窗才会展示,具体位置可参考以下示例:
|
||||
|
||||

|
||||
|
||||
点击 **【保存】** 即可完成商品创建。
|
||||
|
||||
|
||||
|
||||
## 联机大厅作品商品自测
|
||||
|
||||
联机大厅作品商品支持在《我的世界》手机版自测开发包进行自测,开发者需要先在开发者平台上点击 **自测** ,方可在自测端内看到购买入口。
|
||||
|
||||

|
||||
|
||||
**注意:手机版自测开发包将不会显示设定的商品分类,开发者可以预先设置并在之后的线上版本查看正式效果。**
|
||||
|
||||
使用《我的世界》开发工作台联机大厅多人上线自测功能,可以在手机版开发者自测包进行商品购买,触发游戏内的发货逻辑,验证商业化功能的完整性。[详情可查看此文档链接。](./20-联机大厅调试与多人测试文档.html)
|
||||
|
||||
|
||||
|
||||
## 联机大厅作品商品上架
|
||||
|
||||
联机大厅作品商品过审后,开发者可以在 **【库存编辑】** 页下点击 **【更新到橱窗】** 将商品更新至 **【橱窗编辑】** 。
|
||||
|
||||

|
||||
|
||||
接着在 **【橱窗编辑】** 页中,开发者可以对商品进行展示排序的设定,接着选择点击 **【完整更新橱窗列表】** 在线上向玩家进行展示。
|
||||
|
||||

|
||||
|
||||
若商品需要下架,需要在对应商品行目上勾选左侧的确认框,点击下架按钮下架商品。
|
||||
|
||||
**注意:下架商品无需审核,后续商品可以在【库存编辑】页下重新更新到橱窗。下架后且未编辑过的商品可在下次更新时跳过审核,但已重新编辑过信息的商品则需要重新提审。**
|
||||
|
||||

|
||||
|
||||
247
mcguide/26-联机大厅/6-联机大厅商品2.0文档.md
Normal file
@@ -0,0 +1,247 @@
|
||||
---
|
||||
front: https://mc.163.com/dev/mcmanual/mc-dev/assets/img/1.385e53eb.png
|
||||
hard: 进阶
|
||||
time: 30分钟
|
||||
selection: true
|
||||
---
|
||||
|
||||
# 联机大厅商品2.0文档
|
||||
|
||||
**《我的世界》手机版联机大厅** 现已开放 **商业化** 与 **数据储存** 接口,打破开发者的创作边界,为联机游戏开发提供体验式购买、玩家数据持久化等全新条件。
|
||||
|
||||
|
||||
|
||||
## 数据储存说明
|
||||
|
||||
对比资源中心组件,联机大厅的数据储存接口支持上报游戏数据至云端数据库,支持跨存档及跨房间存取数据信息。每创建一个联机大厅作品,皆可在 **自测阶段** 和 **线上阶段** 对全局与单个玩家数据进行单独托管。
|
||||
|
||||
| 接口类型 | 服务范围 | 有效范围 | 数量 |
|
||||
| ---------------- | -------------------------- | -------------------------- | ---- |
|
||||
| 自定义数据储存 | 资源中心组件\|联机大厅玩法 | 单个游戏存档 | 1 |
|
||||
| 联机大厅数据储存 | 联机大厅玩法 | 同玩法内的全部联机大厅房间 | ∞+ |
|
||||
|
||||
|
||||
|
||||
使用联机大厅数据储存功能,开发者便可以根据规范的 **接口调用** 与 **数据结构格式** ,将游戏内的 **成长数值** 、 **货币金额** 、甚至 **背包信息** 等内容由玩家从一个房间带到另一个房间,与不同房间的玩家分享无限可能的乐趣。
|
||||
|
||||
| 常见的数据储存类型 | 应用方向 |
|
||||
| ------------------ | ------------------------------- |
|
||||
| 成长数值 | 经验\|等级\|签到天数\|RPG属性等 |
|
||||
| 回合结算 | 小游戏\|回合制等 |
|
||||
| 货币金额 | 装备交易\|购买商品等 |
|
||||
| 背包信息 | 玩家背包\|额外行囊等 |
|
||||
|
||||
|
||||
|
||||
## 商品化说明
|
||||
|
||||
商品化允许开发者创建体验式购买,即玩家凭意愿和对玩法的认可程度,在联机大厅房间里购买增值服务与物品,让每个开发者的热爱有所回响。
|
||||
|
||||
| 常见的商品类型 | 应用内容 |
|
||||
| -------------- | ------------------------- |
|
||||
| 特殊外观 | 人物、武器、装备、道具 |
|
||||
| 增值服务 | 喊话、称号、VIP权限、礼包 |
|
||||
| 游戏通行证 | 唯一次购买的限量道具 |
|
||||
|
||||
|
||||
|
||||
## MODSDK的API与事件
|
||||
|
||||
### API
|
||||
|
||||
- <a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#querylobbyuseritem">QueryLobbyUserItem</a>
|
||||
|
||||
查询还没发货的订单
|
||||
|
||||
- <a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbysetstorageanduseritem">LobbySetStorageAndUserItem</a>
|
||||
|
||||
设置订单已发货或者存数据
|
||||
|
||||
- <a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbygetstorage">LobbyGetStorage</a>
|
||||
|
||||
获取存储的数据
|
||||
|
||||
- <a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbygetstoragebysort">LobbyGetStorageBySort</a>
|
||||
|
||||
排序获取存储的数据,在开发者平台上配置的可排序的key才可以查询
|
||||
### 事件
|
||||
- <a href="../../mcdocs/1-ModAPI/事件/联机大厅.html#lobbygoodbuysucserverevent">lobbyGoodBuySucServerEvent</a>
|
||||
当玩家购买完商品,或者玩家登录进联机大厅mod时触发
|
||||
|
||||
|
||||
|
||||
## 示例mod
|
||||
|
||||
[lobbyGoodsMod2.0](../20-玩法开发/13-模组SDK编程/60-Demo示例.html)展示了一个基本玩法:
|
||||
|
||||
- 玩法内设计了“金币”的虚拟货币,使用key为money存储,并且设置为可排序的key。
|
||||
- 玩法上架了一个商品,玩家购买后可获得100金币,商品的实现指令为add_money_100
|
||||
- 玩家可以通过聊天栏输入buysword获得初始装备“钻石剑”的7天有效期,有效期内玩家每次进入新房间都会获得一把钻石剑。重复购买会叠加有效期。
|
||||
- 玩家可以在战斗中每击杀一个僵尸获得1个金币,获得的金币在战斗结束时统一结算。聊天栏输入endbattle触发战斗结算。
|
||||
- demo的主要流程如下,详情可阅读demo的代码注释
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Q&A
|
||||
|
||||
### 为什么会有数据冲突的情况?
|
||||
|
||||
根本原因是,可能会有多个联机大厅房间同时修改同一个玩家的数据,同一个房间的get与set操作之间,可能被插入了其他房间的set操作。
|
||||
|
||||
假设我们以这样的流程设置数据(注意这个流程是错的!):
|
||||
|
||||
1. 每个房间记录这一局战斗玩家获得的积分
|
||||
2. 战斗结束时统一结算,先获取玩家最新积分,然后加上本局积分set回去
|
||||
|
||||
就有可能出现这样的情况:
|
||||
|
||||
1. 某个玩家在云端的积分是100
|
||||
|
||||
2. 这个玩家进入了房间A,并且在这一局游戏内的积分是20
|
||||
|
||||

|
||||
|
||||
2. 然后这个玩家先阵亡了,于是退出了房间A(这时房间A的战斗还没结束,也还没有进行结算),进了另一个房间B,然后获得了10个积分
|
||||
|
||||

|
||||
|
||||
3. 然后房间A和房间B同时结算了:两个房间都去获取云端积分,获取到的都是100
|
||||
|
||||

|
||||
|
||||
4. 于是房间A会设置积分为120,房间B设置积分为110。无论设置的先后顺序如何,结果都是错的!正确的积分应该是130!
|
||||
|
||||

|
||||
|
||||
### 那应该怎么保证数据的正确性?
|
||||
|
||||
为了防止上面所说的这种情况,每次设置数据时都会附带一个“版本号”,每次设置数据的版本都是上一次获取到的版本加一,这样云端就可以根据版本号判断数据时候被别的容器修改过,也就是冲突。这个版本号控制已经由引擎内部控制好,不需要开发者操心,您只需要按api文档里的规范处理好冲突即可。
|
||||
|
||||
我们推荐的数据控制流程如下(以积分为例):
|
||||
|
||||
1. 每个房间维护两个容器,一个容器(mPoint)存放云端积分,另一个容器(mDeltaPoint)存放这个房间产生的积分的差异(例如+10分或者-10分)
|
||||
|
||||
2. 玩家登录时get数据,存放到mPoint。如果获取不到,则把默认积分(例如1000)放入mPoint
|
||||
|
||||
3. 结算,调用LobbySetStorageAndUserItem
|
||||
|
||||
4. 上传的积分为mPoint的积分加上mDeltaPoint的积分
|
||||
|
||||
```python
|
||||
def getter():
|
||||
return [
|
||||
{
|
||||
'key': 'point',
|
||||
'value': self.mPoint[playerId] + self.mDeltaPoint[playerId]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
5. 如果返回数据冲突,则用返回的最新积分更新mPoint
|
||||
|
||||
6. 然后引擎会自动重试第4步
|
||||
|
||||
下面解释一下为何这个流程可以避免数据覆盖:
|
||||
|
||||
1. 某个玩家在云端的积分是100
|
||||
|
||||
2. 这个玩家进入了房间A,房间获取到该玩家的云端积分是100(同时也会获取到对应的“版本号”),并且在这一局游戏内的积分是20
|
||||
|
||||

|
||||
|
||||
3. 然后这个玩家先阵亡了,于是退出了房间A(这时房间A的战斗还没结束,也还没有进行结算),进了另一个房间B。
|
||||
|
||||
房间获取到该玩家的云端积分是100(同时也会获取到对应的“版本号”),然后玩家在这一局游戏内的积分是10
|
||||
|
||||

|
||||
|
||||
4. 房间A和房间B同时结算:房间A想要设置积分为100+20,房间B想要设置积分为100+10。
|
||||
|
||||
假设房间A的请求先到达,这时云端积分成功设置为120(同时“版本号”+1)
|
||||
|
||||

|
||||
|
||||
5. 房间B的请求后到达,这时候云端发现版本号不一致!于是将最新的数据(120)返回给房间B。房间B收到后更新本地的mPoint
|
||||
|
||||

|
||||
|
||||
6. 房间B的引擎重新调用getter并提交数据,此次设置的积分为120+10,设置成功,最终数据正确。
|
||||
|
||||

|
||||
|
||||
### 为什么demo的lobbyGoodsServerSystem.py,_EndBattle函数中要求将callback,getter以及接口的调用封装到一个子函数内?
|
||||
|
||||
假设我们不封装,写成以下的样子:
|
||||
|
||||
```python
|
||||
def _EndBattle(self):
|
||||
for playerId in self.mBattleMoney.keys():
|
||||
def getter():
|
||||
return [
|
||||
{
|
||||
'key': 'money',
|
||||
'value': self.mMoney[playerId] + self.mBattleMoney[playerId]
|
||||
}
|
||||
]
|
||||
def callback(data):
|
||||
print playerId
|
||||
...
|
||||
httpComp.LobbySetStorageAndUserItem(callback, self.mUid[playerId], None, getter)
|
||||
```
|
||||
|
||||
因为LobbySetStorageAndUserItem的调用是异步的,getter与callback可能不会马上被调用。
|
||||
|
||||
当他们被调用时,这个for循环可能已经结束了,而此时playerId的值是mBattleMoney中的最后一个!
|
||||
|
||||
如果多一层函数调用,则不会出现这种情况,playerId的遍历不会影响到子函数的参数。
|
||||
|
||||
### 我的玩法不是按局计算,数据会实时更新,我应该如何减小set的频率?
|
||||
|
||||
1. 每隔一定时间(例如5分钟)更新数据到云端
|
||||
2. 玩家退出时更新数据到云端
|
||||
|
||||
set接口频率上限为50次/秒,5分钟的间隔可以保证5\*60\*50=15000名以内的玩家同时在线,以此类推
|
||||
|
||||
如果需要承载玩家数量的量级更高,则要舍弃定时上传,只在玩家退出时上传
|
||||
|
||||
### 我的玩法不是按局计算,数据会实时更新,我应该如何维护数据的正确性?
|
||||
|
||||
对于定时上传,可以参考以下写法:
|
||||
|
||||
```python
|
||||
def callback(data):
|
||||
if data:
|
||||
code = data['code']
|
||||
if code==0:
|
||||
# 设置成功
|
||||
newData = {i["key"]: i["value"] for i in data["entity"]["data"]}
|
||||
newPoint = newData.get('point', DEFAULT_POINT)
|
||||
# 给mDeltaPoint减去上传成功的差量(不能直接清零,因为在调用返回之前mDeltaPoint可能会被更新)
|
||||
self.mDeltaPoint[playerId] -= newPoint - self.mPoint[playerId]
|
||||
# 使用返回的新数据更新mPoint
|
||||
self.mPoint[playerId] = newPoint
|
||||
else if code==2:
|
||||
# 数据冲突,直接用返回的数据更新mPoint
|
||||
newData = {i["key"]: i["value"] for i in data["entity"]["data"]}
|
||||
self.mPoint[playerId] = newData.get('point', DEFAULT_POINT)
|
||||
|
||||
def getter():
|
||||
return [
|
||||
{
|
||||
'key': 'point',
|
||||
'value': self.mPoint[playerId] + self.mDeltaPoint[playerId]
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
257
mcguide/26-联机大厅/7-竞技模式组件文档.md
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
front: https://nie.res.netease.com/r/pic/20220408/06a1fb24-d76a-4d82-816c-96489966196c.png
|
||||
hard: 入门
|
||||
time: 15分钟
|
||||
---
|
||||
|
||||
# 竞技模式组件文档
|
||||
|
||||
竞技模式组件为MOD开发者提供统一的竞技模式开始与结算通知事件,通过调用相关API和监听固定事件,可以将必要的参数通过竞技组件通知webhttpserver进行分数结算。此外游戏过程中的逃跑惩罚也由竞技模式组件通知webhttpserver服务器。
|
||||
|
||||
## MOD客户端接入
|
||||
|
||||
### API
|
||||
- SetArenaGamePlayerReady
|
||||
|
||||
- 说明
|
||||
|
||||
设置当前玩家准备完毕时调用
|
||||
|
||||
- 参数
|
||||
|
||||
无参数
|
||||
|
||||
- 示例
|
||||
|
||||
```python
|
||||
import mod.client.extraClientApi as clientApi
|
||||
clientApi.SetArenaGamePlayerReady()
|
||||
```
|
||||
|
||||
- 备注
|
||||
|
||||
MOD开发者必须调用此函数
|
||||
|
||||
- CancelArenaGamePlayerReady
|
||||
|
||||
- 说明
|
||||
|
||||
设置玩家取消准备时调用
|
||||
|
||||
- 参数
|
||||
|
||||
无参数
|
||||
|
||||
- 示例
|
||||
|
||||
```python
|
||||
import mod.client.extraClientApi as clientApi
|
||||
clientApi.CancelArenaGamePlayerReady()
|
||||
```
|
||||
|
||||
- 备注
|
||||
|
||||
此接口为可选调用
|
||||
|
||||
### 事件
|
||||
- ClientArenaGameAllPlayerReadyEvent
|
||||
|
||||
- 说明
|
||||
当前游戏所有玩家准备完毕后,竞技组件向客户端发出的事件
|
||||
|
||||
- 参数
|
||||
|
||||
无参数
|
||||
|
||||
- 备注
|
||||
|
||||
MOD开发者可选择监听此事件切换游戏状态,也可以忽略由自定义的MOD服务端逻辑控制游戏状态切换
|
||||
|
||||
- ClientArenaGameFinishEvent
|
||||
|
||||
- 说明
|
||||
|
||||
MOD开发者调用结束API后,竞技组件向客户端发出的结束事件
|
||||
|
||||
- 参数
|
||||
|
||||
游戏结果
|
||||
|
||||
```python
|
||||
[
|
||||
{
|
||||
"camp_id": 1,
|
||||
"result": 1,
|
||||
"score": 100,
|
||||
"uid": [
|
||||
uid1
|
||||
]
|
||||
},
|
||||
{
|
||||
"camp_id": 2,
|
||||
"result": 2,
|
||||
"score": 50,
|
||||
"uid": [
|
||||
uid2
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
| 关键字 | 数据类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| camp_id | int | 阵营,不区分默认选0,区分最多三个阵营1,2,3 |
|
||||
| result | int | 比赛胜负:0:平局,1:胜利,2:失败 |
|
||||
| score | int | 分数,不需要时传null |
|
||||
| uid | list string array | 玩家id列表 |
|
||||
|
||||
- 备注
|
||||
|
||||
MOD开发者可选择监听此事件获取游戏结果,也可以由自定义事件从MOD服务端获取结果。在收到此事件后,5秒后竞技组件服务端会自动远程调用关闭当前游戏。
|
||||
|
||||
## MOD服务端接入
|
||||
|
||||
### API
|
||||
|
||||
- SetArenaGameResult
|
||||
|
||||
- 说明
|
||||
|
||||
当前游戏结束时调用,由开发者传入最后结果
|
||||
|
||||
- 参数
|
||||
|
||||
| 关键字 | 数据类型 | 说明 |
|
||||
| --- | --- | ---|
|
||||
| camp_id | int | 阵营,不区分默认选0,区分最多三个阵营1,2,3 |
|
||||
| result | int | 比赛胜负:0:平局,1:胜利,2:失败 |
|
||||
| score | int | 分数,不需要时传null |
|
||||
| uid | list string array | 玩家id列表 |
|
||||
|
||||
- 示例
|
||||
|
||||
```python
|
||||
resList = [
|
||||
{
|
||||
"camp_id": 1,
|
||||
"result": 1,
|
||||
"score": 100,
|
||||
"uid": [
|
||||
uid1
|
||||
]
|
||||
},
|
||||
{
|
||||
"camp_id": 2,
|
||||
"result": 2,
|
||||
"score": 50,
|
||||
"uid": [
|
||||
uid2
|
||||
]
|
||||
}
|
||||
]
|
||||
serverApi.SetArenaGameResult(resList)
|
||||
```
|
||||
|
||||
- 备注
|
||||
|
||||
- 分数设置相关:
|
||||
|
||||
- 如果指定自定义的分数,则每项都需要设置`score`的分数。
|
||||
- 如果使用排行系统默认设置的分数,则每项`score`的值需要设置为None。
|
||||
- 如果设置`result`为2时,即设置为输时,分时需要传递扣去分数`score`正数而不是负数
|
||||
- MOD开发者必须调用此函数,设置比赛结果。
|
||||
|
||||
### 事件
|
||||
|
||||
- ServerArenaGameAllPlayerReadyEvent
|
||||
|
||||
- 说明
|
||||
|
||||
当前游戏所有玩家准备完毕后,竞技组件向服务端发出的事件
|
||||
- 参数
|
||||
|
||||
无参数
|
||||
|
||||
- 备注
|
||||
|
||||
MOD开发者可选择监听此事件切换游戏状态,也可以忽略由自定义的MOD服务端逻辑控制游戏状态切换
|
||||
|
||||
- ServerArenaGamePlayerReconnectSuccessEvent
|
||||
|
||||
- 说明
|
||||
|
||||
玩家掉线后再次连入时,如果没有超时则触发该事件
|
||||
|
||||
- 参数
|
||||
|
||||
| 关键字 | 数据类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| playerId | str | player的entityId |
|
||||
| uid | str | 玩家的uid |
|
||||
|
||||
- 备注
|
||||
MOD开发者可选择监听此事件决定玩家重连状态。
|
||||
|
||||
- ServerArenaGamePlayerReconnectFailedEvent
|
||||
|
||||
- 说明
|
||||
|
||||
玩家掉线后再次连入时,超时则触发该事件
|
||||
|
||||
- 参数
|
||||
|
||||
| 关键字 | 数据类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| playerId | str | player的entityId |
|
||||
| uid | str | 玩家的uid |
|
||||
|
||||
- 备注
|
||||
|
||||
MOD开发者可选择监听此事件,玩家超时重连会被竞技组件发送消息强制退出该局游戏。
|
||||
|
||||
- ServerSetGameResultFailed
|
||||
|
||||
- 说明
|
||||
|
||||
开发者设置有结果失败时触发该事件
|
||||
|
||||
- 参数
|
||||
|
||||
| 关键字 | 数据类型 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| rcode | int | 错误码 |
|
||||
| msg | str | 错误信息 |
|
||||
| detail | str | 错误原因 |
|
||||
|
||||
- 备注
|
||||
|
||||
错误码含义和对应的详细信息如下:
|
||||
|
||||
> **4**:参数为空,缺少某个参数
|
||||
>
|
||||
> **12**:参数错误,具体见details
|
||||
> teams 必须为数组
|
||||
>
|
||||
> team 参数缺失
|
||||
>
|
||||
> result 超出范围 {发送的结果值} (0:平局,1:胜利,2:失败)
|
||||
>
|
||||
> camp_id 超出范围 camp_id:{发送的camp_id} camp_num:{阵营数} (阵营数为0,camp_id只能为0,阵营数大于0,为num,camp_id范围[1,num])
|
||||
>
|
||||
> uid 必须为数组
|
||||
>
|
||||
> uid 不是房间成员 room_id:{房间id} user_id:{玩家id}
|
||||
>
|
||||
> **13**:操作失败,具体见details
|
||||
>
|
||||
> 房间找不到 {房间id}
|
||||
>
|
||||
> 找不到房间成员 {房间id}
|
||||
>
|
||||
> 找不到组件信息 {组件id}
|
||||
>
|
||||
> 匹配状态错误 room_id:{房间id} user_id:{玩家id} state:{匹配状态} (防止重复结算)
|
||||
>
|
||||
> 结算失败
|
||||
>
|
||||
> **12028**:房间秘钥计算错误
|
||||
123
mcguide/26-联机大厅/8-联机大厅运营管理配置试运行文档.md
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
front: https://mc.163.com/dev/mcmanual/mc-dev/assets/img/8_1.4e8d31aa.jpg
|
||||
hard: 高级
|
||||
time: 20分钟
|
||||
---
|
||||
|
||||
# 联机大厅运营管理配置试运行文档
|
||||
|
||||
**《我的世界》** 持续致力于打造更完善的 **开发者内容生态** 。自 **模组SDK2.0** 开放联机大厅地图内购功能以来,官方收到了许多开发者对于全新 **开发赛道** 的热情建议。通过对大家需求的综合评估,现在可以通过开发者平台配置 **已上线** 联机大厅玩法的 **运营信息** 。
|
||||
|
||||
**注: 联机大厅运营管理配置正在试运行中,具体使用文档不代表功能最终的呈现效果。我们将持续收集广大开发者的建议和试用反馈,您可以通过开发者平台左上方的【开发者常见问题答疑】- 【反馈其他问题】与我们取得联系。**
|
||||
|
||||
|
||||
|
||||
## 运营信息说明
|
||||
|
||||
**模组SDK联机大厅模块** 将支持获取开发者在内容管理平台中的运营管理配置,实现不通过玩法包体更新就能够灵活管理的联机大厅活动、数值等操作,大大提升联机大厅组件的开发者运营能力。以下将用说明和示例为开发者讲解运营配置的作用和常见用例。
|
||||
|
||||
**注意:运营管理配置功能目前仅支持手机版联机大厅,电脑版本以及其他平台暂时不支持。**
|
||||
|
||||
### 作用
|
||||
|
||||
运营信息是与游戏玩家内直接互动的功能模块,它的主要作用就是为玩家服务,配置游戏内运营活动,通过公告、邮件、跑马灯等形式通知玩家即将更新的功能或优化内容。
|
||||
|
||||
### 常见用例
|
||||
|
||||
#### 邮件
|
||||
|
||||
邮件主要作用是奖励发放/内容通知,常在内容更新、BUG通知、活动奖励发放时使用。
|
||||
|
||||
#### 跑马灯
|
||||
|
||||
直接在游戏内显示,通常在临时维护/突发紧急情况下通过后台编辑内容发放告知玩家。
|
||||
|
||||
#### 游戏内公告
|
||||
|
||||
游戏内公告主要作用是通知玩家信息(更新信息、活动信息等),公告形式较为简单。
|
||||
|
||||
#### 问卷调查
|
||||
|
||||
一般在游戏新功能上线期间,通过后台配置想要问玩家的问题,了解各系统玩家在玩家看来的满意度,通过奖励激励玩家作答。
|
||||
|
||||
#### 名称自定义
|
||||
|
||||
常用在激励玩家通过充值消费一定金额给与冠名特权,为方便操作直接在后台实现修改玩家昵称前缀(prefix)和后缀(suffix)。
|
||||
|
||||
#### 运营活动配置
|
||||
|
||||
可在后台直接配置游戏内的周期性活动或节日运营活动。
|
||||
|
||||
|
||||
|
||||
## 运营管理配置操作流程
|
||||
|
||||
进入开发者平台,点击 **【作品管理】-【上架与资源管理】** ,在组件标签下选择手机版,找到已上线的联机大厅资源,点击右侧 **【···】** 选择 [**运营配置管理(试运行)**](#运营配置管理(试运行)) 或 [**【存储数据支持排序设置】**](#存储数据支持排序设置) 。
|
||||
|
||||
**注意:运营配置与存储数据排序设置无需审核,但官方会定期对数据信息进行审核,确保符合平台规范,保障官方、开发者与玩家的权益。**
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 运营配置管理(试运行)
|
||||
|
||||
运营管理配置试运行期间仅支持设置运营数据,提交的信息格式需为JSON。开发者可直接点击 **【JS校验与格式化】** 对数据格式进行规范。借由 **模组SDK** 接口获取数据信息,最终将结果通过开发者预设的代码逻辑反映到联机大厅房间内。
|
||||
|
||||
**注意:每次提交的JSON配置会顶替掉上一次的配置信息。请在本地保存好上一次提交的数据配置。**
|
||||
|
||||
平台同时支持设置【手机版测试工具自测环境】和【正式服环境】的运营数据,方便开发者在手机测试工具上校验数据正确性后,再提交至正式服环境。
|
||||
|
||||

|
||||
|
||||
请在提交配置时,务必填写配置说明理由。以便审核人员审核数据信息的安全性、合规性。
|
||||
|
||||
在对应的联机大厅玩法中,开发者可以使用<a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbygetstorage">LobbyGetStorage</a>接口,传入uid为0、key为带有op_config的列表参数,获取来自开发者平台的运营管理配置中配置的数据。
|
||||
|
||||
```python
|
||||
def callback(data):
|
||||
if data:
|
||||
# 在代码块下执行自己的业务逻辑
|
||||
print { i["key"]: i["value"] for i in data["entity"]["data"] }
|
||||
httpComp = compFactory.CreateHttp(serverApi.GetLevelId())
|
||||
# 返回来自开发者平台的运营管理配置中配置的数据。注意:每次在开发者平台提交的JSON配置数据会顶替掉上一次的配置信息。
|
||||
httpComp.LobbyGetStorage(callback, 0, ['op_config'])
|
||||
```
|
||||
|
||||
Callback需要接受一个参数。当请求失败时,参数返回None,当请求成功时,参数为一个Dict,格式如下。(获取的key如果没有设置过,就不会出现在返回的最新数据中)。
|
||||
|
||||
```json
|
||||
{
|
||||
"entity": {
|
||||
"data": [
|
||||
{
|
||||
"key": str, // 数据的key
|
||||
"value": int/float/str // 数据的值
|
||||
},
|
||||
{
|
||||
//...
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 存储数据支持排序设置
|
||||
|
||||
存储数据支持排序配置支持对联机大厅玩法云端数据进行升序或降序,实现类似游戏内排行榜展现的场景实现。根据对应玩家数据存储的 **数据键(key)** ,点击窗口内的 **【+添加key】** ,联机大厅玩法可以在每次房间启动后,借助官方封装的接口对数据进行及时排序,并完成对应的玩法逻辑。
|
||||
|
||||

|
||||
|
||||
平台同时支持设置【手机版测试工具自测环境】和【正式服环境】待排序的 **数据键(key)** ,方便开发者在手机测试工具上校验数据正确性后,再提交至正式服环境。
|
||||
|
||||
存储玩家数据使用到联机大厅模组开发接口<a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbysetstorageanduseritem">LobbySetStorageAndUserItem</a>,配合<a href="../../mcdocs/1-ModAPI/接口/联机大厅.html#lobbygetstoragebysort">LobbyGetStorageBySort</a>按照升序或降序获取数据。点击超链接可查看相应的接口文档。
|
||||
|
||||
**注意:待排序的数据键,对应的值必须为整数,取值范围在-2^63至2^63之间。**
|
||||
|
||||
|
||||
|
||||
## 示例Mod
|
||||
|
||||
详见[lobbyGoodsMod2.0](../20-玩法开发/13-模组SDK编程/60-Demo示例.html)。
|
||||
0
mcguide/26-联机大厅/README.md
Normal file
BIN
mcguide/26-联机大厅/images/20_0.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
mcguide/26-联机大厅/images/20_1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
mcguide/26-联机大厅/images/20_2.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
mcguide/26-联机大厅/images/20_3.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
mcguide/26-联机大厅/images/20_4.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
mcguide/26-联机大厅/images/20_5.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
mcguide/26-联机大厅/images/5_0.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
mcguide/26-联机大厅/images/5_1.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
mcguide/26-联机大厅/images/5_10.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
mcguide/26-联机大厅/images/5_11.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
mcguide/26-联机大厅/images/5_12.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
mcguide/26-联机大厅/images/5_13.jpg
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
mcguide/26-联机大厅/images/5_14.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
mcguide/26-联机大厅/images/5_15.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
mcguide/26-联机大厅/images/5_16.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
mcguide/26-联机大厅/images/5_2.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
mcguide/26-联机大厅/images/5_3.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
mcguide/26-联机大厅/images/5_4.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
mcguide/26-联机大厅/images/5_5.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
mcguide/26-联机大厅/images/5_6.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
mcguide/26-联机大厅/images/5_7.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
mcguide/26-联机大厅/images/5_8.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
mcguide/26-联机大厅/images/5_9.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
mcguide/26-联机大厅/images/8_1.jpg
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
mcguide/26-联机大厅/images/8_2.jpg
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
mcguide/26-联机大厅/images/8_3.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
mcguide/26-联机大厅/images/image-20220509174853688.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
mcguide/26-联机大厅/images/qaa0.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
mcguide/26-联机大厅/images/qaa1.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
mcguide/26-联机大厅/images/qaa2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
mcguide/26-联机大厅/images/qaa3.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
mcguide/26-联机大厅/images/qaa4.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
mcguide/26-联机大厅/images/qaa5.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
mcguide/26-联机大厅/images/qaa6.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
mcguide/26-联机大厅/images/qaa7.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
mcguide/26-联机大厅/images/qaa8.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
mcguide/26-联机大厅/picture/lobbyGoodsMod2.0/1.png
Normal file
|
After Width: | Height: | Size: 39 KiB |