-- ===================================================================== -- Aether Framework — Datenbank-Schema (Grundlage) -- Einspielen mit: mysql -u root -p aether < sql/aether.sql -- ===================================================================== CREATE DATABASE IF NOT EXISTS `aether` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `aether`; -- --------------------------------------------------------------------- -- Benutzer (ein Eintrag pro FiveM-Account, erkannt an der Lizenz) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_users` ( `license` VARCHAR(64) NOT NULL COMMENT 'Rockstar-Lizenz als eindeutige Kennung', `name` VARCHAR(64) NOT NULL DEFAULT 'Unbekannt' COMMENT 'Zuletzt genutzter Spielername', `discord` VARCHAR(64) DEFAULT NULL COMMENT 'Discord-ID, falls vorhanden', `is_banned` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Gebannt ja/nein', `ban_reason` VARCHAR(255) DEFAULT NULL COMMENT 'Grund des Banns', `ban_until` DATETIME DEFAULT NULL COMMENT 'Bann-Ende (NULL = dauerhaft)', `admin_group` VARCHAR(32) NOT NULL DEFAULT 'user' COMMENT 'Rechtegruppe: user/support/admin/owner', `playtime` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Gesamtspielzeit in Minuten', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_seen` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`license`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Charaktere (mehrere pro Benutzer — Multicharacter) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_characters` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `license` VARCHAR(64) NOT NULL COMMENT 'Besitzer des Charakters', `firstname` VARCHAR(32) NOT NULL, `lastname` VARCHAR(32) NOT NULL, `dob` DATE NOT NULL COMMENT 'Geburtsdatum', `gender` VARCHAR(16) NOT NULL DEFAULT 'm' COMMENT 'Geschlecht', `nationality` VARCHAR(48) NOT NULL DEFAULT 'Los Santos' COMMENT 'Herkunft', `appearance` LONGTEXT DEFAULT NULL COMMENT 'Aussehen als JSON (Charakter-Ersteller)', -- Geld (passend zum HUD: Bargeld / Konto / Schwarzgeld) `cash` INT NOT NULL DEFAULT 0, `bank` INT NOT NULL DEFAULT 0, `dirty_money` INT NOT NULL DEFAULT 0, `iban` VARCHAR(24) DEFAULT NULL COMMENT 'Kontonummer fuer das Bank-Modul', `bank_pin` VARCHAR(8) NOT NULL DEFAULT '1234' COMMENT 'PIN des Bankautomaten', -- Arbeit und Zugehoerigkeit `job` VARCHAR(32) NOT NULL DEFAULT 'unemployed', `job_grade` INT NOT NULL DEFAULT 0, `faction` VARCHAR(32) DEFAULT NULL COMMENT 'Fraktion/Gang, falls Mitglied', `faction_rank` INT NOT NULL DEFAULT 0, -- Zustand (passend zu den HUD-Statusringen) `health` INT NOT NULL DEFAULT 200, `hunger` INT NOT NULL DEFAULT 100, `thirst` INT NOT NULL DEFAULT 100, `stamina` INT NOT NULL DEFAULT 100, `position` VARCHAR(128) DEFAULT NULL COMMENT 'Letzte Position als JSON {x,y,z,heading}', `playtime` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Spielzeit dieses Charakters in Minuten', `is_dead` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Liegt der Charakter verletzt am Boden?', `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Weich geloescht (Slot freigegeben)', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_played` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_license` (`license`), CONSTRAINT `fk_char_user` FOREIGN KEY (`license`) REFERENCES `aether_users` (`license`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Inventar (ein Eintrag je Item-Stapel an einem Ort) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_inventory` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `owner_type` VARCHAR(16) NOT NULL DEFAULT 'character' COMMENT 'character/vehicle/stash/ground', `owner_id` VARCHAR(64) NOT NULL COMMENT 'Charakter-ID, Kennzeichen oder Lager-Name', `slot` INT NOT NULL DEFAULT 0 COMMENT 'Platz im jeweiligen Behaelter', `item` VARCHAR(48) NOT NULL COMMENT 'Item-Kennung aus der Registry', `amount` INT NOT NULL DEFAULT 1, `metadata` LONGTEXT DEFAULT NULL COMMENT 'Zusatzdaten als JSON (Seriennummer, Akku, Aufsaetze)', PRIMARY KEY (`id`), KEY `idx_owner` (`owner_type`, `owner_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Fallengelassene Items (bleiben ueber Serverneustarts erhalten) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_drops` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `item` VARCHAR(48) NOT NULL COMMENT 'Item-Kennung aus der Registry', `amount` INT NOT NULL DEFAULT 1, `metadata` LONGTEXT DEFAULT NULL COMMENT 'Zusatzdaten als JSON', `x` FLOAT NOT NULL, `y` FLOAT NOT NULL, `z` FLOAT NOT NULL, `prop` VARCHAR(48) NOT NULL COMMENT 'Modell des sichtbaren Kartons', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Fahrzeuge (Garagen-Modul) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_vehicles` ( `plate` VARCHAR(12) NOT NULL COMMENT 'Kennzeichen als eindeutige Kennung', `owner` INT UNSIGNED NOT NULL COMMENT 'Charakter-ID des Besitzers', `model` VARCHAR(48) NOT NULL COMMENT 'Fahrzeugmodell (Spawnname)', `props` LONGTEXT DEFAULT NULL COMMENT 'Tuning/Farben als JSON', `garage` VARCHAR(48) NOT NULL DEFAULT 'zentralgarage' COMMENT 'Aktueller Standort', `state` VARCHAR(16) NOT NULL DEFAULT 'in' COMMENT 'in = eingeparkt, out = draussen, impound = beschlagnahmt', `fuel` FLOAT NOT NULL DEFAULT 100 COMMENT 'Tankfuellstand in Prozent', `engine` FLOAT NOT NULL DEFAULT 1000 COMMENT 'Motorzustand', `body` FLOAT NOT NULL DEFAULT 1000 COMMENT 'Karosseriezustand', `mileage` INT NOT NULL DEFAULT 0 COMMENT 'Kilometerstand', -- Letzte bekannte Position; ausgeparkte Fahrzeuge stehen nach einem -- Serverneustart wieder genau hier. `pos_x` FLOAT DEFAULT NULL, `pos_y` FLOAT DEFAULT NULL, `pos_z` FLOAT DEFAULT NULL, `heading` FLOAT DEFAULT NULL, PRIMARY KEY (`plate`), KEY `idx_owner` (`owner`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Dokumente (Boerse: Ausweis, Fuehrerschein, Waffenschein ...) -- Name und Geburtsdatum kommen live aus aether_characters, damit sie -- nicht doppelt gepflegt werden muessen. -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_documents` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `character` INT UNSIGNED NOT NULL COMMENT 'Besitzer des Dokuments', `type` VARCHAR(16) NOT NULL COMMENT 'perso/fs/ws/gk/vk', `wallet` INT NOT NULL DEFAULT 0 COMMENT 'In welcher Boerse es steckt (0 = erste)', `data` LONGTEXT DEFAULT NULL COMMENT 'Dokumentdaten als JSON (Nummer, Klassen, Waffen ...)', `issued_by` VARCHAR(64) DEFAULT NULL COMMENT 'Ausstellende Stelle', `issued_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `valid_until` DATE DEFAULT NULL COMMENT 'Gueltig bis (NULL = unbefristet)', `revoked` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Entzogen ja/nein', PRIMARY KEY (`id`), KEY `idx_character` (`character`), UNIQUE KEY `uniq_doc` (`character`, `type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Handy: Geraetedaten je Charakter -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_phone` ( `character` INT UNSIGNED NOT NULL, `number` VARCHAR(16) NOT NULL COMMENT 'Telefonnummer, z. B. 555-0182', `pin` VARCHAR(8) DEFAULT NULL COMMENT 'Entsperrcode (NULL = Ersteinrichtung noetig)', `faceid` TINYINT(1) NOT NULL DEFAULT 0, `theme` VARCHAR(16) NOT NULL DEFAULT 'dark', `wallpaper` VARCHAR(32) NOT NULL DEFAULT 'wp-aurora', `dock` VARCHAR(128) NOT NULL DEFAULT '["phone","messages","bank","camera"]', `battery` INT NOT NULL DEFAULT 100 COMMENT 'Akkustand in Prozent', `unlocked` VARCHAR(255) NOT NULL DEFAULT '{}' COMMENT 'Freigeschaltete Apps als JSON', PRIMARY KEY (`character`), UNIQUE KEY `uniq_number` (`number`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Handy: Kontakte -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_phone_contacts` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `character` INT UNSIGNED NOT NULL COMMENT 'Besitzer der Kontaktliste', `name` VARCHAR(48) NOT NULL, `number` VARCHAR(16) NOT NULL, PRIMARY KEY (`id`), KEY `idx_character` (`character`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Handy: Nachrichten (zwischen Telefonnummern, nicht Charakteren — -- so bleiben sie auch nach einem SIM-Wechsel nachvollziehbar) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_phone_messages` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `sender` VARCHAR(16) NOT NULL COMMENT 'Absendernummer', `receiver` VARCHAR(16) NOT NULL COMMENT 'Empfaengernummer', `text` VARCHAR(512) NOT NULL, `gelesen` TINYINT(1) NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_paar` (`sender`, `receiver`), KEY `idx_empfaenger` (`receiver`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Handy: Anrufverlauf -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_phone_calls` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `caller` VARCHAR(16) NOT NULL COMMENT 'Anrufernummer', `callee` VARCHAR(16) NOT NULL COMMENT 'Angerufene Nummer', `verpasst` TINYINT(1) NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_caller` (`caller`), KEY `idx_callee` (`callee`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Banktransaktionen (Bank- und Handy-Modul) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_transactions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `character` INT UNSIGNED NOT NULL COMMENT 'Betroffener Charakter', `type` VARCHAR(16) NOT NULL COMMENT 'deposit/withdraw/transfer/salary/fine', `amount` INT NOT NULL COMMENT 'Betrag (positiv = Eingang)', `balance` INT NOT NULL COMMENT 'Kontostand nach der Buchung', `label` VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'Verwendungszweck', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_character` (`character`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Jobs: Level und Erfahrung je Charakter und Job -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_jobs` ( `character` INT UNSIGNED NOT NULL, `job` VARCHAR(32) NOT NULL, `level` INT NOT NULL DEFAULT 1, `xp` INT NOT NULL DEFAULT 0, `verdient` INT NOT NULL DEFAULT 0 COMMENT 'Gesamtverdienst in diesem Job', `auftraege` INT NOT NULL DEFAULT 0 COMMENT 'Abgeschlossene Auftraege', PRIMARY KEY (`character`, `job`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Fraktionen: Personenakten (Straftaten, Notizen, Konfisziertes) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_records` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `character` INT UNSIGNED NOT NULL COMMENT 'Betroffene Person', `faction` VARCHAR(32) NOT NULL COMMENT 'Welche Fraktion hat den Eintrag erstellt', `type` VARCHAR(16) NOT NULL COMMENT 'straftat/notiz/konfisziert/behandlung', `text` VARCHAR(512) NOT NULL, `betrag` INT NOT NULL DEFAULT 0 COMMENT 'Strafe/Rechnung, falls zutreffend', `haft` INT NOT NULL DEFAULT 0 COMMENT 'Haftzeit in Minuten', `created_by` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'Name des Beamten', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_character` (`character`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Fraktionen: Fahndungen -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_wanted` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `character` INT UNSIGNED NOT NULL, `faction` VARCHAR(32) NOT NULL, `grund` VARCHAR(255) NOT NULL, `stufe` VARCHAR(16) NOT NULL DEFAULT 'gesucht' COMMENT 'gesucht/bewaffnet/gefaehrlich', `aktiv` TINYINT(1) NOT NULL DEFAULT 1, `created_by` VARCHAR(64) NOT NULL DEFAULT '', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_character` (`character`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Gefaengnis: laufende Haftstrafen -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_jail` ( `character` INT UNSIGNED NOT NULL, `rest` INT NOT NULL DEFAULT 0 COMMENT 'Restliche Haftzeit in Sekunden', `grund` VARCHAR(255) NOT NULL DEFAULT '', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`character`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- -- Staatskasse (eine Zeile; Strafen und Rechnungen fliessen hierher) -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `aether_treasury` ( `id` INT UNSIGNED NOT NULL DEFAULT 1, `betrag` BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT IGNORE INTO `aether_treasury` (`id`, `betrag`) VALUES (1, 12480000);