mirror of
https://github.com/BeamMP/Docs.git
synced 2026-07-22 14:50:55 +00:00
More work!!!
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
::: warning "这个网站正在建设中!"
|
||||
|
||||
```
|
||||
这个网站正在积极建设中。
|
||||
|
||||
觉得你能帮上忙吗?请用铅笔在右侧点击页面!
|
||||
|
||||
这也可以在任何页面上完成。
|
||||
```
|
||||
|
||||
# 模组/游戏内脚本参考
|
||||
|
||||
BeamMP允许您创建自己的客户端插件。我们提供了一些功能,你可以用它来与其他多人模式和其他玩家通过服务器进行通信。
|
||||
|
||||
# 函数列表
|
||||
|
||||
脚本可用函数列表:
|
||||
|
||||
函数 | 说明
|
||||
--- | ---
|
||||
`TriggerServerEvent("eventName", "data")` | 在服务器lua环境中触发事件,两个参数都是字符串。
|
||||
`TriggerClientEvent("eventName", "data")` | 在本地lua环境中触发事件,两个参数都是字符串。有利于插件之间的通信。
|
||||
`AddEventHandler("eventName", Function)` | 当`eventName`被接收时(本地或从服务器),`function`将获得1个参数,一个包含事件数据的字符串。
|
||||
|
||||
# 代码片段
|
||||
|
||||
例如,使用包含的`ChatMessageIncluded`事件解析聊天,如下所示:
|
||||
|
||||
```lua
|
||||
local function chatReceived(msg) -- Receive event with parameters
|
||||
print("chat received: "..msg)
|
||||
local i = string.find(s, ":") -- Find where our first ':' is, used to separate the sender and message
|
||||
if i == nil then
|
||||
print("error parsing message: separator could not be found!")
|
||||
return -- Could not find separator, cancel function
|
||||
end
|
||||
print("index of separator: "..tostring(i))
|
||||
local sender = string.sub(msg, 1, i-1) -- Substring our input to separate its 2 parts
|
||||
local message = string.sub(msg, i+1, -1) -- Do whatever you want to with the message
|
||||
print("sender: " .. sender)
|
||||
print("message: ".. message)
|
||||
end
|
||||
|
||||
AddEventHandler("ChatMessageReceived", chatReceived) -- Add our event handler to the list managed by BeamMP
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
::: warning "这个网站正在建设中!"
|
||||
|
||||
```
|
||||
这个网站正在积极建设中。
|
||||
|
||||
觉得你能帮上忙吗?请用铅笔在右侧点击页面!
|
||||
|
||||
这也可以在任何页面上完成。
|
||||
```
|
||||
|
||||
# 模组/游戏内脚本参考
|
||||
|
||||
BeamMP允许您创建自己的客户端插件。我们提供了一些功能,你可以用它来与其他多人模式和其他玩家通过服务器进行通信。
|
||||
|
||||
# 函数列表
|
||||
|
||||
脚本可用函数列表:
|
||||
|
||||
函数 | 说明
|
||||
--- | ---
|
||||
`TriggerServerEvent("eventName", "data")` | 在服务器lua环境中触发事件,两个参数都是字符串。
|
||||
`TriggerClientEvent("eventName", "data")` | 在本地lua环境中触发事件,两个参数都是字符串。有利于插件之间的通信。
|
||||
`AddEventHandler("eventName", Function)` | 当`eventName`被接收时(本地或从服务器),`function`将获得1个参数,一个包含事件数据的字符串。
|
||||
|
||||
# 代码片段
|
||||
|
||||
例如,使用包含的`ChatMessageIncluded`事件解析聊天,如下所示:
|
||||
|
||||
```lua
|
||||
local function chatReceived(msg) -- Receive event with parameters
|
||||
print("chat received: "..msg)
|
||||
local i = string.find(s, ":") -- Find where our first ':' is, used to separate the sender and message
|
||||
if i == nil then
|
||||
print("error parsing message: separator could not be found!")
|
||||
return -- Could not find separator, cancel function
|
||||
end
|
||||
print("index of separator: "..tostring(i))
|
||||
local sender = string.sub(msg, 1, i-1) -- Substring our input to separate its 2 parts
|
||||
local message = string.sub(msg, i+1, -1) -- Do whatever you want to with the message
|
||||
print("sender: " .. sender)
|
||||
print("message: ".. message)
|
||||
end
|
||||
|
||||
AddEventHandler("ChatMessageReceived", chatReceived) -- Add our event handler to the list managed by BeamMP
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,385 @@
|
||||
::: warning "这个网站正在建设中!"
|
||||
|
||||
```
|
||||
这个网站正在积极建设中。
|
||||
|
||||
觉得你能帮上忙吗?请用铅笔在右侧点击页面!
|
||||
|
||||
这也可以在任何页面上完成。
|
||||
```
|
||||
|
||||
# 服务器脚本参考
|
||||
|
||||
## 服务器端版本 2.X
|
||||
|
||||
::: warning
|
||||
|
||||
```
|
||||
BeamMP 服务器版本 2.X 已不再提供支持。
|
||||
本文档仅供参考。
|
||||
请更新到最新版本以进行维护和支持。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> 这是 2.x 的脚本,仅当你的服务器端版本是老的/过时的(version 2.x.x), 时才能使用此方法,有关最新文档,请参见 [这里](https://docs.beammp.com/scripting/server/latest-server-reference)。 {.is-warning}
|
||||
|
||||
### 说明
|
||||
|
||||
要在服务器控制台中获得函数的输出,必须将其包装在`print()`语句中。例如:`print(GetPlayerName(0))`将返回服务器上第一个玩家的名字。
|
||||
|
||||
`<PlayersServerID>` 从0开始。
|
||||
|
||||
### 用于编写脚本的可用函数列表
|
||||
|
||||
#### GetPlayerName(playersServerID)
|
||||
|
||||
以字符串形式返回玩家的Discord名称
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerID)
|
||||
local name = GetPlayerName(playerID)
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
|
||||
#### GetPlayerDiscordID(playersServerID)
|
||||
|
||||
以字符串形式返回玩家的Discord名称
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerID)
|
||||
local name = GetPlayerDiscordID(playerID)
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
|
||||
#### GetPlayerHWID(playersServerID)
|
||||
|
||||
以字符串形式返回玩家的Discord ID
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerID)
|
||||
local name = GetPlayerHWID(playerID)
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
|
||||
#### GetPlayerVehicles(playersServerID)
|
||||
|
||||
返回玩家的车辆作为一个对象/数组
|
||||
|
||||
```lua
|
||||
function onChatMessage(playerID, senderName, message)
|
||||
local vehicleList = GetPlayerVehicles(playerID)
|
||||
for vehicleID, vehicleData in pairs(vehicleList) do
|
||||
-- Do something
|
||||
-- Could also be used to check how many vehicles a player have
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### DropPlayer(playersServerID)
|
||||
|
||||
断开特定玩家的连接。“其实就是踢出玩家”
|
||||
|
||||
```lua
|
||||
function onVehicleSpawn(playerID, vehicleID, vehicleData)
|
||||
-- Do something
|
||||
DropPlayer(playerID)
|
||||
end
|
||||
```
|
||||
|
||||
#### SendChatMessage(playersServerID, message)
|
||||
|
||||
通过网络向指定的用户发送消息。每个人都用-1
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerID)
|
||||
SendChatMessage(-1, "Someone just joined!")
|
||||
end
|
||||
```
|
||||
|
||||
#### CancelEvent() -- DEPRECIATED
|
||||
|
||||
取消事件的发生。这可能很快就会发生。使用`return 1`来取消事件。
|
||||
|
||||
#### onInit()
|
||||
|
||||
如果在lua文件中声明,它将在c++成功加载当前lua文件后被调用
|
||||
|
||||
```lua
|
||||
function onInit()
|
||||
print("Server ready")
|
||||
end
|
||||
```
|
||||
|
||||
#### exit()
|
||||
|
||||
将关闭服务器
|
||||
|
||||
```lua
|
||||
function onInit()
|
||||
print("Server Ready. But who needs a server which is running")
|
||||
exit() -- Stops the server
|
||||
end
|
||||
```
|
||||
|
||||
#### CreateThread(functionName, callInterval)
|
||||
|
||||
将在专用线程上执行该函数,它将每秒运行callInterval数次。它每秒钟都会跑一次。
|
||||
|
||||
```lua
|
||||
function yourFunction()
|
||||
for i = 1,10 do
|
||||
SendChatMessage(-1, "Countdown: "..i)
|
||||
Sleep(1000)
|
||||
end
|
||||
end
|
||||
CreateThread("yourFunction", 30)
|
||||
```
|
||||
|
||||
已弃用示例:将在专用线程上执行该函数
|
||||
|
||||
```lua
|
||||
function yourFunction()
|
||||
for i = 1,10 do
|
||||
SendChatMessage(-1, "Countdown: "..i)
|
||||
Sleep(1000)
|
||||
end
|
||||
end
|
||||
CreateThread("yourFunction", 30)
|
||||
```
|
||||
|
||||
#### StopThread(functionName)
|
||||
|
||||
将停止尝试调用当前脚本的线程函数
|
||||
|
||||
```lua
|
||||
function yourFunction()
|
||||
delayExpired = false
|
||||
Sleep(10000)
|
||||
delayExpired = true
|
||||
end
|
||||
CreateThread("yourFunction", 30)
|
||||
-- Do something
|
||||
if not delayExpired then
|
||||
StopThread("yourFunction")
|
||||
else
|
||||
-- Do something
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
#### Sleep(millisecs) - DEPRECIATED
|
||||
|
||||
将暂停执行指定的时间(警告,如果没有创建线程,将暂停整个服务器)
|
||||
|
||||
```lua
|
||||
function countdown()
|
||||
for i = 1,10 do
|
||||
SendChatMessage(-1, "Countdown: "..i)
|
||||
Sleep(1000)
|
||||
end
|
||||
end
|
||||
CreateThread("countdown", 10)
|
||||
```
|
||||
|
||||
#### GetPlayerCount()
|
||||
|
||||
将返回多少玩家连接
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerID)
|
||||
SendChatMessage(playerID, "You are the "..GetPlayerCount().."th player!"
|
||||
end
|
||||
```
|
||||
|
||||
#### RemoveVehicle(playerServerID, VehicleID)
|
||||
|
||||
这会导致一辆载具消失。
|
||||
|
||||
```lua
|
||||
function onVehicleSpawn(playerID, vehicleID, vehicleData)
|
||||
if --[[ Vehicle data equal something it shouldn't be ]] then
|
||||
RemoveVehicle(playerID, vehicleIID)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### GetPlayers()
|
||||
|
||||
将返回一个带有name的id表
|
||||
|
||||
```lua
|
||||
local function onPlayerJoin(joinedPlayerID)
|
||||
local players = GetPlayers()
|
||||
for playerID, playerName in pairs(players) do
|
||||
if playerID == joinedPlayerID then
|
||||
-- Do something
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### RegisterEvent(eventName, functionName)
|
||||
|
||||
将该函数注册到指定的事件,都必须是字符串。
|
||||
|
||||
```lua
|
||||
function anyEvent()
|
||||
-- Do something
|
||||
end
|
||||
RegisterEvent("onAnyEventHappen", "anyEvent")
|
||||
-- Do something
|
||||
TriggerLocalEvent("onAnyEventHappen")
|
||||
```
|
||||
|
||||
#### TriggerLocalEvent(eventName)
|
||||
|
||||
将调用同一插件文件夹中的每个注册函数。
|
||||
|
||||
```lua
|
||||
function anyEvent()
|
||||
-- Do something
|
||||
end
|
||||
RegisterEvent("onAnyEventHappen", "anyEvent")
|
||||
-- Do something
|
||||
TriggerLocalEvent("onAnyEventHappen")
|
||||
```
|
||||
|
||||
#### TriggerGlobalEvent(eventName)
|
||||
|
||||
将使用此事件名称调用每个已注册的函数。
|
||||
|
||||
```lua
|
||||
-- File A
|
||||
function anyEvent()
|
||||
-- Do something
|
||||
end
|
||||
RegisterEvent("onAnyEventHappen", "anyEvent")
|
||||
```
|
||||
|
||||
```lua
|
||||
-- File B
|
||||
TriggerGlobalEvent("onAnyEventHappen")
|
||||
```
|
||||
|
||||
#### TriggerClientEvent(playerServerID, eventName, data)
|
||||
|
||||
将使用给定的数据在指定的客户端(-1 表示广播)上触发该事件。
|
||||
|
||||
```lua
|
||||
function onPlayerJoin(playerServerID)
|
||||
TriggerClientEvent(playerServerID, "anyEvent", "You just joined the server")
|
||||
end
|
||||
RegisterEvent("onAnyEventHappen", "anyEvent")
|
||||
```
|
||||
|
||||
#### Set(configID, newValue)
|
||||
|
||||
会将配置设置修改为下方表格中指定的新值。
|
||||
|
||||
```lua
|
||||
function onChatMessage(playerID, senderName, message)
|
||||
if playerID == adminPlayer then
|
||||
if message == --[[ anything ]] then
|
||||
Set(3, 10)
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### 可用于 `Set()` 命令的配置项列表
|
||||
|
||||
> Note that these will not save to the config file.
|
||||
|
||||
Config ID | 名称 | 只接受以下内容
|
||||
--- | --- | ---
|
||||
`0` | 调试设置 | true 或 false
|
||||
`1` | 私人设置 | true 或 false
|
||||
`2` | 每个玩家的最大车辆数 | 数字
|
||||
`3` | 最大玩家数 | 数字
|
||||
`4` | 地图 | 字符串
|
||||
`5` | 名称 | 字符串
|
||||
`6` | 描述 | 字符串
|
||||
任何其他ID都会导致控制台警告 | |
|
||||
|
||||
### 用于编写脚本的可用事件列表
|
||||
|
||||
#### 默认事件
|
||||
|
||||
如何使用事件的示例:
|
||||
|
||||
```lua
|
||||
function onInit()
|
||||
RegisterEvent("onPlayerJoin", "onPlayerJoin")
|
||||
end
|
||||
|
||||
function onPlayerJoin(playerServerID)
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
|
||||
如果你不希望访客进入你的服务器:
|
||||
|
||||
```lua
|
||||
function onInit()
|
||||
print("noGuests Ready")
|
||||
RegisterEvent("onPlayerAuth","onPlayerAuth")
|
||||
end
|
||||
|
||||
function onPlayerAuth(name, role, isGuest)
|
||||
if isGuest then
|
||||
return "You must be signed in to join this server!"
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
事件 | 参数 | 描述
|
||||
--- | --- | ---
|
||||
`onPlayerAuth` | 玩家的名称、论坛角色、是否为访客账号(布尔值) | 有一名玩家已通过验证并正在请求加入。
|
||||
`onPlayerConnecting` | 玩家的ID | 玩家正在加载(在加载地图之前)
|
||||
`onPlayerJoining` | 玩家的ID | 玩家正在加载地图,很快就会加入
|
||||
`onPlayerJoin` | 玩家的ID | 玩家已加入并加载
|
||||
`onPlayerDisconnect` | 玩家的ID | 玩家退出了游戏
|
||||
`onChatMessage` | 发消息的玩家的ID、昵称和聊天消息 | 发送了一条聊天消息。这对于创建命令系统非常有用
|
||||
`onVehicleSpawn` | 玩家ID,车辆ID和车辆数据 | 当有人刷出一辆车时输出
|
||||
`onVehicleEdited` | 玩家ID,车辆ID和车辆数据 | 当有人编辑车辆或替换现有车辆时,就会调用此操作
|
||||
`onVehicleDeleted` | 玩家的ID和车辆ID | 当某人删除自己拥有的车辆时,就会调用此操作
|
||||
|
||||
#### 自定义事件
|
||||
|
||||
可以创建自定义事件以供自己使用。这与默认值的处理方式非常相似。
|
||||
|
||||
如何使用自定义事件的范例:
|
||||
|
||||
```lua
|
||||
function onInit()
|
||||
RegisterEvent("myCustomEvent", "myCustomEvent")
|
||||
end
|
||||
|
||||
function myCustomEvent(playerServerID, customData)
|
||||
-- Do something
|
||||
end
|
||||
```
|
||||
|
||||
接着可以使用各自的函数从客户端或服务器端调用该函数。
|
||||
|
||||
### 玩家
|
||||
|
||||
当玩家连接到你的服务器时,他们会被分配一个从 0 开始递增的 serverID。<br>serverID 会被重复利用;如果玩家离开后再次加入,他们不会获得新的 serverID,而是会被分配一个当前可用的 serverID。<br>当服务器重新启动时,serverID 会被重置。
|
||||
|
||||
#### 静态标识符
|
||||
|
||||
BeamMP 中的玩家拥有 3 个可通过其 serverID 获取的静态标识符,分别是他们的名称、discordID,以及硬件ID(HWID)。<br>(尽管最后一个尚未实现,但在此处我们将假设它已实现。)<br>这三种 ID 类型各自具有不同的来源,以及在玩家识别用途上的优点和缺点。
|
||||
|
||||
ID 类型 | 优点 | 缺点 | 获取的函数
|
||||
--- | --- | --- | :-:
|
||||
name | 容易获得,直截了当 | 不安全 | GetPlayerName()
|
||||
discordID | 非常安全 | 不方便 | GetPlayerDiscordID()
|
||||
HWID | 超级安全 | 难获得 | GetPlayerHWID()
|
||||
|
||||
### 车辆
|
||||
|
||||
BeamMP 中的车辆有 3 个服务器会关注的属性:车辆所属者的 serverID、车辆的 vehicleID 以及车辆的数据。<br>所属者的 serverID 很简单,它就是玩家的 serverID。每辆车也有一个 vehicleID,但 vehicleID 并不是车辆唯一的;来自不同玩家的两辆车可能拥有相同的 vehicleID。<br>与 serverID 不同,vehicleID 会被重复使用。例如,如果我有 4 辆车,它们的 ID 分别是 0、1、2 和 3。如果我删除 vehicleID 为 2 的车辆,我就只剩下 0、1 和 3。当我生成一辆新车时,这辆新车会占用 ID 2。<br>最后,车辆的第三个属性是 data。data 包含车辆名称、部件以及其他数据,顾名思义。data 是以原始 JSON 字符串存储的,因此你需要使用 JSON 库来解析它,或者你也可以手动逐步解析字符串,提取所需的信息。
|
||||
@@ -0,0 +1,75 @@
|
||||
# 开始
|
||||
|
||||
为了开始开发BeamMP,你至少需要:
|
||||
|
||||
- 安装在本地的BeamNG.drive
|
||||
- 安装在本地的BeamMP; 至少是启动器,另外还有服务器
|
||||
- 安装在本地的Git, 和一个 GitHub.com 账号
|
||||
- 一个代码编辑器, 例如VSCode或notepad++
|
||||
|
||||
---
|
||||
|
||||
# 模组,启动器和服务器之间的区别
|
||||
|
||||
BeamMP分为三个主要部分:
|
||||
|
||||
- 该模组与游戏中的其他载具模组或界面模组相同,均通过BeamNG引擎加载运行。其核心功能包括与启动器建立本地通信链路,以及渲染多人联机界面组件。技术架构方面,主体逻辑采用Lua脚本语言实现,界面层则基于JavaScript、HTML与CSS的复合式开发框架进行构建。相关代码仓库详见[https://github.com/BeamMP/BeamMP](https://github.com/BeamMP/BeamMP)。
|
||||
- 本启动器核心功能集包括:与模组维持持续通信、在需要时建立目标服务器连接,以及通过BeamMP后端系统执行用户登录认证流程。该程序基于C++语言开发,部署前已由BeamMP团队完成预编译处理,完整源代码参见[https://github.com/BeamMP/BeamMP-Launcher](https://github.com/BeamMP/BeamMP-Launcher)。
|
||||
- 服务端核心功能涵盖:与多个启动器实例建立通信链路、向BeamMP后端系统发送"心跳"信号同步IP/端口/版本/玩家数量等运行参数,并管理与调度服务端Lua插件运行。底层架构基于C++语言实现,已由BeamMP针对多操作系统平台及CPU指令集进行预编译生成,完整源码仓库位于[https://github.com/BeamMP/BeamMP-Server](https://github.com/BeamMP/BeamMP-Server)。
|
||||
|
||||
---
|
||||
|
||||
# 配置适用于模组开发的运行环境
|
||||
|
||||
## 为BeamNG使用未打包文件
|
||||
|
||||
为实现BeamNG模组开发的高效迭代,建议开发者采用`非打包目录`的实时更新工作流模式,避免每次代码变更后执行重复的压缩打包操作。
|
||||
|
||||
请通过文件管理器访问BeamNG用户目录:`%appdata%/Local/BeamNG.drive/0.xx/mods`,其中`xx`对应当前最新的BeamNG版本号。在`mods`目录内创建名为`unpacked`的专用开发文件夹。
|
||||
|
||||
有关用户目录的技术规范细则,请参阅BeamNG官方文档中心:[https://documentation.beamng.com/support/userfolder/](https://documentation.beamng.com/support/userfolder/)
|
||||
|
||||
## 在BeamMP启动器中启用开发模式
|
||||
|
||||
为防止自动更新机制覆盖本地Git仓库副本,请通过添加运行参数`--no-download`强制停用该功能;若需同时禁止启动器自动运行BeamNG主程序,并获取实时调试日志,推荐配置方案为附加开发调试参数`--dev`。
|
||||
|
||||
命令行参数 | 说明
|
||||
:-- | :--
|
||||
`--help` or `-h` | 该指令将输出下列标准化参数清单
|
||||
`--port <port>` or `-p` | 请将服务端默认监听端口修改为`<port>`,该项变更需同时在游戏客户端内进行同步配置。
|
||||
`--verbose` or `-v` | 详细日志模式,输出调试级系统信息
|
||||
`--no-download` | 强制禁用BeamMP Lua模组自动部署流程
|
||||
`--no-update` | 激活维护模式锁定更新通道(需采用手动升级方式)
|
||||
`--no-launch` | 强制解耦启动器与游戏进程链路(需进行独立启动流程)
|
||||
`--dev` | 开发者模式,与 --verbose --no-download --no-launch --no-update相同
|
||||
`--game <args...>` or `-- <args...>` | 实现运行参数向游戏进程的透传桥接
|
||||
|
||||
## 执行仓库克隆操作至目标解压目录
|
||||
|
||||
虽然您可手动从GitHub仓库(a0)https://github.com/BeamMP/BeamMP复制BeamMP模组文件,但强烈建议使用Git版本控制系统进行规范操作。请首先执行分叉(fork)操作。
|
||||
|
||||
最有效的方式是直接将存储库克隆到`unpacked`文件夹中。
|
||||
|
||||
在`git`环境配置下,请遵循以下部署流程:<br>从`解压根目录`启动PowerShell/CMD终端<br>执行克隆操作:`git clone https://github.com/yourName/BeamMP`
|
||||
|
||||
现在试试开发模式吧。启动BeamMP启动器,手动启动BeamNG,一旦进入游戏,确保BeamMP是唯一有效的模组。你应该能够像往常一样使用BeamMP。
|
||||
|
||||
使用代码编辑器,您现在可以直接在`unpacked`文件夹中添加或更改代码。然后你可以通过按`Ctrl+L`重新加载Lua来尝试更改(如果你做了UI更改,则按`F5`)。
|
||||
|
||||
一旦您对更改满意,就可以通过git提交它们。有关如何使用Git的教程和文档,请参阅Git- scm网站。一旦您的更改被提交并推送(到您的分支),您就可以发出拉取请求。
|
||||
|
||||
如果您遇到任何问题,请在[Discord](https://discord.gg/beammp)的#scripting频道中提问。
|
||||
|
||||
---
|
||||
|
||||
# 设置本地服务器
|
||||
|
||||
在使用BeamMP时,使用本地服务器可能是有益的。您可以遵循常规的[服务器安装](../../server/create-a-server.md),同时省略纯本地连接的前两个步骤。
|
||||
|
||||
在`serverConfig`中将服务器设置为私有。使用任意字符串作为`AuthKey`。
|
||||
|
||||
---
|
||||
|
||||
# 贡献指南
|
||||
|
||||
有关代码格式、提交信息格式、通用开发最佳实践等详细信息,请参阅各仓库中的`CONTRIBUTING.md`文件。该文件包含更详细的贡献指南,各仓库中的`README.md`文件通常也会提供具体的构建步骤说明(针对需要编译的项目)。
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: 指南
|
||||
description: 这组页面为BeamMP提供了一些基本指南
|
||||
status: 新的
|
||||
---
|
||||
|
||||
::: warning "这个网站正在建设中!"
|
||||
|
||||
```
|
||||
This site is being actively worked on.
|
||||
|
||||
Feel you could help? Please do by clicking on the page with a pencil on the right!
|
||||
|
||||
This can be done any page too.
|
||||
```
|
||||
|
||||
# BeamMP开发指南
|
||||
|
||||
本页面将是客户端和服务器内容创建的介绍和序言。
|
||||
|
||||
这一页还需要开发。
|
||||
@@ -0,0 +1,101 @@
|
||||
# 创建多人模式
|
||||
|
||||
## 文件夹结构和基础文件
|
||||
|
||||
基本的文件夹和文件结构应该是这样的:
|
||||
|
||||
```
|
||||
Resources/
|
||||
├─ Client/
|
||||
│ └─ examplePlugin.zip/
|
||||
│ ├─ scripts/
|
||||
│ │ └─ modScript.lua
|
||||
│ └─ lua/
|
||||
│ └─ ge/
|
||||
│ └─ extensions/
|
||||
│ └─ examplePlugin.lua
|
||||
└─ Server/
|
||||
└─ examplePlugin/
|
||||
├─ examplePlugin.lua
|
||||
└─ further_lua/
|
||||
└─ further.lua
|
||||
```
|
||||
|
||||
服务器端lua是最基本的,如果您想添加自定义事件,您还至少需要一个客户端lua以及一个modscript.lua
|
||||
|
||||
Server目录需创建多个子文件夹存放各服务端模组。推荐只在根目录保留一个主Lua文件,新增的Lua文件可归类到对应子目录。实际使用中不必严格遵循此规范,若同一层级存在多个Lua文件时,服务器会按文件名称的字母表顺序自动加载。
|
||||
|
||||
Client目录专门存放将发送给客户端的ZIP格式模组包,当客户端接收后会自动以模组形式加载。该目录若存在其他类型文件会导致服务器启动时报错(但不会阻断服务运行),不过这些无关文件仅会被服务端忽略。核心配置脚本modScript.lua由BeamNG游戏引擎解析,用于指引游戏加载指定插件模块。
|
||||
|
||||
:::范例 "" [Download the examplePlugin.zip](../../../../assets/content/ResourcesForExamplePlugin.zip)
|
||||
|
||||
## 服务器端 lua
|
||||
|
||||
更多完整示例可参考examplePlugin模块的实现,现提供一个基础调试示例,实例的功能是显示玩家身份标识
|
||||
|
||||
```lua
|
||||
function onInit() --runs when plugin is loaded
|
||||
|
||||
MP.RegisterEvent("onPlayerAuth", "onPlayerAuth") --Provided by BeamMP
|
||||
|
||||
print("examplePlugin loaded")
|
||||
end
|
||||
|
||||
--A player has authenticated and is requesting to join
|
||||
--The player's name (string), forum role (string), guest account (bool), identifiers (table -> ip, beammp)
|
||||
function onPlayerAuth(player_name, role, isGuest, identifiers)
|
||||
local ip = identifiers.ip
|
||||
local beammp = identifiers.beammp or "N/A"
|
||||
print("onPlayerAuth: player_name: " .. player_name .. " | role: " .. role .. " | isGuest: " .. tostring(isGuest) .. " | identifiers: ip: " .. ip .. " - beammp: " .. beammp)
|
||||
end
|
||||
```
|
||||
|
||||
`onPlayerAuth`会在玩家尝试加入时触发,详细信息请参考脚本文档中的[onPlayerAuth条目](../../../scripting/server/latest-server-reference/#onplayerauth)
|
||||
|
||||
以下是使用onPlayerAuth的另一个示例,该示例将通过向客户端返回信息来禁止游客加入服务器,返回的信息会直接显示给玩家:
|
||||
|
||||
```lua
|
||||
function onPlayerAuth(playerName, playerRole, isGuest, identifiers)
|
||||
if isGuest then
|
||||
return "No guests allowed, please use a BeamMP account"
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
关于BeamMP服务端函数的详细信息请查阅[最新版服务端技术文档](../../../scripting/server/latest-server-reference.md)
|
||||
|
||||
## 客户端 lua
|
||||
|
||||
该实现主要遵循[BeamNG扩展模块](https://documentation.beamng.com/modding/programming/extensions/)的技术规范。
|
||||
|
||||
```lua
|
||||
local M = {}
|
||||
|
||||
if extensions.isExtensionLoaded("examplePlugin") then
|
||||
log("E", "examplePlugin", "examplePlugin loaded on client side")
|
||||
return
|
||||
end
|
||||
|
||||
return M
|
||||
```
|
||||
|
||||
终端输出提示:examplePlugin已完成加载。
|
||||
|
||||
建议查阅[BeamNG调试输出官方文档](https://documentation.beamng.com/modding/programming/debugging/#a-add-a-log)获取详细说明
|
||||
|
||||
## modScript.lua
|
||||
|
||||
通常只包含两行
|
||||
|
||||
```lua
|
||||
load('examplePlugin')
|
||||
setExtensionUnloadMode('examplePlugin', 'manual')
|
||||
```
|
||||
|
||||
如果你想在日志中看到你的modScript被BeamNG处理,你可以添加一个日志打印
|
||||
|
||||
```lua
|
||||
load('examplePlugin')
|
||||
setExtensionUnloadMode('examplePlugin', 'manual')
|
||||
log('I', 'modScript', "examplePlugin loaded")
|
||||
```
|
||||
Reference in New Issue
Block a user