pc-live/README.md
Bjoern Flessing 785d5f6268 Verwaisten Bleeter-Callback entfernt
Der Callback openBleeter oeffnete Bleeters eigenes Fenster ueber dem PC. Das
nahm dem PC den Fokus - SetNuiFocus gilt global fuer den Client, zwei Resources
sperren sich dabei gegenseitig die Maus aus.

Seit Bleeter als eigene App im PC laeuft (client/bleeter.lua), rief ihn niemand
mehr auf.
2026-08-09 12:43:37 +00:00

210 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

# pc-live — IC-Computer
Ein Computer im Spiel: Schreibtisch, Fenster, Apps. Man tritt an ein
Terminal, drückt **E**, und bekommt eine Oberfläche mit Mail, Browser,
Adressbuch, Kalender und weiteren Anwendungen.
Andere Resources hängen sich als App ein — so laufen hier das IC-Webhosting
(`ic-web`) und Bleeter.
---
## Installation
### 1. Ordner
```
resources/[haleoe]/pc-live/
```
### 2. Datenbank
Reihenfolge einhalten, die Migrationen setzen auf dem Grundschema auf:
```bash
mysql -u BENUTZER -p DATENBANK < sql/pc_live.sql
mysql -u BENUTZER -p DATENBANK < sql/pc_live_devices.sql
mysql -u BENUTZER -p DATENBANK < sql/migration_postfach_ordner.sql
mysql -u BENUTZER -p DATENBANK < sql/migration_kalender.sql
```
| Datei | legt an |
|---|---|
| `pc_live.sql` | Benutzer, Apps, Mail, Ordner, Kalender, Kontakte |
| `pc_live_devices.sql` | **feste PC-Standorte** fehlte im ursprünglichen Schema, ohne sie ist kein fester PC ansprechbar |
| `migration_postfach_ordner.sql` | Ordner je Postfach, Zustellungskennung |
| `migration_kalender.sql` | private, geteilte und öffentliche Kalender |
Alle wiederholt ausführbar.
### 3. server.cfg
```
ensure oxmysql
ensure es_extended
ensure pc-live
```
### 4. Einen PC in die Welt stellen
Ein fester PC braucht **zwei Einträge mit derselben Kennung** — das ist die
häufigste Stolperfalle:
**a) Datenbank** Standort, Beschriftung, Jobsperre:
```sql
INSERT INTO pc_live_devices (id, label, x, y, z, heading, type, job, active)
VALUES ('mission_row_1', 'LSPD Terminal',
441.615, -979.645, 30.425, 195.0, 'public', NULL, 1);
```
**b) `config.lua`** Kamerafahrt und Einfrieren beim Öffnen:
```lua
{
id = "mission_row_1", -- muss zur Datenbank passen
label = "LSPD Terminal",
coords = vector3(441.615, -979.645, 30.425),
heading = 195.0,
type = "public", -- oder: type = "job", job = "police"
}
```
Fehlt der Eintrag in `config.lua`, lässt sich der PC benutzen — aber ohne
Kamera und ohne dass die Spielfigur einfriert.
Zum `heading`: **nicht** die Ausrichtung des Props, sondern die Seite, von der
aus man auf den Bildschirm schaut. Am einfachsten: davorstellen, in die
gewünschte Richtung schauen, eigene Position und Blickrichtung ablesen — die
Blickrichtung plus 180° ist der Wert.
### 5. Apps anderer Resources einhängen
Eine App besteht aus vier Teilen. Beispiel `ic-web`:
| Teil | Ort |
|---|---|
| Brücke NUI → Server | `client/…lua`, eingetragen in `fxmanifest.lua` |
| Oberfläche | `nui/js/apps/….js`, eingetragen in `fxmanifest.lua` **und** `nui/index.html` |
| Schreibtischsymbol | `APP_META` in `nui/js/desktop.js` |
| Registrierung | `AppRegistry.Register` in `server/apps.lua` |
Antworten des Servers laufen über den Nachrichtenverteiler in `desktop.js`
(`window.addEventListener('message', …)`). Jede App bekommt dort ihren eigenen
`case`.
Resources können sich auch von außen eintragen:
```lua
exports['pc-live']:RegisterApp({ app_id = 'meine.app', name = 'Meine App', })
```
Die Oberfläche muss trotzdem in `nui/` liegen — das NUI lädt nur Dateien der
eigenen Resource.
**Eigene App bauen: [PLUGINS.md](PLUGINS.md)** — vollständiges Beispiel von der
Tabelle bis zum Schreibtischsymbol, dazu die Fallen, die sonst Zeit kosten.
---
## Was drin ist
| App | |
|---|---|
| **Browser** | interne Seiten unter `ic://…`, externe über iframe |
| **Mail** | mehrere Postfächer, Ordner je Postfach, Signaturen, Kalender |
| **Adressbuch** | Kontakte, verknüpft mit Mail |
| **Webhosting** | Domänen und Webseiten (`ic-web`) |
| **Bleeter** | soziales Netz: Feed, Werbung, Markt, Kalender, Gewerbe, Profil |
| **Bleeter-Verwaltung** | Unternehmensprofile und Freigaben |
| **Software Store** | Apps nachinstallieren |
---
## Mail: was hier anders ist
**Postfächer hängen an einer Anmeldung, nicht an der Person.** Über *Postfächer
Postfach hinzufügen* schaltet man ein Postfach mit Adresse und Passwort
frei (geprüft von `ic-web`). Mehrere Personen können dasselbe Postfach
gleichzeitig offen haben — ein Firmenpostfach gehört der Firma.
**Ordner gehören zum Postfach.** Legt jemand im Firmenpostfach einen Ordner an,
sehen ihn alle, die es bedienen. Sortiert jemand eine Mail ein, liegt sie für
alle im selben Ordner.
Das ist nicht selbstverständlich, denn eine Mail an ein geteiltes Postfach wird
**je Empfänger einmal** gespeichert. Damit das Einsortieren trotzdem für alle
gilt, tragen alle Kopien einer Zustellung dieselbe `delivery_id`
(`pc_live_mail.delivery_id`) — wird eine verschoben, wandern die anderen mit.
Gelesen und gelöscht bleibt dagegen persönlich. Das ist keine Eigenschaft der
Nachricht, sondern der Person.
**Signaturen** gehören ebenfalls zum Postfach (`ic_mail_accounts.signature`).
Wer es bedient, schreibt mit derselben Fußzeile.
---
## Kalender
| Sichtbarkeit | gehört | sieht | bearbeitet |
|---|---|---|---|
| privat | der Person | nur sie | nur sie |
| geteilt | einem Postfach | wer es bedient | wer es bedient |
| öffentlich | einem Postfach | jeder auf dem Server | wer es bedient |
Ein öffentlicher Termin hängt bewusst auch an einem Postfach — sonst gäbe es
niemanden, der ihn später ändern oder absagen könnte.
Änderungen erreichen alle Beteiligten sofort, sonst hätte jeder eine andere
Vorstellung vom Dienstplan, bis er den PC neu öffnet.
---
## Sicherheit
**Welches Postfach gemeint ist, schickt der Client mit.** Der Server prüft das
bei jeder Ordner- und Mailaktion über `ic-mail:CanAccessAddress` und fällt ohne
Zugriff auf das persönliche Postfach zurück, statt fremde Ordner herauszugeben.
Jede Ordneraktion hängt zusätzlich an einer Besitzprüfung, nicht an der
mitgeschickten Id allein.
**Keine eingebauten Browserdialoge.** `prompt()`, `confirm()` und `alert()`
haben in FiveMs CEF keinen Handler: der Aufruf öffnet nichts und lässt das NUI
stehen. Stattdessen `ICWebRender.promptText` und `ICWebRender.confirmBox` aus
`nui/js/apps/webhosting.js`.
**Spielerinhalte werden über `textContent` gesetzt, nie über `innerHTML`.**
Das NUI ist derselbe Kontext wie der PC — wer dort Markup einschleusen kann,
kann auch dessen Callbacks aufrufen.
---
## Voraussetzungen
| | |
|---|---|
| `oxmysql` | Datenbankzugriff |
| `es_extended` | Spieler, Jobs, Benachrichtigungen |
| `ic-mail` | optional ohne sie gibt es keine Mailadressen |
| `ic-web` | optional liefert Webhosting-App und Postfachanmeldung |
---
## Bekannte Fallstricke
**Der Fensterrahmen hat keine `id`.** `WindowManager.create` setzt
`data-wid`. Wer sein Fenster mit `document.getElementById(WIN_ID)` sucht,
findet nichts und schreibt ins Leere — das Fenster bleibt leer. Richtig ist
das von `create()` zurückgegebene Element oder
`document.querySelector('[data-wid="…"]')`.
**Ja/Nein-Spalten aus der Datenbank.** `TINYINT(1)` kommt je nach Treiberweg
als `1` oder als `true` an — `oxmysql` wandelt es bei `query`/`single` in einen
Boolean um, bei `prepare` nicht. Ein Vergleich mit `== 1` geht deshalb
irgendwann schief, und zwar still. Siehe `ICWeb.Bool` in `ic-web`.
**Keine Datenbankarbeit beim Herunterfahren.** Ein `await` in `onResourceStop`
wartet auf eine Antwort, die niemand mehr entgegennimmt — der Server meldet
„Execution of function reference in script host failed". Aufräumen gehört in
den Start.