Compare commits

..

20 Commits

Author SHA1 Message Date
ancientmarinerdev 00bd3cc835 Default setting fix 2023-01-31 18:24:47 +00:00
ancientmarinerdev 71c236646f Limit spawning of mobs outside y axis as well 2023-01-31 18:13:36 +00:00
ancientmarinerdev a8716c802f Improve balancing for early game 2023-01-31 18:04:01 +00:00
ancientmarinerdev 0ff2f66304 Add settings for percentage of hostile and peaceful groups spawned 2023-01-31 15:55:11 +00:00
ancientmarinerdev abefab73b6 Add world gen limits to spawning to avoid things spawning past the world gen limits 2023-01-30 23:10:37 +00:00
ancientmarinerdev 8f52a42c1f Limit peaceful spawning and add configurable option 2023-01-30 01:31:58 +00:00
ancientmarinerdev 5ba531755a Change spawn cap groups to spawn_type to give water it's own spawn cap. 2023-01-28 23:48:48 +00:00
ancientmarinerdev 61f44a85c5 Clean up 2023-01-28 02:31:41 +00:00
ancientmarinerdev 040f7054a1 Nerf group spawning until group spawn is based on pack size, not per spawn attempt 2023-01-28 00:44:48 +00:00
ancientmarinerdev 92ab24b0cf Add logging 2023-01-28 00:24:33 +00:00
ancientmarinerdev 51bd783e61 Retry if failing to find spawn position 2023-01-28 00:14:08 +00:00
ancientmarinerdev f99c7d7ef6 Mobs now can spawn in multiple positions around you per spawning cycle 2023-01-27 04:08:38 +00:00
ancientmarinerdev da7344e2dc Restructure code and tidy 2023-01-27 03:50:00 +00:00
ancientmarinerdev 814236fc3a Clean logging etc. 2023-01-27 02:47:01 +00:00
ancientmarinerdev 12b9b5cbce Clean up 2023-01-26 16:44:25 +00:00
ancientmarinerdev 11953e0575 Decrease change of groups spawning for peacefuls. Refresh total mobs check on spawn. 2023-01-26 15:42:27 +00:00
ancientmarinerdev 5b8bc87452 Fix mobs debug crash 2023-01-26 15:25:59 +00:00
ancientmarinerdev 3153d14523 Move cap check out of spawn checks and reimplement close cap check 2023-01-26 15:20:38 +00:00
ancientmarinerdev 976be51a3b Add in constants for spawn zones 2023-01-26 13:44:29 +00:00
ancientmarinerdev 2fc69ce3c5 Limit group spawn to available cap space. Total mobs check once per spawn cycle. 2023-01-26 03:57:36 +00:00
20 changed files with 633 additions and 348 deletions

View File

@ -204,7 +204,7 @@ end
-- Checks if the given node would drop its useful drop if dug by a given tool. -- Checks if the given node would drop its useful drop if dug by a given tool.
-- Returns true if it will yield its useful drop, false otherwise. -- Returns true if it will yield its useful drop, false otherwise.
function mcl_autogroup.can_harvest(nodename, toolname, player) function mcl_autogroup.can_harvest(nodename, toolname)
local ndef = minetest.registered_nodes[nodename] local ndef = minetest.registered_nodes[nodename]
if not ndef then if not ndef then
@ -228,9 +228,7 @@ function mcl_autogroup.can_harvest(nodename, toolname, player)
end end
-- Check if it can be dug by hand -- Check if it can be dug by hand
if not player or not player:is_player() then return false end local tdef = minetest.registered_tools[""]
local name = player:get_inventory():get_stack("hand", 1):get_name()
local tdef = minetest.registered_items[name]
if tdef then if tdef then
for g, gdef in pairs(tdef._mcl_diggroups) do for g, gdef in pairs(tdef._mcl_diggroups) do
if ndef.groups[g] then if ndef.groups[g] then
@ -262,7 +260,7 @@ local function get_tool_capabilities(tdef)
-- If the damage group and punch interval from hand is not included, -- If the damage group and punch interval from hand is not included,
-- then the user will not be able to attack with the tool. -- then the user will not be able to attack with the tool.
local hand_toolcaps = mcl_meshhand.survival_hand_tool_caps local hand_toolcaps = minetest.registered_tools[""].tool_capabilities
return { return {
full_punch_interval = hand_toolcaps.full_punch_interval, full_punch_interval = hand_toolcaps.full_punch_interval,
damage_groups = hand_toolcaps.damage_groups damage_groups = hand_toolcaps.damage_groups
@ -282,7 +280,7 @@ end
-- would have to add _mcl_autogroup as a dependency which would break the mod -- would have to add _mcl_autogroup as a dependency which would break the mod
-- loading order. -- loading order.
function mcl_autogroup.get_groupcaps(toolname, efficiency) function mcl_autogroup.get_groupcaps(toolname, efficiency)
local tdef = minetest.registered_items[toolname] local tdef = minetest.registered_tools[toolname]
local groupcaps = table.copy(get_tool_capabilities(tdef).groupcaps or {}) local groupcaps = table.copy(get_tool_capabilities(tdef).groupcaps or {})
add_groupcaps(toolname, groupcaps, tdef._mcl_diggroups, efficiency) add_groupcaps(toolname, groupcaps, tdef._mcl_diggroups, efficiency)
return groupcaps return groupcaps
@ -352,7 +350,7 @@ local function overwrite()
end end
end end
for tname, tdef in pairs(minetest.registered_items) do for tname, tdef in pairs(minetest.registered_tools) do
-- Assign groupcaps for digging the registered digging groups -- Assign groupcaps for digging the registered digging groups
-- depending on the _mcl_diggroups in the tool definition -- depending on the _mcl_diggroups in the tool definition
if tdef._mcl_diggroups then if tdef._mcl_diggroups then
@ -362,12 +360,6 @@ local function overwrite()
minetest.override_item(tname, { minetest.override_item(tname, {
tool_capabilities = toolcaps tool_capabilities = toolcaps
}) })
else
-- This is needed to deal damage when punching mobs
-- with random items in hand in survival mode
minetest.override_item(tname, {
tool_capabilities = mcl_meshhand.survival_hand_tool_caps
})
end end
end end
end end

View File

@ -1,11 +1,10 @@
# mcl_autogroup # mcl_autogroup
This mod emulate digging times from mc. This mod emulate digging times from mc.
## mcl_autogroup.can_harvest(nodename, toolname, player) ## mcl_autogroup.can_harvest(nodename, toolname)
Return true if <nodename> can be dig with <toolname> by <player>. Return true if <nodename> can be dig with <toolname>.
* nodename: string, valid nodename * nodename: string, valid nodename
* toolname: (optional) string, valid toolname * toolname: (optional) string, valid toolname
* player: (optinal) ObjectRef, valid player
## mcl_autogroup.get_groupcaps(toolname, efficiency) ## mcl_autogroup.get_groupcaps(toolname, efficiency)
This function is used to calculate diggroups for tools. This function is used to calculate diggroups for tools.

View File

@ -252,17 +252,10 @@ function minetest.handle_node_drops(pos, drops, digger)
-- NOTE: This function override allows digger to be nil. -- NOTE: This function override allows digger to be nil.
-- This means there is no digger. This is a special case which allows this function to be called -- This means there is no digger. This is a special case which allows this function to be called
-- by hand. Creative Mode is intentionally ignored in this case. -- by hand. Creative Mode is intentionally ignored in this case.
if digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name()) then
local inv = digger:get_inventory() if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
if inv then
for _, item in ipairs(drops) do
if not inv:contains_item("main", item, true) then
inv:add_item("main", item)
end
end
end
return return
elseif not doTileDrops then return end end
-- Check if node will yield its useful drop by the digger's tool -- Check if node will yield its useful drop by the digger's tool
local dug_node = minetest.get_node(pos) local dug_node = minetest.get_node(pos)
@ -270,9 +263,9 @@ function minetest.handle_node_drops(pos, drops, digger)
local tool local tool
if digger then if digger then
tool = digger:get_wielded_item() tool = digger:get_wielded_item()
tooldef = minetest.registered_items[tool:get_name()] tooldef = minetest.registered_tools[tool:get_name()]
if not mcl_autogroup.can_harvest(dug_node.name, tool:get_name(), digger) then if not mcl_autogroup.can_harvest(dug_node.name, tool:get_name()) then
return return
end end
end end

View File

@ -24,11 +24,6 @@ local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= fa
local mobs_debug = minetest.settings:get_bool("mobs_debug", false) -- Shows helpful debug info above each mob local mobs_debug = minetest.settings:get_bool("mobs_debug", false) -- Shows helpful debug info above each mob
local spawn_logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true) local spawn_logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
local MAPGEN_LIMIT = mcl_vars.mapgen_limit
local MAPGEN_MOB_LIMIT = MAPGEN_LIMIT - 90
-- 30927 seems to be the edge of the world, so could be closer, but this is safer
-- Peaceful mode message so players will know there are no monsters -- Peaceful mode message so players will know there are no monsters
if minetest.settings:get_bool("only_peaceful_mobs", false) then if minetest.settings:get_bool("only_peaceful_mobs", false) then
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
@ -333,37 +328,12 @@ local function update_timers (self, dtime)
end end
end end
function mob_class:outside_limits()
local pos = self.object:get_pos()
if pos then
local posx = math.abs(pos.x)
local posy = math.abs(pos.y)
local posz = math.abs(pos.z)
if posx > MAPGEN_MOB_LIMIT or posy > MAPGEN_MOB_LIMIT or posz > MAPGEN_MOB_LIMIT then
--minetest.log("action", "Getting close to limits of worldgen: " .. minetest.pos_to_string(pos))
if posx > MAPGEN_LIMIT or posy > MAPGEN_LIMIT or posz > MAPGEN_LIMIT then
minetest.log("action", "Warning mob past limits of worldgen: " .. minetest.pos_to_string(pos))
else
if self.state ~= "stand" then
minetest.log("action", "Warning mob close to limits of worldgen: " .. minetest.pos_to_string(pos))
self.state = "stand"
self:set_animation("stand")
self.object:set_acceleration(vector.zero())
self.object:set_velocity(vector.zero())
end
end
return true
end
end
end
-- main mob function -- main mob function
function mob_class:on_step(dtime) function mob_class:on_step(dtime)
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not pos then return end if not pos then return end
if self:check_despawn(pos, dtime) then return true end if self:check_despawn(pos, dtime) then return true end
if self:outside_limits() then return end
if self:check_death_and_slow_mob() then if self:check_death_and_slow_mob() then
--minetest.log("action", "Mob is dying: ".. tostring(self.name)) --minetest.log("action", "Mob is dying: ".. tostring(self.name))

