From 976b1eb1531b8e02e79ae56a17c578d6c2ed0be4 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 10 Oct 2022 14:42:51 +0200 Subject: [PATCH 01/18] don't despawn pillager, evoker and witch --- mods/ENTITIES/mobs_mc/pillager.lua | 1 + mods/ENTITIES/mobs_mc/villager_evoker.lua | 1 + mods/ENTITIES/mobs_mc/witch.lua | 1 + 3 files changed, 3 insertions(+) diff --git a/mods/ENTITIES/mobs_mc/pillager.lua b/mods/ENTITIES/mobs_mc/pillager.lua index c49644cd25..1321058b7a 100644 --- a/mods/ENTITIES/mobs_mc/pillager.lua +++ b/mods/ENTITIES/mobs_mc/pillager.lua @@ -28,6 +28,7 @@ pillager = { shoot_interval = 3, shoot_offset = 1.5, armor = {fleshy = 100}, + can_despawn = false, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, pathfinding = 1, group_attack = true, diff --git a/mods/ENTITIES/mobs_mc/villager_evoker.lua b/mods/ENTITIES/mobs_mc/villager_evoker.lua index 070fcdb2e8..b85001985a 100644 --- a/mods/ENTITIES/mobs_mc/villager_evoker.lua +++ b/mods/ENTITIES/mobs_mc/villager_evoker.lua @@ -15,6 +15,7 @@ mcl_mobs:register_mob("mobs_mc:evoker", { description = S("Evoker"), type = "monster", spawn_class = "hostile", + can_despawn = false, physical = true, pathfinding = 1, hp_min = 24, diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index 3b9e3279dc..5d835eab52 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -16,6 +16,7 @@ mcl_mobs:register_mob("mobs_mc:witch", { description = S("Witch"), type = "monster", spawn_class = "hostile", + can_despawn = false, hp_min = 26, hp_max = 26, xp_min = 5, From 83f17fd9a7845ac3bc9216ea13ef73616c088a14 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 10 Oct 2022 14:43:08 +0200 Subject: [PATCH 02/18] Cats keep their color --- mods/ENTITIES/mobs_mc/ocelot.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index 574b5e7636..c50067f5fa 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -157,6 +157,16 @@ cat.on_rightclick = function(self, clicker) end +cat.on_spawn = function(self) + if self.owner == "!witch!" then + self._texture = {"mobs_mc_cat_black.png"} + end + if not self._texture then + self._texture = cat.textures[math.random(#cat.textures)] + end + self.object:set_properties({textures = {self._texture}}) +end + mcl_mobs:register_mob("mobs_mc:cat", cat) local base_spawn_chance = 5000 From 1a380da960e59193a3aedd2307f02f9a3e0d3ff9 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 10 Oct 2022 14:49:49 +0200 Subject: [PATCH 03/18] Don't spawn pilalgers *in* the ground --- mods/MAPGEN/mcl_structures/pillager_outpost.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/MAPGEN/mcl_structures/pillager_outpost.lua b/mods/MAPGEN/mcl_structures/pillager_outpost.lua index fe1db5ce37..3b337886cb 100644 --- a/mods/MAPGEN/mcl_structures/pillager_outpost.lua +++ b/mods/MAPGEN/mcl_structures/pillager_outpost.lua @@ -69,12 +69,12 @@ mcl_structures.register_structure("pillager_outpost",{ if not peaceful then if sp and #sp > 0 then for i=1,5 do - local pos = sp[pr:next(1,#sp)] + local pos = vector.offset(sp[pr:next(1,#sp)],0,1,0) if pos then minetest.add_entity(pos,"mobs_mc:pillager") end end - local pos = sp[pr:next(1,#sp)] + local pos = vector.offset(sp[pr:next(1,#sp)],0,1,0) if pos then minetest.add_entity(pos,"mobs_mc:evoker") end From 39a0353a493866b56818aa30dec61dc33bd1223e Mon Sep 17 00:00:00 2001 From: cora Date: Fri, 7 Oct 2022 22:46:13 +0200 Subject: [PATCH 04/18] Add spawn counts per mob to /mobstats --- mods/ENTITIES/mcl_mobs/spawning.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 64ac6786df..afa4c4ad27 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -25,6 +25,7 @@ local table_remove = table.remove local pairs = pairs local dbg_spawn_attempts = 0 local dbg_spawn_succ = 0 +local dbg_spawn_counts = {} -- range for mob count local aoc_range = 136 @@ -473,6 +474,11 @@ function mcl_mobs.spawn(pos,id) if not def or (def.can_spawn and not def.can_spawn(pos)) or not def.is_mob then return false end + if not dbg_spawn_counts[def.name] then + dbg_spawn_counts[def.name] = 1 + else + dbg_spawn_counts[def.name] = dbg_spawn_counts[def.name] + 1 + end return minetest.add_entity(pos, def.name) end @@ -672,6 +678,7 @@ end minetest.register_chatcommand("mobstats",{ privs = { debug = true }, func = function(n,param) + minetest.chat_send_player(n,dump(dbg_spawn_counts)) local pos = minetest.get_player_by_name(n):get_pos() minetest.chat_send_player(n,"mobs within 32 radius of player:"..count_mobs(pos,32)) minetest.chat_send_player(n,"total mobs:"..count_mobs_total()) From cba176be4a71794ce4650e54664211db404d8b80 Mon Sep 17 00:00:00 2001 From: cora Date: Sat, 8 Oct 2022 03:56:14 +0200 Subject: [PATCH 05/18] make horny mobs move towards each other --- mods/ENTITIES/mcl_mobs/api.lua | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 186fd0473e..696aced93f 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3129,6 +3129,31 @@ local function check_item_pickup(self) end end +local check_herd_timer = 0 +local function check_herd(self,dtime) + local pos = self.object:get_pos() + if not pos then return end + check_herd_timer = check_herd_timer + dtime + if check_herd_timer < 4 then return end + check_herd_timer = 0 + for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do + local l = o:get_luaentity() + local p,y + if l and l.is_mob and l.name == self.name then + if self.horny and l.horny then + p = l.object:get_pos() + else + y = o:get_yaw() + end + if p then + go_to_pos(self,p) + elseif y then + set_yaw(self,y) + end + end + end +end + local function damage_mob(self,reason,damage) if not self.health then return end damage = floor(damage) @@ -4016,6 +4041,10 @@ local mob_step = function(self, dtime) yaw = yaw + random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end + else + if self.move_in_group ~= false then + check_herd(self,dtime) + end end -- Add water flowing for mobs from mcl_item_entity From 97f96148181a0f38b0589397597e04f12f515f5a Mon Sep 17 00:00:00 2001 From: cora Date: Tue, 11 Oct 2022 00:42:10 +0200 Subject: [PATCH 06/18] Log the node a mob spawns on --- mods/ENTITIES/mcl_mobs/spawning.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index afa4c4ad27..6c7bedd118 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -632,13 +632,13 @@ if mobs_spawn then local object if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then if logging then - minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1)) + minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1)) end object = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name},spawn_in_group,spawn_in_group_min) else if logging then - minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1)) + minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at ".. minetest.pos_to_string(spawning_position, 1)) end object = mcl_mobs.spawn(spawning_position, mob_def.name) end From effac327f551259462700364c5fcc3c653e03378 Mon Sep 17 00:00:00 2001 From: cora Date: Tue, 11 Oct 2022 11:51:26 +0200 Subject: [PATCH 07/18] Fix baby Z-pigman visual size --- mods/ENTITIES/mobs_mc/zombiepig.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 05e4d8577c..4d6b05310f 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -103,7 +103,6 @@ baby_pigman.description = S("Baby Zombie Pigman") baby_pigman.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25} baby_pigman.xp_min = 13 baby_pigman.xp_max = 13 -baby_pigman.visual_size = {x=pigman.visual_size.x/2, y=pigman.visual_size.y/2} baby_pigman.textures = { { "mobs_mc_zombie_pigman.png", --baby "default_tool_goldsword.png", --sword From 5db7680cd131c0aed05b0ca11e4ae86b19f406e6 Mon Sep 17 00:00:00 2001 From: cora Date: Wed, 12 Oct 2022 16:30:03 +0200 Subject: [PATCH 08/18] mitigate high cpu usage due to excessive mob counting This was caused by the mob caps being checked too frequently --- mods/ENTITIES/mcl_mobs/spawning.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 6c7bedd118..4c89397f1d 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -419,7 +419,7 @@ local function get_water_spawn(p) end end -local function spawn_check(pos,spawn_def) +local function spawn_check(pos,spawn_def,ignore_caps) if not spawn_def then return end dbg_spawn_attempts = dbg_spawn_attempts + 1 local dimension = mcl_worlds.pos_to_dimension(pos) @@ -442,12 +442,17 @@ local function spawn_check(pos,spawn_def) local is_leaf = get_item_group(gotten_node, "leaves") ~= 0 local is_bedrock = gotten_node == "mcl_core:bedrock" local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0 - local mob_count_wide = count_mobs(pos,aoc_range,mob_type) - local mob_count = count_mobs(pos,32,mob_type) + local mob_count_wide = 0 + + local mob_count = 0 + if not ignore_caps then + mob_count = count_mobs(pos,32,mob_type) + mob_count_wide = count_mobs(pos,aoc_range,mob_type) + end if pos and spawn_def - and mob_count_wide < (mob_cap[mob_type] or 15) - and mob_count < 5 + and ( mob_count_wide < (mob_cap[mob_type] or 15) ) + and ( mob_count < 5 ) and pos.y >= spawn_def.min_height and pos.y <= spawn_def.max_height and spawn_def.dimension == dimension @@ -494,7 +499,7 @@ local function spawn_group(p,mob,spawn_on,group_max,group_min) end for i = 1, math.random(group_min,group_max) do local sp = vector.offset(nn[math.random(#nn)],0,1,0) - if spawn_check(nn[math.random(#nn)],mob) then + if spawn_check(nn[math.random(#nn)],mob,true) then if mob.type_of_spawning == "water" then sp = get_water_spawn(sp) end From 546b9ade6f7f77b198b3694df00ab374325ab885 Mon Sep 17 00:00:00 2001 From: cora Date: Wed, 12 Oct 2022 18:22:37 +0200 Subject: [PATCH 09/18] Make mobs outside of player radius stop moving --- mods/ENTITIES/mcl_mobs/api.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 696aced93f..5d7940f3df 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -204,6 +204,13 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement end end +local function player_in_active_range(self) + for _,p in pairs(minetest.get_connected_players()) do + if vector.distance(self.object:get_pos(),p:get_pos()) <= 38 then return true end + -- slightly larger than the mc 32 since mobs spawn on that circle and easily stand still immediately right after spawning. + end +end + -- play sound local mob_sound = function(self, soundname, is_opinion, fixed_pitch) @@ -3819,6 +3826,11 @@ end -- main mob function local mob_step = function(self, dtime) self.lifetimer = self.lifetimer - dtime + if not player_in_active_range(self) then + set_animation(self, "stand", true) + self.object:set_velocity(vector.new(0,0,0)) + return + end check_item_pickup(self) check_aggro(self,dtime) particlespawner_check(self,dtime) From ba25e57eac01be710324d324c79772f2b3b847ca Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 06:06:14 +0200 Subject: [PATCH 10/18] don't run on_spawn twice --- mods/ENTITIES/mcl_mobs/spawning.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 4c89397f1d..7a6ff7396e 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -647,11 +647,6 @@ if mobs_spawn then end object = mcl_mobs.spawn(spawning_position, mob_def.name) end - - - if object then - return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position) - end end current_summary_chance = current_summary_chance - mob_chance table_remove(mob_library_worker_table, mob_index) From cd862888d1a9c99d436c2890e2d263df89be38e1 Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 06:26:51 +0200 Subject: [PATCH 11/18] Fix indentation --- mods/ENTITIES/mcl_mobs/spawning.lua | 43 +++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 7a6ff7396e..ac30614cca 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -620,33 +620,36 @@ if mobs_spawn then step_chance = step_chance + mob_chance end local mob_def = mob_library_worker_table[mob_index] + --minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance) local spawn_in_group = minetest.registered_entities[mob_def.name].spawn_in_group or 4 local spawn_in_group_min = minetest.registered_entities[mob_def.name].spawn_in_group_min or 1 local mob_type = minetest.registered_entities[mob_def.name].type if spawn_check(spawning_position,mob_def) then - if mob_def.type_of_spawning == "water" then - spawning_position = get_water_spawn(spawning_position) - if not spawning_position then - return - end - end - if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(pos) then + if mob_def.type_of_spawning == "water" then + spawning_position = get_water_spawn(spawning_position) + if not spawning_position then + minetest.log("return") return end - --everything is correct, spawn mob - local object - if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then - if logging then - minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1)) - end - object = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name},spawn_in_group,spawn_in_group_min) - - else - if logging then - minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at ".. minetest.pos_to_string(spawning_position, 1)) - end - object = mcl_mobs.spawn(spawning_position, mob_def.name) + end + if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(pos) then + minetest.log("return") + return + end + --everything is correct, spawn mob + local object + if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then + if logging then + minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1)) end + object = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name},spawn_in_group,spawn_in_group_min) + + else + if logging then + minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at ".. minetest.pos_to_string(spawning_position, 1)) + end + object = mcl_mobs.spawn(spawning_position, mob_def.name) + end end current_summary_chance = current_summary_chance - mob_chance table_remove(mob_library_worker_table, mob_index) From ea48be3f4cf3822862e9a8f802e3986857241d64 Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 06:27:04 +0200 Subject: [PATCH 12/18] Add global and per-player mob caps --- mods/ENTITIES/mcl_mobs/spawning.lua | 20 ++++++++++++++------ mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 2 ++ settingtypes.txt | 6 ++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index ac30614cca..fdafb0348d 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -30,11 +30,13 @@ local dbg_spawn_counts = {} local aoc_range = 136 local mob_cap = { - monster = minetest.settings:get_bool("mcl_mob_cap_monster") or 70, - animal = minetest.settings:get_bool("mcl_mob_cap_animal") or 10, - ambient = minetest.settings:get_bool("mcl_mob_cap_ambient") or 15, - water = minetest.settings:get_bool("mcl_mob_cap_water") or 5, --currently unused - water_ambient = minetest.settings:get_bool("mcl_mob_cap_water_ambient") or 20, --currently unused + monster = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70, + animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10, + ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, + water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 5, --currently unused + water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --currently unused + player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75, + total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500, } --do mobs spawn? @@ -664,7 +666,13 @@ if mobs_spawn then timer = timer + dtime if timer < 10 then return end timer = 0 - for _, player in pairs(get_connected_players()) do + local players = get_connected_players() + local total_mobs = count_mobs_total() + if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then + minetest.log("warning","[mcl_mobs] mob cap reached. no cycle spawning.") + return + end --mob cap per player + for _, player in pairs(players) do local pos = player:get_pos() local dimension = mcl_worlds.pos_to_dimension(pos) -- ignore void and unloaded area diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index f1d1da46eb..eebe16f98b 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -11,6 +11,8 @@ local cow_def = { xp_min = 1, xp_max = 3, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45}, + spawn_in_group = 8, + spawn_in_group_min = 3, visual = "mesh", mesh = "mobs_mc_cow.b3d", textures = { { diff --git a/settingtypes.txt b/settingtypes.txt index 0265778b6d..97464d79ce 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -99,6 +99,12 @@ mobs_griefing (Mobs change blocks) bool true # If enabled, mobs won't damage particles when they got hurt. mobs_disable_blood (Disable mob damage particles) bool false +#Maximum amount mobs (default:500) +mcl_mob_cap_total (Global mob cap) int 500 0 2048 + +#Maximum amount of mobs per player (default:75) +mcl_mob_cap_player (Mob cap per player) int 75 0 2048 + #Maximum amount of monsters that will spawn near a player (default:70) mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048 From c146124a2c41284f61ae0202f09cb0ff151dd63c Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 21:13:21 +0200 Subject: [PATCH 13/18] spawning: check for room accrd. to collisionbox --- mods/ENTITIES/mcl_mobs/spawning.lua | 37 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index fdafb0348d..215ee7bb1a 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -1,4 +1,5 @@ --lua locals +local minetest,vector,math,table = minetest,vector,math,table local get_node = minetest.get_node local get_item_group = minetest.get_item_group local get_node_light = minetest.get_node_light @@ -421,11 +422,38 @@ local function get_water_spawn(p) end end +local function has_room(self,pos) + local cb = self.collisionbox + local nodes = {} + if self.fly_in then + local t = type(self.fly_in) + if t == "table" then + nodes = table.copy(self.fly_in) + elseif t == "string" then + table.insert(nodes,self.fly_in) + end + end + table.insert(nodes,"air") + local x = cb[4] - cb[1] + local y = cb[5] - cb[2] + local z = cb[6] - cb[3] + local r = math.ceil(x * y * z) + local p1 = vector.offset(pos,cb[1],cb[2],cb[3]) + local p2 = vector.offset(pos,cb[4],cb[5],cb[6]) + local n = #minetest.find_nodes_in_area(p1,p2,nodes) or 0 + if r > n then + minetest.log("no room for mob "..self.name) + return false + end + return true +end + local function spawn_check(pos,spawn_def,ignore_caps) if not spawn_def then return end dbg_spawn_attempts = dbg_spawn_attempts + 1 local dimension = mcl_worlds.pos_to_dimension(pos) - local mob_type = minetest.registered_entities[spawn_def.name].type + local mob_def = minetest.registered_entities[spawn_def.name] + local mob_type = mob_def.type local gotten_node = get_node(pos).name local gotten_biome = minetest.get_biome_data(pos) if not gotten_node or not gotten_biome then return end @@ -438,7 +466,6 @@ local function spawn_check(pos,spawn_def,ignore_caps) is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0 end pos.y = pos.y + 1 - local has_room = #minetest.find_nodes_in_area(pos,vector.offset(pos,0,1,0),{"air"}) or 0 >= 2 local is_water = get_item_group(gotten_node, "water") ~= 0 local is_lava = get_item_group(gotten_node, "lava") ~= 0 local is_leaf = get_item_group(gotten_node, "leaves") ~= 0 @@ -461,7 +488,7 @@ local function spawn_check(pos,spawn_def,ignore_caps) and biome_check(spawn_def.biomes, gotten_biome) and (is_ground or spawn_def.type_of_spawning ~= "ground") and (spawn_def.type_of_spawning ~= "ground" or not is_leaf) - and (spawn_def.type_of_spawning ~= "ground" or has_room) + and has_room(mob_def,pos) and (spawn_def.check_position and spawn_def.check_position(pos) or true) and (not is_farm_animal(spawn_def.name) or is_grass) and (spawn_def.type_of_spawning ~= "water" or is_water) @@ -630,12 +657,12 @@ if mobs_spawn then if mob_def.type_of_spawning == "water" then spawning_position = get_water_spawn(spawning_position) if not spawning_position then - minetest.log("return") + minetest.log("warning","[mcl_mobs] no water spawn for mob "..mob_def.name.." found at "..minetest.pos_to_string(vector.round(pos))) return end end if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(pos) then - minetest.log("return") + minetest.log("warning","[mcl_mobs] mob "..mob_def.name.." refused to spawn at "..minetest.pos_to_string(vector.round(pos))) return end --everything is correct, spawn mob From 976b9da7d7486c2220b92ffb8660352b0c7f323c Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 21:14:18 +0200 Subject: [PATCH 14/18] Despawn out of range mobs when immobile --- mods/ENTITIES/mcl_mobs/api.lua | 49 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 5d7940f3df..fbf65b3336 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3602,7 +3602,7 @@ local mob_staticdata = function(self) and ((not self.nametag) or (self.nametag == "")) and self.lifetimer <= 20 then if spawn_logging then - minetest.log("action", "[mcl_mobs] Mob "..tostring(self.name).." despawns in mob_staticdata at "..minetest.pos_to_string(vector.round(self.object:get_pos()))) + minetest.log("action", "[mcl_mobs] Mob "..tostring(self.name).." despawns at "..minetest.pos_to_string(vector.round(self.object:get_pos())) .. " - out of range") end return "remove"-- nil @@ -3826,6 +3826,30 @@ end -- main mob function local mob_step = function(self, dtime) self.lifetimer = self.lifetimer - dtime + + local pos = self.object:get_pos() + -- Despawning: when lifetimer expires, remove mob + if remove_far + and self.can_despawn == true + and ((not self.nametag) or (self.nametag == "")) + and self.state ~= "attack" + and self.following == nil then + if self.despawn_immediately or self.lifetimer <= 0 then + if spawn_logging then + minetest.log("action", "[mcl_mobs] Mob "..self.name.." despawns at "..minetest.pos_to_string(pos, 1) .. " lifetimer ran out") + end + mcl_burning.extinguish(self.object) + self.object:remove() + return + elseif self.lifetimer <= 10 then + if random(10) < 4 then + self.despawn_immediately = true + else + self.lifetimer = 20 + end + end + end + if not player_in_active_range(self) then set_animation(self, "stand", true) self.object:set_velocity(vector.new(0,0,0)) @@ -3840,7 +3864,6 @@ local mob_step = function(self, dtime) if not self.object:get_pos() then return end end - local pos = self.object:get_pos() local yaw = 0 if mobs_debug then @@ -4105,28 +4128,6 @@ local mob_step = function(self, dtime) local yaw = self.object:get_yaw() or 0 yaw = set_yaw(self, yaw + 0.78, 8) end - - -- Despawning: when lifetimer expires, remove mob - if remove_far - and self.can_despawn == true - and ((not self.nametag) or (self.nametag == "")) - and self.state ~= "attack" - and self.following == nil then - if self.despawn_immediately or self.lifetimer <= 0 then - if spawn_logging then - minetest.log("action", "[mcl_mobs] Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1)) - end - mcl_burning.extinguish(self.object) - self.object:remove() - return - elseif self.lifetimer <= 10 then - if random(10) < 4 then - self.despawn_immediately = true - else - self.lifetimer = 20 - end - end - end end From 93f8f2aa3b1acda10c4c7ce19cb234361b01f4de Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 21:14:44 +0200 Subject: [PATCH 15/18] only count despawnable mobs for global caps --- mods/ENTITIES/mcl_mobs/spawning.lua | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 215ee7bb1a..b3200db59f 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -241,6 +241,17 @@ local function count_mobs_total(mob_type) return num end +local function count_mobs_total_cap(mob_type) + local num = 0 + for _,l in pairs(minetest.luaentities) do + if l.is_mob then + if ( mob_type == nil or l.type == mob_type ) and l.can_despawn and not l.nametag then + num = num + 1 + end + end + end + return num +end -- global functions @@ -694,9 +705,9 @@ if mobs_spawn then if timer < 10 then return end timer = 0 local players = get_connected_players() - local total_mobs = count_mobs_total() + local total_mobs = count_mobs_total_cap() if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then - minetest.log("warning","[mcl_mobs] mob cap reached. no cycle spawning.") + minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.") return end --mob cap per player for _, player in pairs(players) do From c044cf8e74b4f6912d5fdb57d4ba263b7040b9ca Mon Sep 17 00:00:00 2001 From: cora Date: Thu, 13 Oct 2022 21:48:32 +0200 Subject: [PATCH 16/18] Fix debug line --- mods/ENTITIES/mcl_mobs/api.lua | 2 +- mods/ENTITIES/mcl_mobs/spawning.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index fbf65b3336..9e6f5a63d2 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1382,10 +1382,10 @@ end -- jump if facing a solid node (not fences or gates) local do_jump = function(self) - if not self.jump or self.jump_height == 0 or self.fly + or self.fly_in or (self.child and self.type ~= "monster") or self.order == "stand" then return false diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index b3200db59f..371407c4ee 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -453,7 +453,7 @@ local function has_room(self,pos) local p2 = vector.offset(pos,cb[4],cb[5],cb[6]) local n = #minetest.find_nodes_in_area(p1,p2,nodes) or 0 if r > n then - minetest.log("no room for mob "..self.name) + minetest.log("warning","[mcl_mobs] No room for mob "..self.name.." at "..minetest.pos_to_string(vector.round(pos))) return false end return true From c855f518291a129ebb55e35de95eb85982bf3808 Mon Sep 17 00:00:00 2001 From: cora Date: Fri, 14 Oct 2022 02:40:25 +0200 Subject: [PATCH 17/18] fix mobs not jumping anymore --- mods/ENTITIES/mcl_mobs/api.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 9e6f5a63d2..4e559ed07d 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1385,7 +1385,6 @@ local do_jump = function(self) if not self.jump or self.jump_height == 0 or self.fly - or self.fly_in or (self.child and self.type ~= "monster") or self.order == "stand" then return false From d90b3c046ab1c8e73355c62dcd5d196e4cac7d48 Mon Sep 17 00:00:00 2001 From: cora Date: Fri, 14 Oct 2022 02:44:23 +0200 Subject: [PATCH 18/18] give mobs a slightly heigher jump height so they don't need 2 tries to jump on a node --- mods/ENTITIES/mcl_mobs/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 4e559ed07d..a17e7466d3 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1449,7 +1449,7 @@ local do_jump = function(self) local v = self.object:get_velocity() - v.y = self.jump_height + v.y = self.jump_height + 0.1 set_animation(self, "jump") -- only when defined