-- ───────────────────────────────────────────────────────────────────────────── -- Store handlers – install / uninstall / list -- ───────────────────────────────────────────────────────────────────────────── -- ── List store ─────────────────────────────────────────────────────────────── RegisterNetEvent('pc-live:server:getStore', function() local src = source local user = ActiveSessions[src] if not user then return end local installs = DB.GetInstalls(user.dbId) local storeList = AppRegistry.BuildStoreList(installs) TriggerClientEvent('pc-live:client:storeData', src, storeList) end) -- ── Install app ────────────────────────────────────────────────────────────── RegisterNetEvent('pc-live:server:installApp', function(appId) local src = source local user = ActiveSessions[src] if not user then return end if type(appId) ~= "string" then return end appId = appId:sub(1, 64) local manifest = AppRegistry.Get(appId) if not manifest then Bridge.Notify(src, "App not found.", "error") return end -- Fetch installs once – used for all checks below local installs = DB.GetInstalls(user.dbId) -- Already installed and up to date? local installedVersion = nil for _, row in ipairs(installs) do if row.app_id == appId then installedVersion = row.version break end end if installedVersion and installedVersion == manifest.version then Bridge.Notify(src, "Already installed.", "primary") return end -- Job permission check (single job OR list of jobs) local perms = manifest.permissions or {} if perms.job or perms.jobs then local playerJob = Bridge.GetJob and Bridge.GetJob(src) or nil local allowed = false if perms.jobs and type(perms.jobs) == "table" then for _, j in ipairs(perms.jobs) do if j == playerJob then allowed = true; break end end elseif perms.job then allowed = (playerJob == perms.job) end if not allowed then local jobList = perms.jobs and table.concat(perms.jobs, ", ") or perms.job Bridge.Notify(src, ("Zugriff verweigert. Benötigt: %s"):format(jobList), "error") return end end -- Dependency check if manifest.dependencies and #manifest.dependencies > 0 then local installedMap = {} for _, row in ipairs(installs) do installedMap[row.app_id] = true end for _, depId in ipairs(manifest.dependencies) do if not installedMap[depId] then local dep = AppRegistry.Get(depId) Bridge.Notify(src, ("Missing dependency: %s"):format(dep and dep.name or depId), "error") return end end end -- Price check local price = manifest.price or 0 if price > 0 then local balance = Bridge.GetMoney(src, "bank") if balance < price then Bridge.Notify(src, ("Insufficient funds. Required: $%d"):format(price), "error") return end Bridge.RemoveMoney(src, "bank", price) end DB.InstallApp(user.dbId, appId, manifest.version) -- Refresh desktop icons AND store view local updated = DB.GetInstalls(user.dbId) TriggerClientEvent('pc-live:client:installedApps', src, AppRegistry.BuildInstalledList(updated)) TriggerClientEvent('pc-live:client:storeData', src, AppRegistry.BuildStoreList(updated)) Bridge.Notify(src, ("%s installed."):format(manifest.name), "success") end) -- ── Uninstall app ──────────────────────────────────────────────────────────── RegisterNetEvent('pc-live:server:uninstallApp', function(appId) local src = source local user = ActiveSessions[src] if not user then return end if type(appId) ~= "string" then return end appId = appId:sub(1, 64) -- Cannot uninstall default system apps local manifest = AppRegistry.Get(appId) if manifest and manifest.default then Bridge.Notify(src, "System apps cannot be uninstalled.", "error") return end DB.UninstallApp(user.dbId, appId) -- Refresh desktop icons AND store view local updated = DB.GetInstalls(user.dbId) TriggerClientEvent('pc-live:client:installedApps', src, AppRegistry.BuildInstalledList(updated)) TriggerClientEvent('pc-live:client:storeData', src, AppRegistry.BuildStoreList(updated)) Bridge.Notify(src, "App uninstalled.", "primary") end)