View File

@ -24,25 +24,59 @@ local vector_floor = vector.floor
local table_copy = table.copy local table_copy = table.copy
local table_remove = table.remove local table_remove = table.remove
local pairs = pairs local pairs = pairs
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_spawning", false)
local function mcl_log (message)
if LOGGING_ON then
mcl_util.mcl_log (message, "[Mobs spawn]", true)
end
end
local dbg_spawn_attempts = 0 local dbg_spawn_attempts = 0
local dbg_spawn_succ = 0 local dbg_spawn_succ = 0
local dbg_spawn_counts = {} local dbg_spawn_counts = {}
-- range for mob count
local aoc_range = 136
local remove_far = true local remove_far = true
local WAIT_FOR_SPAWN_ATTEMPT = 10
local FIND_SPAWN_POS_RETRIES = 10
local MOB_SPAWN_ZONE_INNER = 24
local MOB_SPAWN_ZONE_MIDDLE = 32
local MOB_SPAWN_ZONE_OUTER = 128
-- range for mob count
local MOB_CAP_INNER_RADIUS = 32
local aoc_range = 136
local MISSING_CAP_DEFAULT = 15
local MOBS_CAP_CLOSE = 5
local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150
local mob_cap = { local mob_cap = {
monster = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70, hostile = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70,
animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10, passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13,
ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, 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 = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8,
water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --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, player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75,
total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500, total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500,
} }
local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 35
local peaceful_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_group_percentage_spawned")) or 15
local hostile_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_hostile_group_percentage_spawned")) or 20
mcl_log("Mob cap hostile: " .. mob_cap.hostile)
mcl_log("Mob cap water: " .. mob_cap.water)
mcl_log("Mob cap passive: " .. mob_cap.passive)
mcl_log("Percentage of peacefuls spawned: " .. peaceful_percentage_spawned)
mcl_log("Percentage of peaceful spawns are group: " .. peaceful_group_percentage_spawned)
mcl_log("Percentage of hostile spawns are group: " .. hostile_group_percentage_spawned)
--do mobs spawn? --do mobs spawn?
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
@ -250,22 +284,58 @@ local function count_mobs_total(mob_type)
return num return num
end end
local function count_mobs_all() local function count_mobs_add_entry (mobs_list, mob_cat)
local mobs_found = {} if mobs_list[mob_cat] then
mobs_list[mob_cat] = mobs_list[mob_cat] + 1
else
mobs_list[mob_cat] = 1
end
end
--categorise_by can be name or type or spawn_class
local function count_mobs_all(categorise_by, pos)
local mobs_found_wide = {}
local mobs_found_close = {}
local num = 0 local num = 0
for _,entity in pairs(minetest.luaentities) do for _,entity in pairs(minetest.luaentities) do
if entity.is_mob then if entity and entity.is_mob then
local mob_type = entity.type -- animal / monster / npc
local mob_name = entity.name local add_entry = false
if mobs_found[mob_name] then --local mob_type = entity.type -- animal / monster / npc
mobs_found[mob_name] = mobs_found[mob_name] + 1 local mob_cat = entity[categorise_by]
if pos then
local mob_pos = entity.object:get_pos()
if mob_pos then
local distance = vector.distance(pos, mob_pos)
mcl_log("distance: ".. distance)
if distance <= MOB_SPAWN_ZONE_MIDDLE then
mcl_log("distance is close")
count_mobs_add_entry (mobs_found_close, mob_cat)
count_mobs_add_entry (mobs_found_wide, mob_cat)
add_entry = true
elseif distance <= MOB_SPAWN_ZONE_OUTER then
mcl_log("distance is wide")
count_mobs_add_entry (mobs_found_wide, mob_cat)
add_entry = true
else
--mcl_log("mob_pos: " .. minetest.pos_to_string(mob_pos))
end
end
else else
mobs_found[mob_name] = 1 count_mobs_add_entry (mobs_found_wide, mob_cat)
add_entry = true
end
if add_entry then
num = num + 1
end end
num = num + 1
end end
end end
return mobs_found, num mcl_log("num: ".. num)
return mobs_found_close, mobs_found_wide, num
end end
local function count_mobs_total_cap(mob_type) local function count_mobs_total_cap(mob_type)
@ -280,6 +350,19 @@ local function count_mobs_total_cap(mob_type)
return num return num
end end
local function output_mob_stats(mob_counts, total_mobs)
if (total_mobs) then
minetest.log("action", "Total mobs found: " .. total_mobs)
end
if mob_counts then
for k, v1 in pairs(mob_counts) do
minetest.log("action", "k: " .. tostring(k))
minetest.log("action", "v1: " .. tostring(v1))
end
end
end
-- global functions -- global functions
function mcl_mobs:spawn_abm_check(pos, node, name) function mcl_mobs:spawn_abm_check(pos, node, name)
@ -422,9 +505,12 @@ function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_
summary_chance = summary_chance + chance summary_chance = summary_chance + chance
end end
local two_pi = 2 * math.pi local two_pi = 2 * math.pi
local function get_next_mob_spawn_pos(pos) local function get_next_mob_spawn_pos(pos)
local distance = math_random(25, 32) -- TODO We should consider spawning something a little further away sporadically.
-- It would be good for sky farms and variance, rather than all being on the 24 - 32 block away radius
local distance = math_random(MOB_SPAWN_ZONE_INNER + 1, MOB_SPAWN_ZONE_MIDDLE)
local angle = math_random() * two_pi local angle = math_random() * two_pi
local xoff = math_round(distance * math_cos(angle)) local xoff = math_round(distance * math_cos(angle))
local yoff = math_round(distance * math_sin(angle)) local yoff = math_round(distance * math_sin(angle))
@ -433,7 +519,7 @@ end
local function decypher_limits(posy) local function decypher_limits(posy)
posy = math_floor(posy) posy = math_floor(posy)
return posy - 32, posy + 32 return posy - MOB_SPAWN_ZONE_MIDDLE, posy + MOB_SPAWN_ZONE_MIDDLE
end end
--a simple helper function for mob_spawn --a simple helper function for mob_spawn
@ -484,7 +570,9 @@ local function has_room(self,pos)
return true return true
end end
local function spawn_check(pos,spawn_def,ignore_caps)
local function spawn_check(pos, spawn_def)
if not spawn_def then return end if not spawn_def then return end
dbg_spawn_attempts = dbg_spawn_attempts + 1 dbg_spawn_attempts = dbg_spawn_attempts + 1
local dimension = mcl_worlds.pos_to_dimension(pos) local dimension = mcl_worlds.pos_to_dimension(pos)
@ -507,17 +595,8 @@ local function spawn_check(pos,spawn_def,ignore_caps)
local is_leaf = get_item_group(gotten_node, "leaves") ~= 0 local is_leaf = get_item_group(gotten_node, "leaves") ~= 0
local is_bedrock = gotten_node == "mcl_core:bedrock" local is_bedrock = gotten_node == "mcl_core:bedrock"
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0 local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
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 if pos and spawn_def
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.min_height
and pos.y <= spawn_def.max_height and pos.y <= spawn_def.max_height
and spawn_def.dimension == dimension and spawn_def.dimension == dimension
@ -553,8 +632,7 @@ function mcl_mobs.spawn(pos,id)
end end
local function spawn_group(p,mob,spawn_on,group_max,group_min) local function spawn_group(p,mob,spawn_on,amount_to_spawn)
if not group_min then group_min = 1 end
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on) local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
local o local o
table.shuffle(nn) table.shuffle(nn)
@ -562,9 +640,10 @@ local function spawn_group(p,mob,spawn_on,group_max,group_min)
nn = {} nn = {}
table.insert(nn,p) table.insert(nn,p)
end end
for i = 1, math.random(group_min,group_max) do
for i = 1, amount_to_spawn do
local sp = vector.offset(nn[math.random(#nn)],0,1,0) local sp = vector.offset(nn[math.random(#nn)],0,1,0)
if spawn_check(nn[math.random(#nn)],mob,true) then if spawn_check(nn[math.random(#nn)],mob) then
if mob.type_of_spawning == "water" then if mob.type_of_spawning == "water" then
sp = get_water_spawn(sp) sp = get_water_spawn(sp)
end end
@ -655,25 +734,137 @@ if mobs_spawn then
-- Get pos to spawn, x and z are randomised, y is range -- Get pos to spawn, x and z are randomised, y is range
local function spawn_a_mob(pos, dimension, y_min, y_max) local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide)
--create a disconnected clone of the spawn dictionary
--prevents memory leak -- Some mob examples
--type = "monster", spawn_class = "hostile",
--type = "animal", spawn_class = "passive",
--local cod = { type = "animal", spawn_class = "water",
local type_cap = mob_cap[mob_type] or MISSING_CAP_DEFAULT
local close_zone_cap = MOBS_CAP_CLOSE
local mob_total_wide = mob_counts_wide[mob_type]
if not mob_total_wide then
--mcl_log("none of type found. set as 0")
mob_total_wide = 0
end
local cap_space_wide = type_cap - mob_total_wide
if cap_space_wide < 1 then
cap_space_wide = 0
end
local mob_total_close = mob_counts_close[mob_type]
if not mob_total_close then
--mcl_log("none of type found. set as 0")
mob_total_close = 0
end
local cap_space_close = close_zone_cap - mob_total_close
if cap_space_close < 1 then
cap_space_close = 0
end
--mcl_log("spawn_class: " .. spawn_class)
if false and mob_type == "water" then
mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos))
mcl_log("wide: " .. mob_total_wide .. "/" .. type_cap)
mcl_log("cap_space_wide: " .. cap_space_wide)
mcl_log("close: " .. mob_total_close .. "/" .. close_zone_cap)
mcl_log("cap_space_close: " .. cap_space_close)
end
--TODO Remove old checks
local compare_to_old_checks = false
if compare_to_old_checks then
local mob_count_wide = count_mobs(pos,MOB_SPAWN_ZONE_OUTER,mob_type)
local mob_count_close = count_mobs(pos,MOB_CAP_INNER_RADIUS,mob_type)
if mob_total_wide ~= mob_count_wide then
mcl_log("old mob_count_wide: " .. mob_count_wide)
mcl_log("A difference in wide mob count")
else
--mcl_log("No difference in wide mob count")
end
if mob_total_close ~= mob_count_close then
mcl_log("old mob_count_close: " .. mob_count_close)
mcl_log("A difference in close mob count")
else
--mcl_log("No difference in close mob count")
end
end
return cap_space_wide, cap_space_close
end
local function find_spawning_position(pos, max_times)
local spawning_position
local max_loops = 1
if max_times then max_loops = max_times end
local y_min, y_max = decypher_limits(pos.y)
mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT)
local i = 0
repeat
local goal_pos = get_next_mob_spawn_pos(pos)
if math.abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math.abs(pos.y) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT then
local spawning_position_list = find_nodes_in_area_under_air(
{x = goal_pos.x, y = y_min, z = goal_pos.z},
{x = goal_pos.x, y = y_max, z = goal_pos.z},
{"group:solid", "group:water", "group:lava"}
)
if #spawning_position_list > 0 then
mcl_log("Spawning positions available: " .. minetest.pos_to_string(goal_pos))
spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
else
mcl_log("Spawning position isn't good. Do not spawn: " .. minetest.pos_to_string(goal_pos))
end
else
mcl_log("Pos outside mapgen limits: " .. minetest.pos_to_string(goal_pos))
end
i = i + 1
if i >= max_loops then
mcl_log("Cancel finding spawn positions at: " .. max_loops)
break
end
until spawning_position
return spawning_position
end
local function spawn_a_mob(pos)
--create a disconnected clone of the spawn dictionary, prevents memory leak
local mob_library_worker_table = table_copy(spawn_dictionary) local mob_library_worker_table = table_copy(spawn_dictionary)
local goal_pos = get_next_mob_spawn_pos(pos)
local spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES)
if not spawning_position then
minetest.log("action", "[Mobs spawn] Cannot find a valid spawn position after retries: " .. FIND_SPAWN_POS_RETRIES)
return
end
local mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("spawn_class", spawning_position)
-- TODO remove output
output_mob_stats(mob_counts_close, total_mobs)
output_mob_stats(mob_counts_wide, total_mobs)
--grab mob that fits into the spawning location --grab mob that fits into the spawning location
--randomly grab a mob, don't exclude any possibilities --randomly grab a mob, don't exclude any possibilities
local spawning_position_list = find_nodes_in_area_under_air(
{x = goal_pos.x, y = y_min, z = goal_pos.z},
{x = goal_pos.x, y = y_max, z = goal_pos.z},
{"group:solid", "group:water", "group:lava"}
)
if #spawning_position_list <= 0 then return end
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
perlin_noise = perlin_noise or minetest_get_perlin(noise_params) perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
local noise = perlin_noise:get_3d(spawning_position) local noise = perlin_noise:get_3d(spawning_position)
local current_summary_chance = summary_chance local current_summary_chance = summary_chance
table.shuffle(mob_library_worker_table) table.shuffle(mob_library_worker_table)
while #mob_library_worker_table > 0 do while #mob_library_worker_table > 0 do
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1 local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
local mob_index = 1 local mob_index = 1
@ -684,39 +875,95 @@ if mobs_spawn then
mob_chance = mob_library_worker_table[mob_index].chance mob_chance = mob_library_worker_table[mob_index].chance
step_chance = step_chance + mob_chance step_chance = step_chance + mob_chance
end end
local mob_def = mob_library_worker_table[mob_index]
--minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance) --minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance)
local mob_def = mob_library_worker_table[mob_index]
if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then
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_def_ent = minetest.registered_entities[mob_def.name]
local mob_type = minetest.registered_entities[mob_def.name].type --local mob_type = mob_def_ent.type
if spawn_check(spawning_position,mob_def) then local mob_spawn_class = mob_def_ent.spawn_class
if mob_def.type_of_spawning == "water" then
spawning_position = get_water_spawn(spawning_position) --mcl_log("mob_spawn_class: " .. mob_spawn_class)
if not spawning_position then
minetest.log("warning","[mcl_mobs] no water spawn for mob "..mob_def.name.." found at "..minetest.pos_to_string(vector.round(pos))) local cap_space_wide, cap_space_close = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide)
if cap_space_close > 0 and cap_space_wide > 0 then
--mcl_log("Cap space available")
-- Spawn caps for animals and water creatures fill up rapidly. Need to throttle this somewhat
-- for performance and for early game challenge. We don't want to reduce hostiles though.
local spawn_hostile = (mob_spawn_class == "hostile")
local spawn_passive = (mob_spawn_class ~= "hostile") and math.random(100) < peaceful_percentage_spawned
-- or not hostile
--mcl_log("Spawn_passive: " .. tostring(spawn_passive))
--mcl_log("Spawn_hostile: " .. tostring(spawn_hostile))
if (spawn_hostile or spawn_passive) and 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
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 mob_def_ent.can_spawn and not mob_def_ent.can_spawn(spawning_position) then
minetest.log("warning","[mcl_mobs] mob "..mob_def.name.." refused to spawn at "..minetest.pos_to_string(vector.round(spawning_position)))
return return
end end
end
if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(spawning_position) then
minetest.log("warning","[mcl_mobs] mob "..mob_def.name.." refused to spawn at "..minetest.pos_to_string(vector.round(spawning_position)))
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 --everything is correct, spawn mob
if logging then local spawn_in_group = mob_def_ent.spawn_in_group or 4
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))
local spawn_group_hostile = (mob_spawn_class == "hostile") and (math.random(100) < hostile_group_percentage_spawned)
local spawn_group_passive = (mob_spawn_class ~= "hostile") and (math.random(100) < peaceful_group_percentage_spawned)
mcl_log("spawn_group_hostile: " .. tostring(spawn_group_hostile))
mcl_log("spawn_group_passive: " .. tostring(spawn_group_passive))
local spawned
if spawn_in_group and (spawn_group_hostile or spawn_group_passive) then
local group_min = mob_def_ent.spawn_in_group_min or 1
if not group_min then group_min = 1 end
local amount_to_spawn = math.random(group_min,spawn_in_group)
if amount_to_spawn > cap_space_wide then
mcl_log("Spawning quantity: " .. amount_to_spawn)
mcl_log("Throttle amount to cap space: " .. cap_space_wide)
amount_to_spawn = cap_space_wide
end
if logging then
minetest.log("action", "[mcl_mobs] A group of " ..amount_to_spawn .. " " .. mob_def.name .. " mob spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1))
end
spawned = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name}, amount_to_spawn)
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
spawned = mcl_mobs.spawn(spawning_position, mob_def.name)
end end
object = mcl_mobs.spawn(spawning_position, mob_def.name)
if spawned then
--mcl_log("We have spawned")
mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("type", pos)
local new_spawning_position = find_spawning_position(pos, 3)
if new_spawning_position then
mcl_log("Setting new spawning position")
spawning_position = new_spawning_position
else
mcl_log("Cannot set new spawning position")
end
end
else
mcl_log("Spawn check failed")
end end
else
mcl_log("Cap space full")
end end
end end
current_summary_chance = current_summary_chance - mob_chance current_summary_chance = current_summary_chance - mob_chance
table_remove(mob_library_worker_table, mob_index) table_remove(mob_library_worker_table, mob_index)
@ -728,22 +975,24 @@ if mobs_spawn then
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime timer = timer + dtime
if timer < 10 then return end if timer < WAIT_FOR_SPAWN_ATTEMPT then return end
timer = 0 timer = 0
local players = get_connected_players() local players = get_connected_players()
local total_mobs = count_mobs_total_cap() local total_mobs = count_mobs_total_cap()
if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then
minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.") minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.")
return return
end --mob cap per player end --mob cap per player
for _, player in pairs(players) do for _, player in pairs(players) do
local pos = player:get_pos() local pos = player:get_pos()
local dimension = mcl_worlds.pos_to_dimension(pos) local dimension = mcl_worlds.pos_to_dimension(pos)
-- ignore void and unloaded area -- ignore void and unloaded area
if dimension ~= "void" and dimension ~= "default" then if dimension ~= "void" and dimension ~= "default" then
local y_min, y_max = decypher_limits(pos.y) spawn_a_mob(pos)
spawn_a_mob(pos, dimension, y_min, y_max)
end end
end end
end) end)
@ -775,27 +1024,18 @@ function mob_class:check_despawn(pos, dtime)
end end
end end
minetest.register_chatcommand("mobstats",{ minetest.register_chatcommand("mobstats",{
privs = { debug = true }, privs = { debug = true },
func = function(n,param) func = function(n,param)
minetest.chat_send_player(n,dump(dbg_spawn_counts)) minetest.chat_send_player(n,dump(dbg_spawn_counts))
local pos = minetest.get_player_by_name(n):get_pos() 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,"mobs within 32 radius of player:"..count_mobs(pos,MOB_CAP_INNER_RADIUS))
minetest.chat_send_player(n,"total mobs:"..count_mobs_total()) minetest.chat_send_player(n,"total mobs:"..count_mobs_total())
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts) minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ) minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
local mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("name") -- Can use "type"
local mob_counts, total_mobs = count_mobs_all() output_mob_stats(mob_counts_wide, total_mobs)
if (total_mobs) then
minetest.log("action", "Total mobs found: " .. total_mobs)
end
if mob_counts then
for k, v1 in pairs(mob_counts) do
minetest.log("action", "k: " .. tostring(k))
minetest.log("action", "v1: " .. tostring(v1))
end
end
end end
}) })

