mirror of
https://github.com/BeamMP/Docs.git
synced 2026-06-17 22:32:47 +00:00
Merge branch 'main' into gitlocalize-40718
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
## Warum muss ich meine Mods deaktivieren?
|
||||||
|
|
||||||
|
In BeamMP stellt der Server, mit dem du dich verbindest, die notwendigen Mods bereit. Diese werden beim Verbinden automatisch heruntergeladen und aktiviert. Sind lokale Mods installiert und aktiviert, funktioniert BeamMP oft nicht richtig, selbst wenn du nur einen zusätzlichen Mod neben BeamMP hast.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Entferne alle Mods, die du im Ordner BeamNG.Drive\content\ oder in Unterordnern abgelegt hast. Dieser Speicherort ist NICHT für die Installation von Mods vorgesehen und kann zu Problemen führen, wie in der Datei `DO_NOT_INSTALL_MODS_HERE.txt` im selben Verzeichnis beschrieben.
|
||||||
|
|
||||||
|
!!! quote "DO_NOT_INSTALL_MODS_HERE.txt"
|
||||||
|
|
||||||
|
Kopiere KEINE Mods in diesen Ordner: Dies kann zu beschädigten Mods, einer langsameren Installation von Updates, einem beschädigten Mod-Manager, einem beschädigten abgesicherten Modus und anderen Problemen führen.
|
||||||
|
|
||||||
|
## Wie deaktiviere/entferne ich meine Mods?
|
||||||
|
|
||||||
|
Es gibt drei Möglichkeiten, mögliche Probleme bei der Verwendung von BeamMP zu lösen.
|
||||||
|
|
||||||
|
### 1. Mods deaktivieren
|
||||||
|
|
||||||
|
Bevor du einem Server beitrittst, stelle sicher, dass du außer „multiplayerbeammp“ keine Mods aktiviert hast. Wenn das Spiel einfriert oder weiterhin Probleme auftreten, probiere den nächsten Schritt.
|
||||||
|
|
||||||
|
### 2. Erstellen eines neuen Benutzerordners
|
||||||
|
|
||||||
|
Öffne den Benutzerordner von BeamNG.Drive und benenne den Ordner der neuesten Version (z. B. 0.35) um, z. B. in 0.xx_OLD (0.35_OLD). Schließe BeamNG.drive, bevor du ihn umbenennst.<br>
|
||||||
|
|
||||||
|
### 3. Entfernen von Mods aus dem content Ordnern.
|
||||||
|
|
||||||
|
Um auf den Ordner Beamng.drive\content\ zuzugreifen und ihn von allen Mods zu bereinigen, öffne den Installationsort von BeamNG.drive. Klicke mit der rechten Maustaste auf den Ordner `content` und lösche ihn. Überprüfe anschließend die Spieldateien über Steam oder Epic Games. Dadurch werden die Dateien erneut heruntergeladen.
|
||||||
|
|
||||||
|
Starte anschließend BeamNG.Drive über den BeamMP-Launcher. Im Repository sollte „multiplayerbeammp“ als einziger aktivierter Mod verfügbar sein. Im Hauptmenü findest du außerdem die Schaltfläche zum Aufrufen von BeamMP. Solltest du weiterhin Probleme beim Beitritt zu gemoddeten Servern haben, liegen wahrscheinlich defekte/veraltete Mods vor.
|
||||||
|
|
||||||
|
### 4. BeamMP-Launcher Cache bereinigen
|
||||||
|
|
||||||
|
Um zwischengespeicherte Mods aus den BeamMP-Verzeichnissen zu entfernen, gehe zum Installationsort deines BeamMP-Launchers. Standardmäßig lautet der Pfad „C:\Benutzer\AppData\BeamMP-Launcher“. Dort findest du den Ordner „Ressourcen“. Lösche diesen Ordner, um alle zwischengespeicherten Mods zu löschen. Dies kann hilfreich sein, wenn du mehr Speicherplatz auf deiner Festplatte benötigst oder veraltete BeamNG-Mods entfernen möchtest.
|
||||||
|
|
||||||
|
!!! question "Meine Einstellungen und Konfigurationen sind weg! Wie kann ich sie wiederherstellen?"
|
||||||
|
|
||||||
|
Wenn du den Benutzerordner umbenannt hast, wurde das Spiel gezwungen, einen neuen, sauberen Benutzerordner zu erstellen. Du kannst die beiden Ordner „Einstellungen“ und „Fahrzeuge“ aus dem umbenannten Ordner (z. B. 0.34_OLD) in den neu erstellten Ordner kopieren.
|
||||||
|
Stelle sicher, dass BeamNG.Drive geschlossen ist, und ersetze alle Elemente am Zielort. Alle Konfigurationen und Einstellungen sollten nun wiederhergestellt sein.
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# March 28, 2026 BeamMP Outage FAQ
|
|
||||||
|
|
||||||
Temporary FAQ for the (currently) ongoing BeamMP outage that started on March 28th, 2026.
|
|
||||||
|
|
||||||
**Last updated April 1st, 2026.**
|
|
||||||
|
|
||||||
=== Help! My BeamMP launcher doesn't work!
|
|
||||||
Try reinstalling the BeamMP launcher. To do so, follow the instructions below:
|
|
||||||
1. Go to [beammp.com](https://beammp.com/)
|
|
||||||
2. Click *Download Now*
|
|
||||||
3. Run the installer and follow instructions
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
|
|
||||||
As of April 1st, 2026, the MSI installer is an "unrecognized app" according to Windows Defender SmartScreen.
|
|
||||||
|
|
||||||
To bypass this warning, click *More info*, then click *Run anyway*.
|
|
||||||
|
|
||||||
=== Help! My authkey(s) don't work anymore!
|
|
||||||
As of April 1st, 2026, keymaster and auth systems are offline. This means that your authkeys won't work. To get around this, follow the instructions below:
|
|
||||||
1. Open your `ServerConfig.toml`, or wherever your server config is modified
|
|
||||||
2. Set `Private` to `true`. It should look like this: `Private = true`
|
|
||||||
3. This should fix the authkey issue.
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
|
|
||||||
As of April 1st, 2026, BeamMP's auth systems are offline. Only guest accounts are available.
|
|
||||||
|
|
||||||
Make sure your server allows guests.
|
|
||||||
|
|
||||||
+248
-152
@@ -10,170 +10,266 @@
|
|||||||
|
|
||||||
## Common variables
|
## Common variables
|
||||||
|
|
||||||
=== BeamNG Orange
|
=== "BeamNG CEF Orange"
|
||||||
|
|
||||||
```css
|
```css
|
||||||
var(--bng-orange) /*Common orange*/
|
var(--bng-orange) /*Common orange*/
|
||||||
var(--bng-orange-shade1) /*70% opacity*/
|
var(--bng-orange-shade1) /*70% opacity*/
|
||||||
var(--bng-orange-shade2) /*40% opacity*/
|
var(--bng-orange-shade2) /*40% opacity*/
|
||||||
var(--bng-orange-shade1opaque)
|
var(--bng-orange-shade1opaque)
|
||||||
var(--bng-orange-shade2opaque)
|
var(--bng-orange-shade2opaque)
|
||||||
```
|
```
|
||||||
|
|
||||||
=== Monochrome
|
=== "Monochrome"
|
||||||
|
|
||||||
```css
|
```css
|
||||||
--- Monochrome
|
--- Monochrome
|
||||||
var(--bng-black-8) /*80% opacity (duplicate --bng-black-o8)*/
|
var(--bng-black-8) /*80% opacity (duplicate --bng-black-o8)*/
|
||||||
var(--bng-black-6) /*60% opacity (duplicate --bng-black-o6)*/
|
var(--bng-black-6) /*60% opacity (duplicate --bng-black-o6)*/
|
||||||
var(--bng-black-4) /*40% opacity (duplicate --bng-black-o4)*/
|
var(--bng-black-4) /*40% opacity (duplicate --bng-black-o4)*/
|
||||||
var(--bng-black-2) /*20% opacity (duplicate --bng-black-o2)*/
|
var(--bng-black-2) /*20% opacity (duplicate --bng-black-o2)*/
|
||||||
|
|
||||||
var(--dark-neutral-grey)
|
var(--dark-neutral-grey)
|
||||||
var(--neutral-grey)
|
var(--neutral-grey)
|
||||||
var(--light-neutral-grey)
|
var(--light-neutral-grey)
|
||||||
var(--dark-grey)
|
var(--dark-grey)
|
||||||
var(--dark-grey-alpha) /*80% opacity*/
|
var(--dark-grey-alpha) /*80% opacity*/
|
||||||
|
|
||||||
var(--black-1) /*70% opacity*/
|
var(--black-1) /*70% opacity*/
|
||||||
var(--black-2) /*40% opacity (duplicate --bng-black-o4)*/
|
var(--black-2) /*40% opacity (duplicate --bng-black-o4)*/
|
||||||
|
|
||||||
var(--white-1) /*80% opacity*/
|
var(--white-1) /*80% opacity*/
|
||||||
var(--white-2) /*40% opacity*/
|
var(--white-2) /*40% opacity*/
|
||||||
var(--white-3) /*20% opacity*/
|
var(--white-3) /*20% opacity*/
|
||||||
```
|
```
|
||||||
|
|
||||||
=== BeamNG UI Color Palette
|
=== "BeamNG Vue UI Color Palette"
|
||||||
|
|
||||||
=== Orange
|
All of these support adding `-rgb` to the end of the variable name to convert them to raw red, green, blue values. Use -rgb like so: `rgba(var(--bng-orange-500-rgb), 0.5)` for 50% opacity bng-orange-500.
|
||||||
|
|
||||||
```css
|
=== "Add Red"
|
||||||
var(--bng-orange-50)
|
|
||||||
var(--bng-orange-100)
|
|
||||||
var(--bng-orange-200)
|
|
||||||
var(--bng-orange-300)
|
|
||||||
var(--bng-orange-b400)
|
|
||||||
var(--bng-orange-500)
|
|
||||||
var(--bng-orange-600)
|
|
||||||
var(--bng-orange-700)
|
|
||||||
var(--bng-orange-800)
|
|
||||||
var(--bng-orange-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Cool Gray
|
|
||||||
|
|
||||||
```css
|
```css
|
||||||
var(--bng-cool-gray-50)
|
var(--bng-add-red-50)
|
||||||
var(--bng-cool-gray-100)
|
var(--bng-add-red-100)
|
||||||
var(--bng-cool-gray-200)
|
var(--bng-add-red-200)
|
||||||
var(--bng-cool-gray-300)
|
var(--bng-add-red-300)
|
||||||
var(--bng-cool-gray-400)
|
var(--bng-add-red-400)
|
||||||
var(--bng-cool-gray-500)
|
var(--bng-add-red-500)
|
||||||
var(--bng-cool-gray-600)
|
var(--bng-add-red-550)
|
||||||
var(--bng-cool-gray-700)
|
var(--bng-add-red-600)
|
||||||
var(--bng-cool-gray-800)
|
var(--bng-add-red-650)
|
||||||
var(--bng-cool-gray-900)
|
var(--bng-add-red-700)
|
||||||
```
|
var(--bng-add-red-750)
|
||||||
|
var(--bng-add-red-800)
|
||||||
=== Ter Blue
|
var(--bng-add-red-850)
|
||||||
```css
|
var(--bng-add-red-900)
|
||||||
var(--bng-ter-blue-50)
|
```
|
||||||
var(--bng-ter-blue-100)
|
|
||||||
var(--bng-ter-blue-200)
|
=== "Orange"
|
||||||
var(--bng-ter-blue-300)
|
|
||||||
var(--bng-ter-blue-400)
|
|
||||||
var(--bng-ter-blue-500)
|
|
||||||
var(--bng-ter-blue-600)
|
|
||||||
var(--bng-ter-blue-700)
|
|
||||||
var(--bng-ter-blue-800)
|
|
||||||
var(--bng-ter-blue-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Add Blue
|
|
||||||
```css
|
|
||||||
var(--bng-add-blue-50)
|
|
||||||
var(--bng-add-blue-100)
|
|
||||||
var(--bng-add-blue-200)
|
|
||||||
var(--bng-add-blue-300)
|
|
||||||
var(--bng-add-blue-400)
|
|
||||||
var(--bng-add-blue-500)
|
|
||||||
var(--bng-add-blue-600)
|
|
||||||
var(--bng-add-blue-700)
|
|
||||||
var(--bng-add-blue-800)
|
|
||||||
var(--bng-add-blue-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Add Green
|
|
||||||
```css
|
|
||||||
var(--bng-add-green-50)
|
|
||||||
var(--bng-add-green-100)
|
|
||||||
var(--bng-add-green-200)
|
|
||||||
var(--bng-add-green-300)
|
|
||||||
var(--bng-add-green-400)
|
|
||||||
var(--bng-add-green-500)
|
|
||||||
var(--bng-add-green-600)
|
|
||||||
var(--bng-add-green-700)
|
|
||||||
var(--bng-add-green-800)
|
|
||||||
var(--bng-add-green-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Add Yellow
|
|
||||||
```css
|
|
||||||
var(--bng-add-yellow-50)
|
|
||||||
var(--bng-add-yellow-100)
|
|
||||||
var(--bng-add-yellow-200)
|
|
||||||
var(--bng-add-yellow-300)
|
|
||||||
var(--bng-add-yellow-400)
|
|
||||||
var(--bng-add-yellow-500)
|
|
||||||
var(--bng-add-yellow-600)
|
|
||||||
var(--bng-add-yellow-700)
|
|
||||||
var(--bng-add-yellow-800)
|
|
||||||
var(--bng-add-yellow-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Add Peach
|
|
||||||
```css
|
|
||||||
var(--bng-add-peach-50)
|
|
||||||
var(--bng-add-peach-100)
|
|
||||||
var(--bng-add-peach-200)
|
|
||||||
var(--bng-add-peach-300)
|
|
||||||
var(--bng-add-peach-400)
|
|
||||||
var(--bng-add-peach-500)
|
|
||||||
var(--bng-add-peach-600)
|
|
||||||
var(--bng-add-peach-700)
|
|
||||||
var(--bng-add-peach-800)
|
|
||||||
var(--bng-add-peach-900)
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Add Red
|
```css
|
||||||
```css
|
var(--bng-orange-50)
|
||||||
var(--bng-add-red-50)
|
var(--bng-orange-100)
|
||||||
var(--bng-add-red-100)
|
var(--bng-orange-200)
|
||||||
var(--bng-add-red-200)
|
var(--bng-orange-300)
|
||||||
var(--bng-add-red-300)
|
var(--bng-orange-400)
|
||||||
var(--bng-add-red-400)
|
var(--bng-orange-500)
|
||||||
var(--bng-add-red-500)
|
var(--bng-orange-550)
|
||||||
var(--bng-add-red-600)
|
var(--bng-orange-600)
|
||||||
var(--bng-add-red-700)
|
var(--bng-orange-650)
|
||||||
var(--bng-add-red-800)
|
var(--bng-orange-700)
|
||||||
var(--bng-add-red-900)
|
var(--bng-orange-750)
|
||||||
```
|
var(--bng-orange-800)
|
||||||
|
var(--bng-orange-850)
|
||||||
|
var(--bng-orange-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Ter Peach"
|
||||||
|
|
||||||
=== Extra color presets
|
```css
|
||||||
|
var(--bng-ter-peach-50)
|
||||||
|
var(--bng-ter-peach-100)
|
||||||
|
var(--bng-ter-peach-200)
|
||||||
|
var(--bng-ter-peach-300)
|
||||||
|
var(--bng-ter-peach-400)
|
||||||
|
var(--bng-ter-peach-500)
|
||||||
|
var(--bng-ter-peach-550)
|
||||||
|
var(--bng-ter-peach-600)
|
||||||
|
var(--bng-ter-peach-650)
|
||||||
|
var(--bng-ter-peach-700)
|
||||||
|
var(--bng-ter-peach-750)
|
||||||
|
var(--bng-ter-peach-800)
|
||||||
|
var(--bng-ter-peach-850)
|
||||||
|
var(--bng-ter-peach-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Ter Yellow"
|
||||||
|
|
||||||
```css
|
```css
|
||||||
var(--bng-filter-orange) /*Filter preset to force SVGs to use bng-orange*/
|
var(--bng-ter-yellow-50)
|
||||||
var(--bng-black-o8) /*80% opacity*/
|
var(--bng-ter-yellow-100)
|
||||||
var(--bng-black-o6) /*60% opacity*/
|
var(--bng-ter-yellow-200)
|
||||||
var(--bng-black-o4) /*40% opacity*/
|
var(--bng-ter-yellow-300)
|
||||||
var(--bng-black-o2) /*20% opacity*/
|
var(--bng-ter-yellow-400)
|
||||||
```
|
var(--bng-ter-yellow-500)
|
||||||
|
var(--bng-ter-yellow-550)
|
||||||
|
var(--bng-ter-yellow-600)
|
||||||
|
var(--bng-ter-yellow-650)
|
||||||
|
var(--bng-ter-yellow-700)
|
||||||
|
var(--bng-ter-yellow-750)
|
||||||
|
var(--bng-ter-yellow-800)
|
||||||
|
var(--bng-ter-yellow-850)
|
||||||
|
var(--bng-ter-yellow-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Add Green"
|
||||||
|
|
||||||
=== Corner rounding presets
|
```css
|
||||||
|
var(--bng-add-green-50)
|
||||||
|
var(--bng-add-green-100)
|
||||||
|
var(--bng-add-green-200)
|
||||||
|
var(--bng-add-green-300)
|
||||||
|
var(--bng-add-green-400)
|
||||||
|
var(--bng-add-green-500)
|
||||||
|
var(--bng-add-green-600)
|
||||||
|
var(--bng-add-green-700)
|
||||||
|
var(--bng-add-green-800)
|
||||||
|
var(--bng-add-green-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Baby Blue"
|
||||||
|
|
||||||
```css
|
```css
|
||||||
var(--bng-corners-1) /*0.25rem*/
|
var(--bng-add-babyblue-50)
|
||||||
var(--bng-corners-2) /*0.50rem*/
|
var(--bng-add-babyblue-100)
|
||||||
var(--bng-corners-3) /*1.00rem*/
|
var(--bng-add-babyblue-200)
|
||||||
```
|
var(--bng-add-babyblue-300)
|
||||||
|
var(--bng-add-babyblue-400)
|
||||||
|
var(--bng-add-babyblue-500)
|
||||||
|
var(--bng-add-babyblue-550)
|
||||||
|
var(--bng-add-babyblue-600)
|
||||||
|
var(--bng-add-babyblue-650)
|
||||||
|
var(--bng-add-babyblue-700)
|
||||||
|
var(--bng-add-babyblue-750)
|
||||||
|
var(--bng-add-babyblue-800)
|
||||||
|
var(--bng-add-babyblue-850)
|
||||||
|
var(--bng-add-babyblue-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Add Blue"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-add-blue-50)
|
||||||
|
var(--bng-add-blue-100)
|
||||||
|
var(--bng-add-blue-200)
|
||||||
|
var(--bng-add-blue-300)
|
||||||
|
var(--bng-add-blue-400)
|
||||||
|
var(--bng-add-blue-500)
|
||||||
|
var(--bng-add-blue-600)
|
||||||
|
var(--bng-add-blue-700)
|
||||||
|
var(--bng-add-blue-800)
|
||||||
|
var(--bng-add-blue-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Indigo Blue"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-add-indigoblue-50)
|
||||||
|
var(--bng-add-indigoblue-100)
|
||||||
|
var(--bng-add-indigoblue-200)
|
||||||
|
var(--bng-add-indigoblue-300)
|
||||||
|
var(--bng-add-indigoblue-400)
|
||||||
|
var(--bng-add-indigoblue-500)
|
||||||
|
var(--bng-add-indigoblue-550)
|
||||||
|
var(--bng-add-indigoblue-600)
|
||||||
|
var(--bng-add-indigoblue-650)
|
||||||
|
var(--bng-add-indigoblue-700)
|
||||||
|
var(--bng-add-indigoblue-750)
|
||||||
|
var(--bng-add-indigoblue-800)
|
||||||
|
var(--bng-add-indigoblue-850)
|
||||||
|
var(--bng-add-indigoblue-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Add Magenta"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-add-magenta-50)
|
||||||
|
var(--bng-add-magenta-100)
|
||||||
|
var(--bng-add-magenta-200)
|
||||||
|
var(--bng-add-magenta-300)
|
||||||
|
var(--bng-add-magenta-400)
|
||||||
|
var(--bng-add-magenta-500)
|
||||||
|
var(--bng-add-magenta-550)
|
||||||
|
var(--bng-add-magenta-600)
|
||||||
|
var(--bng-add-magenta-650)
|
||||||
|
var(--bng-add-magenta-700)
|
||||||
|
var(--bng-add-magenta-750)
|
||||||
|
var(--bng-add-magenta-800)
|
||||||
|
var(--bng-add-magenta-850)
|
||||||
|
var(--bng-add-magenta-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Ter Blue Gray"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-ter-blue-gray-50)
|
||||||
|
var(--bng-ter-blue-gray-100)
|
||||||
|
var(--bng-ter-blue-gray-200)
|
||||||
|
var(--bng-ter-blue-gray-300)
|
||||||
|
var(--bng-ter-blue-gray-400)
|
||||||
|
var(--bng-ter-blue-gray-500)
|
||||||
|
var(--bng-ter-blue-gray-550)
|
||||||
|
var(--bng-ter-blue-gray-600)
|
||||||
|
var(--bng-ter-blue-gray-650)
|
||||||
|
var(--bng-ter-blue-gray-700)
|
||||||
|
var(--bng-ter-blue-gray-750)
|
||||||
|
var(--bng-ter-blue-gray-800)
|
||||||
|
var(--bng-ter-blue-gray-850)
|
||||||
|
var(--bng-ter-blue-gray-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Cool Gray"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-cool-gray-50)
|
||||||
|
var(--bng-cool-gray-100)
|
||||||
|
var(--bng-cool-gray-200)
|
||||||
|
var(--bng-cool-gray-300)
|
||||||
|
var(--bng-cool-gray-400)
|
||||||
|
var(--bng-cool-gray-500)
|
||||||
|
var(--bng-cool-gray-550)
|
||||||
|
var(--bng-cool-gray-600)
|
||||||
|
var(--bng-cool-gray-650)
|
||||||
|
var(--bng-cool-gray-700)
|
||||||
|
var(--bng-cool-gray-750)
|
||||||
|
var(--bng-cool-gray-800)
|
||||||
|
var(--bng-cool-gray-850)
|
||||||
|
var(--bng-cool-gray-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Other"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-off-black) /*Used in Vue for buttons and some headers*/
|
||||||
|
var(--bng-off-white) /*Used in Vue for interactable elements*/
|
||||||
|
var(--bng-off-white-brighter) /*Used in Vue for headers*/
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Extra color presets"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-filter-orange) /*Filter preset to force SVGs to use bng-orange*/
|
||||||
|
var(--bng-black-o8) /*80% opacity*/
|
||||||
|
var(--bng-black-o6) /*60% opacity*/
|
||||||
|
var(--bng-black-o4) /*40% opacity*/
|
||||||
|
var(--bng-black-o2) /*20% opacity*/
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Corner rounding presets"
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-corners-1) /*0.25rem*/
|
||||||
|
var(--bng-corners-2) /*0.50rem*/
|
||||||
|
var(--bng-corners-3) /*1.00rem*/
|
||||||
|
```
|
||||||
|
|||||||
@@ -31,47 +31,47 @@ im.End()
|
|||||||
|
|
||||||
## General
|
## General
|
||||||
|
|
||||||
=== Basic Formatting
|
=== "Basic Formatting"
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
im.Text("")
|
im.Text("")
|
||||||
im.TextWrapped("") -- automatic word wrap
|
im.TextWrapped("") -- automatic word wrap
|
||||||
im.TextColored(im.ImVec4(0,1,0,1), "") -- R,G,B,A
|
im.TextColored(im.ImVec4(0,1,0,1), "") -- R,G,B,A
|
||||||
im.TextDisabled("") -- predefined style for disabled text
|
im.TextDisabled("") -- predefined style for disabled text
|
||||||
|
|
||||||
im.LabelText("", "")
|
im.LabelText("", "")
|
||||||
im.BulletText("") -- Bullet point with text
|
im.BulletText("") -- Bullet point with text
|
||||||
im.SeparatorText("") -- Separator with centered text
|
im.SeparatorText("") -- Separator with centered text
|
||||||
|
|
||||||
im.Separator() -- might want a NewLine before these
|
im.Separator() -- might want a NewLine before these
|
||||||
im.SameLine() -- horizontally append the following element to the previous element
|
im.SameLine() -- horizontally append the following element to the previous element
|
||||||
im.NewLine()
|
im.NewLine()
|
||||||
|
|
||||||
im.Spacing() -- small padding
|
im.Spacing() -- small padding
|
||||||
im.Indent()
|
im.Indent()
|
||||||
im.Unindent()
|
im.Unindent()
|
||||||
```
|
```
|
||||||
|
|
||||||
=== Inputs
|
=== "Inputs"
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
im.Button("", im.ImVec2(0,0)) -- 0 = fit to content
|
im.Button("", im.ImVec2(0,0)) -- 0 = fit to content
|
||||||
im.SmallButton("") -- Fit to content and slightly less padding
|
im.SmallButton("") -- Fit to content and slightly less padding
|
||||||
im.ArrowButton("", 0) -- arg 1: string is not actually used? arg 2: 0 = left, 1 = right, 2 = up, 3 = down
|
im.ArrowButton("", 0) -- arg 1: string is not actually used? arg 2: 0 = left, 1 = right, 2 = up, 3 = down
|
||||||
im.InvisibleButton("", im.ImVec2(0,0), ...) -- used for imgui cursor positioning?
|
im.InvisibleButton("", im.ImVec2(0,0), ...) -- used for imgui cursor positioning?
|
||||||
|
|
||||||
im.Checkbox("", im.BoolPtr(false))
|
im.Checkbox("", im.BoolPtr(false))
|
||||||
|
|
||||||
im.RadioButton1("", im.BoolPtr(false))
|
im.RadioButton1("", im.BoolPtr(false))
|
||||||
im.RadioButton2("", im.IntPtr(), 0) -- arg. 3: 0 or 1 for disabled or enabled
|
im.RadioButton2("", im.IntPtr(), 0) -- arg. 3: 0 or 1 for disabled or enabled
|
||||||
```
|
```
|
||||||
|
|
||||||
=== Other
|
=== "Other"
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
im.Bullet()
|
im.Bullet()
|
||||||
|
|
||||||
im.ProgressBar(0.5, im.ImVec2(0,0), "") -- arg 2: 0 for default width and/or height
|
im.ProgressBar(0.5, im.ImVec2(0,0), "") -- arg 2: 0 for default width and/or height
|
||||||
|
|
||||||
im.TextUnformatted("", "") -- Second argument seems to crash the game
|
im.TextUnformatted("", "") -- Second argument seems to crash the game
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -347,4 +347,35 @@ If multiple pages are provided, or the hook is triggered multiple times, then th
|
|||||||
|
|
||||||
### Dialogue
|
### Dialogue
|
||||||
|
|
||||||
todo
|
Dialogue is used in the *A Rocky Start* campaign to display information about a mission. It is a centered, vertically aligned popup with a specific layout. It does not support embedding HTML.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
ui_missionInfo.openDialogue({
|
||||||
|
title = "Dialogue title",
|
||||||
|
type = "Custom", -- isn't actually displayed
|
||||||
|
typeName = "typeName",
|
||||||
|
data = {
|
||||||
|
{label = "objective", value = "reward"}
|
||||||
|
-- add more...
|
||||||
|
},
|
||||||
|
buttons = {
|
||||||
|
{action = "accept", text = "Accept", cmd = ""},
|
||||||
|
{action = 'decline',text = "Decline", cmd = ""}
|
||||||
|
-- add more...
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ui_missionInfo.closeDialogue()
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown>
|
||||||
|

|
||||||
|
</figure>
|
||||||
|
|
||||||
|
Only one Dialogue can be displayed at once. Any existing Dialogue is overridden.
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
`#!lua ui_missionInfo.closeDialogue()` must be used to close a dialogue.
|
||||||
|
|
||||||
|
Make sure you call this function when any button is pressed.
|
||||||
|
|||||||
@@ -1,391 +0,0 @@
|
|||||||
!!! warning "This site is under construction!"
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
# BeamNG.drive Code Snippets
|
|
||||||
|
|
||||||
## Lua Code Snippets
|
|
||||||
|
|
||||||
### World
|
|
||||||
|
|
||||||
#### Drawing a marker & Vehicle detection
|
|
||||||
|
|
||||||
Drawing markers in the map can be one of the best ways to indicate to the user that there is some form of interaction that they can do there.
|
|
||||||
|
|
||||||
Drawing a marker is fairly easy. Here is an example of how the bus route marker is drawn:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
local function createBusMarker(markerName)
|
|
||||||
local marker = createObject('TSStatic')
|
|
||||||
marker:setField('shapeName', 0, "art/shapes/interface/position_marker.dae")
|
|
||||||
marker:setPosition(vec3(0, 0, 0))
|
|
||||||
marker.scale = vec3(1, 1, 1)
|
|
||||||
marker:setField('rotation', 0, '1 0 0 0')
|
|
||||||
marker.useInstanceRenderData = true
|
|
||||||
marker:setField('instanceColor', 0, '1 1 1 0')
|
|
||||||
marker:setField('collisionType', 0, "Collision Mesh")
|
|
||||||
marker:setField('decalType', 0, "Collision Mesh")
|
|
||||||
marker:setField('playAmbient', 0, "1")
|
|
||||||
marker:setField('allowPlayerStep', 0, "1")
|
|
||||||
marker:setField('canSave', 0, "0")
|
|
||||||
marker:setField('canSaveDynamicFields', 0, "1")
|
|
||||||
marker:setField('renderNormals', 0, "0")
|
|
||||||
marker:setField('meshCulling', 0, "0")
|
|
||||||
marker:setField('originSort', 0, "0")
|
|
||||||
marker:setField('forceDetail', 0, "-1")
|
|
||||||
marker.canSave = false
|
|
||||||
marker:registerObject(markerName)
|
|
||||||
scenetree.MissionGroup:addObject(marker)
|
|
||||||
return marker
|
|
||||||
end
|
|
||||||
|
|
||||||
-- this can then be called in a loop to setup your markers.
|
|
||||||
-- NOTE: You should only do this once as part of your setup and not called on each frame.
|
|
||||||
if #markers == 0 then
|
|
||||||
for k,v in pairs(nameMarkers) do
|
|
||||||
local mk = scenetree.findObject(v)
|
|
||||||
if mk == nil then
|
|
||||||
log('I', logTag,'Creating marker '..tostring(v))
|
|
||||||
mk = createBusMarker(v)
|
|
||||||
ScenarioObjectsGroup:addObject(mk.obj)
|
|
||||||
end
|
|
||||||
table.insert(markers, mk)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Here is a custom marker example from [BeamNG-FuelStations](https://github.com/BeamMP/BeamNG-FuelStations/tree/master):
|
|
||||||
|
|
||||||
```lua
|
|
||||||
local stations = [
|
|
||||||
{ "location": [ -778.813, 485.973, 23.46 ], "type":"gas" },
|
|
||||||
{ "location": [ 617.164, -192.107, 53.2 ], "type":"ev" },
|
|
||||||
]
|
|
||||||
|
|
||||||
local function IsEntityInsideArea(pos1, pos2, radius)
|
|
||||||
return pos1:distance(pos2) < radius
|
|
||||||
end
|
|
||||||
|
|
||||||
local onUpdate = function (dt)
|
|
||||||
for k, spot in pairs(stations) do -- loop through all spots on the current map
|
|
||||||
local bottomPos = vec3(spot.location[1], spot.location[2], spot.location[3])
|
|
||||||
local topPos = bottomPos + vec3(0,0,2) -- offset vec to get top position (2m tall)
|
|
||||||
|
|
||||||
local spotInRange = false -- is this spot in range? used for color
|
|
||||||
local spotCompatible = false -- is this spot compatible?
|
|
||||||
|
|
||||||
if activeVeh then -- we have a car and its ours (if in mp)
|
|
||||||
local vehPos = activeVeh:getPosition()
|
|
||||||
|
|
||||||
spotInRange = IsEntityInsideArea(vec3(vehPos.x, vehPos.y,vehPos.z), bottomPos, 1.5)
|
|
||||||
|
|
||||||
spotCompatible = activeFuelType == "any" or spot.type == "any" or activeFuelType == spot.type
|
|
||||||
end
|
|
||||||
|
|
||||||
local spotColor = (spotInRange and spotCompatible) and activeColorMap[spot.type] or inactiveColorMap[spot.type] or ColorF(1,1,1,0.5)
|
|
||||||
|
|
||||||
debugDrawer:drawCylinder(bottomPos:toPoint3F(), topPos:toPoint3F(), 1, spotColor) --bottom, top, radius, color
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### UI snippets
|
|
||||||
|
|
||||||
#### Toast Notifications, Top right of screen
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
--guihooks.trigger('toastrMsg', {type, title, msg, config = {timeOut}})
|
|
||||||
guihooks.trigger('toastrMsg', {type = "info", title = "Info Message:", msg = "Info Message Text Here", config = {timeOut = 5000}})
|
|
||||||
guihooks.trigger('toastrMsg', {type = "warning", title = "Warning Message:", msg = "Warning Message Text Here", config = {timeOut = 5000}})
|
|
||||||
guihooks.trigger('toastrMsg', {type = "error", title = "Error Message:", msg = "Error Message Text Here", config = {timeOut = 5000}})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Message notifications, top left of screen by default in Messages app
|
|
||||||
|
|
||||||
This requires the 'Messages' or 'Messages & Tasks' UI app. Icons can be found at `ui\ui-vue\src\assets\fonts\bngIcons\svg\`
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
--guihooks.trigger('Message', {msg, ttl, category, icon})
|
|
||||||
--ui_message(msg, ttl, category, icon)
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_upward", icon = "arrow_upward"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_downward", icon = "arrow_downward"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "flag", icon = "flag"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "check", icon = "check"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "check_circle", icon = "check_circle"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "warning", icon = "warning"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "error", icon = "error"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "directions_car", icon = "directions_car"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "star", icon = "star"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "timeline", icon = "timeline"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "save", icon = "save"})
|
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "settings", icon = "settings"})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Center large or small display flash
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
--guihooks.trigger('ScenarioFlashMessage', {{msg, ttl, sound, big}} ) -- requires RaceCountdown ui app
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"Message", 5.0, 0, true}} )
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"Message Text Here", 5.0, 0, false}} )
|
|
||||||
|
|
||||||
--countdown example, when all executed at once, the items are queued and will follow eachother after the previous ttl expires
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"3", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown1')", true}})
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"2", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown2')", true}})
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"1", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown3')", true}})
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"GO!", 3.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_CountdownGo')", true}})
|
|
||||||
|
|
||||||
--another sound example
|
|
||||||
guihooks.trigger('ScenarioFlashMessage', {{"Teleported!", 3.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Checkpoint')", false}})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Center mid-size persistent display
|
|
||||||
|
|
||||||
This requires the 'Race Realtime Display' UI app.
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
--guihooks.trigger('ScenarioRealtimeDisplay', {msg = msg} ) -- requires Race Realtime Display ui app
|
|
||||||
guihooks.trigger('ScenarioRealtimeDisplay', {msg = "Message Text Here"} )
|
|
||||||
--these messages persist, clear with a blank string
|
|
||||||
--if you are running live data, this is a good one to update rapidly (think timers, distance calcs, et cetera)
|
|
||||||
guihooks.trigger('ScenarioRealtimeDisplay', {msg = ""} )
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Confirmation Dialog
|
|
||||||
|
|
||||||
ConfirmationDialog is a simplistic popup with up to two buttons.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Open a ConfirmationDialog with a title, body text, and up to two buttons
|
|
||||||
guihooks.trigger("ConfirmationDialogOpen",
|
|
||||||
"Example Title",
|
|
||||||
"Example Body Text",
|
|
||||||
"Okay",
|
|
||||||
"", --gelua. empty string
|
|
||||||
"Cancel",
|
|
||||||
"" --gelua
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Close any open ConfirmationDialog with the provided title
|
|
||||||
guihooks.trigger("ConfirmationDialogClose", "Example Title")
|
|
||||||
```
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
Both fields of a button must be strings in order for the button to appear.
|
|
||||||
|
|
||||||
If the Okay button is provided, pressing the *OK / Primary action* action is equivalent to pressing the Okay button.
|
|
||||||
|
|
||||||
If the Cancel button is provided, pressing the *Menu* action is equivalent to pressing the Cancel button.
|
|
||||||
|
|
||||||
HTML is supported and can be used to add images/icons, for example.
|
|
||||||
|
|
||||||
Multiple can be displayed at once, displayed sequentially.
|
|
||||||
|
|
||||||
!!! bug
|
|
||||||
|
|
||||||
Providing no buttons prevents the player from escaping the dialog without using the console.
|
|
||||||
|
|
||||||
!!! bug
|
|
||||||
|
|
||||||
The SDF parts of the Minimap UI app remain visible while a ConfirmationDialog is active.
|
|
||||||
|
|
||||||
`#!lua guihooks.trigger('ShowApps', false)` to hide UI apps can be used as a hacky workaround.
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
#### introPopupTutorial
|
|
||||||
|
|
||||||
introPopupTutorial is a highly customizable popup that is largely defined with embedded HTML. It is standard to load from a standalone HTML file located in `/gameplay/tutorials/pages/*/content.html`.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
guihooks.trigger("introPopupTutorial", {
|
|
||||||
{
|
|
||||||
content = readFile("/gameplay/tutorials/pages/template/content.html"):gsub("\r\n",""),
|
|
||||||
flavour = "onlyOk"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
guihooks.trigger("introPopupClose")
|
|
||||||
```
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
Flavours controls which buttons are displayed. Four flavours exist:
|
|
||||||
|
|
||||||
* `withLogbook`
|
|
||||||
* Buttons: Career Logbook, Okay
|
|
||||||
* `onlyOk`
|
|
||||||
* Buttons: Okay
|
|
||||||
* `onlyLogbook`
|
|
||||||
* Buttons: Career Logbook
|
|
||||||
* `noButtons`
|
|
||||||
* Provides no buttons
|
|
||||||
|
|
||||||
!!! warning
|
|
||||||
|
|
||||||
When using the noButtons flavour on the page, providing no extra JavaScript in the page content to close the popup causes a softlock. Pages are not combined into one popup in this flavour. It is not recommended to use this flavour.
|
|
||||||
|
|
||||||
If multiple pages are provided, or the hook is triggered multiple times, then the pages are combined into the same popup. If the hook is triggered while a introPopup is active, or when a different introPopup type has already been triggered, then it is displayed in a separate popup after the existing popup is closed.
|
|
||||||
|
|
||||||
#### introPopupCareer
|
|
||||||
|
|
||||||
introPopupCareer is an easy to use, but open ended popup that supports embedding HTML, if needed.
|
|
||||||
|
|
||||||
Flavours control which buttons are displayed and the default image aspect ratio. Four flavours exist:
|
|
||||||
|
|
||||||
* `default`
|
|
||||||
* Default image aspect ratio: 16x9
|
|
||||||
* Buttons: Later, Okay
|
|
||||||
* `welcome`
|
|
||||||
* Default image aspect ratio: 16x9
|
|
||||||
* Buttons: Career Logbook, Okay
|
|
||||||
* `branch-info`
|
|
||||||
* Default image aspect ratio: 16x9
|
|
||||||
* Buttons: Career Logbook, Okay
|
|
||||||
* `garage`
|
|
||||||
* Buttons: Later, Okay
|
|
||||||
|
|
||||||
```lua
|
|
||||||
guihooks.trigger("introPopupCareer", {
|
|
||||||
{
|
|
||||||
title = "Example title",
|
|
||||||
text = "Example text",
|
|
||||||
image = "/gameplay/tutorials/pages/template/image.jpg",
|
|
||||||
ratio = "16x9",
|
|
||||||
flavour = "default"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
guihooks.trigger("introPopupClose")
|
|
||||||
```
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
If multiple pages are provided, or the hook is triggered multiple times, then the pages are combined into the same popup. If the hook is triggered while a introPopup is active, or when a different introPopup type has already been triggered, then it is displayed in a separate popup after the existing popup is closed.
|
|
||||||
|
|
||||||
!!! bug
|
|
||||||
|
|
||||||
The background blur has a minimum height, causing popups with short content to have excess blur below its window. Two main workarounds exist:
|
|
||||||
|
|
||||||
* Repeat `\n` and end with `#!html <div />` until the window covers the blur
|
|
||||||
* Use an empty or missing `image` path and adjust the aspect ratio until the window covers the blur
|
|
||||||
|
|
||||||
#### introPopupMission
|
|
||||||
|
|
||||||
introPopupMission is almost identical to introPopupCareer, but needs buttons to be defined rather than picking a preset for buttons.
|
|
||||||
|
|
||||||
Button styles are combined as *bng-button-*`style`. Built-in button styles are:
|
|
||||||
|
|
||||||
* `main` - orange
|
|
||||||
* `secondary` - cyan
|
|
||||||
* `attention` - red
|
|
||||||
* `white` - white
|
|
||||||
* `link` - translucent
|
|
||||||
* `outline` - orange outline
|
|
||||||
|
|
||||||
```lua
|
|
||||||
guihooks.trigger('introPopupMission', {
|
|
||||||
title = "introPopupMission title",
|
|
||||||
text = "introPopupMission description",
|
|
||||||
image = "/gameplay/tutorials/pages/template/image.jpg",
|
|
||||||
ratio = "16x9",
|
|
||||||
buttons = {
|
|
||||||
{ default=true, class="main", label="main button", clickLua="" },
|
|
||||||
{ default=false, class="secondary", label="secondary button", clickLua="" },
|
|
||||||
{ default=false, class="attention", label="attention button", clickLua="" },
|
|
||||||
{ default=false, class="white", label="white button", clickLua="" },
|
|
||||||
{ default=false, class="link", label="link button", clickLua="" },
|
|
||||||
{ default=false, class="outline", label="outline button", clickLua="" }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
guihooks.trigger("introPopupClose")
|
|
||||||
```
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
If multiple pages are provided, or the hook is triggered multiple times, then the pages are combined into the same popup. If the hook is triggered while a introPopup is active, or when a different introPopup type has already been triggered, then it is displayed in a separate popup after the existing popup is closed.
|
|
||||||
|
|
||||||
!!! bug
|
|
||||||
|
|
||||||
The background blur has a minimum height, causing popups with short content to have excess blur below its window. Two main workarounds exist:
|
|
||||||
|
|
||||||
* Repeat `\n` and end with `#!html <div />` until the window covers the blur
|
|
||||||
* Use an empty or missing `image` path and adjust the aspect ratio until the window covers the blur
|
|
||||||
|
|
||||||
#### Dialogue
|
|
||||||
|
|
||||||
Dialogue is used in the *A Rocky Start* campaign to display information about a mission. It is a centered, vertically aligned popup with a specific layout. It does not support embedding HTML.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
ui_missionInfo.openDialogue({
|
|
||||||
title = "Dialogue title",
|
|
||||||
type = "Custom", -- isn't actually displayed
|
|
||||||
typeName = "typeName",
|
|
||||||
data = {
|
|
||||||
{label = "objective", value = "reward"}
|
|
||||||
-- add more...
|
|
||||||
},
|
|
||||||
buttons = {
|
|
||||||
{action = "accept", text = "Accept", cmd = ""},
|
|
||||||
{action = 'decline',text = "Decline", cmd = ""}
|
|
||||||
-- add more...
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ui_missionInfo.closeDialogue()
|
|
||||||
```
|
|
||||||
|
|
||||||
<figure class="image image_resized" style="width:75%" markdown>
|
|
||||||

|
|
||||||
</figure>
|
|
||||||
|
|
||||||
Only one Dialogue can be displayed at once. Any existing Dialogue is overridden.
|
|
||||||
|
|
||||||
!!! info
|
|
||||||
|
|
||||||
`#!lua ui_missionInfo.closeDialogue()` must be used to close a dialogue.
|
|
||||||
|
|
||||||
Make sure you call this function when any button is pressed.
|
|
||||||
|
|
||||||
## IMGUI Code Snippets
|
|
||||||
|
|
||||||
todo
|
|
||||||
|
|
||||||
## CEF UI Code Snippets
|
|
||||||
|
|
||||||
todo
|
|
||||||
@@ -1171,14 +1171,419 @@ Triggered when a player sends a chat message. When cancelled, it will not show t
|
|||||||
Arguments: `player_id: number`, `vehicle_id: number`, `data: string`
|
Arguments: `player_id: number`, `vehicle_id: number`, `data: string`
|
||||||
Cancellable: YES
|
Cancellable: YES
|
||||||
|
|
||||||
Triggered when a player spawns a new vehicle. The `data` argument contains the car's configuration and positional/rotational data for the vehicle as a json string.
|
Triggered when a player spawns a new vehicle. Note that vehicle swaps/replacements instead fire [`onVehicleEdited`](#onvehicleedited). The `data` argument contains the car's configuration and positional/rotational data for the vehicle as a json string.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
<summary>Example <code>data</code> value</summary>
|
||||||
|
|
||||||
|
The data string begins with a unique vehicle identifier, which is the player's ID, a hyphen, and then the vehicle ID. This is followed by a JSON object containing information about the vehicles configuration and positioning.
|
||||||
|
|
||||||
|
```
|
||||||
|
0-0: {
|
||||||
|
"abs": "realistic",
|
||||||
|
"ign": 3,
|
||||||
|
"jbm": "van",
|
||||||
|
"pid": 0,
|
||||||
|
"pos": [
|
||||||
|
907.93902587891,
|
||||||
|
773.50201416016,
|
||||||
|
238.87800598145
|
||||||
|
],
|
||||||
|
"pro": "0",
|
||||||
|
"rot": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0.99999994039536,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"vcf": {
|
||||||
|
"licenseName": "H30 9VV",
|
||||||
|
"mainPartName": "van",
|
||||||
|
"mainPartPath": "/van",
|
||||||
|
"model": "van",
|
||||||
|
"paints": [
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.21999999880791,
|
||||||
|
0.37000000476837003,
|
||||||
|
0.33000001311302,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.62300002574921,
|
||||||
|
0.62300002574921,
|
||||||
|
0.62300002574921,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0.80000001192093,
|
||||||
|
"clearcoatRoughness": 0.070000000298023,
|
||||||
|
"metallic": 0.80000001192093,
|
||||||
|
"roughness": 0.64999997615814
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.21999999880791,
|
||||||
|
0.37000000476837003,
|
||||||
|
0.33000001311302,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"partConfigFilename": "vehicles/van/h15_xt_passenger.pc",
|
||||||
|
"parts": {
|
||||||
|
"brakepad_F": "brakepad_F_premium",
|
||||||
|
"brakepad_R": "brakepad_R_premium",
|
||||||
|
"gps": "",
|
||||||
|
"licenseplate_design_2_1": "",
|
||||||
|
"linelock": "",
|
||||||
|
"load_seat_FR": "",
|
||||||
|
"n2o_system": "",
|
||||||
|
"paint_design": "van_skin_twotone",
|
||||||
|
"pickup_engine_v8_ecu": "pickup_engine_v8_ecu",
|
||||||
|
"pickup_engine_v8_internals": "pickup_engine_v8_internals",
|
||||||
|
"pickup_enginemounts": "pickup_enginemounts",
|
||||||
|
"pickup_oilpan_v8": "pickup_oilpan_v8",
|
||||||
|
"pickup_reversewarn": "",
|
||||||
|
"pickup_sparetire": "pickup_sparetire_5l",
|
||||||
|
"pickup_towhitch": "",
|
||||||
|
"skin_glass": "van_skin_glass_tint",
|
||||||
|
"skin_interior": "van_skin_interior_black",
|
||||||
|
"soundscape_horn": "soundscape_horn_115",
|
||||||
|
"tire_F_16x7_alt": "tire_F_225_75_16_alt_standard",
|
||||||
|
"tire_R_16x7_alt": "tire_R_225_75_16_alt_standard",
|
||||||
|
"van_ABS": "van_ABS",
|
||||||
|
"van_ESC": "",
|
||||||
|
"van_ac": "van_ac",
|
||||||
|
"van_body": "van_body_passenger",
|
||||||
|
"van_brake_F": "van_brake_F",
|
||||||
|
"van_brake_R": "van_brake_R_drum",
|
||||||
|
"van_bumper_F": "van_bumper_F_altb",
|
||||||
|
"van_bumper_F_lip": "",
|
||||||
|
"van_bumper_R": "van_bumper_R_altb",
|
||||||
|
"van_bumper_accessory_F": "",
|
||||||
|
"van_bumpersignal_FL": "van_bumpersignal_FL",
|
||||||
|
"van_bumpersignal_FR": "van_bumpersignal_FR",
|
||||||
|
"van_coilover_IFS": "van_coilover_IFS",
|
||||||
|
"van_converter": "van_converter",
|
||||||
|
"van_differential_F": "",
|
||||||
|
"van_differential_R": "van_differential_R",
|
||||||
|
"van_door_FL": "van_door_FL",
|
||||||
|
"van_door_FR": "van_door_FR",
|
||||||
|
"van_doordetent_FL": "van_doordetent_FL",
|
||||||
|
"van_doordetent_FR": "van_doordetent_FR",
|
||||||
|
"van_doordetent_RL": "van_doordetent_RL",
|
||||||
|
"van_doordetent_RR": "van_doordetent_RR",
|
||||||
|
"van_doorglass_L": "van_doorglass_L",
|
||||||
|
"van_doorglass_R": "van_doorglass_R",
|
||||||
|
"van_doorpanel_FL": "van_doorpanel_FL",
|
||||||
|
"van_doorpanel_FR": "van_doorpanel_FR",
|
||||||
|
"van_driveshaft_R": "van_driveshaft_R",
|
||||||
|
"van_engine": "van_engine_v8_4.5",
|
||||||
|
"van_exhaust_v8": "van_exhaust_v8",
|
||||||
|
"van_fascia_F": "van_fascia_F_high",
|
||||||
|
"van_fender_L": "van_fender_L",
|
||||||
|
"van_fender_R": "van_fender_R",
|
||||||
|
"van_fenderflare_FL": "",
|
||||||
|
"van_fenderflare_FR": "",
|
||||||
|
"van_fenderflare_RL": "",
|
||||||
|
"van_fenderflare_RR_sidedoor": "",
|
||||||
|
"van_finaldrive_R": "van_finaldrive_R_355",
|
||||||
|
"van_frame": "van_frame",
|
||||||
|
"van_fueltank": "van_fueltank",
|
||||||
|
"van_header": "van_exhmanifold",
|
||||||
|
"van_headlight_L_high": "van_headlight_L_high",
|
||||||
|
"van_headlight_R_high": "van_headlight_R_high",
|
||||||
|
"van_hood": "van_hood",
|
||||||
|
"van_hub_F": "van_hub_F_5",
|
||||||
|
"van_hub_R": "van_hub_R_5",
|
||||||
|
"van_intake_v8": "van_intake_v8",
|
||||||
|
"van_intcarpet_roof": "van_intcarpet_roof",
|
||||||
|
"van_interior": "van_interior",
|
||||||
|
"van_lettering_doors_F": "van_lettering_doors_F_h15",
|
||||||
|
"van_lettering_reardoor_L": "van_lettering_gavril_reardoor_L",
|
||||||
|
"van_lettering_reardoor_R": "van_lettering_h15_xt_reardoor_R",
|
||||||
|
"van_licenseplate_F": "van_licenseplate_F",
|
||||||
|
"van_licenseplate_R": "van_licenseplate_R",
|
||||||
|
"van_lightbar": "",
|
||||||
|
"van_mirror_L": "van_mirror_L",
|
||||||
|
"van_mirror_R": "van_mirror_R",
|
||||||
|
"van_mod": "",
|
||||||
|
"van_muffler": "van_muffler",
|
||||||
|
"van_power_steering": "",
|
||||||
|
"van_radiator": "van_radiator",
|
||||||
|
"van_radio": "van_radio",
|
||||||
|
"van_reardoor_L": "van_reardoor_L",
|
||||||
|
"van_reardoor_R": "van_reardoor_R",
|
||||||
|
"van_reardoorglass_L": "van_reardoorglass_L",
|
||||||
|
"van_reardoorglass_R": "van_reardoorglass_R",
|
||||||
|
"van_reardoorpanel_L": "van_reardoorpanel_L",
|
||||||
|
"van_reardoorpanel_R": "van_reardoorpanel_R",
|
||||||
|
"van_rollcage": "",
|
||||||
|
"van_roof": "van_roof",
|
||||||
|
"van_roof_accessory": "",
|
||||||
|
"van_runningboard": "",
|
||||||
|
"van_seat_1R": "van_seat_1R",
|
||||||
|
"van_seat_2R": "van_seat_2R",
|
||||||
|
"van_seat_3R": "van_seat_3R",
|
||||||
|
"van_seat_FL": "van_seat_FL",
|
||||||
|
"van_seat_FR": "van_seat_FR",
|
||||||
|
"van_shifter": "van_shifter_A",
|
||||||
|
"van_shock_R": "van_shock_R",
|
||||||
|
"van_sidedoor_FR": "van_sidedoor_FR_alt",
|
||||||
|
"van_sidedoor_RR": "van_sidedoor_RR_alt",
|
||||||
|
"van_sidedoorglass_FR": "van_sidedoorglass_FR",
|
||||||
|
"van_sidedoorglass_RR": "van_sidedoorglass_RR",
|
||||||
|
"van_sidedoorpanel_FR": "van_sidedoorpanel_FR",
|
||||||
|
"van_sidedoorpanel_RR": "van_sidedoorpanel_RR",
|
||||||
|
"van_sideglass_FL": "van_sideglass_FL",
|
||||||
|
"van_sideglass_ML": "van_sideglass_ML",
|
||||||
|
"van_sideglass_RL": "van_sideglass_RL",
|
||||||
|
"van_sideglass_RR": "van_sideglass_RR",
|
||||||
|
"van_snorkel": "",
|
||||||
|
"van_spring_R": "van_spring_R",
|
||||||
|
"van_steer": "van_steer",
|
||||||
|
"van_steering": "van_steering",
|
||||||
|
"van_suspension_F": "van_IFS",
|
||||||
|
"van_suspension_R": "van_axle_R",
|
||||||
|
"van_swaybar_F": "van_swaybar_F",
|
||||||
|
"van_swaybar_R": "",
|
||||||
|
"van_taillight_L": "van_taillight_L",
|
||||||
|
"van_taillight_R": "van_taillight_R",
|
||||||
|
"van_taillightguard_L": "",
|
||||||
|
"van_taillightguard_R": "",
|
||||||
|
"van_transfer_case": "van_transfer_case_RWD",
|
||||||
|
"van_transmission": "van_transmission_4A",
|
||||||
|
"van_tubs": "van_tubs",
|
||||||
|
"van_valance_F": "van_valance_F",
|
||||||
|
"van_wheeldata_F": "van_wheeldata_F",
|
||||||
|
"van_wheeldata_R": "van_wheeldata_R",
|
||||||
|
"van_windshield": "van_windshield",
|
||||||
|
"wheel_F_5": "wheel_25a_16x7_5_F",
|
||||||
|
"wheel_R_5": "wheel_25a_16x7_5_R"
|
||||||
|
},
|
||||||
|
"vars": {}
|
||||||
|
},
|
||||||
|
"vid": 29339
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
##### `onVehicleEdited`
|
##### `onVehicleEdited`
|
||||||
|
|
||||||
Arguments: `player_id: number`, `vehicle_id: number`, `data: string`
|
Arguments: `player_id: number`, `vehicle_id: number`, `data: string`
|
||||||
Cancellable: YES
|
Cancellable: YES
|
||||||
|
|
||||||
Triggered when a player edits their vehicle and applies the edit. The `data` argument contains the car's updated configuration as a json string but does **not** include positional or rotational data. You can use [MP.GetPositionRaw](#mpgetpositionrawpid-number-vid-number-tablestring) to get positional and rotational data.
|
Triggered when a player edits or replaces their vehicle. The `data` argument contains the car's updated configuration as a json string but does **not** include positional or rotational data. You can use [MP.GetPositionRaw](#mpgetpositionrawpid-number-vid-number-tablestring) to get positional and rotational data.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
<summary>Example <code>data</code> value</summary>
|
||||||
|
|
||||||
|
The data string begins with a unique vehicle identifier, which is the player's ID, a hyphen, and then the vehicle ID. This is followed by a JSON object containing information about the vehicles configuration.
|
||||||
|
|
||||||
|
```
|
||||||
|
0-0: {
|
||||||
|
"abs": "realistic",
|
||||||
|
"ign": 3,
|
||||||
|
"jbm": "van",
|
||||||
|
"pid": 0,
|
||||||
|
"pro": "0",
|
||||||
|
"vcf": {
|
||||||
|
"licenseName": "P60 1EP",
|
||||||
|
"mainPartName": "van",
|
||||||
|
"mainPartPath": "/van",
|
||||||
|
"model": "van",
|
||||||
|
"paints": [
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"partConfigFilename": "vehicles/van/h15_passenger.pc",
|
||||||
|
"parts": {
|
||||||
|
"brakepad_F": "brakepad_F_premium",
|
||||||
|
"brakepad_R": "brakepad_R_premium",
|
||||||
|
"gps": "",
|
||||||
|
"hubcap_F_16": "hubcap_09c_F_altd",
|
||||||
|
"hubcap_R_16": "hubcap_09c_R_altd",
|
||||||
|
"licenseplate_design_2_1": "",
|
||||||
|
"linelock": "",
|
||||||
|
"load_seat_FR": "",
|
||||||
|
"n2o_system": "",
|
||||||
|
"paint_design": "",
|
||||||
|
"pickup_engine_v8_ecu": "pickup_engine_v8_ecu_late",
|
||||||
|
"pickup_engine_v8_internals": "pickup_engine_v8_internals",
|
||||||
|
"pickup_enginemounts": "pickup_enginemounts",
|
||||||
|
"pickup_oilpan_v8": "pickup_oilpan_v8",
|
||||||
|
"pickup_reversewarn": "",
|
||||||
|
"pickup_sparetire": "pickup_sparetire_6l",
|
||||||
|
"pickup_towhitch": "",
|
||||||
|
"skin_glass": "",
|
||||||
|
"skin_interior": "van_skin_interior_ivory",
|
||||||
|
"soundscape_horn": "soundscape_horn_115",
|
||||||
|
"tire_F_16x7_alt": "tire_F_225_75_16_alt_standard",
|
||||||
|
"tire_R_16x7_alt": "tire_R_225_75_16_alt_standard",
|
||||||
|
"trimring_F_16x7": "",
|
||||||
|
"trimring_R_16x7": "",
|
||||||
|
"van_ABS": "van_ABS",
|
||||||
|
"van_ac": "van_ac",
|
||||||
|
"van_body": "van_body_passenger",
|
||||||
|
"van_brake_F": "van_brake_F",
|
||||||
|
"van_brake_R": "van_brake_R",
|
||||||
|
"van_bumper_accessory_F_late": "",
|
||||||
|
"van_bumper_F": "van_bumper_F_late_alt",
|
||||||
|
"van_bumper_F_lip_late": "",
|
||||||
|
"van_bumper_R": "van_bumper_R_late_alt",
|
||||||
|
"van_coilover_IFS": "van_coilover_IFS",
|
||||||
|
"van_converter": "van_converter",
|
||||||
|
"van_differential_F": "",
|
||||||
|
"van_differential_R": "van_differential_R",
|
||||||
|
"van_door_FL": "van_door_FL",
|
||||||
|
"van_door_FR": "van_door_FR",
|
||||||
|
"van_doordetent_FL": "van_doordetent_FL",
|
||||||
|
"van_doordetent_FR": "van_doordetent_FR",
|
||||||
|
"van_doordetent_RL": "van_doordetent_RL",
|
||||||
|
"van_doordetent_RR": "van_doordetent_RR",
|
||||||
|
"van_doorglass_L": "van_doorglass_L",
|
||||||
|
"van_doorglass_R": "van_doorglass_R",
|
||||||
|
"van_doorpanel_FL": "van_doorpanel_FL",
|
||||||
|
"van_doorpanel_FR": "van_doorpanel_FR",
|
||||||
|
"van_driveshaft_R": "van_driveshaft_R",
|
||||||
|
"van_engine": "van_engine_v8_4.5",
|
||||||
|
"van_ESC": "van_ESC",
|
||||||
|
"van_exhaust_v8": "van_exhaust_v8",
|
||||||
|
"van_fascia_F": "van_fascia_F_late",
|
||||||
|
"van_fender_L": "van_fender_L",
|
||||||
|
"van_fender_R": "van_fender_R",
|
||||||
|
"van_fenderflare_FL": "",
|
||||||
|
"van_fenderflare_FR": "",
|
||||||
|
"van_fenderflare_RL": "",
|
||||||
|
"van_fenderflare_RR_sidedoor": "",
|
||||||
|
"van_finaldrive_R": "van_finaldrive_R_355",
|
||||||
|
"van_frame": "van_frame",
|
||||||
|
"van_fueltank": "van_fueltank",
|
||||||
|
"van_grille_F_late": "van_grille_F_late",
|
||||||
|
"van_header": "van_exhmanifold",
|
||||||
|
"van_headlight_L_late": "van_headlight_L_late",
|
||||||
|
"van_headlight_R_late": "van_headlight_R_late",
|
||||||
|
"van_hood": "van_hood_late",
|
||||||
|
"van_hub_F": "van_hub_F_6",
|
||||||
|
"van_hub_R": "van_hub_R_6",
|
||||||
|
"van_intake_v8": "van_intake_v8_late",
|
||||||
|
"van_intcarpet_roof": "van_intcarpet_roof",
|
||||||
|
"van_interior": "van_interior",
|
||||||
|
"van_lettering_doors_F": "van_lettering_doors_F_h15",
|
||||||
|
"van_lettering_reardoor_L": "van_lettering_gavril_reardoor_L",
|
||||||
|
"van_lettering_reardoor_R": "van_lettering_h15_reardoor_R",
|
||||||
|
"van_licenseplate_F_late": "van_licenseplate_F_late",
|
||||||
|
"van_licenseplate_R_late": "van_licenseplate_R_late",
|
||||||
|
"van_lightbar": "",
|
||||||
|
"van_mirror_L": "van_mirror_L",
|
||||||
|
"van_mirror_R": "van_mirror_R",
|
||||||
|
"van_mod": "",
|
||||||
|
"van_muffler": "van_muffler",
|
||||||
|
"van_power_steering": "",
|
||||||
|
"van_radiator": "van_radiator",
|
||||||
|
"van_radio": "van_radio",
|
||||||
|
"van_reardoor_L": "van_reardoor_L",
|
||||||
|
"van_reardoor_R": "van_reardoor_R",
|
||||||
|
"van_reardoorglass_L": "van_reardoorglass_L",
|
||||||
|
"van_reardoorglass_R": "van_reardoorglass_R",
|
||||||
|
"van_reardoorpanel_L": "van_reardoorpanel_L",
|
||||||
|
"van_reardoorpanel_R": "van_reardoorpanel_R",
|
||||||
|
"van_rollcage": "",
|
||||||
|
"van_roof": "van_roof",
|
||||||
|
"van_roof_accessory": "",
|
||||||
|
"van_runningboard": "",
|
||||||
|
"van_seat_1R": "van_seat_1R",
|
||||||
|
"van_seat_2R": "van_seat_2R",
|
||||||
|
"van_seat_3R": "van_seat_3R",
|
||||||
|
"van_seat_FL": "van_seat_FL",
|
||||||
|
"van_seat_FR": "van_seat_FR",
|
||||||
|
"van_shifter": "van_shifter_A",
|
||||||
|
"van_shock_R": "van_shock_R",
|
||||||
|
"van_sidedoor_FR": "van_sidedoor_FR_alt",
|
||||||
|
"van_sidedoor_RR": "van_sidedoor_RR_alt",
|
||||||
|
"van_sidedoorglass_FR": "van_sidedoorglass_FR",
|
||||||
|
"van_sidedoorglass_RR": "van_sidedoorglass_RR",
|
||||||
|
"van_sidedoorpanel_FR": "van_sidedoorpanel_FR",
|
||||||
|
"van_sidedoorpanel_RR": "van_sidedoorpanel_RR",
|
||||||
|
"van_sideglass_FL": "van_sideglass_FL",
|
||||||
|
"van_sideglass_ML": "van_sideglass_ML",
|
||||||
|
"van_sideglass_RL": "van_sideglass_RL",
|
||||||
|
"van_sideglass_RR": "van_sideglass_RR",
|
||||||
|
"van_snorkel": "",
|
||||||
|
"van_spring_R": "van_spring_R",
|
||||||
|
"van_steer": "van_steer_facelift",
|
||||||
|
"van_steering": "van_steering",
|
||||||
|
"van_suspension_F": "van_IFS",
|
||||||
|
"van_suspension_R": "van_axle_R",
|
||||||
|
"van_swaybar_F": "van_swaybar_F",
|
||||||
|
"van_swaybar_R": "",
|
||||||
|
"van_taillight_L": "van_taillight_L",
|
||||||
|
"van_taillight_R": "van_taillight_R",
|
||||||
|
"van_taillightguard_L": "",
|
||||||
|
"van_taillightguard_R": "",
|
||||||
|
"van_transfer_case": "van_transfer_case_RWD",
|
||||||
|
"van_transmission": "van_transmission_4A",
|
||||||
|
"van_tubs": "van_tubs",
|
||||||
|
"van_valance_F": "van_valance_F_late",
|
||||||
|
"van_wheeldata_F": "van_wheeldata_F",
|
||||||
|
"van_wheeldata_R": "van_wheeldata_R",
|
||||||
|
"van_windshield": "van_windshield",
|
||||||
|
"wheel_F_6": "steelwheel_02b_16x7_F",
|
||||||
|
"wheel_R_6": "steelwheel_02b_16x7_R"
|
||||||
|
},
|
||||||
|
"vars": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
##### `onVehicleDeleted`
|
##### `onVehicleDeleted`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
## Pourquoi dois-je désactiver mes mods ?
|
||||||
|
|
||||||
|
Dans BeamMP, le serveur auquel vous vous connectez fournit les mods nécessaires. Ceux-ci sont téléchargés et activés automatiquement lors de la connexion. L'installation et l'activation de mods locaux peuvent souvent entraîner un dysfonctionnement de BeamMP, même avec un seul mod supplémentaire.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Supprimez tous les mods placés dans le dossier BeamNG.Drive\content\ ou ses sous-dossiers. Cet emplacement n'est PAS destiné à l'installation de mods et peut entraîner des problèmes, comme indiqué dans le fichier « DO_NOT_INSTALL_MODS_HERE.txt », situé dans le même répertoire.
|
||||||
|
|
||||||
|
!!! quote 'DO_NOT_INSTALL_MODS_HERE.txt"
|
||||||
|
|
||||||
|
NE copiez PAS les mods dans ce dossier : cela peut entraîner des mods cassés, une installation plus lente des mises à jour, un gestionnaire de mods cassé, un mode sans échec cassé et autres.
|
||||||
|
|
||||||
|
## Comment désactiver/supprimer mes mods ?
|
||||||
|
|
||||||
|
Il existe 3 options pour résoudre les problèmes possibles lors de l'utilisation de BeamMP.
|
||||||
|
|
||||||
|
### 1. Désactiver les mods
|
||||||
|
|
||||||
|
Avant de rejoindre un serveur, assurez-vous qu'aucun mod autre que « multiplayerbeammp » n'est activé. Si le jeu se bloque ou si vous rencontrez toujours des problèmes, reportez-vous à l'option suivante.
|
||||||
|
|
||||||
|
### 2. Création d'un nouveau dossier utilisateur
|
||||||
|
|
||||||
|
Ouvrez le dossier utilisateur BeamNG.Drive et renommez le dossier de la dernière version (par exemple 0.35) en 0.xx_OLD (0.35_OLD). Fermez BeamNG.drive avant de le renommer. 
|
||||||
|
|
||||||
|
### 3. Suppression des mods des dossiers de contenu.
|
||||||
|
|
||||||
|
Pour accéder au dossier Beamng.drive\content\ et le vider de tout mod, ouvrez l'emplacement d'installation de BeamNG.drive. Faites un clic droit sur le dossier `content` et supprimez-le. Procédez à la vérification des fichiers du jeu via Steam ou Epic Games. Les fichiers seront alors à nouveau téléchargés.
|
||||||
|
|
||||||
|
Une fois terminé, lancez BeamNG.Drive via le lanceur BeamMP. Le seul mod activé dans le dépôt devrait être « multiplayerbeammp », ainsi que le bouton d'accès à BeamMP dans le menu principal. Si vous rencontrez toujours des difficultés pour rejoindre un serveur moddé, il est probable que des mods défectueux ou obsolètes soient disponibles.
|
||||||
|
|
||||||
|
### 4. Nettoyage du cache de BeamMP-Launcher
|
||||||
|
|
||||||
|
Pour nettoyer les mods en cache des répertoires BeamMP, accédez à l'emplacement d'installation de votre lanceur BeamMP. Par défaut, le chemin est « C:\Users\AppData\BeamMP-Launcher ». Vous y trouverez un dossier « Resources ». Supprimez ce dossier pour supprimer tous les mods en cache. Cela peut être utile si vous avez besoin de plus d'espace disque ou si vous souhaitez supprimer des mods BeamNG obsolètes.
|
||||||
|
|
||||||
|
!!! question "Mes paramètres et configurations ont disparu ! Comment puis-je les restaurer ?"
|
||||||
|
|
||||||
|
Si vous avez renommé le dossier utilisateur, vous avez forcé le jeu à créer un nouveau dossier utilisateur propre. Vous pouvez copier les dossiers « paramètres » et « véhicules » du dossier renommé (par exemple, 0.34_OLD) vers le nouveau dossier créé.
|
||||||
|
Assurez-vous que BeamNG.Drive est fermé et remplacez tous les éléments à l'emplacement où vous souhaitez copier les dossiers. Toutes les configurations et tous les paramètres devraient maintenant être identiques.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
# 问题
|
||||||
|
|
||||||
|
启动器没有连接到游戏。这个快速指南解释了如何手动更改启动器端口。
|
||||||
|
|
||||||
|
# 手动修改端口
|
||||||
|
|
||||||
|
1. 启动 BeamNG
|
||||||
|
2. 在主菜单, 打开设置, 然后找到 “Multiplayer”
|
||||||
|
3. 在 “multiplayer” 设置, 启用 `显示高级选项`
|
||||||
|
4. 向下滚动
|
||||||
|
5. 在`启动端口号`中,将端口号更改为其他内容,例如4567
|
||||||
|
6. 关闭 BeamNG
|
||||||
|
7. 右键单击BeamMP-launcher快捷方式,并在上下文菜单中选择`“Open file location”`
|
||||||
|
8. 用文本编辑器打开`launcher.cfg`文件
|
||||||
|
9. 将`“port”:4444,`的编号更改为与之前在游戏内选项中使用的相同,在本例中为4567
|
||||||
|
10. 保存设置并关闭文本编辑器
|
||||||
|
11. 启动 BeamMP-launcher
|
||||||
|
|
||||||
|
如果仍然没有连接,用另一个端口再试一次。在~2000到65535之间的任何数字都是有效的端口
|
||||||
|
|
||||||
|
## 还面临问题吗?
|
||||||
|
|
||||||
|
在我们的[Discord服务器](https://discord.gg/BeamMP)上创建一个支持票。
|
||||||
|
|
||||||
|
标签: Launcher, Connection Failed, Port Number
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
## 为什么我需要停用我的模组 ?
|
||||||
|
|
||||||
|
在BeamMP中,您决定连接的服务器提供了必要的模块。这些会在连接时被下载并自动启用。安装本地模组并启用通常会导致BeamMP不能正常工作,即使您除了BeamMP之外只有一个额外的模组。
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
移除你安装在BeamNG.Drive\content\或子文件夹的任何模组。这个位置不是用来安装mod的,可能会导致位于同一目录下的“DO_NOT_INSTALL_MODS_HERE.txt”文件中所述的问题。
|
||||||
|
|
||||||
|
!!! 引用“DO_NOT_INSTALL_MODS_HERE.txt”
|
||||||
|
|
||||||
|
不要复制mod到这个文件夹:它会导致损坏的mod,更新的安装速度变慢,损坏的mod管理器,损坏的安全模式和其他。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 我如何停用/删除我的模组 ?
|
||||||
|
|
||||||
|
在使用BeamMP时,有3个选项可以解决可能出现的问题。
|
||||||
|
|
||||||
|
### 1. 禁用模组
|
||||||
|
|
||||||
|
在加入任何服务器之前,请确保除了启用“multiplayerbeammp”之外没有其他mod。如果游戏死机或者你仍然有问题,请参考下一个选项
|
||||||
|
|
||||||
|
### 2. 创建一个新的用户文件夹
|
||||||
|
|
||||||
|
打开BeamNG.Drive的用户文件夹,并将`current`文件夹重命名为例如`current_old`。在重命名之前记得关闭BeamNG。
|
||||||
|
|
||||||
|
### 3. 从内容文件夹中删除模组。
|
||||||
|
|
||||||
|
访问BeamNG.Drive\content\文件夹并删除文件夹中的任何模组,打开安装位置的BeamNG.Drive。右键单击`content`文件夹并删除它。继续通过Steam或Epic Games验证游戏文件。这将再次下载文件。
|
||||||
|
|
||||||
|
完成后,通过BeamMP- launcher启动BeamNG,您应该将“multiplayerbeammp”作为模组管理器中唯一启用的mod,然后点击主菜单上的按钮进入BeamMP。如果你在加入mod服务器时仍然有问题,他们可能提供了损坏/未更新的mod。
|
||||||
|
|
||||||
|
### 4. 清理BeamMP-Launcher缓存
|
||||||
|
|
||||||
|
要从BeamMP目录中清除缓存的模组,请转到BeamMP- launcher的安装位置。默认情况下,路径为“C:\Users\AppData\BeamMP-Launcher”。在那里,你会发现一个“Resources”文件夹。删除这个文件夹来删除所有缓存的mod。如果您需要更多磁盘空间或想要删除过时的BeamNG模组,这将非常有用。
|
||||||
|
|
||||||
|
!!! 问题 "我的设置和配置文件都不见了! 我怎样才能恢复呢?"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果你重命名了用户文件夹,你就会让游戏创建一个新的、干净的用户文件夹。你可以从你重命名的文件夹中复制“settings”和“vehicles”文件夹。‘ current_old ’)到它创建的新文件夹。
|
||||||
|
确保BeamNG已关闭,并替换要复制文件夹到的位置中的所有要素。现在,您应该就会有与以前一样的所有配置和设置。
|
||||||
|
```
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
如何检查CGNAT?
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
|
||||||
|
所有防火墙规则和端口转发规则设置正确,但没有人可以加入您的家庭托管服务器?
|
||||||
|
|
||||||
|
如果您有连接问题,并且您正在使用托管服务,请联系他们寻求帮助。如果您想使用VPS或无法在家中托管服务器,请查看我们的[合作托管服务列表](../../server/create-a-server/#partnered-hosting-services-paid)(服务器设置文档)。
|
||||||
|
|
||||||
|
# CGNAT是什么?
|
||||||
|
|
||||||
|
有关CGNAT是什么以及在尝试在家中托管服务器时为什么会出现问题的详细解释,请查看[这个页面](https://en.wikipedia.org/wiki/Carrier-grade_NAT)。
|
||||||
|
|
||||||
|
# 怎么检查CGNAT?
|
||||||
|
|
||||||
|
## 方法 1:
|
||||||
|
|
||||||
|
打开命令提示符,运行`tracert -4 beammp.com`。这将输出一系列网络跳数。等待操作完成(可能需要30跳)。检查路由器/调制解调器/网关IP后的前几个IP地址。如果有多个IP地址在`100.64.x.x`—`100.127.x。X `或`10.xx.xx。xx`出现在第一跳之后,您很可能在CGNAT后面。
|
||||||
|
|
||||||
|
!!! 注意
|
||||||
|
|
||||||
|
```
|
||||||
|
第一跳将是你的路由器/调制解调器/网关,不同的设备不同。
|
||||||
|
本地网络的官方范围如下:‘ ’ 10.0.0。Xxx ' ' - ' ' 192.168.xxx. Xxx。Xxx ' ' - ' ' ' 172.16.xxx.xxx ' ‘ ’
|
||||||
|
```
|
||||||
|
|
||||||
|
## 方法 2:
|
||||||
|
|
||||||
|
在路由器的接口上查找WAN IP。将其与发布在例如https://whatsmyip.org上的IP进行比较。如果它们不一样,你就落后于CGNAT。
|
||||||
|
|
||||||
|
## 方法 3/解决方案:
|
||||||
|
|
||||||
|
请致电互联网服务提供商寻求帮助。根据您的ISP,他们可能不提供专用的*动态* IP地址。请记住,静态IP不是必需的。
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
互联网服务提供商可能只提供专用IP地址作为**付费选项**。
|
||||||
|
请检查我们的合作托管服务的价格,因为他们可能比这个费用便宜!
|
||||||
|
```
|
||||||
|
|
||||||
|
非CGNAT网络的示例:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
标签: Server, 10060 10061, CGNAT, Connection Failed, Port Forward, Firewall
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
## 为什么我需要停用我的模组 ?
|
||||||
|
|
||||||
|
在BeamMP中,您决定连接的服务器提供了必要的模块。这些会在连接时被下载并自动启用。安装本地模组并启用通常会导致BeamMP不能正常工作,即使您除了BeamMP之外只有一个额外的模组。
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
移除你安装在BeamNG.Drive\content\或子文件夹的任何模组。这个位置不是用来安装mod的,可能会导致位于同一目录下的“DO_NOT_INSTALL_MODS_HERE.txt”文件中所述的问题。
|
||||||
|
|
||||||
|
!!! 引用“DO_NOT_INSTALL_MODS_HERE.txt”
|
||||||
|
|
||||||
|
不要复制mod到这个文件夹:它会导致损坏的mod,更新的安装速度变慢,损坏的mod管理器,损坏的安全模式和其他。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 我如何停用/删除我的模组 ?
|
||||||
|
|
||||||
|
在使用BeamMP时,有3个选项可以解决可能出现的问题。
|
||||||
|
|
||||||
|
### 1. 禁用模组
|
||||||
|
|
||||||
|
在加入任何服务器之前,请确保除了启用“multiplayerbeammp”之外没有其他mod。如果游戏死机或者你仍然有问题,请参考下一个选项
|
||||||
|
|
||||||
|
### 2. 创建一个新的用户文件夹
|
||||||
|
|
||||||
|
打开BeamNG.Drive的用户文件夹,并将`current`文件夹重命名为例如`current_old`。在重命名之前记得关闭BeamNG。
|
||||||
|
|
||||||
|
### 3. 从内容文件夹中删除模组。
|
||||||
|
|
||||||
|
访问BeamNG.Drive\content\文件夹并删除文件夹中的任何模组,打开安装位置的BeamNG.Drive。右键单击`content`文件夹并删除它。继续通过Steam或Epic Games验证游戏文件。这将再次下载文件。
|
||||||
|
|
||||||
|
完成后,通过BeamMP- launcher启动BeamNG,您应该将“multiplayerbeammp”作为模组管理器中唯一启用的mod,然后点击主菜单上的按钮进入BeamMP。如果你在加入mod服务器时仍然有问题,他们可能提供了损坏/未更新的mod。
|
||||||
|
|
||||||
|
### 4. 清理BeamMP-Launcher缓存
|
||||||
|
|
||||||
|
要从BeamMP目录中清除缓存的模组,请转到BeamMP- launcher的安装位置。默认情况下,路径为“C:\Users\AppData\BeamMP-Launcher”。在那里,你会发现一个“Resources”文件夹。删除这个文件夹来删除所有缓存的mod。如果您需要更多磁盘空间或想要删除过时的BeamNG模组,这将非常有用。
|
||||||
|
|
||||||
|
!!! 问题 "我的设置和配置文件都不见了! 我怎样才能恢复呢?"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果你重命名了用户文件夹,你就会让游戏创建一个新的、干净的用户文件夹。你可以从你重命名的文件夹中复制“settings”和“vehicles”文件夹。‘ current_old ’)到它创建的新文件夹。
|
||||||
|
确保BeamNG已关闭,并替换要复制文件夹到的位置中的所有要素。现在,您应该就会有与以前一样的所有配置和设置。
|
||||||
|
```
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# 问题
|
||||||
|
|
||||||
|
启动器无法更新或显示空白屏幕?这个快速指南解释了如何手动更新启动器。
|
||||||
|
|
||||||
|
!!! 注意
|
||||||
|
|
||||||
|
```
|
||||||
|
请确保您已通过官网(https://beammp.com)提供的安装程序完成BeamMP的安装及运行,然后再继续后续操作。
|
||||||
|
```
|
||||||
|
|
||||||
|
# 下载并安装一个新的启动器
|
||||||
|
|
||||||
|
1. 直接从[GitHub仓库](https://github.com/BeamMP/BeamMP-Launcher/releases/latest/download/BeamMP-Launcher.exe)下载最新版启动器
|
||||||
|
2. 定位至BeamMP-Launcher.exe所在目录:默认安装路径:`C:\Users\<用户名>\AppData\Roaming\`(将 <用户名> 替换为您的Windows账户名称)<br>自定义安装路径:若您此前将BeamMP安装至其他位置(例如 `D:\BeamMP-Launcher`),请将新启动器文件放入对应文件夹
|
||||||
|
3. 在BeamMP-Launcher文件夹内,使用新启动器覆盖替换旧版本(如存在)
|
||||||
|
4. 按常规方式启动BeamMP-Launcher以验证运行状态
|
||||||
|
|
||||||
|
## 还面临问题?
|
||||||
|
|
||||||
|
请于我们的[Discord服务器](https://discord.gg/BeamMP)创建技术支持工单,标签标注:Launcher, download
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# 常见问题解答
|
||||||
|
|
||||||
|
常见问题列表。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **客户端**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **如何安装 BeamMP?**
|
||||||
|
|
||||||
|
关于如何在Windows上安装BeamMP的完整指南,您可以在[这里](https://docs.beammp.com/game/getting-started/)找到它。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **BeamMP可以运行在盗版或者修改版的BeamNG吗?**
|
||||||
|
|
||||||
|
BeamMP 无法在盗版或旧版本的 BeamNG.drive 上运行。包括但不限于第三方插件在内的修改可能会干扰 BeamMP 的正常运行(请参阅[如何清理插件](https://github.com/Protogen187/Docs/blob/main/docs/en/FAQ/Clearing-mods.md))。<br>BeamMP 支持团队无法针对盗版、旧版本或其他经过修改的 BeamNG.drive 所产生的问题提供技术支持。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **BeamMP 可以在 Linux 上运行吗?**
|
||||||
|
|
||||||
|
客户端在Linux上不被官方支持。但是,您可以查看我们的[指南来了解如何在Linux上使用BeamMP](../game/getting-started/#2b-linux-installation)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **为什么启动器被我的杀毒软件或Windows Defender标记**
|
||||||
|
|
||||||
|
由于 BeamMP 需要与网络进行交互及其他因素,部分杀毒软件可能会将其标记为威胁。但请放心,所有代码中均不含任何病毒。启动器、服务器以及 Lua 客户端的源代码均可在我们的 [GitHub](https://github.com/BeamMP) 页面上找到。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我的游戏性能很差,我该怎么办?**
|
||||||
|
|
||||||
|
我们正在努力使多人游戏体验尽可能稳定。如果您已经降低了图形设置,但性能仍然很差,请考虑在玩家较少的服务器上进行游戏。当你和很多人一起玩游戏时,游戏主要是CPU受限的,所以旧的CPU(甚至是四核)在多人的情况下会受到影响。(一般经验法则:每个CPU线程1辆车)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **其他**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我在哪里可以找到代码?**
|
||||||
|
|
||||||
|
所有源代码都可以在我们的[GitHub](https://github.com/BeamMP)上找到。在进行任何更改之前,请记住代码受我们的[使用条款](https://forum.beammp.com/t/terms-of-use-v1-0/43)和许可的约束:
|
||||||
|
|
||||||
|
代码 | 许可证
|
||||||
|
--- | :-:
|
||||||
|
服务器 | [许可证](https://github.com/BeamMP/BeamMP-Server/blob/master/LICENSE)
|
||||||
|
启动器 | [许可证](https://github.com/BeamMP/BeamMP-Launcher/blob/master/LICENSE)
|
||||||
|
客户端 Lua | [许可证](https://github.com/BeamMP/BeamMP/blob/development/LICENSE)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我发现了错误或漏洞,我该怎么办?**
|
||||||
|
|
||||||
|
如果问题与代码相关,并且您知道如何使用Github,请在[ Github ](https://github.com/BeamMP)上的相应存储库中打开一个新的“issue”。我们使用基于问题的工作流程,所以即使你已经修复了bug,也要考虑打开一个新的“Issue”,然后打开一个包含问题解决方案的“Pull Request”。更多关于贡献的信息可以在[中找到](https://github.com/BeamMP/BeamMP/blob/development/CONTRIBUTING.md)。
|
||||||
|
|
||||||
|
如果您没有GitHub帐户,或者您不知道如何使用GitHub,或者您有任何其他问题,您可以通过以下方式与我们联系:
|
||||||
|
|
||||||
|
- 如果不是敏感内容,您可以在我们的[BeamMP 论坛](https://forum.beammp.com)上创建帖子,或者您可以在我们[的官方 Discord](https://discord.gg/beammp)上报告此问题。
|
||||||
|
- 如果信息敏感,您可以直接向我们的[Discord](https://discord.gg/beammp)上的工作人员报告问题。
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# 2026年3月28日 BeamMP 停机故障常见问题解答(FAQ)
|
||||||
|
|
||||||
|
针对 2026 年 3 月 28 日开始且目前仍在持续的BeamMP停机故障的临时常见问题解答(FAQ)。
|
||||||
|
|
||||||
|
**最后更新于2026年4月1日**
|
||||||
|
|
||||||
|
=== 我需要帮助!我的 BeamMP 启动器无法运行!<br>请尝试重新安装 BeamMP 启动器。具体操作步骤如下:<br><br>1. 访问 [beammp.com](https://beammp.com/)<br>2. 点击 *Download Now(立即下载)*<br>3. 运行安装程序并按照提示进行操作
|
||||||
|
|
||||||
|
```
|
||||||
|
!!! 注意
|
||||||
|
|
||||||
|
截至 2026 年 4 月 1 日,Windows Defender SmartScreen 会将该 MSI 安装程序识别为“未知应用”。
|
||||||
|
|
||||||
|
若要跳过此警告,请点击 *更多信息*,然后点击 *仍要运行*。
|
||||||
|
```
|
||||||
|
|
||||||
|
=== 我需要帮助!我的授权密钥 (authkey) 失效了!<br><br>截至 2026 年 4 月 1 日,Keymaster 和认证系统处于离线状态。这意味着您的 authkeys 将无法正常工作。若要解决此问题,请按照以下步骤操作:<br><br>1. 打开您的 ``ServerConfig.toml`` 文件,或任何存放服务器配置的地方。<br>2. 将 ``Private`` 设置为 ``true``。设置后应如下所示:``Private = true``。<br>3. 这应该能解决 authkey 的失效问题。
|
||||||
|
|
||||||
|
```
|
||||||
|
!!! 注意
|
||||||
|
|
||||||
|
截至 2026 年 4 月 1 日,BeamMP 的认证系统处于离线状态。目前仅支持游客账号(Guest accounts)登录。
|
||||||
|
|
||||||
|
请确保您的服务器已开启游客访问权限。
|
||||||
|
```
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# 常见问题和已知问题
|
||||||
|
|
||||||
|
常见问题和已知bug列表。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **服务器**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我怎么设置自己的服务器**
|
||||||
|
|
||||||
|
设置您自己的服务器的所有信息可以在[中找到](https://docs.beammp.com/server/create-a-server/)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **服务器端兼容LINUX吗?**
|
||||||
|
|
||||||
|
我们在这里提供了许多Linux发行版的二进制文件[。如果您的操作系统/发行版没有二进制文件,您可以通过在](https://github.com/BeamMP/BeamMP-Server/releases/latest)[GitHub](https://github.com/BeamMP/BeamMP-Server)上下载源代码来自己编译它,教程可以在中找到[。](https://github.com/BeamMP/BeamMP-Server#build-instructions)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **运行BeamMP服务器的最低系统要求是什么?**
|
||||||
|
|
||||||
|
- 内存: 50+ MiB可用(不计算操作系统开销)
|
||||||
|
- CPU: >1GHz, 最好是多核
|
||||||
|
- 操作系统: Windows、Linux(理论上兼容所有POSIX系统)
|
||||||
|
- GPU: 不需要
|
||||||
|
- 硬盘:10 MiB + 模组/插件
|
||||||
|
- 带宽:上传5 ~ 10m /s
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **局域网外的玩家无法加入我的自托管服务器**
|
||||||
|
|
||||||
|
请查阅[此处](https://docs.beammp.com/server/port-forwarding/)提供的端口转发指南,下文为其关键步骤摘要。若其他玩家通过BeamMP启动器连接您的服务器时出现错误代码10060、10061或10038,请按以下流程排查:
|
||||||
|
|
||||||
|
- 转发端口30814(或在ServerConfig.toml中配置的其他端口),需同时开放TCP与UDP协议。
|
||||||
|
- 请在Windows防火墙中为BeamMP放行入站与出站连接,直接关闭防火墙通常无法解决问题。
|
||||||
|
- 确认你现在没有在使用VPN (这可能是问题的原因).
|
||||||
|
- 确保服务器确实在运行,没有任何错误或警告。
|
||||||
|
|
||||||
|
您可以在服务器运行时使用CheckBeamMP检查您是否成功地进行了端口转发。
|
||||||
|
|
||||||
|
<form action="https://check.beammp.com/api/v2/beammp" method="get" target="_blank">
|
||||||
|
<label for="ip">IP地址:</label>
|
||||||
|
<input type="text" id="ip" name="ip"><br>
|
||||||
|
<label for="port">端口:</label>
|
||||||
|
<input type="text" id="port" name="port"><br>
|
||||||
|
<input type="submit" value="CheckBeamMP">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
注意:
|
||||||
|
|
||||||
|
- 一些互联网提供商不为您的连接(CGNAT)提供专用的IPv4地址,因此端口转发可能不成功,尽管它在路由器中是可以的。
|
||||||
|
- 如果你使用的是移动(4G/5G)互联网连接,端口转发是不可能的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我可以在服务器列表中看到我的自托管服务器,但我不能自己加入它**
|
||||||
|
|
||||||
|
若服务器与游戏运行于同一台设备,您需通过在直接连接中输入IP地址 127.0.0.1 和服务器端口来加入。若要通过服务器列表加入自托管服务器,您的路由器需支持NAT环回功能,但多数家用路由器未提供此功能。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **其他**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我在哪里可以找到源码?**
|
||||||
|
|
||||||
|
所有源代码都可以在我们的[GitHub](https://github.com/BeamMP)上找到。在做任何事情之前,请记住代码受我们的[使用条款](https://forum.beammp.com/t/terms-of-use-v1-0/43)和许可的约束:
|
||||||
|
|
||||||
|
代码 | 许可证
|
||||||
|
--- | :-:
|
||||||
|
服务器 | [许可证](https://github.com/BeamMP/BeamMP-Server/blob/master/LICENSE)
|
||||||
|
启动器 | [许可证](https://github.com/BeamMP/BeamMP-Launcher/blob/master/README.md)
|
||||||
|
客户端 Lua | [许可证](https://github.com/BeamMP/BeamMP/blob/development/LICENSE.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **我发现了一个bug或漏洞,我应该怎么做?**
|
||||||
|
|
||||||
|
如果问题与代码相关,并且您知道如何使用Github,请在[ Github ](https://github.com/BeamMP)上的适当存储库中创建一个新的“issue”。我们使用基于问题的工作流程,所以即使你已经修复了bug,也可以考虑打开一个新的“Issue”,然后请求一个“Pull Request”来解决你的“问题”。更多关于贡献的信息可以在[中找到](https://github.com/BeamMP/BeamMP/blob/development/CONTRIBUTING.md)。
|
||||||
|
|
||||||
|
如果您没有GitHub帐户或者您不知道如何使用GitHub,您可以通过以下方式与我们联系:
|
||||||
|
|
||||||
|
- 如果问题不涉及隐私或安全,您可以在我们的[BeamMP论坛](https://forum.beammp.com)发帖反馈,或前往[官方Discord服务器](https://discord.gg/beammp)提交报告。
|
||||||
|
- 如果信息敏感,您可以直接向我们的[Discord](https://discord.gg/beammp)上的工作人员报告问题。
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# 我怎样才能找到我服务器的IP ?
|
||||||
|
|
||||||
|
## 对于VPS托管服务器
|
||||||
|
|
||||||
|
如果您使用的我们的合作托管服务之一的托管服务器,其IP地址将显示在对应服务商的服务器管理界面中。您还可以在[Keymaster](https://keymaster.beammp.com/login)网站上找到服务器的IP。
|
||||||
|
|
||||||
|
## 对于家庭托管服务器
|
||||||
|
|
||||||
|
对于家庭自托管服务器,请在浏览器中访问[whatsmyip.org](https://whatsmyip.org),该网站将显示互联网访问您时所使用的公网IPv4地址。
|
||||||
|
|
||||||
|
注意,127.0.0.1是本地主机地址,如果服务器托管在同一台计算机上,则只能由您自己使用。如果您与家庭托管服务器的连接仍然有问题,请检查[端口转发](https://docs.beammp.com/server/port-forwarding/)以及使用CheckBeamMP
|
||||||
|
|
||||||
|
<form action="https://check.beammp.com/api/v2/beammp" method="get" target="_blank">
|
||||||
|
<label for="ip">IP地址:</label>
|
||||||
|
<input type="text" id="ip" name="ip"><br>
|
||||||
|
<label for="port">端口:</label>
|
||||||
|
<input type="text" id="port" name="port"><br>
|
||||||
|
<input type="submit" value="CheckBeamMP">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
## 怎么检查CGNAT?
|
||||||
|
|
||||||
|
请查看[这个页面](https://docs.beammp.com/FAQ/How-to-check-for-CGNAT/),以确定您是否可以在家中托管服务器。
|
||||||
|
|
||||||
|
标签: IP, Server, Connection Failed, 10060/10061
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
!!! warning "本页面正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
本站点目前正处于积极开发与维护阶段。
|
||||||
|
|
||||||
|
觉得您可以提供帮助?请点击页面右侧的铅笔图标参与编辑!
|
||||||
|
此操作适用于站内的任何页面。
|
||||||
|
```
|
||||||
|
|
||||||
|
# BeamNG.drive CEF Code 的片段
|
||||||
|
|
||||||
|
to-do
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
!!! warning "本页面正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
本站点目前正处于积极开发与维护阶段。
|
||||||
|
|
||||||
|
觉得您可以提供帮助?请点击页面右侧的铅笔图标参与编辑!
|
||||||
|
此操作适用于站内的任何页面。
|
||||||
|
```
|
||||||
|
|
||||||
|
# BeamNG.drive CSS Code 的片段
|
||||||
|
|
||||||
|
## 常见变量
|
||||||
|
|
||||||
|
=== BeamNG Orange
|
||||||
|
|
||||||
|
```
|
||||||
|
```css
|
||||||
|
var(--bng-orange) /*Common orange*/
|
||||||
|
var(--bng-orange-shade1) /*70% opacity*/
|
||||||
|
var(--bng-orange-shade2) /*40% opacity*/
|
||||||
|
var(--bng-orange-shade1opaque)
|
||||||
|
var(--bng-orange-shade2opaque)
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Monochrome
|
||||||
|
|
||||||
|
```
|
||||||
|
```css
|
||||||
|
--- Monochrome
|
||||||
|
var(--bng-black-8) /*80% opacity (duplicate --bng-black-o8)*/
|
||||||
|
var(--bng-black-6) /*60% opacity (duplicate --bng-black-o6)*/
|
||||||
|
var(--bng-black-4) /*40% opacity (duplicate --bng-black-o4)*/
|
||||||
|
var(--bng-black-2) /*20% opacity (duplicate --bng-black-o2)*/
|
||||||
|
|
||||||
|
var(--dark-neutral-grey)
|
||||||
|
var(--neutral-grey)
|
||||||
|
var(--light-neutral-grey)
|
||||||
|
var(--dark-grey)
|
||||||
|
var(--dark-grey-alpha) /*80% opacity*/
|
||||||
|
|
||||||
|
var(--black-1) /*70% opacity*/
|
||||||
|
var(--black-2) /*40% opacity (duplicate --bng-black-o4)*/
|
||||||
|
|
||||||
|
var(--white-1) /*80% opacity*/
|
||||||
|
var(--white-2) /*40% opacity*/
|
||||||
|
var(--white-3) /*20% opacity*/
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== BeamNG 界面颜色调色板
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Orange
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-orange-50)
|
||||||
|
var(--bng-orange-100)
|
||||||
|
var(--bng-orange-200)
|
||||||
|
var(--bng-orange-300)
|
||||||
|
var(--bng-orange-b400)
|
||||||
|
var(--bng-orange-500)
|
||||||
|
var(--bng-orange-600)
|
||||||
|
var(--bng-orange-700)
|
||||||
|
var(--bng-orange-800)
|
||||||
|
var(--bng-orange-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Cool Gray
|
||||||
|
|
||||||
|
```css
|
||||||
|
var(--bng-cool-gray-50)
|
||||||
|
var(--bng-cool-gray-100)
|
||||||
|
var(--bng-cool-gray-200)
|
||||||
|
var(--bng-cool-gray-300)
|
||||||
|
var(--bng-cool-gray-400)
|
||||||
|
var(--bng-cool-gray-500)
|
||||||
|
var(--bng-cool-gray-600)
|
||||||
|
var(--bng-cool-gray-700)
|
||||||
|
var(--bng-cool-gray-800)
|
||||||
|
var(--bng-cool-gray-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Ter Blue
|
||||||
|
```css
|
||||||
|
var(--bng-ter-blue-50)
|
||||||
|
var(--bng-ter-blue-100)
|
||||||
|
var(--bng-ter-blue-200)
|
||||||
|
var(--bng-ter-blue-300)
|
||||||
|
var(--bng-ter-blue-400)
|
||||||
|
var(--bng-ter-blue-500)
|
||||||
|
var(--bng-ter-blue-600)
|
||||||
|
var(--bng-ter-blue-700)
|
||||||
|
var(--bng-ter-blue-800)
|
||||||
|
var(--bng-ter-blue-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Add Blue
|
||||||
|
```css
|
||||||
|
var(--bng-add-blue-50)
|
||||||
|
var(--bng-add-blue-100)
|
||||||
|
var(--bng-add-blue-200)
|
||||||
|
var(--bng-add-blue-300)
|
||||||
|
var(--bng-add-blue-400)
|
||||||
|
var(--bng-add-blue-500)
|
||||||
|
var(--bng-add-blue-600)
|
||||||
|
var(--bng-add-blue-700)
|
||||||
|
var(--bng-add-blue-800)
|
||||||
|
var(--bng-add-blue-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Add Green
|
||||||
|
```css
|
||||||
|
var(--bng-add-green-50)
|
||||||
|
var(--bng-add-green-100)
|
||||||
|
var(--bng-add-green-200)
|
||||||
|
var(--bng-add-green-300)
|
||||||
|
var(--bng-add-green-400)
|
||||||
|
var(--bng-add-green-500)
|
||||||
|
var(--bng-add-green-600)
|
||||||
|
var(--bng-add-green-700)
|
||||||
|
var(--bng-add-green-800)
|
||||||
|
var(--bng-add-green-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Add Yellow
|
||||||
|
```css
|
||||||
|
var(--bng-add-yellow-50)
|
||||||
|
var(--bng-add-yellow-100)
|
||||||
|
var(--bng-add-yellow-200)
|
||||||
|
var(--bng-add-yellow-300)
|
||||||
|
var(--bng-add-yellow-400)
|
||||||
|
var(--bng-add-yellow-500)
|
||||||
|
var(--bng-add-yellow-600)
|
||||||
|
var(--bng-add-yellow-700)
|
||||||
|
var(--bng-add-yellow-800)
|
||||||
|
var(--bng-add-yellow-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Add Peach
|
||||||
|
```css
|
||||||
|
var(--bng-add-peach-50)
|
||||||
|
var(--bng-add-peach-100)
|
||||||
|
var(--bng-add-peach-200)
|
||||||
|
var(--bng-add-peach-300)
|
||||||
|
var(--bng-add-peach-400)
|
||||||
|
var(--bng-add-peach-500)
|
||||||
|
var(--bng-add-peach-600)
|
||||||
|
var(--bng-add-peach-700)
|
||||||
|
var(--bng-add-peach-800)
|
||||||
|
var(--bng-add-peach-900)
|
||||||
|
```
|
||||||
|
|
||||||
|
=== Add Red
|
||||||
|
```css
|
||||||
|
var(--bng-add-red-50)
|
||||||
|
var(--bng-add-red-100)
|
||||||
|
var(--bng-add-red-200)
|
||||||
|
var(--bng-add-red-300)
|
||||||
|
var(--bng-add-red-400)
|
||||||
|
var(--bng-add-red-500)
|
||||||
|
var(--bng-add-red-600)
|
||||||
|
var(--bng-add-red-700)
|
||||||
|
var(--bng-add-red-800)
|
||||||
|
var(--bng-add-red-900)
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== 额外颜色预设
|
||||||
|
|
||||||
|
```
|
||||||
|
```css
|
||||||
|
var(--bng-filter-orange) /*Filter preset to force SVGs to use bng-orange*/
|
||||||
|
var(--bng-black-o8) /*80% opacity*/
|
||||||
|
var(--bng-black-o6) /*60% opacity*/
|
||||||
|
var(--bng-black-o4) /*40% opacity*/
|
||||||
|
var(--bng-black-o2) /*20% opacity*/
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== 圆角预设
|
||||||
|
|
||||||
|
```
|
||||||
|
```css
|
||||||
|
var(--bng-corners-1) /*0.25rem*/
|
||||||
|
var(--bng-corners-2) /*0.50rem*/
|
||||||
|
var(--bng-corners-3) /*1.00rem*/
|
||||||
|
```
|
||||||
|
```
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
!!!警告“此网站正在建设中!”
|
||||||
|
|
||||||
|
```
|
||||||
|
这个网站正在积极建设中。
|
||||||
|
|
||||||
|
觉得你能帮忙吗?请用右边的铅笔点击页面!
|
||||||
|
|
||||||
|
这也可以在任何页面上完成。
|
||||||
|
```
|
||||||
|
|
||||||
|
# 车祸模拟器 创建车辆
|
||||||
|
|
||||||
|
。。。
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
。。。
|
||||||
|
|
||||||
|
## 开始进行
|
||||||
|
|
||||||
|
。。。
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
!!! warning "本页面正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
本站点目前正处于积极开发与维护阶段。
|
||||||
|
|
||||||
|
觉得您可以提供帮助?请点击页面右侧的铅笔图标参与编辑!
|
||||||
|
此操作适用于站内的任何页面。
|
||||||
|
|
||||||
|
#创建 ImGui 窗口
|
||||||
|
```
|
||||||
|
|
||||||
|
本页将介绍如何创建一个基础的 ImGui 窗口。
|
||||||
|
|
||||||
|
## 设置
|
||||||
|
|
||||||
|
在开始使用 ImGui 之前,需要进行一些基础设置:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local im = ui_imgui -- 缩写以避免频繁查找。这有助于性能优化
|
||||||
|
local imguiExampleWindowOpen = im.BoolPtr(true)
|
||||||
|
```
|
||||||
|
|
||||||
|
`imguiExampleWindowOpen` 将用于决定该示例窗口是否应当进行渲染。
|
||||||
|
|
||||||
|
## 窗口渲染
|
||||||
|
|
||||||
|
ImGui 窗口及其内容必须在每一个需要显示的帧中重新创建。这意味着,若要使用 ImGui,必须通过某种形式的onUpdate函数来实现。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local function onUpdate()
|
||||||
|
if worldReadyState == 2 then
|
||||||
|
if imguiExampleWindowOpen[0] == true then
|
||||||
|
imguiExample()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
M.onUpdate = onUpdate
|
||||||
|
```
|
||||||
|
|
||||||
|
只要关卡已完全加载,且示例窗口处于应当显示的状态,这段代码就会运行一个函数来创建该示例窗口。
|
||||||
|
|
||||||
|
## 窗口内容
|
||||||
|
|
||||||
|
如果您是初次编写 ImGui,可以把ImGui看作 HTML 的亲戚:
|
||||||
|
|
||||||
|
- `im.SetNextWindowSize(im.ImVec2(x, y), im.Cond_FirstUseEver)` 用于在尚未定义视口尺寸的情况下,对其进行初始化定义。
|
||||||
|
- `im.Begin()` 和 `im.End()`相当于你的 `<body>` 和 `</body>`
|
||||||
|
- `im.Text()` 相当于你的 `<p></p>`
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local buttonPresses = 0
|
||||||
|
|
||||||
|
local function imguiExample()
|
||||||
|
im.SetNextWindowSize(im.ImVec2(366, 100), im.Cond_FirstUseEver) -- 准备窗口尺寸
|
||||||
|
im.Begin("Hello World, I am a window") -- 创建一个标题为“Hello World, I am a window”的窗口
|
||||||
|
im.Indent() -- 缩进元素(类似于内边距)
|
||||||
|
im.Text("Hello World, I am text.") -- 添加一行文本,类似于 <p> 标签
|
||||||
|
im.SameLine() -- 与 HTML 不同,这会将下一个元素附加到上一个元素的同一行
|
||||||
|
if im.Button("The Hello World Button") then -- 类似于 <button>。点击时运行 Lua 代码
|
||||||
|
buttonPresses = buttonPresses + 1
|
||||||
|
end
|
||||||
|
if buttonPresses > 0 then
|
||||||
|
im.Text("The Hello World Button has been pressed " .. buttonPresses .. " times!")
|
||||||
|
else
|
||||||
|
im.Text("The Hello World Button has not been pressed.")
|
||||||
|
end
|
||||||
|
im.Unindent() -- 结束缩进
|
||||||
|
im.End() -- 完成“画布”以便进行渲染
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
您可以添加以下函数,以便轻松切换窗口的可见性:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local function toggleExampleImgui()
|
||||||
|
imguiExampleWindowOpen[0] = not imguiExampleWindowOpen[0]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## 结果
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:100%" markdown="">  </figure>
|
||||||
|
|
||||||
|
当The Hello World Button按钮被按下时,其下方的计数器将更新,并显示The Hello World Button按钮被按下的次数。
|
||||||
|
|
||||||
|
## 下载
|
||||||
|
|
||||||
|
本教程几乎完全基于 [StanleyDudek](https://github.com/StanleyDudek) 的 ImGui 示例模组(Mod)。您可以从[此处](../../../../assets/content/imguiExample.zip)下载该示例模组。
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# imgui-windows.md
|
||||||
|
|
||||||
|
此页面需要创建。
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
# 图形界面-应用程序 创建
|
||||||
|
|
||||||
|
为了制作一个图形界面应用程序,你需要一些AngularJS框架的知识,主要的文档可以在这里找到: [AngularJS docs](https://docs.angularjs.org/guide)
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
一个图形界面应用程序需要四个重要的文件才能工作:
|
||||||
|
|
||||||
|
- app.js | 包含图形界面应用程序使用的主要代码 [Javascript docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||||
|
- app.html | 显示应用程序的代码 [Html docs](https://developer.mozilla.org/fr/docs/Web/HTML)
|
||||||
|
- app.json | 包含图形界面应用程序的信息
|
||||||
|
- app.png | 显示在应用程序选择器中的图像文件
|
||||||
|
|
||||||
|
### 图形界面应用程序 样式
|
||||||
|
|
||||||
|
我们建议使用 `<style>` 标签来设置应用的样式, a .css 文件会工作,但您将无法实时看到更改。
|
||||||
|
|
||||||
|
## 范例
|
||||||
|
|
||||||
|
这个例子来自DanielW,感谢他
|
||||||
|
|
||||||
|
ui\modules\apps\ExampleApp\app.html
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div style="width: 100%; height: 100%;" class="bngApp">
|
||||||
|
<link type="text/css" rel="stylesheet" href="/ui/modules/apps/ExampleApp/app.css" />
|
||||||
|
|
||||||
|
<div id="exampleAppContainer">
|
||||||
|
<span>Gear: <span>{{ gearName }}</span></span>
|
||||||
|
|
||||||
|
<div layout="row" layout-align="center center">
|
||||||
|
<md-input-container flex>
|
||||||
|
<label>Input</label>
|
||||||
|
<input ng-model="message" ng-keydown="sendMessage($event)">
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-button md-no-ink class="md-warn" ng-disabled="!message" ng-click="sendMessage()">Send</md-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span style="display: block">Messages:</span>
|
||||||
|
|
||||||
|
<!-- Scroll Area -->
|
||||||
|
<ul bng-nav-scroll style="margin: 0; padding: 0; overflow-y: auto; width: 100%; height: 100%; background-color: #37373740;">
|
||||||
|
|
||||||
|
<!-- Iterate over the messages and display them -->
|
||||||
|
<li ng-repeat="message in messages track by $index" style="display: flex; align-items: center; height: 35px;">
|
||||||
|
<span style="padding: 0 0.2em; width: 100%;">{{ message }}</span>
|
||||||
|
|
||||||
|
<!-- Button to delete the message, this calls the `deleteMessage` function in `app.js` -->
|
||||||
|
<md-button md-no-ink class="md-icon-button md-warn" ng-click="deleteMessage($index)">
|
||||||
|
<md-icon class="material-icons">delete</md-icon>
|
||||||
|
</md-button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
在这里, 你可以看到一个 `<span>` 显示车辆挡位的标签, 用于将消息发送给 `sendMessage()`函数和一个重复的`<li>`标签(在Javascript中的`messages`变量上使用<b>ng-repeat</b>)
|
||||||
|
|
||||||
|
ui\modules\apps\ExampleApp\app.js
|
||||||
|
|
||||||
|
```js
|
||||||
|
angular.module('beamng.apps')
|
||||||
|
.directive('exampleApp', [function() {
|
||||||
|
return {
|
||||||
|
templateUrl: '/ui/modules/apps/ExampleApp/app.html',
|
||||||
|
replace: true,
|
||||||
|
restrict: 'EA',
|
||||||
|
scope: true,
|
||||||
|
|
||||||
|
controller: ['$scope', function($scope) {
|
||||||
|
$scope.gearName = '0'
|
||||||
|
$scope.message = ''
|
||||||
|
$scope.messages = []
|
||||||
|
|
||||||
|
// Setup the streams we want. For now, we only want the engine information. You can add more, you'll just have to look around to find the different streams
|
||||||
|
let steamList = ['engineInfo']
|
||||||
|
StreamsManager.add(steamList)
|
||||||
|
|
||||||
|
$scope.$on('destroy', function() {
|
||||||
|
StreamsManager.remove(steamList)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Do I even need to put this comment here explaining what this function does?
|
||||||
|
// Well, I have done it for a lot of other things when they weren't needed. I'll leave this one be...
|
||||||
|
$scope.$on('streamsUpdate', function(event, streams) {
|
||||||
|
if (!streams.engineInfo) // Early return... You probably noticed that without this useless comment though
|
||||||
|
return;
|
||||||
|
|
||||||
|
// `lua/vehicle/controller/vehicleController.lua:538` (or use console.log)
|
||||||
|
let gear = streams.engineInfo[5]
|
||||||
|
|
||||||
|
// Update the gear name in HTML if needed
|
||||||
|
if ($scope.gearName !== gear)
|
||||||
|
$scope.gearName = gear
|
||||||
|
})
|
||||||
|
|
||||||
|
$scope.sendMessage = function(event) {
|
||||||
|
if (event && event.key !== 'Enter')
|
||||||
|
return
|
||||||
|
|
||||||
|
if ($scope.message == '')
|
||||||
|
return
|
||||||
|
|
||||||
|
// Forward the message to the Lua extension to modify it
|
||||||
|
bngApi.engineLua('extensions.exampleMod.modifyMessage("' + $scope.message + '")')
|
||||||
|
$scope.message = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.deleteMessage = function(idx) {
|
||||||
|
$scope.messages.splice(idx, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `modifyMessage` function will call this hook with the modified data
|
||||||
|
$scope.$on('MessageReady', function(_, modifiedMessage) {
|
||||||
|
$scope.messages.push(modifiedMessage)
|
||||||
|
});
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
```
|
||||||
|
|
||||||
|
注意<b>$scope{/b0}的用法。这是非常重要的,因为你需要在{b1}$作用域</b>中定义变量和函数,以便能够从<b>ng-*</b>标签中的<b>Html</b>中访问它。所以在这个例子中,在<b>Html</b>中执行`sendMessage()`函数后,它将把它发送到mod的extensions目录中的lua文件中,并在这个lua文件中执行`modifyMessage()`函数。
|
||||||
|
|
||||||
|
下面是lua的一个例子:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local function modifyMessage(message)
|
||||||
|
message = message .. " [Modified!]"
|
||||||
|
guihooks.trigger('MessageReady', message)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
^这是lua的一个简化版本,只是为了展示函数
|
||||||
|
|
||||||
|
这里主要关注的是<b>基钩子的使用。触发器</b>触发一个用`$scope.$on()`定义的AngularJS事件。正如您在Javascript文件的最底部看到的那样,该事件被命名为MessageReady,并将由<b>guihook执行。用消息有效负载触发</b>函数,然后将被推入`$范围。在<b data-md-type="raw_html">Html</b>文件中使用<b data-md-type="raw_html">ng-repeat</b>来显示li标签中的messages`变量
|
||||||
|
|
||||||
|
完整的lua文件就在下面
|
||||||
|
|
||||||
|
lua\ge\extensions\exampleMod.lua
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
--[[
|
||||||
|
This is the entry point of our extension, this is what the game loads from our `modScript.lua`.
|
||||||
|
In the modScript file, you can load more extensions and put them in the same directory as this file.
|
||||||
|
|
||||||
|
In this file, we will communicate with the following:
|
||||||
|
1. Our vehicle extension. That extension tells this extension when to send it data, and we send it. Take a look at `vehicle/extensions/auto/exampleVehicleExtension.lua`
|
||||||
|
2. Input. Take a look at `core/input/actions/myActions.json`. When the bounded key is pressed, it will call `onActionKeyDown` (a function we export below)
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- Game Function Hooks
|
||||||
|
--------------------------------------------
|
||||||
|
local function onExtensionLoaded()
|
||||||
|
log('D', "onExtensionLoaded", "Called")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function onExtensionUnloaded()
|
||||||
|
log('D', "onExtensionUnloaded", "Called")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Custom Functions
|
||||||
|
--------------------------------------------
|
||||||
|
local function onActionKeyDown()
|
||||||
|
log('D', "onActionKeyDown", "Pressed!")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function onVehicleExtensionLoaded(vehID)
|
||||||
|
log('D', "onVehicleExtensionLoaded", "Sending some data to the vehicle")
|
||||||
|
|
||||||
|
local veh = be:getObjectByID(vehID) -- If you don't have the ID, you can also use `be:getPlayerVehicle(0)` to get the current vehicle.
|
||||||
|
if not veh then return end -- The usual error checking
|
||||||
|
|
||||||
|
local data = {
|
||||||
|
["name"] = "Daniel W"
|
||||||
|
}
|
||||||
|
|
||||||
|
veh:queueLuaCommand("extensions.exampleVehicleExtension.onDataReceived('" .. jsonEncode(data) .. "')")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function modifyMessage(message)
|
||||||
|
message = message .. " [Modified!]"
|
||||||
|
guihooks.trigger('MessageReady', message)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Export Interface
|
||||||
|
--------------------------------------------
|
||||||
|
M.onExtensionLoaded = onExtensionLoaded
|
||||||
|
M.onExtensionUnloaded = onExtensionUnloaded
|
||||||
|
|
||||||
|
M.onActionKeyDown = onActionKeyDown
|
||||||
|
M.onVehicleExtensionLoaded = onVehicleExtensionLoaded
|
||||||
|
M.modifyMessage = modifyMessage
|
||||||
|
|
||||||
|
--[[ Other functions could include:
|
||||||
|
- onPreRender(dtReal, dtSim, dtRaw)
|
||||||
|
- onUpdate(dtReal, dtSim, dtRaw)
|
||||||
|
- onClientPreStartMission(levelPath)
|
||||||
|
- onClientPostStartMission(levelPath)
|
||||||
|
|
||||||
|
To find all of these, search the following in `BeamNG.Drive/lua`: `extensions.hook(`
|
||||||
|
--]]
|
||||||
|
|
||||||
|
return M
|
||||||
|
```
|
||||||
|
|
||||||
|
请注意,返回包含所需函数的M(模块)变量非常重要!例如,如果没有`M。modifyMessage = modifyMessage`行,`bngApi.engineLua(‘extensions.exampleMod. ’modifyMessage(' + $scope. ')message + ' ') ')`函数将无法找到modifyMessage()函数
|
||||||
|
|
||||||
|
ui\modules\apps\ExampleApp\app.css
|
||||||
|
|
||||||
|
```css
|
||||||
|
#exampleAppContainer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#exampleAppContainer > * {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
ui\modules\apps\ExampleApp\app.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"domElement": "<example-app></example-app>",
|
||||||
|
"name": "Example App",
|
||||||
|
"types": [
|
||||||
|
"ui.apps.categories.debug"
|
||||||
|
],
|
||||||
|
"description": "example-app",
|
||||||
|
"css": {
|
||||||
|
"left": "0px",
|
||||||
|
"height": "auto",
|
||||||
|
"width": "270px",
|
||||||
|
"min-width": "200px",
|
||||||
|
"min-height": "90px",
|
||||||
|
"top": "0px"
|
||||||
|
},
|
||||||
|
"author": "Daniel W",
|
||||||
|
"version": "0.1",
|
||||||
|
"directive": "exampleApp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
该指令需要与<b>Javascript</b>文件中的指令相同
|
||||||
|
|
||||||
|
# BeamNG为图形界面应用程序提供的Javascript函数
|
||||||
|
|
||||||
|
```js
|
||||||
|
bngApi.engineLua("lua_path.function()")
|
||||||
|
```
|
||||||
|
|
||||||
|
用于运行带或不带参数的lua函数
|
||||||
|
|
||||||
|
# BeamNG为图形界面应用程序提供的Lua函数
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger("EventName", Payload)
|
||||||
|
```
|
||||||
|
|
||||||
|
有效载荷可以是任何类型,但最好将其保留为数组/对象或字符串,以免丢失。
|
||||||
|
|
||||||
|
<b>IMPORTANT</b>:有时候,你使用的事件名称可能已经在内部被其他东西使用了,从而导致问题,因此,如果你的应用名为Nickel,那么最好将你的每个Angular事件命名为NKEventName,而不是EventName
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
!!! warning "本页面正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
本站点目前正处于积极开发与维护阶段。
|
||||||
|
|
||||||
|
觉得您可以提供帮助?请点击页面右侧的铅笔图标参与编辑!
|
||||||
|
此操作适用于站内的任何页面。
|
||||||
|
```
|
||||||
|
|
||||||
|
# BeamNG.drive ImGui Code 的片段
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
### 配置 ImGui
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local im = ui_imgui
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置 Window
|
||||||
|
|
||||||
|
```lua
|
||||||
|
im.SetNextWindowSize(im.ImVec2(366, 100), im.Cond_FirstUseEver)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 创建 window
|
||||||
|
|
||||||
|
```lua
|
||||||
|
im.Begin("Window Title") -- Create window
|
||||||
|
im.End()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 一般演示
|
||||||
|
|
||||||
|
=== 基本格式
|
||||||
|
|
||||||
|
```
|
||||||
|
```lua
|
||||||
|
im.Text("") -- 普通文本
|
||||||
|
im.TextWrapped("") -- 自动换行文本
|
||||||
|
im.TextColored(im.ImVec4(0,1,0,1), "") -- 彩色文本(参数为 R,G,B,A)
|
||||||
|
im.TextDisabled("") -- 禁用状态样式的文本(预设样式)
|
||||||
|
|
||||||
|
im.LabelText("", "") -- 带标签的文本
|
||||||
|
im.BulletText("") -- 带项目符号(圆点)的文本
|
||||||
|
im.SeparatorText("") -- 带中间文字的分隔线
|
||||||
|
|
||||||
|
im.Separator() -- 分隔线(在添加前可能需要换行)
|
||||||
|
im.SameLine() -- 将下一个元素水平附加到上一个元素之后
|
||||||
|
im.NewLine() -- 换行
|
||||||
|
|
||||||
|
im.Spacing() -- 微小间距(填充)
|
||||||
|
im.Indent() -- 缩进
|
||||||
|
im.Unindent() -- 取消缩进
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== 输入
|
||||||
|
|
||||||
|
```
|
||||||
|
```lua
|
||||||
|
im.Button("", im.ImVec2(0,0)) -- 按钮(0 = 自动适应内容大小)
|
||||||
|
im.SmallButton("") -- 小按钮(适应内容且内边距更小)
|
||||||
|
im.ArrowButton("", 0) -- 箭头按钮(参数1:字符串实际未被使用?参数2:0=左,1=右,2=上,3=下)
|
||||||
|
im.InvisibleButton("", im.ImVec2(0,0), ...) -- 不可见按钮(用于 ImGui 光标定位?)
|
||||||
|
|
||||||
|
im.Checkbox("", im.BoolPtr(false)) -- 复选框
|
||||||
|
|
||||||
|
im.RadioButton1("", im.BoolPtr(false)) -- 单选框 1
|
||||||
|
im.RadioButton2("", im.IntPtr(), 0) -- 单选框 2(参数3:0 或 1,分别代表禁用或启用状态)
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
=== 其他
|
||||||
|
|
||||||
|
```
|
||||||
|
```lua
|
||||||
|
im.Bullet()
|
||||||
|
|
||||||
|
im.ProgressBar(0.5, im.ImVec2(0,0), "") -- 进度条(参数 2:填 0 则使用默认宽度和/或高度)
|
||||||
|
im.TextUnformatted("", "") -- 非格式化文本(第二个参数似乎会导致游戏崩溃)
|
||||||
|
```
|
||||||
|
```
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# 欢迎来到 BeamNG.drive 文档
|
||||||
|
|
||||||
|
本文档是非官方的,由BeamMP模组团队和BeamNG社区制作。
|
||||||
|
|
||||||
|
## 了解文件结构
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
## 片段
|
||||||
|
|
||||||
|
对您可能有用的代码片段可以在这里找到: [Lua Snippets](lua-snippets.md)
|
||||||
@@ -0,0 +1,346 @@
|
|||||||
|
!!! warning "本页面正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
本站点目前正处于积极开发与维护阶段。
|
||||||
|
|
||||||
|
觉得您可以提供帮助?请点击页面右侧的铅笔图标参与编辑!
|
||||||
|
此操作适用于站内的任何页面。
|
||||||
|
```
|
||||||
|
|
||||||
|
# BeamNG.drive Lua Code 的片段
|
||||||
|
|
||||||
|
## 世界
|
||||||
|
|
||||||
|
### 绘制标记&车辆检测
|
||||||
|
|
||||||
|
在地图上绘制标记是告知用户该处存在某种交互形式的最佳方式之一。
|
||||||
|
|
||||||
|
绘制标记相当简单。以下是巴士路线标记绘制方式的一个示例:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local function createBusMarker(markerName)
|
||||||
|
local marker = createObject('TSStatic')
|
||||||
|
marker:setField('shapeName', 0, "art/shapes/interface/position_marker.dae")
|
||||||
|
marker:setPosition(vec3(0, 0, 0))
|
||||||
|
marker.scale = vec3(1, 1, 1)
|
||||||
|
marker:setField('rotation', 0, '1 0 0 0')
|
||||||
|
marker.useInstanceRenderData = true
|
||||||
|
marker:setField('instanceColor', 0, '1 1 1 0')
|
||||||
|
marker:setField('collisionType', 0, "Collision Mesh") -- 碰撞类型:碰撞网格
|
||||||
|
marker:setField('decalType', 0, "Collision Mesh") -- 贴花类型:碰撞网格
|
||||||
|
marker:setField('playAmbient', 0, "1") -- 播放环境动画
|
||||||
|
marker:setField('allowPlayerStep', 0, "1") -- 允许玩家踏上
|
||||||
|
marker:setField('canSave', 0, "0") -- 是否可保存
|
||||||
|
marker:setField('canSaveDynamicFields', 0, "1") -- 是否可保存动态字段
|
||||||
|
marker:setField('renderNormals', 0, "0") -- 渲染法线
|
||||||
|
marker:setField('meshCulling', 0, "0") -- 网格剔除
|
||||||
|
marker:setField('originSort', 0, "0")
|
||||||
|
marker:setField('forceDetail', 0, "-1")
|
||||||
|
marker.canSave = false
|
||||||
|
marker:registerObject(markerName)
|
||||||
|
scenetree.MissionGroup:addObject(marker)
|
||||||
|
return marker
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 随后可以在循环中调用此函数来设置您的标记。
|
||||||
|
-- 注意:您应该只在初始化设置时执行一次,而不是在每一帧都调用。
|
||||||
|
if #markers == 0 then
|
||||||
|
for k,v in pairs(nameMarkers) do
|
||||||
|
local mk = scenetree.findObject(v)
|
||||||
|
if mk == nil then
|
||||||
|
log('I', logTag,'Creating marker '..tostring(v)) -- 正在创建标记...
|
||||||
|
mk = createBusMarker(v)
|
||||||
|
ScenarioObjectsGroup:addObject(mk.obj)
|
||||||
|
end
|
||||||
|
table.insert(markers, mk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
这是来自 [BeamNG-FuelStations](https://github.com/BeamMP/BeamNG-FuelStations/tree/master) 的自定义标记示例:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local stations = [
|
||||||
|
{ "location": [ -778.813, 485.973, 23.46 ], "type":"gas" }, -- 燃油站
|
||||||
|
{ "location": [ 617.164, -192.107, 53.2 ], "type":"ev" }, -- 充电站
|
||||||
|
]
|
||||||
|
|
||||||
|
-- 检查实体是否在区域内
|
||||||
|
local function IsEntityInsideArea(pos1, pos2, radius)
|
||||||
|
return pos1:distance(pos2) < radius
|
||||||
|
end
|
||||||
|
|
||||||
|
local onUpdate = function (dt)
|
||||||
|
for k, spot in pairs(stations) do -- 遍历当前地图上的所有站点
|
||||||
|
local bottomPos = vec3(spot.location[1], spot.location[2], spot.location[3])
|
||||||
|
local topPos = bottomPos + vec3(0,0,2) -- 偏移向量以获得顶部位置(2米高)
|
||||||
|
|
||||||
|
local spotInRange = false -- 站点是否在范围内?用于颜色判定
|
||||||
|
local spotCompatible = false -- 站点是否匹配(燃料类型)?
|
||||||
|
|
||||||
|
if activeVeh then -- 如果存在车辆且属于当前玩家(若在多人模式下)
|
||||||
|
local vehPos = activeVeh:getPosition()
|
||||||
|
|
||||||
|
-- 检查车辆是否在站点 1.5 米范围内
|
||||||
|
spotInRange = IsEntityInsideArea(vec3(vehPos.x, vehPos.y,vehPos.z), bottomPos, 1.5)
|
||||||
|
|
||||||
|
-- 检查燃料类型是否匹配
|
||||||
|
spotCompatible = activeFuelType == "any" or spot.type == "any" or activeFuelType == spot.type
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 确定站点颜色:如果范围内且匹配,则使用活动颜色,否则使用非活动颜色或默认半透明白色
|
||||||
|
local spotColor = (spotInRange and spotCompatible) and activeColorMap[spot.type] or inactiveColorMap[spot.type] or ColorF(1,1,1,0.5)
|
||||||
|
|
||||||
|
-- 绘制圆柱体:底部位置,顶部位置,半径,颜色
|
||||||
|
debugDrawer:drawCylinder(bottomPos:toPoint3F(), topPos:toPoint3F(), 1, spotColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## 用户界面
|
||||||
|
|
||||||
|
### 屏幕右上角弹出的通知
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--guihooks.trigger('toastrMsg', {type, title, msg, config = {timeOut}})
|
||||||
|
guihooks.trigger('toastrMsg', {type = "info", title = "Info Message:", msg = "Info Message Text Here", config = {timeOut = 5000}})
|
||||||
|
guihooks.trigger('toastrMsg', {type = "warning", title = "Warning Message:", msg = "Warning Message Text Here", config = {timeOut = 5000}})
|
||||||
|
guihooks.trigger('toastrMsg', {type = "error", title = "Error Message:", msg = "Error Message Text Here", config = {timeOut = 5000}})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 消息通知,默认显示在消息应用的屏幕左上角
|
||||||
|
|
||||||
|
这需要安装“消息”或“消息与任务”UI 应用。图标可以在此处找到: `ui\ui-vue\src\assets\fonts\bngIcons\svg这需要安装“消息”或“消息与任务”UI 应用。图标可以在此处找到:
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--guihooks.trigger('Message', {msg, ttl, category, icon})
|
||||||
|
--ui_message(msg, ttl, category, icon)
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_upward", icon = "arrow_upward"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_downward", icon = "arrow_downward"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "flag", icon = "flag"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "check", icon = "check"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "check_circle", icon = "check_circle"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "warning", icon = "warning"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "error", icon = "error"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "directions_car", icon = "directions_car"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "star", icon = "star"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "timeline", icon = "timeline"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "save", icon = "save"})
|
||||||
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "settings", icon = "settings"})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 屏幕中央大尺寸或小尺寸闪烁显示
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--guihooks.trigger('ScenarioFlashMessage', {{msg, ttl, sound, big}} ) -- requires RaceCountdown ui app
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"Message", 5.0, 0, true}} )
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"Message Text Here", 5.0, 0, false}} )
|
||||||
|
|
||||||
|
--countdown example, when all executed at once, the items are queued and will follow eachother after the previous ttl expires
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"3", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown1')", true}})
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"2", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown2')", true}})
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"1", 1.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Countdown3')", true}})
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"GO!", 3.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_CountdownGo')", true}})
|
||||||
|
|
||||||
|
--另一个声音示例
|
||||||
|
guihooks.trigger('ScenarioFlashMessage', {{"Teleported!", 3.0, "Engine.Audio.playOnce('AudioGui', 'event:UI_Checkpoint')", false}})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 屏幕中央中等尺寸持久显示
|
||||||
|
|
||||||
|
这需要安装实时竞赛显示UI 应用。
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--guihooks.trigger('ScenarioRealtimeDisplay', {msg = msg} ) -- 需要安装 Race Realtime Display UI 应用
|
||||||
|
guihooks.trigger('ScenarioRealtimeDisplay', {msg = "在此输入消息文本"} )
|
||||||
|
-- 这些消息会持久显示,可以通过发送空字符串来清除
|
||||||
|
-- 如果您正在运行实时数据(例如计时器、距离计算等),这是一个非常适合快速更新的接口
|
||||||
|
guihooks.trigger('ScenarioRealtimeDisplay', {msg = ""} )
|
||||||
|
```
|
||||||
|
|
||||||
|
### 确认对话框
|
||||||
|
|
||||||
|
确认对话框是一个带有多达两个按钮的简化弹出窗口。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- 打开一个包含标题、正文文本和最多两个按钮的确认对话框(ConfirmationDialog)
|
||||||
|
guihooks.trigger("ConfirmationDialogOpen",
|
||||||
|
"示例标题",
|
||||||
|
"示例正文文本内容",
|
||||||
|
"确定",
|
||||||
|
"", -- 对应的 gelua 代码,此处为空字符串
|
||||||
|
"取消",
|
||||||
|
"" -- 对应的 gelua 代码
|
||||||
|
)
|
||||||
|
|
||||||
|
-- 关闭任何具有指定标题的已打开确认对话框
|
||||||
|
guihooks.trigger("ConfirmationDialogClose", "示例标题")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
按钮的两个字段都必须为字符串类型,按钮才会显示。
|
||||||
|
|
||||||
|
如果提供了确定按钮,按下 *确定 / 首要操作(OK / Primary action)* 键等同于点击“确定”按钮。
|
||||||
|
|
||||||
|
如果提供了取消按钮,按下 *菜单(Menu)*键等同于点击取消按钮。
|
||||||
|
|
||||||
|
支持HTML,例如可以用来添加图片或图标。
|
||||||
|
|
||||||
|
可以同时显示多个,并将按顺序排列显示。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
如果不提供任何按钮,玩家将无法在不使用控制台的情况下关闭或退出该对话框。
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
当 ConfirmationDialog(确认对话框)处于活动状态时,迷你地图UI应用的 SDF 部分仍然保持可见。
|
||||||
|
|
||||||
|
可以使用 `#!lua guihooks.trigger('ShowApps', false)` 隐藏 UI 应用,作为一种临时解决方案。
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
### introPopupTutorial
|
||||||
|
|
||||||
|
introPopupTutorial 是一个高度可定制的弹出窗口,很大程度上是通过嵌入式 HTML 来定义的。通常的做法是从一个独立的 HTML 文件中进行加载,该文件位于:`/gameplay/tutorials/pages/*/content.html`.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger("introPopupTutorial", {
|
||||||
|
{
|
||||||
|
content = readFile("/gameplay/tutorials/pages/template/content.html"):gsub("\r\n",""),
|
||||||
|
flavour = "onlyOk"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
`flavour` 控制哪些按钮会被显示。共有四种类型:
|
||||||
|
|
||||||
|
- `withLogbook`
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `onlyOk`
|
||||||
|
- Buttons: Okay
|
||||||
|
- `onlyLogbook`
|
||||||
|
- Buttons: Career Logbook
|
||||||
|
- `noButtons`
|
||||||
|
- 不提供任何按钮
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
如果在页面中使用noButtons类型,且页面内容中没有提供额外的 JavaScript 来关闭该弹出窗口,则会导致游戏出现Softlock。在此类型下,多个页面不会合并到同一个弹出窗口中。因此,不建议使用此类型。
|
||||||
|
```
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该Hook被多次触发,这些页面将合并到同一个弹出窗口中。<br>如果在一个 introPopup 处于活动状态时触发该钩子,或者已经触发了另一种不同类型的 introPopup,则它会在当前窗口关闭后,在一个独立的弹出窗口中显示。
|
||||||
|
|
||||||
|
### introPopupCareer
|
||||||
|
|
||||||
|
introPopupCareer是一种易于使用且开放式Open-ended的弹出窗口,如果需要,它还支持嵌入 HTML 内容。
|
||||||
|
|
||||||
|
Flavours控制显示哪些按钮以及默认的图像长宽比。共有四种类型:
|
||||||
|
|
||||||
|
- `default`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Later, Okay
|
||||||
|
- `welcome`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `branch-info`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `garage`
|
||||||
|
- Buttons: Later, Okay
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger("introPopupCareer", {
|
||||||
|
{
|
||||||
|
title = "Example title",
|
||||||
|
text = "Example text",
|
||||||
|
image = "/gameplay/tutorials/pages/template/image.jpg",
|
||||||
|
ratio = "16x9",
|
||||||
|
flavour = "default"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown=""> !在 BeamNG.drive 中显示的introPopupCareer代码片段](../../assets/content/introPopupCareer.png) </figure>
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该Hook被多次触发,这些页面将被合并到同一个弹出窗口中。<br>如果在一个introPopup处于活动状态时触发了该钩子,或者已经触发了另一种不同类型的introPopup,那么它将在当前窗口关闭后,通过一个独立的弹出窗口进行显示。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
背景模糊具有最小高度限制,这会导致内容较少的弹出窗口在其窗口下方出现多余的模糊区域。目前主要有两种解决方法:
|
||||||
|
|
||||||
|
* 重复输入 `\n`(换行符)并在结尾添加 `#!html <div />`,直到窗口遮住模糊区域。
|
||||||
|
* 使用空路径或缺失的 `image` 路径,并调整长宽比(Aspect Ratio),直到窗口遮住模糊区域。
|
||||||
|
```
|
||||||
|
|
||||||
|
### introPopupMission
|
||||||
|
|
||||||
|
introPopupMission与 introPopupCareer几乎完全相同,但它需要手动定义按钮,而不是直接为按钮选择预设样式。
|
||||||
|
|
||||||
|
按钮样式组合为*bng-button-*`style`。内置的按钮样式包括:
|
||||||
|
|
||||||
|
- `main` - 橙色
|
||||||
|
- `secondary` - 青色
|
||||||
|
- `attention` - 红色
|
||||||
|
- `white` - 白色
|
||||||
|
- `link` - 半透明
|
||||||
|
- `outline` - 橙色轮廓
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger('introPopupMission', {
|
||||||
|
title = "introPopupMission title",
|
||||||
|
text = "introPopupMission description",
|
||||||
|
image = "/gameplay/tutorials/pages/template/image.jpg",
|
||||||
|
ratio = "16x9",
|
||||||
|
buttons = {
|
||||||
|
{ default=true, class="main", label="main button", clickLua="" },
|
||||||
|
{ default=false, class="secondary", label="secondary button", clickLua="" },
|
||||||
|
{ default=false, class="attention", label="attention button", clickLua="" },
|
||||||
|
{ default=false, class="white", label="white button", clickLua="" },
|
||||||
|
{ default=false, class="link", label="link button", clickLua="" },
|
||||||
|
{ default=false, class="outline", label="outline button", clickLua="" }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该Hook被多次触发,这些页面将合并到同一个弹出窗口中。<br>如果在一个introPopup处于活动状态时触发了该钩子,或者已经触发了另一种不同类型的 introPopup,则它会在当前窗口关闭后,通过一个独立的弹出窗口进行显示。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
背景模糊具有最小高度限制,这会导致内容较少的弹出窗口在其窗口下方出现多余的模糊区域。目前主要有两种解决方法:
|
||||||
|
|
||||||
|
* 重复输入 `\n`(换行符)并在结尾添加 `#!html <div />`,直到窗口拉长并遮住模糊区域。
|
||||||
|
* 使用空路径或缺失的 `image`(图像)路径,并调整长宽比(Aspect Ratio),直到窗口覆盖住模糊区域。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 对话窗口
|
||||||
|
|
||||||
|
todo
|
||||||
+232
-11
@@ -8,17 +8,19 @@
|
|||||||
这也可以在任何页面上完成。
|
这也可以在任何页面上完成。
|
||||||
```
|
```
|
||||||
|
|
||||||
# BeamNG.drive代码片段
|
# BeamNG.drive 代码的片段
|
||||||
|
|
||||||
## Lua代码片段
|
## Lua代码片段
|
||||||
|
|
||||||
### 绘制标记和车辆检测
|
### 世界
|
||||||
|
|
||||||
|
#### 绘制标记和车辆检测
|
||||||
|
|
||||||
在地图中绘制标记可能是向用户表明他们可以在那里进行某种形式的交互的最佳方式之一。
|
在地图中绘制标记可能是向用户表明他们可以在那里进行某种形式的交互的最佳方式之一。
|
||||||
|
|
||||||
绘制标记相当容易。以下是如何绘制公交车路线标记的示例:
|
绘制标记相当容易。以下是如何绘制公交车路线标记的示例:
|
||||||
|
|
||||||
```Lua
|
```lua
|
||||||
local function createBusMarker(markerName)
|
local function createBusMarker(markerName)
|
||||||
local marker = createObject('TSStatic')
|
local marker = createObject('TSStatic')
|
||||||
marker:setField('shapeName', 0, "art/shapes/interface/position_marker.dae")
|
marker:setField('shapeName', 0, "art/shapes/interface/position_marker.dae")
|
||||||
@@ -60,7 +62,7 @@
|
|||||||
|
|
||||||
以下是来自[BeamNG-FuelStations](https://github.com/BeamMP/BeamNG-FuelStations/tree/master)的自定义标记示例:
|
以下是来自[BeamNG-FuelStations](https://github.com/BeamMP/BeamNG-FuelStations/tree/master)的自定义标记示例:
|
||||||
|
|
||||||
```Lua
|
```lua
|
||||||
local stations = [
|
local stations = [
|
||||||
{ "location": [ -778.813, 485.973, 23.46 ], "type":"gas" },
|
{ "location": [ -778.813, 485.973, 23.46 ], "type":"gas" },
|
||||||
{ "location": [ 617.164, -192.107, 53.2 ], "type":"ev" },
|
{ "location": [ 617.164, -192.107, 53.2 ], "type":"ev" },
|
||||||
@@ -93,11 +95,11 @@
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### guihooks示例
|
### 用户界面
|
||||||
|
|
||||||
#### Toast通知,位于屏幕右上角
|
#### 屏幕右上角弹出的通知
|
||||||
|
|
||||||

|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
--guihooks.trigger('toastrMsg', {type, title, msg, config = {timeOut}})
|
--guihooks.trigger('toastrMsg', {type, title, msg, config = {timeOut}})
|
||||||
@@ -108,10 +110,13 @@ guihooks.trigger('toastrMsg', {type = "error", title = "Error Message:", msg = "
|
|||||||
|
|
||||||
#### 消息通知,消息应用程序中默认位于屏幕左上角
|
#### 消息通知,消息应用程序中默认位于屏幕左上角
|
||||||
|
|
||||||

|
这需要'Messages' 或 'Messages & Tasks' UI 插件。图标文件可以在以下路径中找到 `ui\ui-vue\src\assets\fonts\bngIcons\svg这需要'Messages' 或 'Messages & Tasks' UI 插件。图标文件可以在以下路径中找到
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
--guihooks.trigger('Message', {msg, ttl, category, icon}) --requires Messages app
|
--guihooks.trigger('Message', {msg, ttl, category, icon})
|
||||||
|
--ui_message(msg, ttl, category, icon)
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_upward", icon = "arrow_upward"})
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_upward", icon = "arrow_upward"})
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_downward", icon = "arrow_downward"})
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "arrow_downward", icon = "arrow_downward"})
|
||||||
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "flag", icon = "flag"})
|
guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "flag", icon = "flag"})
|
||||||
@@ -128,7 +133,9 @@ guihooks.trigger('Message', {msg = "Message Text Here", ttl = 5.0, category = "s
|
|||||||
|
|
||||||
#### 位于中心,大,小型短暂显示
|
#### 位于中心,大,小型短暂显示
|
||||||
|
|
||||||

|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
--guihooks.trigger('ScenarioFlashMessage', {{msg, ttl, sound, big}} ) -- requires RaceCountdown ui app
|
--guihooks.trigger('ScenarioFlashMessage', {{msg, ttl, sound, big}} ) -- requires RaceCountdown ui app
|
||||||
@@ -147,7 +154,9 @@ guihooks.trigger('ScenarioFlashMessage', {{"Teleported!", 3.0, "Engine.Audio.pla
|
|||||||
|
|
||||||
#### 位于中心,中型持续显示
|
#### 位于中心,中型持续显示
|
||||||
|
|
||||||

|
这需要 **“比赛实时显示 (Race Realtime Display)”** UI 插件。
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
--guihooks.trigger('ScenarioRealtimeDisplay', {msg = msg} ) -- requires Race Realtime Display ui app
|
--guihooks.trigger('ScenarioRealtimeDisplay', {msg = msg} ) -- requires Race Realtime Display ui app
|
||||||
@@ -157,6 +166,218 @@ guihooks.trigger('ScenarioRealtimeDisplay', {msg = "Message Text Here"} )
|
|||||||
guihooks.trigger('ScenarioRealtimeDisplay', {msg = ""} )
|
guihooks.trigger('ScenarioRealtimeDisplay', {msg = ""} )
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Confirmation Dialog
|
||||||
|
|
||||||
|
ConfirmationDialog是一种简单的弹出窗口,最多支持两个按钮。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- -- 打开一个包含标题、正文及最多两个按钮的Confirmation Dialog
|
||||||
|
guihooks.trigger("ConfirmationDialogOpen",
|
||||||
|
"Example Title",
|
||||||
|
"Example Body Text",
|
||||||
|
"Okay",
|
||||||
|
"", --gelua. empty string
|
||||||
|
"Cancel",
|
||||||
|
"" --gelua
|
||||||
|
)
|
||||||
|
|
||||||
|
-- 关闭任何具有指定标题且处于打开状态的确认对话框
|
||||||
|
guihooks.trigger("ConfirmationDialogClose", "Example Title")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
按钮的两个字段都必须是字符串,该按钮才能正常显示。
|
||||||
|
|
||||||
|
如果提供了Okay按钮,按下 *确定 / 主要动作 (OK / Primary action)*按键的效果等同于点击确定按钮。
|
||||||
|
|
||||||
|
如果提供了Cancel按钮,按下*菜单 (Menu)*按键的效果等同于点击取消按钮。
|
||||||
|
|
||||||
|
支持HTML格式,例如可以用来添加图像或图标。
|
||||||
|
|
||||||
|
可以同时显示多个,并将按顺序依次呈现。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
不提供任何按钮会导致玩家在不使用控制台的情况下无法退出该对话框。
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
当 **ConfirmationDialog**(确认对话框)处于活动状态时,小地图 (Minimap) UI 插件的 **SDF 部分** 依然保持可见。
|
||||||
|
|
||||||
|
可以使用 `#!lua guihooks.trigger('ShowApps', false)` 隐藏 UI 插件,作为一种临时性的补救方案。
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
#### introPopupTutorial
|
||||||
|
|
||||||
|
introPopupTutorial 是一种高度可定制的弹出窗口,其内容主要由嵌入式 HTML 定义。标准做法是从位于`/gameplay/tutorials/pages/*/content.html`的独立 HTML 文件中进行加载。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger("introPopupTutorial", {
|
||||||
|
{
|
||||||
|
content = readFile("/gameplay/tutorials/pages/template/content.html"):gsub("\r\n",""),
|
||||||
|
flavour = "onlyOk"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
Flavours控制显示的按钮类型。共有四种预设模式:
|
||||||
|
|
||||||
|
- `withLogbook`
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `onlyOk`
|
||||||
|
- Buttons: Okay
|
||||||
|
- `onlyLogbook`
|
||||||
|
- Buttons: Career Logbook
|
||||||
|
- `noButtons`
|
||||||
|
- Provides no buttons
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
当页面使用noButtons模式时,如果页面内容中未提供用于关闭弹出窗口的额外 JavaScript 代码,则会导致软锁定。在这种模式下,多个页面不会合并到同一个弹出窗口中。因此,不建议使用该模式。
|
||||||
|
```
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该hook被多次触发,这些页面将合并到同一个弹出窗口中。<br>如果在introPopup处于活动状态时触发钩子,或者已经触发了另一种类型的introPopup,则新内容将在现有弹出窗口关闭后,以独立的弹出窗口形式显示。
|
||||||
|
|
||||||
|
#### introPopupCareer
|
||||||
|
|
||||||
|
introPopupCareer是一种易于使用且具有高度开放性的弹出窗口,如有需要,它还支持嵌入 HTML 内容。
|
||||||
|
|
||||||
|
Flavours控制显示的按钮类型以及默认的图像宽高比。共有四种预设模式:
|
||||||
|
|
||||||
|
- `default`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Later, Okay
|
||||||
|
- `welcome`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `branch-info`
|
||||||
|
- Default image aspect ratio: 16x9
|
||||||
|
- Buttons: Career Logbook, Okay
|
||||||
|
- `garage`
|
||||||
|
- Buttons: Later, Okay
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger("introPopupCareer", {
|
||||||
|
{
|
||||||
|
title = "Example title",
|
||||||
|
text = "Example text",
|
||||||
|
image = "/gameplay/tutorials/pages/template/image.jpg",
|
||||||
|
ratio = "16x9",
|
||||||
|
flavour = "default"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown=""> !在BeamNG.drive中显示的introPopupCareer代码片段](../../assets/content/introPopupCareer.png) </figure>
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该hook被多次触发,这些页面将合并到同一个弹出窗口中。<br>如果在introPopup处于活动状态时触发了hook,或者已经触发了另一种类型的introPopup,则新内容将在当前弹出窗口关闭后,以独立的弹出窗口形式显示。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
背景模糊具有最小高度限制,这会导致内容较短的弹出窗口下方出现多余的模糊区域。目前主要有两种规避方案:
|
||||||
|
|
||||||
|
* 重复输入 `\n` 并以 `#!html <div />` 结尾,直到窗口完全覆盖模糊区域。
|
||||||
|
* 使用空路径或缺失的 `image` 路径,并调整宽高比(Aspect Ratio),直到窗口覆盖模糊区域。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### introPopupMission
|
||||||
|
|
||||||
|
introPopupMission与introPopupCareer几乎完全相同,但它需要手动定义按钮,而不是直接为按钮选择Flavour的预设模式。
|
||||||
|
|
||||||
|
按钮样式以 *bng-button-*`style` 的格式进行组合。内置的按钮样式包括:
|
||||||
|
|
||||||
|
- `main` - 橙色
|
||||||
|
- `secondary` - 青色
|
||||||
|
- `attention` - 红色
|
||||||
|
- `white` - 白色
|
||||||
|
- `link` - 半透明
|
||||||
|
- `outline` - 橙色轮廓
|
||||||
|
|
||||||
|
```lua
|
||||||
|
guihooks.trigger('introPopupMission', {
|
||||||
|
title = "introPopupMission title",
|
||||||
|
text = "introPopupMission description",
|
||||||
|
image = "/gameplay/tutorials/pages/template/image.jpg",
|
||||||
|
ratio = "16x9",
|
||||||
|
buttons = {
|
||||||
|
{ default=true, class="main", label="main button", clickLua="" },
|
||||||
|
{ default=false, class="secondary", label="secondary button", clickLua="" },
|
||||||
|
{ default=false, class="attention", label="attention button", clickLua="" },
|
||||||
|
{ default=false, class="white", label="white button", clickLua="" },
|
||||||
|
{ default=false, class="link", label="link button", clickLua="" },
|
||||||
|
{ default=false, class="outline", label="outline button", clickLua="" }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guihooks.trigger("introPopupClose")
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
如果提供了多个页面,或者该hook被多次触发,这些页面将合并到同一个弹出窗口中。<br>如果在introPopup处于活动状态时触发了hook,或者已经触发了另一种类型的introPopup,则新内容将在当前弹出窗口关闭后,以独立的弹出窗口形式显示。
|
||||||
|
|
||||||
|
!!! bug
|
||||||
|
|
||||||
|
```
|
||||||
|
背景模糊具有最小高度限制,这会导致内容较短的弹出窗口在其窗口下方出现多余的模糊区域。目前主要有两种规避方案:
|
||||||
|
|
||||||
|
* 重复使用 `\n` 并以 `#!html <div />` 结尾,直到窗口高度足以覆盖模糊区域。
|
||||||
|
* 使用空路径或缺失的 `image` 路径,并调整宽高比(Aspect Ratio),直到窗口完全覆盖模糊区域。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Dialogue
|
||||||
|
|
||||||
|
Dialogue被用于*A Rocky Start*活动中,用于显示有关任务的信息。它是一个居中且垂直对齐的弹出窗口,具有特定的布局。它不支持嵌入 HTML。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
ui_missionInfo.openDialogue({
|
||||||
|
title = "Dialogue title",
|
||||||
|
type = "Custom", -- isn't actually displayed
|
||||||
|
typeName = "typeName",
|
||||||
|
data = {
|
||||||
|
{label = "objective", value = "reward"}
|
||||||
|
-- add more...
|
||||||
|
},
|
||||||
|
buttons = {
|
||||||
|
{action = "accept", text = "Accept", cmd = ""},
|
||||||
|
{action = 'decline',text = "Decline", cmd = ""}
|
||||||
|
-- add more...
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ui_missionInfo.closeDialogue()
|
||||||
|
```
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:75%" markdown="">  </figure>
|
||||||
|
|
||||||
|
同时只能显示一个Dialogue。任何现有的Dialogue都会被直接覆盖。
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
```
|
||||||
|
`#!lua ui_missionInfo.closeDialogue()` 必须使用该函数来关闭对话框。
|
||||||
|
|
||||||
|
请确保在按下任何按钮时都调用此函数。
|
||||||
|
```
|
||||||
|
|
||||||
## IMGUI代码片段
|
## IMGUI代码片段
|
||||||
|
|
||||||
|
todo
|
||||||
|
|
||||||
## CEF UI代码片段
|
## CEF UI代码片段
|
||||||
|
|
||||||
|
todo
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
hide:
|
||||||
|
- 导航
|
||||||
|
---
|
||||||
|
|
||||||
|
# 欢迎来到BeamMP社区!
|
||||||
|
|
||||||
|
{width="450"} {width="450"}
|
||||||
|
|
||||||
|
## 我们的社交媒体链接
|
||||||
|
|
||||||
|
!!!failure ""
|
||||||
|
|
||||||
|
```
|
||||||
|
BeamMP Forum - [https://forum.beammp.com](https://forum.beammp.com)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!!quote ""
|
||||||
|
|
||||||
|
```
|
||||||
|
X (Twitter) - [https://x.com/BeamMPOfficial](https://x.com/BeamMPOfficial)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!!danger ""
|
||||||
|
|
||||||
|
```
|
||||||
|
YouTube - [https://www.youtube.com/@BeamMPOfficial](https://www.youtube.com/@BeamMPOfficial)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!!warning ""
|
||||||
|
|
||||||
|
```
|
||||||
|
Patreon - [https://www.patreon.com/c/BeamMP](https://www.patreon.com/c/BeamMP)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!!note ""
|
||||||
|
|
||||||
|
```
|
||||||
|
Discord - [https://discord.com/invite/beammp](https://discord.com/invite/beammp)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!!info ""
|
||||||
|
|
||||||
|
```
|
||||||
|
BlueSky - [https://bsky.app/profile/beammpofficial.bsky.social](https://bsky.app/profile/beammpofficial.bsky.social)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 我们的规则
|
||||||
|
|
||||||
|
你可以找到我们的规则 [这里](rules.md)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# 错误代码
|
||||||
|
|
||||||
|
此页包含启动程序可能显示的所有错误代码。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
代码 | 描述 | 可能的解决方案
|
||||||
|
--- | --- | ---
|
||||||
|
10048 | 其他东西占用了启动器端口 | 确保只运行了一个BeamMP-Launcher程序。或尝试重新启动电脑。
|
||||||
|
10038 / 10060 / 10061 | 在此指定的IP和/或端口上没有服务器应答 | 若您为服务器所有者,请前往[BeamMP-Server](https://docs.beammp.com/server/create-a-server)核验端口转发规则及防火墙策略;若非所有者,请尝试切换其他服务器或联系已知管理员协同排障。
|
||||||
|
10054 | 对方/服务器突然断开了连接 | 您正在连接的服务器已离线。
|
||||||
|
Failed to find the game please launch it. Report this if the issue persists code 3. | 启动器无法在注册表项中找到游戏信息(游戏目录,配置文件目录,版本等) | 至少运行一次游戏,以便创建注册表值。
|
||||||
|
Failed to find the game please launch it. Report this if the issue persists code 4. | 启动器无法从注册表项中读取游戏信息(游戏目录、配置文件目录、版本等) | 此错误最有可能出现在**盗版**游戏的用户中。如果你已经购买了游戏,至少运行一次,这样注册表值就会被创建。
|
||||||
|
Failed to Launch the game! launcher closing soon | 启动器无法找到游戏的可执行文件 | 在再次运行启动器之前,至少运行一次游戏。
|
||||||
|
Game Closed! launcher closing soon | 游戏关闭了 | 此消息将在游戏结束或游戏启动失败时出现。
|
||||||
|
Launcher Update failed! | 启动器未能下载新版本 | 检查您的互联网连接和防火墙/防病毒规则,让启动器没有被阻止。
|
||||||
|
Logger file init failed | 启动器缺乏文件创建权限 | 使用管理员身份运行启动器
|
||||||
|
Please close the game and try again | 游戏已经打开,启动器无法清除`multiplayer/mod `文件夹 | 关闭游戏并重试
|
||||||
|
Please launch the game at least once | 启动器尝试修改游戏目录但是失败了 | 在再次运行启动器之前,至少运行一次游戏。
|
||||||
|
Primary Servers Offline! Sorry for the inconvenience! | 启动器未能检查更新 | 检查你的互联网连接和防火墙规则。如果您没有问题,请查看我们Discord上的[BeamMP更新频道](https://discord.com/channels/601558901657305098/697596153943949352)。
|
||||||
|
Sorry Backend System Outage! Don't worry it will back on soon! | BeamMP后端没有响应 | 检查你的互联网连接和防火墙规则。如果您没有问题,请查看我们Discord上的[BeamMP更新频道](https://discord.com/channels/601558901657305098/697596153943949352)。
|
||||||
|
Stuck on updating | 启动器卡在更新上,不会继续下一步 | 以管理员身份运行启动器并检查反病毒规则,以确保启动器未被阻止。
|
||||||
|
|
||||||
|
如果启动器迅速“闪退”了,请检查安装BeamMP的文件夹中的` launcher .log`文件。
|
||||||
@@ -11,19 +11,23 @@ BeamMP将无法与盗版或过时版本的BeamNG.drive一起工作。
|
|||||||
BeamMP支持团队不提供盗版/过期副本问题的支持。
|
BeamMP支持团队不提供盗版/过期副本问题的支持。
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## **2. 安装**
|
## **2. 安装**
|
||||||
|
|
||||||
### **2a. Windows 安装**
|
### **2a. Windows 安装**
|
||||||
|
|
||||||
1. 访问[beammp.com](https://beammp.com/)并点击“Download Client”按钮。
|
!!!注意
|
||||||
2. 解压`BeamMP_Installer.zip`。
|
|
||||||
3. 运行`BeamMP_Installer.exe`并按照说明进行操作。
|
```
|
||||||
4. BeamMP启动器图标应将出现在您的桌面上。如果没有,只需在Windows搜索栏中搜索“BeamMP”即可。
|
截至 2026 年 4 月 1 日,Windows Defender SmartScreen 会将该 MSI 安装程序识别为“未知应用”。
|
||||||
5. 启动器运行后,您应该会看到一个终端窗口,随即 BeamNG.drive将自动运行。**请勿**关闭终端窗口。
|
|
||||||
6. BeamNG启动后,在主菜单中点击`Repository`按钮,确保`multiplayerbeammp`是**唯一启用**的mod。
|
若要跳过此警告,请点击“更多信息”,然后点击“仍要运行”。
|
||||||
7. 返回主菜单,点击“More..”和“多人模式”按钮开始多人模式。
|
```
|
||||||
8. 系统将提示您登录或以访客身份游玩(并非所有服务器都允许访客)。您可以在我们的[论坛](https://forum.beammp.com)上创建一个帐户,然后使用相同的凭据登录BeamMP。
|
|
||||||
9. 选择您感兴趣的任何服务器,然后点击`连接` 。尽情享受吧!
|
1. 前往 [beammp.com](https://beammp.com/) 然后点击“下载”按钮
|
||||||
|
2. 运行 `BeamMP_Installer.msi`安装程序并按照提示进行操作。
|
||||||
|
3. BeamMP启动器的图标应该会出现在您的桌面上。如果没有出现,只需在 Windows 搜索栏中搜索“BeamMP”即可。
|
||||||
|
|
||||||
!!!注意
|
!!!注意
|
||||||
|
|
||||||
@@ -66,10 +70,10 @@ export PATH=$VCPKG_ROOT:$PATH
|
|||||||
|
|
||||||
使用`git`将BeamMP-Launcher仓库克隆至本地,操作示例如下:`git clone https://github.com/BeamMP/BeamMP-Launcher.git`。[查看GitHub仓库克隆操作完整指南](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
|
使用`git`将BeamMP-Launcher仓库克隆至本地,操作示例如下:`git clone https://github.com/BeamMP/BeamMP-Launcher.git`。[查看GitHub仓库克隆操作完整指南](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
|
||||||
|
|
||||||
检出[最新发布版本](https://github.com/BeamMP/BeamMP-Launcher/releases/latest)所使用的标签。例如,若最新版本使用`v2.6.4`,则执行`git checkout v2.6.4`
|
|
||||||
|
|
||||||
如果你使用了我们提供的示例克隆命令,你可以使用以下命令进入项目的根目录: <br>`cd BeamMP-Launcher`
|
如果你使用了我们提供的示例克隆命令,你可以使用以下命令进入项目的根目录: <br>`cd BeamMP-Launcher`
|
||||||
|
|
||||||
|
查看用于 [最新发布版本](https://github.com/BeamMP/BeamMP-Launcher/releases/latest) 的标签(Tag)。例如,如果最新版本使用的是 `v2.8.0`,则执行命令:`git checkout v2.8.0`
|
||||||
|
|
||||||
在项目的根目录中,
|
在项目的根目录中,
|
||||||
|
|
||||||
1.
|
1.
|
||||||
@@ -135,9 +139,39 @@ cd ~/beammp-launcher
|
|||||||
若需在服务器列表(作为服务器自定义名称组成部分)或游戏内聊天中显示表情符号,您需部署包含表情符号的字形库。例如,可通过安装Windows Segoe UI 表情符号字体的 Linux 移植版实现。
|
若需在服务器列表(作为服务器自定义名称组成部分)或游戏内聊天中显示表情符号,您需部署包含表情符号的字形库。例如,可通过安装Windows Segoe UI 表情符号字体的 Linux 移植版实现。
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### **2d. 更新启动器**
|
||||||
|
|
||||||
|
如果您已经构建了启动器并想要对其进行更新:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export VCPKG_ROOT="$(pwd)/vcpkg"
|
||||||
|
cd BeamMP-Launcher
|
||||||
|
git fetch --tags
|
||||||
|
```
|
||||||
|
|
||||||
|
检出用于 [最新发布版本](https://github.com/BeamMP/BeamMP-Launcher/releases/latest) 的标签。例如,如果最新版本使用的是 `v2.8.0`,则执行 `git checkout v2.8.0`。
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B bin -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-linux
|
||||||
|
cmake --build bin --parallel
|
||||||
|
cp bin/BeamMP-Launcher ~/beammp-launcher/
|
||||||
|
cd ~/beammp-launcher
|
||||||
|
./BeamMP-Launcher
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **3. 已知的问题**
|
## **3. 使用BeamMP**
|
||||||
|
|
||||||
|
1. 启动程序后,您应该会看到一个终端窗口。紧接着,标准的 BeamNG 启动程序也会随之启动。**请勿**关闭该终端窗口。
|
||||||
|
2. 在 BeamNG.drive 的主菜单中,点击 `Repository(仓库)` 按钮,并检查确认 `multiplayerbeammp` 是 **唯一** 启用的插件(Mod)。
|
||||||
|
3. 返回主菜单,点击“More..”和“多人模式”按钮开始多人模式。
|
||||||
|
4. 系统将提示您登录或以访客身份游玩(并非所有服务器都允许访客)。您可以在我们的[论坛](https://forum.beammp.com)上创建一个帐户,然后使用相同的凭据登录BeamMP。
|
||||||
|
5. 选择您感兴趣的任何服务器,然后点击`连接` 。尽情享受吧!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 已知问题**
|
||||||
|
|
||||||
- 当前原生Linux版BeamMP启动器存在单会话限制:成功连接服务器并断开后需重启启动器。可通过热重载方案实现不关闭游戏进程的快速重启
|
- 当前原生Linux版BeamMP启动器存在单会话限制:成功连接服务器并断开后需重启启动器。可通过热重载方案实现不关闭游戏进程的快速重启
|
||||||
- 若未显示多人游戏按钮,请确认以下操作:<br>检查BeamMP模组是否已安装并在模组管理器中启用<br>尝试执行热重载快捷键 Ctrl + L
|
- 若未显示多人游戏按钮,请确认以下操作:<br>检查BeamMP模组是否已安装并在模组管理器中启用<br>尝试执行热重载快捷键 Ctrl + L
|
||||||
|
|||||||
@@ -0,0 +1,318 @@
|
|||||||
|
# 多人模式设置
|
||||||
|
|
||||||
|
## **1. 一般设置**
|
||||||
|
|
||||||
|
??? 设置 “显示高级选项”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,您将看到所有多人游戏设置
|
||||||
|
|
||||||
|
如果禁用,您将只看到基本的多人游戏设置
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “启用克隆保护”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,你生成的车辆配置将不会被其他玩家保存
|
||||||
|
|
||||||
|
如果禁用,你的衍生车辆配置可以被其他玩家保存
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “禁用因不稳定导致的暂停”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,物理不稳定性将不会导致游戏暂停
|
||||||
|
|
||||||
|
如果禁用,物理不稳定性将导致游戏暂停
|
||||||
|
|
||||||
|
!!! 注意 ""
|
||||||
|
|
||||||
|
建议设置为禁用,因为反复的不稳定会导致游戏崩溃
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “可用时使用简化车辆”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,游戏将会替换其他玩家的简化版车辆(来自AI流量)
|
||||||
|
|
||||||
|
如果禁用,游戏将使用预定的车辆模型
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “新聊天菜单”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,游戏内聊天将显示在[IMGUI](https://github.com/ocornut/imgui)窗口中,例如可以从游戏中拖出到另一个显示器上
|
||||||
|
|
||||||
|
如果禁用,游戏内聊天将显示在UI应用程序中
|
||||||
|
|
||||||
|
!!! 注意 ""
|
||||||
|
|
||||||
|
将IMGUI窗口拖出主游戏窗口可能会导致性能问题,还会诱使屏幕录制软件录制聊天窗口而不是主游戏窗口
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “启用车辆位置平滑”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,beamMP将使用算法平滑车辆位置更新到定期间隔。在ping值高的玩家之间,或者当一个连接经历了高包掉落率时,这会优化移动平滑性
|
||||||
|
|
||||||
|
如果禁用,beamMP将在接收到车辆位置时更新
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “跳过模组安全警告提示框”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,当试图用模组连接到服务器时,将不会显示模组安全弹出框
|
||||||
|
|
||||||
|
如果禁用,当你连接到一个带有模组的服务器时,就会显示模组安全弹出框
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “启用玩家车辆更新/编辑排队”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,其他玩家的车辆刷出和编辑将被放入队列。参见第2节。事件队列'获取更多详细信息
|
||||||
|
|
||||||
|
如果禁用,其他玩家的车辆刷出和编辑将立即被游戏加载
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “启用零件自动同步”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,你的车辆部件将在几秒钟后自动同步到其他玩家
|
||||||
|
|
||||||
|
如果禁用,您需要单击部件选择器中的部件同步按钮,以便将同步发送给其他播放器
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “禁止切换到其他玩家的车辆”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,点击车辆将跳过其他玩家的车辆
|
||||||
|
|
||||||
|
如果不启用,将会在每一个衍生的车辆上循环
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “车辆靠近时淡出”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,其他车辆会在靠近时淡出
|
||||||
|
|
||||||
|
如果禁用,其他车辆将保持完全可见,无论距离
|
||||||
|
|
||||||
|
!!! 注意 ""
|
||||||
|
|
||||||
|
这只会影响车辆的可见3d网格,而不会影响其物理节点-光束网格。为了禁用物理,你需要在游戏设置中启用“简化碰撞物理”
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “显示玩家ID”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,游戏内的玩家列表将增加一行,显示每个玩家的 ID。这对于开发或管理很有用。
|
||||||
|
|
||||||
|
如果禁用,游戏内的玩家列表将仅显示玩家名称和延迟这两列。
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “允许游戏内服务器列表刷新”
|
||||||
|
|
||||||
|
```
|
||||||
|
若启用此功能,游戏过程中服务器列表将按固定时间间隔自动更新。此操作可能导致游戏卡顿现象发生。
|
||||||
|
|
||||||
|
若禁用此功能,服务器列表仅会在打开主菜单界面时更新一次。
|
||||||
|
```
|
||||||
|
|
||||||
|
## **2. 事件队列**
|
||||||
|
|
||||||
|
??? 设置 “高亮显示队列玩家”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,具有队列事件的玩家将在游戏玩家列表中突出显示
|
||||||
|
|
||||||
|
如果禁用,玩家将不会单独突出显示
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "应用车辆更改"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果设置为“鼠标左键”,使用鼠标左键点击玩家列表中的玩家名字将加载队列事件。用鼠标右键点击将观看该玩家
|
||||||
|
|
||||||
|
如果设置为“鼠标右键”,使用鼠标右键点击玩家列表中的玩家名字将加载队列事件。用鼠标左键点击将观看该玩家
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “自动应用队列车辆变更”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用了该功能,那么一旦低于设定为超时的速度阈值,就会自动加载队列的事件
|
||||||
|
|
||||||
|
如果禁用,队列事件将只能手动加载,通过点击屏幕顶部的“事件”按钮或玩家列表中的玩家名称
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “队列应用速度阈值”
|
||||||
|
|
||||||
|
```
|
||||||
|
本设定值定义了自动加载事件队列的速度阈值。为使队列事件成功加载,车辆必须持续低于该设定时速且超过"队列应用超时"的持续时长
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “队列应用超时”
|
||||||
|
|
||||||
|
```
|
||||||
|
此设定值定义自动事件队列加载的时间延迟。为了加载排队的事件,您的车辆必须比“队列应用速度阈值”慢
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “观看他人时跳过队列”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,如果您正在观看其他玩家,则会立即加载事件
|
||||||
|
|
||||||
|
如果被禁用,一个事件将被排队,就像它在你自己的车辆上一样
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 “不要排队独轮车(Snowmen/Beamlings)”
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,有关Snowmen/Beamlings的事件将立即加载
|
||||||
|
|
||||||
|
如果禁用,Snowmen/Beamlings将像其他车辆一样排队
|
||||||
|
```
|
||||||
|
|
||||||
|
## **3. 设置默认Unicyle**
|
||||||
|
|
||||||
|
??? 设置 "默认 Unicycle 配置文件"
|
||||||
|
|
||||||
|
```
|
||||||
|
该配置项用于定义默认加载的独轮车类型。您既可以选择预设配置,若已保存自定义独轮车配置,也可选用自有配置。
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置“自动保存上次使用的Unicyle”
|
||||||
|
|
||||||
|
```
|
||||||
|
启用状态最近使用的独轮车配置将被自动保存,并在下次生成时直接加载
|
||||||
|
禁用状态始终使用默认配置生成独轮车
|
||||||
|
```
|
||||||
|
|
||||||
|
## **4. 物理节点**
|
||||||
|
|
||||||
|
??? 设置 "启用未生成载具的物理节点"
|
||||||
|
|
||||||
|
```
|
||||||
|
启用时,未生成载具显示定位球体
|
||||||
|
禁用时完全隐藏
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "调整颜色"
|
||||||
|
|
||||||
|
```
|
||||||
|
??? 设置 "可见"
|
||||||
|
|
||||||
|
如果启用,将绘制一个节点,使用下面的颜色
|
||||||
|
如果禁用,则不会为指定的函数绘制节点
|
||||||
|
??? 设置 "RGB HEX 值"
|
||||||
|
|
||||||
|
队列车辆:当车辆队列等待刷出时,斑点将使用的颜色。标准值#FF6400
|
||||||
|
|
||||||
|
非法车辆:如果车辆是非法的,例如通过侧面加载的mod, blob将使用的颜色。标准值#000000
|
||||||
|
|
||||||
|
已删除的车辆:如果用户删除了车辆,blob将使用的颜色。标准值#333333
|
||||||
|
```
|
||||||
|
|
||||||
|
## **5. 昵称标签**
|
||||||
|
|
||||||
|
??? 设置 "隐藏玩家昵称标签"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,将不会绘制玩家的昵称标签
|
||||||
|
|
||||||
|
如果禁用,玩家的名字将根据他们车辆的相对位置绘制
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "显示与其他玩家的距离"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,将在昵称标签前面加上到相应车辆的距离
|
||||||
|
|
||||||
|
如果禁用,则不会在标签中显示额外的距离
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "淡入/淡出昵称标签"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,标签将根据“淡出距离”和“反转标签淡出方向”淡出。
|
||||||
|
|
||||||
|
如果禁用,则无论与相应车辆的距离如何,都将以标准不透明度绘制图像
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "淡出距离/反转标签淡出方向"
|
||||||
|
|
||||||
|
```
|
||||||
|
!!! 设置 "淡出"
|
||||||
|
|
||||||
|
玩家离得越远,标签就越不显眼
|
||||||
|
|
||||||
|
'渐变距离'定义了标签在最小不透明度下绘制的距离
|
||||||
|
|
||||||
|
!!! 设置 "淡入"
|
||||||
|
|
||||||
|
玩家离得越远,标签就越显眼
|
||||||
|
|
||||||
|
'渐变距离'定义了标签在最大不透明度下绘制的距离
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "不要完全隐藏姓名标签"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,一个标签不能完全不可见,它将保留一个最小的不透明度,无论距离
|
||||||
|
|
||||||
|
如果禁用,昵称标签可以完全不可见
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "缩短昵称标签和角色标签"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,‘ Nametag length limit ’将截断昵称标签和角色到设置的字符限制
|
||||||
|
|
||||||
|
如果禁用,名称标签和角色标签将以完整的长度显示
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "在车辆标签下显示观众的标签"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,观众的名字将被添加到玩家的姓名标签下面
|
||||||
|
|
||||||
|
如果禁用,没有观众的名字会被添加到标签
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "观众昵称标签颜色相同"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,观众的名字将始终被灰色背景包围
|
||||||
|
|
||||||
|
如果禁用,观众的名字将被彩色背景包围,以突出观众的角色
|
||||||
|
```
|
||||||
|
|
||||||
|
## **6. 其他**
|
||||||
|
|
||||||
|
??? 设置 "在控制台中显示网络活动"
|
||||||
|
|
||||||
|
```
|
||||||
|
如果启用,则将在控制台中显示beamMP网络活动
|
||||||
|
|
||||||
|
如果禁用,则控制台中不会显示进一步的网络活动
|
||||||
|
!!! 风险 ""
|
||||||
|
|
||||||
|
要小心这个设置,因为所有控制台输出也会写入日志文件
|
||||||
|
|
||||||
|
启用此设置后,它们可以在几分钟内增长数百MB
|
||||||
|
```
|
||||||
|
|
||||||
|
??? 设置 "启动器端口"
|
||||||
|
|
||||||
|
```
|
||||||
|
此设定值定义用于与启动器通信的端口
|
||||||
|
|
||||||
|
只有标准端口4444不能使用时才需要更改吗
|
||||||
|
|
||||||
|
不要忘记在启动器侧修改它,通过修改‘ launcher.cfg ’
|
||||||
|
|
||||||
|
!!! 提示 ""
|
||||||
|
|
||||||
|
指定的端口只是两个中的第一个,第二个正在使用的端口紧随其后,设置port + 1
|
||||||
|
|
||||||
|
第一个端口携带核心网络数据包,第二个端口携带游戏网络数据包,两者都通过TCP传输
|
||||||
|
```
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: 指南
|
||||||
|
description: 这组页面为BeamMP提供了一些基本指南
|
||||||
|
status: 新的
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! 警告"这个网站正在建设中!"
|
||||||
|
|
||||||
|
```
|
||||||
|
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,36 @@
|
|||||||
|
---
|
||||||
|
hide:
|
||||||
|
- 导航
|
||||||
|
---
|
||||||
|
|
||||||
|
!!!警告“该网站正在建设当中!“
|
||||||
|
|
||||||
|
```
|
||||||
|
这个网站正在积极建设中。
|
||||||
|
|
||||||
|
觉得你能帮上忙吗?请用铅笔在右侧点击页面!
|
||||||
|
|
||||||
|
这也可以在任何页面上完成。
|
||||||
|
```
|
||||||
|
|
||||||
|
# 欢迎来到BeamMP文档!:tada:
|
||||||
|
|
||||||
|
欢迎来到全新改进的BeamMP文档中心!无论您是玩家,服主,还是开发者,我们都能为您提供增强BeamNG.drive多人游戏体验所需的资源。
|
||||||
|
|
||||||
|
## 对于玩家
|
||||||
|
|
||||||
|
首次体验BeamMP联机模组?请访问我们的[新手启航指南](../game/getting-started.md),助您迅速完成配置部署,畅享多人模式下的高拟真驾驶盛宴。若遇基础性问题,建议优先查阅[玩家常见问题解答](../FAQ/player-faq.md)中的故障排查方案
|
||||||
|
|
||||||
|
## 对于服主
|
||||||
|
|
||||||
|
考虑创建专属BeamMP服务器?我们的[完整指南](../server/create-a-server.md)将逐步指导您完成整个流程,确保您掌握所需工具和知识,助您高效搭建服务器
|
||||||
|
|
||||||
|
## 对于开发者
|
||||||
|
|
||||||
|
想要了解如何为BeamMP服务器创建资源?请查看我们的[资源开发指南](../guides/mod-creation/server/getting-started.md),获取完整的功能实现指引。
|
||||||
|
|
||||||
|
令人兴奋的更新即将推出,包括旨在增强您的浏览体验的全新主页。请继续关注!:slight_smile:
|
||||||
|
|
||||||
|
## 社区规则
|
||||||
|
|
||||||
|
请仔细查阅BeamMP [社区规则](https://docs.beammp.com/community/rules/)及封禁申诉流程说明。
|
||||||
@@ -243,7 +243,7 @@ print(mytimer:GetCurrent()) -- print how much time elapsed
|
|||||||
|
|
||||||
#### `MP.GetServerVersion() -> number,number,number`
|
#### `MP.GetServerVersion() -> number,number,number`
|
||||||
|
|
||||||
以主要、次要、补丁格式返回当前服务器版本。例如,v3.0.0版本将返回` 3,0,0 `。
|
以主要、次要、补丁格式返回当前服务器版本。例如,v3.0.0版本将返回`3,0,0`。
|
||||||
|
|
||||||
范例:
|
范例:
|
||||||
|
|
||||||
@@ -336,7 +336,7 @@ print(Results)
|
|||||||
- `IsDone() -> boolean` 会告知您所有处理程序是否已完成。还可以通过检查它的`MP.Sleep`-来等待变为True
|
- `IsDone() -> boolean` 会告知您所有处理程序是否已完成。还可以通过检查它的`MP.Sleep`-来等待变为True
|
||||||
- `GetResults() -> table` 返回一个未注释且未命名的表,其中包含所有处理程序的所有返回值,这是一个数组
|
- `GetResults() -> table` 返回一个未注释且未命名的表,其中包含所有处理程序的所有返回值,这是一个数组
|
||||||
|
|
||||||
一定要用`Obj:Function()` 语法 (`:`, 不要 `.`).
|
一定要用`Obj:Function()` 语法 (`:`, 不要 `.`).
|
||||||
|
|
||||||
范例:
|
范例:
|
||||||
|
|
||||||
@@ -1221,13 +1221,422 @@ MP.RegisterEvent("onPlayerAuth", "myPlayerAuthorizer")
|
|||||||
|
|
||||||
参数: `player_id: number`, `vehicle_id: number`, `data: string` 可取消: YES
|
参数: `player_id: number`, `vehicle_id: number`, `data: string` 可取消: YES
|
||||||
|
|
||||||
当玩家生成一辆新车辆时触发。参数 `data`包含该车辆的配置,以及位置和旋转等信息,格式为 JSON 字符串。
|
当玩家生成一辆新车辆时触发。请注意,车辆切换/替换则会触发 [`onVehicleEdited`](#onvehicleedited)。<br>`data` 参数包含该车辆的配置以及位置/旋转数据,并以 JSON 字符串形式提供。
|
||||||
|
|
||||||
|
<details>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<summary><code>data</code> 值示例</summary>
|
||||||
|
|
||||||
|
该数据字符串以一个唯一的车辆标识符开头,其格式为玩家 ID、一个连字符,以及车辆 ID。随后是一个 JSON 对象,其中包含车辆的配置信息以及位置数据。
|
||||||
|
|
||||||
|
```
|
||||||
|
0-0: {
|
||||||
|
"abs": "realistic",
|
||||||
|
"ign": 3,
|
||||||
|
"jbm": "van",
|
||||||
|
"pid": 0,
|
||||||
|
"pos": [
|
||||||
|
907.93902587891,
|
||||||
|
773.50201416016,
|
||||||
|
238.87800598145
|
||||||
|
],
|
||||||
|
"pro": "0",
|
||||||
|
"rot": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0.99999994039536,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"vcf": {
|
||||||
|
"licenseName": "H30 9VV",
|
||||||
|
"mainPartName": "van",
|
||||||
|
"mainPartPath": "/van",
|
||||||
|
"model": "van",
|
||||||
|
"paints": [
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.21999999880791,
|
||||||
|
0.37000000476837003,
|
||||||
|
0.33000001311302,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.62300002574921,
|
||||||
|
0.62300002574921,
|
||||||
|
0.62300002574921,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0.80000001192093,
|
||||||
|
"clearcoatRoughness": 0.070000000298023,
|
||||||
|
"metallic": 0.80000001192093,
|
||||||
|
"roughness": 0.64999997615814
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.21999999880791,
|
||||||
|
0.37000000476837003,
|
||||||
|
0.33000001311302,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"partConfigFilename": "vehicles/van/h15_xt_passenger.pc",
|
||||||
|
"parts": {
|
||||||
|
"brakepad_F": "brakepad_F_premium",
|
||||||
|
"brakepad_R": "brakepad_R_premium",
|
||||||
|
"gps": "",
|
||||||
|
"licenseplate_design_2_1": "",
|
||||||
|
"linelock": "",
|
||||||
|
"load_seat_FR": "",
|
||||||
|
"n2o_system": "",
|
||||||
|
"paint_design": "van_skin_twotone",
|
||||||
|
"pickup_engine_v8_ecu": "pickup_engine_v8_ecu",
|
||||||
|
"pickup_engine_v8_internals": "pickup_engine_v8_internals",
|
||||||
|
"pickup_enginemounts": "pickup_enginemounts",
|
||||||
|
"pickup_oilpan_v8": "pickup_oilpan_v8",
|
||||||
|
"pickup_reversewarn": "",
|
||||||
|
"pickup_sparetire": "pickup_sparetire_5l",
|
||||||
|
"pickup_towhitch": "",
|
||||||
|
"skin_glass": "van_skin_glass_tint",
|
||||||
|
"skin_interior": "van_skin_interior_black",
|
||||||
|
"soundscape_horn": "soundscape_horn_115",
|
||||||
|
"tire_F_16x7_alt": "tire_F_225_75_16_alt_standard",
|
||||||
|
"tire_R_16x7_alt": "tire_R_225_75_16_alt_standard",
|
||||||
|
"van_ABS": "van_ABS",
|
||||||
|
"van_ESC": "",
|
||||||
|
"van_ac": "van_ac",
|
||||||
|
"van_body": "van_body_passenger",
|
||||||
|
"van_brake_F": "van_brake_F",
|
||||||
|
"van_brake_R": "van_brake_R_drum",
|
||||||
|
"van_bumper_F": "van_bumper_F_altb",
|
||||||
|
"van_bumper_F_lip": "",
|
||||||
|
"van_bumper_R": "van_bumper_R_altb",
|
||||||
|
"van_bumper_accessory_F": "",
|
||||||
|
"van_bumpersignal_FL": "van_bumpersignal_FL",
|
||||||
|
"van_bumpersignal_FR": "van_bumpersignal_FR",
|
||||||
|
"van_coilover_IFS": "van_coilover_IFS",
|
||||||
|
"van_converter": "van_converter",
|
||||||
|
"van_differential_F": "",
|
||||||
|
"van_differential_R": "van_differential_R",
|
||||||
|
"van_door_FL": "van_door_FL",
|
||||||
|
"van_door_FR": "van_door_FR",
|
||||||
|
"van_doordetent_FL": "van_doordetent_FL",
|
||||||
|
"van_doordetent_FR": "van_doordetent_FR",
|
||||||
|
"van_doordetent_RL": "van_doordetent_RL",
|
||||||
|
"van_doordetent_RR": "van_doordetent_RR",
|
||||||
|
"van_doorglass_L": "van_doorglass_L",
|
||||||
|
"van_doorglass_R": "van_doorglass_R",
|
||||||
|
"van_doorpanel_FL": "van_doorpanel_FL",
|
||||||
|
"van_doorpanel_FR": "van_doorpanel_FR",
|
||||||
|
"van_driveshaft_R": "van_driveshaft_R",
|
||||||
|
"van_engine": "van_engine_v8_4.5",
|
||||||
|
"van_exhaust_v8": "van_exhaust_v8",
|
||||||
|
"van_fascia_F": "van_fascia_F_high",
|
||||||
|
"van_fender_L": "van_fender_L",
|
||||||
|
"van_fender_R": "van_fender_R",
|
||||||
|
"van_fenderflare_FL": "",
|
||||||
|
"van_fenderflare_FR": "",
|
||||||
|
"van_fenderflare_RL": "",
|
||||||
|
"van_fenderflare_RR_sidedoor": "",
|
||||||
|
"van_finaldrive_R": "van_finaldrive_R_355",
|
||||||
|
"van_frame": "van_frame",
|
||||||
|
"van_fueltank": "van_fueltank",
|
||||||
|
"van_header": "van_exhmanifold",
|
||||||
|
"van_headlight_L_high": "van_headlight_L_high",
|
||||||
|
"van_headlight_R_high": "van_headlight_R_high",
|
||||||
|
"van_hood": "van_hood",
|
||||||
|
"van_hub_F": "van_hub_F_5",
|
||||||
|
"van_hub_R": "van_hub_R_5",
|
||||||
|
"van_intake_v8": "van_intake_v8",
|
||||||
|
"van_intcarpet_roof": "van_intcarpet_roof",
|
||||||
|
"van_interior": "van_interior",
|
||||||
|
"van_lettering_doors_F": "van_lettering_doors_F_h15",
|
||||||
|
"van_lettering_reardoor_L": "van_lettering_gavril_reardoor_L",
|
||||||
|
"van_lettering_reardoor_R": "van_lettering_h15_xt_reardoor_R",
|
||||||
|
"van_licenseplate_F": "van_licenseplate_F",
|
||||||
|
"van_licenseplate_R": "van_licenseplate_R",
|
||||||
|
"van_lightbar": "",
|
||||||
|
"van_mirror_L": "van_mirror_L",
|
||||||
|
"van_mirror_R": "van_mirror_R",
|
||||||
|
"van_mod": "",
|
||||||
|
"van_muffler": "van_muffler",
|
||||||
|
"van_power_steering": "",
|
||||||
|
"van_radiator": "van_radiator",
|
||||||
|
"van_radio": "van_radio",
|
||||||
|
"van_reardoor_L": "van_reardoor_L",
|
||||||
|
"van_reardoor_R": "van_reardoor_R",
|
||||||
|
"van_reardoorglass_L": "van_reardoorglass_L",
|
||||||
|
"van_reardoorglass_R": "van_reardoorglass_R",
|
||||||
|
"van_reardoorpanel_L": "van_reardoorpanel_L",
|
||||||
|
"van_reardoorpanel_R": "van_reardoorpanel_R",
|
||||||
|
"van_rollcage": "",
|
||||||
|
"van_roof": "van_roof",
|
||||||
|
"van_roof_accessory": "",
|
||||||
|
"van_runningboard": "",
|
||||||
|
"van_seat_1R": "van_seat_1R",
|
||||||
|
"van_seat_2R": "van_seat_2R",
|
||||||
|
"van_seat_3R": "van_seat_3R",
|
||||||
|
"van_seat_FL": "van_seat_FL",
|
||||||
|
"van_seat_FR": "van_seat_FR",
|
||||||
|
"van_shifter": "van_shifter_A",
|
||||||
|
"van_shock_R": "van_shock_R",
|
||||||
|
"van_sidedoor_FR": "van_sidedoor_FR_alt",
|
||||||
|
"van_sidedoor_RR": "van_sidedoor_RR_alt",
|
||||||
|
"van_sidedoorglass_FR": "van_sidedoorglass_FR",
|
||||||
|
"van_sidedoorglass_RR": "van_sidedoorglass_RR",
|
||||||
|
"van_sidedoorpanel_FR": "van_sidedoorpanel_FR",
|
||||||
|
"van_sidedoorpanel_RR": "van_sidedoorpanel_RR",
|
||||||
|
"van_sideglass_FL": "van_sideglass_FL",
|
||||||
|
"van_sideglass_ML": "van_sideglass_ML",
|
||||||
|
"van_sideglass_RL": "van_sideglass_RL",
|
||||||
|
"van_sideglass_RR": "van_sideglass_RR",
|
||||||
|
"van_snorkel": "",
|
||||||
|
"van_spring_R": "van_spring_R",
|
||||||
|
"van_steer": "van_steer",
|
||||||
|
"van_steering": "van_steering",
|
||||||
|
"van_suspension_F": "van_IFS",
|
||||||
|
"van_suspension_R": "van_axle_R",
|
||||||
|
"van_swaybar_F": "van_swaybar_F",
|
||||||
|
"van_swaybar_R": "",
|
||||||
|
"van_taillight_L": "van_taillight_L",
|
||||||
|
"van_taillight_R": "van_taillight_R",
|
||||||
|
"van_taillightguard_L": "",
|
||||||
|
"van_taillightguard_R": "",
|
||||||
|
"van_transfer_case": "van_transfer_case_RWD",
|
||||||
|
"van_transmission": "van_transmission_4A",
|
||||||
|
"van_tubs": "van_tubs",
|
||||||
|
"van_valance_F": "van_valance_F",
|
||||||
|
"van_wheeldata_F": "van_wheeldata_F",
|
||||||
|
"van_wheeldata_R": "van_wheeldata_R",
|
||||||
|
"van_windshield": "van_windshield",
|
||||||
|
"wheel_F_5": "wheel_25a_16x7_5_F",
|
||||||
|
"wheel_R_5": "wheel_25a_16x7_5_R"
|
||||||
|
},
|
||||||
|
"vars": {}
|
||||||
|
},
|
||||||
|
"vid": 29339
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### `onVehicleEdited`
|
##### `onVehicleEdited`
|
||||||
|
|
||||||
参数: `player_id: number`, `vehicle_id: number`, `data: string` 可取消: YES
|
参数: `player_id: number`, `vehicle_id: number`, `data: string` 可取消: YES
|
||||||
|
|
||||||
当玩家编辑并应用其车辆修改时触发。参数 `data` 包含车辆更新后的配置,格式为 JSON 字符串, 但 **不**包含位置或旋转数据。你可以使用 [MP.GetPositionRaw](#mpgetpositionrawpid-number-vid-number-tablestring) 来获取位置和旋转数据。
|
当玩家编辑或替换其车辆时触发。`data` 参数包含车辆更新后的配置,并以 JSON 字符串形式提供,但 **不** 包含位置或旋转数据。<br>你可以使用 [MP.GetPositionRaw](#mpgetpositionrawpid-number-vid-number-tablestring) 来获取位置与旋转数据。
|
||||||
|
|
||||||
|
<details>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<summary><code>data</code> 值示例</summary>
|
||||||
|
|
||||||
|
该数据字符串以一个唯一的车辆标识符开头,其格式为玩家 ID、一个连字符,以及车辆 ID。随后是一个 JSON 对象,其中包含车辆配置信息。
|
||||||
|
|
||||||
|
```
|
||||||
|
0-0: {
|
||||||
|
"abs": "realistic",
|
||||||
|
"ign": 3,
|
||||||
|
"jbm": "van",
|
||||||
|
"pid": 0,
|
||||||
|
"pro": "0",
|
||||||
|
"vcf": {
|
||||||
|
"licenseName": "P60 1EP",
|
||||||
|
"mainPartName": "van",
|
||||||
|
"mainPartPath": "/van",
|
||||||
|
"model": "van",
|
||||||
|
"paints": [
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"baseColor": [
|
||||||
|
0.40000000596046,
|
||||||
|
0.050000000745058,
|
||||||
|
0.050000000745058,
|
||||||
|
1.2000000476837
|
||||||
|
],
|
||||||
|
"clearcoat": 0,
|
||||||
|
"clearcoatRoughness": 0,
|
||||||
|
"metallic": 0,
|
||||||
|
"roughness": 0.070000000298023
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"partConfigFilename": "vehicles/van/h15_passenger.pc",
|
||||||
|
"parts": {
|
||||||
|
"brakepad_F": "brakepad_F_premium",
|
||||||
|
"brakepad_R": "brakepad_R_premium",
|
||||||
|
"gps": "",
|
||||||
|
"hubcap_F_16": "hubcap_09c_F_altd",
|
||||||
|
"hubcap_R_16": "hubcap_09c_R_altd",
|
||||||
|
"licenseplate_design_2_1": "",
|
||||||
|
"linelock": "",
|
||||||
|
"load_seat_FR": "",
|
||||||
|
"n2o_system": "",
|
||||||
|
"paint_design": "",
|
||||||
|
"pickup_engine_v8_ecu": "pickup_engine_v8_ecu_late",
|
||||||
|
"pickup_engine_v8_internals": "pickup_engine_v8_internals",
|
||||||
|
"pickup_enginemounts": "pickup_enginemounts",
|
||||||
|
"pickup_oilpan_v8": "pickup_oilpan_v8",
|
||||||
|
"pickup_reversewarn": "",
|
||||||
|
"pickup_sparetire": "pickup_sparetire_6l",
|
||||||
|
"pickup_towhitch": "",
|
||||||
|
"skin_glass": "",
|
||||||
|
"skin_interior": "van_skin_interior_ivory",
|
||||||
|
"soundscape_horn": "soundscape_horn_115",
|
||||||
|
"tire_F_16x7_alt": "tire_F_225_75_16_alt_standard",
|
||||||
|
"tire_R_16x7_alt": "tire_R_225_75_16_alt_standard",
|
||||||
|
"trimring_F_16x7": "",
|
||||||
|
"trimring_R_16x7": "",
|
||||||
|
"van_ABS": "van_ABS",
|
||||||
|
"van_ac": "van_ac",
|
||||||
|
"van_body": "van_body_passenger",
|
||||||
|
"van_brake_F": "van_brake_F",
|
||||||
|
"van_brake_R": "van_brake_R",
|
||||||
|
"van_bumper_accessory_F_late": "",
|
||||||
|
"van_bumper_F": "van_bumper_F_late_alt",
|
||||||
|
"van_bumper_F_lip_late": "",
|
||||||
|
"van_bumper_R": "van_bumper_R_late_alt",
|
||||||
|
"van_coilover_IFS": "van_coilover_IFS",
|
||||||
|
"van_converter": "van_converter",
|
||||||
|
"van_differential_F": "",
|
||||||
|
"van_differential_R": "van_differential_R",
|
||||||
|
"van_door_FL": "van_door_FL",
|
||||||
|
"van_door_FR": "van_door_FR",
|
||||||
|
"van_doordetent_FL": "van_doordetent_FL",
|
||||||
|
"van_doordetent_FR": "van_doordetent_FR",
|
||||||
|
"van_doordetent_RL": "van_doordetent_RL",
|
||||||
|
"van_doordetent_RR": "van_doordetent_RR",
|
||||||
|
"van_doorglass_L": "van_doorglass_L",
|
||||||
|
"van_doorglass_R": "van_doorglass_R",
|
||||||
|
"van_doorpanel_FL": "van_doorpanel_FL",
|
||||||
|
"van_doorpanel_FR": "van_doorpanel_FR",
|
||||||
|
"van_driveshaft_R": "van_driveshaft_R",
|
||||||
|
"van_engine": "van_engine_v8_4.5",
|
||||||
|
"van_ESC": "van_ESC",
|
||||||
|
"van_exhaust_v8": "van_exhaust_v8",
|
||||||
|
"van_fascia_F": "van_fascia_F_late",
|
||||||
|
"van_fender_L": "van_fender_L",
|
||||||
|
"van_fender_R": "van_fender_R",
|
||||||
|
"van_fenderflare_FL": "",
|
||||||
|
"van_fenderflare_FR": "",
|
||||||
|
"van_fenderflare_RL": "",
|
||||||
|
"van_fenderflare_RR_sidedoor": "",
|
||||||
|
"van_finaldrive_R": "van_finaldrive_R_355",
|
||||||
|
"van_frame": "van_frame",
|
||||||
|
"van_fueltank": "van_fueltank",
|
||||||
|
"van_grille_F_late": "van_grille_F_late",
|
||||||
|
"van_header": "van_exhmanifold",
|
||||||
|
"van_headlight_L_late": "van_headlight_L_late",
|
||||||
|
"van_headlight_R_late": "van_headlight_R_late",
|
||||||
|
"van_hood": "van_hood_late",
|
||||||
|
"van_hub_F": "van_hub_F_6",
|
||||||
|
"van_hub_R": "van_hub_R_6",
|
||||||
|
"van_intake_v8": "van_intake_v8_late",
|
||||||
|
"van_intcarpet_roof": "van_intcarpet_roof",
|
||||||
|
"van_interior": "van_interior",
|
||||||
|
"van_lettering_doors_F": "van_lettering_doors_F_h15",
|
||||||
|
"van_lettering_reardoor_L": "van_lettering_gavril_reardoor_L",
|
||||||
|
"van_lettering_reardoor_R": "van_lettering_h15_reardoor_R",
|
||||||
|
"van_licenseplate_F_late": "van_licenseplate_F_late",
|
||||||
|
"van_licenseplate_R_late": "van_licenseplate_R_late",
|
||||||
|
"van_lightbar": "",
|
||||||
|
"van_mirror_L": "van_mirror_L",
|
||||||
|
"van_mirror_R": "van_mirror_R",
|
||||||
|
"van_mod": "",
|
||||||
|
"van_muffler": "van_muffler",
|
||||||
|
"van_power_steering": "",
|
||||||
|
"van_radiator": "van_radiator",
|
||||||
|
"van_radio": "van_radio",
|
||||||
|
"van_reardoor_L": "van_reardoor_L",
|
||||||
|
"van_reardoor_R": "van_reardoor_R",
|
||||||
|
"van_reardoorglass_L": "van_reardoorglass_L",
|
||||||
|
"van_reardoorglass_R": "van_reardoorglass_R",
|
||||||
|
"van_reardoorpanel_L": "van_reardoorpanel_L",
|
||||||
|
"van_reardoorpanel_R": "van_reardoorpanel_R",
|
||||||
|
"van_rollcage": "",
|
||||||
|
"van_roof": "van_roof",
|
||||||
|
"van_roof_accessory": "",
|
||||||
|
"van_runningboard": "",
|
||||||
|
"van_seat_1R": "van_seat_1R",
|
||||||
|
"van_seat_2R": "van_seat_2R",
|
||||||
|
"van_seat_3R": "van_seat_3R",
|
||||||
|
"van_seat_FL": "van_seat_FL",
|
||||||
|
"van_seat_FR": "van_seat_FR",
|
||||||
|
"van_shifter": "van_shifter_A",
|
||||||
|
"van_shock_R": "van_shock_R",
|
||||||
|
"van_sidedoor_FR": "van_sidedoor_FR_alt",
|
||||||
|
"van_sidedoor_RR": "van_sidedoor_RR_alt",
|
||||||
|
"van_sidedoorglass_FR": "van_sidedoorglass_FR",
|
||||||
|
"van_sidedoorglass_RR": "van_sidedoorglass_RR",
|
||||||
|
"van_sidedoorpanel_FR": "van_sidedoorpanel_FR",
|
||||||
|
"van_sidedoorpanel_RR": "van_sidedoorpanel_RR",
|
||||||
|
"van_sideglass_FL": "van_sideglass_FL",
|
||||||
|
"van_sideglass_ML": "van_sideglass_ML",
|
||||||
|
"van_sideglass_RL": "van_sideglass_RL",
|
||||||
|
"van_sideglass_RR": "van_sideglass_RR",
|
||||||
|
"van_snorkel": "",
|
||||||
|
"van_spring_R": "van_spring_R",
|
||||||
|
"van_steer": "van_steer_facelift",
|
||||||
|
"van_steering": "van_steering",
|
||||||
|
"van_suspension_F": "van_IFS",
|
||||||
|
"van_suspension_R": "van_axle_R",
|
||||||
|
"van_swaybar_F": "van_swaybar_F",
|
||||||
|
"van_swaybar_R": "",
|
||||||
|
"van_taillight_L": "van_taillight_L",
|
||||||
|
"van_taillight_R": "van_taillight_R",
|
||||||
|
"van_taillightguard_L": "",
|
||||||
|
"van_taillightguard_R": "",
|
||||||
|
"van_transfer_case": "van_transfer_case_RWD",
|
||||||
|
"van_transmission": "van_transmission_4A",
|
||||||
|
"van_tubs": "van_tubs",
|
||||||
|
"van_valance_F": "van_valance_F_late",
|
||||||
|
"van_wheeldata_F": "van_wheeldata_F",
|
||||||
|
"van_wheeldata_R": "van_wheeldata_R",
|
||||||
|
"van_windshield": "van_windshield",
|
||||||
|
"wheel_F_6": "steelwheel_02b_16x7_F",
|
||||||
|
"wheel_R_6": "steelwheel_02b_16x7_R"
|
||||||
|
},
|
||||||
|
"vars": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### `onVehicleDeleted`
|
##### `onVehicleDeleted`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,291 @@
|
|||||||
|
# 服务器端的安装
|
||||||
|
|
||||||
|
## **创建服务器**
|
||||||
|
|
||||||
|
设置服务器应用程序的基础知识
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **概述**
|
||||||
|
|
||||||
|
**创建一个家里云是免费的,但是托管一个VPS更容易也更安全**
|
||||||
|
|
||||||
|
服务器是BeamMP的一个组成部分;玩家通过服务器相互连接。它们在Windows和Linux上本机运行。
|
||||||
|
|
||||||
|
你可以制作私人服务器,只有你邀请的人才能加入,或者设置为公共服务器,显示在我们的官方服务器列表中。
|
||||||
|
|
||||||
|
让服务器上线运行需要经过几个步骤!如果遇到任何问题,可以随时在我们的 [论坛](https://forum.beammp.com) 或 [Discord 服务器](https://discord.gg/beammp) 的 `#support` 频道提问。更多信息也可参考 [服务器维护](server-maintenance.md) 部分。
|
||||||
|
|
||||||
|
请在使用服务器前务必阅读 [许可协议](https://raw.githubusercontent.com/BeamMP/BeamMP-Server/master/LICENSE)。
|
||||||
|
|
||||||
|
*服务器仅支持 IPv4。如果你不确定自己使用的是哪种协议,可以查看在 [*whatsmyip.org*](https://www.whatsmyip.org/) 上看到的 IP 地址——如果它包含 `:` *冒号,则为 **IPv6**。在这种情况下,你需要进一步确认自己是否也拥有 IPv4。你可以联系你的 ISP 查询,或者问问与你同住的人(如果他们懂技术,可能知道!)。计划将来支持 IPv6。**
|
||||||
|
|
||||||
|
## 设置服务器
|
||||||
|
|
||||||
|
设置包括以下步骤,您应该遵循所有步骤。
|
||||||
|
|
||||||
|
### **1. 端口转发**
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
```
|
||||||
|
如果你使用的是 VPS(虚拟专用服务器)、Rootserver,或者计划在本地托管服务器(与家里其他玩家在同一屋檐下),可以跳过此步骤。
|
||||||
|
如果你希望家外的人加入你本地托管的服务器(即在本地网络之外),则必须执行此步骤。
|
||||||
|
|
||||||
|
!!! danger ":material-scale-balance: 免责声明:"
|
||||||
|
|
||||||
|
**端口转发存在风险**.
|
||||||
|
|
||||||
|
进行端口转发意味着你理解将家庭网络端口向公众开放的风险,因此 BeamMP 对你或你家庭可能发生的**任何和所有**损害不承担责任。
|
||||||
|
|
||||||
|
我们不对任何外部链接服务或网站上的内容负责。
|
||||||
|
|
||||||
|
因此,建议使用我们的合作服务来托管服务器!
|
||||||
|
|
||||||
|
*请参阅 [端口转发指南]了解详细操作(port-forwarding.md)*
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 合作托管服务(付费):
|
||||||
|
|
||||||
|
- [Horizon Hosting](https://hrzn.link/beammp)
|
||||||
|
- [RackGenius](https://rackgeni.us/beammp-plans)
|
||||||
|
- [Connect Hosting](https://connecthosting.net/beammp)
|
||||||
|
- [Assetto Hosting](https://assettohosting.com/en/games/beamng)
|
||||||
|
- [ZAP-Hosting](https://zap-hosting.com/itsbeammp)
|
||||||
|
- [HostHavoc](https://hosthavoc.com/)
|
||||||
|
- [PedalHost](https://pedal.host/)
|
||||||
|
- [Vyper Hosting](https://vyperhosting.com/r/beammp)
|
||||||
|
- [BisectHosting](https://www.bisecthosting.com/beammp-server-hosting)
|
||||||
|
- [Four Seasons Hosting](https://fourseasonshosting.com)
|
||||||
|
- [Vertuo Hosting](https://vertuohosting.com)
|
||||||
|
- [Winheberg](https://winheberg.fr/offres/gaming/beammp?lang=en)
|
||||||
|
- [Wabbanode](https://wabbanode.com/partner/beammp)
|
||||||
|
- [Iceline Hosting](https://iceline-hosting.com/games/beammp)
|
||||||
|
|
||||||
|
#### 1.1 防火墙
|
||||||
|
|
||||||
|
根据你的设置,你可能需要允许 BeamMP-Server 通过防火墙。在 Windows 上通常需要这样操作(关闭防火墙通常 **无效**),在许多预装的 Linux 服务器上也是如此
|
||||||
|
|
||||||
|
在这里,你需要允许 BeamMP-Server 通过防火墙,**包括入站和出站连接**,并且 **包括 TCP 和 UDP**。如果防火墙要求指定端口,则必须使用你在步骤“1. 端口转发”中使用的相同端口(通常为 30814)。
|
||||||
|
|
||||||
|
如需更详细的指南,请参阅 [此文档页面](https://docs.beammp.com/FAQ/Defender-exclusions/)。<br>如果遇到问题,也欢迎随时在我们的 [论坛](https://forum.beammp.com) 或 [Discord 服务器](https://discord.gg/beammp) 的 `#support` 频道中提问。
|
||||||
|
|
||||||
|
### **2. 获取认证密钥**
|
||||||
|
|
||||||
|
‘认证密钥’,通常称为 ‘AuthKey’,是使 **公共** 服务器可以通过服务器列表访问所必需的。虽然也建议将 AuthKey 添加到私人服务器。你拥有的密钥数量有限。一个密钥一次只能用于一台服务器,因此不能用同一个密钥同时启动两台服务器。通过支持该项目可以获得更多密钥。更多信息请参阅 [这篇文章](https://docs.beammp.com/support/player-faq/)。
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
千万不要把密钥给别人看,把它当作密码!
|
||||||
|
```
|
||||||
|
|
||||||
|
此步骤需要一个 [Discord](https://discord.com) 账号。此举是为了防止垃圾信息。
|
||||||
|
|
||||||
|
#### 2.1. 访问密钥页面
|
||||||
|
|
||||||
|
通过 Discord 登录至 [Keymaster](https://keymaster.beammp.com)。在 Keymaster 主页中,点击屏幕左侧的“Keys(密钥)”:
|
||||||
|
|
||||||
|
<figure markdown="">  </figure>
|
||||||
|
|
||||||
|
#### 2.2. 创建密钥
|
||||||
|
|
||||||
|
要创建密钥,请单击右上角的绿色“+”按钮。
|
||||||
|
|
||||||
|
<figure markdown="">  </figure>
|
||||||
|
|
||||||
|
#### 2.3. 填写关键信息
|
||||||
|
|
||||||
|
接下来,填写服务器名称字段(这只是密钥的名称,而不是服务器列表上显示的实际名称),然后点击“Create”。范例:
|
||||||
|
|
||||||
|
<figure class="image image_resized" style="width:44.84%;" markdown="">  </figure>
|
||||||
|
|
||||||
|
最后,它看起来应该是这样的:
|
||||||
|
|
||||||
|
<figure markdown="">  </figure>
|
||||||
|
|
||||||
|
#### 2.4. 复制密钥
|
||||||
|
|
||||||
|
现在复制“Key”字段中的文本,在此范例中为 `3173a2e-6az0-4542-a3p0-ddqq5ff95558`,并保存以便下一步使用。你可以点击密钥右侧的剪贴板图标来完成复制:
|
||||||
|
|
||||||
|
<figure markdown="">  </figure>
|
||||||
|
|
||||||
|
### **3. 安装**
|
||||||
|
|
||||||
|
BeamMP-Server适用于Windows和Linux。接下来的两节分别介绍Windows和Linux。
|
||||||
|
|
||||||
|
#### 3.a. 安装在Windows上
|
||||||
|
|
||||||
|
对于Linux安装,请参见下一步。
|
||||||
|
|
||||||
|
在尝试在家托管服务器之前,请确保已完成端口转发!如果端口未转发,你将无法向公众托管服务器!
|
||||||
|
|
||||||
|
1. 请确保已安装 [Visual C++ 可再发行组件](https://aka.ms/vs/17/release/vc_redist.x64.exe) 以运行服务器。
|
||||||
|
2. 从 [beammp.com](https://www.beammp.com/) 下载服务器可执行文件。你将得到一个可执行文件,名称类似于 `BeamMP-Server.exe`。
|
||||||
|
3. 下载完成后,在某个位置创建一个文件夹,并将 `BeamMP-Server.exe` 放入其中。这就是你的服务器端所在的位置。
|
||||||
|
4. 双击启动服务器一次。这将为你生成所有必要的文件,当你看到文本输出后即可关闭并进行下一步。你应该会在 `BeamMP-Server.exe` 旁看到一个 `ServerConfig.toml` 文件。
|
||||||
|
5. (可选)为了日后快速访问,你可以轻松为 `BeamMP-Server.exe` 创建桌面快捷方式,方法是 **[右键点击]** > **发送到** > **桌面(创建快捷方式)**。
|
||||||
|
|
||||||
|
现在继续进行步骤 [4. 配置](#4-configuration)。
|
||||||
|
|
||||||
|
#### 3.b. 在Linux上安装
|
||||||
|
|
||||||
|
##### 使用我们的版本(推荐)
|
||||||
|
|
||||||
|
此步骤适用于我们在 [此处](https://github.com/BeamMP/BeamMP-Server/releases/latest) 提供二进制文件的所有发行版。如果你使用的是其他发行版或架构,请参考下方的“从源码构建”步骤。
|
||||||
|
|
||||||
|
1. 请确保已安装列在 [此处](https://github.com/BeamMP/BeamMP-Server#runtime-dependencies) 的依赖项。
|
||||||
|
2. 访问 [beammp.com](https://beammp.com/) 并点击“Download Server”按钮,你将被重定向到服务器的 Github 发布页面。
|
||||||
|
3. 下载与你的发行版对应的正确版本。为了简便起见,今后将其称为 `BeamMP-Server-xxx`,其中 `xxx` 表示你所使用发行版的版本。
|
||||||
|
4. 下载完成后,你应该会看到一个名为 `BeamMP-Server-xxx` 的文件,其他文件暂时可以忽略。在某个位置创建一个文件夹,并将 `BeamMP-Server-xxx` 放入其中。这就是你的服务器所在的位置。
|
||||||
|
5. 打开终端,进入你放置 `BeamMP-Server-xxx` 的文件夹,并运行 `chmod +x BeamMP-Server-xxx`。这可以确保你有权限运行它。
|
||||||
|
6. 运行 `./BeamMP-Server-xxx` 启动服务器一次。这将为你生成所有必要的文件,当你看到文本输出后即可关闭并进行下一步。你应该会在 `BeamMP-Server-xxx` 旁看到一个 `ServerConfig.toml` 文件。
|
||||||
|
7. 可选)强烈建议创建一个名为 `beammpserver`(或类似名称)的用户,因为我们不建议以 root、sudo 或你的个人用户账号运行服务器。之后,你应采取措施确保服务器仅以该用户身份启动。
|
||||||
|
|
||||||
|
现在继续进行步骤“4. 配置”。
|
||||||
|
|
||||||
|
##### 从源码编译
|
||||||
|
|
||||||
|
除了我们在 [此处](https://github.com/BeamMP/BeamMP-Server/releases/latest) 提供二进制文件的发行版外,其他发行版也可能可用,但不在官方支持范围内。如果你想自行编译,可以从我们的 [GitHub](https://github.com/BeamMP/BeamMP-Server) 下载源码,教程可在 [此处](https://github.com/BeamMP/BeamMP-Server#build-instructions) 找到。
|
||||||
|
|
||||||
|
最后,确保运行一次服务器:`./BeamMP-Server`,然后继续进行下一步。
|
||||||
|
|
||||||
|
### **4. 配置**
|
||||||
|
|
||||||
|
现在你已经运行过一次服务器,它应该已经生成了一些文件,并可能出现了一两个错误。这是正常的,因为我们还没有完成。你的文件夹中应该包含以下文件:
|
||||||
|
|
||||||
|
<figure markdown="">  </figure>
|
||||||
|
|
||||||
|
它们分别是 ‘ServerConfig.toml’、‘Server.log’ 和 ‘BeamMP-Server.exe’!(根据你的设置,你可能看不到 [.toml]、[.log]、[.exe] 后缀)
|
||||||
|
|
||||||
|
使用文本编辑器(例如 `Notepad`)打开 `ServerConfig.toml`。你可以通过 [右键点击] → “打开方式…” 然后选择文本编辑器来完成此操作。
|
||||||
|
|
||||||
|
以下是一个示例配置:
|
||||||
|
|
||||||
|
```TOML
|
||||||
|
[General]
|
||||||
|
Port = 30814
|
||||||
|
AuthKey = "auth-key"
|
||||||
|
AllowGuests = false
|
||||||
|
LogChat = false
|
||||||
|
Debug = false
|
||||||
|
IP = "::"
|
||||||
|
Private = true
|
||||||
|
InformationPacket = true
|
||||||
|
Name = "Test Server"
|
||||||
|
Tags = "Freeroam,Modded,Racing,Police"
|
||||||
|
MaxCars = 2
|
||||||
|
MaxPlayers = 10
|
||||||
|
Map = "/levels/ks_nord/info.json"
|
||||||
|
Description = "Total Random Beam MP Server"
|
||||||
|
ResourceFolder = "Resources"
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
```
|
||||||
|
这是您的配置文件。它采用了一种名为 TOML的格式。有关该文件及其变量的更多信息,请参考 [Server Maintenance(服务器维护)](server-maintenance.md) 章节。
|
||||||
|
|
||||||
|
只要设置了`Private = true`,您的服务器就不会出现在服务器列表中。如果您希望服务器在列表中显示,请将其设置为`Private = false`。
|
||||||
|
```
|
||||||
|
|
||||||
|
目前,我们只需要关注 `AuthKey`字段。请将你在第一步中复制的AuthKey粘贴到引号 `''`之间。
|
||||||
|
|
||||||
|
对于我们的范例密钥,它应该是这样的:
|
||||||
|
|
||||||
|
```TOML
|
||||||
|
AuthKey = '3173a2e-6az0-4542-a3p0-ddqq5ff95558'
|
||||||
|
```
|
||||||
|
|
||||||
|
同时,请在`Name`字段中为您的服务器命名。您可以为其设置颜色或其他样式,具体请参考服务器维护页面中关于[名称自定义的章节](server-maintenance.md#customize-the-look-of-your-server-name)。
|
||||||
|
|
||||||
|
如果你选择了除 **30814** 之外的其他 **端口**,请确保在 `Port` 下进行替换。
|
||||||
|
|
||||||
|
### **5. 验证**
|
||||||
|
|
||||||
|
现在再次运行你的服务器,看看是否还会出现 `[ERROR]` 或 `[WARN]` 消息。此时服务器应该会保持开启状态。在下面的步骤(6.)中,你可以了解如何加入服务器。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 5.1 怎么添加模组到我的服务器中
|
||||||
|
|
||||||
|
车辆模组和地图模组的安装方式不同,但都需要将它们放入服务器的 (`Resources/Client`) 文件夹中。只需将你想添加的模组放入该文件夹即可。
|
||||||
|
|
||||||
|
!!! 警告
|
||||||
|
|
||||||
|
```
|
||||||
|
如果在添加模组后尝试加入服务器时收到“done”或“start”消息,很可能是因为你向服务器添加了不兼容或损坏的模组。
|
||||||
|
模组之间也可能存在不兼容的情况。如果你在客户端安装了模组,请查阅本指南
|
||||||
|
了解如何从游戏中移除模组。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.2 一般的模组
|
||||||
|
|
||||||
|
如果你只想添加带模组的车辆,只需将模组的 zip 文件放入 `Resources/Client` 文件夹。加入你服务器的任何人都会自动下载这些模组。
|
||||||
|
|
||||||
|
#### 5.3 地图
|
||||||
|
|
||||||
|
所有默认地图(非模组的地图)都可以开箱即用,无需安装。您只需在 `ServerConfig.toml` 文件中将 `Map` 设置更改为 [这些](server-maintenance.md#all-vanilla-maps-names) 中的任意一个。对于任何其他模组地图,请执行以下操作:
|
||||||
|
|
||||||
|
1. 将你的地图 `.zip` 文件放入服务器的 (`Resources/Client`) 文件夹中。
|
||||||
|
2. 接下来,查看地图的 zip 文件内容(不要解压),并打开 `levels` 文件夹。在此文件夹中,应仅有一个以地图名称命名的子文件夹,例如 “myawesomedriftmap2021”。请确保 *完全按照该文件夹的名称复制或记住这个名称*。
|
||||||
|
3. 打开你的 `ServerConfig.toml`。在 `Map` 设置中,你应该会看到 `/levels/MAPNAME/info.json`,其中 `MAPNAME` 可能类似于 `gridmap_v2`。现在,你需要将此 `MAPNAME` 替换为上一步中子文件夹的名称,在本例中是 `myawesomedriftmap2021`。最终它应像下面这样(以本例为例),并且 ***必须*** 在末尾保留 `/info.json`。
|
||||||
|
|
||||||
|
```TOML
|
||||||
|
Map = '/levels/myawesomedriftmap2021/info.json'
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,当有人加入你的服务器时,地图应会自动下载并正常运行。
|
||||||
|
|
||||||
|
**如果这不起作用**,请在你的单人模式 BeamNG.drive 中安装该地图,启动并进入地图。然后,通过按 `~`(*波浪号*)键打开控制台(如果你使用非美式键盘,请在 **选项 > 控制 > 绑定** 菜单的 **通用调试** 部分中查看 **切换系统控制台** 的操作),并运行 `print(getMissionFilename())`。这样就会显示你需要使用的地图名称。
|
||||||
|
|
||||||
|
就这样!你添加的模组地图现在应该可以加入了!
|
||||||
|
|
||||||
|
### **6. 怎么加入你的服务器**
|
||||||
|
|
||||||
|
你和其他玩家如何加入你的服务器。
|
||||||
|
|
||||||
|
#### 6.a. 加入您自己的服务器(私有和公共)
|
||||||
|
|
||||||
|
如果你的服务器与游戏运行在同一台电脑上,你必须通过直接连接加入服务器。为此,请在服务器列表左侧点击 **Direct Connect Tab**。保持默认信息(应为 127.0.0.1 及对应端口),然后点击连接。
|
||||||
|
|
||||||
|
如果你的服务器托管在本地网络中的另一台电脑上,你必须找到该电脑的本地 IP,并使用该本地 IP 进行直接连接。
|
||||||
|
|
||||||
|
如果你的服务器托管在家外(例如 VPS),你必须找到该机器的 [公网 IP](https://whatismyipaddress.com/) 并通过该方式进行直接连接。
|
||||||
|
|
||||||
|
#### 6.b. 其他人加入您的私人服务器
|
||||||
|
|
||||||
|
你必须将服务器的公网 IP 地址提供给其他用户。但请注意,不要随意将你的公网 IP 地址分享给陌生人!要加入你的私人服务器,玩家必须在 BeamMP 中进入 **Direct Connect Tab**,然后输入你的 IP 和端口。
|
||||||
|
|
||||||
|
#### 6.c. 其他人加入您的公共服务器
|
||||||
|
|
||||||
|
若要加入您的公开服务器,其他玩家只需前往服务器列表,输入服务器名称并点击连接即可。如果您不确定自己的服务器名称,请查看您在 `ServerConfig.toml`中填写的名称。<br>如果找不到服务器,请确保已禁用所有搜索过滤器,并将地图设置为“全部”。您也可以前往 [Keymaster](https://keymaster.beammp.com/) 网站查看服务器的 IP 地址。
|
||||||
|
|
||||||
|
如果你或你的朋友遇到“Connection Failed!”错误,请查看启动器窗口中的代码,如 10060、10061、10030。这意味着你要么使用了 CGNAT IPv4,要么在步骤 **1 端口转发** 或 **1.1 防火墙** 中操作有误。要检查是否使用 CGNAT IPv4,请在路由器界面上查看 WAN IP 地址,并将其与你的 [公网 IP](https://www.whatsmyip.org/) 进行比较。如果两者相同,则表示你不在 CGNAT 后面。IPv6 支持尚未 **实现**。
|
||||||
|
|
||||||
|
### **7. 如何检查您的BeamMP-Server的连通性**
|
||||||
|
|
||||||
|
在下方输入服务器的公网 IPv4 和端口,然后点击“CheckBeamMP”。
|
||||||
|
|
||||||
|
<form action="https://check.beammp.com/api/v2/beammp" method="get" target="_blank">
|
||||||
|
<label for="ip">IP 地址:</label>
|
||||||
|
<input type="text" id="ip" name="ip"><br>
|
||||||
|
<label for="port">端口:</label>
|
||||||
|
<input type="text" id="port" name="port"><br>
|
||||||
|
<input type="submit" value="CheckBeamMP">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
!!! warning "我想使用 RadminVPN、Hamachi 或类似的 VPN。"
|
||||||
|
|
||||||
|
```
|
||||||
|
BeamMP 不支持这些 VPN,因为它们经常引发问题。其中一个问题是 UDP 流量无法转发。要解决此问题,请参考第 1 节。
|
||||||
|
|
||||||
|
!!! question "那为什么以前可以用?"
|
||||||
|
|
||||||
|
这是因为这些应用程序的开发者更新了软件并实施了 BeamMP 无法控制的更改。
|
||||||
|
是否支持像 BeamMP-Server 这样的特定使用场景,由这些应用程序的开发者决定。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 还有问题吗?
|
||||||
|
|
||||||
|
在 [论坛](https://forum.beammp.com) 或我们的 [Discord 服务器](https://discord.gg/beammp) 的 `#support` 频道中发起一个讨论帖。
|
||||||
@@ -21,6 +21,7 @@ AuthKey | 认证密钥格式为`xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`,其中所
|
|||||||
AllowGuests | true/false | 决定游客是否可以加入服务器。
|
AllowGuests | true/false | 决定游客是否可以加入服务器。
|
||||||
LogChat | true/false | 当启用(设置为“true”)时,聊天消息会被记录在 server.log 文件中。
|
LogChat | true/false | 当启用(设置为“true”)时,聊天消息会被记录在 server.log 文件中。
|
||||||
Debug | true /false | 当启用(true)时,将在日志中显示更多消息并提供更多信息。如果遇到问题,请启用此选项。启用此选项将显著增加日志文件的大小。
|
Debug | true /false | 当启用(true)时,将在日志中显示更多消息并提供更多信息。如果遇到问题,请启用此选项。启用此选项将显著增加日志文件的大小。
|
||||||
|
IP | 连接到主机的其中一个网卡(NIC)的本地分类地址。(默认值:"0.0.0.0" 或 "::") | 服务器将尝试绑定到所提供的 IP。除非您清楚自己在做什么,否则请勿随意修改IP字段。此数值无需更改即可使服务器正常运行。
|
||||||
Private | true/false | 当启用(true)时,您的服务器将不会显示在服务器列表中。任何拥有正确IP地址和端口的人仍然可以连接。
|
Private | true/false | 当启用(true)时,您的服务器将不会显示在服务器列表中。任何拥有正确IP地址和端口的人仍然可以连接。
|
||||||
InformationPacket | true/false | 当启用(true)时,服务器将允许未经身份验证的客户端直接通过服务器获取与服务器列表中相同的信息。
|
InformationPacket | true/false | 当启用(true)时,服务器将允许未经身份验证的客户端直接通过服务器获取与服务器列表中相同的信息。
|
||||||
Name | Any "text" | 在服务器列表中显示为您的服务器名称/标题。您可以使用特殊字符来为其添加颜色和样式。
|
Name | Any "text" | 在服务器列表中显示为您的服务器名称/标题。您可以使用特殊字符来为其添加颜色和样式。
|
||||||
|
|||||||
+48
@@ -91,6 +91,9 @@ extra:
|
|||||||
- name: Pусский
|
- name: Pусский
|
||||||
link: /ru/
|
link: /ru/
|
||||||
lang: ru
|
lang: ru
|
||||||
|
- name: 中文
|
||||||
|
link: /zh/
|
||||||
|
lang: zh
|
||||||
homepage: /
|
homepage: /
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
@@ -327,6 +330,51 @@ plugins:
|
|||||||
Contributing: Участие
|
Contributing: Участие
|
||||||
Getting Started: Начало работы
|
Getting Started: Начало работы
|
||||||
Community: Сообщество
|
Community: Сообщество
|
||||||
|
- locale: zh
|
||||||
|
name: 中文
|
||||||
|
build: true
|
||||||
|
nav_translations:
|
||||||
|
Home: 首页
|
||||||
|
Support: 支持
|
||||||
|
Playing BeamMP: 游玩 BeamMP
|
||||||
|
Installing BeamMP: 安装 BeamMP
|
||||||
|
Error Codes: 错误代码
|
||||||
|
Multiplayer Settings: 多人模式设置
|
||||||
|
Running a Server: 运行服务器
|
||||||
|
Server Installation: 服务器端的安装
|
||||||
|
Server Maintenance: 服务器维护
|
||||||
|
Error Codes: 错误代码
|
||||||
|
Server Manual: 服务器手册
|
||||||
|
Mod & Resource Creation: 模组与资源制作
|
||||||
|
Client Side: 客户端
|
||||||
|
Server Side: 服务器端
|
||||||
|
FAQ: 常见问题解答
|
||||||
|
How to check for CGNAT?: 如何检查CGNAT?
|
||||||
|
Where can I find my IP address?: 我怎样才能找到我服务器的IP?
|
||||||
|
How to remove mods?: 如何删除模组?
|
||||||
|
Manually updating the Launcher: 手动更新启动器
|
||||||
|
Changing the Launcher port: 更改启动器端口
|
||||||
|
Creating Exclusions (Defender): 创建 Defender 排除项
|
||||||
|
Player FAQ: 面向玩家的疑难解答
|
||||||
|
Game FAQ: 游戏常见问题
|
||||||
|
Server FAQ: 服务器常见问题
|
||||||
|
Development Guides: 开发指南
|
||||||
|
Mod Creation: 模组制作
|
||||||
|
UI Apps: 图形界面-应用程序
|
||||||
|
IMGUI Windows: IMGUI 窗口
|
||||||
|
Lua Mods: Lua 模组
|
||||||
|
Resource Creation: 资源制作
|
||||||
|
UI Apps: 图形界面-应用程序
|
||||||
|
Snippets: 片段
|
||||||
|
BeamNG Documentation: BeamNG.drive 文档
|
||||||
|
Installation: 安装
|
||||||
|
Helpful Snippets: 实用代码片段
|
||||||
|
Scripting Reference: 脚本参考
|
||||||
|
Mod (In-Game): 游戏内模组
|
||||||
|
Server: 服务器
|
||||||
|
Contributing: 参与贡献
|
||||||
|
Getting Started: 快速开始
|
||||||
|
Community: 社区
|
||||||
- locale: en
|
- locale: en
|
||||||
default: true
|
default: true
|
||||||
name: English
|
name: English
|
||||||
|
|||||||
Reference in New Issue
Block a user