diff --git a/winterize/init.lua b/winterize/init.lua index 5c0d677..8bcb380 100644 --- a/winterize/init.lua +++ b/winterize/init.lua @@ -8,7 +8,7 @@ local grasses = {"dry_grass", "grass", "coniferous_litter",} local leaves = {"leaves", "aspen_leaves", "jungleleaves", "bush_leaves",} minetest.register_node("winterize:ice", { -- breaks instantly, drops nothing - drawtype = "nodebox", + drawtype = "signlike", description = "Ice", tiles = {"winterize_ice_seethrough.png"}, buildable_to = true, @@ -16,7 +16,7 @@ minetest.register_node("winterize:ice", { -- breaks instantly, drops nothing paramtype = "light", sunlight_propagates = true, use_texture_alpha = "clip", - node_box = { + selection_box = { type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, -0.4, 0.5}, @@ -58,88 +58,86 @@ end -- Add snow and ice to map ctf_api.register_on_new_match(function() - minetest.after(2, function() - local vm = VoxelManip(ctf_map.current_map.pos1, ctf_map.current_map.pos2) - local o_pos1, o_pos2 = vm:get_emerged_area() - - minetest.log("action", "Starting to winterize...") - minetest.handle_async(function(data, pos1, pos2, present_count) - local outdata = {} - local present_positions = {} - - local math_random = math.random - local math_min = math.min - - local ID_AIR = minetest.CONTENT_AIR - local ID_IGNORE = minetest.get_content_id("ctf_map:ignore") - local ID_GLASS = minetest.get_content_id("ctf_map:ind_glass") - local ID_WATER = minetest.get_content_id("default:water_source") - - local snow_place_blacklist = { - "ctf_map:", "default:snow", "doors:", "ctf_teams:", "default:fence", - "stairs:", "walls:", "default:mese_post", "xpanes:", - } - local SNOW_ID = minetest.get_content_id("default:snow") - local ICE_ID = minetest.get_content_id("winterize:ice") - local PRESENT_ID = minetest.get_content_id("winterize:present") - - local Nx = pos2.x - pos1.x + 1 - local Ny = pos2.y - pos1.y + 1 - local count = 0 - - for y = pos1.y+1, pos2.y-1 do -- Make sure above/below checks don't go out of bounds - for z = pos1.z, pos2.z do - for x = pos1.x, pos2.x do - local pre = (((z - pos1.z) * Ny) * Nx) - local mid = (y - pos1.y) * Nx - local post = (x - pos1.x) + 1 - - local vi = pre + mid + post - - local vi_below = pre + (mid - Nx) + post - - if data[vi_below] ~= ID_AIR and data[vi] == ID_AIR then - if y <= pos2.y - 10 and data[vi_below] == ID_WATER then -- will ignore water near the ceiling - outdata[vi] = {i = ICE_ID, b = vi_below} - count = count + 1 - elseif data[pre + (mid + Nx) + post] == ID_AIR then -- id_above == AIR - local name = minetest.get_name_from_content_id(data[vi_below]) - local hit = false - - if minetest.registered_nodes[name].walkable == false then - hit = true - else - for _, pattern in pairs(snow_place_blacklist) do - if name:find(pattern) then - hit = true - break - end + local vm = VoxelManip(ctf_map.current_map.pos1, ctf_map.current_map.pos2) + local o_pos1, o_pos2 = vm:get_emerged_area() + + minetest.log("action", "Starting to winterize...") + minetest.handle_async(function(data, pos1, pos2, present_count) + local outdata = {} + local present_positions = {} + + local math_random = math.random + local math_min = math.min + + local ID_AIR = minetest.CONTENT_AIR + local ID_IGNORE = minetest.get_content_id("ctf_map:ignore") + local ID_GLASS = minetest.get_content_id("ctf_map:ind_glass") + local ID_WATER = minetest.get_content_id("default:water_source") + + local snow_place_blacklist = { + "ctf_map:", "default:snow", "doors:", "ctf_teams:", "default:fence", + "stairs:", "walls:", "default:mese_post", "xpanes:", + } + local SNOW_ID = minetest.get_content_id("default:snow") + local ICE_ID = minetest.get_content_id("winterize:ice") + local PRESENT_ID = minetest.get_content_id("winterize:present") + + local Nx = pos2.x - pos1.x + 1 + local Ny = pos2.y - pos1.y + 1 + local count = 0 + + for y = pos1.y+1, pos2.y-1 do -- Make sure above/below checks don't go out of bounds + for z = pos1.z, pos2.z do + for x = pos1.x, pos2.x do + local pre = (((z - pos1.z) * Ny) * Nx) + local mid = (y - pos1.y) * Nx + local post = (x - pos1.x) + 1 + + local vi = pre + mid + post + + local vi_below = pre + (mid - Nx) + post + + if data[vi_below] ~= ID_AIR and data[vi] == ID_AIR then + if y <= pos2.y - 10 and data[vi_below] == ID_WATER then -- will ignore water near the ceiling + outdata[vi] = {i = ICE_ID, b = vi_below} + count = count + 1 + elseif data[pre + (mid + Nx) + post] == ID_AIR then -- id_above == AIR + local name = minetest.get_name_from_content_id(data[vi_below]) + local hit = false + + if minetest.registered_nodes[name].walkable == false then + hit = true + else + for _, pattern in pairs(snow_place_blacklist) do + if name:find(pattern) then + hit = true + break end end + end - if not hit then - for i = 1, math_min((pos2.y - y) - 4, 80) do - local id = data[pre + (mid + (i * Nx)) + post] - - if id ~= ID_AIR then - -- Only count a hit if we aren't near the top of the map - local ignore_check = data[pre + (mid + ((i+4) * Nx)) + post] + if not hit then + for i = 1, math_min((pos2.y - y) - 4, 80) do + local id = data[pre + (mid + (i * Nx)) + post] - if ignore_check ~= ID_AIR and ignore_check ~= ID_IGNORE and ignore_check ~= ID_GLASS then - hit = true - end + if id ~= ID_AIR then + -- Only count a hit if we aren't near the top of the map + local ignore_check = data[pre + (mid + ((i+4) * Nx)) + post] - break + if ignore_check ~= ID_AIR and ignore_check ~= ID_IGNORE and ignore_check ~= ID_GLASS then + hit = true end + + break end + end - if not hit then - if math_random(5) <= 4 then -- roughly 4/5 map coverage - outdata[vi] = {i = SNOW_ID, b = vi_below} - count = count + 1 - elseif present_count > 0 then - table.insert(present_positions, {vi = vi, i = PRESENT_ID, b = vi_below}) - end + if not hit then + if math_random(5) <= 4 then -- roughly 4/5 map coverage + outdata[vi] = {i = SNOW_ID, b = vi_below} + count = count + 1 + elseif present_count > 0 then + table.insert(present_positions, {vi = vi, i = PRESENT_ID, b = vi_below}) end end end @@ -147,50 +145,48 @@ ctf_api.register_on_new_match(function() end end end + end - if present_count > 0 and #present_positions > 0 then - table.shuffle(present_positions) + if present_count > 0 and #present_positions > 0 then + table.shuffle(present_positions) - for i=1, math_min(present_count, #present_positions) do - local vi = present_positions[i].vi - present_positions[i].vi = nil - outdata[vi] = present_positions[i] - end + for i=1, math_min(present_count, #present_positions) do + local vi = present_positions[i].vi + present_positions[i].vi = nil + outdata[vi] = present_positions[i] end - - return outdata, count - end, - function(outdata, change_count) - if change_count <= 1000 then - snow.SPAWN_SNOW = false - minetest.log("action", "Done winterizing, skipped changes: "..change_count) - return + end + + return outdata, count + end, + function(outdata, change_count) + if change_count <= 1000 then + snow.SPAWN_SNOW = false + minetest.log("action", "Done winterizing, skipped changes: "..change_count) + return + else + snow.SPAWN_SNOW = true + minetest.log("action", "Done winterizing. Changes: "..change_count) + end + + local newvm = VoxelManip(o_pos1, o_pos2) + local data = newvm:get_data() + + local ID_AIR = minetest.CONTENT_AIR + local ID_IGNORE = minetest.CONTENT_IGNORE + for i in pairs(data) do + if outdata[i] then + if data[i] == ID_AIR and data[outdata[i].b] ~= ID_AIR then + data[i] = outdata[i].i + end else - snow.SPAWN_SNOW = true - minetest.log("action", "Done winterizing. Changes: "..change_count) + data[i] = ID_IGNORE end + end - minetest.after(2, function() - local newvm = VoxelManip(o_pos1, o_pos2) - local data = newvm:get_data() - - local ID_AIR = minetest.CONTENT_AIR - local ID_IGNORE = minetest.CONTENT_IGNORE - for i in pairs(data) do - if outdata[i] then - if data[i] == ID_AIR and data[outdata[i].b] ~= ID_AIR then - data[i] = outdata[i].i - end - else - data[i] = ID_IGNORE - end - end - - newvm:set_data(data) - newvm:write_to_map(false) - end) - end, vm:get_data(), o_pos1, o_pos2, winterize.get_present_count()) - end) + newvm:set_data(data) + newvm:write_to_map(false) + end, vm:get_data(), o_pos1, o_pos2, winterize.get_present_count()) end) local function get_drop(original, rarity)