View File

@ -40,8 +40,8 @@ local cod = {
xp_max = 3, xp_max = 3,
armor = 100, armor = 100,
rotate = 180, rotate = 180,
spawn_in_group_min = 3, spawn_in_group_min = 2, -- was 3
spawn_in_group = 8, spawn_in_group = 4, -- was 8 nerfed until we can cap them properly locally. this is a group size, not a per spawn attempt
tilt_swim = true, tilt_swim = true,
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
visual = "mesh", visual = "mesh",

View File

@ -14,7 +14,7 @@ local cow_def = {
xp_max = 3, xp_max = 3,
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45}, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
spawn_in_group = 4, spawn_in_group = 4,
spawn_in_group_min = 3, spawn_in_group_min = 2,
visual = "mesh", visual = "mesh",
mesh = "mobs_mc_cow.b3d", mesh = "mobs_mc_cow.b3d",
textures = { { textures = { {
@ -93,8 +93,8 @@ mcl_mobs.register_mob("mobs_mc:cow", cow_def)
-- Mooshroom -- Mooshroom
local mooshroom_def = table.copy(cow_def) local mooshroom_def = table.copy(cow_def)
mooshroom_def.description = S("Mooshroom") mooshroom_def.description = S("Mooshroom")
mooshroom_def.spawn_in_group_min = 4 mooshroom_def.spawn_in_group_min = 2
mooshroom_def.spawn_in_group = 8 mooshroom_def.spawn_in_group = 4
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } } mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
mooshroom_def.on_rightclick = function(self, clicker) mooshroom_def.on_rightclick = function(self, clicker)
if self:feed_tame(clicker, 1, true, false) then return end if self:feed_tame(clicker, 1, true, false) then return end

View File

@ -42,8 +42,8 @@ local dolphin = {
walk_chance = 100, walk_chance = 100,
breath_max = 120, breath_max = 120,
rotate = 180, rotate = 180,
spawn_in_group_min = 3, spawn_in_group_min = 2, -- was 3
spawn_in_group = 5, spawn_in_group = 4, -- was 4. nerfed until water has own cap, and it represents max pack size rather than per spawn attempt
tilt_swim = true, tilt_swim = true,
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
visual = "mesh", visual = "mesh",

View File

@ -125,7 +125,7 @@ local horse = {
type = "animal", type = "animal",
spawn_class = "passive", spawn_class = "passive",
spawn_in_group_min = 2, spawn_in_group_min = 2,
spawn_in_group = 6, spawn_in_group = 4, -- was 6. nerfed until group size is a cap rather than per spawn cycle
visual = "mesh", visual = "mesh",
mesh = "mobs_mc_horse.b3d", mesh = "mobs_mc_horse.b3d",
visual_size = {x=3.0, y=3.0}, visual_size = {x=3.0, y=3.0},

View File

@ -56,8 +56,8 @@ mcl_mobs.register_mob("mobs_mc:llama", {
shoot_interval = 5.5, shoot_interval = 5.5,
arrow = "mobs_mc:llamaspit", arrow = "mobs_mc:llamaspit",
shoot_offset = 1, --3.5 *would* be a good value visually but it somehow messes with the projectiles trajectory shoot_offset = 1, --3.5 *would* be a good value visually but it somehow messes with the projectiles trajectory
spawn_in_group_min = 4, spawn_in_group_min = 2, -- was 4
spawn_in_group = 6, spawn_in_group = 4, -- was 6 nerfed until we can cap them properly locally. this is a group size, not a per spawn attempt
head_swivel = "head.control", head_swivel = "head.control",
bone_eye_height = 11, bone_eye_height = 11,

View File

@ -67,7 +67,7 @@ local tropical_fish = {
xp_min = 1, xp_min = 1,
xp_max = 3, xp_max = 3,
armor = 100, armor = 100,
spawn_in_group = 9, spawn_in_group = 4, -- was 9. nerfed until aquatics use own cap rather than animal, and it represents pack size, not per spawn attempt
tilt_swim = true, tilt_swim = true,
collisionbox = {-0.2, 0.0, -0.2, 0.2, 0.1, 0.2}, collisionbox = {-0.2, 0.0, -0.2, 0.2, 0.1, 0.2},
visual = "mesh", visual = "mesh",

View File

@ -172,7 +172,6 @@ local professions = {
{ { "mcl_mobitems:string", 15, 20 }, E1 }, { { "mcl_mobitems:string", 15, 20 }, E1 },
{ E1, { "mcl_bows:arrow", 8, 12 } }, { E1, { "mcl_bows:arrow", 8, 12 } },
{ { "mcl_core:gravel", 10, 10, "mcl_core:emerald", 1, 1 }, { "mcl_core:flint", 6, 10 } }, { { "mcl_core:gravel", 10, 10, "mcl_core:emerald", 1, 1 }, { "mcl_core:flint", 6, 10 } },
{ { "mcl_core:stick", 32, 32 }, E1 },
}, },
{ {
{ { "mcl_core:flint", 26, 26 }, E1 }, { { "mcl_core:flint", 26, 26 }, E1 },

View File

@ -210,23 +210,9 @@ mcl_weather.skycolor = {
end end
end end
elseif dim == "end" then elseif dim == "end" then
local biomesky = "#000000"
local biomefog = "#A080A0"
if mg_name ~= "v6" and mg_name ~= "singlenode" then
local biome_index = minetest.get_biome_data(player:get_pos()).biome
local biome_name = minetest.get_biome_name(biome_index)
local biome = minetest.registered_biomes[biome_name]
if biome then
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name))
biomesky = biome._mcl_skycolor
biomefog = biome._mcl_fogcolor -- The End biomes seemingly don't use the fog colour, despite having this value according to the wiki. The sky colour is seemingly used for both sky and fog?
else
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
end
end
local t = "mcl_playerplus_end_sky.png" local t = "mcl_playerplus_end_sky.png"
player:set_sky({ type = "skybox", player:set_sky({ type = "skybox",
base_color = biomesky, base_color = "#000000",
textures = {t,t,t,t,t,t}, textures = {t,t,t,t,t,t},
clouds = false, clouds = false,
}) })
@ -235,29 +221,24 @@ mcl_weather.skycolor = {
player:set_stars({visible = false}) player:set_stars({visible = false})
mcl_weather.skycolor.override_day_night_ratio(player, 0.5) mcl_weather.skycolor.override_day_night_ratio(player, 0.5)
elseif dim == "nether" then elseif dim == "nether" then
local biomesky = "#6EB1FF" local nether_sky = {
local biomefog = "#330808" Nether = "#300808",
if mg_name ~= "v6" and mg_name ~= "singlenode" then BasaltDelta = "#685F70",
local biome_index = minetest.get_biome_data(player:get_pos()).biome SoulsandValley = "#1B4745",
local biome_name = minetest.get_biome_name(biome_index) CrimsonForest = "#330303",
local biome = minetest.registered_biomes[biome_name] WarpedForest = "#1A051A"
if biome then }
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name)) local biometint = nether_sky[minetest.get_biome_name(minetest.get_biome_data(player:get_pos()).biome)]
biomesky = biome._mcl_skycolor -- The Nether biomes seemingly don't use the sky colour, despite having this value according to the wiki. The fog colour is used for both sky and fog.
biomefog = biome._mcl_fogcolor
else
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
end
end
mcl_weather.set_sky_color(player, { mcl_weather.set_sky_color(player, {
type = "regular", type = "regular",
sky_color = { sky_color = {
day_sky = biomefog, day_sky = "#300808",
day_horizon = biomefog, day_horizon = biometint,
dawn_sky = biomefog, dawn_sky = "#300808",
dawn_horizon = biomefog, dawn_horizon = biometint,
night_sky = biomefog, night_sky = "#300808",
night_horizon = biomefog, night_horizon = biometint,
}, },
clouds = false, clouds = false,
}) })

View File

@ -156,7 +156,6 @@ local function set_inv_page(page, player)
creative_list = inventory_lists[page] creative_list = inventory_lists[page]
end end
inv:set_size("main", #creative_list) inv:set_size("main", #creative_list)
players[playername].inv_size = #creative_list
inv:set_list("main", creative_list) inv:set_list("main", creative_list)
end end
@ -305,21 +304,37 @@ minetest.register_on_joinplayer(function (player)
end end
end) end)
function mcl_inventory.set_creative_formspec(player) function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, show, page, filter)
local playername = player:get_player_name() --reset_menu_item_bg()
if not players[playername] then return end pagenum = math.floor(pagenum) or 1
local start_i = players[playername].start_i local playername = player:get_player_name()
local pagenum = start_i / (9*5) + 1
local name = players[playername].page if not inv_size then
local inv_size = players[playername].inv_size if page == "nix" then
local filter = players[playername].filter local inv = minetest.get_inventory({type="detached", name="creative_"..playername})
inv_size = inv:get_size("main")
elseif page and page ~= "inv" then
inv_size = #(inventory_lists[page])
else
inv_size = 0
end
end
local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1)) local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1))
local name = "nix"
local main_list local main_list
local listrings = "listring[detached:creative_"..playername..";main]".. local listrings = "listring[detached:creative_"..playername..";main]"..
"listring[current_player;main]".. "listring[current_player;main]"..
"listring[detached:trash;main]" "listring[detached:trash;main]"
if page then
name = page
if players[playername] then
players[playername].page = page
end
end
--bg[name] = "crafting_creative_bg.png"
local inv_bg = "crafting_inventory_creative.png" local inv_bg = "crafting_inventory_creative.png"
if name == "inv" then if name == "inv" then
inv_bg = "crafting_inventory_creative_survival.png" inv_bg = "crafting_inventory_creative_survival.png"
@ -478,6 +493,9 @@ function mcl_inventory.set_creative_formspec(player)
listrings listrings
if name == "nix" then if name == "nix" then
if filter == nil then
filter = ""
end
formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]" formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]"
formspec = formspec .. "field_close_on_enter[search;false]" formspec = formspec .. "field_close_on_enter[search;false]"
end end
@ -564,11 +582,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if page then if page then
players[name].page = page players[name].page = page
else end
if players[name].page then
page = players[name].page page = players[name].page
end end
-- Figure out current scroll bar from formspec
--local formspec = player:get_inventory_formspec()
local start_i = players[name].start_i local start_i = players[name].start_i
if fields.creative_prev then if fields.creative_prev then
start_i = start_i - 9*5 start_i = start_i - 9*5
elseif fields.creative_next then elseif fields.creative_next then
@ -590,7 +613,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
else else
inv_size = 0 inv_size = 0
end end
players[name].inv_size = inv_size
if start_i >= inv_size then if start_i >= inv_size then
start_i = start_i - 9*5 start_i = start_i - 9*5
@ -600,19 +622,72 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
players[name].start_i = start_i players[name].start_i = start_i
if not fields.nix and fields.search then local filter = ""
players[name].filter = fields.search if not fields.nix and fields.search and fields.search ~= "" then
else filter = fields.search
players[name].filter = "" players[name].filter = filter
end end
mcl_inventory.set_creative_formspec(player) mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter)
end) end)
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) if minetest.is_creative_enabled("") then
return placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name()) minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
end) -- Place infinite nodes, except for shulker boxes
local group = minetest.get_item_group(itemstack:get_name(), "shulker_box")
return group == 0 or group == nil
end)
function minetest.handle_node_drops(pos, drops, digger)
if not digger or not digger:is_player() then
for _,item in ipairs(drops) do
minetest.add_item(pos, item)
end
end
local inv = digger:get_inventory()
if inv then
for _,item in ipairs(drops) do
if not inv:contains_item("main", item, true) then
inv:add_item("main", item)
end
end
end
end
mcl_inventory.update_inventory_formspec = function(player)
local page
local name = player:get_player_name()
if players[name].page then
page = players[name].page
else
page = "nix"
end
-- Figure out current scroll bar from formspec
--local formspec = player:get_inventory_formspec()
local start_i = players[name].start_i
local inv_size
if page == "nix" then
local inv = minetest.get_inventory({type="detached", name="creative_"..name})
inv_size = inv:get_size("main")
elseif page and page ~= "inv" then
inv_size = #(inventory_lists[page])
else
inv_size = 0
end
local filter = players[name].filter
if filter == nil then
filter = ""
end
mcl_inventory.set_creative_formspec(player, start_i, start_i / (9*5) + 1, inv_size, false, page, filter)
end
end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
-- Initialize variables and inventory -- Initialize variables and inventory
@ -625,7 +700,7 @@ minetest.register_on_joinplayer(function(player)
end end
init(player) init(player)
-- Setup initial creative inventory to the "nix" page. -- Setup initial creative inventory to the "nix" page.
mcl_inventory.set_creative_formspec(player) mcl_inventory.set_creative_formspec(player, 0, 1, nil, false, "nix", "")
end) end)
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info) minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)

