z_mirror/ChangeInserterDropLane
git clone https://git.raiguard.me/z_mirror/ChangeInserterDropLane
e2c14e2
factorio-2.0
1if script . active_mods [ "bobinserters" ] then 2return 3end 4 5local flib_gui =require ( "__flib__.gui" ) 6local flib_math =require ( "__flib__.math" ) 7local flib_position =require ( "__flib__.position" ) 8 9local near_vectors ={ 10[ defines . direction . north ] ={ 0.01 , - 0.2 } , 11[ defines . direction . east ] ={ 0.2 , 0.01 } , 12[ defines . direction . south ] ={ - 0.01 , 0.2 } , 13[ defines . direction . west ] ={ - 0.2 , - 0.01 } , 14} 15local far_vectors ={ 16[ defines . direction . north ] ={ 0.0 , 0.2 } , 17[ defines . direction . east ] ={ - 0.2 , 0.0 } , 18[ defines . direction . south ] ={ 0.0 , - 0.2 } , 19[ defines . direction . west ] ={ 0.2 , 0.0 } , 20} 21 22--- @param entity LuaEntity 23local function get_prototype ( entity ) 24return entity . type == "entity-ghost" and entity . ghost_prototype or entity . prototype 25end 26 27--- @param entity LuaEntity 28local function get_entity_type ( entity ) 29return entity . type == "entity-ghost" and entity . ghost_type or entity . type 30end 31 32--- @param entity LuaEntity 33local function is_compatible ( entity ) 34local prototype =get_prototype ( entity ) 35return prototype . allow_custom_vectors and not string . find ( prototype . name , "%-?miniloader%-inserter" ) 36end 37 38--- @param entity LuaEntity 39local function get_is_far ( entity ) 40local drop_pos_vector =flib_position . sub ( entity . drop_position , entity . position ) 41local vector_length =flib_math . sqrt ( drop_pos_vector . x * drop_pos_vector . x + drop_pos_vector . y * drop_pos_vector . y ) 42return vector_length % 1 < 0.5 , drop_pos_vector 43end 44 45--- @param entity LuaEntity 46--- @param is_far boolean 47local function change_mode_fx ( entity , is_far ) 48for _ , player in pairs ( game . players ) do 49if player . surface == entity . surface then 50player . create_local_flying_text ( { 51text =is_far and { "message.cidl-drop-far" } or { "message.cidl-drop-near" } , 52color ={ r =1 , g =0.5 , b =0.25 } , 53position =entity . position , 54} ) 55end 56end 57-- Welding sound 58game . play_sound ( { 59path ="cidl-welding" , 60position =entity . position , 61volume_modifier =1.0 , 62} ) 63-- Welding particle 64entity . surface . create_particle ( { 65name ="cidl-welding" , 66position ={ entity . position . x , entity . position . y + 1 } , 67movement ={ 0.0 , - 0.05 } , 68height =1.0 , 69vertical_speed =0.015 , 70frame_speed =1 , 71} ) 72end 73 74--- @param player LuaPlayer 75--- @param entity LuaEntity 76local function change_lane ( player , entity ) 77if not get_prototype ( entity ). allow_custom_vectors then 78player . create_local_flying_text ( { 79text ={ "message.cidl-cannot-change-drop-lane" } , 80create_at_cursor =true , 81} ) 82player . play_sound ( { path ="utility/cannot_build" } ) 83return 84end 85 86-- Change lane 87local is_far , drop_pos_vector =get_is_far ( entity ) 88local vectors =is_far and near_vectors or far_vectors 89local vector =vectors [ entity . direction ] 90entity . drop_position ={ 91entity . position . x + flib_math . round ( drop_pos_vector . x ) + vector [ 1 ], 92entity . position . y + flib_math . round ( drop_pos_vector . y ) + vector [ 2 ], 93} 94 95-- Special effects 96change_mode_fx ( entity , not is_far ) 97end 98 99--- @param e EventData.on_gui_switch_state_changed 100local function on_droplane_switch_state_changed ( e ) 101local player =game . get_player ( e . player_index ) 102if not player or player . opened_gui_type ~= defines . gui_type . entity then 103return 104end 105local entity =player . opened --[[@as LuaEntity?]] 106if not entity or not is_compatible ( entity ) then 107return 108end 109change_lane ( player , entity ) 110e . element . switch_state =get_is_far ( entity ) and "right" or "left" 111end 112 113--- @param player LuaPlayer 114--- @param entity LuaEntity 115local function create_gui ( player , entity ) 116local window =player . gui . relative . cidl_window 117if window then 118window . destroy () 119end 120flib_gui . add ( player . gui . relative , { 121type ="frame" , 122name ="cidl_window" , 123caption ={ "gui.cidl-drop-lane" } , 124anchor ={ 125gui =defines . relative_gui_type . inserter_gui , 126position =defines . relative_gui_position . right , 127} , 128{ 129type ="frame" , 130style ="inside_shallow_frame_with_padding" , 131{ 132type ="switch" , 133left_label_caption ={ "gui.cidl-near" } , 134right_label_caption ={ "gui.cidl-far" } , 135switch_state =get_is_far ( entity ) and "right" or "left" , 136handler ={ 137[ defines . events . on_gui_switch_state_changed ] =on_droplane_switch_state_changed , 138} , 139} , 140} , 141} ) 142end 143 144--- @param e EventData.CustomInputEvent 145local function on_change_lane ( e ) 146local player =game . get_player ( e . player_index ) 147if not player then 148return 149end 150local entity =player . selected 151if not entity then 152return 153end 154if not player . can_reach_entity ( entity ) then 155player . create_local_flying_text ( { 156text ={ "cant-reach" } , 157create_at_cursor =true , 158} ) 159player . play_sound ( { path ="utility/cannot_build" } ) 160return 161end 162change_lane ( player , entity ) 163end 164 165--- @param e EventData.on_pre_entity_settings_pasted 166local function on_pre_entity_settings_pasted ( e ) 167local source , destination =e . source , e . destination 168if not source . valid or not destination . valid then 169return 170end 171if get_entity_type ( source ) ~= "inserter" or get_entity_type ( destination ) ~= "inserter" then 172return 173end 174if not get_prototype ( destination ). allow_custom_vectors then 175return 176end 177storage . temp_inserter_settings [ destination . unit_number ] ={ 178drop_position =destination . drop_position , 179pickup_position =destination . pickup_position , 180} 181end 182 183--- @param e EventData.on_entity_settings_pasted 184local function on_entity_settings_pasted ( e ) 185local source , destination =e . source , e . destination 186if not source . valid or not destination . valid then 187return 188end 189if get_entity_type ( source ) ~= "inserter" or get_entity_type ( destination ) ~= "inserter" then 190return 191end 192if not get_prototype ( destination ). allow_custom_vectors then 193return 194end 195 196local destination_unit_number =destination . unit_number --[[@as uint]] 197local temp_settings =storage . temp_inserter_settings [ destination_unit_number ] 198if not temp_settings then 199return 200end 201storage . temp_inserter_settings [ destination_unit_number ] =nil 202 203destination . drop_position =temp_settings . drop_position 204destination . pickup_position =temp_settings . pickup_position 205 206local player =game . get_player ( e . player_index ) 207if not player then 208return 209end 210local destination_is_far =get_is_far ( destination ) 211if destination_is_far ~= get_is_far ( source ) then 212change_lane ( player , destination ) 213end 214end 215 216--- @param e EventData.on_gui_opened 217local function on_gui_opened ( e ) 218local player =game . get_player ( e . player_index ) 219if not player then 220return 221end 222if player . opened_gui_type ~= defines . gui_type . entity then 223return 224end 225local entity =player . opened --[[@as LuaEntity?]] 226if not entity or not is_compatible ( entity ) then 227return 228end 229create_gui ( player , entity ) 230end 231 232--- @class InserterSettings 233--- @field drop_position MapPosition 234--- @field pickup_position MapPosition 235 236local function on_init () 237--- @type table<uint, InserterSettings?> 238storage . temp_inserter_settings ={} 239end 240 241flib_gui . add_handlers ( { on_droplane_switch_state_changed =on_droplane_switch_state_changed } ) 242flib_gui . handle_events () 243 244script . on_init ( on_init ) 245script . on_configuration_changed ( on_init ) 246script . on_event ( "cidl-change-lane" , on_change_lane ) 247script . on_event ( defines . events . on_gui_opened , on_gui_opened ) 248script . on_event ( defines . events . on_pre_entity_settings_pasted , on_pre_entity_settings_pasted ) 249script . on_event ( defines . events . on_entity_settings_pasted , on_entity_settings_pasted ) 250 251-- For simulations 252remote . add_interface ( "ChangeInserterDropLane_simulation" , { 253--- @param player LuaPlayer 254change_selected_lane =function ( player ) 255local selected =player . selected 256if not selected then 257return 258end 259change_lane ( player , selected ) 260end , 261} )