更新版本,修正sidebar层级问题,开辟原创WIki区
This commit is contained in:
@@ -1,12 +1,37 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import generateSidebar from '../../scripts/sidebar.js';
|
||||
import { withMermaid } from "vitepress-plugin-mermaid";
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
export default withMermaid({
|
||||
lang: 'zh-CN',
|
||||
title: "我的世界中国版 ModSDK",
|
||||
description: "ModSDK 开发者文档 镜像,但提供更优质的搜索",
|
||||
ignoreDeadLinks: true,
|
||||
locales: {
|
||||
root: {
|
||||
label: '简体中文',
|
||||
lang: 'zh-CN',
|
||||
themeConfig: {
|
||||
// 右侧导航栏的本地化文本
|
||||
outlineTitle: '本页目录',
|
||||
// 文档底部的本地化文本
|
||||
docFooter: {
|
||||
prev: '上一页',
|
||||
next: '下一页'
|
||||
},
|
||||
// 最后更新时间的本地化文本
|
||||
lastUpdatedText: '最后更新于',
|
||||
// 返回顶部按钮的本地化文本
|
||||
returnToTopLabel: '返回顶部',
|
||||
// 移动端菜单的本地化文本
|
||||
sidebarMenuLabel: '菜单',
|
||||
darkModeSwitchLabel: '主题',
|
||||
lightModeSwitchTitle: '切换到浅色模式',
|
||||
darkModeSwitchTitle: '切换到深色模式'
|
||||
}
|
||||
}
|
||||
},
|
||||
head: [
|
||||
['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-HPBDPVLP03' }],
|
||||
['script', {}, `
|
||||
@@ -20,9 +45,10 @@ export default defineConfig({
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
nav: [
|
||||
{ text: '首页', link: '/' },
|
||||
{ text: 'API文档', link: '/mcdocs' },
|
||||
{ text: '开发指南', link: '/mcguide' },
|
||||
{ text: '教学课程', link: '/mconline' },
|
||||
{ text: 'Wiki', link: '/wiki/0-欢迎' },
|
||||
{ text: 'API文档', link: '/mcdocs/0-欢迎' },
|
||||
{ text: '开发指南', link: '/mcguide/0-欢迎' },
|
||||
{ text: '教学课程', link: '/mconline/0-欢迎' },
|
||||
],
|
||||
|
||||
sidebar: await generateSidebar(),
|
||||
@@ -31,6 +57,11 @@ export default defineConfig({
|
||||
{ icon: 'github', link: 'https://github.com/EaseCation/netease-modsdk-wiki' }
|
||||
],
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/EaseCation/netease-modsdk-wiki/edit/main/docs/:path',
|
||||
text: '在 GitHub 上编辑此页'
|
||||
},
|
||||
|
||||
search: {
|
||||
provider: 'algolia',
|
||||
options: {
|
||||
@@ -40,6 +71,49 @@ export default defineConfig({
|
||||
searchParameters: {
|
||||
// 筛选掉 rootType 为 mconline 的项目
|
||||
facetFilters: ['rootType:-mconline']
|
||||
},
|
||||
locales: {
|
||||
root: {
|
||||
placeholder: '搜索文档',
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: '搜索文档',
|
||||
buttonAriaLabel: '搜索文档'
|
||||
},
|
||||
modal: {
|
||||
searchBox: {
|
||||
resetButtonTitle: '清除查询条件',
|
||||
resetButtonAriaLabel: '清除查询条件',
|
||||
cancelButtonText: '取消',
|
||||
cancelButtonAriaLabel: '取消'
|
||||
},
|
||||
startScreen: {
|
||||
recentSearchesTitle: '搜索历史',
|
||||
noRecentSearchesText: '没有搜索历史',
|
||||
saveRecentSearchButtonTitle: '保存至搜索历史',
|
||||
removeRecentSearchButtonTitle: '从搜索历史中移除',
|
||||
favoriteSearchesTitle: '收藏',
|
||||
removeFavoriteSearchButtonTitle: '从收藏中移除'
|
||||
},
|
||||
errorScreen: {
|
||||
titleText: '无法获取结果',
|
||||
helpText: '你可能需要检查你的网络连接'
|
||||
},
|
||||
footer: {
|
||||
selectText: '选择',
|
||||
navigateText: '切换',
|
||||
closeText: '关闭',
|
||||
searchByText: '搜索提供商'
|
||||
},
|
||||
noResultsScreen: {
|
||||
noResultsText: '无法找到相关结果',
|
||||
suggestedQueryText: '你可以尝试查询',
|
||||
reportMissingResultsText: '你认为该查询应该有结果?',
|
||||
reportMissingResultsLinkText: '点击反馈'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,24 +5,27 @@ layout: home
|
||||
hero:
|
||||
name: "我的世界中国版 ModSDK"
|
||||
text: ""
|
||||
tagline: "ModSDK 开发者文档 镜像,但提供更优质的搜索 🤩"
|
||||
tagline: "ModSDK 开发者文档镜像,但提供更优质的搜索引擎 🤩"
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 开始
|
||||
link: /mcdocs/0-概述/0-概述
|
||||
link: /wiki/0-欢迎
|
||||
|
||||
features:
|
||||
- icon: 🛠️
|
||||
title: API文档
|
||||
details: API是构建缤纷方块世界的基石,快来查查哪一个是你需要的。
|
||||
link: /mcdocs
|
||||
link: /mcdocs/0-欢迎
|
||||
- icon: 📙
|
||||
title: 开发指南
|
||||
details: 在开发指南中浏览每一个开发工具的使用说明,让它们更加得心应手。
|
||||
link: /mcguide
|
||||
link: /mcguide/0-欢迎
|
||||
- icon: 📝
|
||||
title: 教学课程
|
||||
details: 不断更新的系列课程,系统性地帮助您搭建开发知识体系。
|
||||
link: /mconline
|
||||
link: /mconline/0-欢迎
|
||||
---
|
||||
|
||||
<br>
|
||||
|
||||
> 如果需要查看官方文档,请访问 [我的世界开发者平台](https://mc.163.com/dev/)。
|
||||
45
docs/wiki/0-欢迎.md
Normal file
45
docs/wiki/0-欢迎.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
prev: false
|
||||
next: false
|
||||
---
|
||||
|
||||
# 欢迎来到 Wiki
|
||||
|
||||
由于中国版官网的教程写的太差了,因此我们计划使用简洁清晰的风格,重新编写基础入门教程,方便大家查询和学习哦!同时也期待大家共同贡献和维护本Wiki~
|
||||
|
||||
<MyFeatures :items="[
|
||||
{
|
||||
title: 'Mod脚本开发',
|
||||
desc: '🚀 快速入门我的世界 Mod 开发',
|
||||
link: '/wiki/1-Mod脚本开发/1-快速入门Mod开发'
|
||||
}
|
||||
]" />
|
||||
|
||||
::: tip <span style="font-size: 18px;">🥰 期待你的贡献</span>
|
||||
|
||||
1. Fork [本项目](https://github.com/EaseCation/netease-modsdk-wiki)
|
||||
2. 在 `docs/wiki` 目录下创建新的 Markdown 文件
|
||||
3. 编写你的教程内容
|
||||
4. 提交 PR
|
||||
|
||||
:::
|
||||
|
||||
## 阅读官方文档镜像
|
||||
|
||||
<MyFeatures :items="[
|
||||
{
|
||||
title: 'API文档',
|
||||
desc: '查看官方API文档',
|
||||
link: '/mcdocs/0-欢迎'
|
||||
},
|
||||
{
|
||||
title: '开发指南',
|
||||
desc: '查看官方开发指南',
|
||||
link: '/mcguide/0-欢迎'
|
||||
},
|
||||
{
|
||||
title: '教学课程',
|
||||
desc: '查看官方教学课程',
|
||||
link: '/mconline/0-欢迎'
|
||||
}
|
||||
]" />
|
||||
157
docs/wiki/1-Mod脚本开发/1-快速入门Mod开发.md
Normal file
157
docs/wiki/1-Mod脚本开发/1-快速入门Mod开发.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 🚀 快速入门我的世界 Mod 开发
|
||||
|
||||
::: warning :warning: 接下来需要 Python2 基础知识
|
||||
如果你不熟悉 Python 的这些概念(变量、函数、类等),可以先学习 [Python 官方教程](https://docs.python.org/zh-cn/3/tutorial/index.html)
|
||||
:::
|
||||
|
||||
## 1. 创建你的 Addons
|
||||
|
||||
::: details 什么是 Addons?
|
||||
Addons 是基岩版的玩法与内容扩展的载体,分为行为包(Behavior Pack)和资源包(Resource Pack)两部分。
|
||||
|
||||
在中国版的行为包中,我们可以使用 Python2 编写 Mod 脚本,实现自定义的复杂游戏逻辑。
|
||||
:::
|
||||
|
||||
我们一般推荐使用 MCStudio 来创建你的 Addons(Mod)
|
||||
|
||||
- 左侧切换到 `作品库` > `基岩版组件` 标签页
|
||||
- 顶部切换到 `附加包` 标签页
|
||||
- 点击右上角 `新建` 按钮,选择 `空白附加包` 或 `入门预设脚本模板`
|
||||
- 输入 作品名称、命名空间 等信息,点击 `启动编辑` 启动 MCStudio 编辑器(但是暂时没什么用),也可以点击 `仅新建` 来创建。
|
||||
|
||||
## 2. 创建基础 Mod 框架
|
||||
|
||||
Addons(Mod)创建完毕后,你可以在 MC Studio 中,找到你刚刚创建的 Addons,点击 `更多` > `打开目录`,即可在资源管理器中找到和打开 Addons 文件夹。
|
||||
|
||||
接着,你可以使用任何代码编辑器打开这个 Addons 文件夹。
|
||||
|
||||
> 可以使用 VS Code,也可以使用 PyCharm 等用于 Python 的 IDE(集成开发环境 的缩写)。
|
||||
|
||||
::: code-group
|
||||
``` [Addons目录结构]
|
||||
Addons # Addons 根目录
|
||||
├── resource_pack/ # 基岩版材质包(MCStudio创建时,会自动生成后缀,这是没问题的)
|
||||
│ ├── manifest.json # 材质包描述文件
|
||||
│ └── textures/ # 材质文件目录(目前用不到)
|
||||
│ ├── blocks/
|
||||
│ └── items/
|
||||
├── behavior_pack/ # 基岩版行为包(MCStudio创建时,会自动生成后缀,这是没问题的)
|
||||
│ ├── manifest.json # 行为包描述文件
|
||||
│ ├── myScript/ # Mod脚本目录(这个目录名字随便起!)
|
||||
│ │ ├── modMain.py
|
||||
│ │ ├── MyServerSystem.py # ServerSystem,你也可以随意放在任何子目录,但是需要在modMain.py中正确注册
|
||||
│ │ └── MyClientSystem.py # ClientSystem,你也可以随意放在任何子目录,但是需要在modMain.py中正确注册
|
||||
```
|
||||
:::
|
||||
|
||||
Mod(Python)逻辑位于 `行为包 (Behavior Pack,简称BP)` 中的 **脚本目录**,这里我们取名为 `myScript`,当然你想你可以随便取名。
|
||||
|
||||
::: code-group
|
||||
```python [BP/myScript/modMain.py]
|
||||
from mod.common.mod import Mod
|
||||
import mod.server.extraServerApi as serverApi
|
||||
import mod.client.extraClientApi as clientApi
|
||||
|
||||
# 通过Mod.Binding注明这个class是Mod的主入口。
|
||||
@Mod.Binding(name="MyFirstMod", version="1.0") # Mod名称(name)可以随便取,但是需要唯一且用于下方注册系统和后续注册事件监听。
|
||||
class MyFirstMod: # 这个类名可以随便取
|
||||
@Mod.InitServer()
|
||||
def serverInit(self): # 这个方法名可以随便取,因为已经通过@Mod.InitServer()注明是服务端的初始化方法
|
||||
serverApi.RegisterSystem("MyFirstMod", "MyServerSystem", "myScript.MyServerSystem.MyServerSystem")
|
||||
print("MyFirstMod 服务端已加载!") # print打印的内容将输出在MCStudio的 日志与调试工具 中
|
||||
|
||||
@Mod.InitClient()
|
||||
def clientInit(self): # 这个方法名可以随便取,因为已经通过@Mod.InitClient()注明是客户端的初始化方法
|
||||
clientApi.RegisterSystem("MyFirstMod", "MyClientSystem", "myScript.MyClientSystem.MyClientSystem")
|
||||
print("MyFirstMod 客户端已加载!") # print打印的内容将输出在MCStudio的 日志与调试工具 中
|
||||
```
|
||||
:::
|
||||
|
||||
::: code-group
|
||||
```python [BP/myScript/MyServerSystem.py]
|
||||
from server.extraServerApi import serverApi
|
||||
|
||||
ServerSystem = serverApi.GetServerSystemCls()
|
||||
|
||||
# 继承 ServerSystem 类,表示这是一个 服务端System
|
||||
class MyServerSystem(ServerSystem):
|
||||
|
||||
def __init__(self):
|
||||
super(MyServerSystem, self).__init__()
|
||||
print("MyServerSystem Hello World!") # print打印的内容将输出在MCStudio的 日志与调试工具 中
|
||||
```
|
||||
:::
|
||||
|
||||
::: code-group
|
||||
```python [BP/myScript/MyClientSystem.py]
|
||||
# 本教程中,我们还暂时用不到 ClientSystem,但是我们可以先创建好
|
||||
from client.extraClientApi import clientApi
|
||||
|
||||
ClientSystem = clientApi.GetClientSystemCls()
|
||||
|
||||
# 继承 ClientSystem 类,表示这是一个 客户端System
|
||||
class MyClientSystem(ClientSystem):
|
||||
|
||||
def __init__(self):
|
||||
super(MyClientSystem, self).__init__()
|
||||
print("MyClientSystem Hello World!")
|
||||
```
|
||||
:::
|
||||
|
||||
BOOM!就这么简单!
|
||||
|
||||
::: tip :bulb: 为什么需要这些System?
|
||||
不太理解为什么需要这些System?来阅读进一步的解释吧
|
||||
:::
|
||||
|
||||
## 3. 运行你的Mod
|
||||
|
||||
- 保存你的代码
|
||||
- 在 MCStudio 中找到此 Addons,鼠标划上去后点击 `开发测试` 按钮
|
||||
- 选择一个合适的游戏版本(一般为最新)
|
||||
- 填写相关测试名称和测试地图的配置,点击 `开始` 按钮
|
||||
- 等待游戏启动,你会在 **脚本与测试工具** 看到 `MyFirstMod 服务端已加载!` 和 `MyFirstMod 客户端已加载!` 的输出
|
||||
|
||||
::: details :thinking: 常见问题
|
||||
- 如果你没有看到期望的输出,可以在 **脚本与测试工具** 中查看日志,看看有没有报错
|
||||
- 如果没有任何报错,你需要检查你的 **脚本目录** 及以下的各级目录中,是否有`__init__.py`文件,如果没有,可以手动创建一个空文件
|
||||
- 再次检查后,可以尝试重启游戏(右侧 `测试存档记录`)
|
||||
:::
|
||||
|
||||
## 4. 实现简单功能
|
||||
|
||||
### 🧪 小功能:右键方块,获得钻石
|
||||
|
||||
::: code-group
|
||||
```python [BP/myScript/MyServerSystem.py]
|
||||
from server.extraServerApi import serverApi
|
||||
|
||||
ServerSystem = serverApi.GetServerSystemCls()
|
||||
|
||||
# 继承 ServerSystem 类,表示这是一个 服务端System
|
||||
class MyServerSystem(ServerSystem):
|
||||
def __init__(self):
|
||||
super(MyServerSystem, self).__init__()
|
||||
# 监听玩家使用方块事件
|
||||
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerBlockUseEvent", self, self.onBlockUse)
|
||||
|
||||
def onBlockUse(self, args):
|
||||
# 从事件的参数中,获得玩家ID
|
||||
playerId = args["playerId"]
|
||||
# 生成(获取)一个引擎的ItemComponent
|
||||
itemComp = serverApi.GetEngineCompFactory().CreateItem(playerId)
|
||||
# 向玩家背包中放入一个钻石
|
||||
itemComp.SpawnItemToPlayerInv({
|
||||
"itemName": "minecraft:diamond",
|
||||
"count": 1
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
::: tip 🔌 使用到的相关API
|
||||
- 接口:[ListenForEvent](/mcdocs/1-ModAPI/接口/通用/事件.html#listenforevent)
|
||||
- 事件:[ServerBlockUseEvent](/mcdocs/1-ModAPI/事件/方块.html#serverblockuseevent)
|
||||
- 接口:[SpawnItemToPlayerInv](/mcdocs/1-ModAPI/接口/玩家/背包.html#spawnitemtoplayerinv)
|
||||
:::
|
||||
|
||||
太棒了!赶快进入游戏,右键点击任意方块,你将获得一个钻石!
|
||||
179
docs/wiki/1-Mod脚本开发/2-为什么是System.md
Normal file
179
docs/wiki/1-Mod脚本开发/2-为什么是System.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# 深入理解 System 的概念
|
||||
|
||||
## 🧩 为什么需要两个系统(System)?用餐厅来理解!
|
||||
|
||||
想象一下游戏就像一家餐厅:
|
||||
- **服务器系统** = 厨房(决定食物实际内容)
|
||||
- **客户端系统** = 餐厅前厅(呈现给顾客看到的体验)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "游戏架构(像餐厅一样)"
|
||||
ServerSystem["服务器系统(厨房)"] -->|发送实际变化| ClientSystem["客户端系统(前厅)"]
|
||||
ClientSystem -->|发送玩家请求| ServerSystem
|
||||
end
|
||||
```
|
||||
|
||||
## 👨🍳 服务器系统:游戏的"厨房"
|
||||
|
||||
- **职责**: 决定游戏中真正发生了什么
|
||||
- **简单理解**:
|
||||
- 计算伤害(怪物真的死了吗?)
|
||||
- 决定方块是否被破坏
|
||||
- 控制物品掉落
|
||||
- 存储真实的游戏数据
|
||||
|
||||
## 👨💼 客户端系统:游戏的"前厅"
|
||||
|
||||
- **职责**: 让玩家看到并互动
|
||||
- **简单理解**:
|
||||
- 显示画面和声音
|
||||
- 处理你的鼠标点击和按键
|
||||
- 播放爆炸、火焰等特效
|
||||
- 展示菜单和界面
|
||||
|
||||
## 📮 系统间如何交流:像传纸条一样
|
||||
|
||||
当你在游戏中点击方块,发生了什么?
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 你
|
||||
participant 前厅 as 客户端
|
||||
participant 厨房 as 服务器
|
||||
|
||||
你->>前厅: 点击挖石头
|
||||
前厅->>厨房: 传纸条:"玩家想挖石头"
|
||||
厨房->>厨房: 检查:允许挖吗?
|
||||
厨房->>前厅: 回复:"可以,石头没了,掉落石头物品"
|
||||
前厅->>你: 播放挖矿动画和声音,显示物品
|
||||
```
|
||||
|
||||
## ⚠️ 为什么不能混在一起?
|
||||
|
||||
就像餐厅里顾客不能随便进厨房一样:
|
||||
|
||||
- ❌ 客户端不能直接修改游戏数据(否则会作弊)
|
||||
- ❌ 服务器不负责播放声音和动画(它只关心真实数据)
|
||||
|
||||
## 🌟 简单例子:击打树木得钻石
|
||||
|
||||
### 简化理解版
|
||||
1. **你点击树木**(客户端检测到)
|
||||
2. **客户端发消息**:"嘿,服务器,玩家点击了这棵树"
|
||||
3. **服务器决定**:"好,我给他一颗钻石"
|
||||
4. **服务器通知客户端**:"请在玩家背包里显示一颗新钻石"
|
||||
5. **客户端更新画面**:你看到钻石出现在背包里
|
||||
|
||||
## 🔑 记住这个简单规则
|
||||
|
||||
想象游戏是一部电影:
|
||||
- **服务器是导演**(决定故事情节)
|
||||
- **客户端是摄像机和屏幕**(展示给观众看)
|
||||
|
||||
记住:**服务器决定发生什么,客户端决定如何展示**!
|
||||
|
||||
## 💡 初学者提示
|
||||
|
||||
如果遇到问题,先问自己:
|
||||
- "这个功能应该由谁负责?是真实游戏规则还是显示效果?"
|
||||
- "我需要发送什么消息让另一边知道?"
|
||||
|
||||
学会这种思考方式,你的Mod就能正确运行啦!
|
||||
|
||||
|
||||
## :ribbon: 那么总结一下吧!
|
||||
|
||||
### 核心架构:客户端-服务器分离
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "游戏架构"
|
||||
ServerSystem["服务器系统(游戏逻辑)"] -->|发送状态更新| ClientSystem["客户端系统(视觉呈现)"]
|
||||
ClientSystem -->|发送玩家操作| ServerSystem
|
||||
|
||||
ServerSystem -->|读写| GameState["游戏状态(权威数据)"]
|
||||
ServerSystem -->|管理| Components["游戏组件"]
|
||||
ClientSystem -->|渲染| UI["界面与特效"]
|
||||
end
|
||||
```
|
||||
|
||||
### 双系统模型的必要性
|
||||
|
||||
#### 服务器系统 (ServerSystem)
|
||||
- **职责**: 维护游戏的"真实状态"
|
||||
- **具体功能**:
|
||||
- 处理游戏核心逻辑(如战斗计算、物品掉落)
|
||||
- 管理AI行为与路径寻找
|
||||
- 执行世界生成与物理规则
|
||||
- **拥有数据的最终决定权**
|
||||
|
||||
#### 客户端系统 (ClientSystem)
|
||||
- **职责**: 处理玩家的直接体验
|
||||
- **具体功能**:
|
||||
- 渲染游戏画面与UI界面
|
||||
- 处理玩家输入
|
||||
- 播放音效与粒子效果
|
||||
- 进行预测性渲染(平滑过渡)
|
||||
|
||||
### 系统间通信的关键:事件机制
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Player as 玩家
|
||||
participant Client as 客户端系统
|
||||
participant Server as 服务器系统
|
||||
|
||||
Player->>Client: 点击方块
|
||||
Client->>Server: 发送BlockUseEvent事件
|
||||
Server->>Server: 处理游戏逻辑
|
||||
Server->>Client: 发送状态更新事件
|
||||
Client->>Player: 显示视觉反馈
|
||||
```
|
||||
|
||||
#### 事件驱动设计的优势
|
||||
- **松耦合**: 系统间无需直接相互调用
|
||||
- **可扩展**: 多个系统可响应同一事件
|
||||
- **清晰职责**: 服务端决定结果,客户端呈现效果
|
||||
|
||||
#### 实例:击打方块流程
|
||||
1. **客户端**: 检测到玩家点击方块,发送`BlockUseEvent`
|
||||
2. **服务端**:
|
||||
- 接收到事件,判断方块是否可被破坏
|
||||
- 更新方块状态,计算掉落物
|
||||
3. **客户端**:
|
||||
- 播放方块破坏动画和音效
|
||||
- 显示掉落物
|
||||
|
||||
### 常见问题与最佳实践
|
||||
|
||||
#### 避免的错误模式
|
||||
- ❌ 在客户端直接修改游戏状态
|
||||
- ❌ 在服务端处理UI渲染逻辑
|
||||
- ❌ 遗漏事件监听导致功能不同步
|
||||
|
||||
#### 最佳实践
|
||||
- ✅ 服务端验证所有游戏逻辑(防作弊)
|
||||
- ✅ 合理使用自定义事件进行系统间通信
|
||||
- ✅ 保持客户端代码专注于视觉体验优化
|
||||
- ✅ 在事件参数中携带足够的上下文信息
|
||||
|
||||
### 跨系统通信示例
|
||||
|
||||
```python
|
||||
# 服务端发送自定义事件到客户端
|
||||
def spawn_special_effect(self, position):
|
||||
comp = serverApi.GetEngineCompFactory().CreateGame(serverApi.GetLevelId())
|
||||
comp.NotifyToClient(player_id, "ShowSpecialEffect", {"position": position})
|
||||
|
||||
# 客户端监听并处理
|
||||
def listen_events(self):
|
||||
self.ListenForEvent("MyMod", "MyServerSystem", "ShowSpecialEffect",
|
||||
self, self.on_special_effect)
|
||||
|
||||
def on_special_effect(self, event_data):
|
||||
pos = event_data["position"]
|
||||
# 在客户端显示特效...
|
||||
```
|
||||
|
||||
通过掌握客户端-服务端分离的设计模式,你将能够创建更稳定、可扩展且性能优秀的Mod。记住:**服务端决定发生什么,客户端决定如何展示**。
|
||||
2036
package-lock.json
generated
2036
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,10 @@
|
||||
"dotenv": "^16.4.7",
|
||||
"fast-glob": "^3.3.3",
|
||||
"gray-matter": "^4.0.3",
|
||||
"vitepress": "^1.6.3",
|
||||
"vue": "^3.5.13",
|
||||
"marked": "^15.0.7"
|
||||
"marked": "^15.0.7",
|
||||
"mermaid": "^11.5.0",
|
||||
"vitepress": "^2.0.0-alpha.4",
|
||||
"vitepress-plugin-mermaid": "^2.0.17",
|
||||
"vue": "^3.5.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ const DEFAULT_COLLAPSED = true; // 默认折叠状态
|
||||
|
||||
// 一级目录名称映射表
|
||||
const CATEGORY_MAP: Record<string, string> = {
|
||||
"wiki": "Wiki",
|
||||
'mcdocs': 'API文档',
|
||||
'mcguide': '开发指南',
|
||||
'mconline': '教学课程'
|
||||
@@ -115,7 +116,20 @@ async function generateSidebar(): Promise<Record<string, SidebarItem[]>> {
|
||||
sortSidebarItems(sidebar[key]);
|
||||
}
|
||||
|
||||
return sidebar;
|
||||
// 移除第一级,将每一个第一级中的items平铺到一级
|
||||
const sidebarFlat: Record<string, SidebarItem[]> = {};
|
||||
for (const key in sidebar) {
|
||||
sidebarFlat[key] = [];
|
||||
sidebar[key].forEach(item => {
|
||||
if (item.items) {
|
||||
sidebarFlat[key].push(...item.items);
|
||||
} else {
|
||||
sidebarFlat[key].push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return sidebarFlat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user