View File

@ -46,9 +46,14 @@ function return_fields(player, name)
end end
end end
local function set_inventory(player) local function set_inventory(player, armor_change_only)
if minetest.is_creative_enabled(player:get_player_name()) then if minetest.is_creative_enabled(player:get_player_name()) then
mcl_inventory.set_creative_formspec(player) if armor_change_only then
-- Stay on survival inventory plage if only the armor has been changed
mcl_inventory.set_creative_formspec(player, 0, 0, nil, nil, "inv")
else
mcl_inventory.set_creative_formspec(player, 0, 1)
end
return return
end end
local inv = player:get_inventory() local inv = player:get_inventory()
@ -138,7 +143,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end) end)
mcl_inventory.update_inventory_formspec = set_inventory if not minetest.is_creative_enabled("") then
function mcl_inventory.update_inventory_formspec(player)
set_inventory(player)
end
end
-- Drop crafting grid items on leaving -- Drop crafting grid items on leaving
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
@ -190,6 +199,24 @@ function minetest.is_creative_enabled(name)
return false return false
end end
--Insta "digging" nodes in gamemode-creative
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
if not puncher or not puncher:is_player() then return end
local name = puncher:get_player_name()
if not minetest.is_creative_enabled(name) then return end
if pointed_thing.type ~= "node" then return end
local def = minetest.registered_nodes[node.name]
if def then
minetest.node_dig(pos,node,puncher)
return true
end
end)
--Don't subtract from inv when placing in gamemode-creative
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
if placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name()) then return true end
end)
local function in_table(n,h) local function in_table(n,h)
for k,v in pairs(h) do for k,v in pairs(h) do
if v == n then return true end if v == n then return true end
@ -211,7 +238,6 @@ function mcl_inventory.player_set_gamemode(p,g)
elseif g == "creative" then elseif g == "creative" then
mcl_experience.remove_hud(p) mcl_experience.remove_hud(p)
end end
mcl_meshhand.update_player(p)
set_inventory(p) set_inventory(p)
end end

