269 lines
10 KiB
Lua

--[[ Copyright (c) 2017 Optera
* Part of Logistics Train Network
*
* See LICENSE.md in the project directory for license information.
--]]
on_stops_updated_event = script.generate_event_name()
on_dispatcher_updated_event = script.generate_event_name()
on_dispatcher_no_train_found_event = script.generate_event_name()
on_delivery_created_event = script.generate_event_name()
on_delivery_pickup_complete_event = script.generate_event_name()
on_delivery_completed_event = script.generate_event_name()
on_delivery_failed_event = script.generate_event_name()
on_provider_missing_cargo_alert = script.generate_event_name()
on_provider_unscheduled_cargo_alert = script.generate_event_name()
on_requester_unscheduled_cargo_alert = script.generate_event_name()
on_requester_remaining_cargo_alert = script.generate_event_name()
-- ltn_interface allows mods to register for update events
remote.add_interface("logistic-train-network", {
-- updates for ltn_stops
on_stops_updated = function() return on_stops_updated_event end,
-- updates for dispatcher
on_dispatcher_updated = function() return on_dispatcher_updated_event end,
on_dispatcher_no_train_found = function() return on_dispatcher_no_train_found_event end,
on_delivery_created = function() return on_delivery_created_event end,
-- update for updated deliveries after leaving provider
on_delivery_pickup_complete = function() return on_delivery_pickup_complete_event end,
-- update for completing deliveries
on_delivery_completed = function() return on_delivery_completed_event end,
on_delivery_failed = function() return on_delivery_failed_event end,
-- alerts
on_provider_missing_cargo = function() return on_provider_missing_cargo_alert end,
on_provider_unscheduled_cargo = function() return on_provider_unscheduled_cargo_alert end,
on_requester_unscheduled_cargo = function() return on_requester_unscheduled_cargo_alert end,
on_requester_remaining_cargo = function() return on_requester_remaining_cargo_alert end,
-- surface connections
connect_surfaces = ConnectSurfaces, -- function(entity1 :: LuaEntity, entity2 :: LuaEntity, network_id :: int32)
disconnect_surfaces = DisconnectSurfaces, -- function(entity1 :: LuaEntity, entity2 :: LuaEntity)
clear_all_surface_connections = ClearAllSurfaceConnections,
-- Re-assigns a delivery to a different train.
reassign_delivery = ReassignDelivery, -- function(old_train_id :: uint, new_train :: LuaTrain) :: bool
get_or_create_next_temp_stop = GetOrCreateNextTempStop, -- function(train :: LuaTrain, schedule_index :: uint?) :: uint
get_next_logistic_stop = GetNextLogisticStop, -- function(train :: LuaTrain, schedule_index :: uint?) :: uint?, uint?, string?
})
--[[ register events from LTN:
if remote.interfaces["logistic-train-network"] then
script.on_event(remote.call("logistic-train-network", "on_stops_updated"), on_stops_updated)
script.on_event(remote.call("logistic-train-network", "on_dispatcher_updated"), on_dispatcher_updated)
end
]]--
--[[ EVENTS
on_stops_updated
Raised every UpdateInterval, after delivery generation
-> Contains:
logistic_train_stops = { [stop_id :: uint], {
-- stop data
active_deliveries :: int,
entity :: LuaEntity,
input :: LuaEntity,
output :: LuaEntity,
lamp_control :: LuaEntity,
error_code :: int,
-- control signals
is_depot :: bool,
depot_priority :: int32,
network_id :: int32,
max_carriages :: int32,
min_carriages :: int32,
max_trains :: int32,
providing_threshold :: int32,
providing_threshold_stacks :: int32,
provider_priority :: int32,
requesting_threshold :: int32,
requesting_threshold_stacks :: int32,
requester_priority :: int32,
locked_slots :: int32,
no_warnings :: bool,
-- parked train data
parked_train :: LuaTrain,
parked_train_id :: uint,
parked_train_faces_stop :: bool,
}}
on_dispatcher_updated
Raised every UpdateInterval, after delivery generation
-> Contains:
update_interval = int -- time in ticks LTN needed to run all updates, varies depending on number of stops and requests
provided_by_stop = { [stop_id :: uint], { [item :: string], count :: int } }
requests_by_stop = { [stop_id :: uint], { [item :: string], count :: int } }
new_deliveries = { uint } -- train_ids of deliveries created this UpdateInterval
deliveries = { [train_id :: uint], {
force :: LuaForce,
train :: LuaTrain,
from :: string,
from_id :: uint,
to :: string,
to_id :: uint,
network_id: int32,
started :: uint, -- tick this delivery was created on
surface_connections = { entity1 :: LuaEntity, entity2 :: LuaEntity, network_id :: int32 },
shipment = { [item :: string], count :: int }
} }
available_trains = { [train_id :: uint], {
capacity :: int,
fluid_capacity :: int,
force :: LuaForce,
surface :: LuaSurface,
depot_priority :: int32,
network_id :: int32,
train :: LuaTrain
} }
on_dispatcher_no_train_found
Raised when no train was found to handle a request
-> Contains:
to :: string -- requester.backer_name
to_id :: uint -- requester.unit_number
network_id :: int32
(optional) item :: string
(optional) from :: string
(optional) from_id :: uint
(optional) min_carriages :: int32
(optional) max_carriages :: int32
(optional) shipment = { [item :: string], count :: int }
on_delivery_pickup_complete
Raised when a train leaves provider stop
-> Contains:
train_id :: uint
train :: LuaTrain
planned_shipment= { [item :: string], count :: int }
actual_shipment = { [item :: string], count :: int } -- shipment updated to train inventory
on_delivery_completed
Raised when train leaves requester stop
-> Contains:
train_id :: uint
train :: LuaTrain
shipment= { [item :: string], count :: int }
on_delivery_failed
Raised when rolling stock of a train gets removed, the delivery timed out, train enters depot stop with active delivery
-> Contains:
train_id :: uint
shipment= { [item :: string], count :: int } }
---- Alerts ----
on_dispatcher_no_train_found
Raised when depot was empty
-> Contains:
to :: string
to_id :: uint
network_id :: int32
item :: string -- <type,name>
on_dispatcher_no_train_found
Raised when no matching train was found
-> Contains:
to :: string
to_id :: uint
network_id :: int32
from :: string
from_id :: uint
min_carriages :: int32
max_carriages :: int32
shipment = { [item :: string], count :: int } }
on_provider_missing_cargo
Raised when trains leave provider with less than planned load
-> Contains:
train :: LuaTrain
station :: LuaEntity
planned_shipment = { [item :: string], count :: int } }
actual_shipment = { [item :: string], count :: int } }
on_provider_unscheduled_cargo
Raised when trains leave provider with wrong cargo
-> Contains:
train :: LuaTrain
station :: LuaEntity
planned_shipment = { [item :: string], count :: int } }
unscheduled_load = { [item :: string], count :: int } }
on_requester_unscheduled_cargo
Raised when trains arrive at requester with wrong cargo
-> Contains:
train :: LuaTrain
station :: LuaEntity
planned_shipment = { [item :: string], count :: int } }
unscheduled_load = { [item :: string], count :: int } }
on_requester_remaining_cargo
Raised when trains leave requester with remaining cargo
-> Contains:
train :: LuaTrain
station :: LuaEntity
remaining_load = { [item :: string], count :: int } }
--]]
--[[ REMOTE CALLS
usage:
if remote.interfaces["logistic-train-network"] then
remote.call("logistic-train-network", "<name>", <parameters>?)
end
connect_surfaces(entity1 :: LuaEntity, entity2 :: LuaEntity, network_id :: int32)
Designates two entities on different surfaces as forming a surface connection.
Connections are bi-directional but not transitive, i.e. surface A -> B implies B -> A, but A -> B and B -> C does not imply A -> C.
LTN will generate deliveries between depot and provider on one surface and requester on the other.
Network_id acts as additional mask for potential providers.
It is the caller's responsibility to ensure:
1) trains are moved between surfaces
2) deliveries are updated to the new train after surface transition, see reassign_delivery()
3) trains return to their original surface depot
disconnect_surfaces(entity1 :: LuaEntity, entity2 :: LuaEntity)
Removes a surface connection formed by the two given entities.
Active deliveries will not be affected.
It's not necessary to call this function when deleting one or both entities.
clear_all_surface_connections()
Clears all surface connections.
Active deliveries will not be affected
This function exists for debugging purposes, no event is raised to notify connection owners.
reassign_delivery(old_train_id :: uint, new_train :: LuaTrain) :: bool
Re-assigns a delivery to a different train.
Should be called after creating a train based on another train, for example after moving a train to a different surface.
Calls with an old_train_id without delivery have no effect.
Don't call this function when coupling trains via script, LTN already handles that through Factorio events.
This function does not add missing temp stops. See get_or_create_next_temp_stop for that.
get_or_create_next_temp_stop(train :: LuaTrain, schedule_index :: uint?) :: uint
Ensures the next logistic stop in the schedule has a temporary stop if it is on the same surface as the train.
If no schedule_index is given, the search for the next logistic stop starts from train.schedule.current
In case the train is currently stopping at that index, the search starts at the next higher index.
The result will be the schedule index of the temp stop of the next logistic stop or nil if there is no further logistic stop.
get_next_logistic_stop(train :: LuaTrain, schedule_index :: uint?) :: uint?, uint?, string?
Finds the next logistic stop in the schedule of the given train.
If no schedule_index is given, the search starts from train.schedule.current.
In case the train is currently stopping at that index, the search starts at the next higher index.
The result will be three values stop_schedule_index, stop_id and either the string "provider" or "requester".
If there is no further logistic stop in the schedule, the result will be nil.
--]]