mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
Merge pull request #114 from mattNeumayer/perf_fix
Biter Battle: Improve terrain generation performance
This commit is contained in:
commit
3ec2142a47
@ -107,6 +107,22 @@ local function process_entity(surface, entity)
|
||||
entity_copy_functions[entity.type](surface, entity, mirror_position)
|
||||
end
|
||||
|
||||
|
||||
local function mirror_tiles(surface, source_area)
|
||||
mirrored = {}
|
||||
|
||||
local i = 0
|
||||
for x = source_area.left_top.x, source_area.left_top.x+31 do
|
||||
for y = source_area.left_top.y, source_area.left_top.y+31 do
|
||||
local tile = surface.get_tile(x, y)
|
||||
mirrored[i] = {name = tile.name, position = {-x, -y - 1}}
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(mirrored, true)
|
||||
end
|
||||
|
||||
local function clear_chunk(surface, area)
|
||||
surface.destroy_decoratives{area=area}
|
||||
if area.left_top.y > 32 or area.left_top.x > 32 or area.left_top.x < -32 then
|
||||
@ -163,6 +179,13 @@ local function on_chunk_generated(event)
|
||||
global.chunks_to_mirror[game.tick + delay][#global.chunks_to_mirror[game.tick + delay] + 1] = {x = x / 32, y = y / 32}
|
||||
end
|
||||
|
||||
local function add_work(work)
|
||||
if not global.ctp then global.ctp = { continue = 1, last = 0 } end
|
||||
local idx = global.ctp.last + 1
|
||||
global.ctp[idx] = work
|
||||
global.ctp.last = idx
|
||||
end
|
||||
|
||||
local function ocg (event)
|
||||
if event.area.left_top.y < 0 then return end
|
||||
if event.surface.name ~= "biter_battles" then return end
|
||||
@ -176,14 +199,10 @@ local function ocg (event)
|
||||
|
||||
local x = ((event.area.left_top.x + 16) * -1) - 16
|
||||
local y = ((event.area.left_top.y + 16) * -1) - 16
|
||||
add_work({x = x / 32, y = y / 32, state = 1})
|
||||
|
||||
if not global.ctp then global.ctp = { continue = 1, last = 0 } end
|
||||
local idx = global.ctp.last + 1
|
||||
global.ctp[idx] = {x = x / 32, y = y / 32, state = 1}
|
||||
global.ctp.last = idx
|
||||
end
|
||||
|
||||
|
||||
local function ticking_work()
|
||||
if not global.ctp then return end
|
||||
local work = global.mws or 512 -- define the number of work per tick here (for copies, creations, deletions)
|
||||
@ -204,8 +223,12 @@ local function ticking_work()
|
||||
}
|
||||
local surface = game.surfaces["biter_battles"]
|
||||
if not surface.is_chunk_generated(c) then
|
||||
-- game.print("Chunk not generated yet, requesting..")
|
||||
surface.request_to_generate_chunks({x = area.left_top.x - 16, y = area.left_top.y - 16}, 1)
|
||||
--game.print("Chunk not generated yet, requesting..")
|
||||
surface.request_to_generate_chunks({x = area.left_top.x + 16, y = area.left_top.y + 16}, 0)
|
||||
-- requeue
|
||||
add_work(c)
|
||||
global.ctp.continue = i+1
|
||||
global.ctp[i] = nil
|
||||
return
|
||||
end
|
||||
|
||||
@ -215,16 +238,7 @@ local function ticking_work()
|
||||
list = function () return surface.find_entities_filtered({area = inverted_area, name = "character", invert = true}) end,
|
||||
action = function (e) e.destroy() end
|
||||
},
|
||||
[2] = {
|
||||
name = "Tile copy",
|
||||
list = function () return surface.find_tiles_filtered({area = area}) end,
|
||||
action = function (tile)
|
||||
surface.set_tiles({{
|
||||
name = tile.name,
|
||||
position = {x = tile.position.x * -1, y = (tile.position.y * -1) - 1}
|
||||
}}, true)
|
||||
end
|
||||
},
|
||||
[2] = {},
|
||||
[3] = {
|
||||
name = "Entity copy",
|
||||
list = function () return surface.find_entities_filtered({area = area}) end,
|
||||
@ -246,24 +260,31 @@ local function ticking_work()
|
||||
}
|
||||
}
|
||||
|
||||
local task = tasks[c.state]
|
||||
-- game.print(task.name)
|
||||
d = d or task.list()
|
||||
local last_idx = nil
|
||||
for k, v in pairs(d) do
|
||||
task.action(v)
|
||||
d[k] = nil
|
||||
last_idx = k
|
||||
w = w + 1
|
||||
if w > work then break end
|
||||
end
|
||||
|
||||
local next_idx, _ = next(d, last_idx)
|
||||
if next_idx == nil then
|
||||
c.state = c.state + 1
|
||||
c.data = nil
|
||||
else
|
||||
c.data = d
|
||||
if c.state == 2 then
|
||||
mirror_tiles(surface, area)
|
||||
c.state = c.state + 1
|
||||
c.data = nil
|
||||
else
|
||||
local task = tasks[c.state]
|
||||
-- game.print(task.name)
|
||||
d = d or task.list()
|
||||
local last_idx = nil
|
||||
for k, v in pairs(d) do
|
||||
task.action(v)
|
||||
d[k] = nil
|
||||
last_idx = k
|
||||
w = w + 1
|
||||
if w > work then break end
|
||||
end
|
||||
|
||||
local next_idx, _ = next(d, last_idx)
|
||||
if next_idx == nil then
|
||||
c.state = c.state + 1
|
||||
c.data = nil
|
||||
else
|
||||
c.data = d
|
||||
end
|
||||
end
|
||||
|
||||
if c.state == 5 then
|
||||
|
@ -22,29 +22,25 @@ local function get_noise(name, pos)
|
||||
local seed = game.surfaces[1].map_gen_settings.seed
|
||||
local noise_seed_add = 25000
|
||||
if name == 1 then
|
||||
local noise = {}
|
||||
noise[1] = simplex_noise(pos.x * 0.0042, pos.y * 0.0042, seed)
|
||||
local noise = simplex_noise(pos.x * 0.0042, pos.y * 0.0042, seed)
|
||||
seed = seed + noise_seed_add
|
||||
noise[2] = simplex_noise(pos.x * 0.031, pos.y * 0.031, seed)
|
||||
seed = seed + noise_seed_add
|
||||
noise[3] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
|
||||
local noise = noise[1] + noise[2] * 0.08 + noise[3] * 0.025
|
||||
noise = noise + simplex_noise(pos.x * 0.031, pos.y * 0.031, seed) * 0.08
|
||||
seed = seed + noise_seed_add
|
||||
noise = noise + simplex_noise(pos.x * 0.1, pos.y * 0.1, seed) * 0.025
|
||||
return noise
|
||||
end
|
||||
|
||||
if name == 2 then
|
||||
local noise = {}
|
||||
noise[1] = simplex_noise(pos.x * 0.011, pos.y * 0.011, seed)
|
||||
local noise = simplex_noise(pos.x * 0.011, pos.y * 0.011, seed)
|
||||
seed = seed + noise_seed_add
|
||||
noise[2] = simplex_noise(pos.x * 0.08, pos.y * 0.08, seed)
|
||||
local noise = noise[1] + noise[2] * 0.2
|
||||
noise = noise + simplex_noise(pos.x * 0.08, pos.y * 0.08, seed) * 0.2
|
||||
return noise
|
||||
end
|
||||
|
||||
if name == 3 then
|
||||
local noise = {}
|
||||
noise[1] = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed)
|
||||
local noise = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed)
|
||||
seed = seed + noise_seed_add
|
||||
noise[2] = simplex_noise(pos.x * 0.08, pos.y * 0.08, seed)
|
||||
local noise = noise[1] + noise[2] * 0.1
|
||||
noise = noise + simplex_noise(pos.x * 0.08, pos.y * 0.08, seed) * 0.1
|
||||
return noise
|
||||
end
|
||||
end
|
||||
@ -145,6 +141,92 @@ function is_horizontal_border_river(pos)
|
||||
return false
|
||||
end
|
||||
|
||||
local function generate_inner_spawn_circle(pos, distance_to_center, surface)
|
||||
-- assert(distance_to_center < spawn_circle_size) == true
|
||||
local tile = false
|
||||
if distance_to_center < 7 then
|
||||
tile = "sand-1"
|
||||
elseif distance_to_center < 9.5 then
|
||||
tile = "refined-concrete"
|
||||
else
|
||||
tile = "deepwater"
|
||||
if math_random(1, 48) == 1 then surface.create_entity({name = "fish", position = pos}) end
|
||||
end
|
||||
|
||||
surface.set_tiles({{name = tile, position = pos}}, true)
|
||||
end
|
||||
|
||||
local function generate_starting_area(pos, distance_to_center, surface)
|
||||
-- assert(distance_to_center >= spawn_circle_size) == true
|
||||
local spawn_wall_radius = 116
|
||||
local noise_multiplier = 15
|
||||
local min_noise = -noise_multiplier * 1.25
|
||||
|
||||
-- Avoid calculating noise, see comment below
|
||||
if (distance_to_center + min_noise - spawn_wall_radius) > 4.5 then
|
||||
return
|
||||
end
|
||||
|
||||
local noise = get_noise(2, pos) * noise_multiplier
|
||||
local distance_from_spawn_wall = distance_to_center + noise - spawn_wall_radius
|
||||
-- distance_from_spawn_wall is the difference between the distance_to_center (with added noise)
|
||||
-- and our spawn_wall radius (spawn_wall_radius=116), i.e. how far are we from the ring with radius spawn_wall_radius.
|
||||
-- The following shows what happens depending on distance_from_spawn_wall:
|
||||
-- min max
|
||||
-- N/A -10 => replace water
|
||||
-- if noise_2 > -0.5:
|
||||
-- -1.75 0 => wall
|
||||
-- else:
|
||||
-- -6 -3 => 1/16 chance of turrent or turret-remnants
|
||||
-- -1.95 0 => wall
|
||||
-- 0 4.5 => chest-remnants with 1/3, chest with 1/(distance_from_spawn_wall+2)
|
||||
--
|
||||
-- => We never do anything for (distance_to_center + min_noise - spawn_wall_radius) > 4.5
|
||||
|
||||
if distance_from_spawn_wall < -10 and not is_horizontal_border_river(pos) then
|
||||
local tile_name = surface.get_tile(pos).name
|
||||
if tile_name == "water" or tile_name == "deepwater" then
|
||||
surface.set_tiles({{name = get_replacement_tile(surface, pos), position = pos}}, true)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if surface.can_place_entity({name = "wooden-chest", position = pos}) and surface.can_place_entity({name = "coal", position = pos}) then
|
||||
local noise_2 = get_noise(3, pos)
|
||||
if noise_2 < 0.25 then
|
||||
if noise_2 > -0.5 then
|
||||
if distance_from_spawn_wall > -1.75 and distance_from_spawn_wall < 0 then
|
||||
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
|
||||
end
|
||||
else
|
||||
if distance_from_spawn_wall > -1.95 and distance_from_spawn_wall < 0 then
|
||||
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
|
||||
|
||||
elseif distance_from_spawn_wall > 0 and distance_from_spawn_wall < 4.5 then
|
||||
local name = "wooden-chest"
|
||||
local r_max = math.floor(math.abs(distance_from_spawn_wall)) + 2
|
||||
if math_random(1,3) == 1 then name = name .. "-remnants" end
|
||||
if math_random(1,r_max) == 1 then surface.create_entity({name = name, position = pos, force = "north"}) end
|
||||
|
||||
elseif distance_from_spawn_wall > -6 and distance_from_spawn_wall < -3 then
|
||||
if math_random(1, 16) == 1 then
|
||||
if surface.can_place_entity({name = "gun-turret", position = pos}) then
|
||||
local t = surface.create_entity({name = "gun-turret", position = pos, force = "north"})
|
||||
t.insert({name = "firearm-magazine", count = math_random(6,12)})
|
||||
end
|
||||
else
|
||||
if math_random(1, 16) == 1 then
|
||||
if surface.can_place_entity({name = "gun-turret", position = pos}) then
|
||||
surface.create_entity({name = "gun-turret-remnants", position = pos, force = "north"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function generate_circle_spawn(event)
|
||||
if global.bb_spawn_generated then return end
|
||||
|
||||
@ -153,69 +235,19 @@ local function generate_circle_spawn(event)
|
||||
local left_top_x = event.area.left_top.x
|
||||
local left_top_y = event.area.left_top.y
|
||||
|
||||
if left_top_x < -320 then return end
|
||||
if left_top_x > 320 then return end
|
||||
if left_top_y < -320 then return end
|
||||
if left_top_x < -160 then return end
|
||||
if left_top_x > 160 then return end
|
||||
if left_top_y < -160 then return end
|
||||
|
||||
local r = 116
|
||||
for x = 0, 31, 1 do
|
||||
for y = 0, 31, 1 do
|
||||
local pos = {x = left_top_x + x, y = left_top_y + y}
|
||||
local distance_to_center = math.sqrt(pos.x ^ 2 + pos.y ^ 2)
|
||||
local noise = get_noise(2, pos) * 15
|
||||
|
||||
local tile = false
|
||||
if distance_to_center < spawn_circle_size then
|
||||
tile = "deepwater"
|
||||
if math_random(1, 48) == 1 then surface.create_entity({name = "fish", position = pos}) end
|
||||
end
|
||||
if distance_to_center < 9.5 then tile = "refined-concrete" end
|
||||
if distance_to_center < 7 then tile = "sand-1" end
|
||||
|
||||
if distance_to_center + noise < r - 10 and distance_to_center > spawn_circle_size and not is_horizontal_border_river(pos) then
|
||||
local tile_name = surface.get_tile(pos).name
|
||||
if tile_name == "water" or tile_name == "deepwater" then
|
||||
surface.set_tiles({{name = get_replacement_tile(surface, pos), position = pos}}, true)
|
||||
end
|
||||
end
|
||||
|
||||
if tile then surface.set_tiles({{name = tile, position = pos}}, true) end
|
||||
|
||||
if surface.can_place_entity({name = "wooden-chest", position = pos}) and surface.can_place_entity({name = "coal", position = pos}) then
|
||||
local noise_2 = get_noise(3, pos)
|
||||
if noise_2 < 0.25 then
|
||||
local spawn_wall_r = distance_to_center + noise
|
||||
if noise_2 > -0.5 then
|
||||
if spawn_wall_r < r and spawn_wall_r > r - 1.75 then
|
||||
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
|
||||
end
|
||||
else
|
||||
if spawn_wall_r < r and spawn_wall_r > r - 1.95 then
|
||||
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
|
||||
else
|
||||
if spawn_wall_r < r + 4.5 and spawn_wall_r > r then
|
||||
local name = "wooden-chest"
|
||||
local r_max = math.floor(math.abs(spawn_wall_r - r)) + 2
|
||||
if math_random(1,3) == 1 then name = name .. "-remnants" end
|
||||
if math_random(1,r_max) == 1 then surface.create_entity({name = name, position = pos, force = "north"}) end
|
||||
end
|
||||
end
|
||||
if spawn_wall_r < r - 3 and spawn_wall_r > r - 6 then
|
||||
if math_random(1, 16) == 1 then
|
||||
if surface.can_place_entity({name = "gun-turret", position = pos}) then
|
||||
local t = surface.create_entity({name = "gun-turret", position = pos, force = "north"})
|
||||
t.insert({name = "firearm-magazine", count = math_random(6,12)})
|
||||
end
|
||||
else
|
||||
if math_random(1, 16) == 1 then
|
||||
if surface.can_place_entity({name = "gun-turret", position = pos}) then
|
||||
surface.create_entity({name = "gun-turret-remnants", position = pos, force = "north"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
generate_inner_spawn_circle(pos, distance_to_center, surface)
|
||||
else
|
||||
generate_starting_area(pos, distance_to_center, surface)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -29,6 +29,11 @@ for i=0,511 do
|
||||
perm[i+1] = p[bit32.band(i, 255) + 1]
|
||||
end
|
||||
|
||||
-- special case of dot with 3 inputs
|
||||
local function dot2(g, x, y)
|
||||
return x * g[1] + y *g[2]
|
||||
end
|
||||
|
||||
local function dot(g, ...)
|
||||
local v = {...}
|
||||
local sum = 0
|
||||
@ -38,16 +43,17 @@ local function dot(g, ...)
|
||||
return sum
|
||||
end
|
||||
|
||||
local F2 = 0.5*(math.sqrt(3.0)-1.0)
|
||||
local G2 = (3.0-math.sqrt(3.0))/6.0
|
||||
|
||||
function Simplex.d2(xin, yin,seed)
|
||||
xin = xin + seed
|
||||
yin = yin + seed
|
||||
local n0, n1, n2 -- Noise contributions from the three corners
|
||||
-- Skew the input space to determine which simplex cell we're in
|
||||
local F2 = 0.5*(math.sqrt(3.0)-1.0)
|
||||
local s = (xin+yin)*F2; -- Hairy factor for 2D
|
||||
local i = math.floor(xin+s)
|
||||
local j = math.floor(yin+s)
|
||||
local G2 = (3.0-math.sqrt(3.0))/6.0
|
||||
local t = (i+j)*G2
|
||||
local X0 = i-t -- Unskew the cell origin back to (x,y) space
|
||||
local Y0 = j-t
|
||||
@ -70,34 +76,39 @@ function Simplex.d2(xin, yin,seed)
|
||||
local y1 = y0 - j1 + G2
|
||||
local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
|
||||
local y2 = y0 - 1 + 2 * G2
|
||||
|
||||
-- Work out the hashed gradient indices of the three simplex corners
|
||||
local ii = bit32.band(i, 255)
|
||||
local jj = bit32.band(j, 255)
|
||||
local gi0 = perm[ii + perm[jj+1]+1] % 12
|
||||
local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
|
||||
local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
|
||||
|
||||
-- Calculate the contribution from the three corners
|
||||
local t0 = 0.5 - x0 * x0 - y0 * y0
|
||||
if t0 < 0 then
|
||||
n0 = 0.0
|
||||
else
|
||||
t0 = t0 * t0
|
||||
n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
|
||||
n0 = t0 * t0 * dot2(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
|
||||
end
|
||||
|
||||
local t1 = 0.5 - x1 * x1 - y1 * y1
|
||||
if t1 < 0 then
|
||||
n1 = 0.0
|
||||
else
|
||||
t1 = t1 * t1
|
||||
n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
|
||||
n1 = t1 * t1 * dot2(grad3[gi1+1], x1, y1)
|
||||
end
|
||||
|
||||
local t2 = 0.5 - x2 * x2 - y2 * y2
|
||||
if t2 < 0 then
|
||||
n2 = 0.0
|
||||
else
|
||||
t2 = t2 * t2
|
||||
n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
|
||||
n2 = t2 * t2 * dot2(grad3[gi2+1], x2, y2)
|
||||
end
|
||||
|
||||
-- Add contributions from each corner to get the final noise value.
|
||||
-- The result is scaled to return values in the interval [-1,1].
|
||||
return 70.0 * (n0 + n1 + n2)
|
||||
|
Loading…
Reference in New Issue
Block a user