View File

@ -19,6 +19,50 @@ dig_speed_class group:
- 7: Instantaneous - 7: Instantaneous
]] ]]
-- The hand
local groupcaps, hand_range, hand_groups
if minetest.is_creative_enabled("") then
-- Instant breaking in creative mode
groupcaps = { creative_breakable = { times = {0}, uses = 0 } }
hand_range = tonumber(minetest.settings:get("mcl_hand_range_creative")) or 10
hand_groups = { dig_speed_class = 7 }
else
groupcaps = {}
hand_range = tonumber(minetest.settings:get("mcl_hand_range")) or 4.5
hand_groups = { dig_speed_class = 1 }
end
minetest.register_tool(":", {
type = "none",
_doc_items_longdesc = S("You use your bare hand whenever you are not wielding any item. With your hand you can mine most blocks, but this is the slowest method and only the weakest blocks will yield their useful drop. The hand also deals minor damage by punching. Using the hand is often a last resort, as proper mining tools and weapons are much better.").."\n"..
S("When you are wielding an item which is not a mining tool or a weapon, it will behave as if it were the hand when you start mining or punching.").."\n"..
S("In Creative Mode, the hand is able to break all blocks instantly."),
wield_image = "blank.png",
wield_scale = {x=1.0,y=1.0,z=2.0},
-- According to Minecraft Wiki, the exact range is 3.975.
-- Minetest seems to only support whole numbers, so we use 4.
range = hand_range,
tool_capabilities = {
full_punch_interval = 0.25,
max_drop_level = 0,
groupcaps = groupcaps,
damage_groups = {fleshy=1},
},
groups = hand_groups,
_mcl_diggroups = {
handy = { speed = 1, level = 1, uses = 0 },
axey = { speed = 1, level = 1, uses = 0 },
shovely = { speed = 1, level = 1, uses = 0 },
hoey = { speed = 1, level = 1, uses = 0 },
pickaxey = { speed = 1, level = 0, uses = 0 },
swordy = { speed = 1, level = 0, uses = 0 },
swordy_cobweb = { speed = 1, level = 0, uses = 0 },
shearsy = { speed = 1, level = 0, uses = 0 },
shearsy_wool = { speed = 1, level = 0, uses = 0 },
shearsy_cobweb = { speed = 1, level = 0, uses = 0 },
}
})
-- Help texts -- Help texts
local pickaxe_longdesc = S("Pickaxes are mining tools to mine hard blocks, such as stone. A pickaxe can also be used as weapon, but it is rather inefficient.") local pickaxe_longdesc = S("Pickaxes are mining tools to mine hard blocks, such as stone. A pickaxe can also be used as weapon, but it is rather inefficient.")
local axe_longdesc = S("An axe is your tool of choice to cut down trees, wood-based blocks and other blocks. Axes deal a lot of damage as well, but they are rather slow.") local axe_longdesc = S("An axe is your tool of choice to cut down trees, wood-based blocks and other blocks. Axes deal a lot of damage as well, but they are rather slow.")

