z_mirror/Krastorio2
git clone https://git.raiguard.me/z_mirror/Krastorio2
0ee5744d
trunk
1local flib_gui =require ( "__flib__.gui" ) 2 3local util =require ( "scripts.util" ) 4 5--- @type table<string, {color: Color?, suffix: string, text: string}> 6local mode_data ={ 7normal ={ suffix ="" , text ="normal" } , 8construction ={ color ={ r =0.5 , g =1 , b =0.4 } , suffix ="-construction-mode" , text ="construction" } , 9logistic ={ color ={ r =1 , g =0.5 , b =0.25 } , suffix ="-logistic-mode" , text ="logistic" } , 10} 11 12local next_roboport_mode ={ 13[ "" ] ="construction" , 14[ "-construction-mode" ] ="logistic" , 15[ "-logistic-mode" ] ="normal" , 16} 17 18local roboport_has_variants_gui ={} 19do 20-- Find all compatible roboports 21local lookup ={} 22for _ , entity in pairs ( prototypes . get_entity_filtered ( { { filter ="type" , type ="roboport" } } )) do 23local matched , _ , base_name =string . find ( entity . name , "^(.-)%-%w*%-mode" ) 24if matched then 25lookup [ base_name ] =true 26lookup [ entity . name ] =true 27end 28end 29 30-- Convert to a format usable by GuiAnchor 31local i =0 32for entity_name in pairs ( lookup ) do 33i =i + 1 34roboport_has_variants_gui [ i ] =entity_name 35end 36end 37 38--- @param player LuaPlayer 39--- @param entity LuaEntity 40local function update_gui ( player , entity ) 41local player_gui =storage . roboport_guis [ player . index ] 42if not player_gui or not player_gui . valid then 43return 44end 45local mode =string . match ( entity . name , "^.*%-(%w*)%-mode" ) or "normal" 46 47for _ , button in pairs ( player_gui . inner_frame . children ) do 48if button . name == mode then 49button . state =true 50else 51button . state =false 52end 53end 54end 55 56--- @param entity LuaEntity 57--- @param player LuaPlayer 58--- @param to_mode string? 59local function change_mode ( entity , player , to_mode ) 60local matched , _ , base_name , suffix =string . find ( entity . name , "^(.-)(%-%w-%-mode)$" ) 61if not matched then 62base_name =entity . name 63suffix ="" 64end 65 66local new_mode_data 67if to_mode then 68new_mode_data =mode_data [ to_mode ] 69else 70new_mode_data =mode_data [ next_roboport_mode [ suffix ]] 71end 72 73local new_name =base_name .. new_mode_data . suffix 74 75if new_name == entity . name then 76return 77end 78 79if not prototypes . entity [ new_name ] then 80util . flying_text_with_sound ( player , { "message.kr-roboport-modes-not-supported" } , { position =entity . position } ) 81return 82end 83 84local energy =entity . energy 85local health =entity . health 86 87-- Find all players that have this roboport open 88-- This must be done before the roboport is swapped 89local guis_to_update ={} 90for player_index in pairs ( storage . roboport_guis ) do 91local gui_player =game . get_player ( player_index ) 92if gui_player and gui_player . opened_gui_type == defines . gui_type . entity then 93local opened =gui_player . opened 94if opened and opened == entity then 95table . insert ( guis_to_update , gui_player ) 96end 97end 98end 99 100local new_entity =entity . surface . create_entity ( { 101name =new_name , 102position =entity . position , 103force =entity . force , 104direction =entity . direction , 105quality =entity . quality , 106fast_replace =true , 107raise_built =true , 108spill =false , 109create_build_effect_smoke =false , 110} ) 111 112if not new_entity then 113return 114end 115new_entity . energy =energy 116new_entity . health =health 117new_entity . last_user =player 118 119util . entity_flying_text ( new_entity , { "message.kr-" .. new_mode_data . text .. "-mode" } , new_mode_data . color ) 120game . play_sound ( { 121path ="kr-welding" , 122position =new_entity . position , 123volume_modifier =1.0 , 124} ) 125new_entity . surface . create_particle ( { 126name ="kr-welding-particle" , 127position ={ new_entity . position . x , new_entity . position . y + 1 } , 128movement ={ 0.0 , - 0.05 } , 129height =1.0 , 130vertical_speed =0.015 , 131frame_speed =1 , 132} ) 133 134-- Swapping the entity will close any open GUIs, so we must re-open them. 135for _ , gui_player in pairs ( guis_to_update ) do 136gui_player . opened =new_entity 137update_gui ( gui_player , new_entity ) 138end 139end 140 141--- @param e EventData.on_gui_checked_state_changed 142local function on_mode_radio_button_checked ( e ) 143local player =game . get_player ( e . player_index ) 144if not player or player . opened_gui_type ~= defines . gui_type . entity then 145return 146end 147local entity =player . opened --[[@as LuaEntity]] 148if not entity . valid or entity . type ~= "roboport" then 149return 150end 151change_mode ( entity , player , e . element . name ) 152end 153 154--- @param mode string 155local function radio_button ( mode ) 156return { 157type ="radiobutton" , 158name =mode , 159caption ={ "message.kr-" .. mode .. "-mode" } , 160state =false , 161handler ={ [ defines . events . on_gui_checked_state_changed ] =on_mode_radio_button_checked } , 162} 163end 164 165--- @param player_index uint 166local function destroy_gui ( player_index ) 167local player_gui =storage . roboport_guis [ player_index ] 168if not player_gui then 169return 170end 171if player_gui . valid then 172player_gui . destroy () 173end 174storage . roboport_guis [ player_index ] =nil 175end 176 177--- @param player LuaPlayer 178local function refresh_gui ( player ) 179destroy_gui ( player . index ) 180 181_ , storage . roboport_guis [ player . index ] =flib_gui . add ( player . gui . relative , { 182type ="frame" , 183name ="kr_roboport_mode_window" , 184caption ={ "gui.kr-change-mode" } , 185anchor ={ 186gui =defines . relative_gui_type . roboport_gui , 187position =defines . relative_gui_position . right , 188names =roboport_has_variants_gui , 189} , 190{ 191type ="frame" , 192name ="inner_frame" , 193style ="inside_shallow_frame_with_padding" , 194direction ="vertical" , 195radio_button ( "normal" ), 196radio_button ( "construction" ), 197radio_button ( "logistic" ), 198} , 199} ) 200end 201 202--- @param e EventData.on_gui_opened 203local function on_gui_opened ( e ) 204local entity =e . entity 205if not entity or not entity . valid then 206return 207end 208local player =game . get_player ( e . player_index ) 209if not player then 210return 211end 212if entity . type == "roboport" then 213update_gui ( player , entity ) 214end 215end 216 217--- @param e EventData.on_player_created 218local function on_player_created ( e ) 219local player =game . get_player ( e . player_index ) 220if player then 221refresh_gui ( player ) 222end 223end 224 225--- @param e EventData.on_player_removed 226local function on_player_removed ( e ) 227destroy_gui ( e . player_index ) 228end 229 230--- @param e EventData.CustomInputEvent 231local function on_change_roboport_mode_hotkey ( e ) 232local player =game . get_player ( e . player_index ) 233if not player then 234return 235end 236local selected =player . selected 237if selected and selected . valid and selected . type == "roboport" then 238change_mode ( selected , player ) 239end 240end 241 242local function refresh () 243for _ , player in pairs ( game . players ) do 244refresh_gui ( player ) 245end 246end 247 248local function on_init () 249-- XXX: When migrating from standalone K2SO to K2 + K2SO, there will be a leftover GUI which will cause a crash. It must be removed here. 250for _ , player in pairs ( game . players ) do 251local window =player . gui . relative [ "kr_roboport_mode_window" ] 252if window and window . valid then 253window . destroy () 254end 255end 256 257--- @type table<uint, LuaGuiElement> 258storage . roboport_guis ={} 259refresh () 260end 261 262--- @class RoboportHandler : event_handler 263local roboport ={} 264 265roboport . on_init =on_init 266roboport . on_configuration_changed =on_configuration_changed 267 268roboport . events ={ 269[ defines . events . on_gui_opened ] =on_gui_opened , 270[ defines . events . on_player_created ] =on_player_created , 271[ defines . events . on_player_removed ] =on_player_removed , 272[ "kr-change-roboport-state" ] =on_change_roboport_mode_hotkey , 273} 274 275flib_gui . add_handlers ( { roboport_on_mode_radio_button_checked =on_mode_radio_button_checked } ) 276 277return roboport