1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-24 03:47:58 +02:00

planet_prison: optimize map gen

Optimizes map generation. Currently, 16kb were used per chunk for
internal processing geared towards update time and not save time.
Map generation was optimized in a such was that only 8 bytes are
used per chunk, but since we no longer have granular data as before,
occasional lag spikes may occur as much more data needs to get
processed right as we get it.
This commit is contained in:
cogito 2020-01-09 20:32:13 +01:00
parent ea2eaf2a01
commit 17486c4053
2 changed files with 123 additions and 114 deletions

View File

@ -202,7 +202,7 @@ local function redraw_gui(p)
p.gui.left.clear() p.gui.left.clear()
local merchant = global.this.events.merchant local merchant = global.this.events.merchant
local perks = global.this.perks[p.tag] local perks = global.this.perks[p.name]
local chat_type = "Global chat" local chat_type = "Global chat"
if not perks.chat_global then if not perks.chat_global then
chat_type = "Buddies chat" chat_type = "Buddies chat"
@ -243,7 +243,7 @@ end
local function print_merchant_position(player) local function print_merchant_position(player)
local position = global.this.events.merchant.position local position = global.this.events.merchant.position
local perks = global.this.perks[player.tag] local perks = global.this.perks[player.name]
if not perks.minimap then if not perks.minimap then
player.print(string.format(">> You were able to spot him %s from your location", player.print(string.format(">> You were able to spot him %s from your location",
_common.get_readable_direction(player.position, position))) _common.get_readable_direction(player.position, position)))
@ -255,7 +255,7 @@ end
local function on_gui_click(e) local function on_gui_click(e)
local elem = e.element local elem = e.element
local p = game.players[e.player_index] local p = game.players[e.player_index]
local perks = global.this.perks[p.tag] local perks = global.this.perks[p.name]
if elem.name == "chat_toggle" then if elem.name == "chat_toggle" then
if perks.chat_global then if perks.chat_global then
@ -293,17 +293,26 @@ local function on_gui_click(e)
end end
end end
local function get_random_id()
while true do
local id = _common.rand_range(1000, 9999)
if global.this.perks[id] == nil then
return id
end
end
end
local function init_player(p) local function init_player(p)
p.teleport({0, 0}, "arena") p.teleport({0, 0}, "arena")
local s = p.surface local s = p.surface
local position = get_non_obstructed_position(s, 10) local position = get_non_obstructed_position(s, 10)
p.teleport(position, "arena") p.teleport(position, "arena")
p.name = "inmate" local id = get_random_id()
p.tag = string.format("[%d]", _common.rand_range(1000, 9999)) p.name = string.format("inmate_%d", id)
p.force = game.create_force(p.tag) p.force = game.create_force(p.name)
p.force.set_friend("neutral", true) p.force.set_friend("neutral", true)
global.this.perks[p.tag] = { global.this.perks[p.name] = {
flashlight = false, flashlight = false,
flashlight_enabled = false, flashlight_enabled = false,
minimap = false, minimap = false,
@ -424,25 +433,16 @@ local function on_tick()
return return
end end
if not s.is_chunk_generated then
log("on_tick: is_chunk_generated nil, map save?")
return
end
if not s.is_chunk_generated({0, 0}) then
return
end
local surf = global.this.surface local surf = global.this.surface
if game.tick % 4 == 0 then if game.tick % 4 == 0 then
_ai.do_job(surf, _ai.command.seek_and_destroy_player) _ai.do_job(surf, _ai.command.seek_and_destroy_player)
end end
if game.tick % 10000 == 0 then if (game.tick + 1) % 500 == 0 then
unlink_old_blueprints("player_ship") unlink_old_blueprints("player_ship")
end end
_layers.do_job(surf, 64) _layers.do_job(surf)
cause_event(s) cause_event(s)
end end
@ -466,7 +466,7 @@ local function on_chunk_generated(e)
end end
make_ore_patch(e) make_ore_patch(e)
_layers.push_bounding_box(e.area) _layers.push_chunk(e.position)
end end
local function on_player_mined_entity(e) local function on_player_mined_entity(e)
@ -503,13 +503,8 @@ local function on_player_died(e)
end end
local p = game.players[index] local p = game.players[index]
game.merge_forces(p.tag, "neutral") game.merge_forces(p.name, "neutral")
global.this.perks[p.tag] = { global.this.perks[p.name] = nil
flashlight = false,
flashlight_enabled = false,
minimap = false,
chat_global = true,
}
end end
local function on_player_respawned(e) local function on_player_respawned(e)
@ -537,23 +532,22 @@ local function on_player_dropped_item(e)
local peer = ent_list[1].player local peer = ent_list[1].player
if p.force.get_friend(peer.force) then if p.force.get_friend(peer.force) then
p.print(string.format("The %s %s is your buddy already", peer.name, p.print(string.format("The %s is your buddy already", peer.name))
peer.tag))
return return
end end
if global.this.last_friend[peer.tag] == p.tag then if global.this.last_friend[peer.name] == p.name then
p.force.set_cease_fire(peer.force, true) p.force.set_cease_fire(peer.force, true)
peer.force.set_cease_fire(p.force, true) peer.force.set_cease_fire(p.force, true)
p.print(string.format("%s %s is now your buddy", peer.name, peer.tag)) p.print(string.format("%s is now your buddy", peer.name))
peer.print(string.format("%s %s is now your buddy", p.name, p.tag)) peer.print(string.format("%s is now your buddy", p.name))
global.this.last_friend[p.tag] = "" global.this.last_friend[p.name] = nil
return return
end end
global.this.last_friend[p.tag] = peer.tag global.this.last_friend[p.name] = peer.name
p.print(string.format("You want %s %s to be your buddy", peer.name, peer.tag)) p.print(string.format("You want %s to be your buddy", peer.name))
peer.print(string.format("The %s %s wants to be your buddy", p.name, p.tag)) peer.print(string.format("The %s wants to be your buddy", p.name))
elseif ent.stack.name == "coal" then elseif ent.stack.name == "coal" then
local ent_list = p.surface.find_entities_filtered({ local ent_list = p.surface.find_entities_filtered({
name = p.character.name, name = p.character.name,
@ -567,15 +561,15 @@ local function on_player_dropped_item(e)
local peer = ent_list[1].player local peer = ent_list[1].player
if p.force.get_friend(peer.force) then if p.force.get_friend(peer.force) then
p.print(string.format("The %s %s is not your buddy", p.name, p.tag)) p.print(string.format("The %s is not your buddy", p.name))
return return
end end
p.force.set_cease_fire(peer.force, false) p.force.set_cease_fire(peer.force, false)
peer.force.set_cease_fire(p.force, false) peer.force.set_cease_fire(p.force, false)
p.print(string.format("The %s %s is no longer your buddy", peer.name, peer.tag)) p.print(string.format("The %s is no longer your buddy", peer.name))
peer.print(string.format("The %s %s is no longer your buddy", p.name, p.tag)) peer.print(string.format("The %s is no longer your buddy", p.name))
end end
end end
@ -699,7 +693,7 @@ local function on_market_item_purchased(e)
local p = game.players[e.player_index] local p = game.players[e.player_index]
local m = e.market local m = e.market
local o = m.get_market_items()[e.offer_index].offer local o = m.get_market_items()[e.offer_index].offer
local perks = global.this.perks[p.tag] local perks = global.this.perks[p.name]
if o.effect_description == "Construct a flashlight" then if o.effect_description == "Construct a flashlight" then
perks.flashlight = true perks.flashlight = true
@ -730,13 +724,13 @@ local function stringify_color(color)
end end
local function create_console_message(p, message) local function create_console_message(p, message)
local prefix_fmt = "[color=%s]%s %s:[/color]" local prefix_fmt = "[color=%s]%s:[/color]"
local msg_fmt = "[color=%s]%s[/color]" local msg_fmt = "[color=%s]%s[/color]"
local color = stringify_color(p.chat_color) local color = stringify_color(p.chat_color)
local prefix = string.format(prefix_fmt, color, p.name, p.tag) local prefix = string.format(prefix_fmt, color, p.name)
local p_msg = string.format(msg_fmt, color, message) local p_msg = string.format(msg_fmt, color, message)
if global.this.perks[p.tag].chat_global then if global.this.perks[p.name].chat_global then
msg_fmt = "[color=red]global:[/color] %s %s" msg_fmt = "[color=red]global:[/color] %s %s"
else else
msg_fmt = "[color=green]buddies:[/color] %s %s" msg_fmt = "[color=green]buddies:[/color] %s %s"
@ -759,10 +753,10 @@ local function on_console_chat(e)
local p = game.players[pid] local p = game.players[pid]
local msg = create_console_message(p, e.message) local msg = create_console_message(p, e.message)
if global.this.perks[p.tag].chat_global then if global.this.perks[p.name].chat_global then
for _, peer in pairs(game.players) do for _, peer in pairs(game.players) do
local perks = global.this.perks[peer.tag] if peer.name ~= p.name then
if peer.tag ~= p.tag then local perks = global.this.perks[peer.name]
if perks.minimap then if perks.minimap then
peer.print(msg) peer.print(msg)
else else
@ -774,8 +768,8 @@ local function on_console_chat(e)
for _, f in pairs(game.forces) do for _, f in pairs(game.forces) do
if p.force.get_cease_fire(f) then if p.force.get_cease_fire(f) then
local peer = f.players[1] local peer = f.players[1]
local perks = global.this.perks[peer.tag] if peer.name ~= p.name then
if peer.tag ~= p.tag then local perks = global.this.perks[peer.name]
if perks.minimap then if perks.minimap then
peer.print(msg) peer.print(msg)
else else
@ -813,7 +807,7 @@ local function on_rocket_launched(e)
surf.print(">> Nobody escaped by it") surf.print(">> Nobody escaped by it")
else else
local p = game.players[pid] local p = game.players[pid]
surf.print(string.format(">> The inmate %s was able to escape", p.tag)) surf.print(string.format(">> The %s was able to escape", p.name))
on_player_died({player_index = pid}) on_player_died({player_index = pid})
p.character.die() p.character.die()
end end

View File

@ -1,28 +1,24 @@
local this, public = {}, {} local public = {}
global.this = {}
local _global = require("utils.global") local _global = require("utils.global")
local _common = require(".common") local _common = require(".common")
local _simplex = require(".simplex_noise") local _simplex = require(".simplex_noise")
_global.register(this, function(t) this = t end) _global.register(global.this, function(t) global.this = t end)
this._grid = {} global.this._grid = {}
this._exclusions = {} global.this._exclusions = {}
this._layers = {} global.this._layers = {}
this._collision_mask = {} global.this._collision_mask = {}
public.init = function() public.init = function()
_simplex.init() _simplex.init()
end end
local function _push_bounding_box(_, x, y)
table.insert(this._grid, { x, y })
end
--[[ --[[
push_bounding_box - Pushes bounding box into a grid for later processing. push_chunk - Pushes chunk position into a grid for later processing.
@param bb - BoundingBox. @param chunk - ChunkPosition
--]] --]]
public.push_bounding_box = function(bb) public.push_chunk = function(chunk)
_common.for_bounding_box(nil, bb, _push_bounding_box) table.insert(global.this._grid, chunk)
end end
--[[ --[[
@ -30,7 +26,7 @@ add_excluding_bounding_box - Pushes bounding box into exclusion list.
@param bb - BoundindBox. @param bb - BoundindBox.
--]] --]]
public.push_excluding_bounding_box = function(bb) public.push_excluding_bounding_box = function(bb)
table.insert(this._exclusions, bb) table.insert(global.this._exclusions, bb)
end end
--[[ --[[
@ -38,10 +34,10 @@ remove_ecluding_bounding_box - Removes bounding box from exclusion list.
@param bb - BoundingBox to get rid of. @param bb - BoundingBox to get rid of.
--]] --]]
public.remove_excluding_bounding_box = function(bb) public.remove_excluding_bounding_box = function(bb)
for i = 1, #this._exclusions do for i = 1, #global.this._exclusions do
local box = this._exclusions[i] local box = global.this._exclusions[i]
if box == bb then if box == bb then
table.remove(this._exclusions, i) table.remove(global.this._exclusions, i)
break break
end end
end end
@ -66,7 +62,7 @@ public.add_noise_layer = function(type, name, objects, elevation, resolution)
hook = nil, hook = nil,
} }
table.insert(this._layers, layer) table.insert(global.this._layers, layer)
end end
--[[ --[[
@ -75,7 +71,7 @@ add_noise_layer_hook - Execute callback on created object.
@param hook - Callback that will be called with an object argument. @param hook - Callback that will be called with an object argument.
--]] --]]
public.add_noise_layer_hook = function(name, hook) public.add_noise_layer_hook = function(name, hook)
for _, layer in pairs(this._layers) do for _, layer in pairs(global.this._layers) do
if layer.name == name then if layer.name == name then
layer.hook = hook layer.hook = hook
break break
@ -88,7 +84,7 @@ set_collision_mask - Set which tiles should be ignored.
@param mask - Table of collision masks. @param mask - Table of collision masks.
--]] --]]
public.set_collision_mask = function(mask) public.set_collision_mask = function(mask)
this._collision_mask = mask global.this._collision_mask = mask
end end
local function _do_job_tile(surf, layer) local function _do_job_tile(surf, layer)
@ -117,54 +113,73 @@ local function _do_job_entity(surf, layer)
end end
end end
--[[ local function _do_job(surf, x, y)
do_job - Do a single step propagation of a layers. local point = {
@param surf - LuaSurface, onto which action is taken. x = x,
@param limit - How many requests to process. y = y,
--]] }
public.do_job = function(surf, limit)
for i = 1, #this._grid do
local point = table.remove(this._grid)
for _, box in pairs(this._exclusions) do
if _common.point_in_bounding_box(point, box) then
goto next_point
end
end
for _, layer in pairs(this._layers) do for _, exclusion in pairs(global.this._exclusions) do
local ret = _simplex.get(point, layer.resolution) if _common.point_in_bounding_box(point, exclusion) then
if ret >= layer.elevation then return
local tile = surf.get_tile(point)
for _, mask in pairs(this._collision_mask) do
if tile.collides_with(mask) then
goto continue
end
end
local object_name = layer.objects[1]
if #layer.objects > 1 then
local index = _common.rand_range(1, #layer.objects)
object_name = layer.objects[index]
end
local object = {
name = object_name,
position = point,
}
table.insert(layer.cache, object)
break
::continue::
end
end
::next_point::
if i >= limit then
break
end end
end end
for _, layer in pairs(this._layers) do for _, layer in pairs(global.this._layers) do
local ret = _simplex.get(point, layer.resolution)
if ret >= layer.elevation then
local tile = surf.get_tile(point)
for _, mask in pairs(global.this._collision_mask) do
if tile.collides_with(mask) then
goto continue
end
end
local object_name = layer.objects[1]
if #layer.objects > 1 then
local index = _common.rand_range(1, #layer.objects)
object_name = layer.objects[index]
end
local object = {
name = object_name,
position = point,
}
table.insert(layer.cache, object)
break
::continue::
end
end
end
--[[
do_job - Do a single step propagation of a layers.
@param surf - LuaSurface, onto which action is taken.
--]]
public.do_job = function(surf)
if #global.this._grid <= 0 then
return
end
local chunk = table.remove(global.this._grid)
local x = _common.get_axis(chunk, "x")
local y = _common.get_axis(chunk, "y")
chunk = {
left_top = {
x = x * 32,
y = y * 32
},
right_bottom = {
x = (x * 32) + 32,
y = (y * 32) + 32,
}
}
_common.for_bounding_box(surf, chunk, _do_job)
for _, layer in pairs(global.this._layers) do
local cache = layer.cache local cache = layer.cache
if #cache >= 1 then if #cache >= 1 then
if layer.type == "LuaTile" then if layer.type == "LuaTile" then