View File

@ -1,12 +1,3 @@
local overworld_fogcolor = "#C0D8FF"
local beach_skycolor = "#78A7FF" -- This is the case for all beach biomes except for the snowy ones! Those beaches will have their own colour instead of this one.
local ocean_skycolor = "#7BA4FF" -- This is the case for all ocean biomes except for non-deep frozen oceans! Those oceans will have their own colour instead of this one.
local nether_skycolor = "#6EB1FF" -- The Nether biomes seemingly don't use the sky colour, despite having this value according to the wiki. The fog colour is used for both sky and fog.
local end_skycolor = "#000000"
local end_fogcolor = "#A080A0" -- The End biomes seemingly don't use the fog colour, despite having this value according to the wiki. The sky colour is used for both sky and fog.
local mg_name = minetest.get_mapgen_setting("mg_name") local mg_name = minetest.get_mapgen_setting("mg_name")
local mg_seed = minetest.get_mapgen_setting("seed") local mg_seed = minetest.get_mapgen_setting("seed")
@ -143,6 +134,15 @@ local function register_biomes()
"BambooJungleEdgeM", "BambooJungleEdgeM",
} }
local beach_skycolor = "#78A7FF" -- This is the case for all beach biomes except for the snowy ones! Those beaches will have their own colour instead of this one.
local ocean_skycolor = "#7BA4FF" -- This is the case for all ocean biomes except for non-deep frozen oceans! Those oceans will have their own colour instead of this one.
local overworld_fogcolor = "#C0D8FF"
local nether_skycolor = "#6EB1FF"
local end_fogcolor = "#A080A0"
local end_skycolor = "#000000"
-- Ice Plains Spikes (rare) -- Ice Plains Spikes (rare)
minetest.register_biome({ minetest.register_biome({
name = "IcePlainsSpikes", name = "IcePlainsSpikes",
@ -1940,8 +1940,8 @@ local function register_dimension_biomes()
humidity_point = 0, humidity_point = 0,
_mcl_biome_type = "hot", _mcl_biome_type = "hot",
_mcl_grass_palette_index = 17, _mcl_grass_palette_index = 17,
_mcl_skycolor = nether_skycolor, -- _mcl_skycolor = nether_skycolor,
_mcl_fogcolor = "#330808" -- _mcl_fogcolor = "#330808"
}) })
minetest.register_decoration({ minetest.register_decoration({
@ -1971,8 +1971,8 @@ local function register_dimension_biomes()
humidity_point = 33, humidity_point = 33,
_mcl_biome_type = "hot", _mcl_biome_type = "hot",
_mcl_grass_palette_index = 17, _mcl_grass_palette_index = 17,
_mcl_skycolor = nether_skycolor, -- _mcl_skycolor = nether_skycolor,
_mcl_fogcolor = "#1B4745" -- _mcl_fogcolor = "#1B4745"
}) })
minetest.register_decoration({ minetest.register_decoration({
deco_type = "simple", deco_type = "simple",
@ -2022,8 +2022,8 @@ local function register_dimension_biomes()
humidity_point = 47, humidity_point = 47,
_mcl_biome_type = "hot", _mcl_biome_type = "hot",
_mcl_grass_palette_index = 17, _mcl_grass_palette_index = 17,
_mcl_skycolor = nether_skycolor, -- _mcl_skycolor = nether_skycolor,
_mcl_fogcolor = "#330303" -- _mcl_fogcolor = "#330303"
}) })
minetest.register_decoration({ minetest.register_decoration({
deco_type = "simple", deco_type = "simple",
@ -2051,8 +2051,8 @@ local function register_dimension_biomes()
humidity_point = 70, humidity_point = 70,
_mcl_biome_type = "hot", _mcl_biome_type = "hot",
_mcl_grass_palette_index = 17, _mcl_grass_palette_index = 17,
_mcl_skycolor = nether_skycolor, -- _mcl_skycolor = nether_skycolor,
_mcl_fogcolor = "#1A051A" -- _mcl_fogcolor = "#1A051A"
}) })
minetest.register_decoration({ minetest.register_decoration({
deco_type = "simple", deco_type = "simple",
@ -2080,8 +2080,8 @@ local function register_dimension_biomes()
humidity_point = 80, humidity_point = 80,
_mcl_biome_type = "hot", _mcl_biome_type = "hot",
_mcl_grass_palette_index = 17, _mcl_grass_palette_index = 17,
_mcl_skycolor = nether_skycolor, -- _mcl_skycolor = nether_skycolor,
_mcl_fogcolor = "#685F70" -- _mcl_fogcolor = "#685F70"
}) })
minetest.register_decoration({ minetest.register_decoration({
@ -2134,8 +2134,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
name = "EndBarrens", name = "EndBarrens",
@ -2151,8 +2151,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
name = "EndMidlands", name = "EndMidlands",
@ -2168,8 +2168,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
name = "EndHighlands", name = "EndHighlands",
@ -2185,8 +2185,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
name = "EndSmallIslands", name = "EndSmallIslands",
@ -2202,8 +2202,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
@ -2222,8 +2222,8 @@ local function register_dimension_biomes()
min_pos = {x = -1250, y = mcl_vars.mg_end_min, z = -1250}, min_pos = {x = -1250, y = mcl_vars.mg_end_min, z = -1250},
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
minetest.register_biome({ minetest.register_biome({
@ -2240,8 +2240,8 @@ local function register_dimension_biomes()
vertical_blend = 16, vertical_blend = 16,
_mcl_biome_type = "medium", _mcl_biome_type = "medium",
_mcl_grass_palette_index = 0, _mcl_grass_palette_index = 0,
_mcl_skycolor = end_skycolor, -- _mcl_skycolor = end_skycolor,
_mcl_fogcolor = end_fogcolor -- _mcl_fogcolor = end_fogcolor
}) })
end end

View File

@ -1,5 +1,4 @@
local mcl_skins_enabled = minetest.global_exists("mcl_skins") local mcl_skins_enabled = minetest.global_exists("mcl_skins")
mcl_meshhand = { }
---This is a fake node that should never be placed in the world ---This is a fake node that should never be placed in the world
---@type node_definition ---@type node_definition
@ -16,77 +15,43 @@ local node_def = {
end, end,
drop = "", drop = "",
on_drop = function(_, _, _) return ItemStack() end, on_drop = function(_, _, _) return ItemStack() end,
groups = { groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
dig_immediate = 3, range = minetest.registered_items[""].range
not_in_creative_inventory = 1,
dig_speed_class = 1,
},
tool_capabilities = {
full_punch_interval = 0.25,
max_drop_level = 0,
groupcaps = { },
damage_groups = { fleshy = 1 },
},
_mcl_diggroups = {
handy = { speed = 1, level = 1, uses = 0 },
axey = { speed = 1, level = 1, uses = 0 },
shovely = { speed = 1, level = 1, uses = 0 },
hoey = { speed = 1, level = 1, uses = 0 },
pickaxey = { speed = 1, level = 0, uses = 0 },
swordy = { speed = 1, level = 0, uses = 0 },
swordy_cobweb = { speed = 1, level = 0, uses = 0 },
shearsy = { speed = 1, level = 0, uses = 0 },
shearsy_wool = { speed = 1, level = 0, uses = 0 },
shearsy_cobweb = { speed = 1, level = 0, uses = 0 },
},
range = tonumber(minetest.settings:get("mcl_hand_range")) or 4.5
} }
-- This is for _mcl_autogroup to know about the survival hand tool capabilites
mcl_meshhand.survival_hand_tool_caps = node_def.tool_capabilities
local creative_dig_speed = tonumber(minetest.settings:get("mcl_creative_dig_speed")) or 0.2
local creative_hand_range = tonumber(minetest.settings:get("mcl_hand_range_creative")) or 10
if mcl_skins_enabled then if mcl_skins_enabled then
-- Generate a node for every skin -- Generate a node for every skin
local list = mcl_skins.get_skin_list() local list = mcl_skins.get_skin_list()
for _, skin in pairs(list) do for _, skin in pairs(list) do
local node_def = table.copy(node_def) if skin.slim_arms then
node_def._mcl_hand_id = skin.id local female = table.copy(node_def)
node_def.tiles = { skin.texture } female._mcl_hand_id = skin.id
node_def.mesh = skin.slim_arms and "mcl_meshhand_female.b3d" or "mcl_meshhand.b3d" female.mesh = "mcl_meshhand_female.b3d"
if skin.creative then female.tiles = { skin.texture }
node_def.range = creative_hand_range minetest.register_node("mcl_meshhand:" .. skin.id, female)
node_def.groups.dig_speed_class = 7 else
node_def.tool_capabilities.groupcaps.creative_breakable = { times = { creative_dig_speed }, uses = 0 } local male = table.copy(node_def)
male._mcl_hand_id = skin.id
male.mesh = "mcl_meshhand.b3d"
male.tiles = { skin.texture }
minetest.register_node("mcl_meshhand:" .. skin.id, male)
end end
minetest.register_node("mcl_meshhand:" .. skin.id, node_def)
end end
else else
node_def._mcl_hand_id = "hand" node_def._mcl_hand_id = "hand"
node_def.mesh = "mcl_meshhand.b3d" node_def.mesh = "mcl_meshhand.b3d"
node_def.tiles = { "character.png" } node_def.tiles = { "character.png" }
minetest.register_node("mcl_meshhand:hand_surv", node_def) minetest.register_node("mcl_meshhand:hand", node_def)
node_def = table.copy(node_def)
node_def.range = creative_hand_range
node_def.groups.dig_speed_class = 7
node_def.tool_capabilities.groupcaps.creative_breakable = { times = { creative_dig_speed }, uses = 0 }
minetest.register_node("mcl_meshhand:hand_crea", node_def)
end
function mcl_meshhand.update_player(player)
if mcl_skins_enabled then
local node_id = mcl_skins.get_node_id_by_player(player)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id)
else
local creative = minetest.is_creative_enabled(player:get_player_name())
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:hand" .. (creative and "_crea" or "_surv"))
end
end end
if mcl_skins_enabled then if mcl_skins_enabled then
mcl_player.register_on_visual_change(mcl_meshhand.update_player) -- Change the player's hand to their skin
mcl_player.register_on_visual_change(function(player)
local node_id = mcl_skins.get_node_id_by_player(player)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id)
end)
else else
minetest.register_on_joinplayer(mcl_meshhand.update_player) minetest.register_on_joinplayer(function(player)
player:get_inventory():set_stack("hand", 1, ItemStack("mcl_meshhand:hand"))
end)
end end

View File

@ -11,51 +11,43 @@ end
function mcl_skins.get_skin_list() function mcl_skins.get_skin_list()
local list = {} local list = {}
for _, game_mode in pairs({"_crea", "_surv"}) do for _, base in pairs(mcl_skins.base) do
for _, base in pairs(mcl_skins.base) do for _, base_color in pairs(mcl_skins.base_color) do
for _, base_color in pairs(mcl_skins.base_color) do local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "")
local id = base:gsub(".png$", "") .. minetest.colorspec_to_colorstring(base_color):gsub("#", "") local female = {
local female = { texture = make_texture(base, base_color),
texture = make_texture(base, base_color), slim_arms = true,
slim_arms = true, id = id .. "_female"
id = id .. "_female" .. game_mode, }
creative = game_mode == "_crea" table.insert(list, female)
}
table.insert(list, female) local male = {
texture = make_texture(base, base_color),
local male = { slim_arms = false,
texture = make_texture(base, base_color), id = id .. "_male"
slim_arms = false, }
id = id .. "_male" .. game_mode, table.insert(list, male)
creative = game_mode == "_crea"
}
table.insert(list, male)
end
end
for _, skin in pairs(mcl_skins.simple_skins) do
table.insert(list, {
texture = skin.texture,
slim_arms = skin.slim_arms,
id = skin.texture:gsub(".png$", "") .. (skin.slim_arms and "_female" or "_male") .. game_mode,
creative = game_mode == "_crea"
})
end end
end end
for _, skin in pairs(mcl_skins.simple_skins) do
table.insert(list, {
texture = skin.texture,
slim_arms = skin.slim_arms,
id = skin.texture:gsub(".png$", "") .. "_" .. (skin.slim_arms and "female" or "male"),
})
end
return list return list
end end
function mcl_skins.get_node_id_by_player(player) function mcl_skins.get_node_id_by_player(player)
local skin = mcl_skins.players[player] local skin = mcl_skins.players[player]
local simple_skin = skin.simple_skins_id if skin.simple_skins_id then
if simple_skin then local skin = mcl_skins.simple_skins[skin.simple_skins_id]
skin = mcl_skins.simple_skins[skin.simple_skins_id] return skin.texture:gsub(".png$", "") ..
end "_" .. (skin.slim_arms and "female" or "male")
local creative = minetest.is_creative_enabled(player:get_player_name())
local append = (skin.slim_arms and "_female" or "_male") .. (creative and "_crea" or "_surv")
if simple_skin then
return skin.texture:gsub(".png$", "") .. append
else else
return skin.base:gsub(".png$", "") .. return skin.base:gsub(".png$", "") ..
minetest.colorspec_to_colorstring(skin.base_color):gsub("#", "") .. append minetest.colorspec_to_colorstring(skin.base_color):gsub("#", "") ..
"_" .. (skin.slim_arms and "female" or "male")
end end
end end

