z_mirror/QuickbarTemplates
git clone https://git.raiguard.me/z_mirror/QuickbarTemplates
aef62a9
trunk
1--- @param player LuaPlayer 2local function create_gui ( player ) 3local window =player . gui . screen . add ( { type ="frame" , name ="qt_window" , style ="slot_window_frame" } ) 4local inner_panel =window . add ( { type ="frame" , name ="qt_inner_panel" , style ="shortcut_bar_inner_panel" } ) 5local export_button =inner_panel . add ( { 6type ="sprite-button" , 7name ="qt_export_button" , 8style ="shortcut_bar_button_blue" , 9sprite ="qt-export-blueprint-white" , 10tooltip ={ "qt-gui.export" } , 11} ) 12export_button . style . padding =4 13local import_button =inner_panel . add ( { 14type ="sprite-button" , 15name ="qt_import_button" , 16style ="shortcut_bar_button_blue" , 17sprite ="qt-import-blueprint-white" , 18tooltip ={ "qt-gui.import" } , 19} ) 20import_button . style . padding =4 21window . visible =false 22return { window =window , export_button =export_button , import_button =import_button } 23end 24 25--- @param player LuaPlayer 26local function setup_player ( player ) 27local data =create_gui ( player ) 28storage . players [ player . index ] =data 29end 30 31--- @param player LuaPlayer 32--- @param window LuaGuiElement 33local function set_gui_location ( player , window ) 34local resolution =player . display_resolution 35local scale =player . display_scale 36window . location ={ 37x =( resolution . width / 2 ) - (( 56 + 258 ) * scale ), 38y =( resolution . height - ( 56 * scale )), 39} 40end 41 42--- @param position MapPosition 43--- @param zero_position MapPosition 44--- @return integer 45local function position_to_index ( position , zero_position ) 46return math . floor ( position . x - zero_position . x ) + math . floor ( zero_position . y - position . y ) * 10 + 1 47end 48 49--- @param entities BlueprintEntity[] 50local function get_zero_position ( entities ) 51local result ={ x =entities [ 1 ]. position . x , y =entities [ 1 ]. position . y } 52for i =2 , 100 do 53local position =entities [ i ]. position 54if result . x > position . x then 55result . x =position . x 56end 57if result . y < position . y then 58result . y =position . y 59end 60end 61return result 62end 63 64local ignored_item_names ={ 65[ "blueprint" ] =true , 66[ "blueprint-book" ] =true , 67[ "upgrade-planner" ] =true , 68[ "deconstruction-planner" ] =true , 69} 70 71--- @param player LuaPlayer 72local function export_quickbar ( player ) 73local entities ={} 74local pos ={ x =- 4 , y =4 } 75for i =1 , 100 do 76entities [ i ] ={ 77entity_number =i , 78name ="constant-combinator" , 79position ={ x =pos . x , y =pos . y } , 80} 81 82local item =player . get_quick_bar_slot ( i ) 83if item and not ignored_item_names [ item . name ] then 84entities [ i ]. control_behavior ={ 85filters ={ 86{ 87count =1 , 88index =1 , 89signal ={ 90type ="item" , 91name =item . name , 92quality =item . quality , 93} , 94} , 95} , 96} 97end 98 99pos . x =pos . x + 1 100if pos . x == 6 then 101pos . x =- 4 102pos . y =pos . y - 1 103end 104end 105return entities 106end 107 108--- @param player LuaPlayer 109--- @param entities BlueprintEntity[] 110--- @param ignore_empty boolean 111--- @return boolean # If the transfer was successful. 112local function import_quickbar ( player , entities , ignore_empty ) 113if # entities ~= 100 then 114return false 115end 116 117--- @type ({name: string, quality: string}?)[] 118local filters ={} 119local zero_position =get_zero_position ( entities ) 120for i =1 , 100 do 121local entity =entities [ i ] 122if not entity or entity . name ~= "constant-combinator" then 123return false 124end 125local filter_index =position_to_index ( entity . position , zero_position ) 126local cb =entity . control_behavior 127if not cb then 128goto continue 129end 130local sections_outer =cb . sections --- @diagnostic disable-line:undefined-field 131if not sections_outer then 132goto continue 133end 134local sections_inner =sections_outer . sections 135if not sections_inner then 136goto continue 137end 138local first_section =sections_inner [ 1 ] 139if not first_section then 140goto continue 141end 142local section_filters =first_section . filters 143if not section_filters then 144goto continue 145end 146local first_filter =section_filters [ 1 ] 147if not first_filter then 148goto continue 149end 150filters [ filter_index ] ={ name =first_filter . name , quality =first_filter . quality } 151:: continue :: 152end 153 154for i =1 , 100 do 155local filter =filters [ i ] 156if not ignore_empty or filter then 157player . set_quick_bar_slot ( i , filter ) 158end 159end 160 161return true 162end 163 164--- @param player LuaPlayer 165--- @return BlueprintEntity[]? 166local function get_blueprint_entities ( player ) 167if not player . is_cursor_blueprint () then 168return 169end 170local cursor_stack =player . cursor_stack 171if cursor_stack and cursor_stack . valid_for_read and cursor_stack . type == "blueprint" then 172return cursor_stack . get_blueprint_entities () 173end 174local cursor_record =player . cursor_record 175if cursor_record and cursor_record . type == "blueprint" then 176return cursor_record . get_blueprint_entities () 177end 178end 179 180-- EVENT HANDLERS 181 182script . on_init ( function () 183storage . players ={} 184for _ , player in pairs ( game . players ) do 185setup_player ( player ) 186end 187end ) 188 189script . on_configuration_changed ( function () 190for i , player_table in pairs ( storage . players ) do 191player_table . window . destroy () 192local player =game . get_player ( i ) 193if player then 194storage . players [ i ] =create_gui ( player ) 195else 196storage . players [ i ] =nil 197end 198end 199end ) 200 201script . on_event ( defines . events . on_player_created , function ( e ) 202local player =game . players [ e . player_index ] 203setup_player ( player ) 204 205local template =player . mod_settings [ "qt-default-template" ]. value --[[@as string]] 206if template == "" then 207return 208end 209 210local temp_inventory =game . create_inventory ( 1 ) 211temp_inventory . insert ( { name ="blueprint" } ) 212local blueprint =temp_inventory [ 1 ] 213 214if blueprint . import_stack ( template ) == 0 then 215local entities =blueprint . get_blueprint_entities () 216if not entities or not import_quickbar ( player , entities , false ) then 217player . ( { "qt-message.invalid-default-blueprint" } ) 218end 219else 220player . ( { "qt-message.invalid-default-blueprint" } ) 221end 222 223temp_inventory . destroy () 224end ) 225 226--- @param e EventData.on_player_cursor_stack_changed 227local function on_cursor_stack_changed ( e ) 228local player =game . players [ e . player_index ] 229local gui =storage . players [ e . player_index ] 230if not player . is_cursor_blueprint () then 231gui . window . visible =false 232return 233end 234set_gui_location ( player , gui . window ) 235local entities =get_blueprint_entities ( player ) 236if entities then 237gui . export_button . visible =false 238gui . import_button . visible =true 239else 240gui . export_button . visible =true 241gui . import_button . visible =false 242end 243gui . window . visible =true 244end 245script . on_event ( defines . events . on_player_cursor_stack_changed , on_cursor_stack_changed ) 246 247script . on_event ( 248{ defines . events . on_player_display_resolution_changed , defines . events . on_player_display_scale_changed } , 249--- @param e EventData.on_player_display_resolution_changed|EventData.on_player_display_scale_changed 250function ( e ) 251set_gui_location ( game . players [ e . player_index ], storage . players [ e . player_index ]. window ) 252end 253) 254 255script . on_event ( defines . events . on_gui_click , function ( e ) 256if e . element . name == "qt_export_button" then 257local player =game . players [ e . player_index ] 258local stack =player . cursor_stack 259if stack and stack . valid_for_read and stack . name == "blueprint" then 260stack . set_blueprint_entities ( export_quickbar ( player )) 261on_cursor_stack_changed ( e ) --- @diagnostic disable-line:param-type-mismatch 262end 263elseif e . element . name == "qt_import_button" then 264local player =game . players [ e . player_index ] 265local entities =get_blueprint_entities ( player ) 266if entities then 267if not import_quickbar ( player , entities , e . shift ) then 268player . ( { "qt-message.invalid-blueprint" } ) 269end 270end 271end 272end )