1
0
mirror of https://github.com/veden/Rampant.git synced 2025-03-17 20:58:35 +02:00

FACTO-230: onTick performance tuning

This commit is contained in:
Aaron Veden 2023-03-19 10:25:46 -07:00
parent 984f5afcbe
commit 6216e8e799
No known key found for this signature in database
GPG Key ID: FF5990B1C6DD3F84
11 changed files with 224 additions and 223 deletions

View File

@ -68,6 +68,7 @@ Version: 3.2.0
- Reduced corpse and particle variation to optimize increased entity times due to high entity counts
- Removed unneeded iterators
- Moved map properties directly into chunk object
- Moved background chunk scanning under a mod setting for when mods don't raise events
Framework:
- Consolidated most libraries

View File

@ -281,6 +281,7 @@ local function onModSettingsChange(event)
Universe["peacefulAIToggle"] = settings.global["rampant--peacefulAIToggle"].value
Universe["printAIStateChanges"] = settings.global["rampant--printAIStateChanges"].value
Universe["debugTemperament"] = settings.global["rampant--debugTemperament"].value
Universe["legacyChunkScanning"] = settings.global["rampant--legacyChunkScanning"].value
Universe["enabledPurpleSettlerCloud"] = settings.global["rampant--enabledPurpleSettlerCloud"].value
@ -340,45 +341,44 @@ local function onConfigChanged()
end
end
local function onEnemyBaseBuild(event)
local entity = event.entity or event.created_entity
if entity.valid then
local map = Universe.maps[entity.surface.index]
if not map then
return
local function onEnemyBaseBuild(entity, tick)
local map = Universe.maps[entity.surface.index]
if not map then
return
end
local chunk = getChunkByPosition(map, entity.position)
if (chunk ~= -1) then
local base = findNearbyBase(chunk)
if not base then
base = createBase(map,
chunk,
tick)
end
activateMap(map)
local chunk = getChunkByPosition(map, entity.position)
if (chunk ~= -1) then
local base = findNearbyBase(chunk)
if not base then
base = createBase(map,
chunk,
event.tick)
end
registerEnemyBaseStructure(entity, base, event.tick)
if Universe.NEW_ENEMIES then
if Universe.NEW_ENEMIES then
if VANILLA_ENTITY_TYPE_LOOKUP[entity.name] then
queueUpgrade(entity,
base,
nil,
true,
true)
else
registerEnemyBaseStructure(entity, base, tick, true)
end
else
local x,y = positionToChunkXY(entity.position)
onChunkGenerated({
surface = entity.surface,
tick = event.tick,
area = {
left_top = {
x = x,
y = y
}
}
})
registerEnemyBaseStructure(entity, base, tick)
end
else
local x,y = positionToChunkXY(entity.position)
onChunkGenerated({
surface = entity.surface,
tick = tick,
area = {
left_top = {
x = x,
y = y
}
}
})
end
end
@ -386,14 +386,16 @@ local function onBuild(event)
local entity = event.created_entity or event.entity
if entity.valid then
local entityForceName = entity.force.name
if entityForceName == "enemy" and BUILDING_HIVE_TYPE_LOOKUP[entity.name] then
onEnemyBaseBuild(event)
if entityForceName == "enemy" then
if BUILDING_HIVE_TYPE_LOOKUP[entity.name] then
onEnemyBaseBuild(entity, event.tick)
end
else
local map = Universe.maps[entity.surface.index]
if not map then
return
end
if (entity.type == "resource") and (entityForceName == "neutral") then
if entity.type == "resource" then
registerResource(entity, map)
else
accountPlayerEntity(entity, map, true)
@ -662,59 +664,8 @@ local function onRocketLaunch(event)
end
end
local function onEntitySpawned(entity, tick)
if Universe.NEW_ENEMIES and entity.valid then
local map = Universe.maps[entity.surface.index]
if not map then
return
end
if BUILDING_HIVE_TYPE_LOOKUP[entity.name] then
activateMap(map)
local disPos = distortPosition(Universe.random, entity.position, 8)
local chunk = getChunkByPosition(map, disPos)
if (chunk ~= -1) then
local base = findNearbyBase(chunk)
if not base then
base = createBase(map,
chunk,
tick)
end
local meanTTL = linearInterpolation(Universe.evolutionLevel, MAX_HIVE_TTL, MIN_HIVE_TTL)
queueUpgrade(entity,
base,
disPos,
true,
true,
tick + gaussianRandomRangeRG(meanTTL,
DEV_HIVE_TTL,
MIN_HIVE_TTL,
MAX_HIVE_TTL,
Universe.random))
else
local x,y = positionToChunkXY(entity.position)
onChunkGenerated({
surface = entity.surface,
tick = tick,
area = {
left_top = {
x = x,
y = y
}
}
})
entity.destroy()
end
end
end
end
local function onTriggerEntityCreated(event)
if (event.effect_id == "hive-spawned--rampant") then
onEntitySpawned(event.source_entity, event.tick)
elseif (event.effect_id == "rampant-drain-trigger") then
if (event.effect_id == "rampant-drain-trigger") then
local entity = event.target_entity
if (entity and entity.valid) then
local map = Universe.maps[event.surface_index]
@ -1004,7 +955,8 @@ script.on_event(defines.events.on_tick,
function ()
local gameRef = game
local tick = gameRef.tick
local pick = tick % 8
local range = (Universe.legacyChunkScanning and 5) or 4
local pick = tick % range
-- local profiler = game.create_profiler()
local map = nextMap()
@ -1018,38 +970,31 @@ script.on_event(defines.events.on_tick,
elseif (pick == 1) then
processPlayers(gameRef.connected_players, tick)
elseif (pick == 2) then
processPendingUpgrades(tick)
processVengence()
elseif (pick == 3) then
disperseVictoryScent()
processAttackWaves()
processClouds(tick)
elseif (pick == 3) then
processPendingUpgrades(tick)
processScanChunks()
planning(gameRef.forces.enemy.evolution_factor)
elseif (pick == 4) then
if map then
scanPlayerMap(map)
scanResourceMap(map)
scanEnemyMap(map, tick)
end
elseif (pick == 5) then
if map then
scanEnemyMap(map, tick)
end
elseif (pick == 6) then
if map then
scanPlayerMap(map)
end
elseif (pick == 7) then
processPendingChunks(tick)
processScanChunks()
planning(gameRef.forces.enemy.evolution_factor)
end
if map then
processMap(map, tick)
end
-- game.print({"", "--dispatch3 ", profiler, " , ", pick," , ",math.random()})
processBaseAIs(tick)
processNests(tick)
processPendingUpgrades(tick)
processPendingUpgrades(tick)
cleanSquads(tick)
-- game.print({"", "--dispatch4 ", profiler, " , ", pick," , ",math.random()})
@ -1076,14 +1021,18 @@ script.on_event(defines.events.on_script_trigger_effect, onTriggerEntityCreated)
script.on_event(defines.events.on_pre_robot_exploded_cliff, onRobotCliff)
script.on_event(defines.events.on_biter_base_built, onEnemyBaseBuild)
script.on_event({defines.events.on_player_mined_entity,
defines.events.on_robot_mined_entity}, onMine)
script.on_event({defines.events.on_built_entity,
defines.events.on_robot_built_entity,
defines.events.script_raised_built,
defines.events.script_raised_revive}, onBuild)
script.on_event(
{
defines.events.on_built_entity,
defines.events.on_robot_built_entity,
defines.events.script_raised_built,
defines.events.script_raised_revive,
defines.events.on_biter_base_built
},
onBuild)
script.on_event(defines.events.on_rocket_launched, onRocketLaunch)
script.on_event({defines.events.on_entity_died,

View File

@ -16,7 +16,6 @@
local vanillaUpdates = require("prototypes/utils/UpdatesVanilla")
local attackBall = require("prototypes/utils/AttackBall")
local constants = require("libs/Constants")
if settings.startup["rampant--useDumbProjectiles"].value or settings.startup["rampant--newEnemies"].value then
attackBall.generateVanilla()
@ -47,18 +46,3 @@ for _, robot in pairs(data.raw["construction-robot"]) do
end
end
--[[
try to make sure new maps use the correct map settings without having to completely load the mod.
done because seeing desync issues with dynamic map-settings changes before re-saving the map.
--]]
local mapSettings = data.raw["map-settings"]["map-settings"]
mapSettings.max_failed_behavior_count = 3 -- constants.MAX_FAILED_BEHAVIORS
mapSettings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
mapSettings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
mapSettings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS
mapSettings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
mapSettings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
mapSettings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR

View File

@ -19,7 +19,6 @@
local colorUtils = require("prototypes/utils/ColorUtils")
local smokeUtils = require("prototypes/utils/SmokeUtils")
local swarmUtils = require("prototypes/SwarmUtils")
local constants = require("libs/Constants")
local collision_mask_util = require("collision-mask-util")
-- imported functions

View File

@ -387,14 +387,54 @@ function BaseUtils.canMigrate(base)
return true
end
function BaseUtils.queueUpgrade(entity, base, disPos, evolve, register, timeDelay)
function BaseUtils.queueUpgrade(entity, base, disPos, evolve, timeDelay)
local map = base.map
local baseAlignment = base.alignment
local position = disPos or entity.position
local pickedBaseAlignment
if baseAlignment[2] then
if Universe.random() < 0.75 then
pickedBaseAlignment = baseAlignment[2]
else
pickedBaseAlignment = baseAlignment[1]
end
else
pickedBaseAlignment = baseAlignment[1]
end
local currentEvo = entity.prototype.build_base_evolution_requirement or 0
local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX)
local evoIndex = mMax(distance, Universe.evolutionLevel)
local name = BaseUtils.findEntityUpgrade(pickedBaseAlignment,
currentEvo,
evoIndex,
entity,
map,
evolve)
if name == entity.name then
return
end
if not evolve and Universe.printBaseUpgrades then
local surface = base.map.surface
surface.print(
"["..base.id.."]:"..surface.name.." Upgrading "
.. entity.name .. " to " .. name
.. " [gps=".. position.x ..",".. position.y .."]"
)
end
Universe.pendingUpgrades[entity.unit_number] = {
["position"] = disPos,
["register"] = register,
["evolve"] = evolve,
["base"] = base,
["position"] = position,
["map"] = map,
["name"] = name,
["entity"] = entity,
["delayTLL"] = timeDelay
["delayTLL"] = timeDelay,
["state"] = 1
}
end
@ -541,7 +581,7 @@ function BaseUtils.processBaseMutation(chunk, map, base)
if (base.points >= cost) then
local position = entity.position
BaseUtils.modifyBaseSpecialPoints(base, -cost, "Scheduling Entity upgrade", position.x, position.y)
BaseUtils.queueUpgrade(entity, base, nil, false, true)
BaseUtils.queueUpgrade(entity, base, nil, false)
end
end
end

View File

@ -282,7 +282,6 @@ function ChunkUtils.initialScan(chunk, map, tick)
queueUpgrade(enemyBuilding,
base,
nil,
true,
true)
end
end

View File

@ -35,7 +35,7 @@ constants.TEMPERAMENT_RANGE_MAX = 10000
constants.TEMPERAMENT_RANGE_MIN = -constants.TEMPERAMENT_RANGE_MAX
constants.TEMPERAMENT_DIVIDER = 1 / (2 * constants.TEMPERAMENT_RANGE_MAX)
constants.PROCESS_QUEUE_SIZE = 50
constants.PROCESS_QUEUE_SIZE = 40
constants.SCAN_QUEUE_SIZE = 2
constants.RESOURCE_QUEUE_SIZE = 2
constants.ENEMY_QUEUE_SIZE = 1

View File

@ -22,6 +22,7 @@ local Processor = {}
--
local Universe
local Queries
-- imports
@ -36,6 +37,8 @@ local MathUtils = require("MathUtils")
-- Constants
local CHUNK_SIZE = Constants.CHUNK_SIZE
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = Constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
local PROCESS_QUEUE_SIZE = Constants.PROCESS_QUEUE_SIZE
@ -182,41 +185,76 @@ function Processor.processPlayers(players, tick)
end
end
if (#players > 0) then
local player = players[Universe.random(#players)]
if validPlayer(player) then
local char = player.character
local map = Universe.maps[char.surface.index]
if map then
local playerChunk = getChunkByPosition(map, char.position)
if (#players == 0) then
return
end
local player = players[Universe.random(#players)]
if not validPlayer(player) then
return
end
local char = player.character
local map = Universe.maps[char.surface.index]
if not map then
return
end
local playerChunk = getChunkByPosition(map, char.position)
if (playerChunk ~= -1) then
local base = findNearbyBase(playerChunk)
if not base then
return
end
local allowingAttacks = canAttack(base)
local vengence = allowingAttacks and
(base.unitPoints >= AI_VENGENCE_SQUAD_COST) and
((getEnemyStructureCount(playerChunk) > 0) or
(getCombinedDeathGeneratorRating(playerChunk) < Universe.retreatThreshold))
if (playerChunk == -1) then
return
end
local base = findNearbyBase(playerChunk)
if not base then
return
end
local allowingAttacks = canAttack(base)
local vengence = allowingAttacks and
(base.unitPoints >= AI_VENGENCE_SQUAD_COST) and
((getEnemyStructureCount(playerChunk) > 0) or
(getCombinedDeathGeneratorRating(playerChunk) < Universe.retreatThreshold))
for x=playerChunk.x - PROCESS_PLAYER_BOUND, playerChunk.x + PROCESS_PLAYER_BOUND, 32 do
for y=playerChunk.y - PROCESS_PLAYER_BOUND, playerChunk.y + PROCESS_PLAYER_BOUND, 32 do
local chunk = getChunkByXY(map, x, y)
local quadrant = Universe.random(4)
if (chunk ~= -1) then
processPheromone(chunk, tick, true)
local pX = playerChunk.x
local pY = playerChunk.y
local pXStart
local pYStart
local pXEnd
local pYEnd
if chunk.nestCount then
processNestActiveness(chunk, tick)
if quadrant == 1 then
pXStart = pX - PROCESS_PLAYER_BOUND
pXEnd = pX
pYStart = pY - PROCESS_PLAYER_BOUND
pYEnd = pY
elseif quadrant == 2 then
pXStart = pX
pXEnd = pX + PROCESS_PLAYER_BOUND
pYStart = pY - PROCESS_PLAYER_BOUND
pYEnd = pY
elseif quadrant == 3 then
pXStart = pX - PROCESS_PLAYER_BOUND
pXEnd = pX
pYStart = pY
pYEnd = pY + PROCESS_PLAYER_BOUND
elseif quadrant == 4 then
pXStart = pX
pXEnd = pX + PROCESS_PLAYER_BOUND
pYStart = pY
pYEnd = pY + PROCESS_PLAYER_BOUND
end
if vengence then
Universe.vengenceQueue[chunk.id] = chunk
end
end
end
end
for x=pXStart, pXEnd, CHUNK_SIZE do
for y=pYStart, pYEnd, CHUNK_SIZE do
local chunk = getChunkByXY(map, x, y)
if (chunk ~= -1) then
processPheromone(chunk, tick, true)
if chunk.nestCount then
processNestActiveness(chunk, tick)
if vengence then
Universe.vengenceQueue[chunk.id] = chunk
end
end
end
@ -514,7 +552,7 @@ function Processor.processPendingUpgrades(tick)
return
end
local entity = entityData.entity
if not entity.valid then
if (entityData.state ~= 3) and not entity.valid then
Universe.pendingUpgrades[entityId] = nil
return
end
@ -522,69 +560,45 @@ function Processor.processPendingUpgrades(tick)
if entityData.delayTLL and tick < entityData.delayTLL then
return
end
Universe.pendingUpgrades[entityId] = nil
local base = entityData.base
local map = base.map
local baseAlignment = base.alignment
local position = entityData.position or entity.position
local state = entityData.state
if state == 1 then
local map = entityData.map
unregisterEnemyBaseStructure(map, entity, nil, true)
local pickedBaseAlignment
if baseAlignment[2] then
if Universe.random() < 0.75 then
pickedBaseAlignment = baseAlignment[2]
else
pickedBaseAlignment = baseAlignment[1]
end
else
pickedBaseAlignment = baseAlignment[1]
end
entityData.position = map.surface.find_non_colliding_position(
entityData.name,
entityData.position,
8,
1,
true
)
local currentEvo = entity.prototype.build_base_evolution_requirement or 0
local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX)
local evoIndex = mMax(distance, Universe.evolutionLevel)
local name = findEntityUpgrade(pickedBaseAlignment,
currentEvo,
evoIndex,
entity,
map,
entityData.evolve)
local entityName = entity.name
if not name then
entityData.state = 2
elseif state == 2 then
entity.destroy()
return
elseif (name == entityName) or not name then
return
end
local surface = entity.surface
local query = Universe.ppuUpgradeEntityQuery
query.name = name
unregisterEnemyBaseStructure(map, entity, nil, true)
entity.destroy()
local foundPosition = surface.find_non_colliding_position(name,
position,
2,
1,
true)
setPositionInQuery(query, foundPosition or position)
local createdEntity = surface.create_entity({
name = query.name,
position = query.position
})
if createdEntity and createdEntity.valid then
if entityData.register then
registerEnemyBaseStructure(createdEntity, base, tick, true)
end
if not entityData.evolve and Universe.printBaseUpgrades then
surface.print("["..base.id.."]:"..surface.name.." Upgrading ".. entityName .. " to " .. name .. " [gps=".. position.x ..",".. position.y .."]")
if not entityData.name or not entityData.position then
Universe.pendingUpgrades[entityId] = nil
return
end
entityData.state = 3
elseif state == 3 then
Universe.pendingUpgrades[entityId] = nil
local query = Queries.createEntityQuery
local name = entityData.name
query.name = name
local position = entityData.position
setPositionInQuery(query, position)
local surface = entityData.map.surface
surface.create_entity(query)
if remote.interfaces["kr-creep"] then
remote.call("kr-creep", "spawn_creep_at_position", surface, foundPosition or position, false, createdEntity.name)
remote.call(
"kr-creep",
"spawn_creep_at_position",
surface,
position,
false,
name
)
end
end
end
@ -613,6 +627,7 @@ end
function Processor.init(universe)
Universe = universe
Queries = universe.baseUtilsQueries
end
ProcessorG = Processor

View File

@ -287,9 +287,11 @@ local function addCommandSet()
}
-- ppu
Universe.ppuUpgradeEntityQuery = {
Universe.baseUtilsQueries = {}
Universe.baseUtilsQueries.createEntityQuery = {
name = "",
position = {0,0}
position = {0,0},
raise_built = true
}
Universe.squadQueries = {}

View File

@ -75,6 +75,7 @@ acid-ball-5-acid-fire-rampant=Acid Pool
hive=Spawns enemy structures
[mod-setting-name]
rampant--legacyChunkScanning=Optimization: Scan chunks outside raised events
rampant--scaleParticleCount=Optimization: Scale blood particle count
rampant--maxBaseAlignmentHistory=World: Max Base Mutation History
rampant--enabledPurpleSettlerCloud=World: Enable Purple Cloud
@ -206,6 +207,7 @@ rampant--temperamentRateModifier=AI: Temperament Rate Modifier
rampant--enableLandfillOnDeath=World: Enemies fill water on death
[mod-setting-description]
rampant--legacyChunkScanning=Enabling this will cause Rampant to slowly scan chunks for resources, enemies, and player structures that are created or destroyed by mods that dont raise an event when creating or destroying entities.
rampant--maxBaseAlignmentHistory=The number of mutations that a base will remember. Remembered mutations cannot be mutated to again.
rampant--enableLandfillOnDeath=The body parts that are thrown off when dying will landfill water tiles. If Remove blood particles is enabled then this setting will not work.
rampant--enabledPurpleSettlerCloud=Toggle the purple cloud that spawns when a settler group starts building a nest.

View File

@ -606,6 +606,16 @@ data:extend({
per_user = false
},
{
type = "bool-setting",
name = "rampant--legacyChunkScanning",
description = "rampant--legacyChunkScanning",
setting_type = "runtime-global",
default_value = false,
order = "m[total]-c[ai]zz",
per_user = false
},
{
type = "double-setting",
name = "rampant--minimumAdaptationEvolution",