42.20 and Towtrucks
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
if not TowBarMod then TowBarMod = {} end
|
||||
TowBarMod.Persistence = TowBarMod.Persistence or {}
|
||||
|
||||
local Persistence = TowBarMod.Persistence
|
||||
local RegistryName = "TowBar.PersistentPairsV2"
|
||||
|
||||
local function getRegistry()
|
||||
if not ModData or not ModData.getOrCreate then return nil end
|
||||
local registry = ModData.getOrCreate(RegistryName)
|
||||
registry.pairs = registry.pairs or {}
|
||||
return registry
|
||||
end
|
||||
|
||||
local function getSqlId(vehicle)
|
||||
if not vehicle or not vehicle.getSqlId then return nil end
|
||||
local ok, sqlId = pcall(function() return vehicle:getSqlId() end)
|
||||
if ok and type(sqlId) == "number" and sqlId >= 0 then return sqlId end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function makeKey(kind, towingSqlId, towedSqlId)
|
||||
if type(kind) ~= "string" or type(towingSqlId) ~= "number" or type(towedSqlId) ~= "number" then
|
||||
return nil
|
||||
end
|
||||
return kind .. ":" .. tostring(towingSqlId) .. ":" .. tostring(towedSqlId)
|
||||
end
|
||||
|
||||
local function transmit()
|
||||
if isServer and isServer() and ModData.transmit then
|
||||
ModData.transmit(RegistryName)
|
||||
end
|
||||
end
|
||||
|
||||
function Persistence.savePair(kind, towingVehicle, towedVehicle, attachmentA, attachmentB, heightLevel)
|
||||
local towingSqlId = getSqlId(towingVehicle)
|
||||
local towedSqlId = getSqlId(towedVehicle)
|
||||
local key = makeKey(kind, towingSqlId, towedSqlId)
|
||||
local registry = getRegistry()
|
||||
if not key or not registry then return false end
|
||||
local previous = registry.pairs[key]
|
||||
if previous and previous.attachmentA == attachmentA and previous.attachmentB == attachmentB
|
||||
and previous.heightLevel == heightLevel then
|
||||
return true
|
||||
end
|
||||
registry.pairs[key] = {
|
||||
kind = kind,
|
||||
towingSqlId = towingSqlId,
|
||||
towedSqlId = towedSqlId,
|
||||
attachmentA = attachmentA,
|
||||
attachmentB = attachmentB,
|
||||
heightLevel = heightLevel
|
||||
}
|
||||
transmit()
|
||||
return true
|
||||
end
|
||||
|
||||
function Persistence.getPair(kind, towingVehicle, towedVehicle)
|
||||
local key = makeKey(kind, getSqlId(towingVehicle), getSqlId(towedVehicle))
|
||||
local registry = getRegistry()
|
||||
return key and registry and registry.pairs[key] or nil
|
||||
end
|
||||
|
||||
function Persistence.removePair(kind, towingVehicle, towedVehicle)
|
||||
local key = makeKey(kind, getSqlId(towingVehicle), getSqlId(towedVehicle))
|
||||
local registry = getRegistry()
|
||||
if not key or not registry or registry.pairs[key] == nil then return false end
|
||||
registry.pairs[key] = nil
|
||||
transmit()
|
||||
return true
|
||||
end
|
||||
|
||||
function Persistence.forEachPair(kind, callback)
|
||||
local registry = getRegistry()
|
||||
if not registry or not callback then return end
|
||||
for _, record in pairs(registry.pairs) do
|
||||
if type(record) == "table" and record.kind == kind then callback(record) end
|
||||
end
|
||||
end
|
||||
|
||||
function Persistence.notePeerAvailability(state, available)
|
||||
state = state or {}
|
||||
if not available then
|
||||
state.peerMissing = true
|
||||
return state
|
||||
end
|
||||
if state.peerMissing then
|
||||
-- A missing vehicle means its cell was not loaded. When both members
|
||||
-- return, treat the absent native constraint as load recovery rather
|
||||
-- than a runtime break of a previously confirmed pair.
|
||||
state.peerMissing = nil
|
||||
state.confirmed = false
|
||||
state.pendingUntil = nil
|
||||
state.unlinkedSince = nil
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
function Persistence.advanceRecoveryState(state, now, linked, occupied, retryMs, breakMs)
|
||||
state = state or {}
|
||||
if linked then
|
||||
state.confirmed = true
|
||||
state.pendingUntil = nil
|
||||
state.unlinkedSince = nil
|
||||
return state, "adopt"
|
||||
end
|
||||
if occupied then
|
||||
state.unlinkedSince = nil
|
||||
return state, "wait"
|
||||
end
|
||||
if state.confirmed then
|
||||
state.unlinkedSince = state.unlinkedSince or now
|
||||
if now - state.unlinkedSince >= breakMs then return state, "break" end
|
||||
return state, "wait"
|
||||
end
|
||||
if not state.pendingUntil or now >= state.pendingUntil then
|
||||
state.pendingUntil = now + retryMs
|
||||
return state, "restore"
|
||||
end
|
||||
return state, "wait"
|
||||
end
|
||||
|
||||
Persistence.getSqlId = getSqlId
|
||||
Reference in New Issue
Block a user