z_mirror/PipeVisualizer
git clone https://git.raiguard.me/z_mirror/PipeVisualizer
9371b54
2.0
1local flib_queue =require ( "__flib__/queue" ) 2 3local entity_data =require ( "__PipeVisualizer__/scripts/entity-data" ) 4local renderer =require ( "__PipeVisualizer__/scripts/renderer" ) 5local util =require ( "__PipeVisualizer__/scripts/util" ) 6 7--- @alias FlowDirection "input"|"output"|"input-output" 8--- @alias FluidSystemID uint 9--- @alias PlayerIndex uint 10 11--- @class Iterator 12--- @field entities table<UnitNumber, EntityData> 13--- @field in_overlay boolean 14--- @field player_index PlayerIndex 15--- @field queue Queue<{entity: LuaEntity, update_neighbours: boolean}> 16--- @field systems table<FluidSystemID, Color> 17 18--- @param entity LuaEntity 19--- @param player_index PlayerIndex 20--- @param in_overlay boolean 21--- @return boolean accepted 22local function request ( entity , player_index , in_overlay ) 23if not global . iterator then 24return false 25end 26 27local iterator =global . iterator [ player_index ] 28if not iterator then 29--- @type Iterator 30iterator ={ 31entities ={} , 32in_overlay =in_overlay , 33player_index =player_index , 34queue =flib_queue . new (), 35systems ={} , 36} 37end 38 39local fluidbox =entity . fluidbox 40local should_iterate =false 41for fluidbox_index , fluid_system_id in util . iterate_fluid_systems ( fluidbox ) do 42local system =iterator . systems [ fluid_system_id ] 43if system and not in_overlay then 44goto continue 45end 46 47if not system then 48-- TODO: Handle when there's no fluid in the system 49local color ={ r =0.3 , g =0.3 , b =0.3 } 50local contents =fluidbox . get_fluid_system_contents ( fluidbox_index ) 51if contents and next ( contents ) then 52color =global . fluid_colors [ next ( contents )] 53end 54 55iterator . systems [ fluid_system_id ] =color 56end 57 58should_iterate =true 59 60:: continue :: 61end 62 63if should_iterate then 64flib_queue . push_back ( iterator . queue , { entity =entity } ) 65global . iterator [ player_index ] =iterator 66end 67 68return should_iterate 69end 70 71--- @param iterator Iterator 72--- @param entity LuaEntity 73--- @param update_neighbours boolean? 74local function request2 ( iterator , entity , update_neighbours ) 75update_neighbours =update_neighbours or false 76flib_queue . push_back ( iterator . queue , { entity =entity , update_neighbours =update_neighbours } ) 77end 78 79--- @param iterator Iterator 80--- @param entities_per_tick integer 81local function iterate ( iterator , entities_per_tick ) 82for _ =1 , entities_per_tick do 83local to_iterate =flib_queue . pop_front ( iterator . queue ) 84if not to_iterate then 85break 86end 87local entity , update_neighbours =to_iterate . entity , to_iterate . update_neighbours 88if not entity . valid then 89goto continue 90end 91 92-- If the entity data already existed, this entity was requested to be redrawn 93local data =entity_data . create ( iterator , entity ) 94if not data then 95return 96end 97 98renderer . draw ( iterator , data ) 99 100if iterator . in_overlay and not update_neighbours then 101goto continue 102end 103 104-- Propagate to undrawn neighbours 105for fluid_system_id , connections in pairs ( data . connections ) do 106if iterator . systems [ fluid_system_id ] then 107for _ , connection in pairs ( connections ) do 108local owner =connection . target_owner 109if owner then 110local data =entity_data . get ( iterator , owner ) 111if 112update_neighbours 113or not data 114or ( data . connections [ fluid_system_id ] and not data . connection_objects [ fluid_system_id ]) 115then 116flib_queue . push_back ( iterator . queue , { entity =owner } ) 117end 118end 119end 120end 121end 122 123:: continue :: 124end 125end 126 127--- @param iterator Iterator 128--- @param fluid_system_id FluidSystemID 129local function clear_system ( iterator , fluid_system_id ) 130iterator . systems [ fluid_system_id ] =nil 131for _ , data in pairs ( iterator . entities ) do 132if data . connections [ fluid_system_id ] then 133entity_data . remove_system ( iterator , data , fluid_system_id ) 134end 135end 136if not next ( iterator . systems ) then 137global . iterator [ iterator . player_index ] =nil 138end 139end 140 141--- @param player_index PlayerIndex 142local function clear_all ( player_index ) 143if not global . iterator then 144return 145end 146local it =global . iterator [ player_index ] 147if not it then 148return 149end 150for _ , entity_data in pairs ( it . entities ) do 151renderer . clear ( entity_data ) 152end 153global . iterator [ player_index ] =nil 154end 155 156--- @param entity LuaEntity 157--- @param player_index PlayerIndex 158local function request_or_clear ( entity , player_index ) 159if not global . iterator then 160return 161end 162local iterator =global . iterator [ player_index ] 163if not iterator then 164request ( entity , player_index , false , false ) 165return 166end 167if iterator . in_overlay then 168return 169end 170if request ( entity , player_index , false , false ) then 171return 172end 173-- TODO: Rewrite this 174local fluidbox =entity . fluidbox 175for fluidbox_index =1 , # fluidbox do 176--- @cast fluidbox_index uint 177local id =fluidbox . get_fluid_system_id ( fluidbox_index ) 178if id and iterator . systems [ id ] then 179clear_system ( iterator , id ) 180end 181end 182end 183 184local function on_tick () 185if not global . iterator then 186return 187end 188local entities_per_tick =math . ceil ( 30 / table_size ( global . iterator )) 189for _ , iterator in pairs ( global . iterator ) do 190iterate ( iterator , entities_per_tick ) 191end 192end 193 194--- @param e EventData.CustomInputEvent 195local function on_toggle_hover ( e ) 196local iterator =global . iterator [ e . player_index ] 197if iterator and iterator . in_overlay then 198return 199end 200local player =game . get_player ( e . player_index ) 201if not player then 202return 203end 204local entity =player . selected 205if not entity then 206clear_all ( e . player_index ) 207return 208end 209request_or_clear ( entity , e . player_index ) 210end 211 212--- @class iterator 213local iterator ={} 214 215function iterator . on_init () 216--- @type table<PlayerIndex, Iterator> 217global . iterator ={} 218end 219 220iterator . events ={ 221[ defines . events . on_tick ] =on_tick , 222[ "pv-visualize-selected" ] =on_toggle_hover , 223} 224 225iterator . clear_all =clear_all 226iterator . request =request 227iterator . request2 =request2 228 229return iterator