z_mirror/Krastorio2
git clone https://git.raiguard.me/z_mirror/Krastorio2
f534e8d3
discrete-steel-pipes
1local flib_position =require ( "__flib__.position" ) 2local flib_table =require ( "__flib__.table" ) 3 4local data_util ={} 5 6--- Overwrites or adds ammo effects for the given technology. 7--- @param tech data.TechnologyPrototype 8--- @param effects data.Modifier[] 9function data_util . update_ammo_effects ( tech , effects ) 10if not tech . effects then 11tech . effects ={} 12end 13 14for _ , updated_effect in pairs ( effects ) do 15local exists =false 16for _ , effect in pairs ( tech . effects ) do 17if 18effect . type == updated_effect . type 19and ( 20( effect . ammo_category ~= nil and effect . ammo_category == updated_effect . ammo_category ) 21or ( effect . turret_id ~= nil and effect . turret_id == updated_effect . turret_id ) 22) 23then 24effect . modifier =updated_effect . modifier --- @diagnostic disable-line:assign-type-mismatch 25exists =true 26break 27end 28end 29if not exists then 30table . insert ( 31tech . effects , 32{ type =updated_effect . type , ammo_category =updated_effect . ammo_category , modifier =updated_effect . modifier } --- @diagnostic disable-line:assign-type-mismatch 33) 34end 35end 36end 37 38--- @param technology_name data.TechnologyID 39--- @param new_effect data.Modifier 40function data_util . add_effect ( technology_name , new_effect ) 41local technology =data . raw . technology [ technology_name ] 42if not technology then 43error ( "Technology " .. technology_name .. " does not exist." ) 44end 45local effects =technology . effects 46if not effects or not next ( effects ) then 47technology . effects ={ new_effect } 48return 49end 50 51local found =false 52for _ , effect in pairs ( effects ) do 53if effect . type == new_effect . type then 54-- TODO: Update for new effect types. 55if effect . type == "gun-speed" then 56if effect . ammo_category == new_effect . ammo_category and effect . modifier == new_effect . modifier then 57found =true 58break 59end 60elseif effect . type == "ammo-damage" then 61if effect . ammo_category == new_effect . ammo_category and effect . modifier == new_effect . modifier then 62found =true 63break 64end 65elseif effect . type == "give-item" then 66if effect . item == new_effect . item and effect . count == new_effect . count then 67found =true 68break 69end 70elseif effect . type == "turret-attack" then 71if effect . turret_id == new_effect . turret_id and effect . modifier == new_effect . modifier then 72found =true 73break 74end 75elseif effect . type == "unlock-recipe" then 76if effect . recipe == new_effect . recipe then 77found =true 78break 79end 80elseif effect . type == "nothing" then 81if effect . effect_description == new_effect . effect_description then 82found =true 83break 84end 85else 86if effect . modifier == new_effect . modifier then 87found =true 88break 89end 90end 91end 92end 93 94if not found then 95table . insert ( effects , new_effect ) 96end 97end 98 99--- Adds the given recipe as an unlock of the given technology. 100--- @param technology_name data.TechnologyID 101--- @param recipe_name data.RecipeID 102function data_util . add_recipe_unlock ( technology_name , recipe_name ) 103local technology =data . raw . technology [ technology_name ] 104if not technology then 105error ( "Technology " .. technology_name .. " does not exist." ) 106end 107for _ , effect in pairs ( technology . effects ) do 108if effect . type == "unlock-recipe" and effect . recipe == recipe_name then 109error ( "Technology " .. technology_name .. " already unlocks recipe " .. recipe_name .. "." ) 110end 111end 112table . insert ( technology . effects , { type ="unlock-recipe" , recipe =recipe_name } ) 113end 114 115--- Removes the given recipe from the unlocks of the given technology. 116--- @param technology_name data.TechnologyID 117--- @param recipe_name data.RecipeID 118function data_util . remove_recipe_unlock ( technology_name , recipe_name ) 119local technology =data . raw . technology [ technology_name ] 120if not technology then 121error ( "Technology " .. technology_name .. " does not exist." ) 122end 123for i , effect in pairs ( technology . effects ) do 124if effect . type == "unlock-recipe" and effect . recipe == recipe_name then 125table . remove ( technology . effects , i ) 126return 127end 128end 129error ( "Technology " .. technology_name .. " does not unlock recipe " .. recipe_name .. "." ) 130end 131 132--- Adds the given prerequisite to the technology. 133--- @param technology_id data.TechnologyID 134--- @param prerequisite_id data.TechnologyID 135function data_util . add_prerequisite ( technology_id , prerequisite_id ) 136local technology =data . raw . technology [ technology_id ] 137if not technology then 138error ( "Technology " .. technology_id .. " does not exist." ) 139end 140local prerequisite =data . raw . technology [ prerequisite_id ] 141if not prerequisite then 142error ( "Technology prerequisite " .. prerequisite_id .. " does not exist." ) 143end 144if not technology . prerequisites then 145technology . prerequisites ={ prerequisite_id } 146return 147end 148if flib_table . find ( technology . prerequisites , prerequisite_id ) then 149error ( "Technology " .. technology_id .. " already has prerequisite " .. prerequisite_id ) 150end 151table . insert ( technology . prerequisites , prerequisite_id ) 152end 153 154--- Removes the given prerequisite from the technology. 155--- @param technology_id data.TechnologyID 156--- @param prerequisite_id data.TechnologyID 157function data_util . remove_prerequisite ( technology_id , prerequisite_id ) 158local technology =data . raw . technology [ technology_id ] 159if not technology then 160error ( "Technology " .. technology_id .. " does not exist." ) 161end 162local prerequisite =data . raw . technology [ prerequisite_id ] 163if not prerequisite then 164error ( "Technology prerequisite " .. prerequisite_id .. " does not exist." ) 165end 166local i =flib_table . find ( technology . prerequisites or {} , prerequisite_id ) 167if not i then 168error ( "Technology " .. technology_id .. " does not have prerequisite " .. prerequisite_id ) 169end 170table . remove ( technology . prerequisites , i ) 171end 172 173--- Converts one research unit ingredient to another, updating science pack prerequisites if needed. 174--- @param technology_id data.TechnologyID 175--- @param from_id data.ItemID 176--- @param to_id data.ItemID 177function data_util . convert_research_unit_ingredient ( technology_id , from_id , to_id ) 178local technology =data . raw . technology [ technology_id ] 179if not technology then 180error ( "Technology " .. technology_id .. " does not exist." ) 181end 182if not technology . unit or not technology . unit . ingredients then 183error ( "Technology " .. technology_id .. " has no research unit ingredients." ) 184end 185local converted =false 186for _ , ingredient in pairs ( technology . unit . ingredients ) do 187if ingredient [ 1 ] == from_id then 188converted =true 189ingredient [ 1 ] =to_id 190elseif ingredient [ 1 ] == to_id then 191error ( "Technology " .. technology_id .. " already has research unit ingredient " .. to_id ) 192end 193end 194if not converted then 195error ( "Technology " .. technology_id .. " does not have research unit ingredient " .. from_id ) 196end 197-- XXX: Hardcoding the science pack name like this feels bad, but it's what the old code did... 198local from_index =flib_table . find ( technology . prerequisites , from_id ) 199if from_index then 200table . remove ( technology . prerequisites , from_index ) 201end 202local new_tech =data . raw . technology [ to_id ] 203if not new_tech then 204log ( "Aborting due to lack of " .. to_id .. " tech" ) 205return 206end 207if not technology . prerequisites then 208technology . prerequisites ={ to_id } 209return 210end 211if not flib_table . find ( technology . prerequisites , to_id ) then 212log ( "Adding prerequisite " .. to_id ) 213table . insert ( technology . prerequisites , to_id ) 214end 215end 216 217--- Adds the given research ingredient to the technology. 218--- @param technology_id data.TechnologyID 219--- @param ingredient_id data.ItemID 220--- @param ingredient_count uint? Defaults to 1. 221function data_util . add_research_unit_ingredient ( technology_id , ingredient_id , ingredient_count ) 222ingredient_count =ingredient_count or 1 223local technology =data . raw . technology [ technology_id ] 224if not technology then 225error ( "Technology " .. technology_id .. " does not exist." ) 226end 227if technology . research_trigger then 228error ( "Technology " .. technology_id .. " has a research trigger, so cannot have ingredients." ) 229end 230local unit =technology . unit 231if not unit then 232error ( "Technology " .. technology_id .. " has no research unit." ) 233end 234for _ , ingredient in pairs ( technology . unit . ingredients ) do 235if ingredient [ 1 ] == ingredient_id then 236error ( "Technology " .. technology_id .. " already has research unit ingredient" .. ingredient_id ) 237end 238end 239table . insert ( technology . unit . ingredients , { ingredient_id , ingredient_count } ) 240end 241 242--- Removes the given research ingredient from the technology. 243--- @param technology_id data.TechnologyID 244--- @param ingredient_id data.ItemID 245function data_util . remove_research_unit_ingredient ( technology_id , ingredient_id ) 246local technology =data . raw . technology [ technology_id ] 247if not technology then 248error ( "Technology " .. technology_id .. " does not exist." ) 249end 250if not technology . unit then 251error ( "Technology " .. technology_id .. " has no research units." ) 252end 253for i , ingredient in pairs ( technology . unit . ingredients ) do 254if ingredient [ 1 ] == ingredient_id then 255table . remove ( technology . unit . ingredients , i ) 256return 257end 258end 259error ( "Technology " .. technology_id .. " does not have research unit ingredient " .. ingredient_id .. "." ) 260end 261 262--- Returns a technology that unlocks the given recipe. The technology returned will be the one that was added earliest. 263--- @param recipe_id data.RecipeID 264--- @return data.TechnologyPrototype? 265function data_util . get_technology_for_recipe ( recipe_id ) 266for _ , technology in pairs ( data . raw . technology ) do 267for _ , effect in pairs ( technology . effects or {} ) do 268if effect . type == "unlock-recipe" and effect . recipe == recipe_id then 269return technology 270end 271end 272end 273end 274 275--- Converts a furnace prototype into an assembling machine prototype. 276--- @param furnace_name data.EntityID 277--- @return data.AssemblingMachinePrototype 278function data_util . furnace_to_assembler ( furnace_name ) 279local furnace =data . raw . furnace [ furnace_name ] 280if not furnace then 281error ( "Furnace " .. furnace_name .. " does not exist." ) 282end 283 284local assembler =table . deepcopy ( furnace ) --[[@as data.AssemblingMachinePrototype]] 285assembler . type ="assembling-machine" 286assembler . source_inventory_size =nil --- @diagnostic disable-line 287assembler . energy_source . emissions_per_minute ={ pollution =2 } 288assembler . energy_usage ="0.2MW" 289data . raw . furnace [ furnace_name ] =nil 290data : extend ( { assembler } ) 291return assembler 292end 293 294--- Returns a copy of the given prototype's icons in the standard format. 295--- @param prototype k2.PrototypeWithIcons 296--- @return data.IconData[] 297function data_util . get_icons ( prototype ) 298local icons =prototype . icons -- LuaLS isn't inferring the dropped optional unless we assign it to a local first. 299if icons then 300return table . deepcopy ( icons ) 301end 302return { { icon =prototype . icon , icon_size =prototype . icon_size } } 303end 304 305--- Converts the given prototype's icons to the standard format and returns a reference to them. 306--- The game will throw an error if you provide an empty icons array, so if using the function, care must be taken to 307--- ensure that at least one icon layer exists at tne end of loading. 308--- @param prototype k2.PrototypeWithIcons 309--- @return data.IconData[] 310function data_util . standardize_icons ( prototype ) 311if not prototype . icons then 312prototype . icons ={} 313if prototype . icon then 314table . insert ( prototype . icons , { icon =prototype . icon , icon_size =prototype . icon_size } ) 315prototype . icon =nil 316prototype . icon_size =nil 317end 318end 319return prototype . icons 320end 321 322--- Overrides the prototype's icon. 323--- @param prototype k2.PrototypeWithIcons 324--- @param icon data.FileName 325--- @param icon_size double? 326function data_util . set_icon ( prototype , icon , icon_size ) 327assert ( prototype , "Provided prototype was nil." ) 328if prototype . icons then 329prototype . icons =nil 330end 331prototype . icon =icon 332prototype . icon_size =icon_size 333end 334 335--- Overrides the prototype's icons array. 336--- @param prototype k2.PrototypeWithIcons 337--- @param icons data.IconData[] 338function data_util . set_icons ( prototype , icons ) 339assert ( prototype , "Provided prototype was nil." ) 340prototype . icons =icons 341prototype . icon =nil 342prototype . icon_size =nil 343end 344 345--- Fields are analagous to `data.IconData`. 346--- @class k2.IconTransformOptions 347--- @field shift Vector? 348--- @field scale double? 349 350--- Applies the given transformations to each layer in the icons array in-place and returns the array. 351--- @param icons data.IconData[] 352--- @param transforms k2.IconTransformOptions 353--- @return data.IconData[] 354function data_util . transform_icons ( icons , transforms ) 355for _ , icon in pairs ( icons ) do 356if transforms . shift then 357icon . shift =flib_position . add (( icon . shift or { 0 , 0 } ), transforms . shift ) 358end 359if transforms . scale then 360icon . scale =( icon . scale or 1 ) * transforms . scale 361end 362end 363return icons 364end 365 366--- Adds or replaces the recipe's ingredient matching the given name. 367--- @param recipe_name data.RecipeID 368--- @param old_ingredient_name data.FluidID|data.ItemID 369--- @param new_ingredient data.IngredientPrototype 370function data_util . add_or_replace_ingredient ( recipe_name , old_ingredient_name , new_ingredient ) 371local recipe =data . raw . recipe [ recipe_name ] 372if not recipe then 373error ( "Recipe " .. recipe_name .. " does not exist." ) 374end 375if not recipe . ingredients then 376recipe . ingredients ={ new_ingredient } 377return 378end 379for i , ingredient in pairs ( recipe . ingredients ) do 380if ingredient . name == old_ingredient_name then 381recipe . ingredients [ i ] =new_ingredient 382return 383end 384end 385table . insert ( recipe . ingredients , new_ingredient ) 386end 387 388--- Converts the given ingredient to the new ingredient, carrying over other properties. 389--- @param recipe_name data.RecipeID 390--- @param old_ingredient_name data.FluidID|data.ItemID 391--- @param new_ingredient_name data.FluidID|data.ItemID 392function data_util . convert_ingredient ( recipe_name , old_ingredient_name , new_ingredient_name ) 393local recipe =data . raw . recipe [ recipe_name ] 394if not recipe then 395error ( "Recipe " .. recipe_name .. " does not exist." ) 396end 397if not recipe . ingredients then 398error ( "Recipe " .. recipe_name .. " has no ingredients." ) 399return 400end 401for _ , ingredient in pairs ( recipe . ingredients ) do 402if ingredient . name == old_ingredient_name then 403ingredient . name =new_ingredient_name 404break 405end 406end 407end 408 409--- Remove the given ingredient from the recipe. 410--- @param recipe_name data.RecipeID 411--- @param ingredient_name data.FluidID|data.ItemID 412function data_util . remove_ingredient ( recipe_name , ingredient_name ) 413local recipe =data . raw . recipe [ recipe_name ] 414if not recipe then 415error ( "Recipe " .. recipe_name .. " does not exist." ) 416end 417if not recipe . ingredients then 418error ( "Recipe " .. recipe_name .. " has no ingredients." ) 419return 420end 421for i , ingredient in pairs ( recipe . ingredients ) do 422if ingredient . name == ingredient_name then 423table . remove ( recipe . ingredients , i ) 424return 425end 426end 427error ( "Recipe " .. recipe_name .. " does not have ingredient " .. ingredient_name .. "." ) 428end 429 430--- Adds or replaces the recipe's product matching the given name. 431--- @param recipe_name data.RecipeID 432--- @param old_product_name data.FluidID|data.ItemID 433--- @param new_product data.ProductPrototype 434function data_util . add_or_replace_product ( recipe_name , old_product_name , new_product ) 435local recipe =data . raw . recipe [ recipe_name ] 436if not recipe then 437error ( "Recipe " .. recipe_name .. " does not exist." ) 438end 439if not recipe . results then 440recipe . results ={ new_product } 441return 442end 443for i , product in pairs ( recipe . results ) do 444if product . name == old_product_name then 445recipe . results [ i ] =new_product 446return 447end 448end 449table . insert ( recipe . results , new_product ) 450end 451 452--- @param lab_name data.EntityID 453--- @param input_name data.ItemID 454function data_util . remove_lab_input ( lab_name , input_name ) 455local lab =data . raw . lab [ lab_name ] 456assert ( lab , "Lab " .. lab_name .. " does not exist." ) 457local inputs =lab . inputs 458assert ( inputs , "Lab inputs are nil." ) 459for i =1 , # inputs do 460if inputs [ i ] == input_name then 461table . remove ( inputs , i ) 462return 463end 464end 465error ( "Lab " .. lab_name .. " does not contain input " .. input_name .. "." ) 466end 467 468--- @param energy_source data.EnergySource 469--- @param category_name data.FuelCategoryID 470function data_util . add_fuel_category ( energy_source , category_name ) 471if energy_source . type ~= "burner" then 472error ( "Energy source must be a burner to add a fuel category." ) 473end 474if not energy_source . fuel_categories then 475energy_source . fuel_categories ={} 476end 477table . insert ( energy_source . fuel_categories , category_name ) 478end 479 480return data_util