From 4d65ac72af32a59054d5fa95c29b274c5afee690 Mon Sep 17 00:00:00 2001 From: sapier Date: Tue, 19 Aug 2014 19:25:18 +0200 Subject: [PATCH] Fix broken spawner initialization Add support for regenerating lost spawners (only around players) --- README.txt | 14 ++++++++ api.lua | 3 ++ init.lua | 2 +- internal.lua | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ spawn_seed.lua | 33 ++++++++++++++++--- 5 files changed, 136 insertions(+), 5 deletions(-) diff --git a/README.txt b/README.txt index e470f4a..5b14caa 100644 --- a/README.txt +++ b/README.txt @@ -189,8 +189,22 @@ Statistics: } } +Settings: + adv_spawning_validate_spawners = false + ^ make advanced_spawning check area around active players for lost spawner seeds + Changelog: +0.0.9 + -Fix broken spawner initialization + -Add support for regenerating spawner seeds (only around active players) + set >>adv_spawning_validate_spawners<< to true if you want advanced spawning + to do this. + Note: this might need some additional cpu time + +0.0.8 + -Fix large steps caused by uninterruptable spawn seed initialization within activation + 0.0.7 -handle time steps backward without assertion diff --git a/api.lua b/api.lua index a9f6d5d..298d742 100644 --- a/api.lua +++ b/api.lua @@ -26,6 +26,9 @@ function adv_spawning.register(spawner_name,spawning_def) adv_spawning.spawner_definitions[spawner_name] = spawning_def adv_spawning.dbg_log(0, "registering spawner \"" .. spawner_name .. "\"") + adv_spawning.dbg_log(0, "now handling: " .. + adv_spawning.table_count(adv_spawning.spawner_definitions) .. + " spawner definitions") return true else return false diff --git a/init.lua b/init.lua index e136f82..83b2f79 100644 --- a/init.lua +++ b/init.lua @@ -8,7 +8,7 @@ -- ------------------------------------------------------------------------------- -local version = "0.0.8" +local version = "0.0.9" if adv_spawning ~= nil then core.log("error", "MOD: adv_spawning requires adv_spawning variable to be available") diff --git a/internal.lua b/internal.lua index a493d33..abf8387 100644 --- a/internal.lua +++ b/internal.lua @@ -65,6 +65,8 @@ function adv_spawning.initialize() adv_spawning.max_mapgen_tries_per_step = 3 adv_spawning.spawner_warned = {} adv_spawning.loglevel = 0 + adv_spawning.spawner_validation_delta = 0 + adv_spawning.spawner_validation_interval = 30 adv_spawning.active_range = minetest.setting_get("active_block_range") @@ -216,6 +218,32 @@ function adv_spawning.global_onstep(dtime) (adv_spawning.statistics.session.steps-1)) + adv_spawning.statistics.load.cur) / adv_spawning.statistics.session.steps + + if core.is_yes( + core.setting_get("adv_spawning_validate_spawners")) then + + adv_spawning.spawner_validation_delta = + adv_spawning.spawner_validation_delta + dtime + + if adv_spawning.spawner_validation_delta > + adv_spawning.spawner_validation_interval then + + if adv_spawning.quota_enter() then + local playerlist = core.get_connected_players() + + for k,v in ipairs(playerlist) do + if not adv_spawning.time_over(10) then + adv_spawning.refresh_spawners(v:getpos()) + else + break + end + end + + adv_spawning.spawner_validation_delta = 0 + + end + end + end --reduce following quota by overtime from last step if adv_spawning.quota_left < 0 then @@ -1491,4 +1519,65 @@ function adv_spawning.dbg_log(loglevel, message) if (adv_spawning.loglevel >= loglevel ) then core.log("action", "ADV_SPAWNING: " .. message) end +end + + +-------------------------------------------------------------------------------- +-- @function [parent=#adv_spawning] refresh_spawners +-- @param pos to refresh spawners around +-------------------------------------------------------------------------------- +function adv_spawning.refresh_spawners(pos) + + local min = {x=pos.x-32, y=pos.y-32, z=pos.z-32} + local max = {x=pos.x+32, y=pos.y+32, z=pos.z+32} + + core.log("action", "Checking spawners from: " .. core.pos_to_string(min) .. + " to " .. core.pos_to_string(max)) + + local start_x = + math.floor(min.x/adv_spawning.spawner_distance) + * adv_spawning.spawner_distance + local start_y = + (math.floor(min.y/adv_spawning.spawner_distance) + * adv_spawning.spawner_distance) + + adv_spawning.spawner_y_offset + local start_z = + math.floor(min.z/adv_spawning.spawner_distance) + * adv_spawning.spawner_distance + + for x=start_x,max.x,adv_spawning.spawner_distance do + for y=start_y,max.y,adv_spawning.spawner_distance do + for z=start_z,max.z,adv_spawning.spawner_distance do + + core.log("action", "Checking: (" .. x .. "," .. y .. "," .. z .. ")") + if x > min.x and + y > min.y and + z > min.z then + if not adv_spawning.quota_leave() then + adv_spawning.dbg_log(2, + "adv_spawning: refresh_spawners did use way too much time 1") + end + minetest.add_entity({x=x,y=y,z=z},"adv_spawning:spawn_seed") + adv_spawning.quota_enter(true) + adv_spawning.log("info", "adv_spawning: adding spawner entity at " + .. core.pos_to_string({x=x,y=y,z=z})) + adv_spawning.statistics.session.spawners_created = + adv_spawning.statistics.session.spawners_created +1 + end + end + end + end +end + +-------------------------------------------------------------------------------- +-- @function [parent=#adv_spawning] table_count +-- @param tocount table to get number of elements from +-------------------------------------------------------------------------------- +function adv_spawning.table_count(tocount) + local retval = 0 + for k,v in pairs(tocount) do + retval = retval +1 + end + + return retval end \ No newline at end of file diff --git a/spawn_seed.lua b/spawn_seed.lua index cd79ac4..34923a9 100644 --- a/spawn_seed.lua +++ b/spawn_seed.lua @@ -35,6 +35,7 @@ function adv_spawning.seed_step(self,dtime) self.pending_spawners = {} adv_spawning.seed_countdown_spawners(self,self.mydtime) + self.mydtime = 0 --check quota again @@ -48,7 +49,7 @@ function adv_spawning.seed_step(self,dtime) while #self.pending_spawners > 0 and per_step_count < adv_spawning.max_spawns_per_spawner and - adv_spawning.time_over(10) do + (not adv_spawning.time_over(10)) do local rand_spawner = math.random(1,#self.pending_spawners) key = self.pending_spawners[rand_spawner] @@ -132,7 +133,9 @@ end -------------------------------------------------------------------------------- function adv_spawning.on_rightclick(self, clicker) if adv_spawning.debug then - print("ADV_SPAWNING: Spawner may spawn following mobs:") + print("ADV_SPAWNING: time till next spawn: " .. self.mydtime) + print("ADV_SPAWNING: pending spawners: " .. #self.pending_spawners) + print("ADV_SPAWNING: Spawner may spawn " .. adv_spawning.table_count(self.spawning_data) .. " mobs:") local index = 1 for key,value in pairs(self.spawning_data) do print(string.format("%3d:",index) .. string.format("%30s ",key) .. string.format("%3d s", value)) @@ -165,6 +168,7 @@ function adv_spawning.seed_initialize() self.activated = false self.mydtime = dtime_s self.serialized_data = staticdata + self.object:set_armor_groups({ immortal=100 }) adv_spawning.seed_activate(self) end, on_step = adv_spawning.seed_step, @@ -210,7 +214,27 @@ end -- @return true/false -------------------------------------------------------------------------------- function adv_spawning.seed_check_for_collision(self) - --TODO check if there already is another spawner at exactly this position + assert(self ~= nil) + local pos = self.object:getpos() + local objects = minetest.get_objects_inside_radius(pos, 0.5) + + if objects == nil then + return false + end + + -- check if any of those found objects is a spawning seed + for k,v in ipairs(objects) do + local entity = v:get_luaentity() + + if entity ~= nil then + if entity.name == "adv_spawning:spawn_seed" and + entity.object ~= self.object then + self.object:remove() + return true + end + end + end + return false end @@ -221,7 +245,8 @@ end -------------------------------------------------------------------------------- function adv_spawning.seed_scan_for_applyable_spawners(self) - if self.initialized_spawners >= #adv_spawning.spawner_definitions then + if self.initialized_spawners >= + adv_spawning.table_count(adv_spawning.spawner_definitions) then return true end