z_mirror/EditorExtensions
git clone https://git.raiguard.me/z_mirror/EditorExtensions
55451ea
trunk
1local flib_direction =require ( "__flib__.direction" ) 2local position =require ( "__flib__.position" ) 3 4local transport_belt_connectables ={ 5"transport-belt" , 6"underground-belt" , 7"splitter" , 8"loader" , 9"loader-1x1" , 10"linked-belt" , 11"lane-splitter" , 12} 13 14--- @type table<defines.direction, Vector> 15local deltas ={ 16[ defines . direction . north ] ={ 0 , - 1 } , 17[ defines . direction . east ] ={ 1 , 0 } , 18[ defines . direction . south ] ={ 0 , 1 } , 19[ defines . direction . west ] ={ - 1 , 0 } , 20} 21 22--- @param entity LuaEntity 23local function snap ( entity ) 24local offset_direction =entity . direction 25if entity . loader_type == "input" then 26offset_direction =flib_direction . opposite ( offset_direction ) 27end 28local belt_position =position . add ( entity . position , deltas [ offset_direction ]) 29local belt = 30entity . surface . find_entities_filtered ( { position =belt_position , type =transport_belt_connectables } )[ 1 ] 31if not belt then 32belt = 33entity . surface . find_entities_filtered ( { position =belt_position , ghost_type =transport_belt_connectables } )[ 1 ] 34end 35if not belt then 36return 37end 38if belt . direction == flib_direction . opposite ( entity . direction ) then 39entity . loader_type =entity . loader_type == "output" and "input" or "output" 40end 41end 42 43--- @param entity LuaEntity 44--- @param chest LuaEntity? 45local function sync_chest_filter ( entity , chest ) 46if not chest then 47chest =entity . surface . find_entity ( "ee-infinity-loader-chest" , entity . position ) 48end 49if not chest then 50entity . destroy () 51return 52end 53for i =1 , 2 do 54local filter =entity . get_filter ( i ) 55if filter then 56chest . set_infinity_container_filter ( i , { 57index =i , 58name =filter . name --[[@as string]] , 59quality =filter . quality , 60count =prototypes . item [ filter . name ]. stack_size * 5 , 61mode ="exactly" , 62} ) 63else 64chest . set_infinity_container_filter ( i , nil ) 65end 66end 67end 68 69--- @param loader LuaEntity 70--- @param combinator LuaEntity 71local function copy_from_loader_to_combinator ( loader , combinator ) 72local cb =combinator . get_or_create_control_behavior () --[[@as LuaConstantCombinatorControlBehavior]] 73--- @type LuaLogisticSection? 74local section 75for _ , sec in pairs ( cb . sections ) do 76if sec . group == "" then 77section =sec 78break 79end 80end 81if not section then 82section =cb . add_section () 83end 84if not section then 85return -- When will this ever happen? 86end 87--- @type ItemFilter? 88local first_filter 89for i =1 , 2 do 90local filter =loader . get_filter ( i ) 91if not filter then 92goto continue 93end 94if i == 1 then 95first_filter =filter 96elseif first_filter and filter . name == first_filter . name and filter . quality == first_filter . quality then 97return 98end 99section . set_slot ( i , { 100value ={ 101type ="item" , 102name =filter . name --[[@as string]] , 103quality =filter . quality , 104} , 105min =1 , 106} ) 107:: continue :: 108end 109end 110 111--- @param combinator LuaEntity 112--- @param loader LuaEntity 113local function copy_from_combinator_to_loader ( combinator , loader ) 114local cb =combinator . get_control_behavior () --[[@as LuaConstantCombinatorControlBehavior?]] 115if not cb then 116return 117end 118local section =cb . get_section ( 1 ) 119if not section then 120return 121end 122for i =1 , 2 do 123local filter =section . filters [ i ] 124if filter then 125local value =filter . value 126if value and ( not value . type or value . type == "item" ) then 127loader . set_filter ( i , { name =value . name , quality =value . quality } ) 128else 129loader . set_filter ( i , nil ) 130end 131end 132end 133sync_chest_filter ( loader ) 134end 135 136--- @param e BuiltEvent 137local function on_entity_built ( e ) 138local entity =e . entity or e . destination 139if not entity . valid then 140return 141end 142 143if entity . name ~= "ee-infinity-loader" then 144return 145end 146 147-- Create chest 148local chest =entity . surface . create_entity ( { 149name ="ee-infinity-loader-chest" , 150position =entity . position , 151force =entity . force , 152create_build_effect_smoke =false , 153raise_built =true , 154} ) 155 156if not chest then 157entity . destroy () 158return 159end 160 161chest . remove_unfiltered_items =true 162sync_chest_filter ( entity , chest ) 163snap ( entity ) 164end 165 166--- @param e DestroyedEvent 167local function on_entity_destroyed ( e ) 168local entity =e . entity 169if not entity . valid or entity . name ~= "ee-infinity-loader" then 170return 171end 172local chest =entity . surface . find_entity ( "ee-infinity-loader-chest" , entity . position ) 173if chest then 174chest . destroy ( { raise_destroy =true } ) 175end 176end 177 178--- @param e EventData.on_player_rotated_entity 179local function on_entity_rotated ( e ) 180local entity =e . entity 181if not entity . valid or entity . name ~= "ee-infinity-loader" then 182return 183end 184sync_chest_filter ( entity ) 185end 186 187--- @param e EventData.on_entity_settings_pasted 188local function on_entity_settings_pasted ( e ) 189local source , destination =e . source , e . destination 190if not source . valid or not destination . valid then 191return 192end 193local source_is_loader , destination_is_loader = 194source . name == "ee-infinity-loader" , destination . name == "ee-infinity-loader" 195if source_is_loader and destination . name == "constant-combinator" then 196copy_from_loader_to_combinator ( source , destination ) 197elseif source . name == "constant-combinator" and destination_is_loader then 198copy_from_combinator_to_loader ( source , destination ) 199elseif destination_is_loader then 200sync_chest_filter ( destination ) 201end 202end 203 204--- @param e EventData.on_gui_opened 205local function on_gui_opened ( e ) 206if e . gui_type ~= defines . gui_type . entity then 207return 208end 209local entity =e . entity 210if not entity or not entity . valid then 211return 212end 213if entity . name == "ee-infinity-loader" then 214storage . infinity_loader_open [ e . player_index ] =entity 215end 216end 217 218--- @param e EventData.on_gui_closed 219local function on_gui_closed ( e ) 220if e . gui_type ~= defines . gui_type . entity then 221return 222end 223local loader =storage . infinity_loader_open [ e . player_index ] 224if loader and loader . valid then 225sync_chest_filter ( loader ) 226storage . infinity_loader_open [ e . player_index ] =nil 227end 228end 229 230local infinity_loader ={} 231 232function infinity_loader . on_init () 233--- @type table<uint, LuaEntity> 234storage . infinity_loader_open ={} 235end 236 237infinity_loader . events ={ 238[ defines . events . on_built_entity ] =on_entity_built , 239[ defines . events . on_entity_cloned ] =on_entity_built , 240[ defines . events . on_entity_died ] =on_entity_destroyed , 241[ defines . events . on_entity_settings_pasted ] =on_entity_settings_pasted , 242[ defines . events . on_gui_closed ] =on_gui_closed , 243[ defines . events . on_gui_opened ] =on_gui_opened , 244[ defines . events . on_player_mined_entity ] =on_entity_destroyed , 245[ defines . events . on_player_rotated_entity ] =on_entity_rotated , 246[ defines . events . on_robot_built_entity ] =on_entity_built , 247[ defines . events . on_robot_mined_entity ] =on_entity_destroyed , 248[ defines . events . script_raised_built ] =on_entity_built , 249[ defines . events . script_raised_destroy ] =on_entity_destroyed , 250[ defines . events . script_raised_revive ] =on_entity_built , 251[ defines . events . on_space_platform_built_entity ] =on_entity_built , 252[ defines . events . on_space_platform_mined_entity ] =on_entity_destroyed , 253} 254 255infinity_loader . on_nth_tick ={ 256[ 15 ] =function () 257for unit_number , loader in pairs ( storage . infinity_loader_open ) do 258if loader . valid then 259sync_chest_filter ( loader ) 260else 261storage . infinity_loader_open [ unit_number ] =nil 262end 263end 264end , 265} 266 267infinity_loader . snap =snap 268 269return infinity_loader