diff --git a/mobs/init.lua b/mobs/init.lua new file mode 100644 index 0000000..f63fb16 --- /dev/null +++ b/mobs/init.lua @@ -0,0 +1,19 @@ + +local path = minetest.get_modpath("mobs") + +-- Mob API +dofile(path .. "/api.lua") + +-- Rideable Mobs +dofile(path .. "/mount.lua") + +-- Mob Items +dofile(path .. "/crafts.lua") + +-- Mob Spawner +dofile(path .. "/spawner.lua") + +-- Lucky Blocks +dofile(path .. "/lucky_block.lua") + +minetest.log("action", "[MOD] Mobs Redo loaded") diff --git a/mobs/intllib.lua b/mobs/intllib.lua new file mode 100644 index 0000000..6669d72 --- /dev/null +++ b/mobs/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/mobs/license.txt b/mobs/license.txt new file mode 100644 index 0000000..fec6f6a --- /dev/null +++ b/mobs/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TenPlus1 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/mobs/lucky_block.lua b/mobs/lucky_block.lua new file mode 100644 index 0000000..ef7d59c --- /dev/null +++ b/mobs/lucky_block.lua @@ -0,0 +1,18 @@ + +if minetest.get_modpath("lucky_block") then + + lucky_block:add_blocks({ + {"dro", {"mobs:meat_raw"}, 5}, + {"dro", {"mobs:meat"}, 5}, + {"dro", {"mobs:nametag"}, 1}, + {"dro", {"mobs:leather"}, 5}, + {"dro", {"default:stick"}, 10}, + {"dro", {"mobs:net"}, 1}, + {"dro", {"mobs:lasso"}, 1}, + {"dro", {"mobs:shears"}, 1}, + {"dro", {"mobs:protector"}, 1}, + {"dro", {"mobs:fence_wood"}, 10}, + {"dro", {"mobs:fence_top"}, 12}, + {"lig"}, + }) +end diff --git a/mobs/spawner.lua b/mobs/spawner.lua new file mode 100644 index 0000000..16e0d11 --- /dev/null +++ b/mobs/spawner.lua @@ -0,0 +1,179 @@ + +local S = mobs.intllib + +-- mob spawner + +local spawner_default = "mobs_animal:pumba 10 15 0 0" + +minetest.register_node("mobs:spawner", { + tiles = {"mob_spawner.png"}, + drawtype = "glasslike", + paramtype = "light", + walkable = true, + description = S("Mob Spawner"), + groups = {cracky = 1}, + + on_construct = function(pos) + + local meta = minetest.get_meta(pos) + + -- text entry formspec + meta:set_string("formspec", + "field[text;" .. S("Mob MinLight MaxLight Amount PlayerDist") .. ";${command}]") + meta:set_string("infotext", S("Spawner Not Active (enter settings)")) + meta:set_string("command", spawner_default) + end, + + on_right_click = function(pos, placer) + + if minetest.is_protected(pos, placer:get_player_name()) then + return + end + end, + + on_receive_fields = function(pos, formname, fields, sender) + + if not fields.text or fields.text == "" then + return + end + + local meta = minetest.get_meta(pos) + local comm = fields.text:split(" ") + local name = sender:get_player_name() + + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return + end + + local mob = comm[1] -- mob to spawn + local mlig = tonumber(comm[2]) -- min light + local xlig = tonumber(comm[3]) -- max light + local num = tonumber(comm[4]) -- total mobs in area + local pla = tonumber(comm[5]) -- player distance (0 to disable) + local yof = tonumber(comm[6]) or 0 -- Y offset to spawn mob + + if mob and mob ~= "" and mobs.spawning_mobs[mob] == true + and num and num >= 0 and num <= 10 + and mlig and mlig >= 0 and mlig <= 15 + and xlig and xlig >= 0 and xlig <= 15 + and pla and pla >=0 and pla <= 20 + and yof and yof > -10 and yof < 10 then + + meta:set_string("command", fields.text) + meta:set_string("infotext", S("Spawner Active (@1)", mob)) + + else + minetest.chat_send_player(name, S("Mob Spawner settings failed!")) + minetest.chat_send_player(name, + 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]”")) + end + end, +}) + + +local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 99) + +-- spawner abm +minetest.register_abm({ + label = "Mob spawner node", + nodenames = {"mobs:spawner"}, + interval = 10, + chance = 4, + catch_up = false, + + action = function(pos, node, active_object_count, active_object_count_wider) + + -- return if too many entities already + if active_object_count_wider >= max_per_block then + return + end + + -- get meta and command + local meta = minetest.get_meta(pos) + local comm = meta:get_string("command"):split(" ") + + -- get settings from command + local mob = comm[1] + local mlig = tonumber(comm[2]) + local xlig = tonumber(comm[3]) + local num = tonumber(comm[4]) + local pla = tonumber(comm[5]) or 0 + local yof = tonumber(comm[6]) or 0 + + -- if amount is 0 then do nothing + if num == 0 then + return + end + + -- are we spawning a registered mob? + if not mobs.spawning_mobs[mob] then + --print ("--- mob doesn't exist", mob) + return + end + + -- check objects inside 9x9 area around spawner + local objs = minetest.get_objects_inside_radius(pos, 9) + local count = 0 + local ent = nil + + -- count mob objects of same type in area + for k, obj in ipairs(objs) do + + ent = obj:get_luaentity() + + if ent and ent.name and ent.name == mob then + count = count + 1 + end + end + + -- is there too many of same type? + if count >= num then + return + end + + -- spawn mob if player detected and in range + if pla > 0 then + + local in_range = 0 + local objs = minetest.get_objects_inside_radius(pos, pla) + + for _,oir in pairs(objs) do + + if oir:is_player() then + + in_range = 1 + + break + end + end + + -- player not found + if in_range == 0 then + return + end + end + + -- find air blocks within 5 nodes of spawner + local air = minetest.find_nodes_in_area( + {x = pos.x - 5, y = pos.y + yof, z = pos.z - 5}, + {x = pos.x + 5, y = pos.y + yof, z = pos.z + 5}, + {"air"}) + + -- spawn in random air block + if air and #air > 0 then + + local pos2 = air[math.random(#air)] + local lig = minetest.get_node_light(pos2) or 0 + + pos2.y = pos2.y + 0.5 + + -- only if light levels are within range + if lig >= mlig and lig <= xlig + and minetest.registered_entities[mob] then + minetest.add_entity(pos2, mob) + end + end + + end +})