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