View File

@ -76,13 +76,10 @@ mcl_enable_skin_customization (Enable player skin customization) bool true
# Default:4.5 # Default:4.5
mcl_hand_range (Hand range) float 4.5 1 128 mcl_hand_range (Hand range) float 4.5 1 128
# How far the player hand can reach in creative mode # How far the player hand can reach in creative mode (not gamemode-creative)
# Default:10 # Default:10
mcl_hand_range_creative (Creative mode hand range) float 10 1 128 mcl_hand_range_creative (Creative mode hand range) float 10 1 128
# Creative mode dig speed in seconds
mcl_creative_dig_speed (Creative mode dig speed) float 0.2
# If enabled the hunger mechanic will be active # If enabled the hunger mechanic will be active
mcl_enable_hunger (Hunger mechanic) bool true mcl_enable_hunger (Hunger mechanic) bool true
@ -115,6 +112,15 @@ mobs_griefing (Mobs change blocks) bool true
# If enabled, mobs won't damage particles when they got hurt. # If enabled, mobs won't damage particles when they got hurt.
mobs_disable_blood (Disable mob damage particles) bool false mobs_disable_blood (Disable mob damage particles) bool false
#Percentage of peaceful spawn attempts that succeed (default:35)
mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 35 0 100
#Percentage of peaceful spawn attempts that are group spawns (default:15)
mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 100
#Percentage of hostile spawn attempts that are group spawns (default:20)
mcl_mob_hostile_group_percentage_spawned (Hostile group percentage) int 20 0 100
#Maximum amount mobs (default:500) #Maximum amount mobs (default:500)
mcl_mob_cap_total (Global mob cap) int 500 0 2048 mcl_mob_cap_total (Global mob cap) int 500 0 2048
@ -124,8 +130,11 @@ mcl_mob_cap_player (Mob cap per player) int 75 0 2048
#Maximum amount of monsters that will spawn near a player (default:70) #Maximum amount of monsters that will spawn near a player (default:70)
mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048 mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048
#Maximum amount of animals that will spawn near a player (default:10) #Maximum amount of animals that will spawn near a player (default:13)
mcl_mob_cap_animal (Mob cap animals) int 10 0 1024 mcl_mob_cap_animal (Mob cap animals) int 13 0 1024
#Maximum amount of water mobs that will spawn near a player (default:8)
mcl_mob_cap_water (Mob cap water) int 8 0 1024
#Maximum amount of ambient mobs that will spawn near a player (default:15) #Maximum amount of ambient mobs that will spawn near a player (default:15)
mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024 mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024