- GameConfig: RX7AllowedUserIds allowlist + isRX7Allowed/starterCarFor helpers - ProfileTemplate: no hard-coded starter; granted per-player by UserId - DataManager: grants RX-7 to allowlisted players, public car to everyone else - Economy.buyCar + CarManager.spawn: server-side refuse RX-7 for non-allowlisted - Cars: RX-7 flagged Restricted; client dealership hides it from non-owners - Gates: stylua clean, selene 0/0, rojo builds
This commit is contained in:
@@ -19,6 +19,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local Shared = ReplicatedStorage.Shared
|
||||
local Cars = require(Shared.Cars)
|
||||
local GameConfig = require(Shared.GameConfig)
|
||||
local ProfileTemplate = require(Shared.ProfileTemplate)
|
||||
local DataManager = require(script.Parent.DataManager)
|
||||
|
||||
@@ -125,6 +126,11 @@ function CarManager.spawn(player: Player, carId: string?)
|
||||
if not car then
|
||||
return
|
||||
end
|
||||
-- Defense in depth: never spawn the restricted RX-7 for a non-allowlisted user,
|
||||
-- even if their save somehow contained it.
|
||||
if car.Id == GameConfig.RestrictedStarterCarId and not GameConfig.isRX7Allowed(player.UserId) then
|
||||
return
|
||||
end
|
||||
-- Only spawn cars the player owns (anti-cheat: no spawning unowned exotics).
|
||||
local owned
|
||||
for _, o in ipairs(data.OwnedCars) do
|
||||
|
||||
@@ -71,6 +71,22 @@ local function onPlayerAdded(player: Player)
|
||||
profile:AddUserId(player.UserId) -- GDPR-friendly association
|
||||
profile:Reconcile() -- fill missing template keys
|
||||
|
||||
-- Grant the correct starter car for THIS player (RX-7 only for allowlisted
|
||||
-- UserIds; everyone else gets the public starter). Idempotent: only grants
|
||||
-- if the player has no cars yet (i.e. genuinely first join).
|
||||
local data = profile.Data
|
||||
if #data.OwnedCars == 0 then
|
||||
local starterId = GameConfig.starterCarFor(player.UserId)
|
||||
table.insert(data.OwnedCars, {
|
||||
Id = starterId,
|
||||
Upgrades = { Engine = 0, Tires = 0, Nitro = 0 },
|
||||
})
|
||||
data.EquippedCarId = starterId
|
||||
elseif data.EquippedCarId == "" then
|
||||
-- Safety: if somehow they own cars but have nothing equipped, equip the first.
|
||||
data.EquippedCarId = data.OwnedCars[1].Id
|
||||
end
|
||||
|
||||
profile.OnSessionEnd:Connect(function()
|
||||
-- The session was lost (another server stole it, or we released it).
|
||||
profiles[player] = nil
|
||||
|
||||
@@ -88,6 +88,10 @@ function Economy.buyCar(player: Player, carId: string): Result
|
||||
if not car then
|
||||
return { ok = false, reason = "Unknown car" }
|
||||
end
|
||||
-- Restricted demo car: the RX-7 can only ever be owned by allowlisted UserIds.
|
||||
if car.Id == GameConfig.RestrictedStarterCarId and not GameConfig.isRX7Allowed(player.UserId) then
|
||||
return { ok = false, reason = "This car is not available" }
|
||||
end
|
||||
if ownsCar(data, carId) then
|
||||
return { ok = false, reason = "You already own this car" }
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user