-- ───────────────────────────────────────────────────────────────────────────── -- App Registry – manages registered apps, installation & export -- ───────────────────────────────────────────────────────────────────────────── AppRegistry = {} local _registry = {} -- app_id -> manifest --- Register an app with the system. ---@param manifest table function AppRegistry.Register(manifest) if not manifest or not manifest.app_id then Utils.Warn("AppRegistry.Register: invalid manifest (missing app_id)") return false end if _registry[manifest.app_id] then Utils.Warn(("AppRegistry: app '%s' already registered, overwriting"):format(manifest.app_id)) end _registry[manifest.app_id] = manifest Utils.Log(("Registered app: %s v%s"):format(manifest.app_id, manifest.version or "?")) return true end --- Get the full registry sorted (default/system first, then alphabetically). ---@return table[] function AppRegistry.GetAll() local list = {} for _, m in pairs(_registry) do list[#list + 1] = m end table.sort(list, function(a, b) if (a.default or false) ~= (b.default or false) then return (a.default and true or false) end return (a.name or "") < (b.name or "") end) return list end --- Get a single app manifest by id. ---@param appId string ---@return table? function AppRegistry.Get(appId) return _registry[appId] end --- Check if an app is registered. ---@param appId string ---@return boolean function AppRegistry.Exists(appId) return _registry[appId] ~= nil end --- Combine registry with per-user install data (for store listing). ---@param installs table[] rows from pc_live_installs ---@return table[] function AppRegistry.BuildStoreList(installs) local installedMap = {} for _, row in ipairs(installs) do installedMap[row.app_id] = row.version end local list = AppRegistry.GetAll() for _, app in ipairs(list) do app.installed = installedMap[app.app_id] ~= nil app.installed_version = installedMap[app.app_id] app.update_available = app.installed and (app.installed_version ~= app.version) end return list end --- Build list of currently installed apps for the desktop. ---@param installs table[] ---@return table[] function AppRegistry.BuildInstalledList(installs) local list = {} for _, row in ipairs(installs) do local manifest = _registry[row.app_id] if manifest then local entry = {} for k, v in pairs(manifest) do entry[k] = v end entry.installed_version = row.version list[#list + 1] = entry end end return list end -- ── Export for external resources ────────────────────────────────────────── exports('RegisterApp', function(manifest) return AppRegistry.Register(manifest) end) -- ── Register Built-In Apps ───────────────────────────────────────────────── -- NOTE: icon field uses the emoji directly so NUI can display it without a -- separate lookup table. Add dependencies = {} on every app. -- ────────────────────────────────────────────────────────────────────────── CreateThread(function() Wait(0) -- Let other resources load first -- ┌─────────────────────────────────────────────┐ -- │ SYSTEM (pre-installed, cannot remove) │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.browser", name = "Browser", icon = "🌐", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "Browse internal IC websites.", price = 0, }) AppRegistry.Register({ app_id = "pc.mail", name = "Mail", icon = "✉", version = "2.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "E-Mail, Ordner, Kalender – alles in einer App.", price = 0, }) AppRegistry.Register({ app_id = "pc.addressbook", name = "Adressbuch", icon = "👤", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "Kontakte verwalten – Name, E-Mail, Telefon. Direkt mit Mail verknüpft.", price = 0, }) AppRegistry.Register({ app_id = "pc.store", name = "Software Store", icon = "🛒", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "Browse and install software.", price = 0, }) -- Webhosting (ic-web). Vorinstalliert, weil die Anmeldung ohnehin -- entscheidet, wer hier etwas tun kann – ohne Zugang sieht man nur die -- Anmeldemaske. AppRegistry.Register({ app_id = "pc.webhosting", name = "Webhosting", icon = "🌍", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "IC-Domänen und Webseiten verwalten. Anmeldung erforderlich.", price = 0, }) -- Bleeter selbst, eingebettet als Fenster im PC. AppRegistry.Register({ app_id = "pc.bleeter", name = "Bleeter", icon = "🐦", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "Bleeter – Feed, Werbung, Gewerbe und Profil.", price = 0, }) -- Bleeter-Verwaltung. Ohne Anmeldung sieht man nur die Anmeldemaske, -- deshalb vorinstalliert wie das Webhosting. AppRegistry.Register({ app_id = "pc.bleeteradmin", name = "Bleeter-Verwaltung", icon = "🐦", version = "1.0.0", category = "system", permissions = {}, dependencies = {}, default = true, description = "Unternehmensprofile auf Bleeter einrichten und Mitarbeiter freigeben.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ UTILITY │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.terminal", name = "Terminal", icon = "⌨", version = "1.3.0", category = "utility", permissions = {}, dependencies = {}, default = false, description = "Advanced command-line interface for power users.", price = 0, }) AppRegistry.Register({ app_id = "pc.notes", name = "Notepad Pro", icon = "📝", version = "1.0.0", category = "utility", permissions = {}, dependencies = {}, default = false, description = "Text editor with rich formatting and local storage.", price = 299, }) AppRegistry.Register({ app_id = "pc.calculator", name = "Calculator", icon = "🔢", version = "1.0.0", category = "utility", permissions = {}, dependencies = {}, default = false, description = "Scientific calculator with unit conversion.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ COMMUNICATION │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.chat", name = "IC Chat", icon = "💬", version = "2.0.0", category = "communication", permissions = {}, dependencies = {}, default = false, description = "In-character instant messaging platform.", price = 0, }) AppRegistry.Register({ app_id = "pc.voip", name = "VoIP Client", icon = "📞", version = "1.1.0", category = "communication", permissions = {}, dependencies = {}, default = false, description = "Encrypted voice-over-IP calls via IC network.", price = 499, }) -- ┌─────────────────────────────────────────────┐ -- │ SECURITY │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.vpn", name = "SecureVPN", icon = "🔒", version = "2.0.0", category = "security", permissions = {}, dependencies = {}, default = false, description = "Encrypt your connection and mask your IP on IC networks.", price = 1499, }) AppRegistry.Register({ app_id = "pc.firewall", name = "Firewall Pro", icon = "🛡", version = "1.1.0", category = "security", permissions = {}, dependencies = {}, default = false, description = "Block unauthorized access to your system.", price = 999, }) -- ┌─────────────────────────────────────────────┐ -- │ BUSINESS │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.finance", name = "Finance Manager", icon = "💰", version = "1.0.0", category = "business", permissions = {}, dependencies = {}, default = false, description = "Track income, expenses and bank account balances.", price = 4999, }) -- ┌─────────────────────────────────────────────┐ -- │ GOVERNMENT (job-locked) │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.police.mdw", name = "Police MDW", icon = "🔍", version = "3.0.1", category = "government", permissions = { job = "police" }, dependencies = {}, default = false, description = "Mobile Data Workstation: criminal records, warrants, BOLO alerts.", price = 0, }) AppRegistry.Register({ app_id = "pc.police.dispatch", name = "Dispatch Board", icon = "🚔", version = "2.1.0", category = "government", permissions = { job = "police" }, dependencies = {}, default = false, description = "Live dispatch board for law enforcement units.", price = 0, }) AppRegistry.Register({ app_id = "pc.ems", name = "EMS Dashboard", icon = "🏥", version = "1.2.0", category = "government", permissions = { job = "ambulance" }, dependencies = {}, default = false, description = "Patient management and ambulance dispatch system.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ ENTERTAINMENT │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.music", name = "TuneStream", icon = "🎵", version = "1.0.0", category = "entertainment", permissions = {}, dependencies = {}, default = false, description = "Stream in-character radio stations and playlists.", price = 999, }) -- ┌─────────────────────────────────────────────┐ -- │ PARKING JOB │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.parkuhr", name = "Parkuhr Dashboard", icon = "🅿", version = "1.0.0", category = "government", permissions = { job = "parking" }, dependencies = {}, default = false, description = "Parking management dashboard – device overview, revenue tracking and tariff management.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ IC-VERWALTUNG (Behörden) │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.ic_verwaltung", name = "IC-Verwaltung", icon = "🏛", version = "1.0.0", category = "government", permissions = { jobs = { "police", "ambulance", "dpa", "fire", "doj" } }, dependencies = {}, default = false, description = "Zugang zum IC-Verwaltungsportal. Nur für Behörden: PD, MD, DPA, FD, DOJ.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ GESETZBUCH (öffentliche Gesetze-Übersicht) │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.gesetzbuch", name = "Gesetzbuch", icon = "📖", version = "1.0.0", category = "government", permissions = {}, dependencies = {}, default = false, description = "Öffentliche Übersicht aller Gesetzbücher und Paragraphen des Bundesstaates San Andreas – ohne Login einsehbar.", price = 0, }) -- ┌─────────────────────────────────────────────┐ -- │ BLEETER │ -- └─────────────────────────────────────────────┘ -- ┌─────────────────────────────────────────────┐ -- │ DARKNET (requires VPN) │ -- └─────────────────────────────────────────────┘ AppRegistry.Register({ app_id = "pc.darkbrowser", name = "Dark Browser", icon = "🕵", version = "0.9.0", category = "darknet", permissions = {}, dependencies = { "pc.vpn" }, default = false, description = "Access the hidden IC darknet. Requires SecureVPN. Use at your own risk.", price = 2499, }) end)