161 lines
7.1 KiB
Lua
Raw Normal View History

---
--- constants
---
--this is the distance from spawn where ore will be at max density
--anything past that will still be at max density. it's best to have
--the max density of ore back from the edge of the world a bit.
--remember this distance is calculated in 3d, if you set it at 30000
--then a player at -20000,-10000,-20000 will reach the max density point
--with 45000 max density will be reached at -26000,-26000,-26000
--still might need to be bigger than that.
local orethin_maxdist=45000
local orethin_maxheight=100
local orethin_mindensity=0.05
local orethin_eastadj=0.5 --remember this is chance to THIN, so bigger numbers mean less ore
local orethin_westadj=1
--this needs to be further parameterized, allow the east west border to be parameterized, etc.
--grab content IDs -- You need these to efficiently access and set node data. get_node() works, but is far slower
local c_air = minetest.get_content_id("air")
local c_stone = minetest.get_content_id("default:stone")
local c_water = minetest.get_content_id("default:water_source")
local c_lava = minetest.get_content_id("default:lava_source")
local c_iron = minetest.get_content_id("default:stone_with_iron")
local c_coal = minetest.get_content_id("default:stone_with_coal")
local c_copper = minetest.get_content_id("default:stone_with_copper")
local c_mese = minetest.get_content_id("default:stone_with_mese")
local c_meseblock = minetest.get_content_id("default:mese")
local c_esem = minetest.get_content_id("default:stone_with_esem")
local c_esemblock = minetest.get_content_id("default:esem")
local c_diamond = minetest.get_content_id("default:stone_with_diamond")
local c_goldblock = minetest.get_content_id("default:goldblock")
local c_diamondblock = minetest.get_content_id("default:diamondblock")
local c_drydirt = minetest.get_content_id("default:dry_dirt")
--I would love to do these as const arrays, but I'm afraid
--it would slow the logic down.
local orethin_thinlist={minetest.get_content_id("default:stone_with_iron"),
minetest.get_content_id("default:stone_with_coal"),
minetest.get_content_id("default:stone_with_copper"),
minetest.get_content_id("default:stone_with_mese"),
minetest.get_content_id("default:mese"),
minetest.get_content_id("default:stone_with_esem"),
minetest.get_content_id("default:esem"),
minetest.get_content_id("default:stone_with_diamond"),
minetest.get_content_id("default:goldblock"),
minetest.get_content_id("default:diamondblock")
}
--print("thinlist="..dump(orethin_thinlist))
--the list of ores that will appear in the west only
local orethin_westlist={minetest.get_content_id("default:stone_with_mese"),
minetest.get_content_id("default:mese"),
minetest.get_content_id("default:stone_with_esem"),
minetest.get_content_id("default:esem")
}
--print("westlist="..dump(orethin_westlist))
--grab content IDs -- You need these to efficiently access and set node data. get_node() works, but is far slower
local c_stone = minetest.get_content_id("default:stone")
local c_goldblock = minetest.get_content_id("default:goldblock")
local c_diamondblock = minetest.get_content_id("default:diamondblock")
---ORE THINNING
minetest.register_on_generated(function(minp, maxp, seed)
--if out of range of ore_gen limits (will need to change this when skylands implemented
if minp.y > orethin_maxheight then
return --quit; otherwise, you'd have wasted resources
end
--easy reference to commonly used values
local t1 = os.clock()
local x1 = maxp.x
local y1 = maxp.y
local z1 = maxp.z
local x0 = minp.x
local y0 = minp.y
local z0 = minp.z
print ("[ore_thin] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
--This actually initializes the LVM
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local data = vm:get_data()
--we do NOT need to recalculate adj for each and every node!
--calculate it once for the entire cluster
local dist = math.sqrt(x0^2 + y0^2 + z0^2)
if dist > orethin_maxdist then
dist=orethin_maxdist
end --orethin_maxdist
local adj=(dist/orethin_maxdist)
if adj < orethin_mindensity then
adj=orethin_mindensity --because we don't want spawn completely bare
end --min adj
--adj for east
if x0 > 0 then
adj=adj*orethin_eastadj
else
adj=adj*orethin_westadj
end
print("[orethin] ("..x0..","..y0..","..z0..") dist="..dist.." orethin_maxdist="..orethin_maxdist.." adj="..adj)
local changed=false
for z = z0, z1 do -- for each xy plane progressing northwards
for y = y0, y1 do -- for each x row progressing upwards
--local vi = area:index(x0, y, z) -- This accesses the node at a given position
for x = x0, x1 do -- for each node do
local vi = area:index(x, y, z) -- This accesses the node at a given position
--x>0 is east, so we exclude ores in the west only list
--cant search arrays that way when the elements are numbers.
--if x > 0 and orethin_westlist.data[vi] then
if x > 0 and (data[vi] == c_mese or
data[vi] == c_meseblock or
data[vi] == c_esem or
data[vi] == c_esemblock ) then
data[vi] = c_stone -- remove the ore
--data[vi] = c_diamondblock --*VIEWTHINNING* uncomment this line to make it easy to see removal
changed=true
-- Now test the node if it's an ore that needs to be potentially thinned out
--elseif orethin_thinlist[data[vi]] then
elseif data[vi] == c_iron or
data[vi] == c_copper or
data[vi] == c_diamond or
data[vi] == c_mese or
data[vi] == c_meseblock or
data[vi] == c_esem or
data[vi] == c_esemblock then
-- it is, so now thin it based on distance from center
-- note the bigger adj is, the smaller the chance of thinning.
if math.random() > adj then
data[vi] = c_stone -- remove the ore
--data[vi] = c_goldblock --*VIEWTHINNING* uncomment this line to make it easy to see thinning
changed=true
end
end -- end ore existence check
end -- end 'x' loop
end -- end 'y' loop
end -- end 'z' loop
if changed==true then
-- Wrap things up and write back to map
--send data back to voxelmanip
vm:set_data(data)
--calc lighting
vm:set_lighting({day=0, night=0})
vm:calc_lighting()
--write it to world
vm:write_to_map(data)
end
local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
print ("[ore_thin] "..chugent.." ms") --tell people how long
end) --register_on_generated ore thinning