2 local MP
= minetest
.get_modpath(minetest
.get_current_modname())
3 local S
= minetest
.get_translator("mobs")
7 local spawner_default
= "mobs_hades:mutant 0 15 0 0"
9 minetest
.register_node("mobs:spawner", {
10 tiles
= {"mob_spawner.png"},
11 drawtype
= "glasslike",
14 description
= S("Mob Spawner"),
15 _tt_help
= S("Periodically spawns mobs around it"),
16 groups
= {cracky
= 1},
18 on_construct
= function(pos
)
20 local meta
= minetest
.get_meta(pos
)
22 -- text entry formspec
23 meta
:set_string("formspec",
24 "field[text;" .. minetest
.formspec_escape(S("Mob MinLight MaxLight Amount PlayerDist")) .. ";${command}]")
25 meta
:set_string("infotext", S("Spawner Not Active (enter settings)"))
26 meta
:set_string("command", spawner_default
)
29 on_right_click
= function(pos
, placer
)
31 if minetest
.is_protected(pos
, placer
:get_player_name()) then
36 on_receive_fields
= function(pos
, formname
, fields
, sender
)
38 if not fields
.text
or fields
.text
== "" then
42 local meta
= minetest
.get_meta(pos
)
43 local comm
= fields
.text
:split(" ")
44 local name
= sender
:get_player_name()
46 if minetest
.is_protected(pos
, name
) then
47 minetest
.record_protection_violation(pos
, name
)
51 local mob
= comm
[1] -- mob to spawn
52 local mlig
= tonumber(comm
[2]) -- min light
53 local xlig
= tonumber(comm
[3]) -- max light
54 local num
= tonumber(comm
[4]) -- total mobs in area
55 local pla
= tonumber(comm
[5]) -- player distance (0 to disable)
56 local yof
= tonumber(comm
[6]) or 0 -- Y offset to spawn mob
58 if mob
and mob
~= "" and mobs
.spawning_mobs
[mob
] == true
59 and num
and num
>= 0 and num
<= 10
60 and mlig
and mlig
>= 0 and mlig
<= 15
61 and xlig
and xlig
>= 0 and xlig
<= 15
62 and pla
and pla
>=0 and pla
<= 20
63 and yof
and yof
> -10 and yof
< 10 then
65 meta
:set_string("command", fields
.text
)
66 meta
:set_string("infotext", S("Spawner Active (@1)", mob
))
69 minetest
.chat_send_player(name
, S("Mob Spawner settings failed!"))
70 minetest
.chat_send_player(name
,
71 S("Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] distance[1-20] y_offset[-10 to 10]”"))
77 local max_per_block
= tonumber(minetest
.settings
:get("max_objects_per_block") or 99)
80 minetest
.register_abm({
81 label
= "Mob spawner node",
82 nodenames
= {"mobs:spawner"},
87 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
89 -- return if too many entities already
90 if active_object_count_wider
>= max_per_block
then
94 -- get meta and command
95 local meta
= minetest
.get_meta(pos
)
96 local comm
= meta
:get_string("command"):split(" ")
98 -- get settings from command
100 local mlig
= tonumber(comm
[2])
101 local xlig
= tonumber(comm
[3])
102 local num
= tonumber(comm
[4])
103 local pla
= tonumber(comm
[5]) or 0
104 local yof
= tonumber(comm
[6]) or 0
106 -- if amount is 0 then do nothing
111 -- are we spawning a registered mob?
112 if not mobs
.spawning_mobs
[mob
] then
113 --print ("--- mob doesn't exist", mob)
117 -- check objects inside 9x9 area around spawner
118 local objs
= minetest
.get_objects_inside_radius(pos
, 9)
122 -- count mob objects of same type in area
123 for k
, obj
in ipairs(objs
) do
125 ent
= obj
:get_luaentity()
127 if ent
and ent
.name
and ent
.name
== mob
then
132 -- is there too many of same type?
137 -- spawn mob if player detected and in range
141 local objs
= minetest
.get_objects_inside_radius(pos
, pla
)
143 for _
,oir
in pairs(objs
) do
145 if oir
:is_player() then
154 if in_range
== 0 then
159 -- find air blocks within 5 nodes of spawner
160 local air
= minetest
.find_nodes_in_area(
161 {x
= pos
.x
- 5, y
= pos
.y
+ yof
, z
= pos
.z
- 5},
162 {x
= pos
.x
+ 5, y
= pos
.y
+ yof
, z
= pos
.z
+ 5},
165 -- spawn in random air block
166 if air
and #air
> 0 then
168 local pos2
= air
[math
.random(#air
)]
169 local lig
= minetest
.get_node_light(pos2
) or 0
171 pos2
.y
= pos2
.y
+ 0.5
173 -- only if light levels are within range
174 if lig
>= mlig
and lig
<= xlig
175 and minetest
.registered_entities
[mob
] then
176 minetest
.add_entity(pos2
, mob
)