z_mirror/Krastorio2
git clone https://git.raiguard.me/z_mirror/Krastorio2
5c23cc70
trunk
1local flib_direction =require ( "__flib__.direction" ) 2local flib_position =require ( "__flib__.position" ) 3 4local loader_snapping_enabled =true 5 6--- @type table<defines.direction, Vector> 7local offsets ={ 8[ defines . direction . north ] ={ 0 , - 1 } , 9[ defines . direction . east ] ={ 1 , 0 } , 10[ defines . direction . south ] ={ 0 , 1 } , 11[ defines . direction . west ] ={ - 1 , 0 } , 12} 13 14local belt_types ={ 15"linked-belt" , 16"loader" , 17"loader-1x1" , 18"splitter" , 19"transport-belt" , 20"underground-belt" , 21} 22 23local container_types ={ 24"assembling-machine" , 25"beacon" , 26"boiler" , 27"burner-generator" , 28"container" , 29"curved-rail" , 30"furnace" , 31"infinity-container" , 32"lab" , 33"linked-container" , 34"logistic-container" , 35"mining-drill" , 36"proxy-container" , 37"rail" , 38"reactor" , 39"rocket-silo" , 40"straight-rail" , 41} 42 43--- @param entity LuaEntity 44local function flip_loader ( entity ) 45entity . direction =flib_direction . opposite ( entity . direction ) 46entity . loader_type =entity . loader_type == "output" and "input" or "output" 47end 48 49--- Find entities and entity ghosts of the corresponding types. 50--- @param surface LuaSurface 51--- @param position MapPosition 52--- @param force ForceID 53--- @param types string[] 54--- @return LuaEntity[] 55local function find_entities ( surface , position , force , types ) 56local entities =surface . find_entities_filtered ( { 57force =force , 58position =position , 59type =types , 60} ) 61local ghosts =surface . find_entities_filtered ( { 62force =force , 63ghost_type =types , 64position =position , 65} ) 66for i =1 , # ghosts do 67entities [ # entities + 1 ] =ghosts [ i ] 68end 69return entities 70end 71 72--- Ensure that the loader has the belt on the correct side. 73--- @param entity LuaEntity 74local function snap_direction ( entity ) 75local offset_direction =entity . direction 76if entity . loader_type == "input" then 77offset_direction =flib_direction . opposite ( offset_direction ) 78end 79local container_position =flib_position . add ( entity . position , offsets [ offset_direction ]) 80 81-- Case 1: If a container is in front, then flip the loader 82local containers =find_entities ( entity . surface , container_position , entity . force , container_types ) 83if # containers > 0 then 84-- Check that it's not a composite loader entity 85local is_composite =entity . surface . count_entities_filtered ( { 86force =entity . force , 87position =container_position , 88type ={ "loader" , "loader-1x1" } , 89} ) > 0 90if not is_composite then 91flip_loader ( entity ) 92return 93end 94end 95 96-- Case 2: If a belt is behind, then flip the loader 97offset_direction =flib_direction . opposite ( offset_direction ) 98local belt_position =flib_position . add ( entity . position , offsets [ offset_direction ]) 99local belt =find_entities ( entity . surface , belt_position , entity . force , belt_types )[ 1 ] 100if not belt then 101return 102end 103 104local belt_type =belt . type 105if belt_type == "entity-ghost" then 106belt_type =belt . ghost_type 107end 108if 109belt_type == "transport-belt" 110or belt_type == "underground-belt" 111or math . abs ( offset_direction - belt . direction ) % 4 == 0 112then 113flip_loader ( entity ) 114end 115end 116 117--- @param entity LuaEntity 118local function snap_to_belt ( entity ) 119local offset_direction =entity . direction 120if entity . loader_type == "input" then 121offset_direction =flib_direction . opposite ( offset_direction ) 122end 123local belt_position =flib_position . add ( entity . position , offsets [ offset_direction ]) 124 125local belt =find_entities ( entity . surface , belt_position , entity . force , belt_types )[ 1 ] 126if not belt then 127return 128end 129 130local belt_direction =belt . direction 131local belt_type =belt . type 132if belt_type == "entity-ghost" then 133belt_type =belt . ghost_type 134end 135if entity . direction == belt_direction then 136-- Pass 137elseif entity . direction == flib_direction . opposite ( belt_direction ) then 138entity . loader_type ="input" 139elseif belt_type == "transport-belt" or belt_type == "underground-belt" then 140-- Sideloading 141entity . loader_type ="output" 142end 143end 144 145--- @param e EntityBuiltEvent 146local function on_entity_built ( e ) 147if not loader_snapping_enabled then 148return 149end 150 151local entity =e . entity or e . destination 152if not entity . valid or not string . match ( entity . name , "^kr.*%-loader$" ) then 153return 154end 155 156entity . update_connections () 157if not entity . loader_container then 158snap_direction ( entity ) 159end 160 161snap_to_belt ( entity ) 162end 163 164remote . add_interface ( "kr_loader_snapping" , { 165--- Sets whether or not loader snapping is enabled. Setting is not preserved across save/load. 166--- @param value boolean 167set_enabled =function ( value ) 168assert ( type ( value ) == "boolean" , "`value` must be a boolean" ) 169loader_snapping_enabled =value 170end , 171--- Returns whether or not loader snapping is currently enabled. 172get_enabled =function () 173return loader_snapping_enabled 174end , 175} ) 176 177--- @class LoaderSnappingHandler : event_handler 178local snap_loader ={} 179 180snap_loader . events ={ 181[ defines . events . on_built_entity ] =on_entity_built , 182[ defines . events . on_entity_cloned ] =on_entity_built , 183[ defines . events . on_robot_built_entity ] =on_entity_built , 184[ defines . events . script_raised_built ] =on_entity_built , 185[ defines . events . script_raised_revive ] =on_entity_built , 186[ defines . events . on_space_platform_built_entity ] =on_entity_built , 187} 188 189return snap_loader