236 lines
6.5 KiB
Lua
236 lines
6.5 KiB
Lua
local util = require("util")
|
|
|
|
local fuel_signal = "%[virtual%-signal=refuel%-signal]"
|
|
local fuel_signal_disabled = "%[virtual%-signal=refuel%-signal%-disabled]"
|
|
|
|
local depot_signal = "%[virtual%-signal=depot%-signal]"
|
|
local depot_signal_disabled = "%[virtual%-signal=depot%-signal%-disabled]"
|
|
|
|
local skip_signal = "%[virtual%-signal=skip%-signal]"
|
|
|
|
local train_needs_refueling = function(train)
|
|
local locomotives = train.locomotives
|
|
for k, movers in pairs (locomotives) do
|
|
for k, locomotive in pairs (movers) do
|
|
local fuel_inventory = locomotive.get_fuel_inventory()
|
|
if not fuel_inventory then return false end
|
|
if #fuel_inventory == 0 then return false end
|
|
fuel_inventory.sort_and_merge()
|
|
if #fuel_inventory > 1 then
|
|
if not fuel_inventory[2].valid_for_read then
|
|
return true
|
|
end
|
|
else
|
|
--Locomotive with only 1 fuel stack... idk, lets just guess
|
|
local stack = fuel_inventory[1]
|
|
if not stack.valid_for_read then
|
|
--Nothing in the stack, needs refueling.
|
|
return true
|
|
end
|
|
if stack.count < math.ceil(stack.prototype.stack_size / 4) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local station_is_disabled = function(station)
|
|
return station:find(skip_signal)
|
|
end
|
|
|
|
local station_is_open_depot = function(station)
|
|
if not station then return false end
|
|
return station:find(depot_signal) and not station_is_disabled(station)
|
|
end
|
|
|
|
local train_needs_depot = function(train, old_state)
|
|
|
|
local schedule = train.schedule
|
|
if not schedule then return end
|
|
|
|
if train.state == defines.train_state.wait_station then
|
|
-- We just arrived at a station, if its a depot station keep it open
|
|
return station_is_open_depot(schedule.records[schedule.current].station)
|
|
end
|
|
|
|
if old_state == defines.train_state.no_path then
|
|
--We had no path, now we do
|
|
--We only keep depots open if we are going to a depot
|
|
return station_is_open_depot(schedule.records[schedule.current].station)
|
|
end
|
|
|
|
if old_state == defines.train_state.destination_full then
|
|
--We had no path, now we do
|
|
--We only keep depots open if we are going to a depot
|
|
return station_is_open_depot(schedule.records[schedule.current].station)
|
|
end
|
|
|
|
if old_state == defines.train_state.wait_station then
|
|
--We just left a station
|
|
if train.has_path then
|
|
--We have a path, if we're going to a depot, we keep it open.
|
|
return station_is_open_depot(schedule.records[schedule.current].station)
|
|
end
|
|
return true
|
|
end
|
|
|
|
end
|
|
|
|
local care_about =
|
|
{
|
|
[defines.train_state.wait_station] = true,
|
|
[defines.train_state.no_path] = true,
|
|
[defines.train_state.destination_full] = true,
|
|
}
|
|
|
|
local on_train_changed_state = function(event)
|
|
|
|
local train = event.train
|
|
if not (train and train.valid) then return end
|
|
|
|
if not (care_about[train.state] or care_about[event.old_state]) then
|
|
-- Some state that we don't care about
|
|
return
|
|
end
|
|
|
|
local schedule = train.schedule
|
|
if not schedule then return end
|
|
|
|
local needs_refuel = train_needs_refueling(train)
|
|
local needs_depot = train_needs_depot(train, event.old_state)
|
|
local changed = false
|
|
for k, record in pairs (schedule.records) do
|
|
local station = record.station
|
|
if station then
|
|
local enable = false
|
|
local disable = false
|
|
if station:find(fuel_signal) then
|
|
enable = needs_refuel
|
|
disable = not enable
|
|
end
|
|
if station:find(depot_signal) then
|
|
enable = enable or needs_depot
|
|
disable = not enable
|
|
end
|
|
if enable and station:find(skip_signal) then
|
|
record.station = station:gsub(skip_signal, "")
|
|
changed = true
|
|
end
|
|
if disable and not station:find(skip_signal) then
|
|
record.station = skip_signal:gsub("%%", "") .. station
|
|
changed = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if not changed then return end
|
|
|
|
if needs_depot then
|
|
|
|
-- We are able to go to a depot, but we only want to do that if it is in the schedule in the correct order
|
|
-- What that means, is we just check if the previous station in the schedule is a depot, if so, go there, if not, we stay with destination full.
|
|
|
|
local current = schedule.current
|
|
local index = current
|
|
while true do
|
|
index = index - 1
|
|
if index == 0 then index = #schedule.records end
|
|
if index == current then break end
|
|
if station_is_open_depot(schedule.records[index].station) then
|
|
schedule.current = index
|
|
break
|
|
end
|
|
if not station_is_disabled(schedule.records[index].station) then
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
train.schedule = schedule
|
|
|
|
end
|
|
|
|
local check_rename_signal = function(entity, old_name, enabled_name)
|
|
|
|
local new_name = entity.backer_name
|
|
|
|
if new_name:find(skip_signal) then
|
|
--naughty...
|
|
entity.backer_name = new_name:gsub(skip_signal, "")
|
|
return
|
|
end
|
|
|
|
if not old_name:find(enabled_name) then
|
|
return
|
|
end
|
|
|
|
--old name had a control signal, lets emulate the base game thing where it fixes the schedules
|
|
|
|
local stops = entity.force.get_train_stops({surface = entity.surface, name = old_name})
|
|
if next(stops) then
|
|
--there are still some with the old name, do nothing
|
|
return
|
|
end
|
|
|
|
local old_disabled_name = skip_signal:gsub("%%", "") .. old_name
|
|
local new_disabled_name = skip_signal:gsub("%%", "") .. new_name
|
|
|
|
local trains = entity.force.get_trains(entity.surface)
|
|
|
|
for k, train in pairs (trains) do
|
|
local schedule = train.schedule
|
|
if schedule then
|
|
local changed = false
|
|
for k, record in pairs(schedule.records) do
|
|
if record.station then
|
|
if record.station == old_disabled_name then
|
|
changed = true
|
|
record.station = new_disabled_name
|
|
end
|
|
end
|
|
end
|
|
if changed then
|
|
train.schedule = schedule
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
local on_entity_renamed = function(event)
|
|
local entity = event.entity
|
|
if not (entity and entity.valid and entity.type == "train-stop") then
|
|
return
|
|
end
|
|
|
|
check_rename_signal(entity, event.old_name, fuel_signal)
|
|
check_rename_signal(entity, event.old_name, depot_signal)
|
|
|
|
end
|
|
|
|
local on_train_schedule_changed = function(event)
|
|
if event.player_index then
|
|
on_train_changed_state(event)
|
|
end
|
|
end
|
|
|
|
local lib = {}
|
|
|
|
lib.events =
|
|
{
|
|
[defines.events.on_train_changed_state] = on_train_changed_state,
|
|
[defines.events.on_entity_renamed] = on_entity_renamed,
|
|
[defines.events.on_train_schedule_changed] = on_train_schedule_changed,
|
|
}
|
|
|
|
lib.on_init = function()
|
|
end
|
|
|
|
lib.on_configuration_changed = function()
|
|
end
|
|
|
|
return lib
|