z_mirror/MouseOverConstruction
git clone https://git.raiguard.me/z_mirror/MouseOverConstruction
7a81c3d
insertion
1--- @param box1 BoundingBox 2--- @param box2 BoundingBox 3local function bounding_boxes_equal ( box1 , box2 ) 4return box1 . left_top . x == box2 . left_top . x 5and box1 . left_top . y == box2 . left_top . y 6and box1 . right_bottom . x == box2 . right_bottom . x 7and box1 . right_bottom . y == box2 . right_bottom . y 8end 9 10--- @class common 11local common ={} 12 13--- Builds an entity over the top of an existing entity. 14--- @param player LuaPlayer 15--- @param entity LuaEntity 16--- @param new_prototype LuaEntityPrototype 17--- @param new_quality LuaQualityPrototype 18--- @return LuaEntity? 19function common . build ( player , entity , new_prototype , new_quality ) 20local item_spec =common . get_item_to_place ( player , new_prototype , new_quality ) 21if not item_spec then 22return nil 23end 24 25local bounding_box =entity . bounding_box 26local surface =entity . surface 27local position =entity . position 28local direction =entity . direction 29local quality =entity . quality 30local force =entity . force 31 32local new_entity =player . surface . create_entity ( { 33name =new_prototype . name , 34position =entity . position , 35direction =entity . direction , 36quality =new_quality , 37force =entity . force , 38fast_replace =true , 39player =player , 40character =player . character , 41raise_built =true , 42create_build_effect_smoke =true , 43spawn_decorations =true , 44move_stuck_players =true , 45item =item_spec . item , 46register_plant =true , 47--- Undergound belt 48type =entity . type == "underground-belt" and entity . belt_to_ground_type or nil , 49} ) 50if not new_entity or not new_entity . valid then 51-- Some mods will immediately replace the entity with a different one. Let's see if we can detect this. 52for _ , replaced_entity in 53pairs ( surface . find_entities_filtered ( { 54direction =direction , 55position =position , 56quality =quality . name , 57force =force , 58} )) 59do 60if 61replaced_entity . type ~= "entity-ghost" 62and replaced_entity . type ~= "tile-ghost" 63and bounding_boxes_equal ( replaced_entity . bounding_box , bounding_box ) 64then 65new_entity =replaced_entity 66break 67else 68return 69end 70end 71end 72 73item_spec . item . count =item_spec . item . count - item_spec . count 74 75player . play_sound ( { 76path ="entity-build/" .. new_entity . name , 77position =new_entity . position , 78} ) 79 80return new_entity 81end 82 83--- @param player LuaPlayer 84--- @param entity LuaEntity 85--- @param new_prototype LuaEntityPrototype 86--- @return boolean 87function common . check_can_place_entity ( player , entity , new_prototype ) 88-- TODO: Remote interface for mods to conditionally decide if placement is allowed. 89if 90not player . can_place_entity ( { 91name =new_prototype . name , 92position =entity . position , 93direction =entity . direction , 94} ) 95then 96storage . recheck_on_move [ player . index ] =true 97return false 98end 99return true 100end 101 102--- @param item LuaItemStack 103--- @param name string 104--- @param quality LuaQualityPrototype 105--- @param min_count uint? 106--- @param max_count uint? 107local function does_item_match ( item , name , quality , min_count , max_count ) 108min_count =min_count or 0 109max_count =max_count or math . huge 110 111return item . valid_for_read 112and item . name == name 113and item . quality == quality 114and item . count >= min_count 115and item . count <= max_count 116end 117 118--- Returns the first LuaItemStack with the given name and quality. If count is provided, the returned item stack will 119--- contain at least count items. 120--- @param player LuaPlayer 121--- @param name string 122--- @param quality LuaQualityPrototype 123--- @param min_count uint? 124--- @param max_count uint? 125--- @return fun(): LuaItemStack? 126function common . get_item ( player , name , quality , min_count , max_count ) 127local cursor_stack_used =false 128local cursor_stack =player . cursor_stack 129local inventory =player . get_main_inventory () 130local i =0 131return function () 132if not cursor_stack_used then 133cursor_stack_used =true 134if cursor_stack and does_item_match ( cursor_stack , name , quality , min_count , max_count ) then 135return cursor_stack 136end 137end 138 139if not inventory then 140return 141end 142 143while i <= # inventory do 144i =i + 1 145local stack =inventory [ i ] 146if does_item_match ( stack , name , quality , min_count , max_count ) then 147return stack 148end 149end 150end 151end 152 153--- Returns the first LuaItemStack that can build the given entity and quality. 154--- @param player LuaPlayer 155--- @param prototype LuaEntityPrototype 156--- @param quality LuaQualityPrototype 157--- @return {item: LuaItemStack, count: uint}? 158function common . get_item_to_place ( player , prototype , quality ) 159for _ , item_to_place in pairs ( prototype . items_to_place_this or {} ) do 160local item =common . get_item ( player , item_to_place . name , quality , item_to_place . count )() 161if item then 162return { item =item , count =item_to_place . count } 163end 164end 165end 166 167return common