mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
init
This commit is contained in:
315
lua/metrostroi/sv_centralisation.lua
Normal file
315
lua/metrostroi/sv_centralisation.lua
Normal file
@@ -0,0 +1,315 @@
|
||||
|
||||
local function GetOccupation(tbl)
|
||||
if not tbl then return end
|
||||
for sID,signame in ipairs(tbl) do
|
||||
if signame[1] == "@" then
|
||||
local trigger = Metrostroi.ARMGet(signame:sub(2,-1), "trigger")
|
||||
--if not trigger then print(signame) end
|
||||
if not trigger or trigger.ARMTriggered then
|
||||
return true
|
||||
end
|
||||
elseif signame ~= "" then
|
||||
local signal = Metrostroi.ARMGet(signame, "signal")
|
||||
if not signal or signal.OccupiedBy and signal.OccupiedBy ~= signal then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Metrostroi.CentralisationPrepareRoute(station,route)
|
||||
if not Metrostroi.ARMTable[station].routes then Metrostroi.ARMTable[station].routes = {} end
|
||||
local Routes = Metrostroi.ARMTable[station].routes
|
||||
local stationT = Metrostroi.ARMConfigGenerated[station]
|
||||
if not Routes[route] then
|
||||
local segments = route.route
|
||||
for i,segm in pairs(segments) do
|
||||
if segm.inroute then
|
||||
RunConsoleCommand("say",Format("Station %d. Error building route %s, because there is already another route",station,route))
|
||||
return false
|
||||
end
|
||||
if route.ignores and (not route.ignores or not route.ignores[i]) and segm.occupied then
|
||||
RunConsoleCommand("say",Format("Station %d. Error building route %s. Route occupied!",station,route))
|
||||
return false
|
||||
end
|
||||
end
|
||||
if route.checks then
|
||||
for i,segm in pairs(route.checks) do
|
||||
if segm.inroute then
|
||||
RunConsoleCommand("say",Format("Station %d. Error building route %s, because there is already another route on protective segments",station,route))
|
||||
return false
|
||||
end
|
||||
if route.ignores and (not route.ignores or not route.ignores[i]) and segm.occupied then
|
||||
RunConsoleCommand("say",Format("Station %d. Error building route %s. Protective segments occupied!",station,route))
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _,segm in pairs(segments) do
|
||||
segm.inroute = true
|
||||
end
|
||||
Routes[route] = table.insert(Routes,route)
|
||||
RunConsoleCommand("say",Format("Station %d. Added route %s with ID:%d",station,route,Routes[route]))
|
||||
return true
|
||||
end
|
||||
end
|
||||
local function CentralistationCalculateFreeBS(segm,dir,sigconf,pSeg,rccount)
|
||||
if pSeg then
|
||||
local signal = dir and segm.signal2 or not dir and segm.signal1
|
||||
if signal then
|
||||
local ent = signal.ent
|
||||
if not ent then return 1 end
|
||||
local conf = sigconf[ent.Name]
|
||||
--return (ent.FreeBSARM or ent.FreeBS or 0)+(conf and conf.bs or 1),ent
|
||||
return (ent.FreeBSARM or ent.FreeBS or 0)+rccount,ent
|
||||
end
|
||||
end
|
||||
rccount = (rccount or 0) + 1
|
||||
if not segm or segm.occupied then
|
||||
return rccount
|
||||
end
|
||||
local alt,main = false,true
|
||||
if segm.switch then
|
||||
local switch = Metrostroi.ARMGet(segm.switch, "switch")
|
||||
main = switch and switch.MainTrack and not switch.AlternateTrack
|
||||
alt = switch and not switch.MainTrack and switch.AlternateTrack
|
||||
if not alt and not main then return 0 end
|
||||
end
|
||||
|
||||
if pSeg and segm.next_a and (segm.next_a == pSeg and not alt or segm.next_m == pSeg and not main) then return 0 end
|
||||
local segmM,segmA = segm.next_m,segm.next_a
|
||||
local segmP = segm.prev
|
||||
|
||||
|
||||
local mainM = segmM and (dir and segmM.x > segm.x or not dir and segmM.x < segm.x)
|
||||
local mainP = segmP and (dir and segmP.x > segm.x or not dir and segmP.x < segm.x)
|
||||
if mainM then
|
||||
local next
|
||||
if alt and segmA then next = segmA end
|
||||
if main and segmM then next = segmM end
|
||||
return CentralistationCalculateFreeBS(next,dir,sigconf,segm,rccount)
|
||||
end
|
||||
if segmP and mainP then
|
||||
return CentralistationCalculateFreeBS(segmP,dir,sigconf,segm,rccount)
|
||||
end
|
||||
end
|
||||
local function CentralisationSolveSignalLogic(signal,signalE,signalDir,station,segm)
|
||||
if not signalE then return end
|
||||
if station.signals and station.signals[signal] then
|
||||
local sigconf = station.signals[signal]
|
||||
signalE.ControllerLogic = station
|
||||
local target,codes = "",""
|
||||
local alt = false
|
||||
local occupied = segm.occupied
|
||||
if segm.switch then
|
||||
local switch = Metrostroi.ARMGet(segm.switch, "switch")
|
||||
local main = switch and switch.MainTrack and not switch.AlternateTrack
|
||||
alt = switch and not switch.MainTrack and switch.AlternateTrack
|
||||
if not alt and not main then occupied = true end
|
||||
end
|
||||
if alt then
|
||||
--occupied = occupied or segm.next_a and GetOccupation(segm.next_a)
|
||||
else
|
||||
--occupied = occupied or segm.next_m and GetOccupation(segm.next_m)
|
||||
end
|
||||
|
||||
local route = sigconf.route
|
||||
local free,nextSignal = CentralistationCalculateFreeBS(segm,signalDir,station.signals)
|
||||
--print(free,signalE,signalE.Name)
|
||||
local dir = route and route.dir
|
||||
if route and dir ~= signalDir then
|
||||
print(signalE.Name,dir ,signalDir)
|
||||
route = nil
|
||||
occupied = true
|
||||
end
|
||||
if sigconf.Mode == 1 then
|
||||
if occupied then
|
||||
target = sigconf.R
|
||||
codes = "2"
|
||||
elseif route then
|
||||
if nextSignal then
|
||||
local colors = nextSignal.Colors or ""
|
||||
local segments = route[2]
|
||||
--print(route)
|
||||
local start = false
|
||||
local specialS = sigconf.routes and sigconf.routes[route[1].name]
|
||||
if free < (sigconf.bs or 1) then
|
||||
target = sigconf.RY or sigconf.R
|
||||
elseif route.mode == 3 then
|
||||
target = sigconf.W
|
||||
elseif colors:find("[rR]+") and colors:find("[yY]+") then
|
||||
target = sigconf.Y or sigconf.YG or sigconf.RY or sigconf.R
|
||||
elseif colors:find("[rR]+") then
|
||||
target = sigconf.Y or sigconf.RY or sigconf.R
|
||||
elseif colors:find("[ygYG]+[ygYG]+") or colors:find("[gwGW]+") then
|
||||
target = sigconf.G or sigconf.YG or sigconf.Y or sigconf.RY or sigconf.R
|
||||
elseif colors:find("[yY]+") then
|
||||
target = sigconf.YG or sigconf.G or sigconf.Y or sigconf.RY or sigconf.R
|
||||
else
|
||||
target = sigconf.R
|
||||
end
|
||||
elseif route.mode == 3 then
|
||||
target = sigconf.W
|
||||
else
|
||||
target = sigconf.R
|
||||
end
|
||||
else
|
||||
if free and free < 1 then
|
||||
target = sigconf.R or sigconf.RY or ""
|
||||
else
|
||||
target = sigconf.RY or sigconf.R
|
||||
end
|
||||
codes = "0"
|
||||
end
|
||||
signalE.Red = target==sigconf.R or target==sigconf.RY
|
||||
signalE.AutoEnabled = signalE.AutoEnabled
|
||||
else
|
||||
|
||||
end
|
||||
local sig = ""
|
||||
for i=1,#target do
|
||||
local id = tonumber(target[i])
|
||||
if not id then continue end
|
||||
if #sig < id then sig = sig..string.rep("0",id-#sig) end
|
||||
sig = string.SetChar(sig,tonumber(target[i]),target[i+1]=="b" and "2" or "1")
|
||||
end
|
||||
signalE.Sig = sig
|
||||
signalE.FreeBSARM = occupied and 0 or free
|
||||
signalE.FreeBS = math.ceil(signalE.FreeBSARM or 0)
|
||||
--print(occupied,free,signalE.FreeBS)
|
||||
--print(signalE.Colors,target,signalE.Sig)
|
||||
end
|
||||
end
|
||||
local function CentralisationSolveRoutesLogic(stationID,station)
|
||||
local Routes = Metrostroi.ARMTable[stationID].routes
|
||||
local HasPrepared = true
|
||||
for k,route in ipairs(Routes) do
|
||||
local segments = route.route
|
||||
local directions = route.directions
|
||||
if route.prepared then
|
||||
--HasPrepared = true
|
||||
local done,occupiedN,halfroute = true--,100
|
||||
for segmID,segm in ipairs(segments) do
|
||||
if segm.occupied then
|
||||
if not occupiedN or occupiedN < segmID then occupiedN = segmID end
|
||||
end
|
||||
if segm.route then done = false end
|
||||
if not segm.route then halfroute = true end
|
||||
end
|
||||
if occupiedN then
|
||||
for segmID,segm in ipairs(segments) do
|
||||
if segmID > occupiedN then break end
|
||||
if segm.route == route then
|
||||
segm.route = false
|
||||
segm.inroute = false
|
||||
local signal = route[3] and segm.signal2 or not route[3] and segm.signal1
|
||||
local sig = Metrostroi.ARMGet(signal and signal.name, "signal")
|
||||
end
|
||||
end
|
||||
end
|
||||
if done or halfroute and not occupiedN then
|
||||
for _,segm in ipairs(segments) do
|
||||
segm.inroute = false
|
||||
segm.route = false
|
||||
end
|
||||
for i,signame in pairs(route.signals) do
|
||||
if not station.signals[signame] then continue end
|
||||
station.signals[signame].route = nil
|
||||
end
|
||||
RunConsoleCommand("say",Format("Station %d. Route %s(%d) has destroyed",stationID,route,Routes[route]))
|
||||
table.remove(Routes,Routes[route])
|
||||
Routes[route] = nil
|
||||
for i,v in pairs(Routes) do Routes[v] = i end
|
||||
route.prepared = false
|
||||
end
|
||||
else
|
||||
local Prepared = true
|
||||
--Check for occupation
|
||||
for i,segm in ipairs(segments) do
|
||||
if route.ignores and not route.ignores[i] and segm.occupied then Prepared = false break end
|
||||
if segm.route then Prepared = false break end
|
||||
end
|
||||
--If there is no occupation - check and prepare switches
|
||||
if Prepared then
|
||||
for segmID,segm in ipairs(segments) do
|
||||
if not segm.switch then continue end
|
||||
local switch = Metrostroi.ARMGet(segm.switch, "switch")
|
||||
if not switch then continue end
|
||||
local dir = directions[segmID]
|
||||
|
||||
local main = switch and switch.MainTrack and not switch.AlternateTrack
|
||||
local alt = switch and not switch.MainTrack and switch.AlternateTrack
|
||||
--print(route[3],switch,dir)
|
||||
if dir and main or not dir and alt or (not main and not alt) then
|
||||
switch:SwitchTo(dir and "alt" or "main")
|
||||
Prepared = false
|
||||
print("Move",segmID,segm.switch,switch,dir and "alt" or "main")
|
||||
end
|
||||
if not main and not alt then Prepared = false end
|
||||
end
|
||||
end
|
||||
if Prepared then
|
||||
for k,segm in ipairs(segments) do
|
||||
segm.route = route
|
||||
local signal = route[3] and segm.signal2 or not route[3] and segm.signal1
|
||||
local sig = Metrostroi.ARMGet(signal and signal.name, "signal")
|
||||
end
|
||||
for i,signame in pairs(route.signals) do
|
||||
if not station.signals[signame] then continue end
|
||||
station.signals[signame].route = route
|
||||
end
|
||||
route.prepared = true
|
||||
RunConsoleCommand("say",Format("Station %d. Route %s(%d) has assembled",stationID,route,Routes[route]))
|
||||
end
|
||||
end
|
||||
end
|
||||
return HasPrepared
|
||||
end
|
||||
|
||||
function Metrostroi.Centralisation()
|
||||
if not Metrostroi.ARMConfigGenerated then return end
|
||||
for stationID,station in pairs(Metrostroi.ARMConfigGenerated) do
|
||||
--Route logic
|
||||
local HasPrepared = CentralisationSolveRoutesLogic(stationID,station)
|
||||
|
||||
for name, signal in pairs(station.signals) do
|
||||
if signal.sig then
|
||||
local ent = Metrostroi.ARMGet(name, "signal")
|
||||
signal.sig.ent = ent
|
||||
CentralisationSolveSignalLogic(name,ent,signal.sig.dir,station,signal.segm)
|
||||
end
|
||||
end
|
||||
for segmID, segm in ipairs(station) do
|
||||
segm.occupied = segm._occup or GetOccupation(segm.occup) or GetOccupation(segm.occupAlt)
|
||||
if true then
|
||||
if segm.switch then
|
||||
local switch = Metrostroi.ARMGet(segm.switch, "switch")
|
||||
local main = switch and switch.MainTrack and not switch.AlternateTrack
|
||||
local alt = switch and not switch.MainTrack and switch.AlternateTrack
|
||||
if switch and not segm.route and not segm.inroute and not segm.occupied and (alt or not main and not alt) then
|
||||
switch:SwitchTo("main")
|
||||
print("Reset",segm.switch,switch,segmID,segm.route)
|
||||
end
|
||||
end
|
||||
--[[ if segm.signal1 then
|
||||
local ent = Metrostroi.ARMGet(segm.signal1.name, "signal")
|
||||
segm.signal1.ent = ent
|
||||
CentralisationSolveSignalLogic(segm.signal1.name,ent,false,station,segm)
|
||||
end
|
||||
if segm.signal2 then
|
||||
local ent = Metrostroi.ARMGet(segm.signal2.name, "signal")
|
||||
segm.signal2.ent = ent
|
||||
CentralisationSolveSignalLogic(segm.signal2.name,ent,true,station,segm)
|
||||
end--]]
|
||||
--[[ if segm.route and not HasPrepared then
|
||||
segm.route = false
|
||||
segm.inroute = false
|
||||
end--]]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timer.Create("metrostroi_centralisation",0.1,0,Metrostroi.Centralisation)
|
||||
Reference in New Issue
Block a user