diff --git a/.gitignore b/.gitignore index 8228ba34a..574521980 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.blend1 *.blend2 *.blend3 +/.idea/ diff --git a/CREDITS.md b/CREDITS.md index 63cd24155..b258ca54b 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -33,6 +33,9 @@ * RandomLegoBrick * SumianVoice * MrRar +* talamh +* Faerraven +* AncientMariner ## Contributors * Laurent Rocher @@ -66,7 +69,6 @@ * Benjamin Schötz * Doloment * Sydney Gems -* talamh * Emily2255 * Emojigit * FinishedFragment @@ -85,6 +87,14 @@ * opfromthestart * snowyu * FaceDeer +* Faerraven / Michieal +* FossFanatic +* Herbert West +* GuyLiner +* 3raven +* anarquimico +* TheOnlyJoeEnderman +* Ranko Saotome ## MineClone5 * kay27 @@ -95,7 +105,7 @@ * chmodsayshello * 3raven * PrairieWind -* Gustavo1 +* Gustavo6046 / wallabra * CableGuy67 * MrRar @@ -154,6 +164,7 @@ * MysticTempest * RandomLegoBrick * cora +* Faerraven / Michieal ## Translations * Wuzzy diff --git a/README.md b/README.md index 044764661..5d9ca077d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils. Developed by many people. Not developed or endorsed by Mojang AB. -Version: 0.79 +Version: 0.82 (in development) ### Gameplay You start in a randomly-generated world made entirely of cubes. You can explore diff --git a/game.conf b/game.conf index 9f54e5159..1fa1d6671 100644 --- a/game.conf +++ b/game.conf @@ -1,2 +1,4 @@ title = MineClone 2 description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more. +disallowed_mapgens = v6 +version=MCL2-0.82-indev \ No newline at end of file diff --git a/mods/CORE/mcl_attached/init.lua b/mods/CORE/mcl_attached/init.lua index c4a7a3337..2013dbde2 100644 --- a/mods/CORE/mcl_attached/init.lua +++ b/mods/CORE/mcl_attached/init.lua @@ -5,6 +5,8 @@ -- Nodes in group "supported_node" can be placed on any node that does not -- have the "airlike" drawtype. Carpets are an example of this type. +local pairs = pairs +local math = math local vector = vector local facedir_to_dir = minetest.facedir_to_dir @@ -22,15 +24,17 @@ local add_item = minetest.add_item -- We need this to do the exact same dropping node handling in our override -- minetest.check_single_for_falling() function as in the builtin function. -- +---@param p Vector local function drop_attached_node(p) local n = get_node(p) local drops = get_node_drops(n, "") local def = registered_nodes[n.name] + if def and def.preserve_metadata then local oldmeta = get_meta(p):to_table().fields -- Copy pos and node because the callback can modify them. - local pos_copy = vector.new(p) - local node_copy = {name=n.name, param1=n.param1, param2=n.param2} + local pos_copy = vector.copy(p) + local node_copy = { name = n.name, param1 = n.param1, param2 = n.param2 } local drop_stacks = {} for k, v in pairs(drops) do drop_stacks[k] = ItemStack(v) @@ -38,16 +42,18 @@ local function drop_attached_node(p) drops = drop_stacks def.preserve_metadata(pos_copy, node_copy, oldmeta, drops) end + if def and def.sounds and def.sounds.fall then - core.sound_play(def.sounds.fall, {pos = p}, true) + minetest.sound_play(def.sounds.fall, { pos = p }, true) end + remove_node(p) for _, item in pairs(drops) do - local pos = { - x = p.x + math.random()/2 - 0.25, - y = p.y + math.random()/2 - 0.25, - z = p.z + math.random()/2 - 0.25, - } + local pos = vector.offset(p, + math.random() / 2 - 0.25, + math.random() / 2 - 0.25, + math.random() / 2 - 0.25 + ) add_item(pos, item) end end @@ -90,4 +96,3 @@ function minetest.check_single_for_falling(pos) return false end - diff --git a/mods/CORE/mcl_damage/init.lua b/mods/CORE/mcl_damage/init.lua index 740ac2b65..773e7a43e 100644 --- a/mods/CORE/mcl_damage/init.lua +++ b/mods/CORE/mcl_damage/init.lua @@ -12,6 +12,7 @@ mcl_damage = { drown = {bypasses_armor = true}, starve = {bypasses_armor = true, bypasses_magic = true}, cactus = {}, + sweet_berry = {}, fall = {bypasses_armor = true}, fly_into_wall = {bypasses_armor = true}, -- unused out_of_world = {bypasses_armor = true, bypasses_magic = true, bypasses_invulnerability = true, bypasses_totem = true}, @@ -33,6 +34,8 @@ mcl_damage = { } } +local damage_enabled = minetest.settings:get_bool("enabled_damage",true) + function mcl_damage.register_modifier(func, priority) table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0}) end @@ -139,6 +142,7 @@ function mcl_damage.register_type(name, def) end minetest.register_on_player_hpchange(function(player, hp_change, mt_reason) + if not damage_enabled then return 0 end if hp_change < 0 then if player:get_hp() <= 0 then return 0 @@ -149,6 +153,7 @@ minetest.register_on_player_hpchange(function(player, hp_change, mt_reason) end, true) minetest.register_on_player_hpchange(function(player, hp_change, mt_reason) + if not damage_enabled then return 0 end if player:get_hp() > 0 then mt_reason.approved = true if hp_change < 0 then diff --git a/mods/CORE/mcl_events/API.md b/mods/CORE/mcl_events/API.md new file mode 100644 index 000000000..c94328e50 --- /dev/null +++ b/mods/CORE/mcl_events/API.md @@ -0,0 +1,27 @@ +## mcl_events +### Registering Events + `mlc_events.register_event("name",def)` + +#### Event Definition + { + stage = 0, + max_stage = 1, + percent = 100, + bars = {}, + completed = false, + cond_start = function() end, + --return table of paramtables e.g. { { player = playername, pos = position, ... } }, custom parameters will be passed to the event object/table + on_step = function(event) end, + --this function is run every game step when the event is active + on_start = function(event) end, + -- this function is run when the event starts + on_stage_begin = function(event) end, + -- this function runs when a new stage of the event starts + cond_progress = function(event) end, --return false or next stage id + --this function checks if the event should progress to the next (or any other) stage + cond_complete = function(event) end, + --return true if event finished successfully +} + +### Debugging + * /event_start -- starts the given event at the current player coordinates diff --git a/mods/CORE/mcl_events/init.lua b/mods/CORE/mcl_events/init.lua new file mode 100644 index 000000000..5ec2577a9 --- /dev/null +++ b/mods/CORE/mcl_events/init.lua @@ -0,0 +1,151 @@ +mcl_events = {} +mcl_events.registered_events = {} +local disabled_events = minetest.settings:get("mcl_disabled_events") +if disabled_events then disabled_events = disabled_events:split(",") +else disabled_events = {} end +local DBG = minetest.settings:get_bool("mcl_logging_event_api",false) +local active_events = {} + +local event_tpl = { + stage = 0, + max_stage = 1, + percent = 100, + bars = {}, + completed = false, + cond_start = function(event) end, --return table of positions + on_step = function(event) end, + on_start = function(event) end, + on_stage_begin = function(event) end, + cond_progress = function(event) end, --return next stage + cond_complete = function(event) end, --return success +} + +local function mcl_log(m,l) + if DBG then + if not l then l = "action" end + minetest.log(l,"[mcl_events] "..m) + end +end + +function mcl_events.register_event(name,def) + if table.indexof(disabled_events,name) ~= -1 then return end + mcl_events.registered_events[name] = def + mcl_events.registered_events[name].name = name +end + +local function addbars(self) + if not self.enable_bossbar then return end + for _,player in pairs(minetest.get_connected_players()) do + if vector.distance(self.pos,player:get_pos()) < 64 then + local bar = mcl_bossbars.add_bar(player, {color = "red", text = self.readable_name .. ": Wave "..self.stage.." / "..self.max_stage, percentage = self.percent }, true,1) + table.insert(self.bars,bar) + end + end +end + +local function start_event(p,e) + mcl_log("[mcl_events] Event started: "..e.readable_name.." at "..minetest.pos_to_string(vector.round(p.pos))) + local idx = #active_events + 1 + active_events[idx] = table.copy(e) + setmetatable(active_events[idx],{__index = event_tpl}) + for k,v in pairs(p) do active_events[idx][k] = v end + active_events[idx].stage = 0 + active_events[idx].percent = 100 + active_events[idx].bars = {} + active_events[idx].time_start = os.time() + if active_events[idx].on_start then + active_events[idx]:on_start(p.pos) + end + addbars(active_events[idx]) +end + +local function finish_event(self,idx) + mcl_log("[mcl_events] Finished: "..self.readable_name.." at "..minetest.pos_to_string(vector.round(self.pos))) + if self.on_complete then self:on_complete() end + for _,b in pairs(self.bars) do + mcl_bossbars.remove_bar(b) + end + table.remove(active_events,idx) +end + +local etime = 0 +function check_events(dtime) + --process active events + for idx,ae in pairs(active_events) do + if ae.cond_complete and ae:cond_complete() then + ae.finished = true + finish_event(ae,idx) + elseif not ae.cond_complete and ae.max_stage and ae.max_stage <= ae.stage then + ae.finished = true + finish_event(ae,idx) + elseif not ae.finished and ae.cond_progress then + local p = ae:cond_progress() + if p == true then + ae.stage = ae.stage + 1 + if ae:on_stage_begin() == true then + mcl_log("[mcl_events] Event "..ae.readable_name.." at "..minetest.pos_to_string(vector.round(ae.pos)).." failed at stage_begin of stage "..ae.stage ) + active_events[idx] = nil + end + elseif tonumber(p) then + ae.stage = tonumber(p) or ae.stage + 1 + ae:on_stage_begin() + end + elseif not ae.finished and ae.on_step then + ae:on_step(dtime) + end + addbars(ae) + end + -- check if a new event should be started + etime = etime - dtime + if etime > 0 then return end + etime = 10 + for _,e in pairs(mcl_events.registered_events) do + local pp = e.cond_start() + if pp then + for _,p in pairs(pp) do + local start = true + if e.exclusive_to_area then + for _,ae in pairs(active_events) do + if e.name == ae.name and vector.distance(p.pos,ae.pos) < e.exclusive_to_area then start = false end + end + end + if start then + start_event(p,e) + elseif DBG then + mcl_log("[mcl_events] Event "..e.readable_name.." already active at "..minetest.pos_to_string(vector.round(p.pos))) + end + end + end + end + for idx,ae in pairs(active_events) do + local player_near = false + for _,pl in pairs(minetest.get_connected_players()) do + if ae.pos and vector.distance(pl:get_pos(),ae.pos) < 64 then player_near = true end + end + if ae.pos and not player_near then + mcl_log("[mcl_events] Event "..ae.readable_name.." at "..minetest.pos_to_string(vector.round(ae.pos)).." aborted - no players near." ) + active_events[idx] = nil + end + end +end + +minetest.register_globalstep(check_events) + +mcl_info.register_debug_field("Active Events",{ + level = 4, + func = function(pl,pos) + return tostring(#active_events) + end +}) + +minetest.register_chatcommand("event_start",{ + privs = {debug = true}, + description = "Debug command to start events", + func = function(pname,param) + local p = minetest.get_player_by_name(pname) + local evdef = mcl_events.registered_events[param] + if not evdef then return false,"Event "..param.." doesn't exist.'" end + start_event({pos=p:get_pos(),player=pname,factor=1},evdef) + return true,"Started event "..param + end, +}) diff --git a/mods/CORE/mcl_events/mod.conf b/mods/CORE/mcl_events/mod.conf new file mode 100644 index 000000000..29a45628a --- /dev/null +++ b/mods/CORE/mcl_events/mod.conf @@ -0,0 +1,3 @@ +name = mcl_events +author = cora +depends = mcl_mobs,mcl_bossbars, mcl_info diff --git a/mods/CORE/mcl_explosions/init.lua b/mods/CORE/mcl_explosions/init.lua index cb9af5c79..b67c7c6a2 100644 --- a/mods/CORE/mcl_explosions/init.lua +++ b/mods/CORE/mcl_explosions/init.lua @@ -130,10 +130,10 @@ local function add_particles(pos, radius) time = 0.125, minpos = pos, maxpos = pos, - minvel = {x = -radius, y = -radius, z = -radius}, - maxvel = {x = radius, y = radius, z = radius}, - minacc = vector.new(), - maxacc = vector.new(), + minvel = vector.new(-radius, -radius, -radius), + maxvel = vector.new(radius, radius, radius), + minacc = vector.zero(), + maxacc = vector.zero(), minexptime = 0.5, maxexptime = 1.0, minsize = radius * 0.5, @@ -207,7 +207,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc local npos_z = math.floor(rpos_z + 0.5) local npos = { x = npos_x, y = npos_y, z = npos_z } local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride + - npos_x - emin_x + 1 + npos_x - emin_x + 1 local cid = data[idx] local br = node_blastres[cid] or INDESTRUCT_BLASTRES @@ -288,7 +288,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc rdir_y = rdir_y / rdir_len rdir_z = rdir_z / rdir_len - for i=0, rdir_len / STEP_LENGTH do + for i = 0, rdir_len / STEP_LENGTH do rpos_x = rpos_x + rdir_x * STEP_LENGTH rpos_y = rpos_y + rdir_y * STEP_LENGTH rpos_z = rpos_z + rdir_z * STEP_LENGTH @@ -296,7 +296,7 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc local npos_y = math.floor(rpos_y + 0.5) local npos_z = math.floor(rpos_z + 0.5) local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride + - npos_x - emin_x + 1 + npos_x - emin_x + 1 local cid = data[idx] @@ -333,16 +333,17 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc end if sleep_formspec_doesnt_close_mt53 then - minetest.after(0.3, function() -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE - if not obj:is_player() then - return - end - mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source}) + minetest.after(0.3, + function() -- 0.2 is minimum delay for closing old formspec and open died formspec -- TODO: REMOVE THIS IN THE FUTURE + if not obj:is_player() then + return + end + mcl_util.deal_damage(obj, damage, { type = "explosion", direct = direct, source = source }) - obj:add_velocity(vector.multiply(punch_dir, impact * 20)) - end) + obj:add_velocity(vector.multiply(punch_dir, impact * 20)) + end) else - mcl_util.deal_damage(obj, damage, {type = "explosion", direct = direct, source = source}) + mcl_util.deal_damage(obj, damage, { type = "explosion", direct = direct, source = source }) if obj:is_player() or ent.tnt_knockback then obj:add_velocity(vector.multiply(punch_dir, impact * 20)) @@ -388,23 +389,24 @@ local function trace_explode(pos, strength, raydirs, radius, info, direct, sourc -- We use bulk_set_node instead of LVM because we want to have on_destruct and -- on_construct being called if #airs > 0 then - bulk_set_node(airs, {name="air"}) + bulk_set_node(airs, { name = "air" }) end if #fires > 0 then - bulk_set_node(fires, {name="mcl_fire:fire"}) + bulk_set_node(fires, { name = "mcl_fire:fire" }) end -- Update falling nodes - for a=1, #airs do + for a = 1, #airs do local p = airs[a] - check_for_falling({x=p.x, y=p.y+1, z=p.z}) + check_for_falling(vector.offset(p, 0, 1, 0)) end - for f=1, #fires do + for f = 1, #fires do local p = fires[f] - check_for_falling({x=p.x, y=p.y+1, z=p.z}) + check_for_falling(vector.offset(p, 0, 1, 0)) end -- Log explosion - minetest.log("action", "Explosion at "..pos_to_string(pos).." with strength "..strength.." and radius "..radius) + minetest.log("action", "Explosion at " .. pos_to_string(pos) .. " with strength " .. strength .. " and radius " .. + radius) end -- Create an explosion with strength at pos. @@ -428,6 +430,11 @@ end -- griefing - If true, the explosion will destroy nodes (default: true) -- grief_protected - If true, the explosion will also destroy nodes which have -- been protected (default: false) +---@param pos Vector +---@param strength number +---@param info {drop_chance: number, max_blast_resistance: number, sound: boolean, particles: boolean, fire: boolean, griefing: boolean, grief_protected: boolean} +---@param direct? ObjectRef +---@param source? ObjectRef function mcl_explosions.explode(pos, strength, info, direct, source) if info == nil then info = {} diff --git a/mods/CORE/mcl_init/init.lua b/mods/CORE/mcl_init/init.lua index 6773949b7..3acce957f 100644 --- a/mods/CORE/mcl_init/init.lua +++ b/mods/CORE/mcl_init/init.lua @@ -138,6 +138,7 @@ mcl_vars.mg_nether_min = -29067 -- Carefully chosen to be at a mapchunk border mcl_vars.mg_nether_max = mcl_vars.mg_nether_min + 128 mcl_vars.mg_bedrock_nether_bottom_min = mcl_vars.mg_nether_min mcl_vars.mg_bedrock_nether_top_max = mcl_vars.mg_nether_max +mcl_vars.mg_nether_deco_max = mcl_vars.mg_nether_max -11 -- this is so ceiling decorations don't spill into other biomes as bedrock generation calls minetest.generate_decorations to put netherrack under the bedrock if not superflat then mcl_vars.mg_bedrock_nether_bottom_max = mcl_vars.mg_bedrock_nether_bottom_min + 4 mcl_vars.mg_bedrock_nether_top_min = mcl_vars.mg_bedrock_nether_top_max - 4 diff --git a/mods/CORE/mcl_particles/textures/mcl_particles_soul_fire_flame.png b/mods/CORE/mcl_particles/textures/mcl_particles_soul_fire_flame.png new file mode 100644 index 000000000..94022a6c3 Binary files /dev/null and b/mods/CORE/mcl_particles/textures/mcl_particles_soul_fire_flame.png differ diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index a179d53e6..4684234e5 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -22,6 +22,29 @@ function table.update_nil(t, ...) return t end +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default",false) +local LOG_MODULE = "[MCL2]" +function mcl_util.mcl_log (message, module, bypass_default_logger) + local selected_module = LOG_MODULE + if module then + selected_module = module + end + if (bypass_default_logger or LOGGING_ON) and message then + minetest.log(selected_module .. " " .. message) + end +end + + +function mcl_util.file_exists(name) + if type(name) ~= "string" then return end + local f = io.open(name) + if not f then + return false + end + f:close() + return true +end + -- Based on minetest.rotate_and_place --[[ @@ -590,10 +613,12 @@ function mcl_util.get_object_name(object) end function mcl_util.replace_mob(obj, mob) + if not obj then return end local rot = obj:get_yaw() local pos = obj:get_pos() obj:remove() obj = minetest.add_entity(pos, mob) + if not obj then return end obj:set_yaw(rot) return obj end @@ -610,3 +635,96 @@ function mcl_util.get_pointed_thing(player, liquid) end end end + +-- This following part is 2 wrapper functions + helpers for +-- object:set_bones +-- and player:set_properties preventing them from being resent on +-- every globalstep when they have not changed. + +local function roundN(n, d) + if type(n) ~= "number" then return n end + local m = 10^d + return math.floor(n * m + 0.5) / m +end + +local function close_enough(a,b) + local rt=true + if type(a) == "table" and type(b) == "table" then + for k,v in pairs(a) do + if roundN(v,2) ~= roundN(b[k],2) then + rt=false + break + end + end + else + rt = roundN(a,2) == roundN(b,2) + end + return rt +end + +local function props_changed(props,oldprops) + local changed=false + local p={} + for k,v in pairs(props) do + if not close_enough(v,oldprops[k]) then + p[k]=v + changed=true + end + end + return changed,p +end + +--tests for roundN +local test_round1=15 +local test_round2=15.00199999999 +local test_round3=15.00111111 +local test_round4=15.00999999 + +assert(roundN(test_round1,2)==roundN(test_round1,2)) +assert(roundN(test_round1,2)==roundN(test_round2,2)) +assert(roundN(test_round1,2)==roundN(test_round3,2)) +assert(roundN(test_round1,2)~=roundN(test_round4,2)) + +-- tests for close_enough +local test_cb = {-0.35,0,-0.35,0.35,0.8,0.35} --collisionboxes +local test_cb_close = {-0.351213,0,-0.35,0.35,0.8,0.351212} +local test_cb_diff = {-0.35,0,-1.35,0.35,0.8,0.35} + +local test_eh = 1.65 --eye height +local test_eh_close = 1.65123123 +local test_eh_diff = 1.35 + +local test_nt = { r = 225, b = 225, a = 225, g = 225 } --nametag +local test_nt_diff = { r = 225, b = 225, a = 0, g = 225 } + +assert(close_enough(test_cb,test_cb_close)) +assert(not close_enough(test_cb,test_cb_diff)) +assert(close_enough(test_eh,test_eh_close)) +assert(not close_enough(test_eh,test_eh_diff)) +assert(not close_enough(test_nt,test_nt_diff)) --no floats involved here + +--tests for properties_changed +local test_properties_set1={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }} +local test_properties_set2={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 225, g = 225 }} + +local test_p1,_=props_changed(test_properties_set1,test_properties_set1) +local test_p2,_=props_changed(test_properties_set1,test_properties_set2) + +assert(not test_p1) +assert(test_p2) + +function mcl_util.set_properties(obj,props) + local changed,p=props_changed(props,obj:get_properties()) + if changed then + obj:set_properties(p) + end +end + +function mcl_util.set_bone_position(obj, bone, pos, rot) + local current_pos, current_rot = obj:get_bone_position(bone) + local pos_equal = not pos or vector.equals(vector.round(current_pos), vector.round(pos)) + local rot_equal = not rot or vector.equals(vector.round(current_rot), vector.round(rot)) + if not pos_equal or not rot_equal then + obj:set_bone_position(bone, pos or current_pos, rot or current_rot) + end +end diff --git a/mods/ENTITIES/mcl_boats/init.lua b/mods/ENTITIES/mcl_boats/init.lua index 0b2d67730..b4d98b1e2 100644 --- a/mods/ENTITIES/mcl_boats/init.lua +++ b/mods/ENTITIES/mcl_boats/init.lua @@ -56,7 +56,7 @@ end local function set_attach(boat) boat._driver:set_attach(boat.object, "", - {x = 0, y = 0.42, z = -1}, {x = 0, y = 0, z = 0}) + {x = 0, y = 1.5, z = 1}, {x = 0, y = 0, z = 0}) end local function set_double_attach(boat) @@ -65,9 +65,13 @@ local function set_double_attach(boat) boat._passenger:set_attach(boat.object, "", {x = 0, y = 0.42, z = -2.2}, {x = 0, y = 0, z = 0}) end +local function set_choat_attach(boat) + boat._driver:set_attach(boat.object, "", + {x = 0, y = 1.5, z = 1}, {x = 0, y = 0, z = 0}) +end local function attach_object(self, obj) - if self._driver then + if self._driver and not self._inv_id then if self._driver:is_player() then self._passenger = obj else @@ -77,7 +81,11 @@ local function attach_object(self, obj) set_double_attach(self) else self._driver = obj - set_attach(self) + if self._inv_id then + set_choat_attach(self) + else + set_attach(self) + end end local visual_size = get_visual_size(obj) @@ -101,6 +109,7 @@ local function attach_object(self, obj) end local function detach_object(obj, change_pos) + if not obj or not obj:get_pos() then return end obj:set_detach() obj:set_properties({visual_size = get_visual_size(obj)}) if obj:is_player() then @@ -123,11 +132,11 @@ local boat = { pointable = true, -- Warning: Do not change the position of the collisionbox top surface, -- lowering it causes the boat to fall through the world if underwater - collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5}, - selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.3, 0.7}, + collisionbox = {-0.5, -0.15, -0.5, 0.5, 0.55, 0.5}, + selectionbox = {-0.7, -0.15, -0.7, 0.7, 0.55, 0.7}, visual = "mesh", mesh = "mcl_boats_boat.b3d", - textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"}, + textures = { "mcl_boats_texture_oak_boat.png", "blank.png" }, visual_size = boat_visual_size, hp_max = boat_max_hp, damage_texture_modifier = "^[colorize:white:0", @@ -138,7 +147,7 @@ local boat = { _last_v = 0, -- Temporary speed variable _removed = false, -- If true, boat entity is considered removed (e.g. after punch) and should be ignored _itemstring = "mcl_boats:boat", -- Itemstring of the boat item (implies boat type) - _animation = 0, -- 0: not animated; 1: paddling forwards; -1: paddling forwards + _animation = 0, -- 0: not animated; 1: paddling forwards; -1: paddling backwards _regen_timer = 0, _damage_anim = 0, } @@ -161,8 +170,14 @@ function boat.on_activate(self, staticdata, dtime_s) self._last_v = self._v self._itemstring = data.itemstring - while #data.textures < 5 do - table.insert(data.textures, data.textures[1]) + -- Update the texutes for existing old boat entity instances. + -- Maybe remove this in the future. + if #data.textures ~= 2 then + local has_chest = self._itemstring:find("chest") + data.textures = { + data.textures[1]:gsub("_chest", ""), + has_chest and "mcl_chests_normal.png" or "blank.png" + } end self.object:set_properties({textures = data.textures}) @@ -413,13 +428,18 @@ end -- Register one entity for all boat types minetest.register_entity("mcl_boats:boat", boat) -local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian" } -local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat") } -local craftstuffs = {} -if minetest.get_modpath("mcl_core") then - craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian" } -end -local images = { "oak", "spruce", "birch", "jungle", "acacia", "dark_oak", "obsidian" } +local cboat = table.copy(boat) +cboat.textures = { "mcl_boats_texture_oak_chest_boat.png", "mcl_chests_normal.png" } +cboat._itemstring = "mcl_boats:chest_boat" +cboat.collisionbox = {-0.5, -0.15, -0.5, 0.5, 0.75, 0.5} +cboat.selectionbox = {-0.7, -0.15, -0.7, 0.7, 0.75, 0.7} + +minetest.register_entity("mcl_boats:chest_boat", cboat) +mcl_entity_invs.register_inv("mcl_boats:chest_boat","Boat",27) + +local boat_ids = { "boat", "boat_spruce", "boat_birch", "boat_jungle", "boat_acacia", "boat_dark_oak", "boat_obsidian", "boat_mangrove", "chest_boat", "chest_boat_spruce", "chest_boat_birch", "chest_boat_jungle", "chest_boat_acacia", "chest_boat_dark_oak", "chest_boat_mangrove" } +local names = { S("Oak Boat"), S("Spruce Boat"), S("Birch Boat"), S("Jungle Boat"), S("Acacia Boat"), S("Dark Oak Boat"), S("Obsidian Boat"), S("Mangrove Boat"), S("Oak Chest Boat"), S("Spruce Chest Boat"), S("Birch Chest Boat"), S("Jungle Chest Boat"), S("Acacia Chest Boat"), S("Dark Oak Chest Boat"), S("Mangrove Chest Boat") } +local craftstuffs = { "mcl_core:wood", "mcl_core:sprucewood", "mcl_core:birchwood", "mcl_core:junglewood", "mcl_core:acaciawood", "mcl_core:darkwood", "mcl_core:obsidian", "mcl_mangrove:mangrove_wood" } for b=1, #boat_ids do local itemstring = "mcl_boats:"..boat_ids[b] @@ -435,6 +455,21 @@ for b=1, #boat_ids do end tt_help = S("Water vehicle") + local inventory_image + local texture + local id = boat_ids[b] + if id:find("chest") then + if id == "chest_boat" then id = "oak" end + local id = id:gsub("chest_boat_", "") + inventory_image = "mcl_boats_" .. id .. "_chest_boat.png" + texture = "mcl_boats_texture_" .. id .. "_boat.png" + else + if id == "boat" then id = "oak" end + local id = id:gsub("boat_", "") + inventory_image = "mcl_boats_" .. id .. "_boat.png" + texture = "mcl_boats_texture_" .. id .. "_boat.png" + end + minetest.register_craftitem(itemstring, { description = names[b], _tt_help = tt_help, @@ -442,7 +477,7 @@ for b=1, #boat_ids do _doc_items_entry_name = helpname, _doc_items_longdesc = longdesc, _doc_items_usagehelp = usagehelp, - inventory_image = "mcl_boats_"..images[b].."_boat.png", + inventory_image = inventory_image, liquids_pointable = true, groups = { boat = 1, transport = 1}, stack_max = 1, @@ -469,10 +504,15 @@ for b=1, #boat_ids do else pos = vector.add(pos, vector.multiply(dir, boat_y_offset_ground)) end - local boat = minetest.add_entity(pos, "mcl_boats:boat") - local texture = "mcl_boats_texture_"..images[b].."_boat.png" + local boat_ent = "mcl_boats:boat" + local chest_tex = "blank.png" + if itemstring:find("chest") then + boat_ent = "mcl_boats:chest_boat" + chest_tex = "mcl_chests_normal.png" + end + local boat = minetest.add_entity(pos, boat_ent) boat:get_luaentity()._itemstring = itemstring - boat:set_properties({textures = { texture, texture, texture, texture, texture }}) + boat:set_properties({ textures = { texture, chest_tex } }) boat:set_yaw(placer:get_look_horizontal()) if not minetest.is_creative_enabled(placer:get_player_name()) then itemstack:take_item() @@ -492,13 +532,22 @@ for b=1, #boat_ids do }) local c = craftstuffs[b] - minetest.register_craft({ - output = itemstring, - recipe = { - {c, "", c}, - {c, c, c}, - }, - }) + if not itemstring:find("chest") then + minetest.register_craft({ + output = itemstring:gsub(":boat",":chest_boat"), + recipe = { + {"mcl_chests:chest"}, + {itemstring}, + }, + }) + minetest.register_craft({ + output = itemstring, + recipe = { + {c, "", c}, + {c, c, c}, + }, + }) + end end minetest.register_craft({ diff --git a/mods/ENTITIES/mcl_boats/mod.conf b/mods/ENTITIES/mcl_boats/mod.conf index 61463b6ec..fcbe3f2f6 100644 --- a/mods/ENTITIES/mcl_boats/mod.conf +++ b/mods/ENTITIES/mcl_boats/mod.conf @@ -1,7 +1,5 @@ name = mcl_boats author = PilzAdam description = Adds drivable boats. -depends = mcl_player, flowlib, mcl_title +depends = mcl_player, flowlib, mcl_title, mcl_entity_invs optional_depends = mcl_core, doc_identifier - - diff --git a/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d b/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d index 6c9c31469..344bb3e70 100644 Binary files a/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d and b/mods/ENTITIES/mcl_boats/models/mcl_boats_boat.b3d differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_acacia_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_acacia_chest_boat.png new file mode 100644 index 000000000..5fb44b766 Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_acacia_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_birch_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_birch_chest_boat.png new file mode 100644 index 000000000..c5671285f Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_birch_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_dark_oak_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_dark_oak_chest_boat.png new file mode 100644 index 000000000..28ab392da Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_dark_oak_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_jungle_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_jungle_chest_boat.png new file mode 100644 index 000000000..304fd771d Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_jungle_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_boat.png new file mode 100644 index 000000000..f1f0d2506 Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_chest_boat.png new file mode 100644 index 000000000..ec2acd07f Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_mangrove_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_oak_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_oak_chest_boat.png new file mode 100644 index 000000000..0c7c2e0e2 Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_oak_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_spruce_chest_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_spruce_chest_boat.png new file mode 100644 index 000000000..e7f043e56 Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_spruce_chest_boat.png differ diff --git a/mods/ENTITIES/mcl_boats/textures/mcl_boats_texture_mangrove_boat.png b/mods/ENTITIES/mcl_boats/textures/mcl_boats_texture_mangrove_boat.png new file mode 100644 index 000000000..435db3966 Binary files /dev/null and b/mods/ENTITIES/mcl_boats/textures/mcl_boats_texture_mangrove_boat.png differ diff --git a/mods/ENTITIES/mcl_burning/api.lua b/mods/ENTITIES/mcl_burning/api.lua index 1d07e96f0..df0953398 100644 --- a/mods/ENTITIES/mcl_burning/api.lua +++ b/mods/ENTITIES/mcl_burning/api.lua @@ -1,3 +1,5 @@ +local enable_damage = minetest.settings:get_bool("enable_damage") + function mcl_burning.get_storage(obj) return obj:is_player() and mcl_burning.storage[obj] or obj:get_luaentity() end @@ -77,7 +79,7 @@ end -- The effective burn duration is modified by obj's armor protection. -- If obj was already burning, its burn duration is updated if the current -- duration is less than burn_time. --- If obj is dead, fireproof or a creative player, this function does nothing. +-- If obj is dead, fireproof or enable_damage is disabled, this function does nothing. -- function mcl_burning.set_on_fire(obj, burn_time) if obj:get_hp() < 0 then @@ -89,8 +91,9 @@ function mcl_burning.set_on_fire(obj, burn_time) return end - if obj:is_player() and minetest.is_creative_enabled(obj:get_player_name()) then + if obj:is_player() and not enable_damage then burn_time = 0 + return else local max_fire_prot_lvl = 0 local inv = mcl_util.get_inventory(obj) diff --git a/mods/ENTITIES/mcl_dripping/README.md b/mods/ENTITIES/mcl_dripping/README.md new file mode 100644 index 000000000..d6ff75ff1 --- /dev/null +++ b/mods/ENTITIES/mcl_dripping/README.md @@ -0,0 +1,36 @@ +# mcl_dripping + +Dripping Mod by kddekadenz, modified for MineClone 2 by Wuzzy, NO11 and AFCM + +## Manual + +- drops are generated rarely under solid nodes +- they will stay some time at the generated block and than they fall down +- when they collide with the ground, a sound is played and they are destroyed + +Water and Lava have builtin drops registered. + +## License + +code & sounds: CC0 + +## API + +```lua +mcl_dripping.register_drop({ + -- The group the liquid's nodes belong to + liquid = "water", + -- The texture used (particles will take a random 2x2 area of it) + texture = "default_water_source_animated.png", + -- Define particle glow, ranges from `0` to `minetest.LIGHT_MAX` + light = 1, + -- The nodes (or node group) the particles will spawn under + nodes = { "group:opaque", "group:leaves" }, + -- The sound that will be played then the particle detaches from the roof, see SimpleSoundSpec in lua_api.txt + sound = "drippingwater_drip", + -- The interval for the ABM to run + interval = 60, + -- The chance of the ABM + chance = 10, +}) +``` diff --git a/mods/ENTITIES/mcl_dripping/init.lua b/mods/ENTITIES/mcl_dripping/init.lua index 0a5b3d08c..b5a5043b7 100644 --- a/mods/ENTITIES/mcl_dripping/init.lua +++ b/mods/ENTITIES/mcl_dripping/init.lua @@ -3,53 +3,99 @@ -- License of code, textures & sounds: CC0 local math = math -local function make_drop(pos,liquid,sound,interval) + +mcl_dripping = {} + + +---@param pos Vector +---@param liquid string +---@param sound SimpleSoundSpec +---@param interval integer +---@param texture string +local function make_drop(pos, liquid, sound, interval, texture) local pt = { - velocity = vector.new(0,0,0), + velocity = vector.zero(), collision_removal = false, } + local t = math.random() + math.random(1, interval) - minetest.after(t,function() + + minetest.after(t, function() local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100 - pt.pos = vector.offset(pos,x,-0.52,z) - pt.acceleration = vector.new(0,0,0) + + pt.pos = vector.offset(pos, x, -0.52, z) + pt.acceleration = vector.zero() pt.collisiondetection = false pt.expirationtime = t - pt.texture="[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png" + pt.texture = "[combine:2x2:" .. + -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=" .. texture + minetest.add_particle(pt) - minetest.after(t,function() - pt.acceleration = vector.new(0,-5,0) + + minetest.after(t, function() + pt.acceleration = vector.new(0, -5, 0) pt.collisiondetection = true - pt.expirationtime = math.random() + math.random(1, interval/2) + pt.expirationtime = math.random() + math.random(1, interval / 2) + minetest.add_particle(pt) - minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = pos, gain = 0.5, max_hear_distance = 8}, true) + + minetest.sound_play(sound, { pos = pos, gain = 0.5, max_hear_distance = 8 }, + true) end) end) end -local function register_drop(liquid, glow, sound, nodes, interval, chance) +---@class mcl_dripping_drop_definition +---@field liquid string The group the liquid's nodes belong to +---@field texture string The texture used (particles will take a random 2x2 area of it) +---@field light integer Define particle glow, ranges from `0` to `minetest.LIGHT_MAX` +---@field nodes string[] The nodes (or node group) the particles will spawn under +---@field interval integer The interval for the ABM to run +---@field chance integer The chance of the ABM +---@field sound SimpleSoundSpec The sound that will be played then the particle detaches from the roof + +---@param def mcl_dripping_drop_definition +function mcl_dripping.register_drop(def) minetest.register_abm({ label = "Create drops", - nodenames = nodes, - neighbors = {"group:" .. liquid}, - interval = interval, - chance = chance, + nodenames = def.nodes, + neighbors = { "group:" .. def.liquid }, + interval = def.interval, + chance = def.chance, action = function(pos) - local r = math.ceil(interval / 20) - local nn=minetest.find_nodes_in_area(vector.offset(pos,-r,0,-r),vector.offset(pos,r,0,r),nodes) + local below = minetest.get_node(vector.offset(pos,0,-1,0)).name + if below ~= "air" then return end + local r = math.ceil(def.interval / 20) + local nn = minetest.find_nodes_in_area(vector.offset(pos, -r, 0, -r), vector.offset(pos, r, 0, r), def.nodes) --start a bunch of particle cycles to be able to get away --with longer abm cycles table.shuffle(nn) - for i=1,math.random(#nn) do - if minetest.get_item_group(minetest.get_node(vector.offset(nn[i], 0, 1, 0)).name, liquid) ~= 0 - and minetest.get_node(vector.offset(nn[i], 0, -1, 0)).name == "air" then - make_drop(nn[i],liquid,sound,interval) + for i = 1, math.random(#nn) do + if minetest.get_item_group(minetest.get_node(vector.offset(nn[i], 0, 1, 0)).name, def.liquid) ~= 0 then + make_drop(nn[i], def.liquid, def.sound, def.interval, def.texture) end end end, }) end -register_drop("water", 1, "", {"group:opaque", "group:leaves"},60,10) -register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"},60,10) +mcl_dripping.register_drop({ + liquid = "water", + texture = "default_water_source_animated.png", + light = 1, + nodes = { "group:opaque", "group:leaves" }, + sound = "drippingwater_drip", + interval = 60.3, + chance = 10, +}) + +mcl_dripping.register_drop({ + liquid = "lava", + texture = "default_lava_source_animated.png", + light = math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), + nodes = { "group:opaque" }, + sound = "drippingwater_lavadrip", + interval = 110.1, + chance = 10, +}) diff --git a/mods/ENTITIES/mcl_dripping/readme.txt b/mods/ENTITIES/mcl_dripping/readme.txt deleted file mode 100644 index afe35608e..000000000 --- a/mods/ENTITIES/mcl_dripping/readme.txt +++ /dev/null @@ -1,29 +0,0 @@ -Dripping Mod -by kddekadenz - -modified for MineClone 2 by Wuzzy and NO11 - - -Installing instructions: - - 1. Copy the mcl_dripping mod folder into games/gamemode/mods - - 2. Start game and enjoy :) - - -Manual: - --> drops are generated rarely under solid nodes --> they will stay some time at the generated block and than they fall down --> when they collide with the ground, a sound is played and they are destroyed - - -License: - -code & sounds: CC0 - - -Changelog: - -16.04.2012 - first release -28.04.2012 - drops are now 3D; added lava drops; fixed generating of drops (not at edges now) diff --git a/mods/ENTITIES/mcl_entity_invs/api.txt b/mods/ENTITIES/mcl_entity_invs/api.txt new file mode 100644 index 000000000..98cee1a23 --- /dev/null +++ b/mods/ENTITIES/mcl_entity_invs/api.txt @@ -0,0 +1,13 @@ +mcl_entity_invs +=============== + +Inventories for your entities. It's simple. Depend on mcl_entity_invs and register your entity like so: + +* mcl_entity_invs.register_inv("entity:name","Title shown in formspec",inventory_size,disable_on_righclick) + *If disable_on_righclick is true other mods can handle when to show the inventory themselves + * The inventory size can be set dynamically by initializing it with an explicit nil + +* mcl_entity_invs.show_inv_form(entity,clicker,[formspec text]) + * formspec_text is an additional text that is put after the title + +It works by setting up a detached inventory per entity which is accessed by an id/hash generated from the entities position at creation, the progressed gametime at creation and a random salt. diff --git a/mods/ENTITIES/mcl_entity_invs/init.lua b/mods/ENTITIES/mcl_entity_invs/init.lua new file mode 100644 index 000000000..35af491e1 --- /dev/null +++ b/mods/ENTITIES/mcl_entity_invs/init.lua @@ -0,0 +1,210 @@ +mcl_entity_invs = {} + +local open_invs = {} + +local function mcl_log (message) + mcl_util.mcl_log (message, "[Entity Invs]") +end + +local function check_distance(inv,player,count) + for _,o in pairs(minetest.get_objects_inside_radius(player:get_pos(),5)) do + local l = o:get_luaentity() + if l and l._inv_id and inv:get_location().name == l._inv_id then return count end + end + return 0 +end + +local inv_callbacks = { + allow_take = function(inv, listname, index, stack, player) + return check_distance(inv,player,stack:get_count()) + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return check_distance(inv,player,count) + end, + allow_put = function(inv, listname, index, stack, player) + return check_distance(inv,player,stack:get_count()) + end, +} + +function mcl_entity_invs.load_inv(ent,size) + mcl_log("load_inv") + if not ent._inv_id then return end + mcl_log("load_inv 2") + local inv = minetest.get_inventory({type="detached", name=ent._inv_id}) + if not inv then + mcl_log("load_inv 3") + inv = minetest.create_detached_inventory(ent._inv_id, inv_callbacks) + inv:set_size("main", size) + if ent._items then + inv:set_list("main",ent._items) + end + else + mcl_log("load_inv 4") + end + return inv +end + +function mcl_entity_invs.save_inv(ent) + if ent._inv then + ent._items = {} + for i,it in ipairs(ent._inv:get_list("main")) do + ent._items[i] = it:to_string() + end + minetest.remove_detached_inventory(ent._inv_id) + ent._inv = nil + end +end + +local function load_default_formspec (ent, text) + text = text or "" + + local invent_size = ent._inv_size + local div_by_two = invent_size % 2 == 0 + local div_by_three = invent_size % 3 == 0 + + --mcl_log("Div by 3: ".. tostring(div_by_three)) + --mcl_log("Div by 2: ".. tostring(div_by_two)) + --mcl_log("invent_size: ".. tostring(invent_size)) + local rows = 3 + if invent_size > 18 or (div_by_three == true and invent_size > 8) then + --mcl_log("Div by 3") + rows = 3 + elseif (div_by_two == true and invent_size > 3) or invent_size > 9 then + --mcl_log("Div by 2") + rows = 2 + else + --mcl_log("Not div by 2 or 3") + rows = 1 + end + + --local rows = 3 + local cols = (math.ceil(ent._inv_size/rows)) + local spacing = (9 - cols) / 2 + + local formspec = "size[9,8.75]" + .. "label[0,0;" .. minetest.formspec_escape( + minetest.colorize("#313131", ent._inv_title .. " ".. text)) .. "]" + .. "list[detached:"..ent._inv_id..";main;"..spacing..",0.5;"..cols..","..rows..";]" + .. mcl_formspec.get_itemslot_bg(spacing,0.5,cols,rows) + .. "label[0,4.0;" .. minetest.formspec_escape( + minetest.colorize("#313131", "Inventory")) .. "]" + .. "list[current_player;main;0,4.5;9,3;9]" + .. mcl_formspec.get_itemslot_bg(0,4.5,9,3) + .. "list[current_player;main;0,7.74;9,1;]" + .. mcl_formspec.get_itemslot_bg(0,7.74,9,1) + .. "listring[detached:"..ent._inv_id..";main]" + .. "listring[current_player;main]" + return formspec +end + + +function mcl_entity_invs.show_inv_form(ent,player,text) + if not ent._inv_id then return end + if not open_invs[ent] then + open_invs[ent] = 0 + end + ent._inv = mcl_entity_invs.load_inv(ent,ent._inv_size) + open_invs[ent] = open_invs[ent] + 1 + + local playername = player:get_player_name() + + minetest.show_formspec(playername, ent._inv_id, load_default_formspec (ent, text)) +end + +local function drop_inv(ent) + if not ent._items then return end + local pos = ent.object:get_pos() + for i,it in pairs(ent._items) do + local p = vector.add(pos,vector.new(math.random() - 0.5, math.random()-0.5, math.random()-0.5)) + minetest.add_item(p,it) + end + ent._items = nil +end + +local function on_remove(self,killer,oldf) + mcl_entity_invs.save_inv(self) + drop_inv(self) + if oldf then return oldf(self,killer) end +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + for k,v in pairs(open_invs) do + if formname == k._inv_id then + open_invs[k] = open_invs[k] - 1 + if open_invs[k] < 1 then + mcl_entity_invs.save_inv(k) + open_invs[k] = nil + end + end + end +end) + +function mcl_entity_invs.register_inv(entity_name,show_name,size,no_on_righclick,no_sneak) + assert(minetest.registered_entities[entity_name],"mcl_entity_invs.register_inv called with invalid entity: "..tostring(entity_name)) + minetest.registered_entities[entity_name]._inv_size = size + minetest.registered_entities[entity_name]._inv_title = show_name + + local old_oa = minetest.registered_entities[entity_name].on_activate + minetest.registered_entities[entity_name].on_activate = function(self,staticdata,dtime_s) + local r + if old_oa then r=old_oa(self,staticdata,dtime_s) end + local d = minetest.deserialize(staticdata) + if type(d) == "table" and d._inv_id then + self._inv_id = d._inv_id + self._items = d._items + self._inv_size = d._inv_size + else + self._inv_id="entity_inv_"..minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random())) + --gametime and position for collision safety and math.random salt to protect against position brute-force + end + return r + end + if not no_on_righclick then + local old_rc = minetest.registered_entities[entity_name].on_rightclick + minetest.registered_entities[entity_name].on_rightclick = function(self,clicker) + if no_sneak or clicker:get_player_control().sneak then + mcl_entity_invs.show_inv_form(self,clicker,"") + if not no_sneak then return end + end + if old_rc then return old_rc(self,clicker) end + end + end + + local old_gsd = minetest.registered_entities[entity_name].get_staticdata + minetest.registered_entities[entity_name].get_staticdata = function(self) + local old_sd = old_gsd(self) + local d = minetest.deserialize(old_sd) + assert(type(d) == "table","mcl_entity_invs currently only works with entities that return a (serialized) table in get_staticdata. "..tostring(self.name).." returned: "..tostring(old_sd)) + d._inv_id = self._inv_id + d._inv_size = self._inv_size + d._items = {} + if self._items then + for i,it in ipairs(self._items) do + d._items[i] = it + end + end + return minetest.serialize(d) + end + + local old_ode = minetest.registered_entities[entity_name].on_deactivate + minetest.registered_entities[entity_name].on_deactivate = function(self,removal) + mcl_entity_invs.save_inv(self) + if removal then + on_remove(self) + end + if old_ode then return old_ode(self,removal) end + end + + local old_od = minetest.registered_entities[entity_name].on_death + minetest.registered_entities[entity_name].on_death = function(self,killer) + if not self.is_mob then + on_remove(self,killer,old_od) + end + end + local old_odi = minetest.registered_entities[entity_name].on_die + minetest.registered_entities[entity_name].on_die = function(self,killer) + if self.is_mob then + on_remove(self,killer,old_od) + end + end +end diff --git a/mods/ENTITIES/mcl_entity_invs/mod.conf b/mods/ENTITIES/mcl_entity_invs/mod.conf new file mode 100644 index 000000000..8e94d6b1e --- /dev/null +++ b/mods/ENTITIES/mcl_entity_invs/mod.conf @@ -0,0 +1,3 @@ +name = mcl_entity_invs +author = cora +depends = mcl_formspec diff --git a/mods/ENTITIES/mcl_item_entity/README.txt b/mods/ENTITIES/mcl_item_entity/README.txt index 41e9e6e57..d39ec0ba9 100644 --- a/mods/ENTITIES/mcl_item_entity/README.txt +++ b/mods/ENTITIES/mcl_item_entity/README.txt @@ -25,4 +25,10 @@ http://minetest.net/ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - 0. You just DO WHAT THE FUCK YOU WANT TO. + 0. You just DO WHAT THE FUCK YOU WANT TO. + +--------- + +Alterations and contributions are released under GNU GPLv3 after 11/11/2022 and for contributors: + +AncientMariner/ancientmarinerdev \ No newline at end of file diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 5d91a6aad..0152caec9 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -6,6 +6,16 @@ local pool = {} local tick = false + +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_item_entities",false) +local function mcl_log (message) + if LOGGING_ON then + mcl_util.mcl_log (message, "[Item Entities]", true) + end +end + + + minetest.register_on_joinplayer(function(player) local name name = player:get_player_name() @@ -375,6 +385,116 @@ local function cxcz(o, cw, one, zero) return o end +local function hopper_take_item (self, pos) + --mcl_log("self.itemstring: ".. self.itemstring) + --mcl_log("self.itemstring: ".. minetest.pos_to_string(pos)) + + local objs = minetest.get_objects_inside_radius(pos, 2) + + if objs and self.itemstring then + --mcl_log("there is an itemstring. Number of objs: ".. #objs) + + for k,v in pairs(objs) do + local ent = v:get_luaentity() + + -- Don't forget actual hoppers + if ent and ent.name == "mcl_minecarts:hopper_minecart" then + local taken_items = false + + mcl_log("ent.name: ".. tostring(ent.name)) + mcl_log("ent pos: ".. tostring(ent.object:get_pos())) + + local inv = mcl_entity_invs.load_inv(ent,5) + + if not inv then + mcl_log("No inv") + return false + end + + local current_itemstack = ItemStack(self.itemstring) + + mcl_log("inv. size: " .. ent._inv_size) + if inv:room_for_item("main", current_itemstack) then + mcl_log("Room") + inv:add_item("main", current_itemstack) + self.object:get_luaentity().itemstring = "" + self.object:remove() + taken_items = true + else + mcl_log("no Room") + end + + if not taken_items then + local items_remaining = current_itemstack:get_count() + + -- This will take part of a floating item stack if no slot can hold the full amount + for i = 1, ent._inv_size,1 do + local stack = inv:get_stack("main", i) + + mcl_log("i: " .. tostring(i)) + mcl_log("Items remaining: " .. items_remaining) + mcl_log("Name: " .. tostring(stack:get_name())) + + if current_itemstack:get_name() == stack:get_name() then + mcl_log("We have a match. Name: " .. tostring(stack:get_name())) + + local room_for = stack:get_stack_max() - stack:get_count() + mcl_log("Room for: " .. tostring(room_for)) + + if room_for == 0 then + -- Do nothing + mcl_log("No room") + elseif room_for < items_remaining then + mcl_log("We have more items remaining than space") + + items_remaining = items_remaining - room_for + stack:set_count(stack:get_stack_max()) + inv:set_stack("main", i, stack) + taken_items = true + else + local new_stack_size = stack:get_count() + items_remaining + stack:set_count(new_stack_size) + mcl_log("We have more than enough space. Now holds: " .. new_stack_size) + + inv:set_stack("main", i, stack) + items_remaining = 0 + + self.object:get_luaentity().itemstring = "" + self.object:remove() + + taken_items = true + break + end + + mcl_log("Count: " .. tostring(stack:get_count())) + mcl_log("stack max: " .. tostring(stack:get_stack_max())) + --mcl_log("Is it empty: " .. stack:to_string()) + end + + if i == ent._inv_size and taken_items then + mcl_log("We are on last item and still have items left. Set final stack size: " .. items_remaining) + current_itemstack:set_count(items_remaining) + --mcl_log("Itemstack2: " .. current_itemstack:to_string()) + self.itemstring = current_itemstack:to_string() + end + end + end + + --Add in, and delete + if taken_items then + mcl_log("Saving") + mcl_entity_invs.save_inv(ent) + return taken_items + else + mcl_log("No need to save") + end + end + end + end + + return false +end + minetest.register_entity(":__builtin:item", { initial_properties = { hp_max = 1, @@ -648,6 +768,12 @@ minetest.register_entity(":__builtin:item", { end local p = self.object:get_pos() + + -- If hopper has taken item, it has gone, and no operations should be conducted on this item + if hopper_take_item(self, p) then + return + end + local node = minetest.get_node_or_nil(p) local in_unloaded = (node == nil) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index d894f9722..6a837207f 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -677,7 +677,8 @@ register_minecart( { "mcl_chests_normal.png", "mcl_minecarts_minecart.png" }, "mcl_minecarts_minecart_chest.png", {"mcl_minecarts:minecart", "mcl_chests:chest"}, - nil, nil, false) + nil, nil, true) +mcl_entity_invs.register_inv("mcl_minecarts:chest_minecart","Minecart",27,false,true) -- Minecart with Furnace register_minecart( @@ -730,7 +731,7 @@ register_minecart( "mcl_minecarts_minecart.png", }}) end - end, nil, false + end, nil, true ) -- Minecart with Command Block @@ -769,8 +770,9 @@ register_minecart( }, "mcl_minecarts_minecart_hopper.png", {"mcl_minecarts:minecart", "mcl_hoppers:hopper"}, - nil, nil, false + nil, nil, true ) +mcl_entity_invs.register_inv("mcl_minecarts:hopper_minecart", "Hopper Minecart", 5, false, true) -- Minecart with TNT register_minecart( @@ -830,8 +832,7 @@ minetest.register_craft({ }, }) --- TODO: Re-enable crafting of special minecarts when they have been implemented ---[[minetest.register_craft({ +minetest.register_craft({ output = "mcl_minecarts:furnace_minecart", recipe = { {"mcl_furnaces:furnace"}, @@ -847,18 +848,18 @@ minetest.register_craft({ }, }) + minetest.register_craft({ output = "mcl_minecarts:chest_minecart", recipe = { {"mcl_chests:chest"}, {"mcl_minecarts:minecart"}, }, -})]] +}) if has_mcl_wip then mcl_wip.register_wip_item("mcl_minecarts:chest_minecart") mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart") mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart") - mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart") end diff --git a/mods/ENTITIES/mcl_minecarts/mod.conf b/mods/ENTITIES/mcl_minecarts/mod.conf index 3b8ae5551..b810c2b6a 100644 --- a/mods/ENTITIES/mcl_minecarts/mod.conf +++ b/mods/ENTITIES/mcl_minecarts/mod.conf @@ -1,6 +1,5 @@ name = mcl_minecarts author = Krock description = Minecarts are vehicles to move players quickly on rails. -depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons +depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_entity_invs optional_depends = doc_identifier, mcl_wip - diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index b9e4c9e63..a898ed979 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1,37 +1,30 @@ +local mob_class = mcl_mobs.mob_class +local mob_class_meta = {__index = mcl_mobs.mob_class} +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs -- API for Mobs Redo: MineClone 2 Edition (MRM) - -mcl_mobs = {} - local MAX_MOB_NAME_LENGTH = 30 -local HORNY_TIME = 30 -local HORNY_AGAIN_TIME = 300 -local CHILD_GROW_TIME = 60*20 -local DEATH_DELAY = 0.5 -local DEFAULT_FALL_SPEED = -10 -local FLOP_HEIGHT = 5.0 -local FLOP_HOR_SPEED = 1.5 -local ENTITY_CRAMMING_MAX = 24 -local CRAMMING_DAMAGE = 3 +local DEFAULT_FALL_SPEED = -9.81*1.5 + +local PATHFINDING = "gowp" -- Localize local S = minetest.get_translator("mcl_mobs") +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false) +local function mcl_log (message) + if LOGGING_ON then + mcl_util.mcl_log (message, "[Mobs]", true) + end +end + + -- Invisibility mod check mcl_mobs.invis = {} -- localize math functions -local pi = math.pi -local sin = math.sin -local cos = math.cos -local abs = math.abs -local min = math.min -local max = math.max local atann = math.atan -local random = math.random -local floor = math.floor -local ceil = math.ceil -local atan = function(x) +local function atan(x) if not x or x ~= x then return 0 else @@ -39,18 +32,10 @@ local atan = function(x) end end --- Load settings -local damage_enabled = minetest.settings:get_bool("enable_damage") -local disable_blood = minetest.settings:get_bool("mobs_disable_blood") -local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false +local remove_far = true local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false -local remove_far = true -local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 -local show_health = false - --- Shows helpful debug info above each mob -local mobs_debug = minetest.settings:get_bool("mobs_debug", false) +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) -- Peaceful mode message so players will know there are no monsters @@ -61,596 +46,23 @@ if minetest.settings:get_bool("only_peaceful_mobs", false) then end) end --- pathfinding settings -local enable_pathfinding = true -local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching -local stuck_path_timeout = 10 -- how long will mob follow path before giving up - --- default nodes -local node_ice = "mcl_core:ice" -local node_snowblock = "mcl_core:snowblock" -local node_snow = "mcl_core:snow" -mcl_mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" - -minetest.register_chatcommand("clearmobs",{ - privs={maphack=true}, - params = "||", - description=S("Removes all spawned mobs except nametagged and tamed ones. all removes all mobs, nametagged only nametagged ones and with the range paramter all mobs in a distance of the current player are removed."), - func=function(n,param) - local p = minetest.get_player_by_name(n) - local num=tonumber(param) - for _,o in pairs(minetest.luaentities) do - if o.is_mob then - if param == "all" or - ( param == "nametagged" and o.nametag ) or - ( param == "" and ( not o.nametag or o.nametag == "" ) and not o.tamed ) or - ( num and num > 0 and vector.distance(p:get_pos(),o.object:get_pos()) <= num ) then - o.object:remove() - end - end - end -end}) - -----For Water Flowing: -local enable_physics = function(object, luaentity, ignore_check) - if luaentity.physical_state == false or ignore_check == true then - luaentity.physical_state = true - object:set_properties({ - physical = true - }) - object:set_velocity({x=0,y=0,z=0}) - object:set_acceleration({x=0,y=-9.81,z=0}) +local node_ok = function(pos, fallback) + fallback = fallback or mcl_mobs.fallback_node + local node = minetest.get_node_or_nil(pos) + if node and minetest.registered_nodes[node.name] then + return node end + return minetest.registered_nodes[fallback] end -local disable_physics = function(object, luaentity, ignore_check, reset_movement) - if luaentity.physical_state == true or ignore_check == true then - luaentity.physical_state = false - object:set_properties({ - physical = false - }) - if reset_movement ~= false then - object:set_velocity({x=0,y=0,z=0}) - object:set_acceleration({x=0,y=0,z=0}) - end - end -end - - --- play sound -local mob_sound = function(self, soundname, is_opinion, fixed_pitch) - - local soundinfo - if self.sounds_child and self.child then - soundinfo = self.sounds_child - elseif self.sounds then - soundinfo = self.sounds - end - if not soundinfo then - return - end - local sound = soundinfo[soundname] - if sound then - if is_opinion and self.opinion_sound_cooloff > 0 then - return - end - local pitch - if not fixed_pitch then - local base_pitch = soundinfo.base_pitch - if not base_pitch then - base_pitch = 1 - end - if self.child and (not self.sounds_child) then - -- Children have higher pitch - pitch = base_pitch * 1.5 - else - pitch = base_pitch - end - -- randomize the pitch a bit - pitch = pitch + random(-10, 10) * 0.005 - end - minetest.sound_play(sound, { - object = self.object, - gain = 1.0, - max_hear_distance = self.sounds.distance, - pitch = pitch, - }, true) - self.opinion_sound_cooloff = 1 - end -end - --- Return true if object is in view_range -local function object_in_range(self, object) - if not object then - return false - end - local factor - -- Apply view range reduction for special player armor - if object:is_player() then - local factors = mcl_armor.player_view_range_factors[object] - factor = factors and factors[self.name] - end - -- Distance check - local dist - if factor and factor == 0 then - return false - elseif factor then - dist = self.view_range * factor - else - dist = self.view_range - end - - local p1, p2 = self.object:get_pos(), object:get_pos() - return p1 and p2 and (vector.distance(p1, p2) <= dist) -end - --- attack player/mob -local do_attack = function(self, player) - - if self.state == "attack" or self.state == "die" then - return - end - - self.attack = player - self.state = "attack" - - -- TODO: Implement war_cry sound without being annoying - --if random(0, 100) < 90 then - --mob_sound(self, "war_cry", true) - --end -end - - --- collision function borrowed amended from jordan4ibanez open_ai mod -local collision = function(self) - - local pos = self.object:get_pos() - if not pos then return {0,0} end - local vel = self.object:get_velocity() - local x = 0 - local z = 0 - local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 - for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do - - local ent = object:get_luaentity() - if object:is_player() or (ent and ent.is_mob and object ~= self.object) then - - local pos2 = object:get_pos() - local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} - local force = (width + 0.5) - vector.distance( - {x = pos.x, y = 0, z = pos.z}, - {x = pos2.x, y = 0, z = pos2.z}) - - x = x + (vec.x * force) - z = z + (vec.z * force) - end - end - - return({x,z}) -end - --- move mob in facing direction -local set_velocity = function(self, v) - - local c_x, c_y = 0, 0 - - -- can mob be pushed, if so calculate direction - if self.pushable then - c_x, c_y = unpack(collision(self)) - end - - -- halt mob if it has been ordered to stay - if self.order == "stand" or self.order == "sit" then - self.object:set_velocity({x = 0, y = 0, z = 0}) - return - end - - local yaw = (self.object:get_yaw() or 0) + self.rotate - local vv = self.object:get_velocity() - if vv then - self.object:set_velocity({ - x = (sin(yaw) * -v) + c_x, - y = vv.y, - z = (cos(yaw) * v) + c_y, - }) - end -end - - - --- calculate mob velocity -local get_velocity = function(self) - - local v = self.object:get_velocity() - if v then - return (v.x * v.x + v.z * v.z) ^ 0.5 - end - - return 0 -end - -local function update_roll(self) - local is_Fleckenstein = self.nametag == "Fleckenstein" - local was_Fleckenstein = false - - local rot = self.object:get_rotation() - rot.z = is_Fleckenstein and pi or 0 - self.object:set_rotation(rot) - - local cbox = table.copy(self.collisionbox) - local acbox = self.object:get_properties().collisionbox - - if abs(cbox[2] - acbox[2]) > 0.1 then - was_Fleckenstein = true - end - - if is_Fleckenstein ~= was_Fleckenstein then - local pos = self.object:get_pos() - pos.y = pos.y + (acbox[2] + acbox[5]) - self.object:set_pos(pos) - end - - if is_Fleckenstein then - cbox[2], cbox[5] = -cbox[5], -cbox[2] - self.object:set_properties({collisionbox = cbox}) - -- This leads to child mobs having the wrong collisionbox - -- and seeing as it seems to be nothing but an easter egg - -- i've put it inside the if. Which just makes it be upside - -- down lol. - end - -end - --- set and return valid yaw -local set_yaw = function(self, yaw, delay, dtime) - - if self.noyaw then return end - if true then - self.object:set_yaw(yaw) - return yaw - end - - if not yaw or yaw ~= yaw then - yaw = 0 - end - - delay = delay or 0 - - if delay == 0 then - if self.shaking and dtime then - yaw = yaw + (random() * 2 - 1) * 5 * dtime - end - self.object:set_yaw(yaw) - update_roll(self) - return yaw - end - - self.target_yaw = yaw - self.delay = delay - - return self.target_yaw -end - --- global function to set mob yaw -function mcl_mobs:yaw(self, yaw, delay, dtime) - set_yaw(self, yaw, delay, dtime) -end - -local add_texture_mod = function(self, mod) - local full_mod = "" - local already_added = false - for i=1, #self.texture_mods do - if mod == self.texture_mods[i] then - already_added = true - end - full_mod = full_mod .. self.texture_mods[i] - end - if not already_added then - full_mod = full_mod .. mod - table.insert(self.texture_mods, mod) - end - self.object:set_texture_mod(full_mod) -end -local remove_texture_mod = function(self, mod) - local full_mod = "" - local remove = {} - for i=1, #self.texture_mods do - if self.texture_mods[i] ~= mod then - full_mod = full_mod .. self.texture_mods[i] - else - table.insert(remove, i) - end - end - for i=#remove, 1 do - table.remove(self.texture_mods, remove[i]) - end - self.object:set_texture_mod(full_mod) -end - --- are we flying in what we are suppose to? (taikedz) -local flight_check = function(self) - - local nod = self.standing_in - local def = minetest.registered_nodes[nod] - - if not def then return false end -- nil check - - local fly_in - if type(self.fly_in) == "string" then - fly_in = { self.fly_in } - elseif type(self.fly_in) == "table" then - fly_in = self.fly_in - else - return false - end - - for _,checknode in pairs(fly_in) do - if nod == checknode then - return true - elseif checknode == "__airlike" or def.walkable == false and - (def.liquidtype == "none" or minetest.get_item_group(nod, "fake_liquid") == 1) then - return true - end - end - - return false -end - --- set defined animation -local set_animation = function(self, anim, fixed_frame) - if not self.animation or not anim then - return - end - if self.state == "die" and anim ~= "die" and anim ~= "stand" then - return - end - - if flight_check(self) and self.fly and anim == "walk" then anim = "fly" end - - self._current_animation = self._current_animation or "" - - if (anim == self._current_animation - or not self.animation[anim .. "_start"] - or not self.animation[anim .. "_end"]) and self.state ~= "die" then - return - end - - self._current_animation = anim - - local a_start = self.animation[anim .. "_start"] - local a_end - if fixed_frame then - a_end = a_start - else - a_end = self.animation[anim .. "_end"] - end - - self.object:set_animation({ - x = a_start, - y = a_end}, - self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, - 0, self.animation[anim .. "_loop"] ~= false) -end - - --- above function exported for mount.lua -function mcl_mobs:set_animation(self, anim) - set_animation(self, anim) -end - --- Returns true is node can deal damage to self -local is_node_dangerous = function(self, nodename) - local nn = nodename - if self.lava_damage > 0 then - if minetest.get_item_group(nn, "lava") ~= 0 then - return true - end - end - if self.fire_damage > 0 then - if minetest.get_item_group(nn, "fire") ~= 0 then - return true - end - end - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].damage_per_second and minetest.registered_nodes[nn].damage_per_second > 0 then - return true - end - return false -end - - --- Returns true if node is a water hazard -local is_node_waterhazard = function(self, nodename) - local nn = nodename - if self.water_damage > 0 then - if minetest.get_item_group(nn, "water") ~= 0 then - return true - end - end - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].drowning and minetest.registered_nodes[nn].drowning > 0 then - if self.breath_max ~= -1 then - -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case - -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous - if not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then - return true - end - end - end - return false -end - - --- check line of sight (BrunoMine) -local line_of_sight = function(self, pos1, pos2, stepsize) - - stepsize = stepsize or 1 - - local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) - - -- normal walking and flying mobs can see you through air - if s == true then - return true - end - - -- New pos1 to be analyzed - local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} - - local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) - - -- Checks the return - if r == true then return true end - - -- Nodename found - local nn = minetest.get_node(pos).name - - -- Target Distance (td) to travel - local td = vector.distance(pos1, pos2) - - -- Actual Distance (ad) traveled - local ad = 0 - - -- It continues to advance in the line of sight in search of a real - -- obstruction which counts as 'normal' nodebox. - while minetest.registered_nodes[nn] - and minetest.registered_nodes[nn].walkable == false do - - -- Check if you can still move forward - if td < ad + stepsize then - return true -- Reached the target - end - - -- Moves the analyzed pos - local d = vector.distance(pos1, pos2) - - npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x - npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y - npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z - - -- NaN checks - if d == 0 - or npos1.x ~= npos1.x - or npos1.y ~= npos1.y - or npos1.z ~= npos1.z then - return false - end - - ad = ad + stepsize - - -- scan again - r, pos = minetest.line_of_sight(npos1, pos2, stepsize) - - if r == true then return true end - - -- New Nodename found - nn = minetest.get_node(pos).name - - end - - return false -end - --- custom particle effects -local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) - - radius = radius or 2 - min_size = min_size or 0.5 - max_size = max_size or 1 - gravity = gravity or -10 - glow = glow or 0 - go_down = go_down or false - - local ym - if go_down then - ym = 0 - else - ym = -radius - end - - minetest.add_particlespawner({ - amount = amount, - time = 0.25, - minpos = pos, - maxpos = pos, - minvel = {x = -radius, y = ym, z = -radius}, - maxvel = {x = radius, y = radius, z = radius}, - minacc = {x = 0, y = gravity, z = 0}, - maxacc = {x = 0, y = gravity, z = 0}, - minexptime = 0.1, - maxexptime = 1, - minsize = min_size, - maxsize = max_size, - texture = texture, - glow = glow, - }) -end - -local damage_effect = function(self, damage) - -- damage particles - if (not disable_blood) and damage > 0 then - - local amount_large = floor(damage / 2) - local amount_small = damage % 2 - - local pos = self.object:get_pos() - - pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 - - local texture = "mobs_blood.png" - -- full heart damage (one particle for each 2 HP damage) - if amount_large > 0 then - effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) - end - -- half heart damage (one additional particle if damage is an odd number) - if amount_small > 0 then - -- TODO: Use "half heart" - effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) - end - end -end - -mcl_mobs.death_effect = function(pos, yaw, collisionbox, rotate) - local min, max - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - else - min = { x = -0.5, y = 0, z = -0.5 } - max = { x = 0.5, y = 0.5, z = 0.5 } - end - if rotate then - min = vector.rotate(min, {x=0, y=yaw, z=pi/2}) - max = vector.rotate(max, {x=0, y=yaw, z=pi/2}) - min, max = vector.sort(min, max) - min = vector.multiply(min, 0.5) - max = vector.multiply(max, 0.5) - end - - minetest.add_particlespawner({ - amount = 50, - time = 0.001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-5,-5,-5), - maxvel = vector.new(5,5,5), - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "mcl_particles_mob_death.png^[colorize:#000000:255", - }) - - minetest.sound_play("mcl_mobs_mob_poof", { - pos = pos, - gain = 1.0, - max_hear_distance = 8, - }, true) -end - -local update_tag = function(self) +function mob_class:update_tag() --update nametag and/or the debug box local tag if mobs_debug then - tag = "nametag = '"..tostring(self.nametag).."'\n".. + local name = self.name + if self.nametag and self.nametag ~= "" then + name = self.nametag + end + tag = "name = '"..tostring(name).."'\n".. "state = '"..tostring(self.state).."'\n".. "order = '"..tostring(self.order).."'\n".. "attack = "..tostring(self.attack).."\n".. @@ -661,2751 +73,21 @@ local update_tag = function(self) "horny = "..tostring(self.horny).."\n".. "hornytimer = "..tostring(self.hornytimer).."\n".. "runaway_timer = "..tostring(self.runaway_timer).."\n".. - "following = "..tostring(self.following) + "following = "..tostring(self.following).."\n".. + "lifetimer = "..tostring(self.lifetimer) else tag = self.nametag end self.object:set_properties({ nametag = tag, }) - - update_roll(self) end --- drop items -local item_drop = function(self, cooked, looting_level) +function mob_class:get_staticdata() - -- no drops if disabled by setting - if not mobs_drop_items then return end - - looting_level = looting_level or 0 - - -- no drops for child mobs (except monster) - if (self.child and self.type ~= "monster") then - return - end - - local obj, item, num - local pos = self.object:get_pos() - - self.drops = self.drops or {} -- nil check - - for n = 1, #self.drops do - local dropdef = self.drops[n] - local chance = 1 / dropdef.chance - local looting_type = dropdef.looting - - if looting_level > 0 then - local chance_function = dropdef.looting_chance_function - if chance_function then - chance = chance_function(looting_level) - elseif looting_type == "rare" then - chance = chance + (dropdef.looting_factor or 0.01) * looting_level - end - end - - local num = 0 - local do_common_looting = (looting_level > 0 and looting_type == "common") - if random() < chance then - num = random(dropdef.min or 1, dropdef.max or 1) - elseif not dropdef.looting_ignore_chance then - do_common_looting = false - end - - if do_common_looting then - num = num + floor(random(0, looting_level) + 0.5) - end - - if num > 0 then - item = dropdef.name - - -- cook items when true - if cooked then - - local output = minetest.get_craft_result({ - method = "cooking", width = 1, items = {item}}) - - if output and output.item and not output.item:is_empty() then - item = output.item:get_name() - end - end - - -- add item if it exists - for x = 1, num do - obj = minetest.add_item(pos, ItemStack(item .. " " .. 1)) - end - - if obj and obj:get_luaentity() then - - obj:set_velocity({ - x = random(-10, 10) / 9, - y = 6, - z = random(-10, 10) / 9, - }) - elseif obj then - obj:remove() -- item does not exist - end - end - end - - self.drops = {} -end - - --- check if mob is dead or only hurt -local check_for_death = function(self, cause, cmi_cause) - - if self.state == "die" then - return true - end - - -- has health actually changed? - if self.health == self.old_health and self.health > 0 then - return false - end - - local damaged = self.health < self.old_health - self.old_health = self.health - - -- still got some health? - if self.health > 0 then - - -- make sure health isn't higher than max - if self.health > self.hp_max then - self.health = self.hp_max - end - - -- play damage sound if health was reduced and make mob flash red. - if damaged then - add_texture_mod(self, "^[colorize:red:130") - minetest.after(.2, function(self) - if self and self.object then - remove_texture_mod(self, "^[colorize:red:130") - end - end, self) - mob_sound(self, "damage") - end - - -- backup nametag so we can show health stats - if not self.nametag2 then - self.nametag2 = self.nametag or "" - end - - if show_health - and (cmi_cause and cmi_cause.type == "punch") then - - self.htimer = 2 - self.nametag = "♥ " .. self.health .. " / " .. self.hp_max - - update_tag(self) - end - - return false - end - - mob_sound(self, "death") - - local function death_handle(self) - -- dropped cooked item if mob died in fire or lava - if cause == "lava" or cause == "fire" then - item_drop(self, true, 0) - else - local wielditem = ItemStack() - if cause == "hit" then - local puncher = cmi_cause.puncher - if puncher then - wielditem = puncher:get_wielded_item() - end - end - local cooked = mcl_burning.is_burning(self.object) or mcl_enchanting.has_enchantment(wielditem, "fire_aspect") - local looting = mcl_enchanting.get_enchantment(wielditem, "looting") - item_drop(self, cooked, looting) - - if ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then - mcl_experience.throw_xp(self.object:get_pos(), random(self.xp_min, self.xp_max)) - end - end - end - - -- execute custom death function - if self.on_die then - - local pos = self.object:get_pos() - local on_die_exit = self.on_die(self, pos, cmi_cause) - if on_die_exit ~= true then - death_handle(self) - end - - if on_die_exit == true then - self.state = "die" - mcl_burning.extinguish(self.object) - self.object:remove() - return true - end - end - - local collisionbox - if self.collisionbox then - collisionbox = table.copy(self.collisionbox) - end - - self.state = "die" - self.attack = nil - self.v_start = false - self.fall_speed = DEFAULT_FALL_SPEED - self.timer = 0 - self.blinktimer = 0 - remove_texture_mod(self, "^[colorize:#FF000040") - remove_texture_mod(self, "^[brighten") - self.passive = true - - self.object:set_properties({ - pointable = false, - collide_with_objects = false, - }) - - set_velocity(self, 0) - local acc = self.object:get_acceleration() - acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0 - self.object:set_acceleration(acc) - - local length - -- default death function and die animation (if defined) - if self.instant_death then - length = 0 - elseif self.animation - and self.animation.die_start - and self.animation.die_end then - - local frames = self.animation.die_end - self.animation.die_start - local speed = self.animation.die_speed or 15 - length = max(frames / speed, 0) + DEATH_DELAY - set_animation(self, "die") - else - local rot = self.object:get_rotation() - rot.z = pi/2 - self.object:set_rotation(rot) - length = 1 + DEATH_DELAY - set_animation(self, "stand", true) - end - - - -- Remove body after a few seconds and drop stuff - local kill = function(self) - if not self.object:get_luaentity() then - return - end - - death_handle(self) - local dpos = self.object:get_pos() - local cbox = self.collisionbox - local yaw = self.object:get_rotation().y - mcl_burning.extinguish(self.object) - self.object:remove() - mcl_mobs.death_effect(dpos, yaw, cbox, not self.instant_death) - end - if length <= 0 then - kill(self) - else - minetest.after(length, kill, self) - end - - return true -end - - --- check if within physical map limits (-30911 to 30927) -local within_limits, wmin, wmax = nil, -30913, 30928 -within_limits = function(pos, radius) - if mcl_vars then - if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then - wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max - within_limits = function(pos, radius) - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax - end - end - end - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax -end - - --- is mob facing a cliff or danger -local is_at_cliff_or_danger = function(self) - - if self.fear_height == 0 then -- 0 for no falling protection! - return false - end - - if not self.object:get_luaentity() then - return false - end - local yaw = self.object:get_yaw() - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) - local pos = self.object:get_pos() - local ypos = pos.y + self.collisionbox[2] -- just above floor - - local free_fall, blocker = minetest.line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) - if free_fall then - return true - else - local bnode = minetest.get_node(blocker) - local danger = is_node_dangerous(self, bnode.name) - if danger then - return true - else - local def = minetest.registered_nodes[bnode.name] - if def and def.walkable then - return false - end - end - end - - return false -end - - --- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water -local is_at_water_danger = function(self) - - - if not self.object:get_luaentity() then - return false - end - local yaw = self.object:get_yaw() - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) - local pos = self.object:get_pos() - local ypos = pos.y + self.collisionbox[2] -- just above floor - - local free_fall, blocker = minetest.line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) - if free_fall then - return true - else - local bnode = minetest.get_node(blocker) - local waterdanger = is_node_waterhazard(self, bnode.name) - if - waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) then - return false - elseif waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) == false then - return true - else - local def = minetest.registered_nodes[bnode.name] - if def and def.walkable then - return false - end - end - end - - return false -end - - --- get node but use fallback for nil or unknown -local node_ok = function(pos, fallback) - - fallback = fallback or mcl_mobs.fallback_node - - local node = minetest.get_node_or_nil(pos) - - if node and minetest.registered_nodes[node.name] then - return node - end - - return minetest.registered_nodes[fallback] -end - -local function get_light(pos, tod) - if minetest.get_node_or_nil(pos) then - local lightfunc = minetest.get_natural_light or minetest.get_node_light - return lightfunc(pos, tod) - else - return 0 - end -end - --- environmental damage (water, lava, fire, light etc.) -local do_env_damage = function(self) - - -- feed/tame text timer (so mob 'full' messages dont spam chat) - if self.htimer > 0 then - self.htimer = self.htimer - 1 - end - - -- reset nametag after showing health stats - if self.htimer < 1 and self.nametag2 then - - self.nametag = self.nametag2 - self.nametag2 = nil - - update_tag(self) - end - - local pos = self.object:get_pos() - - self.time_of_day = minetest.get_timeofday() - - -- remove mob if beyond map limits - if not within_limits(pos, 0) then - mcl_burning.extinguish(self.object) - self.object:remove() - return true - end - - - -- Deal light damage to mob, returns true if mob died - local deal_light_damage = function(self, pos, damage) - if not ((mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then - self.health = self.health - damage - - effect(pos, 5, "mcl_particles_smoke.png") - - if check_for_death(self, "light", {type = "light"}) then - return true - end - end - end - - -- Use get_node_light for Minetest version 5.3 where get_natural_light - -- does not exist yet. - local sunlight = get_light(pos, self.time_of_day) - - -- bright light harms mob - if self.light_damage ~= 0 and (sunlight or 0) > 12 then - if deal_light_damage(self, pos, self.light_damage) then - return true - end - end - local _, dim = mcl_worlds.y_to_layer(pos.y) - if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then - if self.ignited_by_sunlight then - mcl_burning.set_on_fire(self.object, 10) - else - deal_light_damage(self, pos, self.sunlight_damage) - return true - end - end - - local y_level = self.collisionbox[2] - - if self.child then - y_level = self.collisionbox[2] * 0.5 - end - - -- what is mob standing in? - pos.y = pos.y + y_level + 0.25 -- foot level - local pos2 = {x=pos.x, y=pos.y-1, z=pos.z} - self.standing_in = node_ok(pos, "air").name - self.standing_on = node_ok(pos2, "air").name - - -- don't fall when on ignore, just stand still - if self.standing_in == "ignore" then - self.object:set_velocity({x = 0, y = 0, z = 0}) - end - - local nodef = minetest.registered_nodes[self.standing_in] - - -- rain - if self.rain_damage > 0 then - if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then - - self.health = self.health - self.rain_damage - - if check_for_death(self, "rain", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - end - - pos.y = pos.y + 1 -- for particle effect position - - -- water damage - if self.water_damage > 0 - and nodef.groups.water then - - if self.water_damage ~= 0 then - - self.health = self.health - self.water_damage - - effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil) - - if check_for_death(self, "water", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- lava damage - elseif self.lava_damage > 0 - and (nodef.groups.lava) then - - if self.lava_damage ~= 0 then - - self.health = self.health - self.lava_damage - - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) - - if check_for_death(self, "lava", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- fire damage - elseif self.fire_damage > 0 - and (nodef.groups.fire) then - - if self.fire_damage ~= 0 then - - self.health = self.health - self.fire_damage - - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) - - if check_for_death(self, "fire", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- damage_per_second node check - elseif nodef.damage_per_second ~= 0 and not nodef.groups.lava and not nodef.groups.fire then - - self.health = self.health - nodef.damage_per_second - - effect(pos, 5, "mcl_particles_smoke.png") - - if check_for_death(self, "dps", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- Drowning damage - if self.breath_max ~= -1 then - local drowning = false - if self.breathes_in_water then - if minetest.get_item_group(self.standing_in, "water") == 0 then - drowning = true - end - elseif nodef.drowning > 0 then - drowning = true - end - if drowning then - - self.breath = max(0, self.breath - 1) - - effect(pos, 2, "bubble.png", nil, nil, 1, nil) - if self.breath <= 0 then - local dmg - if nodef.drowning > 0 then - dmg = nodef.drowning - else - dmg = 4 - end - damage_effect(self, dmg) - self.health = self.health - dmg - end - if check_for_death(self, "drowning", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - else - self.breath = min(self.breath_max, self.breath + 1) - end - end - - --- suffocation inside solid node - -- FIXME: Redundant with mcl_playerplus - if (self.suffocation == true) - and (nodef.walkable == nil or nodef.walkable == true) - and (nodef.collision_box == nil or nodef.collision_box.type == "regular") - and (nodef.node_box == nil or nodef.node_box.type == "regular") - and (nodef.groups.disable_suffocation ~= 1) - and (nodef.groups.opaque == 1) then - - -- Short grace period before starting to take suffocation damage. - -- This is different from players, who take damage instantly. - -- This has been done because mobs might briefly be inside solid nodes - -- when e.g. climbing up stairs. - -- This is a bit hacky because it assumes that do_env_damage - -- is called roughly every second only. - self.suffocation_timer = self.suffocation_timer + 1 - if self.suffocation_timer >= 3 then - -- 2 damage per second - -- TODO: Deal this damage once every 1/2 second - self.health = self.health - 2 - - if check_for_death(self, "suffocation", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - else - self.suffocation_timer = 0 - end - - return check_for_death(self, "", {type = "unknown"}) -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.child and self.type ~= "monster") - or self.order == "stand" then - return false - end - - self.facing_fence = false - - -- something stopping us while moving? - if self.state ~= "stand" - and get_velocity(self) > 0.5 - and self.object:get_velocity().y ~= 0 then - return false - end - - local pos = self.object:get_pos() - local yaw = self.object:get_yaw() - - -- what is mob standing on? - pos.y = pos.y + self.collisionbox[2] - 0.2 - - local nod = node_ok(pos) - - if minetest.registered_nodes[nod.name].walkable == false then - return false - end - - -- where is front - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) - - -- what is in front of mob? - nod = node_ok({ - x = pos.x + dir_x, - y = pos.y + 0.5, - z = pos.z + dir_z - }) - - -- this is used to detect if there's a block on top of the block in front of the mob. - -- If there is, there is no point in jumping as we won't manage. - local nodTop = node_ok({ - x = pos.x + dir_x, - y = pos.y + 1.5, - z = pos.z + dir_z - }, "air") - - -- we don't attempt to jump if there's a stack of blocks blocking - if minetest.registered_nodes[nodTop.name].walkable == true then - return false - end - - -- thin blocks that do not need to be jumped - if nod.name == node_snow then - return false - end - - local ndef = minetest.registered_nodes[nod.name] - if self.walk_chance == 0 or ndef and ndef.walkable then - - if minetest.get_item_group(nod.name, "fence") == 0 - and minetest.get_item_group(nod.name, "fence_gate") == 0 - and minetest.get_item_group(nod.name, "wall") == 0 then - - local v = self.object:get_velocity() - - v.y = self.jump_height - - set_animation(self, "jump") -- only when defined - - self.object:set_velocity(v) - - -- when in air move forward - minetest.after(0.3, function(self, v) - if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then - return - end - self.object:set_acceleration({ - x = v.x * 2, - y = -10, - z = v.z * 2, - }) - end, self, v) - - if self.jump_sound_cooloff <= 0 then - mob_sound(self, "jump") - self.jump_sound_cooloff = 0.5 - end - else - self.facing_fence = true - end - - -- if we jumped against a block/wall 4 times then turn - if self.object:get_velocity().x ~= 0 - and self.object:get_velocity().z ~= 0 then - - self.jump_count = (self.jump_count or 0) + 1 - - if self.jump_count == 4 then - - local yaw = self.object:get_yaw() or 0 - - yaw = set_yaw(self, yaw + 1.35, 8) - - self.jump_count = 0 - end - end - - return true - end - - return false -end - - --- blast damage to entities nearby -local entity_physics = function(pos, radius) - - radius = radius * 2 - - local objs = minetest.get_objects_inside_radius(pos, radius) - local obj_pos, dist - - for n = 1, #objs do - - obj_pos = objs[n]:get_pos() - - dist = vector.distance(pos, obj_pos) - if dist < 1 then dist = 1 end - - local damage = floor((4 / dist) * radius) - local ent = objs[n]:get_luaentity() - - -- punches work on entities AND players - objs[n]:punch(objs[n], 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = damage}, - }, pos) - end -end - - --- should mob follow what I'm holding ? -local follow_holding = function(self, clicker) - if self.nofollow then return false end - - if mcl_mobs.invis[clicker:get_player_name()] then - return false - end - - local item = clicker:get_wielded_item() - local t = type(self.follow) - - -- single item - if t == "string" - and item:get_name() == self.follow then - return true - - -- multiple items - elseif t == "table" then - - for no = 1, #self.follow do - - if self.follow[no] == item:get_name() then - return true - end - end - end - - return false -end - - --- find two animals of same type and breed if nearby and horny -local breed = function(self) - - -- child takes a long time before growing into adult - if self.child == true then - - -- When a child, hornytimer is used to count age until adulthood - self.hornytimer = self.hornytimer + 1 - - if self.hornytimer >= CHILD_GROW_TIME then - - self.child = false - self.hornytimer = 0 - - self.object:set_properties({ - textures = self.base_texture, - mesh = self.base_mesh, - visual_size = self.base_size, - collisionbox = self.base_colbox, - selectionbox = self.base_selbox, - }) - - -- custom function when child grows up - if self.on_grown then - self.on_grown(self) - else - -- jump when fully grown so as not to fall into ground - self.object:set_velocity({ - x = 0, - y = self.jump_height, - z = 0 - }) - end - end - - return - end - - -- horny animal can mate for HORNY_TIME seconds, - -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds - if self.horny == true - and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then - - self.hornytimer = self.hornytimer + 1 - - if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then - self.hornytimer = 0 - self.horny = false - end - end - - -- find another same animal who is also horny and mate if nearby - if self.horny == true - and self.hornytimer <= HORNY_TIME then - - local pos = self.object:get_pos() - - effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) - - local objs = minetest.get_objects_inside_radius(pos, 3) - local num = 0 - local ent = nil - - for n = 1, #objs do - - ent = objs[n]:get_luaentity() - - -- check for same animal with different colour - local canmate = false - - if ent then - - if ent.name == self.name then - canmate = true - else - local entname = string.split(ent.name,":") - local selfname = string.split(self.name,":") - - if entname[1] == selfname[1] then - entname = string.split(entname[2],"_") - selfname = string.split(selfname[2],"_") - - if entname[1] == selfname[1] then - canmate = true - end - end - end - end - - if ent - and canmate == true - and ent.horny == true - and ent.hornytimer <= HORNY_TIME then - num = num + 1 - end - - -- found your mate? then have a baby - if num > 1 then - - self.hornytimer = HORNY_TIME + 1 - ent.hornytimer = HORNY_TIME + 1 - - -- spawn baby - minetest.after(5, function(parent1, parent2, pos) - if not parent1.object:get_luaentity() then - return - end - if not parent2.object:get_luaentity() then - return - end - - mcl_experience.throw_xp(pos, random(1, 7)) - - -- custom breed function - if parent1.on_breed then - -- when false, skip going any further - if parent1.on_breed(parent1, parent2) == false then - return - end - end - - local child = mcl_mobs:spawn_child(pos, parent1.name) - - local ent_c = child:get_luaentity() - - - -- Use texture of one of the parents - local p = random(1, 2) - if p == 1 then - ent_c.base_texture = parent1.base_texture - else - ent_c.base_texture = parent2.base_texture - end - child:set_properties({ - textures = ent_c.base_texture - }) - - -- tamed and owned by parents' owner - ent_c.tamed = true - ent_c.owner = parent1.owner - end, self, ent, pos) - - num = 0 - - break - end - end - end -end - - --- find and replace what mob is looking for (grass, wheat etc.) -local replace = function(self, pos) - - if not self.replace_rate - or not self.replace_what - or self.child == true - or self.object:get_velocity().y ~= 0 - or random(1, self.replace_rate) > 1 then - return - end - - local what, with, y_offset - - if type(self.replace_what[1]) == "table" then - - local num = random(#self.replace_what) - - what = self.replace_what[num][1] or "" - with = self.replace_what[num][2] or "" - y_offset = self.replace_what[num][3] or 0 - else - what = self.replace_what - with = self.replace_with or "" - y_offset = self.replace_offset or 0 - end - - pos.y = pos.y + y_offset - - local node = minetest.get_node(pos) - if node.name == what then - - local oldnode = {name = what, param2 = node.param2} - local newnode = {name = with, param2 = node.param2} - local on_replace_return - - if self.on_replace then - on_replace_return = self.on_replace(self, pos, oldnode, newnode) - end - - if on_replace_return ~= false then - - if mobs_griefing then - minetest.set_node(pos, newnode) - end - - end - end -end - - --- check if daytime and also if mob is docile during daylight hours -local day_docile = function(self) - - if self.docile_by_day == false then - - return false - - elseif self.docile_by_day == true - and self.time_of_day > 0.2 - and self.time_of_day < 0.8 then - - return true - end -end - - -local los_switcher = false -local height_switcher = false - --- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 -local smart_mobs = function(self, s, p, dist, dtime) - - local s1 = self.path.lastpos - - local target_pos = self.attack:get_pos() - - -- is it becoming stuck? - if abs(s1.x - s.x) + abs(s1.z - s.z) < .5 then - self.path.stuck_timer = self.path.stuck_timer + dtime - else - self.path.stuck_timer = 0 - end - - self.path.lastpos = {x = s.x, y = s.y, z = s.z} - - local use_pathfind = false - local has_lineofsight = minetest.line_of_sight( - {x = s.x, y = (s.y) + .5, z = s.z}, - {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) - - -- im stuck, search for path - if not has_lineofsight then - - if los_switcher == true then - use_pathfind = true - los_switcher = false - end -- cannot see target! - else - if los_switcher == false then - - los_switcher = true - use_pathfind = false - - minetest.after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end -- can see target! - end - - if (self.path.stuck_timer > stuck_timeout and not self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest.after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest.after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if abs(vector.subtract(s,target_pos).y) > self.stepheight then - - if height_switcher then - use_pathfind = true - height_switcher = false - end - else - if not height_switcher then - use_pathfind = false - height_switcher = true - end - end - - if use_pathfind then - -- lets try find a path, first take care of positions - -- since pathfinder is very sensitive - local sheight = self.collisionbox[5] - self.collisionbox[2] - - -- round position to center of node to avoid stuck in walls - -- also adjust height for player models! - s.x = floor(s.x + 0.5) - s.z = floor(s.z + 0.5) - - local ssight, sground = minetest.line_of_sight(s, { - x = s.x, y = s.y - 4, z = s.z}, 1) - - -- determine node above ground - if not ssight then - s.y = sground.y + 1 - end - - local p1 = self.attack:get_pos() - - p1.x = floor(p1.x + 0.5) - p1.y = floor(p1.y + 0.5) - p1.z = floor(p1.z + 0.5) - - local dropheight = 12 - if self.fear_height ~= 0 then dropheight = self.fear_height end - local jumpheight = 0 - if self.jump and self.jump_height >= 4 then - jumpheight = min(ceil(self.jump_height / 4), 4) - elseif self.stepheight > 0.5 then - jumpheight = 1 - end - self.path.way = minetest.find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") - - self.state = "" - do_attack(self, self.attack) - - -- no path found, try something else - if not self.path.way then - - self.path.following = false - - -- lets make way by digging/building if not accessible - if self.pathfinding == 2 and mobs_griefing then - - -- is player higher than mob? - if s.y < p1.y then - - -- build upwards - if not minetest.is_protected(s, "") then - - local ndef1 = minetest.registered_nodes[self.standing_in] - - if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then - - minetest.set_node(s, {name = mcl_mobs.fallback_node}) - end - end - - local sheight = ceil(self.collisionbox[5]) + 1 - - -- assume mob is 2 blocks high so it digs above its head - s.y = s.y + sheight - - -- remove one block above to make room to jump - if not minetest.is_protected(s, "") then - - local node1 = node_ok(s, "air").name - local ndef1 = minetest.registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest.set_node(s, {name = "air"}) - minetest.add_item(s, ItemStack(node1)) - - end - end - - s.y = s.y - sheight - self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) - - else -- dig 2 blocks to make door toward player direction - - local yaw1 = self.object:get_yaw() + pi / 2 - local p1 = { - x = s.x + cos(yaw1), - y = s.y, - z = s.z + sin(yaw1) - } - - if not minetest.is_protected(p1, "") then - - local node1 = node_ok(p1, "air").name - local ndef1 = minetest.registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest.add_item(p1, ItemStack(node1)) - minetest.set_node(p1, {name = "air"}) - end - - p1.y = p1.y + 1 - node1 = node_ok(p1, "air").name - ndef1 = minetest.registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest.add_item(p1, ItemStack(node1)) - minetest.set_node(p1, {name = "air"}) - end - - end - end - end - - -- will try again in 2 seconds - self.path.stuck_timer = stuck_timeout - 2 - elseif s.y < p1.y and (not self.fly) then - do_jump(self) --add jump to pathfinding - self.path.following = true - -- Yay, I found path! - -- TODO: Implement war_cry sound without being annoying - --mob_sound(self, "war_cry", true) - else - set_velocity(self, self.walk_velocity) - - -- follow path now that it has it - self.path.following = true - end - end -end - - --- specific attacks -local specific_attack = function(list, what) - - -- no list so attack default (player, animals etc.) - if list == nil then - return true - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - --- find someone to attack -local monster_attack = function(self) - if not damage_enabled - or minetest.is_creative_enabled("") - or self.passive ~= false - or self.state == "attack" - or day_docile(self) then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then - type = "" - elseif (self.type == "monster" or self._aggro) then - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" - end - end - - -- find specific mob to attack, failing that attack player/npc/animal - if specific_attack(self.specific_attack, name) - and (type == "player" or ( type == "npc" and self.attack_npcs ) - or (type == "animal" and self.attack_animals == true)) then - - p = player:get_pos() - sp = s - - dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - - -- choose closest player to attack - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - -- attack player - if min_player then - do_attack(self, min_player) - end -end - - --- npc, find closest monster to attack -local npc_attack = function(self) - - if self.type ~= "npc" - or not self.attacks_monsters - or self.state == "attack" then - return - end - - local p, sp, obj, min_player - local s = self.object:get_pos() - local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj and obj.type == "monster" then - - p = obj.object:get_pos() - sp = s - - local dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = obj.object - end - end - end - - if min_player then - do_attack(self, min_player) - end -end - - --- specific runaway -local specific_runaway = function(list, what) - - -- no list so do not run - if list == nil then - return false - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - - --- find someone to runaway from -local runaway_from = function(self) - - if not self.runaway_from and self.state ~= "flop" then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - - if mcl_mobs.invis[ objs[n]:get_player_name() ] - or self.owner == objs[n]:get_player_name() - or (not object_in_range(self, objs[n])) then - type = "" - else - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" - end - end - - -- find specific mob to runaway from - if name ~= "" and name ~= self.name - and specific_runaway(self.runaway_from, name) then - - p = player:get_pos() - sp = s - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - dist = vector.distance(p, s) - - - -- choose closest player/mpb to runaway from - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - if min_player then - - local lp = player:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + pi - end - - yaw = set_yaw(self, yaw, 4) - self.state = "runaway" - self.runaway_timer = 3 - self.following = nil - end -end - - --- follow player if owner or holding item, if fish outta water then flop -local follow_flop = function(self) - - -- find player to follow - if (self.follow ~= "" - or self.order == "follow") - and not self.following - and self.state ~= "attack" - and self.order ~= "sit" - and self.state ~= "runaway" then - - local s = self.object:get_pos() - local players = minetest.get_connected_players() - - for n = 1, #players do - - if (object_in_range(self, players[n])) - and not mcl_mobs.invis[ players[n]:get_player_name() ] then - - self.following = players[n] - - break - end - end - end - - if self.type == "npc" - and self.order == "follow" - and self.state ~= "attack" - and self.order ~= "sit" - and self.owner ~= "" then - - -- npc stop following player if not owner - if self.following - and self.owner - and self.owner ~= self.following:get_player_name() then - self.following = nil - end - else - -- stop following player if not holding specific item, - -- mob is horny, fleeing or attacking - if self.following - and self.following:is_player() - and (follow_holding(self, self.following) == false or - self.horny or self.state == "runaway") then - self.following = nil - end - - end - - -- follow that thing - if self.following then - - local s = self.object:get_pos() - local p - - if self.following:is_player() then - - p = self.following:get_pos() - - elseif self.following.object then - - p = self.following.object:get_pos() - end - - if p then - - local dist = vector.distance(p, s) - - -- dont follow if out of range - if (not object_in_range(self, self.following)) then - self.following = nil - else - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + pi end - - set_yaw(self, yaw, 2.35) - - -- anyone but standing npc's can move along - if dist > 3 - and self.order ~= "stand" then - - set_velocity(self, self.follow_velocity) - - if self.walk_chance ~= 0 then - set_animation(self, "run") - end - else - set_velocity(self, 0) - set_animation(self, "stand") - end - - return - end - end - end - - -- swimmers flop when out of their element, and swim again when back in - if self.fly then - local s = self.object:get_pos() - if not flight_check(self, s) then - - self.state = "flop" - self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) - - local sdef = minetest.registered_nodes[self.standing_on] - -- Flop on ground - if sdef and sdef.walkable then - mob_sound(self, "flop") - self.object:set_velocity({ - x = random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), - y = FLOP_HEIGHT, - z = random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), - }) - end - - set_animation(self, "stand", true) - - return - elseif self.state == "flop" then - self.state = "stand" - self.object:set_acceleration({x = 0, y = 0, z = 0}) - set_velocity(self, 0) - end - end -end - - --- dogshoot attack switch and counter function -local dogswitch = function(self, dtime) - - -- switch mode not activated - if not self.dogshoot_switch - or not dtime then - return 0 - end - - self.dogshoot_count = self.dogshoot_count + dtime - - if (self.dogshoot_switch == 1 - and self.dogshoot_count > self.dogshoot_count_max) - or (self.dogshoot_switch == 2 - and self.dogshoot_count > self.dogshoot_count2_max) then - - self.dogshoot_count = 0 - - if self.dogshoot_switch == 1 then - self.dogshoot_switch = 2 - else - self.dogshoot_switch = 1 - end - end - - return self.dogshoot_switch -end - -local function go_to_pos(entity,b) - if not entity then return end - local s=entity.object:get_pos() - if not b then - --self.state = "stand" - return end - if vector.distance(b,s) < 1 then - --set_velocity(entity,0) - return true - end - local v = { x = b.x - s.x, z = b.z - s.z } - local yaw = (atann(v.z / v.x) + pi / 2) - entity.rotate - if b.x > s.x then yaw = yaw + pi end - entity.object:set_yaw(yaw) - set_velocity(entity,entity.follow_velocity) - mcl_mobs:set_animation(entity, "walk") -end - -local function check_doors(self) - local p = self.object:get_pos() - local t = minetest.get_timeofday() - local dd = minetest.find_nodes_in_area(vector.offset(p,-1,-1,-1),vector.offset(p,1,1,1),{"group:door"}) - for _,d in pairs(dd) do - local n = minetest.get_node(d) - if n.name:find("_b_") then - local def = minetest.registered_nodes[n.name] - local closed = n.name:find("_b_1") - if t < 0.3 or t > 0.8 then - if not closed and def.on_rightclick then def.on_rightclick(d,n,self) end - else - if closed and def.on_rightclick then def.on_rightclick(d,n,self) end - end - - end + for _,p in pairs(minetest.get_connected_players()) do + self:remove_particlespawners(p:get_player_name()) end -end - -local gowp_etime = 0 - -local function check_gowp(self,dtime) - gowp_etime = gowp_etime + dtime - if gowp_etime < 0.2 then return end - gowp_etime = 0 - local p = self.object:get_pos() - if not p or not self._target then return end - if vector.distance(p,self._target) < 1 then - self.waypoints = nil - self._target = nil - self.current_target = nil - self.state = "stand" - if self.callback_arrived then return self.callback_arrived(self) end - return true - end - if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 2 ) then - self.current_target = table.remove(self.waypoints, 1) - --minetest.log("nextwp:".. tostring(self.current_target) ) - go_to_pos(self,self.current_target) - return - elseif self.current_target then - go_to_pos(self,self.current_target) - end - - if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then - self.waypoints=minetest.find_path(p,self._target,150,1,4) - if not self.waypoints then self.state = "walk" end --give up - self.current_target = nil - return - end - if not self.current_target then - --minetest.log("no path") - self.state = "walk" - end -end - --- execute current state (stand, walk, run, attacks) --- returns true if mob has died -local do_states = function(self, dtime) - if self.can_open_doors then check_doors(self) end - - local yaw = self.object:get_yaw() or 0 - - if self.state == "stand" then - if random(1, 4) == 1 then - - local s = self.object:get_pos() - local objs = minetest.get_objects_inside_radius(s, 3) - local lp - for n = 1, #objs do - if objs[n]:is_player() then - lp = objs[n]:get_pos() - break - end - end - - -- look at any players nearby, otherwise turn randomly - if lp and self.look_at_players then - - local vec = { - x = lp.x - s.x, - z = lp.z - s.z - } - - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - if lp.x > s.x then yaw = yaw + pi end - else - yaw = yaw + random(-0.5, 0.5) - end - - yaw = set_yaw(self, yaw, 8) - end - if self.order == "sit" then - set_animation(self, "sit") - set_velocity(self, 0) - else - set_animation(self, "stand") - set_velocity(self, 0) - end - - -- npc's ordered to stand stay standing - if self.type ~= "npc" - or self.order ~= "stand" then - - if self.walk_chance ~= 0 - and self.facing_fence ~= true - and random(1, 100) <= self.walk_chance - and is_at_cliff_or_danger(self) == false then - - set_velocity(self, self.walk_velocity) - self.state = "walk" - set_animation(self, "walk") - end - end - - elseif self.state == "gowp" then - check_gowp(self,dtime) - - elseif self.state == "walk" then - local s = self.object:get_pos() - local lp = nil - - -- is there something I need to avoid? - if (self.water_damage > 0 - and self.lava_damage > 0) - or self.breath_max ~= -1 then - - lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) - - elseif self.water_damage > 0 then - - lp = minetest.find_node_near(s, 1, {"group:water"}) - - elseif self.lava_damage > 0 then - - lp = minetest.find_node_near(s, 1, {"group:lava"}) - - elseif self.fire_damage > 0 then - - lp = minetest.find_node_near(s, 1, {"group:fire"}) - - end - - local is_in_danger = false - if lp then - -- If mob in or on dangerous block, look for land - if (is_node_dangerous(self, self.standing_in) or - is_node_dangerous(self, self.standing_on)) or (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) and (not self.fly) then - is_in_danger = true - - -- If mob in or on dangerous block, look for land - if is_in_danger then - -- Better way to find shore - copied from upstream - lp = minetest.find_nodes_in_area_under_air( - {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, - {x = s.x + 5, y = s.y + 1, z = s.z + 5}, - {"group:solid"}) - - lp = #lp > 0 and lp[random(#lp)] - - -- did we find land? - if lp then - - local vec = { - x = lp.x - s.x, - z = lp.z - s.z - } - - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - - if lp.x > s.x then yaw = yaw + pi end - - -- look towards land and move in that direction - yaw = set_yaw(self, yaw, 6) - set_velocity(self, self.walk_velocity) - - end - end - - -- A danger is near but mob is not inside - else - - -- Randomly turn - if random(1, 100) <= 30 then - yaw = yaw + random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - end - - yaw = set_yaw(self, yaw, 8) - - -- otherwise randomly turn - elseif random(1, 100) <= 30 then - - yaw = yaw + random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - - -- stand for great fall or danger or fence in front - local cliff_or_danger = false - if is_in_danger then - cliff_or_danger = is_at_cliff_or_danger(self) - end - if self.facing_fence == true - or cliff_or_danger - or random(1, 100) <= 30 then - - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - - set_velocity(self, self.walk_velocity) - - if flight_check(self) - and self.animation - and self.animation.fly_start - and self.animation.fly_end then - set_animation(self, "fly") - else - set_animation(self, "walk") - end - end - - -- runaway when punched - elseif self.state == "runaway" then - - self.runaway_timer = self.runaway_timer + 1 - - -- stop after 5 seconds or when at cliff - if self.runaway_timer > 5 - or is_at_cliff_or_danger(self) then - self.runaway_timer = 0 - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - set_velocity(self, self.run_velocity) - set_animation(self, "run") - end - - -- attack routines (explode, dogfight, shoot, dogshoot) - elseif self.state == "attack" then - - local s = self.object:get_pos() - local p = self.attack:get_pos() or s - - -- stop attacking if player invisible or out of range - if not self.attack - or not self.attack:get_pos() - or not object_in_range(self, self.attack) - or self.attack:get_hp() <= 0 - or (self.attack:is_player() and mcl_mobs.invis[ self.attack:get_player_name() ]) then - - self.state = "stand" - set_velocity(self, 0) - set_animation(self, "stand") - self.attack = nil - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.path.way = nil - - return - end - - -- calculate distance from mob and enemy - local dist = vector.distance(p, s) - - if self.attack_type == "explode" then - - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - local node_break_radius = self.explosion_radius or 1 - local entity_damage_radius = self.explosion_damage_radius - or (node_break_radius * 2) - - -- start timer when in reach and line of sight - if not self.v_start - and dist <= self.reach - and line_of_sight(self, s, p, 2) then - - self.v_start = true - self.timer = 0 - self.blinktimer = 0 - mob_sound(self, "fuse", nil, false) - - -- stop timer if out of reach or direct line of sight - elseif self.allow_fuse_reset - and self.v_start - and (dist >= self.explosiontimer_reset_radius - or not line_of_sight(self, s, p, 2)) then - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.blinkstatus = false - remove_texture_mod(self, "^[brighten") - end - - -- walk right up to player unless the timer is active - if self.v_start and (self.stop_to_explode or dist < self.reach) then - set_velocity(self, 0) - else - set_velocity(self, self.run_velocity) - end - - if self.animation and self.animation.run_start then - set_animation(self, "run") - else - set_animation(self, "walk") - end - - if self.v_start then - - self.timer = self.timer + dtime - self.blinktimer = (self.blinktimer or 0) + dtime - - if self.blinktimer > 0.2 then - - self.blinktimer = 0 - - if self.blinkstatus then - remove_texture_mod(self, "^[brighten") - else - add_texture_mod(self, "^[brighten") - end - - self.blinkstatus = not self.blinkstatus - end - - if self.timer > self.explosion_timer then - - local pos = self.object:get_pos() - - if mobs_griefing and not minetest.is_protected(pos, "") then - mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) - else - minetest.sound_play(self.sounds.explode, { - pos = pos, - gain = 1.0, - max_hear_distance = self.sounds.distance or 32 - }, true) - - entity_physics(pos, entity_damage_radius) - effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0) - end - mcl_burning.extinguish(self.object) - self.object:remove() - - return true - end - end - - elseif self.attack_type == "dogfight" - or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 2) - or (self.attack_type == "dogshoot" and dist <= self.reach and dogswitch(self) == 0) then - - if self.fly - and dist > self.reach then - - local p1 = s - local me_y = floor(p1.y) - local p2 = p - local p_y = floor(p2.y + 1) - local v = self.object:get_velocity() - - if flight_check(self, s) then - - if me_y < p_y then - - self.object:set_velocity({ - x = v.x, - y = 1 * self.walk_velocity, - z = v.z - }) - - elseif me_y > p_y then - - self.object:set_velocity({ - x = v.x, - y = -1 * self.walk_velocity, - z = v.z - }) - end - else - if me_y < p_y then - - self.object:set_velocity({ - x = v.x, - y = 0.01, - z = v.z - }) - - elseif me_y > p_y then - - self.object:set_velocity({ - x = v.x, - y = -0.01, - z = v.z - }) - end - end - - end - - -- rnd: new movement direction - if self.path.following - and self.path.way - and self.attack_type ~= "dogshoot" then - - -- no paths longer than 50 - if #self.path.way > 50 - or dist < self.reach then - self.path.following = false - return - end - - local p1 = self.path.way[1] - - if not p1 then - self.path.following = false - return - end - - if abs(p1.x-s.x) + abs(p1.z - s.z) < 0.6 then - -- reached waypoint, remove it from queue - table.remove(self.path.way, 1) - end - - -- set new temporary target - p = {x = p1.x, y = p1.y, z = p1.z} - end - - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - -- move towards enemy if beyond mob reach - if dist > self.reach then - - -- path finding by rnd - if self.pathfinding -- only if mob has pathfinding enabled - and enable_pathfinding then - - smart_mobs(self, s, p, dist, dtime) - end - - if is_at_cliff_or_danger(self) then - - set_velocity(self, 0) - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - - if self.path.stuck then - set_velocity(self, self.walk_velocity) - else - set_velocity(self, self.run_velocity) - end - - if self.animation and self.animation.run_start then - set_animation(self, "run") - else - set_animation(self, "walk") - end - end - - else -- rnd: if inside reach range - - self.path.stuck = false - self.path.stuck_timer = 0 - self.path.following = false -- not stuck anymore - - set_velocity(self, 0) - - if not self.custom_attack then - - if self.timer > 1 then - - self.timer = 0 - - if self.double_melee_attack - and random(1, 2) == 1 then - set_animation(self, "punch2") - else - set_animation(self, "punch") - end - - local p2 = p - local s2 = s - - p2.y = p2.y + .5 - s2.y = s2.y + .5 - - if line_of_sight(self, p2, s2) == true then - - -- play attack sound - mob_sound(self, "attack") - - -- punch player (or what player is attached to) - local attached = self.attack:get_attach() - if attached then - self.attack = attached - end - self.attack:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self.damage} - }, nil) - end - end - else -- call custom attack every second - if self.custom_attack - and self.timer > 1 then - - self.timer = 0 - - self.custom_attack(self, p) - end - end - end - - elseif self.attack_type == "shoot" - or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 1) - or (self.attack_type == "dogshoot" and dist > self.reach and dogswitch(self) == 0) then - - p.y = p.y - .5 - s.y = s.y + .5 - - local dist = vector.distance(p, s) - local vec = { - x = p.x - s.x, - y = p.y - s.y, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - set_velocity(self, 0) - - local p = self.object:get_pos() - p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 - - if self.shoot_interval - and self.timer > self.shoot_interval - and not minetest.raycast(p, self.attack:get_pos(), false, false):next() - and random(1, 100) <= 60 then - - self.timer = 0 - set_animation(self, "shoot") - - -- play shoot attack sound - mob_sound(self, "shoot_attack") - - -- Shoot arrow - if minetest.registered_entities[self.arrow] then - - local arrow, ent - local v = 1 - if not self.shoot_arrow then - self.firing = true - minetest.after(1, function() - self.firing = false - end) - arrow = minetest.add_entity(p, self.arrow) - ent = arrow:get_luaentity() - if ent.velocity then - v = ent.velocity - end - ent.switch = 1 - ent.owner_id = tostring(self.object) -- add unique owner id to arrow - - -- important for mcl_shields - ent._shooter = self.object - ent._saved_shooter_pos = self.object:get_pos() - end - - local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 - -- offset makes shoot aim accurate - vec.y = vec.y + self.shoot_offset - vec.x = vec.x * (v / amount) - vec.y = vec.y * (v / amount) - vec.z = vec.z * (v / amount) - if self.shoot_arrow then - vec = vector.normalize(vec) - self:shoot_arrow(p, vec) - else - arrow:set_velocity(vec) - end - end - end - end - end -end - -local plane_adjacents = { - vector.new(1,0,0), - vector.new(-1,0,0), - vector.new(0,0,1), - vector.new(0,0,-1), -} - - -local gopath_last = os.time() -function mcl_mobs:gopath(self,target,callback_arrived) - if os.time() - gopath_last < 15 then return end - gopath_last = os.time() - --minetest.log("gowp") - local p = self.object:get_pos() - local t = vector.offset(target,0,1,0) - local wp = minetest.find_path(p,t,150,1,4) - if not wp then - local d = minetest.find_node_near(target,16,{"group:door"}) - if d then - for _,v in pairs(plane_adjacents) do - local pos = vector.add(d,v) - local n = minetest.get_node(pos) - if n.name == "air" then - wp = minetest.find_path(p,pos,150,1,4) - if wp then break end - end - end - end - end - if wp and #wp > 0 then - self._target = t - self.callback_arrived = callback_arrived - table.remove(wp,1) - self.waypoints = wp - self.state = "gowp" - return true - else - self.state = "walk" - self.waypoints = nil - self.current_target = nil - -- minetest.log("no path found") - end -end - -local function player_near(pos) - for _,o in pairs(minetest.get_objects_inside_radius(pos,2)) do - if o:is_player() then return true end - end -end - -local function check_item_pickup(self) - if self.pick_up and #self.pick_up > 0 then - local p = self.object:get_pos() - for _,o in pairs(minetest.get_objects_inside_radius(p,2)) do - local l=o:get_luaentity() - if l and l.name == "__builtin:item" then - for k,v in pairs(self.pick_up) do - if not player_near(p) and self.on_pick_up and l.itemstring:find(v) then - if self.on_pick_up(self,l) == nil then o:remove() end - end - end - end - end - end -end - -local function damage_mob(self,reason,damage) - if not self.health then return end - damage = floor(damage) - if damage > 0 then - self.health = self.health - damage - - effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil) - - if check_for_death(self, reason, {type = reason}) then - return true - end - end -end - -local function check_entity_cramming(self) - local p = self.object:get_pos() - if not p then return end - local oo = minetest.get_objects_inside_radius(p,1) - local mobs = {} - for _,o in pairs(oo) do - local l = o:get_luaentity() - if l and l.is_mob and l.health > 0 then table.insert(mobs,l) end - end - local clear = #mobs < ENTITY_CRAMMING_MAX - local ncram = {} - for _,l in pairs(mobs) do - if l then - if clear then - l.cram = nil - elseif l.cram == nil and not self.child then - table.insert(ncram,l) - elseif l.cram then - damage_mob(l,"cramming",CRAMMING_DAMAGE) - end - end - end - for i,l in pairs(ncram) do - if i > ENTITY_CRAMMING_MAX then - l.cram = true - else - l.cram = nil - end - end -end - --- falling and fall damage --- returns true if mob died -local falling = function(self, pos) - - if self.fly and self.state ~= "die" then - return - end - - if mcl_portals ~= nil then - if mcl_portals.nether_portal_cooloff(self.object) then - return false -- mob has teleported through Nether portal - it's 99% not falling - end - end - - -- floating in water (or falling) - local v = self.object:get_velocity() - - if v.y > 0 then - - -- apply gravity when moving up - self.object:set_acceleration({ - x = 0, - y = -10, - z = 0 - }) - - elseif v.y <= 0 and v.y > self.fall_speed then - - -- fall downwards at set speed - self.object:set_acceleration({ - x = 0, - y = self.fall_speed, - z = 0 - }) - else - -- stop accelerating once max fall speed hit - self.object:set_acceleration({x = 0, y = 0, z = 0}) - end - - if minetest.registered_nodes[node_ok(pos).name].groups.lava then - - if self.floats_on_lava == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (max(1, v.y) ^ 2), - z = 0 - }) - end - end - - -- in water then float up - if minetest.registered_nodes[node_ok(pos).name].groups.water then - - if self.floats == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (max(1, v.y) ^ 2), - z = 0 - }) - end - else - - -- fall damage onto solid ground - if self.fall_damage == 1 - and self.object:get_velocity().y == 0 then - - local d = (self.old_y or 0) - self.object:get_pos().y - - if d > 5 then - - local add = minetest.get_item_group(self.standing_on, "fall_damage_add_percent") - local damage = d - 5 - if add ~= 0 then - damage = damage + damage * (add/100) - end - damage_mob(self,"fall",damage) - end - - self.old_y = self.object:get_pos().y - end - end -end - -local teleport = function(self, target) - if self.do_teleport then - if self.do_teleport(self, target) == false then - return - end - end -end - - --- deal damage and effects when mob punched -local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) - - -- custom punch function - if self.do_punch then - - -- when false skip going any further - if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then - return - end - end - - -- error checking when mod profiling is enabled - if not tool_capabilities then - minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") - return - end - - local is_player = hitter:is_player() - - if is_player then - -- is mob protected? - if self.protected and minetest.is_protected(self.object:get_pos(), hitter:get_player_name()) then - return - end - - if minetest.is_creative_enabled(hitter:get_player_name()) then - self.health = 0 - end - - -- set/update 'drop xp' timestamp if hitted by player - self.xp_timestamp = minetest.get_us_time() - end - - - -- punch interval - local weapon = hitter:get_wielded_item() - local punch_interval = 1.4 - - -- exhaust attacker - if is_player then - mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) - end - - -- calculate mob damage - local damage = 0 - local armor = self.object:get_armor_groups() or {} - local tmp - - -- quick error check incase it ends up 0 (serialize.h check test) - if tflp == 0 then - tflp = 0.2 - end - - - for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do - - tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) - - if tmp < 0 then - tmp = 0.0 - elseif tmp > 1 then - tmp = 1.0 - end - - damage = damage + (tool_capabilities.damage_groups[group] or 0) - * tmp * ((armor[group] or 0) / 100.0) - end - - if weapon then - local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") - if fire_aspect_level > 0 then - mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) - end - end - - -- check for tool immunity or special damage - for n = 1, #self.immune_to do - - if self.immune_to[n][1] == weapon:get_name() then - - damage = self.immune_to[n][2] or 0 - break - end - end - - -- healing - if damage <= -1 then - self.health = self.health - floor(damage) - return - end - - if tool_capabilities then - punch_interval = tool_capabilities.full_punch_interval or 1.4 - end - - -- add weapon wear manually - -- Required because we have custom health handling ("health" property) - if minetest.is_creative_enabled("") ~= true - and tool_capabilities then - if tool_capabilities.punch_attack_uses then - -- Without this delay, the wear does not work. Quite hacky ... - minetest.after(0, function(name) - local player = minetest.get_player_by_name(name) - if not player then return end - local weapon = hitter:get_wielded_item(player) - local def = weapon:get_definition() - if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then - local wear = floor(65535/tool_capabilities.punch_attack_uses) - weapon:add_wear(wear) - hitter:set_wielded_item(weapon) - end - end, hitter:get_player_name()) - end - end - - local die = false - - - if damage >= 0 then - -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. - if damage >= 0.1 then - -- weapon sounds - if weapon:get_definition().sounds ~= nil then - - local s = random(0, #weapon:get_definition().sounds) - - minetest.sound_play(weapon:get_definition().sounds[s], { - object = self.object, --hitter, - max_hear_distance = 8 - }, true) - else - minetest.sound_play("default_punch", { - object = self.object, - max_hear_distance = 5 - }, true) - end - - damage_effect(self, damage) - - -- do damage - self.health = self.health - damage - - -- skip future functions if dead, except alerting others - if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then - die = true - end - end - -- knock back effect (only on full punch) - if not die - and self.knock_back - and tflp >= punch_interval then - - local v = self.object:get_velocity() - local r = 1.4 - min(punch_interval, 1.4) - local kb = r * 2.0 - local up = 2 - - -- if already in air then dont go up anymore when hit - if v.y ~= 0 - or self.fly then - up = 0 - end - - -- direction error check - dir = dir or {x = 0, y = 0, z = 0} - - -- check if tool already has specific knockback value - if tool_capabilities.damage_groups["knockback"] then - kb = tool_capabilities.damage_groups["knockback"] - else - kb = kb * 1.5 - end - - - local luaentity - if hitter then - luaentity = hitter:get_luaentity() - end - if hitter and is_player then - local wielditem = hitter:get_wielded_item() - kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") - elseif luaentity and luaentity._knockback then - kb = kb + luaentity._knockback - end - - self.object:set_velocity({ - x = dir.x * kb, - y = dir.y * kb + up * 2, - z = dir.z * kb - }) - - self.pause_timer = 0.25 - end - end -- END if damage - - -- if skittish then run away - if not die and self.runaway == true and self.state ~= "flop" then - - local lp = hitter:get_pos() - local s = self.object:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + pi - end - - yaw = set_yaw(self, yaw, 6) - self.state = "runaway" - self.runaway_timer = 0 - self.following = nil - end - - local name = hitter:get_player_name() or "" - - -- attack puncher and call other mobs for help - if self.passive == false - and self.state ~= "flop" - and (self.child == false or self.type == "monster") - and hitter:get_player_name() ~= self.owner - and not mcl_mobs.invis[ name ] then - if not die then - -- attack whoever punched mob - self.state = "" - do_attack(self, hitter) - self._aggro= true - end - - -- alert others to the attack - local objs = minetest.get_objects_inside_radius(hitter:get_pos(), self.view_range) - local obj = nil - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj then - -- only alert members of same mob or friends - if obj.group_attack - and obj.state ~= "attack" - and obj.owner ~= name then - if obj.name == self.name then - do_attack(obj, hitter) - elseif type(obj.group_attack) == "table" then - for i=1, #obj.group_attack do - if obj.name == obj.group_attack[i] then - obj._aggro = true - do_attack(obj, hitter) - break - end - end - end - end - - -- have owned mobs attack player threat - if obj.owner == name and obj.owner_loyal then - do_attack(obj, self.object) - end - end - end - end -end - -local mob_detach_child = function(self, child) - - if self.driver == child then - self.driver = nil - end - -end - --- get entity staticdata -local mob_staticdata = function(self) - - -- remove mob when out of range unless tamed if remove_far and self.can_despawn @@ -3413,10 +95,8 @@ 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(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 - mcl_burning.extinguish(self.object) - self.object:remove() return "remove"-- nil end @@ -3443,25 +123,19 @@ local mob_staticdata = function(self) return minetest.serialize(tmp) end - --- activate mob and reload settings -local mob_activate = function(self, staticdata, def, dtime) - - -- remove monsters in peaceful mode +function mob_class:mob_activate(staticdata, def, dtime) + if not self.object:get_pos() or staticdata == "remove" then + mcl_burning.extinguish(self.object) + self.object:remove() + return + end if self.type == "monster" and minetest.settings:get_bool("only_peaceful_mobs", false) then mcl_burning.extinguish(self.object) self.object:remove() - return end - if staticdata == "remove" then - mcl_burning.extinguish(self.object) - self.object:remove() - return - end - -- load entity variables local tmp = minetest.deserialize(staticdata) if tmp then @@ -3470,7 +144,6 @@ local mob_activate = function(self, staticdata, def, dtime) end end - -- select random texture, set model and size if not self.base_texture then -- compatiblity with old simple mobs textures @@ -3481,38 +154,33 @@ local mob_activate = function(self, staticdata, def, dtime) local c = 1 if #def.textures > c then c = #def.textures end - self.base_texture = def.textures[random(c)] + self.base_texture = def.textures[math.random(c)] self.base_mesh = def.mesh self.base_size = self.visual_size self.base_colbox = self.collisionbox self.base_selbox = self.selectionbox end - -- for current mobs that dont have this set if not self.base_selbox then self.base_selbox = self.selectionbox or self.base_colbox end - -- set texture, model and size local textures = self.base_texture local mesh = self.base_mesh local vis_size = self.base_size local colbox = self.base_colbox local selbox = self.base_selbox - -- specific texture if gotten if self.gotten == true and def.gotten_texture then textures = def.gotten_texture end - -- specific mesh if gotten if self.gotten == true and def.gotten_mesh then mesh = def.gotten_mesh end - -- set child objects to half size if self.child == true then vis_size = { @@ -3543,13 +211,12 @@ local mob_activate = function(self, staticdata, def, dtime) end if self.health == 0 then - self.health = random (self.hp_min, self.hp_max) + self.health = math.random (self.hp_min, self.hp_max) end if self.breath == nil then self.breath = self.breath_max end - -- pathfinding init self.path = {} self.path.way = {} -- path to follow, table of positions self.path.lastpos = {x = 0, y = 0, z = 0} @@ -3589,64 +256,102 @@ local mob_activate = function(self, staticdata, def, dtime) self.blinktimer = 0 self.blinkstatus = false - -- check existing nametag if not self.nametag then self.nametag = def.nametag end - - -- set anything changed above - self.object:set_properties(self) - set_yaw(self, (random(0, 360) - 180) / 180 * pi, 6) - update_tag(self) - set_animation(self, "stand") - - -- run on_spawn function if found - if self.on_spawn and not self.on_spawn_run then - if self.on_spawn(self) then - self.on_spawn_run = true -- if true, set flag to run once only + if not self.custom_visual_size then + self.visual_size = nil + self.base_size = self.visual_size + if self.child then + self.visual_size = { + x = self.visual_size.x * 0.5, + y = self.visual_size.y * 0.5, + } end end - -- run after_activate + self.object:set_properties(self) + self:set_yaw( (math.random(0, 360) - 180) / 180 * math.pi, 6) + self:update_tag() + self._current_animation = nil + self:set_animation( "stand") + + if self.on_spawn and not self.on_spawn_run then + if self.on_spawn(self) then + self.on_spawn_run = true + end + end + + if not self.wears_armor and self.armor_list then + self.armor_list = nil + end + + if not self._run_armor_init and self.wears_armor then + self.armor_list={helmet="",chestplate="",boots="",leggings=""} + self:set_armor_texture() + self._run_armor_init = true + end + if def.after_activate then def.after_activate(self, staticdata, def, dtime) end end -local function check_aggro(self,dtime) - if not self._aggro or not self.attack then return end - if not self._check_aggro_timer or self._check_aggro_timer > 5 then - self._check_aggro_timer = 0 - if not self.attack:get_pos() or vector.distance(self.attack:get_pos(),self.object:get_pos()) > 128 then - self._aggro = nil - self.attack = nil - self.state = "stand" - end - end - self._check_aggro_timer = self._check_aggro_timer + dtime -end + -- main mob function -local mob_step = function(self, dtime) +function mob_class:on_step(dtime) self.lifetimer = self.lifetimer - dtime - check_item_pickup(self) - check_aggro(self,dtime) + local pos = self.object:get_pos() + if not pos then return end + if self:check_despawn(pos) then return true end + + local d = 0.85 + if self:check_dying() then d = 0.92 end + + local v = self.object:get_velocity() + if v then + --diffuse object velocity + self.object:set_velocity({x = v.x*d, y = v.y, z = v.z*d}) + end + + if self:falling(pos) then return end + + self:check_suspend() + self:check_water_flow() + + local yaw = 0 + if self:is_at_water_danger() and self.state ~= "attack" then + if math.random(1, 10) <= 6 then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + yaw = yaw + math.random(-0.5, 0.5) + yaw = self:set_yaw( yaw, 8) + end + else + if self.move_in_group ~= false then + self:check_herd(dtime) + end + end + + if self:is_at_cliff_or_danger() then + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + local yaw = self.object:get_yaw() or 0 + yaw = self:set_yaw( yaw + 0.78, 8) + end + if not self.fire_resistant then mcl_burning.tick(self.object, dtime, self) -- mcl_burning.tick may remove object immediately if not self.object:get_pos() then return end end - local pos = self.object:get_pos() - local yaw = 0 + if mobs_debug then self:update_tag() end - if mobs_debug then - update_tag(self) - end - - if self.state == "die" then - return - end + if self.state == "die" then return end if self.jump_sound_cooloff > 0 then self.jump_sound_cooloff = self.jump_sound_cooloff - dtime @@ -3654,54 +359,22 @@ local mob_step = function(self, dtime) if self.opinion_sound_cooloff > 0 then self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime end - if falling(self, pos) then - -- Return if mob died after falling - return - end - -- smooth rotation by ThomasMonroe314 + --Mob following code. + self:follow_flop() + --set animation speed relitive to velocity + self:set_animation_speed() + self:check_smooth_rotation(dtime) + self:check_head_swivel(dtime) - if self.delay and self.delay > 0 then + self:do_jump() + self:set_armor_texture() + self:check_runaway_from() - local yaw = self.object:get_yaw() or 0 - - if self.delay == 1 then - yaw = self.target_yaw - else - local dif = abs(yaw - self.target_yaw) - - if yaw > self.target_yaw then - - if dif > pi then - dif = 2 * pi - dif -- need to add - yaw = yaw + dif / self.delay - else - yaw = yaw - dif / self.delay -- need to subtract - end - - elseif yaw < self.target_yaw then - - if dif > pi then - dif = 2 * pi - dif - yaw = yaw - dif / self.delay -- need to subtract - else - yaw = yaw + dif / self.delay -- need to add - end - end - - if yaw > (pi * 2) then yaw = yaw - (pi * 2) end - if yaw < 0 then yaw = yaw + (pi * 2) end - end - - self.delay = self.delay - 1 - if self.shaking then - yaw = yaw + (random() * 2 - 1) * 5 * dtime - end - self.object:set_yaw(yaw) - update_roll(self) - end - - -- end rotation + self:monster_attack() + self:npc_attack() + self:check_breeding() + self:check_aggro(dtime) -- run custom function (defined in mob lua file) if self.do_custom then @@ -3723,13 +396,14 @@ local mob_step = function(self, dtime) -- attack timer self.timer = self.timer + dtime - if self.state ~= "attack" and self.state ~= "gowp" then + if self.state ~= "attack" and self.state ~= PATHFINDING then if self.timer < 1 then return end - self.timer = 0 end + self:check_particlespawners(dtime) + self:check_item_pickup() -- never go over 100 if self.timer > 100 then @@ -3737,8 +411,8 @@ local mob_step = function(self, dtime) end -- mob plays random sound at times - if random(1, 70) == 1 then - mob_sound(self, "random", true) + if math.random(1, 70) == 1 then + self:mob_sound("random", true) end -- environmental damage timer (every 1 second) @@ -3746,773 +420,25 @@ local mob_step = function(self, dtime) if (self.state == "attack" and self.env_damage_timer > 1) or self.state ~= "attack" then - check_entity_cramming(self) + self:check_entity_cramming() self.env_damage_timer = 0 -- check for environmental damage (water, fire, lava etc.) - if do_env_damage(self) then + if self:do_env_damage() then return end -- node replace check (cow eats grass etc.) - replace(self, pos) + self:replace(pos) end - monster_attack(self) - - npc_attack(self) - - breed(self) - - if do_states(self, dtime) then + if self:do_states(dtime) then return end if not self.object:get_luaentity() then return false end - - do_jump(self) - - runaway_from(self) - - if is_at_water_danger(self) and self.state ~= "attack" then - if random(1, 10) <= 6 then - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - yaw = yaw + random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - end - - -- Add water flowing for mobs from mcl_item_entity - local p, node, nn, def - p = self.object:get_pos() - node = minetest.get_node_or_nil(p) - if node then - nn = node.name - def = minetest.registered_nodes[nn] - end - - -- Move item around on flowing liquids - if def and def.liquidtype == "flowing" then - - --[[ Get flowing direction (function call from flowlib), if there's a liquid. - NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. - Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] - local vec = flowlib.quick_flow(p, node) - -- Just to make sure we don't manipulate the speed for no reason - if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then - -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" - local f = 1.39 - -- Set new item moving speed into the direciton of the liquid - local newv = vector.multiply(vec, f) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) - - self.physical_state = true - self._flowing = true - self.object:set_properties({ - physical = true - }) - return - end - elseif self._flowing == true then - -- Disable flowing physics if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) - return - end - - --Mob following code. - follow_flop(self) - - if is_at_cliff_or_danger(self) then - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - 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 - - --- default function when mobs are blown up with TNT -local do_tnt = function(obj, damage) - - obj.object:punch(obj.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = damage}, - }, nil) - - return false, true, {} -end - - -mcl_mobs.spawning_mobs = {} - --- Code to execute before custom on_rightclick handling -local on_rightclick_prefix = function(self, clicker) - local item = clicker:get_wielded_item() - - -- Name mob with nametag - if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then - - local tag = item:get_meta():get_string("name") - if tag ~= "" then - if string.len(tag) > MAX_MOB_NAME_LENGTH then - tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) - end - self.nametag = tag - - update_tag(self) - - if not minetest.is_creative_enabled(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) - end - return true - end - - end - return false -end - -local create_mob_on_rightclick = function(on_rightclick) - return function(self, clicker) - local stop = on_rightclick_prefix(self, clicker) - if (not stop) and (on_rightclick) then - on_rightclick(self, clicker) - end - end -end - --- register mob entity -function mcl_mobs:register_mob(name, def) - - mcl_mobs.spawning_mobs[name] = true - -local can_despawn -if def.can_despawn ~= nil then - can_despawn = def.can_despawn -elseif def.spawn_class == "passive" then - can_despawn = false -else - can_despawn = true -end - -local function scale_difficulty(value, default, min, special) - if (not value) or (value == default) or (value == special) then - return default - else - return max(min, value * difficulty) - end -end - -local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} --- Workaround for : --- Increase upper Y limit to avoid mobs glitching through solid nodes. --- FIXME: Remove workaround if it's no longer needed. -if collisionbox[5] < 0.79 then - collisionbox[5] = 0.79 -end - -minetest.register_entity(name, { - - use_texture_alpha = def.use_texture_alpha, - stepheight = def.stepheight or 0.6, - name = name, - description = def.description, - type = def.type, - attack_type = def.attack_type, - fly = def.fly, - fly_in = def.fly_in or {"air", "__airlike"}, - owner = def.owner or "", - order = def.order or "", - on_die = def.on_die, - spawn_small_alternative = def.spawn_small_alternative, - do_custom = def.do_custom, - jump_height = def.jump_height or 4, -- was 6 - rotate = math.rad(def.rotate or 0), -- 0=front, 90=side, 180=back, 270=side2 - lifetimer = def.lifetimer or 57.73, - hp_min = scale_difficulty(def.hp_min, 5, 1), - hp_max = scale_difficulty(def.hp_max, 10, 1), - xp_min = def.xp_min or 0, - xp_max = def.xp_max or 0, - xp_timestamp = 0, - breath_max = def.breath_max or 15, - breathes_in_water = def.breathes_in_water or false, - physical = true, - collisionbox = collisionbox, - selectionbox = def.selectionbox or def.collisionbox, - visual = def.visual, - visual_size = def.visual_size or {x = 1, y = 1}, - mesh = def.mesh, - makes_footstep_sound = def.makes_footstep_sound or false, - view_range = def.view_range or 16, - walk_velocity = def.walk_velocity or 1, - run_velocity = def.run_velocity or 2, - damage = scale_difficulty(def.damage, 0, 0), - light_damage = def.light_damage or 0, - sunlight_damage = def.sunlight_damage or 0, - water_damage = def.water_damage or 0, - lava_damage = def.lava_damage or 8, - fire_damage = def.fire_damage or 1, - suffocation = def.suffocation or true, - fall_damage = def.fall_damage or 1, - fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 - drops = def.drops or {}, - armor = def.armor or 100, - on_rightclick = create_mob_on_rightclick(def.on_rightclick), - arrow = def.arrow, - shoot_interval = def.shoot_interval, - sounds = def.sounds or {}, - animation = def.animation, - follow = def.follow, - nofollow = def.nofollow, - can_open_doors = def.can_open_doors, - jump = def.jump ~= false, - walk_chance = def.walk_chance or 50, - attacks_monsters = def.attacks_monsters or false, - group_attack = def.group_attack or false, - passive = def.passive or false, - knock_back = def.knock_back ~= false, - shoot_offset = def.shoot_offset or 0, - floats = def.floats or 1, -- floats in water by default - floats_on_lava = def.floats_on_lava or 0, - replace_rate = def.replace_rate, - replace_what = def.replace_what, - replace_with = def.replace_with, - replace_offset = def.replace_offset or 0, - on_replace = def.on_replace, - timer = 0, - env_damage_timer = 0, - tamed = false, - pause_timer = 0, - horny = false, - hornytimer = 0, - gotten = false, - health = 0, - reach = def.reach or 3, - htimer = 0, - texture_list = def.textures, - child_texture = def.child_texture, - docile_by_day = def.docile_by_day or false, - time_of_day = 0.5, - fear_height = def.fear_height or 0, - runaway = def.runaway, - runaway_timer = 0, - pathfinding = def.pathfinding, - immune_to = def.immune_to or {}, - explosion_radius = def.explosion_radius, -- LEGACY - explosion_damage_radius = def.explosion_damage_radius, -- LEGACY - explosiontimer_reset_radius = def.explosiontimer_reset_radius, - explosion_timer = def.explosion_timer or 3, - allow_fuse_reset = def.allow_fuse_reset ~= false, - stop_to_explode = def.stop_to_explode ~= false, - custom_attack = def.custom_attack, - double_melee_attack = def.double_melee_attack, - dogshoot_switch = def.dogshoot_switch, - dogshoot_count = 0, - dogshoot_count_max = def.dogshoot_count_max or 5, - dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), - attack_animals = def.attack_animals or false, - attack_npcs = def.attack_npcs or false, - specific_attack = def.specific_attack, - runaway_from = def.runaway_from, - owner_loyal = def.owner_loyal, - facing_fence = false, - is_mob = true, - pushable = def.pushable or true, - - - -- MCL2 extensions - teleport = teleport, - do_teleport = def.do_teleport, - spawn_class = def.spawn_class, - can_spawn = def.can_spawn, - ignores_nametag = def.ignores_nametag or false, - rain_damage = def.rain_damage or 0, - glow = def.glow, - can_despawn = can_despawn, - child = def.child or false, - texture_mods = {}, - shoot_arrow = def.shoot_arrow, - sounds_child = def.sounds_child, - pick_up = def.pick_up, - explosion_strength = def.explosion_strength, - suffocation_timer = 0, - follow_velocity = def.follow_velocity or 2.4, - instant_death = def.instant_death or false, - fire_resistant = def.fire_resistant or false, - fire_damage_resistant = def.fire_damage_resistant or false, - ignited_by_sunlight = def.ignited_by_sunlight or false, - spawn_in_group = def.spawn_in_group, - spawn_in_group_min = def.spawn_in_group_min, - noyaw = def.noyaw or false, - -- End of MCL2 extensions - - on_spawn = def.on_spawn, - - on_blast = def.on_blast or do_tnt, - - on_step = mob_step, - - do_punch = def.do_punch, - - on_punch = mob_punch, - - on_breed = def.on_breed, - - on_grown = def.on_grown, - - on_pick_up = def.on_pick_up, - - on_detach_child = mob_detach_child, - - on_activate = function(self, staticdata, dtime) - --this is a temporary hack so mobs stop - --glitching and acting really weird with the - --default built in engine collision detection - self.is_mob = true - self.object:set_properties({ - collide_with_objects = false, - }) - return mob_activate(self, staticdata, def, dtime) - end, - - get_staticdata = function(self) - return mob_staticdata(self) - end, - - harmed_by_heal = def.harmed_by_heal, - -}) - -if minetest.get_modpath("doc_identifier") ~= nil then - doc.sub.identifier.register_object(name, "basics", "mobs") -end - -end -- END mcl_mobs:register_mob function - - --- register arrow for shoot attack -function mcl_mobs:register_arrow(name, def) - - if not name or not def then return end -- errorcheck - - minetest.register_entity(name, { - - physical = false, - visual = def.visual, - visual_size = def.visual_size, - textures = def.textures, - velocity = def.velocity, - hit_player = def.hit_player, - hit_node = def.hit_node, - hit_mob = def.hit_mob, - hit_object = def.hit_object, - drop = def.drop or false, -- drops arrow as registered item when true - collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows - timer = 0, - switch = 0, - owner_id = def.owner_id, - rotate = def.rotate, - on_punch = function(self) - local vel = self.object:get_velocity() - self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) - end, - collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, - automatic_face_movement_dir = def.rotate - and (def.rotate - (pi / 180)) or false, - - on_activate = def.on_activate, - - on_step = def.on_step or function(self, dtime) - - self.timer = self.timer + 1 - - local pos = self.object:get_pos() - - if self.switch == 0 - or self.timer > 150 - or not within_limits(pos, 0) then - mcl_burning.extinguish(self.object) - self.object:remove(); - - return - end - - -- does arrow have a tail (fireball) - if def.tail - and def.tail == 1 - and def.tail_texture then - - minetest.add_particle({ - pos = pos, - velocity = {x = 0, y = 0, z = 0}, - acceleration = {x = 0, y = 0, z = 0}, - expirationtime = def.expire or 0.25, - collisiondetection = false, - texture = def.tail_texture, - size = def.tail_size or 5, - glow = def.glow or 0, - }) - end - - if self.hit_node then - - local node = node_ok(pos).name - - if minetest.registered_nodes[node].walkable then - - self.hit_node(self, pos, node) - - if self.drop == true then - - pos.y = pos.y + 1 - - self.lastpos = (self.lastpos or pos) - - minetest.add_item(self.lastpos, self.object:get_luaentity().name) - end - - self.object:remove(); - - return - end - end - - if self.hit_player or self.hit_mob or self.hit_object then - - for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do - - if self.hit_player - and player:is_player() then - - self.hit_player(self, player) - self.object:remove(); - return - end - - local entity = player:get_luaentity() - - if entity - and self.hit_mob - and entity.is_mob == true - and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name then - self.hit_mob(self, player) - self.object:remove(); - return - end - - if entity - and self.hit_object - and (not entity.is_mob) - and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name then - self.hit_object(self, player) - self.object:remove(); - return - end - end - end - - self.lastpos = pos - end - }) -end - - --- no damage to nodes explosion -function mcl_mobs:safe_boom(self, pos, strength) - minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { - pos = pos, - gain = 1.0, - max_hear_distance = self.sounds and self.sounds.distance or 32 - }, true) - local radius = strength - entity_physics(pos, radius) - effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) -end - - --- make explosion with protection and tnt mod check -function mcl_mobs:boom(self, pos, strength, fire) - if mobs_griefing and not minetest.is_protected(pos, "") then - mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) - else - mcl_mobs:safe_boom(self, pos, strength) - end - - -- delete the object after it punched the player to avoid nil entities in e.g. mcl_shields!! - self.object:remove() -end - - --- Register spawn eggs - --- Note: This also introduces the “spawn_egg” group: --- * spawn_egg=1: Spawn egg (generic mob, no metadata) --- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata) -function mcl_mobs:register_egg(mob, desc, background, addegg, no_creative) - - local grp = {spawn_egg = 1} - - -- do NOT add this egg to creative inventory (e.g. dungeon master) - if no_creative == true then - grp.not_in_creative_inventory = 1 - end - - local invimg = background - - if addegg == 1 then - invimg = "mobs_chicken_egg.png^(" .. invimg .. - "^[mask:mobs_chicken_egg_overlay.png)" - end - - -- register old stackable mob egg - minetest.register_craftitem(mob, { - - description = desc, - inventory_image = invimg, - groups = grp, - - _doc_items_longdesc = S("This allows you to place a single mob."), - _doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."), - - on_place = function(itemstack, placer, pointed_thing) - - local pos = pointed_thing.above - - -- am I clicking on something with existing on_rightclick function? - local under = minetest.get_node(pointed_thing.under) - local def = minetest.registered_nodes[under.name] - if def and def.on_rightclick then - return def.on_rightclick(pointed_thing.under, under, placer, itemstack) - end - - if pos - and within_limits(pos, 0) - and not minetest.is_protected(pos, placer:get_player_name()) then - - local name = placer:get_player_name() - local privs = minetest.get_player_privs(name) - if under.name == "mcl_mobspawners:spawner" then - if minetest.is_protected(pointed_thing.under, name) then - minetest.record_protection_violation(pointed_thing.under, name) - return itemstack - end - if not privs.maphack then - minetest.chat_send_player(name, S("You need the “maphack” privilege to change the mob spawner.")) - return itemstack - end - mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name()) - if not minetest.is_creative_enabled(name) then - itemstack:take_item() - end - return itemstack - end - - if not minetest.registered_entities[mob] then - return itemstack - end - - if minetest.settings:get_bool("only_peaceful_mobs", false) - and minetest.registered_entities[mob].type == "monster" then - minetest.chat_send_player(name, S("Only peaceful mobs allowed!")) - return itemstack - end - - pos.y = pos.y - 0.5 - - local mob = minetest.add_entity(pos, mob) - local entityname = itemstack:get_name() - minetest.log("action", "Player " ..name.." spawned "..entityname.." at "..minetest.pos_to_string(pos)) - local ent = mob:get_luaentity() - - -- don't set owner if monster or sneak pressed - if ent.type ~= "monster" - and not placer:get_player_control().sneak then - ent.owner = placer:get_player_name() - ent.tamed = true - end - - -- set nametag - local nametag = itemstack:get_meta():get_string("name") - if nametag ~= "" then - if string.len(nametag) > MAX_MOB_NAME_LENGTH then - nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH) - end - ent.nametag = nametag - update_tag(ent) - end - - -- if not in creative then take item - if not minetest.is_creative_enabled(placer:get_player_name()) then - itemstack:take_item() - end - end - - return itemstack - end, - }) - -end - - --- No-op in MCL2 (capturing mobs is not possible). --- Provided for compability with Mobs Redo -function mcl_mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) - return false -end - - --- No-op in MCL2 (protecting mobs is not possible). -function mcl_mobs:protect(self, clicker) - return false -end - - --- feeding, taming and breeding (thanks blert2112) -function mcl_mobs:feed_tame(self, clicker, feed_count, breed, tame, notake) - if not self.follow then - return false - end - -- can eat/tame with item in hand - if self.nofollow or follow_holding(self, clicker) then - local consume_food = false - - -- tame if not still a baby - - if tame and not self.child then - if not self.owner or self.owner == "" then - self.tamed = true - self.owner = clicker:get_player_name() - consume_food = true - end - end - - -- increase health - - if self.health < self.hp_max and not consume_food then - consume_food = true - self.health = min(self.health + 4, self.hp_max) - - if self.htimer < 1 then - self.htimer = 5 - end - self.object:set_hp(self.health) - end - - -- make children grow quicker - - if not consume_food and self.child == true then - consume_food = true - -- deduct 10% of the time to adulthood - self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) - end - - -- breed animals - - if breed and not consume_food and self.hornytimer == 0 and not self.horny then - self.food = (self.food or 0) + 1 - consume_food = true - if self.food >= feed_count then - self.food = 0 - self.horny = true - end - end - - update_tag(self) - -- play a sound if the animal used the item and take the item if not in creative - if consume_food then - -- don't consume food if clicker is in creative - if not minetest.is_creative_enabled(clicker:get_player_name()) and not notake then - local item = clicker:get_wielded_item() - item:take_item() - clicker:set_wielded_item(item) - end - -- always play the eat sound if food is used, even in creative - mob_sound(self, "eat", nil, true) - - else - -- make sound when the mob doesn't want food - mob_sound(self, "random", true) - end - return true - end - return false -end - --- Spawn a child -function mcl_mobs:spawn_child(pos, mob_type) - local child = minetest.add_entity(pos, mob_type) - if not child then - return - end - - local ent = child:get_luaentity() - effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) - - ent.child = true - - local textures - -- using specific child texture (if found) - if ent.child_texture then - textures = ent.child_texture[1] - end - - -- and resize to half height - child:set_properties({ - textures = textures, - visual_size = { - x = ent.base_size.x * .5, - y = ent.base_size.y * .5, - }, - collisionbox = { - ent.base_colbox[1] * .5, - ent.base_colbox[2] * .5, - ent.base_colbox[3] * .5, - ent.base_colbox[4] * .5, - ent.base_colbox[5] * .5, - ent.base_colbox[6] * .5, - }, - selectionbox = { - ent.base_selbox[1] * .5, - ent.base_selbox[2] * .5, - ent.base_selbox[3] * .5, - ent.base_selbox[4] * .5, - ent.base_selbox[5] * .5, - ent.base_selbox[6] * .5, - }, - }) - - return child end local timer = 0 @@ -4524,10 +450,29 @@ minetest.register_globalstep(function(dtime) for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do local lua = obj:get_luaentity() if lua and lua.is_mob then - lua.lifetimer = max(20, lua.lifetimer) + lua.lifetimer = math.max(20, lua.lifetimer) lua.despawn_immediately = false end end end timer = 0 end) + +minetest.register_chatcommand("clearmobs",{ + privs={maphack=true}, + params = "||", + description=S("Removes all spawned mobs except nametagged and tamed ones. all removes all mobs, nametagged only nametagged ones and with the range paramter all mobs in a distance of the current player are removed."), + func=function(n,param) + local p = minetest.get_player_by_name(n) + local num=tonumber(param) + for _,o in pairs(minetest.luaentities) do + if o.is_mob then + if param == "all" or + ( param == "nametagged" and o.nametag ) or + ( param == "" and ( not o.nametag or o.nametag == "" ) and not o.tamed ) or + ( num and num > 0 and vector.distance(p:get_pos(),o.object:get_pos()) <= num ) then + o.object:remove() + end + end + end +end}) diff --git a/mods/ENTITIES/mcl_mobs/api.txt b/mods/ENTITIES/mcl_mobs/api.txt index b9b6613b6..5b5809bca 100644 --- a/mods/ENTITIES/mcl_mobs/api.txt +++ b/mods/ENTITIES/mcl_mobs/api.txt @@ -258,7 +258,10 @@ functions needed for the mob to work properly which contains the following: 'nofollow' Do not follow players when they wield the "follow" item. For mobs (like villagers) that are bred in a different way. 'pick_up' table of itemstrings the mob will pick up (e.g. for breeding) - 'on_pick_up' function that will be called on item pickup - return true to not pickup the item + 'on_pick_up' function that will be called on item pickup - arguments are self and the itementity return a (modified) itemstack + 'custom_visual_size' will not reset visual_size from the base class on reload + 'noyaw' If true this mob will not automatically change yaw + 'particlespawners' Table of particlespawners attached to the mob. This is implemented in a coord safe manner i.e. spawners are only sent to players within the player_transfer_distance (and automatically removed). This enables infinitely lived particlespawners. mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival @@ -433,7 +436,7 @@ true the mob will not spawn. MineClone 2 extensions ---------------------- -mobs:spawn_child(pos, mob_type) +mcl_mobs:spawn_child(pos, mob_type) This function spawns a mob as a child. The parameter mob_type is the entitystring of the new mob. @@ -443,6 +446,7 @@ mobs:death_effect(pos, collisionbox) Create death particles at pos with the given collisionbox. +mcl_mobs.spawn(pos,name/entity name) Making Arrows ------------- @@ -484,13 +488,13 @@ This function registers a arrow for mobs with the attack type shoot. Spawn Eggs ---------- -mobs:register_egg(name, description, background, addegg, no_creative) +mobs:register_egg(name, description, background_color, overlay_color, addegg, no_creative) This function registers a spawn egg which can be used by admin to properly spawn in a mob. 'name' this is the name of your new mob to spawn e.g. "mob:sheep" 'description' the name of the new egg you are creating e.g. "Spawn Sheep" - 'background'the texture displayed for the egg in inventory + 'background_color' and 'overlay_color' define the colors for the texture displayed for the egg in inventory 'addegg' would you like an egg image in front of your texture (1 = yes, 0 = no) 'no_creative' when set to true this stops spawn egg appearing in creative diff --git a/mods/ENTITIES/mcl_mobs/breeding.lua b/mods/ENTITIES/mcl_mobs/breeding.lua new file mode 100644 index 000000000..9284163cd --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/breeding.lua @@ -0,0 +1,352 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class + +local MAX_MOB_NAME_LENGTH = 30 +local HORNY_TIME = 30 +local HORNY_AGAIN_TIME = 300 +local CHILD_GROW_TIME = 60*20 + +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false) + +local LOG_MODULE = "[mcl_mobs]" +local function mcl_log (message) + if LOGGING_ON and message then + minetest.log(LOG_MODULE .. " " .. message) + end +end + +-- No-op in MCL2 (capturing mobs is not possible). +-- Provided for compability with Mobs Redo +function mcl_mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) + return false +end + + +-- No-op in MCL2 (protecting mobs is not possible). +function mcl_mobs:protect(self, clicker) + return false +end + + +-- feeding, taming and breeding (thanks blert2112) +function mob_class:feed_tame(clicker, feed_count, breed, tame, notake) + if not self.follow then + return false + end + -- can eat/tame with item in hand + if self.nofollow or self:follow_holding(clicker) then + local consume_food = false + + -- tame if not still a baby + + if tame and not self.child then + if not self.owner or self.owner == "" then + self.tamed = true + self.owner = clicker:get_player_name() + consume_food = true + end + end + + -- increase health + + if self.health < self.hp_max and not consume_food then + consume_food = true + self.health = math.min(self.health + 4, self.hp_max) + + if self.htimer < 1 then + self.htimer = 5 + end + self.object:set_hp(self.health) + end + + -- make children grow quicker + + if not consume_food and self.child == true then + consume_food = true + -- deduct 10% of the time to adulthood + self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) + end + + -- breed animals + + if breed and not consume_food and self.hornytimer == 0 and not self.horny then + self.food = (self.food or 0) + 1 + consume_food = true + if self.food >= feed_count then + self.food = 0 + self.horny = true + end + end + + self:update_tag() + -- play a sound if the animal used the item and take the item if not in creative + if consume_food then + -- don't consume food if clicker is in creative + if not minetest.is_creative_enabled(clicker:get_player_name()) and not notake then + local item = clicker:get_wielded_item() + item:take_item() + clicker:set_wielded_item(item) + end + -- always play the eat sound if food is used, even in creative + self:mob_sound("eat", nil, true) + + else + -- make sound when the mob doesn't want food + self:mob_sound("random", true) + end + return true + end + return false +end + +-- Spawn a child +function mcl_mobs.spawn_child(pos, mob_type) + local child = minetest.add_entity(pos, mob_type) + if not child then + return + end + + local ent = child:get_luaentity() + mcl_mobs.effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) + + ent.child = true + + local textures + -- using specific child texture (if found) + if ent.child_texture then + textures = ent.child_texture[1] + end + + -- and resize to half height + child:set_properties({ + textures = textures, + visual_size = { + x = ent.base_size.x * .5, + y = ent.base_size.y * .5, + }, + collisionbox = { + ent.base_colbox[1] * .5, + ent.base_colbox[2] * .5, + ent.base_colbox[3] * .5, + ent.base_colbox[4] * .5, + ent.base_colbox[5] * .5, + ent.base_colbox[6] * .5, + }, + selectionbox = { + ent.base_selbox[1] * .5, + ent.base_selbox[2] * .5, + ent.base_selbox[3] * .5, + ent.base_selbox[4] * .5, + ent.base_selbox[5] * .5, + ent.base_selbox[6] * .5, + }, + }) + + ent.animation = ent._child_animations + ent._current_animation = nil + ent:set_animation("stand") + + return child +end + +-- find two animals of same type and breed if nearby and horny +function mob_class:check_breeding() + + --mcl_log("In breed function") + -- child takes a long time before growing into adult + if self.child == true then + + -- When a child, hornytimer is used to count age until adulthood + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer >= CHILD_GROW_TIME then + + self.child = false + self.hornytimer = 0 + + self.object:set_properties({ + textures = self.base_texture, + mesh = self.base_mesh, + visual_size = self.base_size, + collisionbox = self.base_colbox, + selectionbox = self.base_selbox, + }) + + -- custom function when child grows up + if self.on_grown then + self.on_grown(self) + else + -- jump when fully grown so as not to fall into ground + self.object:set_velocity({ + x = 0, + y = self.jump_height*3, + z = 0 + }) + end + + self.animation = nil + local anim = self._current_animation + self._current_animation = nil -- Mobs Redo does nothing otherwise + self:set_animation(anim) + end + + return + end + + -- horny animal can mate for HORNY_TIME seconds, + -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds + if self.horny == true + and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then + + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then + self.hornytimer = 0 + self.horny = false + end + end + + -- find another same animal who is also horny and mate if nearby + if self.horny == true + and self.hornytimer <= HORNY_TIME then + + mcl_log("In breed function. All good. Do the magic.") + + local pos = self.object:get_pos() + + mcl_mobs.effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) + + local objs = minetest.get_objects_inside_radius(pos, 3) + local num = 0 + local ent = nil + + for n = 1, #objs do + + ent = objs[n]:get_luaentity() + + -- check for same animal with different colour + local canmate = false + + if ent then + + if ent.name == self.name then + canmate = true + else + local entname = string.split(ent.name,":") + local selfname = string.split(self.name,":") + + if entname[1] == selfname[1] then + entname = string.split(entname[2],"_") + selfname = string.split(selfname[2],"_") + + if entname[1] == selfname[1] then + canmate = true + end + end + end + end + + if canmate then mcl_log("In breed function. Can mate.") end + + if ent + and canmate == true + and ent.horny == true + and ent.hornytimer <= HORNY_TIME then + num = num + 1 + end + + -- found your mate? then have a baby + if num > 1 then + + self.hornytimer = HORNY_TIME + 1 + ent.hornytimer = HORNY_TIME + 1 + + -- spawn baby + + + minetest.after(5, function(parent1, parent2, pos) + if not parent1.object:get_luaentity() then + return + end + if not parent2.object:get_luaentity() then + return + end + + mcl_experience.throw_xp(pos, math.random(1, 7)) + + -- custom breed function + if parent1.on_breed then + -- when false, skip going any further + if parent1.on_breed(parent1, parent2) == false then + return + end + end + + local child = mcl_mobs.spawn_child(pos, parent1.name) + + local ent_c = child:get_luaentity() + + + -- Use texture of one of the parents + local p = math.random(1, 2) + if p == 1 then + ent_c.base_texture = parent1.base_texture + else + ent_c.base_texture = parent2.base_texture + end + child:set_properties({ + textures = ent_c.base_texture + }) + + -- tamed and owned by parents' owner + ent_c.tamed = true + ent_c.owner = parent1.owner + end, self, ent, pos) + + num = 0 + + break + end + end + end +end + +function mob_class:toggle_sit(clicker,p) + if not self.tamed or self.child or self.owner ~= clicker:get_player_name() then + return + end + local pos = self.object:get_pos() + local particle + if not self.order or self.order == "" or self.order == "sit" then + particle = "mobs_mc_wolf_icon_roam.png" + self.order = "roam" + self.state = "stand" + self.walk_chance = default_walk_chance + self.jump = true + self:set_animation("stand") + -- TODO: Add sitting model + else + particle = "mobs_mc_wolf_icon_sit.png" + self.order = "sit" + self.state = "stand" + self.walk_chance = 0 + self.jump = false + if self.animation.sit_start then + self:set_animation("sit") + else + self:set_animation("stand") + end + end + local pp = vector.new(0,1.4,0) + if p then pp = vector.offset(pp,0,p,0) end + -- Display icon to show current order (sit or roam) + minetest.add_particle({ + pos = vector.add(pos, pp), + velocity = {x=0,y=0.2,z=0}, + expirationtime = 1, + size = 4, + texture = particle, + playername = self.owner, + glow = minetest.LIGHT_MAX, + }) +end diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua new file mode 100644 index 000000000..5577a4361 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -0,0 +1,796 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class + +local damage_enabled = minetest.settings:get_bool("enable_damage") +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false + +-- pathfinding settings +local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching +local stuck_path_timeout = 10 -- how long will mob follow path before giving up + +-- check if daytime and also if mob is docile during daylight hours +function mob_class:day_docile() + if self.docile_by_day == false then + return false + elseif self.docile_by_day == true + and self.time_of_day > 0.2 + and self.time_of_day < 0.8 then + return true + end +end + +-- attack player/mob +function mob_class:do_attack(player) + + if self.state == "attack" or self.state == "die" then + return + end + + self.attack = player + self.state = "attack" + + -- TODO: Implement war_cry sound without being annoying + --if random(0, 100) < 90 then + --self:mob_sound("war_cry", true) + --end +end + +-- blast damage to entities nearby +local function entity_physics(pos,radius) + + radius = radius * 2 + + local objs = minetest.get_objects_inside_radius(pos, radius) + local obj_pos, dist + + for n = 1, #objs do + + obj_pos = objs[n]:get_pos() + + dist = vector.distance(pos, obj_pos) + if dist < 1 then dist = 1 end + + local damage = math.floor((4 / dist) * radius) + local ent = objs[n]:get_luaentity() + + -- punches work on entities AND players + objs[n]:punch(objs[n], 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, pos) + end +end + +function mob_class:entity_physics(pos,radius) return entity_physics(pos,radius) end + +local los_switcher = false +local height_switcher = false + +-- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 +function mob_class:smart_mobs(s, p, dist, dtime) + + local s1 = self.path.lastpos + + local target_pos = self.attack:get_pos() + + -- is it becoming stuck? + if math.abs(s1.x - s.x) + math.abs(s1.z - s.z) < .5 then + self.path.stuck_timer = self.path.stuck_timer + dtime + else + self.path.stuck_timer = 0 + end + + self.path.lastpos = {x = s.x, y = s.y, z = s.z} + + local use_pathfind = false + local has_lineofsight = minetest.line_of_sight( + {x = s.x, y = (s.y) + .5, z = s.z}, + {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) + + -- im stuck, search for path + if not has_lineofsight then + + if los_switcher == true then + use_pathfind = true + los_switcher = false + end -- cannot see target! + else + if los_switcher == false then + + los_switcher = true + use_pathfind = false + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end -- can see target! + end + + if (self.path.stuck_timer > stuck_timeout and not self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if math.abs(vector.subtract(s,target_pos).y) > self.stepheight then + + if height_switcher then + use_pathfind = true + height_switcher = false + end + else + if not height_switcher then + use_pathfind = false + height_switcher = true + end + end + + if use_pathfind then + -- lets try find a path, first take care of positions + -- since pathfinder is very sensitive + local sheight = self.collisionbox[5] - self.collisionbox[2] + + -- round position to center of node to avoid stuck in walls + -- also adjust height for player models! + s.x = math.floor(s.x + 0.5) + s.z = math.floor(s.z + 0.5) + + local ssight, sground = minetest.line_of_sight(s, { + x = s.x, y = s.y - 4, z = s.z}, 1) + + -- determine node above ground + if not ssight then + s.y = sground.y + 1 + end + + local p1 = self.attack:get_pos() + + p1.x = math.floor(p1.x + 0.5) + p1.y = math.floor(p1.y + 0.5) + p1.z = math.floor(p1.z + 0.5) + + local dropheight = 12 + if self.fear_height ~= 0 then dropheight = self.fear_height end + local jumpheight = 0 + if self.jump and self.jump_height >= 4 then + jumpheight = math.min(math.ceil(self.jump_height / 4), 4) + elseif self.stepheight > 0.5 then + jumpheight = 1 + end + self.path.way = minetest.find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") + + self.state = "" + self:do_attack(self.attack) + + -- no path found, try something else + if not self.path.way then + + self.path.following = false + + -- lets make way by digging/building if not accessible + if self.pathfinding == 2 and mobs_griefing then + + -- is player higher than mob? + if s.y < p1.y then + + -- build upwards + if not minetest.is_protected(s, "") then + + local ndef1 = minetest.registered_nodes[self.standing_in] + + if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then + + minetest.set_node(s, {name = mcl_mobs.fallback_node}) + end + end + + local sheight = math.ceil(self.collisionbox[5]) + 1 + + -- assume mob is 2 blocks high so it digs above its head + s.y = s.y + sheight + + -- remove one block above to make room to jump + if not minetest.is_protected(s, "") then + + local node1 = node_ok(s, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.set_node(s, {name = "air"}) + minetest.add_item(s, ItemStack(node1)) + + end + end + + s.y = s.y - sheight + self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) + + else -- dig 2 blocks to make door toward player direction + + local yaw1 = self.object:get_yaw() + math.pi / 2 + local p1 = { + x = s.x + math.cos(yaw1), + y = s.y, + z = s.z + math.sin(yaw1) + } + + if not minetest.is_protected(p1, "") then + + local node1 = node_ok(p1, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + p1.y = p1.y + 1 + node1 = node_ok(p1, "air").name + ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + end + end + end + + -- will try again in 2 seconds + self.path.stuck_timer = stuck_timeout - 2 + elseif s.y < p1.y and (not self.fly) then + self:do_jump() --add jump to pathfinding + self.path.following = true + -- Yay, I found path! + -- TODO: Implement war_cry sound without being annoying + --self:mob_sound("war_cry", true) + else + self:set_velocity(self.walk_velocity) + + -- follow path now that it has it + self.path.following = true + end + end +end + + +-- specific attacks +local specific_attack = function(list, what) + + -- no list so attack default (player, animals etc.) + if list == nil then + return true + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + +-- find someone to attack +function mob_class:monster_attack() + if not damage_enabled + or self.passive ~= false + or self.state == "attack" + or self:day_docile() then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + local blacklist_attack = {} + + for n = 1, #objs do + if not objs[n]:is_player() then + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + name = obj.name or "" + end + if obj and obj.type == self.type and obj.passive == false and obj.state == "attack" and obj.attack then + table.insert(blacklist_attack, obj.attack) + end + end + end + + for n = 1, #objs do + + + if objs[n]:is_player() then + if mcl_mobs.invis[ objs[n]:get_player_name() ] or (not self:object_in_range(objs[n])) then + type = "" + elseif (self.type == "monster" or self._aggro) then + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + + end + + -- find specific mob to attack, failing that attack player/npc/animal + if specific_attack(self.specific_attack, name) + and (type == "player" or ( type == "npc" and self.attack_npcs ) + or (type == "animal" and self.attack_animals == true)) then + + p = player:get_pos() + sp = s + + dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + local attacked_p = false + for c=1, #blacklist_attack do + if blacklist_attack[c] == player then + attacked_p = true + end + end + -- choose closest player to attack + if dist < min_dist + and not attacked_p + and self:line_of_sight( sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + if not min_player and #blacklist_attack > 0 then + min_player=blacklist_attack[math.random(#blacklist_attack)] + end + -- attack player + if min_player then + self:do_attack(min_player) + end +end + + +-- npc, find closest monster to attack +function mob_class:npc_attack() + + if self.type ~= "npc" + or not self.attacks_monsters + or self.state == "attack" then + return + end + + local p, sp, obj, min_player + local s = self.object:get_pos() + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj and obj.type == "monster" then + + p = obj.object:get_pos() + sp = s + + local dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + if dist < min_dist + and self:line_of_sight( sp, p, 2) == true then + min_dist = dist + min_player = obj.object + end + end + end + + if min_player then + self:do_attack(min_player) + end +end + + + +-- dogshoot attack switch and counter function +function mob_class:dogswitch(dtime) + + -- switch mode not activated + if not self.dogshoot_switch + or not dtime then + return 0 + end + + self.dogshoot_count = self.dogshoot_count + dtime + + if (self.dogshoot_switch == 1 + and self.dogshoot_count > self.dogshoot_count_max) + or (self.dogshoot_switch == 2 + and self.dogshoot_count > self.dogshoot_count2_max) then + + self.dogshoot_count = 0 + + if self.dogshoot_switch == 1 then + self.dogshoot_switch = 2 + else + self.dogshoot_switch = 1 + end + end + + return self.dogshoot_switch +end + +-- no damage to nodes explosion +function mob_class:safe_boom(pos, strength) + minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + pos = pos, + gain = 1.0, + max_hear_distance = self.sounds and self.sounds.distance or 32 + }, true) + local radius = strength + entity_physics(pos, radius) + mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) +end + + +-- make explosion with protection and tnt mod check +function mob_class:boom(pos, strength, fire) + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) + else + mcl_mobs.mob_class.safe_boom(self, pos, strength) --need to call it this way bc self is the "arrow" object here + end + + -- delete the object after it punched the player to avoid nil entities in e.g. mcl_shields!! + self.object:remove() +end + +-- deal damage and effects when mob punched +function mob_class:on_punch(hitter, tflp, tool_capabilities, dir) + + -- custom punch function + if self.do_punch then + + -- when false skip going any further + if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then + return + end + end + + -- error checking when mod profiling is enabled + if not tool_capabilities then + minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") + return + end + + local is_player = hitter:is_player() + + if is_player then + -- is mob protected? + if self.protected and minetest.is_protected(self.object:get_pos(), hitter:get_player_name()) then + return + end + + if minetest.is_creative_enabled(hitter:get_player_name()) then + self.health = 0 + end + + -- set/update 'drop xp' timestamp if hitted by player + self.xp_timestamp = minetest.get_us_time() + end + + + -- punch interval + local weapon = hitter:get_wielded_item() + local punch_interval = 1.4 + + -- exhaust attacker + if is_player then + mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) + end + + -- calculate mob damage + local damage = 0 + local armor = self.object:get_armor_groups() or {} + local tmp + + -- quick error check incase it ends up 0 (serialize.h check test) + if tflp == 0 then + tflp = 0.2 + end + + + for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do + + tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + + if tmp < 0 then + tmp = 0.0 + elseif tmp > 1 then + tmp = 1.0 + end + + damage = damage + (tool_capabilities.damage_groups[group] or 0) + * tmp * ((armor[group] or 0) / 100.0) + end + + if weapon then + local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") + if fire_aspect_level > 0 then + mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) + end + end + + -- check for tool immunity or special damage + for n = 1, #self.immune_to do + + if self.immune_to[n][1] == weapon:get_name() then + + damage = self.immune_to[n][2] or 0 + break + end + end + + -- healing + if damage <= -1 then + self.health = self.health - math.floor(damage) + return + end + + if tool_capabilities then + punch_interval = tool_capabilities.full_punch_interval or 1.4 + end + + -- add weapon wear manually + -- Required because we have custom health handling ("health" property) + if minetest.is_creative_enabled("") ~= true + and tool_capabilities then + if tool_capabilities.punch_attack_uses then + -- Without this delay, the wear does not work. Quite hacky ... + minetest.after(0, function(name) + local player = minetest.get_player_by_name(name) + if not player then return end + local weapon = hitter:get_wielded_item(player) + local def = weapon:get_definition() + if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then + local wear = math.floor(65535/tool_capabilities.punch_attack_uses) + weapon:add_wear(wear) + hitter:set_wielded_item(weapon) + end + end, hitter:get_player_name()) + end + end + + local die = false + + + if damage >= 0 then + -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. + if damage >= 0.1 then + -- weapon sounds + if weapon:get_definition().sounds ~= nil then + + local s = math.random(0, #weapon:get_definition().sounds) + + minetest.sound_play(weapon:get_definition().sounds[s], { + object = self.object, --hitter, + max_hear_distance = 8 + }, true) + else + minetest.sound_play("default_punch", { + object = self.object, + max_hear_distance = 5 + }, true) + end + + self:damage_effect(damage) + + -- do damage + self.health = self.health - damage + + -- skip future functions if dead, except alerting others + if self:check_for_death( "hit", {type = "punch", puncher = hitter}) then + die = true + end + end + -- knock back effect (only on full punch) + if self.knock_back + and tflp >= punch_interval then + -- direction error check + dir = dir or {x = 0, y = 0, z = 0} + + local v = self.object:get_velocity() + if not v then return end + local r = 1.4 - math.min(punch_interval, 1.4) + local kb = r * (math.abs(v.x)+math.abs(v.z)) + local up = 2 + + if die==true then + kb=kb*2 + end + + -- if already in air then dont go up anymore when hit + if math.abs(v.y) > 0.1 + or self.fly then + up = 0 + end + + + -- check if tool already has specific knockback value + if tool_capabilities.damage_groups["knockback"] then + kb = tool_capabilities.damage_groups["knockback"] + else + kb = kb * 1.5 + end + + + local luaentity + if hitter then + luaentity = hitter:get_luaentity() + end + if hitter and is_player then + local wielditem = hitter:get_wielded_item() + kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + elseif luaentity and luaentity._knockback then + kb = kb + luaentity._knockback + end + self._kb_turn = true + self._turn_to=self.object:get_yaw()-1.57 + self.frame_speed_multiplier=2.3 + if self.animation.run_end then + self:set_animation( "run") + elseif self.animation.walk_end then + self:set_animation( "walk") + end + minetest.after(0.2, function() + if self and self.object then + self.frame_speed_multiplier=1 + self._kb_turn = false + end + end) + self.object:add_velocity({ + x = dir.x * kb, + y = up*2, + z = dir.z * kb + }) + + self.pause_timer = 0.25 + end + end -- END if damage + + -- if skittish then run away + if hitter and is_player and hitter:get_pos() and not die and self.runaway == true and self.state ~= "flop" then + + local yaw = self:set_yaw( minetest.dir_to_yaw(vector.direction(hitter:get_pos(), self.object:get_pos()))) + minetest.after(0.2,function() + if self and self.object and self.object:get_pos() and hitter and is_player and hitter:get_pos() then + yaw = self:set_yaw( minetest.dir_to_yaw(vector.direction(hitter:get_pos(), self.object:get_pos()))) + self:set_velocity( self.run_velocity) + end + end) + self.state = "runaway" + self.runaway_timer = 0 + self.following = nil + end + + local name = hitter:get_player_name() or "" + + -- attack puncher and call other mobs for help + if self.passive == false + and self.state ~= "flop" + and (self.child == false or self.type == "monster") + and hitter:get_player_name() ~= self.owner + and not mcl_mobs.invis[ name ] then + if not die then + -- attack whoever punched mob + self.state = "" + self:do_attack(hitter) + self._aggro= true + end + + -- alert others to the attack + local objs = minetest.get_objects_inside_radius(hitter:get_pos(), self.view_range) + local obj = nil + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj then + -- only alert members of same mob or friends + if obj.group_attack + and obj.state ~= "attack" + and obj.owner ~= name then + if obj.name == self.name then + obj:do_attack(hitter) + elseif type(obj.group_attack) == "table" then + for i=1, #obj.group_attack do + if obj.name == obj.group_attack[i] then + obj._aggro = true + obj:do_attack(hitter) + break + end + end + end + end + + -- have owned mobs attack player threat + if obj.owner == name and obj.owner_loyal then + obj:do_attack(self.object) + end + end + end + end +end + +function mob_class:check_aggro(dtime) + if not self._aggro or not self.attack then return end + if not self._check_aggro_timer or self._check_aggro_timer > 5 then + self._check_aggro_timer = 0 + if not self.attack:get_pos() or vector.distance(self.attack:get_pos(),self.object:get_pos()) > 128 then + self._aggro = nil + self.attack = nil + self.state = "stand" + end + end + self._check_aggro_timer = self._check_aggro_timer + dtime +end diff --git a/mods/ENTITIES/mcl_mobs/compat.lua b/mods/ENTITIES/mcl_mobs/compat.lua new file mode 100644 index 000000000..020a089b2 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/compat.lua @@ -0,0 +1,32 @@ + +-- this is to make the register_mob and register egg functions commonly used by mods not break +-- when they use the weird old : notation AND self as first argument +local oldregmob = mcl_mobs.register_mob +function mcl_mobs.register_mob(self,name,def) + if type(self) == "string" then + def = name + name = self + end + return oldregmob(name,def) +end +local oldregegg = mcl_mobs.register_egg +function mcl_mobs.register_egg(self, mob, desc, background_color, overlay_color, addegg, no_creative) + if type(self) == "string" then + no_creative = addegg + addegg = overlay_color + overlay_color = background_color + background_color = desc + desc = mob + mob = self + end + return oldregegg(mob, desc, background_color, overlay_color, addegg, no_creative) +end + +local oldregarrow = mcl_mobs.register_mob +function mcl_mobs.register_mob(self,name,def) + if type(self) == "string" then + def = name + name = self + end + return oldregarrow(name,def) +end diff --git a/mods/ENTITIES/mcl_mobs/effects.lua b/mods/ENTITIES/mcl_mobs/effects.lua new file mode 100644 index 000000000..476c13469 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/effects.lua @@ -0,0 +1,384 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class +local active_particlespawners = {} +local disable_blood = minetest.settings:get_bool("mobs_disable_blood") +local DEFAULT_FALL_SPEED = -9.81*1.5 + +local player_transfer_distance = tonumber(minetest.settings:get("player_transfer_distance")) or 128 +if player_transfer_distance == 0 then player_transfer_distance = math.huge end + + +-- custom particle effects +function mcl_mobs.effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) + + radius = radius or 2 + min_size = min_size or 0.5 + max_size = max_size or 1 + gravity = gravity or DEFAULT_FALL_SPEED + glow = glow or 0 + go_down = go_down or false + + local ym + if go_down then + ym = 0 + else + ym = -radius + end + + minetest.add_particlespawner({ + amount = amount, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x = -radius, y = ym, z = -radius}, + maxvel = {x = radius, y = radius, z = radius}, + minacc = {x = 0, y = gravity, z = 0}, + maxacc = {x = 0, y = gravity, z = 0}, + minexptime = 0.1, + maxexptime = 1, + minsize = min_size, + maxsize = max_size, + texture = texture, + glow = glow, + }) +end + +function mcl_mobs.death_effect(pos, yaw, collisionbox, rotate) + local min, max + if collisionbox then + min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} + max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} + else + min = { x = -0.5, y = 0, z = -0.5 } + max = { x = 0.5, y = 0.5, z = 0.5 } + end + if rotate then + min = vector.rotate(min, {x=0, y=yaw, z=math.pi/2}) + max = vector.rotate(max, {x=0, y=yaw, z=math.pi/2}) + min, max = vector.sort(min, max) + min = vector.multiply(min, 0.5) + max = vector.multiply(max, 0.5) + end + + minetest.add_particlespawner({ + amount = 50, + time = 0.001, + minpos = vector.add(pos, min), + maxpos = vector.add(pos, max), + minvel = vector.new(-5,-5,-5), + maxvel = vector.new(5,5,5), + minexptime = 1.1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_particles_mob_death.png^[colorize:#000000:255", + }) + + minetest.sound_play("mcl_mobs_mob_poof", { + pos = pos, + gain = 1.0, + max_hear_distance = 8, + }, true) +end + + +-- play sound +function mob_class:mob_sound(soundname, is_opinion, fixed_pitch) + + local soundinfo + if self.sounds_child and self.child then + soundinfo = self.sounds_child + elseif self.sounds then + soundinfo = self.sounds + end + if not soundinfo then + return + end + local sound = soundinfo[soundname] + if sound then + if is_opinion and self.opinion_sound_cooloff > 0 then + return + end + local pitch + if not fixed_pitch then + local base_pitch = soundinfo.base_pitch + if not base_pitch then + base_pitch = 1 + end + if self.child and (not self.sounds_child) then + -- Children have higher pitch + pitch = base_pitch * 1.5 + else + pitch = base_pitch + end + -- randomize the pitch a bit + pitch = pitch + math.random(-10, 10) * 0.005 + end + minetest.sound_play(sound, { + object = self.object, + gain = 1.0, + max_hear_distance = self.sounds.distance, + pitch = pitch, + }, true) + self.opinion_sound_cooloff = 1 + end +end + +function mob_class:add_texture_mod(mod) + local full_mod = "" + local already_added = false + for i=1, #self.texture_mods do + if mod == self.texture_mods[i] then + already_added = true + end + full_mod = full_mod .. self.texture_mods[i] + end + if not already_added then + full_mod = full_mod .. mod + table.insert(self.texture_mods, mod) + end + self.object:set_texture_mod(full_mod) +end + +function mob_class:remove_texture_mod(mod) + local full_mod = "" + local remove = {} + for i=1, #self.texture_mods do + if self.texture_mods[i] ~= mod then + full_mod = full_mod .. self.texture_mods[i] + else + table.insert(remove, i) + end + end + for i=#remove, 1 do + table.remove(self.texture_mods, remove[i]) + end + self.object:set_texture_mod(full_mod) +end + +function mob_class:damage_effect(damage) + -- damage particles + if (not disable_blood) and damage > 0 then + + local amount_large = math.floor(damage / 2) + local amount_small = damage % 2 + + local pos = self.object:get_pos() + + pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 + + local texture = "mobs_blood.png" + -- full heart damage (one particle for each 2 HP damage) + if amount_large > 0 then + mcl_mobs.effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) + end + -- half heart damage (one additional particle if damage is an odd number) + if amount_small > 0 then + -- TODO: Use "half heart" + mcl_mobs.effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) + end + end +end + +function mob_class:remove_particlespawners(pn) + if not active_particlespawners[pn] then return end + if not active_particlespawners[pn][self.object] then return end + for k,v in pairs(active_particlespawners[pn][self.object]) do + minetest.delete_particlespawner(v) + end +end + +function mob_class:add_particlespawners(pn) + if not active_particlespawners[pn] then active_particlespawners[pn] = {} end + if not active_particlespawners[pn][self.object] then active_particlespawners[pn][self.object] = {} end + for _,ps in pairs(self.particlespawners) do + ps.attached = self.object + ps.playername = pn + table.insert(active_particlespawners[pn][self.object],minetest.add_particlespawner(ps)) + end +end + +function mob_class:check_particlespawners(dtime) + if not self.particlespawners then return end + --minetest.log(dump(active_particlespawners)) + if self._particle_timer and self._particle_timer >= 1 then + self._particle_timer = 0 + local players = {} + for _,player in pairs(minetest.get_connected_players()) do + local pn = player:get_player_name() + table.insert(players,pn) + if not active_particlespawners[pn] then + active_particlespawners[pn] = {} end + + local dst = vector.distance(player:get_pos(),self.object:get_pos()) + if dst < player_transfer_distance and not active_particlespawners[pn][self.object] then + self:add_particlespawners(pn) + elseif dst >= player_transfer_distance and active_particlespawners[pn][self.object] then + self:remove_particlespawners(pn) + end + end + elseif not self._particle_timer then + self._particle_timer = 0 + end + self._particle_timer = self._particle_timer + dtime +end + + +-- set defined animation +function mob_class:set_animation(anim, fixed_frame) + if not self.animation or not anim then + return + end + if self.state == "die" and anim ~= "die" and anim ~= "stand" then + return + end + + if self.jockey then + anim = "jockey" + end + + + if self:flight_check() and self.fly and anim == "walk" then anim = "fly" end + + self._current_animation = self._current_animation or "" + + if (anim == self._current_animation + or not self.animation[anim .. "_start"] + or not self.animation[anim .. "_end"]) and self.state ~= "die" then + return + end + + self._current_animation = anim + + local a_start = self.animation[anim .. "_start"] + local a_end + if fixed_frame then + a_end = a_start + else + a_end = self.animation[anim .. "_end"] + end + if a_start and a_end then + self.object:set_animation({ + x = a_start, + y = a_end}, + self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, + 0, self.animation[anim .. "_loop"] ~= false) + end +end + +-- above function exported for mount.lua +function mcl_mobs:set_animation(self, anim) + self:set_animation(anim) +end + +local function dir_to_pitch(dir) + --local dir2 = vector.normalize(dir) + local xz = math.abs(dir.x) + math.abs(dir.z) + return -math.atan2(-dir.y, xz) +end + +function mob_class:check_head_swivel(dtime) + if not self.head_swivel or type(self.head_swivel) ~= "string" then return end + local final_rotation = vector.new(0,0,0) + local oldp,oldr = self.object:get_bone_position(self.head_swivel) + + local pos = self.object:get_pos() + + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 10)) do + if obj:is_player() and not self.attack or obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity() then + if not self._locked_object then + if math.random(5000/self.curiosity) == 1 or vector.distance(pos,obj:get_pos())<4 and obj:is_player() then + self._locked_object = obj + end + else + if math.random(10000/self.curiosity) == 1 then + self._locked_object = nil + end + end + end + end + + if self.attack or self.following then + self._locked_object = self.attack or self.following + end + + if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then + local _locked_object_eye_height = 1.5 + if self._locked_object:get_luaentity() then + _locked_object_eye_height = self._locked_object:get_luaentity().head_eye_height + end + if self._locked_object:is_player() then + _locked_object_eye_height = self._locked_object:get_properties().eye_height + end + if _locked_object_eye_height then + local self_rot = self.object:get_rotation() + if self.object:get_attach() then + self_rot = self.object:get_attach():get_rotation() + end + if self.rot then + local player_pos = self._locked_object:get_pos() + local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0))) + local mob_yaw = math.deg(-(-(self_rot.y)-(-minetest.dir_to_yaw(direction_player))))+self.head_yaw_offset + local mob_pitch = math.deg(-dir_to_pitch(direction_player))*self.head_pitch_multiplier + + if (mob_yaw < -60 or mob_yaw > 60) and not (self.attack and self.state == "attack" and not self.runaway) then + final_rotation = vector.multiply(oldr, 0.9) + elseif self.attack and self.state == "attack" and not self.runaway then + if self.head_yaw == "y" then + final_rotation = vector.new(mob_pitch, mob_yaw, 0) + elseif self.head_yaw == "z" then + final_rotation = vector.new(mob_pitch, 0, -mob_yaw) + end + + else + + if self.head_yaw == "y" then + final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, ((mob_yaw-oldr.y)*.3)+oldr.y, 0) + elseif self.head_yaw == "z" then + final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, 0, -(((mob_yaw-oldr.y)*.3)+oldr.y)*3) + end + end + end + end + elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then + final_rotation = vector.multiply(oldr, 0.9) + else + final_rotation = vector.new(0,0,0) + end + + mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), final_rotation) +end + +function mob_class:set_animation_speed() + local v = self.object:get_velocity() + if v then + if self.frame_speed_multiplier then + local v2 = math.abs(v.x)+math.abs(v.z)*.833 + if not self.animation.walk_speed then + self.animation.walk_speed = 25 + end + if math.abs(v.x)+math.abs(v.z) > 0.5 then + self.object:set_animation_frame_speed((v2/math.max(1,self.run_velocity))*self.animation.walk_speed*self.frame_speed_multiplier) + else + self.object:set_animation_frame_speed(25) + end + end + --set_speed + if self.acc then + self.object:add_velocity(self.acc) + end + end +end + +minetest.register_on_leaveplayer(function(player) + local pn = player:get_player_name() + if not active_particlespawners[pn] then return end + for _,m in pairs(active_particlespawners[pn]) do + for k,v in pairs(m) do + minetest.delete_particlespawner(v) + end + end + active_particlespawners[pn] = nil +end) diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 69246b470..ed3641dc5 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -1,14 +1,566 @@ - -local path = minetest.get_modpath(minetest.get_current_modname()) - --- Mob API +mcl_mobs = {} +mcl_mobs.mob_class = {} +mcl_mobs.mob_class_meta = {__index = mcl_mobs.mob_class} +mcl_mobs.registered_mobs = {} +local modname = minetest.get_current_modname() +local path = minetest.get_modpath(modname) +local S = minetest.get_translator(modname) +mcl_mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" +--api and helpers +-- effects: sounds and particles mostly +dofile(path .. "/effects.lua") +-- physics: involuntary mob movement - particularly falling and death +dofile(path .. "/physics.lua") +-- movement: general voluntary mob movement, walking avoiding cliffs etc. +dofile(path .. "/movement.lua") +-- items: item management for mobs +dofile(path .. "/items.lua") +-- pathfinding: pathfinding to target positions +dofile(path .. "/pathfinding.lua") +-- combat: attack logic +dofile(path .. "/combat.lua") +-- the enity functions themselves dofile(path .. "/api.lua") --- Spawning Algorithm + +--utility functions +dofile(path .. "/breeding.lua") dofile(path .. "/spawning.lua") - --- Rideable Mobs dofile(path .. "/mount.lua") +dofile(path .. "/crafts.lua") +dofile(path .. "/compat.lua") --- Mob Items -dofile(path .. "/crafts.lua") \ No newline at end of file +local DEFAULT_FALL_SPEED = -9.81*1.5 +local MAX_MOB_NAME_LENGTH = 30 + +local old_spawn_icons = minetest.settings:get_bool("mcl_old_spawn_icons",false) +local extended_pet_control = minetest.settings:get_bool("mcl_extended_pet_control",true) +local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + fallback = fallback or mcl_mobs.fallback_node + local node = minetest.get_node_or_nil(pos) + if node and minetest.registered_nodes[node.name] then + return node + end + return minetest.registered_nodes[fallback] +end + +--#### REGISTER FUNCS + +-- Code to execute before custom on_rightclick handling +local on_rightclick_prefix = function(self, clicker) + if not clicker:is_player() then return end + local item = clicker:get_wielded_item() + if extended_pet_control and self.tamed and self.owner == clicker:get_player_name() then + self:toggle_sit(clicker) + end + -- Name mob with nametag + if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then + + local tag = item:get_meta():get_string("name") + if tag ~= "" then + if string.len(tag) > MAX_MOB_NAME_LENGTH then + tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) + end + self.nametag = tag + + self:update_tag() + + if not minetest.is_creative_enabled(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + return true + end + + end + + return false +end + +local create_mob_on_rightclick = function(on_rightclick) + return function(self, clicker) + local stop = on_rightclick_prefix(self, clicker) + if (not stop) and (on_rightclick) then + on_rightclick(self, clicker) + end + end +end + +-- check if within physical map limits (-30911 to 30927) +local function within_limits(pos, radius) + local wmin, wmax = -30912, 30928 + if mcl_vars then + if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then + wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + end + end + if radius then + wmin = wmin - radius + wmax = wmax + radius + end + for _,v in pairs(pos) do + if v < wmin or v > wmax then return false end + end + return true +end + +mcl_mobs.spawning_mobs = {} +-- register mob entity +function mcl_mobs.register_mob(name, def) + + mcl_mobs.spawning_mobs[name] = true + mcl_mobs.registered_mobs[name] = def + + local can_despawn + if def.can_despawn ~= nil then + can_despawn = def.can_despawn + elseif def.spawn_class == "passive" then + can_despawn = false + else + can_despawn = true + end + + local function scale_difficulty(value, default, min, special) + if (not value) or (value == default) or (value == special) then + return default + else + return math.max(min, value * difficulty) + end + end + + local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} + -- Workaround for : + -- Increase upper Y limit to avoid mobs glitching through solid nodes. + -- FIXME: Remove workaround if it's no longer needed. + if collisionbox[5] < 0.79 then + collisionbox[5] = 0.79 + end + local final_def = { + use_texture_alpha = def.use_texture_alpha, + head_swivel = def.head_swivel or nil, -- bool to activate this function + head_yaw_offset = def.head_yaw_offset or 0, -- for wonkey model bones + head_pitch_multiplier = def.head_pitch_multiplier or 1, --for inverted pitch + bone_eye_height = def.bone_eye_height or 1.4, -- head bone offset + head_eye_height = def.head_eye_height or def.bone_eye_height or 0, -- how hight aproximatly the mobs head is fromm the ground to tell the mob how high to look up at the player + curiosity = def.curiosity or 1, -- how often mob will look at player on idle + head_yaw = def.head_yaw or "y", -- axis to rotate head on + horrizonatal_head_height = def.horrizonatal_head_height or 0, + wears_armor = def.wears_armor, -- a number value used to index texture slot for armor + stepheight = def.stepheight or 0.6, + name = name, + description = def.description, + type = def.type, + attack_type = def.attack_type, + fly = def.fly or false, + fly_in = def.fly_in or {"air", "__airlike"}, + owner = def.owner or "", + order = def.order or "", + on_die = def.on_die, + spawn_small_alternative = def.spawn_small_alternative, + do_custom = def.do_custom, + detach_child = def.detach_child, + jump_height = def.jump_height or 4, -- was 6 + rotate = math.rad(def.rotate or 0), -- 0=front, 90=side, 180=back, 270=side2 + lifetimer = def.lifetimer or 57.73, + hp_min = scale_difficulty(def.hp_min, 5, 1), + hp_max = scale_difficulty(def.hp_max, 10, 1), + xp_min = def.xp_min or 0, + xp_max = def.xp_max or 0, + xp_timestamp = 0, + breath_max = def.breath_max or 15, + breathes_in_water = def.breathes_in_water or false, + physical = true, + collisionbox = collisionbox, + selectionbox = def.selectionbox or def.collisionbox, + visual = def.visual, + visual_size = def.visual_size or {x = 1, y = 1}, + mesh = def.mesh, + makes_footstep_sound = def.makes_footstep_sound or false, + view_range = def.view_range or 16, + walk_velocity = def.walk_velocity or 1, + run_velocity = def.run_velocity or 2, + damage = scale_difficulty(def.damage, 0, 0), + light_damage = def.light_damage or 0, + sunlight_damage = def.sunlight_damage or 0, + water_damage = def.water_damage or 0, + lava_damage = def.lava_damage or 8, + fire_damage = def.fire_damage or 1, + suffocation = def.suffocation or true, + fall_damage = def.fall_damage or 1, + fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 + drops = def.drops or {}, + armor = def.armor or 100, + on_rightclick = create_mob_on_rightclick(def.on_rightclick), + arrow = def.arrow, + shoot_interval = def.shoot_interval, + sounds = def.sounds or {}, + animation = def.animation or {}, + follow = def.follow, + nofollow = def.nofollow, + can_open_doors = def.can_open_doors, + jump = def.jump ~= false, + automatic_face_movement_max_rotation_per_sec = 300, + walk_chance = def.walk_chance or 50, + attacks_monsters = def.attacks_monsters or false, + group_attack = def.group_attack or false, + passive = def.passive or false, + knock_back = def.knock_back ~= false, + shoot_offset = def.shoot_offset or 0, + floats = def.floats or 1, -- floats in water by default + floats_on_lava = def.floats_on_lava or 0, + replace_rate = def.replace_rate, + replace_what = def.replace_what, + replace_with = def.replace_with, + replace_offset = def.replace_offset or 0, + on_replace = def.on_replace, + timer = 0, + env_damage_timer = 0, + tamed = false, + pause_timer = 0, + horny = false, + hornytimer = 0, + gotten = false, + health = 0, + frame_speed_multiplier = 1, + reach = def.reach or 3, + htimer = 0, + texture_list = def.textures, + child_texture = def.child_texture, + docile_by_day = def.docile_by_day or false, + time_of_day = 0.5, + fear_height = def.fear_height or 0, + runaway = def.runaway, + runaway_timer = 0, + pathfinding = def.pathfinding, + immune_to = def.immune_to or {}, + explosion_radius = def.explosion_radius, -- LEGACY + explosion_damage_radius = def.explosion_damage_radius, -- LEGACY + explosiontimer_reset_radius = def.explosiontimer_reset_radius, + explosion_timer = def.explosion_timer or 3, + allow_fuse_reset = def.allow_fuse_reset ~= false, + stop_to_explode = def.stop_to_explode ~= false, + custom_attack = def.custom_attack, + double_melee_attack = def.double_melee_attack, + dogshoot_switch = def.dogshoot_switch, + dogshoot_count = 0, + dogshoot_count_max = def.dogshoot_count_max or 5, + dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), + attack_animals = def.attack_animals or false, + attack_npcs = def.attack_npcs or false, + specific_attack = def.specific_attack, + runaway_from = def.runaway_from, + owner_loyal = def.owner_loyal, + facing_fence = false, + is_mob = true, + pushable = def.pushable or true, + + -- MCL2 extensions + shooter_avoid_enemy = def.shooter_avoid_enemy, + strafes = def.strafes, + avoid_distance = def.avoid_distance or 9, + do_teleport = def.do_teleport, + spawn_class = def.spawn_class, + can_spawn = def.can_spawn, + ignores_nametag = def.ignores_nametag or false, + rain_damage = def.rain_damage or 0, + glow = def.glow, + can_despawn = can_despawn, + child = def.child or false, + texture_mods = {}, + shoot_arrow = def.shoot_arrow, + sounds_child = def.sounds_child, + _child_animations = def.child_animations, + pick_up = def.pick_up, + explosion_strength = def.explosion_strength, + suffocation_timer = 0, + follow_velocity = def.follow_velocity or 2.4, + instant_death = def.instant_death or false, + fire_resistant = def.fire_resistant or false, + fire_damage_resistant = def.fire_damage_resistant or false, + ignited_by_sunlight = def.ignited_by_sunlight or false, + spawn_in_group = def.spawn_in_group, + spawn_in_group_min = def.spawn_in_group_min, + noyaw = def.noyaw or false, + particlespawners = def.particlespawners, + -- End of MCL2 extensions + on_spawn = def.on_spawn, + on_blast = def.on_blast or function(self,damage) + self.object:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, nil) + return false, true, {} + end, + do_punch = def.do_punch, + on_breed = def.on_breed, + on_grown = def.on_grown, + on_pick_up = def.on_pick_up, + on_activate = function(self, staticdata, dtime) + --this is a temporary hack so mobs stop + --glitching and acting really weird with the + --default built in engine collision detection + self.is_mob = true + self.object:set_properties({ + collide_with_objects = false, + }) + + return self:mob_activate(staticdata, def, dtime) + end, + harmed_by_heal = def.harmed_by_heal, + on_lightning_strike = def.on_lightning_strike + } + minetest.register_entity(name, setmetatable(final_def,mcl_mobs.mob_class_meta)) + + if minetest.get_modpath("doc_identifier") ~= nil then + doc.sub.identifier.register_object(name, "basics", "mobs") + end + +end -- END mcl_mobs.register_mob function + + +-- register arrow for shoot attack +function mcl_mobs.register_arrow(name, def) + + if not name or not def then return end -- errorcheck + + minetest.register_entity(name, { + + physical = false, + visual = def.visual, + visual_size = def.visual_size, + textures = def.textures, + velocity = def.velocity, + hit_player = def.hit_player, + hit_node = def.hit_node, + hit_mob = def.hit_mob, + hit_object = def.hit_object, + drop = def.drop or false, -- drops arrow as registered item when true + collisionbox = {0, 0, 0, 0, 0, 0}, -- remove box around arrows + timer = 0, + switch = 0, + owner_id = def.owner_id, + rotate = def.rotate, + on_punch = function(self) + local vel = self.object:get_velocity() + self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) + end, + collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, + automatic_face_movement_dir = def.rotate + and (def.rotate - (math.pi / 180)) or false, + + on_activate = def.on_activate, + + on_step = def.on_step or function(self, dtime) + + self.timer = self.timer + 1 + + local pos = self.object:get_pos() + + if self.switch == 0 + or self.timer > 150 + or not within_limits(pos, 0) then + mcl_burning.extinguish(self.object) + self.object:remove(); + + return + end + + -- does arrow have a tail (fireball) + if def.tail + and def.tail == 1 + and def.tail_texture then + + minetest.add_particle({ + pos = pos, + velocity = {x = 0, y = 0, z = 0}, + acceleration = {x = 0, y = 0, z = 0}, + expirationtime = def.expire or 0.25, + collisiondetection = false, + texture = def.tail_texture, + size = def.tail_size or 5, + glow = def.glow or 0, + }) + end + + if self.hit_node then + + local node = node_ok(pos).name + + if minetest.registered_nodes[node].walkable then + + self.hit_node(self, pos, node) + + if self.drop == true then + + pos.y = pos.y + 1 + + self.lastpos = (self.lastpos or pos) + + minetest.add_item(self.lastpos, self.object:get_luaentity().name) + end + + self.object:remove(); + + return + end + end + + if self.hit_player or self.hit_mob or self.hit_object then + + for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + + if self.hit_player + and player:is_player() then + + self.hit_player(self, player) + self.object:remove(); + return + end + + local entity = player:get_luaentity() + + if entity + and self.hit_mob + and entity.is_mob == true + and tostring(player) ~= self.owner_id + and entity.name ~= self.object:get_luaentity().name then + self.hit_mob(self, player) + self.object:remove(); + return + end + + if entity + and self.hit_object + and (not entity.is_mob) + and tostring(player) ~= self.owner_id + and entity.name ~= self.object:get_luaentity().name then + self.hit_object(self, player) + self.object:remove(); + return + end + end + end + + self.lastpos = pos + end + }) +end + +-- Register spawn eggs + +-- Note: This also introduces the “spawn_egg” group: +-- * spawn_egg=1: Spawn egg (generic mob, no metadata) +-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata) +function mcl_mobs.register_egg(mob, desc, background_color, overlay_color, addegg, no_creative) + + local grp = {spawn_egg = 1} + + -- do NOT add this egg to creative inventory (e.g. dungeon master) + if no_creative == true then + grp.not_in_creative_inventory = 1 + end + + local invimg = "(spawn_egg.png^[multiply:" .. background_color ..")^(spawn_egg_overlay.png^[multiply:" .. overlay_color .. ")" + if old_spawn_icons then + local mobname = mob:gsub("mobs_mc:","") + local fn = "mobs_mc_spawn_icon_"..mobname..".png" + if mcl_util.file_exists(minetest.get_modpath("mobs_mc").."/textures/"..fn) then + invimg = fn + end + end + if addegg == 1 then + invimg = "mobs_chicken_egg.png^(" .. invimg .. + "^[mask:mobs_chicken_egg_overlay.png)" + end + + -- register old stackable mob egg + minetest.register_craftitem(mob, { + + description = desc, + inventory_image = invimg, + groups = grp, + + _doc_items_longdesc = S("This allows you to place a single mob."), + _doc_items_usagehelp = S("Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns."), + + on_place = function(itemstack, placer, pointed_thing) + + local pos = pointed_thing.above + + -- am I clicking on something with existing on_rightclick function? + local under = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[under.name] + if def and def.on_rightclick then + return def.on_rightclick(pointed_thing.under, under, placer, itemstack) + end + + if pos + and within_limits(pos, 0) + and not minetest.is_protected(pos, placer:get_player_name()) then + + local name = placer:get_player_name() + local privs = minetest.get_player_privs(name) + if under.name == "mcl_mobspawners:spawner" then + if minetest.is_protected(pointed_thing.under, name) then + minetest.record_protection_violation(pointed_thing.under, name) + return itemstack + end + if not privs.maphack then + minetest.chat_send_player(name, S("You need the “maphack” privilege to change the mob spawner.")) + return itemstack + end + mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name()) + if not minetest.is_creative_enabled(name) then + itemstack:take_item() + end + return itemstack + end + + if not minetest.registered_entities[mob] then + return itemstack + end + + if minetest.settings:get_bool("only_peaceful_mobs", false) + and minetest.registered_entities[mob].type == "monster" then + minetest.chat_send_player(name, S("Only peaceful mobs allowed!")) + return itemstack + end + + pos.y = pos.y - 0.5 + + local mob = minetest.add_entity(pos, mob) + local entityname = itemstack:get_name() + minetest.log("action", "Player " ..name.." spawned "..entityname.." at "..minetest.pos_to_string(pos)) + local ent = mob:get_luaentity() + + -- don't set owner if monster or sneak pressed + if ent.type ~= "monster" + and not placer:get_player_control().sneak then + ent.owner = placer:get_player_name() + ent.tamed = true + end + + -- set nametag + local nametag = itemstack:get_meta():get_string("name") + if nametag ~= "" then + if string.len(nametag) > MAX_MOB_NAME_LENGTH then + nametag = string.sub(nametag, 1, MAX_MOB_NAME_LENGTH) + end + ent.nametag = nametag + update_tag(ent) + end + + -- if not in creative then take item + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + end + + return itemstack + end, + }) + +end diff --git a/mods/ENTITIES/mcl_mobs/items.lua b/mods/ENTITIES/mcl_mobs/items.lua new file mode 100644 index 000000000..267dd8595 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/items.lua @@ -0,0 +1,103 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class +--- Item and armor management + +local function player_near(pos) + for _,o in pairs(minetest.get_objects_inside_radius(pos,2)) do + if o:is_player() then return true end + end +end + +local function get_armor_texture(armor_name) + if armor_name == "" then + return "" + end + if armor_name=="blank.png" then + return "blank.png" + end + local seperator = string.find(armor_name, ":") + return "mcl_armor_"..string.sub(armor_name, seperator+1, -1)..".png^" +end + +function mob_class:set_armor_texture() + if self.armor_list then + local chestplate=minetest.registered_items[self.armor_list.chestplate] or {name=""} + local boots=minetest.registered_items[self.armor_list.boots] or {name=""} + local leggings=minetest.registered_items[self.armor_list.leggings] or {name=""} + local helmet=minetest.registered_items[self.armor_list.helmet] or {name=""} + + if helmet.name=="" and chestplate.name=="" and leggings.name=="" and boots.name=="" then + helmet={name="blank.png"} + end + local texture = get_armor_texture(chestplate.name)..get_armor_texture(helmet.name)..get_armor_texture(boots.name)..get_armor_texture(leggings.name) + if string.sub(texture, -1,-1) == "^" then + texture=string.sub(texture,1,-2) + end + if self.textures[self.wears_armor] then + self.textures[self.wears_armor]=texture + end + self.object:set_properties({textures=self.textures}) + + local armor_ + if type(self.armor) == "table" then + armor_ = table.copy(self.armor) + armor_.immortal = 1 + else + armor_ = {immortal=1, fleshy = self.armor} + end + + for _,item in pairs(self.armor_list) do + if not item then return end + if type(minetest.get_item_group(item, "mcl_armor_points")) == "number" then + armor_.fleshy=armor_.fleshy-(minetest.get_item_group(item, "mcl_armor_points")*3.5) + end + end + self.object:set_armor_groups(armor_) + end +end + +function mob_class:check_item_pickup() + if self.pick_up and #self.pick_up > 0 or self.wears_armor then + local p = self.object:get_pos() + if not p then return end + for _,o in pairs(minetest.get_objects_inside_radius(p,2)) do + local l=o:get_luaentity() + if l and l.name == "__builtin:item" then + if not player_near(p) and l.itemstring:find("mcl_armor") and self.wears_armor then + local armor_type + if l.itemstring:find("chestplate") then + armor_type = "chestplate" + elseif l.itemstring:find("boots") then + armor_type = "boots" + elseif l.itemstring:find("leggings") then + armor_type = "leggings" + elseif l.itemstring:find("helmet") then + armor_type = "helmet" + end + if not armor_type then + return + end + if not self.armor_list then + self.armor_list={helmet="",chestplate="",boots="",leggings=""} + elseif self.armor_list[armor_type] and self.armor_list[armor_type] ~= "" then + return + end + self.armor_list[armor_type]=ItemStack(l.itemstring):get_name() + o:remove() + end + if self.pick_up then + for k,v in pairs(self.pick_up) do + if not player_near(p) and self.on_pick_up and l.itemstring:find(v) then + local r = self.on_pick_up(self,l) + if r and r.is_empty and not r:is_empty() then + l.itemstring = r:to_string() + elseif r and r.is_empty and r:is_empty() then + o:remove() + end + end + end + end + end + end + end +end diff --git a/mods/ENTITIES/mcl_mobs/mount.lua b/mods/ENTITIES/mcl_mobs/mount.lua index 3944613a5..21c52157a 100644 --- a/mods/ENTITIES/mcl_mobs/mount.lua +++ b/mods/ENTITIES/mcl_mobs/mount.lua @@ -1,4 +1,5 @@ - +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class -- lib_mount by Blert2112 (edited by TenPlus1) local enable_crash = false @@ -206,7 +207,7 @@ function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) -- move forwards if ctrl.up then - entity.v = entity.v + entity.accel / 10 + entity.v = entity.v + entity.accel / 10 * entity.run_velocity / 2.6 -- move backwards elseif ctrl.down then @@ -385,7 +386,6 @@ function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) entity.v2 = v end - -- directional flying routine by D00Med (edited by TenPlus1) function mcl_mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_anim) @@ -446,3 +446,18 @@ function mcl_mobs.fly(entity, dtime, speed, shoots, arrow, moving_anim, stand_an mcl_mobs:set_animation(entity, moving_anim) end end + +mcl_mobs.mob_class.drive = mcl_mobs.drive +mcl_mobs.mob_class.fly = mcl_mobs.fly +mcl_mobs.mob_class.attach = mcl_mobs.attach + +function mob_class:on_detach_child(child) + if self.detach_child then + if self.detach_child(self, child) then + return + end + end + if self.driver == child then + self.driver = nil + end +end diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua new file mode 100644 index 000000000..65023b0d4 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -0,0 +1,1404 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class +local DEFAULT_FALL_SPEED = -9.81*1.5 +local FLOP_HEIGHT = 6 +local FLOP_HOR_SPEED = 1.5 +local PATHFINDING = "gowp" +local enable_pathfinding = true + +local node_ice = "mcl_core:ice" +local node_snowblock = "mcl_core:snowblock" +local node_snow = "mcl_core:snow" + + +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false + +local atann = math.atan +local function atan(x) + if not x or x ~= x then + return 0 + else + return atann(x) + end +end + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + fallback = fallback or mcl_mobs.fallback_node + local node = minetest.get_node_or_nil(pos) + if node and minetest.registered_nodes[node.name] then + return node + end + return minetest.registered_nodes[fallback] +end + +-- Returns true is node can deal damage to self +function mob_class:is_node_dangerous(nodename) + local nn = nodename + if self.lava_damage > 0 then + if minetest.get_item_group(nn, "lava") ~= 0 then + return true + end + end + if self.fire_damage > 0 then + if minetest.get_item_group(nn, "fire") ~= 0 then + return true + end + end + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].damage_per_second and minetest.registered_nodes[nn].damage_per_second > 0 then + return true + end + return false +end + + +-- Returns true if node is a water hazard +function mob_class:is_node_waterhazard(nodename) + local nn = nodename + if self.water_damage > 0 then + if minetest.get_item_group(nn, "water") ~= 0 then + return true + end + end + if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].drowning and minetest.registered_nodes[nn].drowning > 0 then + if self.breath_max ~= -1 then + -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case + -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous + if not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then + return true + end + end + end + return false +end + +-- check line of sight (BrunoMine) +function mob_class:line_of_sight(pos1, pos2, stepsize) + + stepsize = stepsize or 1 + + local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) + + -- normal walking and flying mobs can see you through air + if s == true then + return true + end + + -- New pos1 to be analyzed + local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} + + local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + -- Checks the return + if r == true then return true end + + -- Nodename found + local nn = minetest.get_node(pos).name + + -- Target Distance (td) to travel + local td = vector.distance(pos1, pos2) + + -- Actual Distance (ad) traveled + local ad = 0 + + -- It continues to advance in the line of sight in search of a real + -- obstruction which counts as 'normal' nodebox. + while minetest.registered_nodes[nn] + and minetest.registered_nodes[nn].walkable == false do + + -- Check if you can still move forward + if td < ad + stepsize then + return true -- Reached the target + end + + -- Moves the analyzed pos + local d = vector.distance(pos1, pos2) + + npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x + npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y + npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z + + -- NaN checks + if d == 0 + or npos1.x ~= npos1.x + or npos1.y ~= npos1.y + or npos1.z ~= npos1.z then + return false + end + + ad = ad + stepsize + + -- scan again + r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + if r == true then return true end + + -- New Nodename found + nn = minetest.get_node(pos).name + + end + + return false +end + +function mob_class:can_jump_cliff() + local yaw = self.object:get_yaw() + local pos = self.object:get_pos() + local v = self.object:get_velocity() + + local v2 = math.abs(v.x)+math.abs(v.z)*.833 + local jump_c_multiplier = 1 + if v2/self.walk_velocity/2>1 then + jump_c_multiplier = v2/self.walk_velocity/2 + end + + -- where is front + local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5)*jump_c_multiplier+0.6 + local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5)*jump_c_multiplier+0.6 + + --is there nothing under the block in front? if so jump the gap. + local nodLow = node_ok({ + x = pos.x + dir_x-0.6, + y = pos.y - 0.5, + z = pos.z + dir_z-0.6 + }, "air") + + local nodFar = node_ok({ + x = pos.x + dir_x*2, + y = pos.y - 0.5, + z = pos.z + dir_z*2 + }, "air") + + local nodFar2 = node_ok({ + x = pos.x + dir_x*2.5, + y = pos.y - 0.5, + z = pos.z + dir_z*2.5 + }, "air") + + + if minetest.registered_nodes[nodLow.name] + and minetest.registered_nodes[nodLow.name].walkable ~= true + + + and (minetest.registered_nodes[nodFar.name] + and minetest.registered_nodes[nodFar.name].walkable == true + + or minetest.registered_nodes[nodFar2.name] + and minetest.registered_nodes[nodFar2.name].walkable == true) + + then + --disable fear heigh while we make our jump + self._jumping_cliff = true + minetest.after(1, function() + if self and self.object then + self._jumping_cliff = false + end + end) + return true + else + return false + end +end + +-- is mob facing a cliff or danger +function mob_class:is_at_cliff_or_danger() + if self.fear_height == 0 or self:can_jump_cliff() or self._jumping_cliff or not self.object:get_luaentity() then -- 0 for no falling protection! + return false + end + + local yaw = self.object:get_yaw() + local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5) + local pos = self.object:get_pos() + local ypos = pos.y + self.collisionbox[2] -- just above floor + + local free_fall, blocker = minetest.line_of_sight( + {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, + {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) + if free_fall then + return true + else + local bnode = minetest.get_node(blocker) + local danger = self:is_node_dangerous(bnode.name) + if danger then + return true + else + local def = minetest.registered_nodes[bnode.name] + if def and def.walkable then + return false + end + end + end + + return false +end + + +-- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water +function mob_class:is_at_water_danger() + if not self.object:get_luaentity() or self:can_jump_cliff() or self._jumping_cliff then + return false + end + local yaw = self.object:get_yaw() + local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5) + local pos = self.object:get_pos() + local ypos = pos.y + self.collisionbox[2] -- just above floor + + local free_fall, blocker = minetest.line_of_sight( + {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, + {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) + if free_fall then + return true + else + local bnode = minetest.get_node(blocker) + local waterdanger = self:is_node_waterhazard(bnode.name) + if + waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard( self.standing_on)) then + return false + elseif waterdanger and (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on)) == false then + return true + else + local def = minetest.registered_nodes[bnode.name] + if def and def.walkable then + return false + end + end + end + + return false +end + +-- jump if facing a solid node (not fences or gates) +function mob_class:do_jump() + if not self.jump + or self.jump_height == 0 + or self.fly + or (self.child and self.type ~= "monster") + or self.order == "stand" then + return false + end + + self.facing_fence = false + + -- something stopping us while moving? + if self.state ~= "stand" + and self:get_velocity() > 0.5 + and self.object:get_velocity().y ~= 0 then + return false + end + + local pos = self.object:get_pos() + local yaw = self.object:get_yaw() + + -- what is mob standing on? + pos.y = pos.y + self.collisionbox[2] - 0.2 + + local nod = node_ok(pos) + + if minetest.registered_nodes[nod.name].walkable == false then + return false + end + + local v = self.object:get_velocity() + local v2 = math.abs(v.x)+math.abs(v.z)*.833 + local jump_c_multiplier = 1 + if v2/self.walk_velocity/2>1 then + jump_c_multiplier = v2/self.walk_velocity/2 + end + + -- where is front + local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5)*jump_c_multiplier+0.6 + local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5)*jump_c_multiplier+0.6 + + -- what is in front of mob? + nod = node_ok({ + x = pos.x + dir_x, + y = pos.y + 0.5, + z = pos.z + dir_z + }) + + -- this is used to detect if there's a block on top of the block in front of the mob. + -- If there is, there is no point in jumping as we won't manage. + local nodTop = node_ok({ + x = pos.x + dir_x, + y = pos.y + 1.5, + z = pos.z + dir_z + }, "air") + + + -- we don't attempt to jump if there's a stack of blocks blocking + if minetest.registered_nodes[nodTop.name].walkable == true and not (self.attack and self.state == "attack") then + return false + end + + -- thin blocks that do not need to be jumped + if nod.name == node_snow then + return false + end + + local ndef = minetest.registered_nodes[nod.name] + if self.walk_chance == 0 or ndef and ndef.walkable or self:can_jump_cliff() then + + if minetest.get_item_group(nod.name, "fence") == 0 + and minetest.get_item_group(nod.name, "fence_gate") == 0 + and minetest.get_item_group(nod.name, "wall") == 0 then + + local v = self.object:get_velocity() + + v.y = self.jump_height + 0.1 * 3 + + if self:can_jump_cliff() then + v=vector.multiply(v, vector.new(2.8,1,2.8)) + end + + self:set_animation( "jump") -- only when defined + + self.object:set_velocity(v) + + -- when in air move forward + minetest.after(0.3, function(self, v) + if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then + return + end + self.object:set_acceleration({ + x = v.x * 2, + y = DEFAULT_FALL_SPEED, + z = v.z * 2, + }) + end, self, v) + + if self.jump_sound_cooloff <= 0 then + self:mob_sound("jump") + self.jump_sound_cooloff = 0.5 + end + else + self.facing_fence = true + end + + -- if we jumped against a block/wall 4 times then turn + if self.object:get_velocity().x ~= 0 + and self.object:get_velocity().z ~= 0 then + + self.jump_count = (self.jump_count or 0) + 1 + + if self.jump_count == 4 then + + local yaw = self.object:get_yaw() or 0 + + yaw = self:set_yaw( yaw + 1.35, 8) + + self.jump_count = 0 + end + end + + return true + end + + return false +end + +-- should mob follow what I'm holding ? +function mob_class:follow_holding(clicker) + if self.nofollow then return false end + + if mcl_mobs.invis[clicker:get_player_name()] then + return false + end + + local item = clicker:get_wielded_item() + local t = type(self.follow) + + -- single item + if t == "string" + and item:get_name() == self.follow then + return true + + -- multiple items + elseif t == "table" then + + for no = 1, #self.follow do + + if self.follow[no] == item:get_name() then + return true + end + end + end + + return false +end + + +-- find and replace what mob is looking for (grass, wheat etc.) +function mob_class:replace(pos) + + if not self.replace_rate + or not self.replace_what + or self.child == true + or self.object:get_velocity().y ~= 0 + or math.random(1, self.replace_rate) > 1 then + return + end + + local what, with, y_offset + + if type(self.replace_what[1]) == "table" then + + local num = math.random(#self.replace_what) + + what = self.replace_what[num][1] or "" + with = self.replace_what[num][2] or "" + y_offset = self.replace_what[num][3] or 0 + else + what = self.replace_what + with = self.replace_with or "" + y_offset = self.replace_offset or 0 + end + + pos.y = pos.y + y_offset + + local node = minetest.get_node(pos) + if node.name == what then + + local oldnode = {name = what, param2 = node.param2} + local newnode = {name = with, param2 = node.param2} + local on_replace_return + + if self.on_replace then + on_replace_return = self.on_replace(self, pos, oldnode, newnode) + end + + if on_replace_return ~= false then + + if mobs_griefing then + minetest.set_node(pos, newnode) + end + + end + end +end + +-- specific runaway +local specific_runaway = function(list, what) + if type(list) ~= "table" then + list = {} + end + + -- no list so do not run + if list == nil then + return false + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- find someone to runaway from +function mob_class:check_runaway_from() + if not self.runaway_from and self.state ~= "flop" then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + if mcl_mobs.invis[ objs[n]:get_player_name() ] + or self.owner == objs[n]:get_player_name() + or (not self:object_in_range(objs[n])) then + type = "" + else + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + end + + -- find specific mob to runaway from + if name ~= "" and name ~= self.name + and specific_runaway(self.runaway_from, name) then + + p = player:get_pos() + sp = s + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + dist = vector.distance(p, s) + + + -- choose closest player/mpb to runaway from + if dist < min_dist + and self:line_of_sight(sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + if min_player then + + local lp = player:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 *math.pi/ 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + math.pi + end + + yaw = self:set_yaw( yaw, 4) + self.state = "runaway" + self.runaway_timer = 3 + self.following = nil + end +end + + +-- follow player if owner or holding item, if fish outta water then flop +function mob_class:follow_flop() + + -- find player to follow + if (self.follow ~= "" + or self.order == "follow") + and not self.following + and self.state ~= "attack" + and self.order ~= "sit" + and self.state ~= "runaway" then + + local s = self.object:get_pos() + local players = minetest.get_connected_players() + + for n = 1, #players do + + if (self:object_in_range(players[n])) + and not mcl_mobs.invis[ players[n]:get_player_name() ] then + + self.following = players[n] + + break + end + end + end + + if self.type == "npc" + and self.order == "follow" + and self.state ~= "attack" + and self.order ~= "sit" + and self.owner ~= "" then + + -- npc stop following player if not owner + if self.following + and self.owner + and self.owner ~= self.following:get_player_name() then + self.following = nil + end + else + -- stop following player if not holding specific item, + -- mob is horny, fleeing or attacking + if self.following + and self.following:is_player() + and (self:follow_holding(self.following) == false or + self.horny or self.state == "runaway") then + self.following = nil + end + + end + + -- follow that thing + if self.following then + + local s = self.object:get_pos() + local p + + if self.following:is_player() then + + p = self.following:get_pos() + + elseif self.following.object then + + p = self.following.object:get_pos() + end + + if p then + + local dist = vector.distance(p, s) + + -- dont follow if out of range + if (not self:object_in_range(self.following)) then + self.following = nil + else + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + local yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate + + if p.x > s.x then yaw = yaw +math.pi end + + self:set_yaw( yaw, 2.35) + + -- anyone but standing npc's can move along + if dist > 3 + and self.order ~= "stand" then + + self:set_velocity(self.follow_velocity) + + if self.walk_chance ~= 0 then + self:set_animation( "run") + end + else + self:set_velocity(0) + self:set_animation( "stand") + end + + return + end + end + end + + -- swimmers flop when out of their element, and swim again when back in + if self.fly then + local s = self.object:get_pos() + if self:flight_check( s) == false then + + self.state = "flop" + self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) + + local p = self.object:get_pos() + local sdef = minetest.registered_nodes[node_ok(vector.add(p, vector.new(0,self.collisionbox[2]-0.2,0))).name] + -- Flop on ground + if sdef and sdef.walkable then + if self.object:get_velocity().y < 0.1 then + self:mob_sound("flop") + self.object:set_velocity({ + x = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + y = FLOP_HEIGHT, + z = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + }) + end + end + + self:set_animation( "stand", true) + + return + elseif self.state == "flop" then + self.state = "stand" + self.object:set_acceleration({x = 0, y = 0, z = 0}) + self:set_velocity(0) + end + end +end + +function mob_class:go_to_pos(b) + if not self then return end + local s=self.object:get_pos() + if not b then + --self.state = "stand" + return end + if vector.distance(b,s) < 1 then + --self:set_velocity(0) + return true + end + local v = { x = b.x - s.x, z = b.z - s.z } + local yaw = (atann(v.z / v.x) +math.pi/ 2) - self.rotate + if b.x > s.x then yaw = yaw +math.pi end + self.object:set_yaw(yaw) + self:set_velocity(self.follow_velocity) + self:set_animation("walk") +end + +local check_herd_timer = 0 +function mob_class:check_herd(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 + self:go_to_pos(p) + elseif y then + self:set_yaw(y) + end + end + end +end + +function mob_class:teleport(target) + if self.do_teleport then + if self.do_teleport(self, target) == false then + return + end + end +end + +-- execute current state (stand, walk, run, attacks) +-- returns true if mob has died +function mob_class:do_states(dtime) + --if self.can_open_doors then check_doors(self) end + + local yaw = self.object:get_yaw() or 0 + + if self.state == "stand" then + if math.random(1, 4) == 1 then + + local s = self.object:get_pos() + local objs = minetest.get_objects_inside_radius(s, 3) + local lp + for n = 1, #objs do + if objs[n]:is_player() then + lp = objs[n]:get_pos() + break + end + end + + -- look at any players nearby, otherwise turn randomly + if lp and self.look_at_players then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate + + if lp.x > s.x then yaw = yaw +math.pi end + else + yaw = yaw + math.random(-0.5, 0.5) + end + + yaw = self:set_yaw( yaw, 8) + end + if self.order == "sit" then + self:set_animation( "sit") + self:set_velocity(0) + else + self:set_animation( "stand") + self:set_velocity(0) + end + + -- npc's ordered to stand stay standing + if self.order == "stand" or self.order == "sleep" or self.order == "work" then + + else + if self.walk_chance ~= 0 + and self.facing_fence ~= true + and math.random(1, 100) <= self.walk_chance + and self:is_at_cliff_or_danger() == false then + + self:set_velocity(self.walk_velocity) + self.state = "walk" + self:set_animation( "walk") + end + end + + elseif self.state == PATHFINDING then + self:check_gowp(dtime) + + elseif self.state == "walk" then + local s = self.object:get_pos() + local lp = nil + + -- is there something I need to avoid? + if (self.water_damage > 0 + and self.lava_damage > 0) + or self.breath_max ~= -1 then + + lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) + + elseif self.water_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:water"}) + + elseif self.lava_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:lava"}) + + elseif self.fire_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:fire"}) + + end + + local is_in_danger = false + if lp then + -- If mob in or on dangerous block, look for land + if (self:is_node_dangerous(self.standing_in) or + self:is_node_dangerous(self.standing_on)) or (self:is_node_waterhazard(self.standing_in) or self:is_node_waterhazard(self.standing_on)) and (not self.fly) then + is_in_danger = true + + -- If mob in or on dangerous block, look for land + if is_in_danger then + -- Better way to find shore - copied from upstream + lp = minetest.find_nodes_in_area_under_air( + {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, + {x = s.x + 5, y = s.y + 1, z = s.z + 5}, + {"group:solid"}) + + lp = #lp > 0 and lp[math.random(#lp)] + + -- did we find land? + if lp then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate + + + if lp.x > s.x then yaw = yaw +math.pi end + + -- look towards land and move in that direction + yaw = self:set_yaw( yaw, 6) + self:set_velocity(self.walk_velocity) + + end + end + + -- A danger is near but mob is not inside + else + + -- Randomly turn + if math.random(1, 100) <= 30 then + yaw = yaw + math.random(-0.5, 0.5) + yaw = self:set_yaw( yaw, 8) + end + end + + yaw = self:set_yaw( yaw, 8) + + -- otherwise randomly turn + elseif math.random(1, 100) <= 30 then + yaw = yaw + math.random(-0.5, 0.5) + yaw = self:set_yaw( yaw, 8) + end + + -- stand for great fall or danger or fence in front + local cliff_or_danger = false + if is_in_danger then + cliff_or_danger = self:is_at_cliff_or_danger() + end + if self.facing_fence == true + or cliff_or_danger + or math.random(1, 100) <= 30 then + + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + local yaw = self.object:get_yaw() or 0 + yaw = self:set_yaw( yaw + 0.78, 8) + else + + self:set_velocity(self.walk_velocity) + + if self:flight_check() + and self.animation + and self.animation.fly_start + and self.animation.fly_end then + self:set_animation( "fly") + else + self:set_animation( "walk") + end + end + + -- runaway when punched + elseif self.state == "runaway" then + + self.runaway_timer = self.runaway_timer + 1 + + -- stop after 5 seconds or when at cliff + if self.runaway_timer > 5 + or self:is_at_cliff_or_danger() then + self.runaway_timer = 0 + self:set_velocity(0) + self.state = "stand" + self:set_animation( "stand") + local yaw = self.object:get_yaw() or 0 + yaw = self:set_yaw( yaw + 0.78, 8) + else + self:set_velocity( self.run_velocity) + self:set_animation( "run") + end + + -- attack routines (explode, dogfight, shoot, dogshoot) + elseif self.state == "attack" then + + local s = self.object:get_pos() + local p = self.attack:get_pos() or s + + -- stop attacking if player invisible or out of range + if not self.attack + or not self.attack:get_pos() + or not self:object_in_range(self.attack) + or self.attack:get_hp() <= 0 + or (self.attack:is_player() and mcl_mobs.invis[ self.attack:get_player_name() ]) then + + self.state = "stand" + self:set_velocity( 0) + self:set_animation( "stand") + self.attack = nil + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.path.way = nil + + return + end + + -- calculate distance from mob and enemy + local dist = vector.distance(p, s) + + if self.attack_type == "explode" then + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate + + if p.x > s.x then yaw = yaw +math.pi end + + yaw = self:set_yaw( yaw, 0, dtime) + + local node_break_radius = self.explosion_radius or 1 + local entity_damage_radius = self.explosion_damage_radius + or (node_break_radius * 2) + + -- start timer when in reach and line of sight + if not self.v_start + and dist <= self.reach + and self:line_of_sight( s, p, 2) then + + self.v_start = true + self.timer = 0 + self.blinktimer = 0 + self:mob_sound("fuse", nil, false) + + -- stop timer if out of reach or direct line of sight + elseif self.allow_fuse_reset + and self.v_start + and (dist >= self.explosiontimer_reset_radius + or not self:line_of_sight( s, p, 2)) then + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.blinkstatus = false + self:remove_texture_mod("^[brighten") + end + + -- walk right up to player unless the timer is active + if self.v_start and (self.stop_to_explode or dist < self.reach) then + self:set_velocity( 0) + else + self:set_velocity( self.run_velocity) + end + + if self.animation and self.animation.run_start then + self:set_animation( "run") + else + self:set_animation( "walk") + end + + if self.v_start then + + self.timer = self.timer + dtime + self.blinktimer = (self.blinktimer or 0) + dtime + + if self.blinktimer > 0.2 then + + self.blinktimer = 0 + + if self.blinkstatus then + self:remove_texture_mod("^[brighten") + else + self:add_texture_mod("^[brighten") + end + + self.blinkstatus = not self.blinkstatus + end + + if self.timer > self.explosion_timer then + + local pos = self.object:get_pos() + + if mobs_griefing and not minetest.is_protected(pos, "") then + mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) + else + minetest.sound_play(self.sounds.explode, { + pos = pos, + gain = 1.0, + max_hear_distance = self.sounds.distance or 32 + }, true) + self:entity_physics(pos,entity_damage_radius) + mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0) + end + mcl_burning.extinguish(self.object) + self.object:remove() + + return true + end + end + + elseif self.attack_type == "dogfight" + or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 2) and (dist >= self.avoid_distance or not self.shooter_avoid_enemy) + or (self.attack_type == "dogshoot" and dist <= self.reach and self:dogswitch() == 0) then + + if self.fly + and dist > self.reach then + + local p1 = s + local me_y = math.floor(p1.y) + local p2 = p + local p_y = math.floor(p2.y + 1) + local v = self.object:get_velocity() + + if self:flight_check( s) then + + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 1 * self.walk_velocity, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -1 * self.walk_velocity, + z = v.z + }) + end + else + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 0.01, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -0.01, + z = v.z + }) + end + end + + end + + -- rnd: new movement direction + if self.path.following + and self.path.way + and self.attack_type ~= "dogshoot" then + + -- no paths longer than 50 + if #self.path.way > 50 + or dist < self.reach then + self.path.following = false + return + end + + local p1 = self.path.way[1] + + if not p1 then + self.path.following = false + return + end + + if math.abs(p1.x-s.x) + math.abs(p1.z - s.z) < 0.6 then + -- reached waypoint, remove it from queue + table.remove(self.path.way, 1) + end + + -- set new temporary target + p = {x = p1.x, y = p1.y, z = p1.z} + end + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math.pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + math.pi end + + yaw = self:set_yaw( yaw, 0, dtime) + + -- move towards enemy if beyond mob reach + if dist > self.reach then + + -- path finding by rnd + if self.pathfinding -- only if mob has pathfinding enabled + and enable_pathfinding then + + self:smart_mobs(s, p, dist, dtime) + end + + if self:is_at_cliff_or_danger() then + + self:set_velocity( 0) + self:set_animation( "stand") + local yaw = self.object:get_yaw() or 0 + yaw = self:set_yaw( yaw + 0.78, 8) + else + + if self.path.stuck then + self:set_velocity( self.walk_velocity) + else + self:set_velocity( self.run_velocity) + end + + if self.animation and self.animation.run_start then + self:set_animation( "run") + else + self:set_animation( "walk") + end + end + + else -- rnd: if inside reach range + + self.path.stuck = false + self.path.stuck_timer = 0 + self.path.following = false -- not stuck anymore + + self:set_velocity( 0) + + if not self.custom_attack then + + if self.timer > 1 then + + self.timer = 0 + + if self.double_melee_attack + and math.random(1, 2) == 1 then + self:set_animation( "punch2") + else + self:set_animation( "punch") + end + + local p2 = p + local s2 = s + + p2.y = p2.y + .5 + s2.y = s2.y + .5 + + if self:line_of_sight( p2, s2) == true then + + -- play attack sound + self:mob_sound("attack") + + -- punch player (or what player is attached to) + local attached = self.attack:get_attach() + if attached then + self.attack = attached + end + self.attack:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self.damage} + }, nil) + end + end + else -- call custom attack every second + if self.custom_attack + and self.timer > 1 then + + self.timer = 0 + + self.custom_attack(self, p) + end + end + end + + elseif self.attack_type == "shoot" + or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 1) + or (self.attack_type == "dogshoot" and (dist > self.reach or dist < self.avoid_distance and self.shooter_avoid_enemy) and self:dogswitch() == 0) then + + p.y = p.y - .5 + s.y = s.y + .5 + + local dist = vector.distance(p, s) + local vec = { + x = p.x - s.x, + y = p.y - s.y, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate + + if p.x > s.x then yaw = yaw +math.pi end + + yaw = self:set_yaw( yaw, 0, dtime) + + local stay_away_from_player = vector.new(0,0,0) + + --strafe back and fourth + + --stay away from player so as to shoot them + if dist < self.avoid_distance and self.shooter_avoid_enemy then + self:set_animation( "shoot") + stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33) + end + + if self.strafes then + if not self.strafe_direction then + self.strafe_direction = 1.57 + end + if math.random(40) == 1 then + self.strafe_direction = self.strafe_direction*-1 + end + self.acc = vector.add(vector.multiply(vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction), 0.3*self.walk_velocity), stay_away_from_player) + else + self:set_velocity( 0) + end + + local p = self.object:get_pos() + p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 + + if self.shoot_interval + and self.timer > self.shoot_interval + and not minetest.raycast(vector.add(p, vector.new(0,self.shoot_offset,0)), vector.add(self.attack:get_pos(), vector.new(0,1.5,0)), false, false):next() + and math.random(1, 100) <= 60 then + + self.timer = 0 + self:set_animation( "shoot") + + -- play shoot attack sound + self:mob_sound("shoot_attack") + + -- Shoot arrow + if minetest.registered_entities[self.arrow] then + + local arrow, ent + local v = 1 + if not self.shoot_arrow then + self.firing = true + minetest.after(1, function() + self.firing = false + end) + arrow = minetest.add_entity(p, self.arrow) + ent = arrow:get_luaentity() + if ent.velocity then + v = ent.velocity + end + ent.switch = 1 + ent.owner_id = tostring(self.object) -- add unique owner id to arrow + + -- important for mcl_shields + ent._shooter = self.object + ent._saved_shooter_pos = self.object:get_pos() + end + + local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 + -- offset makes shoot aim accurate + vec.y = vec.y + self.shoot_offset + vec.x = vec.x * (v / amount) + vec.y = vec.y * (v / amount) + vec.z = vec.z * (v / amount) + if self.shoot_arrow then + vec = vector.normalize(vec) + self:shoot_arrow(p, vec) + else + arrow:set_velocity(vec) + end + end + end + else + + end + end +end + +function mob_class:check_smooth_rotation(dtime) + -- smooth rotation by ThomasMonroe314 + if self._turn_to then + self:set_yaw( self._turn_to, .1) + end + + if self.delay and self.delay > 0 then + + local yaw = self.object:get_yaw() or 0 + + if self.delay == 1 then + yaw = self.target_yaw + else + local dif = math.abs(yaw - self.target_yaw) + + if yaw > self.target_yaw then + + if dif > math.pi then + dif = 2 * math.pi - dif -- need to add + yaw = yaw + dif / self.delay + else + yaw = yaw - dif / self.delay -- need to subtract + end + + elseif yaw < self.target_yaw then + + if dif >math.pi then + dif = 2 * math.pi - dif + yaw = yaw - dif / self.delay -- need to subtract + else + yaw = yaw + dif / self.delay -- need to add + end + end + + if yaw > (math.pi * 2) then yaw = yaw - (math.pi * 2) end + if yaw < 0 then yaw = yaw + (math.pi * 2) end + end + + self.delay = self.delay - 1 + if self.shaking then + yaw = yaw + (math.random() * 2 - 1) * 5 * dtime + end + self.object:set_yaw(yaw) + self:update_roll() + end + -- end rotation +end diff --git a/mods/ENTITIES/mcl_mobs/pathfinding.lua b/mods/ENTITIES/mcl_mobs/pathfinding.lua new file mode 100644 index 000000000..6cb37434f --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/pathfinding.lua @@ -0,0 +1,382 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class + +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false) +local PATHFINDING = "gowp" +local enable_pathfinding = true + +local LOG_MODULE = "[Mobs]" +local function mcl_log (message) + if LOGGING_ON and message then + minetest.log(LOG_MODULE .. " " .. message) + end +end + +function output_table (wp) + if not wp then return end + mcl_log("wp items: ".. tostring(#wp)) + for a,b in pairs(wp) do + mcl_log(a.. ": ".. tostring(b)) + end +end + +function append_paths (wp1, wp2) + mcl_log("Start append") + if not wp1 or not wp2 then + mcl_log("Cannot append wp's") + return + end + output_table(wp1) + output_table(wp2) + for _,a in pairs (wp2) do + table.insert(wp1, a) + end + mcl_log("End append") +end + +local function output_enriched (wp_out) + mcl_log("Output enriched path") + local i = 0 + for _,outy in pairs (wp_out) do + i = i + 1 + mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"])) + + local action = outy["action"] + if action then + mcl_log("type: " .. action["type"]) + mcl_log("action: " .. action["action"]) + mcl_log("target: " .. minetest.pos_to_string(action["target"])) + end + mcl_log("failed attempts: " .. outy["failed_attempts"]) + end +end + +-- This function will take a list of paths, and enrich it with: +-- a var for failed attempts +-- an action, such as to open or close a door where we know that pos requires that action +local function generate_enriched_path(wp_in, door_open_pos, door_close_pos, cur_door_pos) + local wp_out = {} + for i, cur_pos in pairs(wp_in) do + local action = nil + + local one_down = vector.new(0,-1,0) + local cur_pos_to_add = vector.add(cur_pos, one_down) + if door_open_pos and vector.equals (cur_pos, door_open_pos) then + mcl_log ("Door open match") + --action = {type = "door", action = "open"} + action = {} + action["type"] = "door" + action["action"] = "open" + action["target"] = cur_door_pos + cur_pos_to_add = vector.add(cur_pos, one_down) + elseif door_close_pos and vector.equals(cur_pos, door_close_pos) then + mcl_log ("Door close match") + --action = {type = "door", action = "closed"} + action = {} + action["type"] = "door" + action["action"] = "close" + action["target"] = cur_door_pos + cur_pos_to_add = vector.add(cur_pos, one_down) + elseif cur_door_pos and vector.equals(cur_pos, cur_door_pos) then + mcl_log("Current door pos") + cur_pos_to_add = vector.add(cur_pos, one_down) + action = {} + action["type"] = "door" + action["action"] = "open" + action["target"] = cur_door_pos + else + cur_pos_to_add = cur_pos + --mcl_log ("Pos doesn't match") + end + + wp_out[i] = {} + wp_out[i]["pos"] = cur_pos_to_add + wp_out[i]["failed_attempts"] = 0 + wp_out[i]["action"] = action + + --wp_out[i] = {"pos" = cur_pos, "failed_attempts" = 0, "action" = action} + --output_pos(cur_pos, i) + end + output_enriched(wp_out) + return wp_out +end + +local plane_adjacents = { + vector.new(1,0,0), + vector.new(-1,0,0), + vector.new(0,0,1), + vector.new(0,0,-1), +} + +-- This function is used to see if we can path. We could use to check a route, rather than making people move. +local function calculate_path_through_door (p, t, target) + -- target is the same as t, just 1 square difference. Maybe we don't need target + mcl_log("Plot route from mob: " .. minetest.pos_to_string(p) .. ", to target: " .. minetest.pos_to_string(t)) + + local enriched_path = nil + + local cur_door_pos = nil + local pos_closest_to_door = nil + local other_side_of_door = nil + + --Path to door first + local wp = minetest.find_path(p,t,150,1,4) + if not wp then + mcl_log("No direct path. Path through door") + + -- This could improve. There could be multiple doors. Check you can path from door to target first. + local cur_door_pos = minetest.find_node_near(target,16,{"group:door"}) + if cur_door_pos then + mcl_log("Found a door near: " .. minetest.pos_to_string(cur_door_pos)) + for _,v in pairs(plane_adjacents) do + pos_closest_to_door = vector.add(cur_door_pos,v) + + local n = minetest.get_node(pos_closest_to_door) + if n.name == "air" then + wp = minetest.find_path(p,pos_closest_to_door,150,1,4) + if wp then + mcl_log("Found a path to next to door".. minetest.pos_to_string(pos_closest_to_door)) + other_side_of_door = vector.add(cur_door_pos,-v) + mcl_log("Opposite is: ".. minetest.pos_to_string(other_side_of_door)) + + local wp_otherside_door_to_target = minetest.find_path(other_side_of_door,t,150,1,4) + if wp_otherside_door_to_target and #wp_otherside_door_to_target > 0 then + table.insert(wp, cur_door_pos) + append_paths (wp, wp_otherside_door_to_target) + enriched_path = generate_enriched_path(wp, pos_closest_to_door, other_side_of_door, cur_door_pos) + mcl_log("We have a path from outside door to target") + else + mcl_log("We cannot path from outside door to target") + end + break + else + mcl_log("This block next to door doesn't work.") + end + else + mcl_log("Block is not air, it is: ".. n.name) + end + + end + else + mcl_log("No door found") + end + else + mcl_log("We have a direct route") + end + + if wp and not enriched_path then + enriched_path = generate_enriched_path(wp) + end + return enriched_path +end + +local gopath_last = os.time() +function mob_class:gopath(target,callback_arrived) + if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end + + if self._pf_last_failed and (os.time() - self._pf_last_failed) < 30 then + mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed)) + return + else + mcl_log("We are ready to pathfind, no previous fail or we are past threshold") + end + + --if os.time() - gopath_last < 5 then + -- mcl_log("Not ready to path yet") + -- return + --end + --gopath_last = os.time() + + self.order = nil + + local p = self.object:get_pos() + local t = vector.offset(target,0,1,0) + + local wp = calculate_path_through_door(p, t, target) + if not wp then + mcl_log("Could not calculate path") + self._pf_last_failed = os.time() + -- Cover for a flaw in pathfind where it chooses the wrong door and gets stuck. Take a break, allow others. + end + --output_table(wp) + + if wp and #wp > 0 then + self._target = t + self.callback_arrived = callback_arrived + local current_location = table.remove(wp,1) + if current_location and current_location["pos"] then + mcl_log("Removing first co-ord? " .. tostring(current_location["pos"])) + else + mcl_log("Nil pos") + end + self.current_target = current_location + self.waypoints = wp + self.state = PATHFINDING + return true + else + self.state = "walk" + self.waypoints = nil + self.current_target = nil + -- minetest.log("no path found") + end +end + +function mob_class:interact_with_door(action, target) + local p = self.object:get_pos() + --local t = minetest.get_timeofday() + --local dd = minetest.find_nodes_in_area(vector.offset(p,-1,-1,-1),vector.offset(p,1,1,1),{"group:door"}) + --for _,d in pairs(dd) do + if target then + mcl_log("Door target is: ".. minetest.pos_to_string(target)) + + local n = minetest.get_node(target) + if n.name:find("_b_") or n.name:find("_t_") then + mcl_log("Door") + local def = minetest.registered_nodes[n.name] + local closed = n.name:find("_b_1") or n.name:find("_t_1") + --if self.state == PATHFINDING then + if closed and action == "open" and def.on_rightclick then + mcl_log("Open door") + def.on_rightclick(target,n,self) + end + if not closed and action == "close" and def.on_rightclick then + mcl_log("Close door") + def.on_rightclick(target,n,self) + end + --else + else + mcl_log("Not door") + end + else + mcl_log("no target. cannot try and open or close door") + end + --end +end + +function mob_class:do_pathfind_action(action) + if action then + mcl_log("Action present") + local type = action["type"] + local action_val = action["action"] + local target = action["target"] + if target then + mcl_log("Target: ".. minetest.pos_to_string(target)) + end + if type and type == "door" then + mcl_log("Type is door") + self:interact_with_door(action_val, target) + end + end +end + +local gowp_etime = 0 + +function mob_class:check_gowp(dtime) + gowp_etime = gowp_etime + dtime + + -- 0.1 is optimal. + --less frequently = villager will get sent back after passing a point. + --more frequently = villager will fail points they shouldn't they just didn't get there yet + + --if gowp_etime < 0.05 then return end + --gowp_etime = 0 + local p = self.object:get_pos() + + -- no destination + if not p or not self._target then + mcl_log("p: ".. tostring(p)) + mcl_log("self._target: ".. tostring(self._target)) + return + end + + -- arrived at location, finish gowp + local distance_to_targ = vector.distance(p,self._target) + --mcl_log("Distance to targ: ".. tostring(distance_to_targ)) + if distance_to_targ < 2 then + mcl_log("Arrived at _target") + self.waypoints = nil + self._target = nil + self.current_target = nil + self.state = "stand" + self.order = "stand" + self.object:set_velocity({x = 0, y = 0, z = 0}) + self.object:set_acceleration({x = 0, y = 0, z = 0}) + if self.callback_arrived then return self.callback_arrived(self) end + return true + end + + -- More pathing to be done + local distance_to_current_target = 50 + if self.current_target and self.current_target["pos"] then + distance_to_current_target = vector.distance(p,self.current_target["pos"]) + end + + -- 0.6 is working but too sensitive. sends villager back too frequently. 0.7 is quite good, but not with heights + -- 0.8 is optimal for 0.025 frequency checks and also 1... Actually. 0.8 is winning + -- 0.9 and 1.0 is also good. Stick with unless door open or closing issues + if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < 0.9 ) then + -- We have waypoints, and no current target, or we're at it. We need a new current_target. + self:do_pathfind_action (self.current_target["action"]) + + local failed_attempts = self.current_target["failed_attempts"] + mcl_log("There after " .. failed_attempts .. " failed attempts. current target:".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: " .. distance_to_current_target) + + self.current_target = table.remove(self.waypoints, 1) + self:go_to_pos(self.current_target["pos"]) + return + elseif self.current_target and self.current_target["pos"] then + -- No waypoints left, but have current target. Potentially last waypoint to go to. + self.current_target["failed_attempts"] = self.current_target["failed_attempts"] + 1 + local failed_attempts = self.current_target["failed_attempts"] + if failed_attempts >= 50 then + mcl_log("Failed to reach position (" .. minetest.pos_to_string(self.current_target["pos"]) .. ") too many times. Abandon route. Times tried: " .. failed_attempts) + self.state = "stand" + self.current_target = nil + self.waypoints = nil + self._target = nil + self._pf_last_failed = os.time() + self.object:set_velocity({x = 0, y = 0, z = 0}) + self.object:set_acceleration({x = 0, y = 0, z = 0}) + return + end + + --mcl_log("Not at pos with failed attempts ".. failed_attempts ..": ".. minetest.pos_to_string(p) .. "self.current_target: ".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: ".. distance_to_current_target) + self:go_to_pos(self.current_target["pos"]) + -- Do i just delete current_target, and return so we can find final path. + else + -- Not at target, no current waypoints or current_target. Through the door and should be able to path to target. + -- Is a little sensitive and could take 1 - 7 times. A 10 fail count might be a good exit condition. + + mcl_log("We don't have waypoints or a current target. Let's try to path to target") + local final_wp = minetest.find_path(p,self._target,150,1,4) + if final_wp then + mcl_log("We might be able to get to target here.") + -- self.waypoints = final_wp + self:go_to_pos(self._target) + else + -- Abandon route? + mcl_log("Cannot plot final route to target") + end + end + + -- I don't think we need the following anymore, but test first. + -- Maybe just need something to path to target if no waypoints left + if self.current_target and self.current_target["pos"] and (self.waypoints and #self.waypoints == 0) then + local updated_p = self.object:get_pos() + local distance_to_cur_targ = vector.distance(updated_p,self.current_target["pos"]) + + mcl_log("Distance to current target: ".. tostring(distance_to_cur_targ)) + mcl_log("Current p: ".. minetest.pos_to_string(updated_p)) + + -- 1.6 is good. is 1.9 better? It could fail less, but will it path to door when it isn't after door + if distance_to_cur_targ > 1.9 then + mcl_log("not close to current target: ".. minetest.pos_to_string(self.current_target["pos"])) + self:go_to_pos(self._current_target) + else + mcl_log("close to current target: ".. minetest.pos_to_string(self.current_target["pos"])) + self.current_target = nil + end + + return + end +end diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua new file mode 100644 index 000000000..a03e21543 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -0,0 +1,976 @@ +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class + +local ENTITY_CRAMMING_MAX = 24 +local CRAMMING_DAMAGE = 3 +local DEATH_DELAY = 0.5 +local DEFAULT_FALL_SPEED = -9.81*1.5 +local FLOP_HEIGHT = 6 +local FLOP_HOR_SPEED = 1.5 +local PATHFINDING = "gowp" +local mobs_debug = minetest.settings:get_bool("mobs_debug", false) +local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false +local mob_active_range = tonumber(minetest.settings:get("mcl_mob_active_range")) or 48 +local show_health = false + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + + fallback = fallback or mcl_mobs.fallback_node + + local node = minetest.get_node_or_nil(pos) + + if node and minetest.registered_nodes[node.name] then + return node + end + + return minetest.registered_nodes[fallback] +end + +-- check if within physical map limits (-30911 to 30927) +local function within_limits(pos, radius) + local wmin, wmax = -30912, 30928 + if mcl_vars then + if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then + wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + end + end + if radius then + wmin = wmin - radius + wmax = wmax + radius + end + if not pos then return true end + for _,v in pairs(pos) do + if v < wmin or v > wmax then return false end + end + return true +end + +function mob_class:player_in_active_range() + for _,p in pairs(minetest.get_connected_players()) do + if vector.distance(self.object:get_pos(),p:get_pos()) <= mob_active_range 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 + +-- Return true if object is in view_range +function mob_class:object_in_range(object) + if not object then + return false + end + local factor + -- Apply view range reduction for special player armor + if object:is_player() then + local factors = mcl_armor.player_view_range_factors[object] + factor = factors and factors[self.name] + end + -- Distance check + local dist + if factor and factor == 0 then + return false + elseif factor then + dist = self.view_range * factor + else + dist = self.view_range + end + + local p1, p2 = self.object:get_pos(), object:get_pos() + return p1 and p2 and (vector.distance(p1, p2) <= dist) +end + +function mob_class:item_drop(cooked, looting_level) + + if not mobs_drop_items then return end + + looting_level = looting_level or 0 + + if (self.child and self.type ~= "monster") then + return + end + + local obj, item, num + local pos = self.object:get_pos() + + self.drops = self.drops or {} + + for n = 1, #self.drops do + local dropdef = self.drops[n] + local chance = 1 / dropdef.chance + local looting_type = dropdef.looting + + if looting_level > 0 then + local chance_function = dropdef.looting_chance_function + if chance_function then + chance = chance_function(looting_level) + elseif looting_type == "rare" then + chance = chance + (dropdef.looting_factor or 0.01) * looting_level + end + end + + local num = 0 + local do_common_looting = (looting_level > 0 and looting_type == "common") + if math.random() < chance then + num = math.random(dropdef.min or 1, dropdef.max or 1) + elseif not dropdef.looting_ignore_chance then + do_common_looting = false + end + + if do_common_looting then + num = num + math.floor(math.random(0, looting_level) + 0.5) + end + + if num > 0 then + item = dropdef.name + + if cooked then + + local output = minetest.get_craft_result({ + method = "cooking", width = 1, items = {item}}) + + if output and output.item and not output.item:is_empty() then + item = output.item:get_name() + end + end + + for x = 1, num do + obj = minetest.add_item(pos, ItemStack(item .. " " .. 1)) + end + + if obj and obj:get_luaentity() then + + obj:set_velocity({ + x = math.random(-10, 10) / 9, + y = 6, + z = math.random(-10, 10) / 9, + }) + elseif obj then + obj:remove() -- item does not exist + end + end + end + + self.drops = {} +end + +-- collision function borrowed amended from jordan4ibanez open_ai mod +function mob_class:collision() + local pos = self.object:get_pos() + if not pos then return {0,0} end + local vel = self.object:get_velocity() + local x = 0 + local z = 0 + local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 + for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do + + local ent = object:get_luaentity() + if object:is_player() or (ent and ent.is_mob and object ~= self.object) then + + if object:is_player() and mcl_burning.is_burning(self.object) then + mcl_burning.set_on_fire(object, 4) + end + + local pos2 = object:get_pos() + local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} + local force = (width + 0.5) - vector.distance( + {x = pos.x, y = 0, z = pos.z}, + {x = pos2.x, y = 0, z = pos2.z}) + + x = x + (vec.x * force) + z = z + (vec.z * force) + end + end + + return({x,z}) +end + +-- move mob in facing direction +function mob_class:set_velocity(v) + local c_x, c_y = 0, 0 + + -- can mob be pushed, if so calculate direction + if self.pushable then + c_x, c_y = unpack(self:collision()) + end + + -- halt mob if it has been ordered to stay + if self.order == "stand" or self.order == "sit" then + self.acc=vector.new(0,0,0) + return + end + + local yaw = (self.object:get_yaw() or 0) + self.rotate + local vv = self.object:get_velocity() + if vv then + self.acc={ + x = ((math.sin(yaw) * -v) + c_x)*.27, + y = 0, + z = ((math.cos(yaw) * v) + c_y)*.27, + } + end +end + +-- calculate mob velocity +function mob_class:get_velocity() + local v = self.object:get_velocity() + if v then + return (v.x * v.x + v.z * v.z) ^ 0.5 + end + + return 0 +end + +function mob_class:update_roll() + local is_Fleckenstein = self.nametag == "Fleckenstein" + local was_Fleckenstein = false + + local rot = self.object:get_rotation() + rot.z = is_Fleckenstein and pi or 0 + self.object:set_rotation(rot) + + local cbox = table.copy(self.collisionbox) + local acbox = self.object:get_properties().collisionbox + + if math.abs(cbox[2] - acbox[2]) > 0.1 then + was_Fleckenstein = true + end + + if is_Fleckenstein ~= was_Fleckenstein then + local pos = self.object:get_pos() + pos.y = pos.y + (acbox[2] + acbox[5]) + self.object:set_pos(pos) + end + + if is_Fleckenstein then + cbox[2], cbox[5] = -cbox[5], -cbox[2] + self.object:set_properties({collisionbox = cbox}) + -- This leads to child mobs having the wrong collisionbox + -- and seeing as it seems to be nothing but an easter egg + -- i've put it inside the if. Which just makes it be upside + -- down lol. + end + +end + +local function shortest_term_of_yaw_rotation(self, rot_origin, rot_target, nums) + + if not rot_origin or not rot_target then + return + end + + rot_origin = math.deg(rot_origin) + rot_target = math.deg(rot_target) + + if rot_origin < rot_target then + if math.abs(rot_origin-rot_target)<180 then + if nums then + return rot_target-rot_origin + else + return 1 + end + else + if nums then + return -(rot_origin-(rot_target-360)) + else + return -1 + end + end + else + if math.abs(rot_origin-rot_target)<180 then + if nums then + return rot_target-rot_origin + else + return -1 + end + else + if nums then + return (rot_target-(rot_origin-360)) + else + return 1 + end + end + end + +end + + + +-- set and return valid yaw +function mob_class:set_yaw(yaw, delay, dtime) + if self.noyaw then return end + + if self.state ~= PATHFINDING then + self._turn_to = yaw + end + + --mcl_log("Yaw is: \t\t" .. tostring(math.deg(yaw))) + --mcl_log("self.object:get_yaw() is: \t" .. tostring(math.deg(self.object:get_yaw()))) + + --clamp our yaw to a 360 range + if math.deg(self.object:get_yaw()) > 360 then + self.object:set_yaw(math.rad(0)) + elseif math.deg(self.object:get_yaw()) < 0 then + self.object:set_yaw(math.rad(360)) + end + + if math.deg(yaw) > 360 then + yaw=yaw%360 + elseif math.deg(yaw) < 0 then + yaw=((360*5)-yaw)%360 + end + + --calculate the shortest way to turn to find our target + local target_shortest_path = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), yaw, false) + local target_shortest_path_nums = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), yaw, true) + + --turn in the shortest path possible toward our target. if we are attacking, don't dance. + if (math.abs(target_shortest_path) > 50 and not self._kb_turn) and (self.attack and self.attack:get_pos() or self.following and self.following:get_pos()) then + if self.following then + target_shortest_path = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.following:get_pos())), true) + target_shortest_path_nums = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.following:get_pos())), false) + else + target_shortest_path = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.attack:get_pos())), true) + target_shortest_path_nums = shortest_term_of_yaw_rotation(self, self.object:get_yaw(), minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.attack:get_pos())), false) + end + end + + local ddtime = 0.05 --set_tick_rate + + if dtime then + ddtime = dtime + end + + if math.abs(target_shortest_path_nums) > 5 then + self.object:set_yaw(self.object:get_yaw()+(target_shortest_path*(3.6*ddtime))) + if self.acc then + self.acc=vector.rotate_around_axis(self.acc,vector.new(0,1,0), target_shortest_path*(3.6*ddtime)) + end + end + + delay = delay or 0 + + yaw = self.object:get_yaw() + + if delay == 0 then + if self.shaking and dtime then + yaw = yaw + (math.random() * 2 - 1) * 5 * dtime + end + self:update_roll() + return yaw + end + + self.target_yaw = yaw + self.delay = delay + + return self.target_yaw +end + +-- global function to set mob yaw +function mcl_mobs.yaw(self, yaw, delay, dtime) + return mob_class.set_yaw(self, yaw, delay, dtime) +end + +-- are we flying in what we are suppose to? (taikedz) +function mob_class:flight_check() + + local nod = self.standing_in + local def = minetest.registered_nodes[nod] + + if not def then return false end -- nil check + + local fly_in + if type(self.fly_in) == "string" then + fly_in = { self.fly_in } + elseif type(self.fly_in) == "table" then + fly_in = self.fly_in + else + return false + end + + for _,checknode in pairs(fly_in) do + if nod == checknode or nod == "ignore" then + return true + end + end + + return false +end + +-- check if mob is dead or only hurt +function mob_class:check_for_death(cause, cmi_cause) + + if self.state == "die" then + return true + end + + -- has health actually changed? + if self.health == self.old_health and self.health > 0 then + return false + end + + local damaged = self.health < self.old_health + self.old_health = self.health + + -- still got some health? + if self.health > 0 then + + -- make sure health isn't higher than max + if self.health > self.hp_max then + self.health = self.hp_max + end + + -- play damage sound if health was reduced and make mob flash red. + if damaged then + self:add_texture_mod("^[colorize:#d42222:175") + minetest.after(1, function(self) + if self and self.object then + self:remove_texture_mod("^[colorize:#d42222:175") + end + end, self) + self:mob_sound("damage") + end + + -- backup nametag so we can show health stats + if not self.nametag2 then + self.nametag2 = self.nametag or "" + end + + if show_health + and (cmi_cause and cmi_cause.type == "punch") then + + self.htimer = 2 + self.nametag = "♥ " .. self.health .. " / " .. self.hp_max + + self:update_tag() + end + + return false + end + + self:mob_sound("death") + + local function death_handle(self) + -- dropped cooked item if mob died in fire or lava + if cause == "lava" or cause == "fire" then + self:item_drop(true, 0) + else + local wielditem = ItemStack() + if cause == "hit" then + local puncher = cmi_cause.puncher + if puncher then + wielditem = puncher:get_wielded_item() + end + end + local cooked = mcl_burning.is_burning(self.object) or mcl_enchanting.has_enchantment(wielditem, "fire_aspect") + local looting = mcl_enchanting.get_enchantment(wielditem, "looting") + self:item_drop(cooked, looting) + + if ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= math.huge) then + mcl_experience.throw_xp(self.object:get_pos(), math.random(self.xp_min, self.xp_max)) + end + end + end + + -- execute custom death function + if self.on_die then + + local pos = self.object:get_pos() + local on_die_exit = self.on_die(self, pos, cmi_cause) + if on_die_exit ~= true then + death_handle(self) + end + + if on_die_exit == true then + self.state = "die" + mcl_burning.extinguish(self.object) + self.object:remove() + return true + end + end + + local collisionbox + if self.collisionbox then + collisionbox = table.copy(self.collisionbox) + end + + self.state = "die" + self.attack = nil + self.v_start = false + self.fall_speed = DEFAULT_FALL_SPEED + self.timer = 0 + self.blinktimer = 0 + self:remove_texture_mod("^[colorize:#FF000040") + self:remove_texture_mod("^[brighten") + self.passive = true + + self.object:set_properties({ + pointable = false, + collide_with_objects = false, + }) + + self:set_velocity(0) + local acc = self.object:get_acceleration() + acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0 + self.object:set_acceleration(acc) + + local length + -- default death function and die animation (if defined) + if self.instant_death then + length = 0 + elseif self.animation + and self.animation.die_start + and self.animation.die_end then + + local frames = self.animation.die_end - self.animation.die_start + local speed = self.animation.die_speed or 15 + length = math.max(frames / speed, 0) + DEATH_DELAY + self:set_animation( "die") + else + length = 1 + DEATH_DELAY + self:set_animation( "stand", true) + end + + + -- Remove body after a few seconds and drop stuff + local kill = function(self) + if not self.object:get_luaentity() then + return + end + + death_handle(self) + local dpos = self.object:get_pos() + local cbox = self.collisionbox + local yaw = self.object:get_rotation().y + mcl_burning.extinguish(self.object) + self.object:remove() + mcl_mobs.death_effect(dpos, yaw, cbox, not self.instant_death) + end + if length <= 0 then + kill(self) + else + minetest.after(length, kill, self) + end + + return true +end + +-- Deal light damage to mob, returns true if mob died +function mob_class:deal_light_damage(pos, damage) + if not ((mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then + self.health = self.health - damage + + mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png") + + if self:check_for_death("light", {type = "light"}) then + return true + end + end +end + +-- environmental damage (water, lava, fire, light etc.) +function mob_class:do_env_damage() + -- feed/tame text timer (so mob 'full' messages dont spam chat) + if self.htimer > 0 then + self.htimer = self.htimer - 1 + end + + -- reset nametag after showing health stats + if self.htimer < 1 and self.nametag2 then + + self.nametag = self.nametag2 + self.nametag2 = nil + + self:update_tag() + end + + local pos = self.object:get_pos() + if not pos then return end + + self.time_of_day = minetest.get_timeofday() + + -- remove mob if beyond map limits + if not within_limits(pos, 0) then + mcl_burning.extinguish(self.object) + self.object:remove() + return true + end + + local sunlight = minetest.get_natural_light(pos, self.time_of_day) + + -- bright light harms mob + if self.light_damage ~= 0 and (sunlight or 0) > 12 then + if self:deal_light_damage(pos, self.light_damage) then + return true + end + end + local _, dim = mcl_worlds.y_to_layer(pos.y) + if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then + if self.armor_list and not self.armor_list.helmet or not self.armor_list or self.armor_list and self.armor_list.helmet and self.armor_list.helmet == "" then + if self.ignited_by_sunlight then + mcl_burning.set_on_fire(self.object, 10) + else + self:deal_light_damage(pos, self.sunlight_damage) + return true + end + end + end + + local y_level = self.collisionbox[2] + + if self.child then + y_level = self.collisionbox[2] * 0.5 + end + + -- what is mob standing in? + pos.y = pos.y + y_level + 0.25 -- foot level + local pos2 = {x=pos.x, y=pos.y-1, z=pos.z} + self.standing_in = node_ok(pos, "air").name + self.standing_on = node_ok(pos2, "air").name + + -- don't fall when on ignore, just stand still + if self.standing_in == "ignore" then + self.object:set_velocity({x = 0, y = 0, z = 0}) + end + + local nodef = minetest.registered_nodes[self.standing_in] + + -- rain + if self.rain_damage > 0 then + if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then + + self.health = self.health - self.rain_damage + + if self:check_for_death("rain", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + end + + pos.y = pos.y + 1 -- for particle effect position + + -- water damage + if self.water_damage > 0 + and nodef.groups.water then + + if self.water_damage ~= 0 then + + self.health = self.health - self.water_damage + + mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil) + + if self:check_for_death("water", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- lava damage + elseif self.lava_damage > 0 + and (nodef.groups.lava) then + + if self.lava_damage ~= 0 then + + self.health = self.health - self.lava_damage + + mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) + mcl_burning.set_on_fire(self.object, 10) + + if self:check_for_death("lava", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- fire damage + elseif self.fire_damage > 0 + and (nodef.groups.fire) then + + if self.fire_damage ~= 0 then + + self.health = self.health - self.fire_damage + + mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) + mcl_burning.set_on_fire(self.object, 5) + + if self:check_for_death("fire", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- damage_per_second node check + elseif nodef.damage_per_second ~= 0 and not nodef.groups.lava and not nodef.groups.fire then + + self.health = self.health - nodef.damage_per_second + + mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png") + + if self:check_for_death("dps", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- Drowning damage + if self.breath_max ~= -1 then + local drowning = false + if self.breathes_in_water then + if minetest.get_item_group(self.standing_in, "water") == 0 then + drowning = true + end + elseif nodef.drowning > 0 then + drowning = true + end + if drowning then + + self.breath = math.max(0, self.breath - 1) + + mcl_mobs.effect(pos, 2, "bubble.png", nil, nil, 1, nil) + if self.breath <= 0 then + local dmg + if nodef.drowning > 0 then + dmg = nodef.drowning + else + dmg = 4 + end + self:damage_effect(dmg) + self.health = self.health - dmg + end + if self:check_for_death("drowning", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + else + self.breath = math.min(self.breath_max, self.breath + 1) + end + end + + --- suffocation inside solid node + -- FIXME: Redundant with mcl_playerplus + if (self.suffocation == true) + and (nodef.walkable == nil or nodef.walkable == true) + and (nodef.collision_box == nil or nodef.collision_box.type == "regular") + and (nodef.node_box == nil or nodef.node_box.type == "regular") + and (nodef.groups.disable_suffocation ~= 1) + and (nodef.groups.opaque == 1) then + + -- Short grace period before starting to take suffocation damage. + -- This is different from players, who take damage instantly. + -- This has been done because mobs might briefly be inside solid nodes + -- when e.g. climbing up stairs. + -- This is a bit hacky because it assumes that do_env_damage + -- is called roughly every second only. + self.suffocation_timer = self.suffocation_timer + 1 + if self.suffocation_timer >= 3 then + -- 2 damage per second + -- TODO: Deal this damage once every 1/2 second + self.health = self.health - 2 + + if self:check_for_death("suffocation", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + else + self.suffocation_timer = 0 + end + + return self:check_for_death("", {type = "unknown"}) +end + +function mob_class:damage_mob(reason,damage) + if not self.health then return end + damage = math.floor(damage) + if damage > 0 then + self.health = self.health - damage + + mcl_mobs.effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil) + + if self:check_for_death(reason, {type = reason}) then + return true + end + end +end + +function mob_class:check_entity_cramming() + local p = self.object:get_pos() + if not p then return end + local oo = minetest.get_objects_inside_radius(p,1) + local mobs = {} + for _,o in pairs(oo) do + local l = o:get_luaentity() + if l and l.is_mob and l.health > 0 then table.insert(mobs,l) end + end + local clear = #mobs < ENTITY_CRAMMING_MAX + local ncram = {} + for _,l in pairs(mobs) do + if l then + if clear then + l.cram = nil + elseif l.cram == nil and not self.child then + table.insert(ncram,l) + elseif l.cram then + l:damage_mob("cramming",CRAMMING_DAMAGE) + end + end + end + for i,l in pairs(ncram) do + if i > ENTITY_CRAMMING_MAX then + l.cram = true + else + l.cram = nil + end + end +end + +-- falling and fall damage +-- returns true if mob died +function mob_class:falling(pos) + + if self.fly and self.state ~= "die" then + return + end + + if not self.fall_speed then self.fall_speed = DEFAULT_FALL_SPEED end + + if mcl_portals ~= nil then + if mcl_portals.nether_portal_cooloff(self.object) then + return false -- mob has teleported through Nether portal - it's 99% not falling + end + end + + -- floating in water (or falling) + local v = self.object:get_velocity() + + if v.y > 0 then + + -- apply gravity when moving up + self.object:set_acceleration({ + x = 0, + y = DEFAULT_FALL_SPEED, + z = 0 + }) + + elseif v.y <= 0 and v.y > self.fall_speed then + + -- fall downwards at set speed + self.object:set_acceleration({ + x = 0, + y = self.fall_speed, + z = 0 + }) + else + -- stop accelerating once max fall speed hit + self.object:set_acceleration({x = 0, y = 0, z = 0}) + end + + if minetest.registered_nodes[node_ok(pos).name].groups.lava then + + if self.floats_on_lava == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (math.max(1, v.y) ^ 2), + z = 0 + }) + end + end + + -- in water then float up + if minetest.registered_nodes[node_ok(pos).name].groups.water then + + if self.floats == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (math.max(1, v.y) ^ 2), + z = 0 + }) + end + else + + -- fall damage onto solid ground + if self.fall_damage == 1 + and self.object:get_velocity().y == 0 then + local n = node_ok(vector.offset(pos,0,-1,0)).name + local d = (self.old_y or 0) - self.object:get_pos().y + + if d > 5 and n ~= "air" and n ~= "ignore" then + local add = minetest.get_item_group(self.standing_on, "fall_damage_add_percent") + local damage = d - 5 + if add ~= 0 then + damage = damage + damage * (add/100) + end + self:damage_mob("fall",damage) + end + + self.old_y = self.object:get_pos().y + end + end +end + +function mob_class:check_water_flow() + -- Add water flowing for mobs from mcl_item_entity + local p, node, nn, def + p = self.object:get_pos() + node = minetest.get_node_or_nil(p) + if node then + nn = node.name + def = minetest.registered_nodes[nn] + end + + -- Move item around on flowing liquids + if def and def.liquidtype == "flowing" then + + --[[ Get flowing direction (function call from flowlib), if there's a liquid. + NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. + Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] + local vec = flowlib.quick_flow(p, node) + -- Just to make sure we don't manipulate the speed for no reason + if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then + -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" + local f = 1.39 + -- Set new item moving speed into the direciton of the liquid + local newv = vector.multiply(vec, f) + self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) + + self.physical_state = true + self._flowing = true + self.object:set_properties({ + physical = true + }) + return + end + elseif self._flowing == true then + -- Disable flowing physics if not on/in flowing liquid + self._flowing = false + return + end +end + +function mob_class:check_dying() + if ((self.state and self.state=="die") or self:check_for_death()) and not self.animation.die_end then + local rot = self.object:get_rotation() + rot.z = ((math.pi/2-rot.z)*.2)+rot.z + self.object:set_rotation(rot) + return true + end +end + +function mob_class:check_suspend() + if not self:player_in_active_range() then + local pos = self.object:get_pos() + local node_under = node_ok(vector.offset(pos,0,-1,0)).name + local acc = self.object:get_acceleration() + self:set_animation( "stand", true) + if acc.y > 0 or node_under ~= "air" then + self.object:set_acceleration(vector.new(0,0,0)) + self.object:set_velocity(vector.new(0,0,0)) + end + if acc.y == 0 and node_under == "air" then + self:falling(pos) + end + return true + end +end diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 7a67bd4c8..a8250c19e 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -1,4 +1,7 @@ --lua locals +local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs +local mob_class = mcl_mobs.mob_class + local get_node = minetest.get_node local get_item_group = minetest.get_item_group local get_node_light = minetest.get_node_light @@ -25,15 +28,19 @@ 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 +local remove_far = true 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? @@ -237,6 +244,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 @@ -418,11 +436,38 @@ local function get_water_spawn(p) end end -local function spawn_check(pos,spawn_def) +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("warning","[mcl_mobs] No room for mob "..self.name.." at "..minetest.pos_to_string(vector.round(pos))) + 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 @@ -435,29 +480,33 @@ local function spawn_check(pos,spawn_def) 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 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 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) - and ( not spawn_protected or not minetest.is_protected(s, "") ) + and ( not spawn_protected or not minetest.is_protected(pos, "") ) and not is_bedrock then --only need to poll for node light if everything else worked local gotten_light = get_node_light(pos) @@ -473,6 +522,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 @@ -488,7 +542,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 @@ -501,15 +555,77 @@ end mcl_mobs.spawn_group = spawn_group +local S = minetest.get_translator("mcl_mobs") + minetest.register_chatcommand("spawn_mob",{ privs = { debug = true }, + description=S("spawn_mob is a chatcommand that allows you to type in the name of a mob without 'typing mobs_mc:' all the time like so; 'spawn_mob spider'. however, there is more you can do with this special command, currently you can edit any number, boolian, and string variable you choose with this format: spawn_mob 'any_mob:var:'. any_mob being your mob of choice, mobs_variable being the variable, and variable value being the value of the chosen variable. and example of this format: \n spawn_mob skeleton:var:\n this would spawn a skeleton that wouldn't attack you. REMEMBER-THIS> when changing a number value always prefix it with 'NUM', example: \n spawn_mob skeleton:var:\n this setting the skelly's jump height to 10. if you want to make multiple changes to a mob, you can, example: \n spawn_mob skeleton:var::var::var::var:\n etc."), func = function(n,param) local pos = minetest.get_player_by_name(n):get_pos() - if mcl_mobs.spawn(pos,param) then - return true, param.." spawned at "..minetest.pos_to_string(pos), - minetest.log("action", n.." spawned "..param.." at "..minetest.pos_to_string(pos)) + + local modifiers = {} + for capture in string.gmatch(param, "%:(.-)%:") do + table.insert(modifiers, ":"..capture) end - return false, "Couldn't spawn "..param + + local mod1 = string.find(param, ":") + + + + local mobname = param + if mod1 then + mobname = string.sub(param, 1, mod1-1) + end + + local mob = mcl_mobs.spawn(pos,mobname) + + for c=1, #modifiers do + modifs = modifiers[c] + + local mod1 = string.find(modifs, ":") + local mod_start = string.find(modifs, "<") + local mod_vals = string.find(modifs, "=") + local mod_end = string.find(modifs, ">") + local mod_end = string.find(modifs, ">") + if mob then + local mob_entity = mob:get_luaentity() + if string.sub(modifs, mod1+1, mod1+3) == "var" then + if mod1 and mod_start and mod_vals and mod_end then + local variable = string.sub(modifs, mod_start+1, mod_vals-1) + local value = string.sub(modifs, mod_vals+1, mod_end-1) + + number_tag = string.find(value, "NUM") + if number_tag then + value = tonumber(string.sub(value, 4, -1)) + end + + if value == "true" then + value = true + elseif value == "false" then + value = false + end + + if not mob_entity[variable] then + minetest.log("warning", n.." mob variable "..variable.." previously unset") + end + + mob_entity[variable] = value + + else + minetest.log("warning", n.." couldn't modify "..mobname.." at "..minetest.pos_to_string(pos).. ", missing paramaters") + end + else + minetest.log("warning", n.." couldn't modify "..mobname.." at "..minetest.pos_to_string(pos).. ", missing modification type") + end + end + end + + + if mob then + return true, mobname.." spawned at "..minetest.pos_to_string(pos), + minetest.log("action", n.." spawned "..mobname.." at "..minetest.pos_to_string(pos)) + end + return false, "Couldn't spawn "..mobname end }) @@ -547,38 +663,38 @@ if mobs_spawn then step_chance = step_chance + mob_chance end local mob_def = mob_library_worker_table[mob_index] - 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 + --minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance) + 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_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 + 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 + 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 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 - - - if object then - return mob_def.on_spawn and mob_def.on_spawn(object, spawning_position) - end + end end current_summary_chance = current_summary_chance - mob_chance table_remove(mob_library_worker_table, mob_index) @@ -593,23 +709,52 @@ 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_cap() + 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.") + 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 if dimension ~= "void" and dimension ~= "default" then local y_min, y_max = decypher_limits(pos.y) - for i = 1, math_random(1, 4) do - spawn_a_mob(pos, dimension, y_min, y_max) - end + spawn_a_mob(pos, dimension, y_min, y_max) end end end) end +function mob_class:check_despawn(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 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 true + elseif self.lifetimer <= 10 then + if math.random(10) < 4 then + self.despawn_immediately = true + else + self.lifetimer = 20 + end + end + end +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()) diff --git a/mods/ENTITIES/mobs_mc/README.md b/mods/ENTITIES/mobs_mc/README.md index 4ee435d72..881f56619 100644 --- a/mods/ENTITIES/mobs_mc/README.md +++ b/mods/ENTITIES/mobs_mc/README.md @@ -58,6 +58,7 @@ This mod adds mobs which closely resemble the mobs from the game Minecraft, vers ### Peaceful mobs +* Axolotl * Chicken * Cow * Pig diff --git a/mods/ENTITIES/mobs_mc/axolotl.lua b/mods/ENTITIES/mobs_mc/axolotl.lua new file mode 100644 index 000000000..124f6bd3a --- /dev/null +++ b/mods/ENTITIES/mobs_mc/axolotl.lua @@ -0,0 +1,181 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local axolotl = { + type = "animal", + spawn_class = "water", + can_despawn = true, + passive = false, + hp_min = 14, + hp_max = 14, + xp_min = 1, + xp_max = 7, + + head_swivel = "head.control", + bone_eye_height = -1, + head_eye_height = -0.5, + horrizonatal_head_height = 0, + curiosity = 10, + head_yaw="z", + + armor = 100, + rotate = 180, + spawn_in_group_min = 1, + spawn_in_group = 4, + tilt_swim = true, + collisionbox = {-0.5, 0.0, -0.5, 0.5, 0.8, 0.5}, + visual = "mesh", + mesh = "mobs_mc_axolotl.b3d", + textures = { + {"mobs_mc_axolotl_brown.png"}, + {"mobs_mc_axolotl_yellow.png"}, + {"mobs_mc_axolotl_green.png"}, + {"mobs_mc_axolotl_pink.png"}, + {"mobs_mc_axolotl_black.png"}, + {"mobs_mc_axolotl_purple.png"}, + {"mobs_mc_axolotl_white.png"} + }, + sounds = { + random = "mobs_mc_axolotl", + damage = "mobs_mc_axolotl_hurt", + distance = 16, + }, + animation = {-- Stand: 1-20; Walk: 20-60; Swim: 61-81 + stand_start = 61, stand_end = 81, stand_speed = 15, + walk_start = 61, walk_end = 81, walk_speed = 15, + run_start = 61, run_end = 81, run_speed = 20, + }, + + follow = { + "mcl_fishing:clownfish_raw" + }, + + view_range = 16, + fear_height = 4, + + on_rightclick = function(self, clicker) + local bn = clicker:get_wielded_item():get_name() + if bn == "mcl_buckets:bucket_water" or bn == "mcl_buckets:bucket_river_water" then + if clicker:set_wielded_item("mcl_buckets:bucket_axolotl") then + local it = clicker:get_wielded_item() + local m = it:get_meta() + m:set_string("properties",minetest.serialize(self.object:get_properties())) + clicker:set_wielded_item(it) + self.object:remove() + end + awards.unlock(clicker:get_player_name(), "mcl:cutestPredator") + return + end + if self:feed_tame(clicker, 1, true, false) then return end + end, + makes_footstep_sound = false, + fly = true, + fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" }, + breathes_in_water = true, + jump = true, + damage = 2, + reach = 2, + attack_type = "dogfight", + attack_animals = true, + specific_attack = { + "extra_mobs_cod", + "mobs_mc:sheep", + "extra_mobs_glow_squid", + "extra_mobs_salmon", + "extra_mobs_tropical_fish", + "mobs_mc_squid" + }, + runaway = true, +} + +mcl_mobs.register_mob("mobs_mc:axolotl", axolotl) + +local water = 0 + +mcl_mobs:spawn_specific( +"mobs_mc:axolotl", +"overworld", +"water", +{ +"Swampland", +"MushroomIsland", +"RoofedForest", +"FlowerForest_beach", +"Forest_beach", +"StoneBeach", +"Taiga_beach", +"Savanna_beach", +"Plains_beach", +"ExtremeHills_beach", +"Swampland_shore", +"MushroomIslandShore", +"JungleM_shore", +"Jungle_shore", +"RoofedForest_ocean", +"JungleEdgeM_ocean", +"BirchForestM_ocean", +"BirchForest_ocean", +"IcePlains_deep_ocean", +"Jungle_deep_ocean", +"Savanna_ocean", +"MesaPlateauF_ocean", +"SunflowerPlains_ocean", +"Swampland_ocean", +"ExtremeHillsM_ocean", +"Mesa_ocean", +"StoneBeach_ocean", +"Plains_ocean", +"MesaPlateauFM_ocean", +"MushroomIsland_ocean", +"MegaTaiga_ocean", +"StoneBeach_deep_ocean", +"SavannaM_ocean", +"ExtremeHills_ocean", +"Forest_ocean", +"JungleEdge_ocean", +"MesaBryce_ocean", +"MegaSpruceTaiga_ocean", +"ExtremeHills+_ocean", +"Jungle_ocean", +"FlowerForest_ocean", +"Desert_ocean", +"Taiga_ocean", +"JungleM_ocean", +"FlowerForest_underground", +"JungleEdge_underground", +"StoneBeach_underground", +"MesaBryce_underground", +"Mesa_underground", +"RoofedForest_underground", +"Jungle_underground", +"Swampland_underground", +"MushroomIsland_underground", +"BirchForest_underground", +"Plains_underground", +"MesaPlateauF_underground", +"ExtremeHills_underground", +"MegaSpruceTaiga_underground", +"BirchForestM_underground", +"SavannaM_underground", +"MesaPlateauFM_underground", +"Desert_underground", +"Savanna_underground", +"Forest_underground", +"SunflowerPlains_underground", +"MegaTaiga_underground", +"Taiga_underground", +"ExtremeHills+_underground", +"JungleM_underground", +"ExtremeHillsM_underground", +"JungleEdgeM_underground", +"LushCaves", +}, +0, +minetest.LIGHT_MAX+1, +30, +4000, +3, +water-16, +water+1) + +-- spawn eggs +mcl_mobs.register_egg("mobs_mc:axolotl", S("Axolotl"), "#e890bf", "#b83D7e", 0) diff --git a/mods/ENTITIES/mobs_mc/bat.lua b/mods/ENTITIES/mobs_mc/bat.lua index 1a40203c0..b5532e2ee 100644 --- a/mods/ENTITIES/mobs_mc/bat.lua +++ b/mods/ENTITIES/mobs_mc/bat.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:bat", { +mcl_mobs.register_mob("mobs_mc:bat", { description = S("Bat"), type = "animal", spawn_class = "ambient", @@ -144,4 +144,4 @@ mobs_mc.water_level-1) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:bat", S("Bat"), "mobs_mc_spawn_icon_bat.png", 0) +mcl_mobs.register_egg("mobs_mc:bat", S("Bat"), "#4c3e30", "#0f0f0f", 0) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index c06e0bea6..18b7ea676 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -12,7 +12,7 @@ local mod_target = minetest.get_modpath("mcl_target") --################### -mcl_mobs:register_mob("mobs_mc:blaze", { +mcl_mobs.register_mob("mobs_mc:blaze", { description = S("Blaze"), type = "monster", spawn_class = "hostile", @@ -26,6 +26,12 @@ mcl_mobs:register_mob("mobs_mc:blaze", { rotate = -180, visual = "mesh", mesh = "mobs_mc_blaze.b3d", + head_swivel = "head.control", + bone_eye_height = 4, + head_eye_height = 3.5, + curiosity = 10, + head_yaw_offset = 180, + head_pitch_multiplier=-1, textures = { {"mobs_mc_blaze.png"}, }, @@ -147,7 +153,7 @@ mcl_vars.mg_nether_min, mcl_vars.mg_nether_max) -- Blaze fireball -mcl_mobs:register_arrow("mobs_mc:blaze_fireball", { +mcl_mobs.register_arrow("mobs_mc:blaze_fireball", { visual = "sprite", visual_size = {x = 0.3, y = 0.3}, textures = {"mcl_fire_fire_charge.png"}, @@ -202,4 +208,4 @@ mcl_mobs:register_arrow("mobs_mc:blaze_fireball", { }) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:blaze", S("Blaze"), "mobs_mc_spawn_icon_blaze.png", 0) +mcl_mobs.register_egg("mobs_mc:blaze", S("Blaze"), "#f6b201", "#fff87e", 0) diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index 5dc417582..399294390 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -8,7 +8,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:chicken", { +mcl_mobs.register_mob("mobs_mc:chicken", { description = S("Chicken"), type = "animal", spawn_class = "passive", @@ -20,12 +20,18 @@ mcl_mobs:register_mob("mobs_mc:chicken", { collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2}, runaway = true, floats = 1, + head_swivel = "head.control", + bone_eye_height = 4, + head_eye_height = 1.5, + horrizonatal_head_height = -.3, + curiosity = 10, + head_yaw="z", + visual_size = {x=1,y=1}, visual = "mesh", mesh = "mobs_mc_chicken.b3d", textures = { {"mobs_mc_chicken.png"}, }, - visual_size = {x=2.2, y=2.2}, makes_footstep_sound = true, walk_velocity = 1, @@ -58,12 +64,15 @@ mcl_mobs:register_mob("mobs_mc:chicken", { distance = 16, }, animation = { - stand_speed = 25, walk_speed = 25, run_speed = 50, - stand_start = 0, stand_end = 0, - walk_start = 0, walk_end = 40, - run_start = 0, run_end = 40, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 20, walk_speed = 25, + run_start = 0, run_end = 20, run_speed = 50, + }, + child_animations = { + stand_start = 31, stand_end = 31, + walk_start = 31, walk_end = 51, walk_speed = 37, + run_start = 31, run_end = 51, run_speed = 75, }, - follow = { "mcl_farming:wheat_seeds", "mcl_farming:melon_seeds", @@ -74,7 +83,7 @@ mcl_mobs:register_mob("mobs_mc:chicken", { fear_height = 4, on_rightclick = function(self, clicker) - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:protect(self, clicker) then return end if mcl_mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end end, @@ -154,4 +163,4 @@ mobs_mc.water_level, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0) +mcl_mobs.register_egg("mobs_mc:chicken", S("Chicken"), "#a1a1a1", "#ff0000", 0) diff --git a/mods/ENTITIES/mobs_mc/cod.lua b/mods/ENTITIES/mobs_mc/cod.lua index 98020cca8..24f3131b3 100644 --- a/mods/ENTITIES/mobs_mc/cod.lua +++ b/mods/ENTITIES/mobs_mc/cod.lua @@ -102,7 +102,8 @@ local cod = { end end, on_rightclick = function(self, clicker) - if clicker:get_wielded_item():get_name() == "mcl_buckets:bucket_water" then + local bn = clicker:get_wielded_item():get_name() + if bn == "mcl_buckets:bucket_water" or bn == "mcl_buckets:bucket_river_water" then self.object:remove() clicker:set_wielded_item("mcl_buckets:bucket_cod") awards.unlock(clicker:get_player_name(), "mcl:tacticalFishing") @@ -110,7 +111,7 @@ local cod = { end } -mcl_mobs:register_mob("mobs_mc:cod", cod) +mcl_mobs.register_mob("mobs_mc:cod", cod) --spawning TODO: in schools @@ -271,4 +272,4 @@ water-16, water+1) --spawn egg -mcl_mobs:register_egg("mobs_mc:cod", S("Cod"), "extra_mobs_spawn_icon_cod.png", 0) +mcl_mobs.register_egg("mobs_mc:cod", S("Cod"), "#c1a76a", "#e5c48b", 0) diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index fe04650cd..5ac5912a4 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -6,18 +6,26 @@ local cow_def = { description = S("Cow"), type = "animal", spawn_class = "passive", + passive = true, hp_min = 10, hp_max = 10, 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 = { { "mobs_mc_cow.png", "blank.png", }, }, - visual_size = {x=2.8, y=2.8}, + head_swivel = "head.control", + bone_eye_height = 10, + head_eye_height = 1.1, + horrizonatal_head_height=-1.8, + curiosity = 2, + head_yaw="z", makes_footstep_sound = true, walk_velocity = 1, drops = { @@ -41,14 +49,17 @@ local cow_def = { distance = 16, }, animation = { - stand_speed = 25, walk_speed = 40, - run_speed = 60, stand_start = 0, - stand_end = 0, walk_start = 0, - walk_end = 40, run_start = 0, - run_end = 40, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 30, + run_start = 0, run_end = 40, run_speed = 40, + }, + child_animations = { + stand_start = 41, stand_end = 41, + walk_start = 41, walk_end = 81, walk_speed = 45, + run_start = 41, run_end = 81, run_speed = 60, }, on_rightclick = function(self, clicker) - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:protect(self, clicker) then return end if self.child then @@ -77,17 +88,16 @@ local cow_def = { fear_height = 4, } -mcl_mobs:register_mob("mobs_mc:cow", cow_def) +mcl_mobs.register_mob("mobs_mc:cow", cow_def) -- Mooshroom local mooshroom_def = table.copy(cow_def) mooshroom_def.description = S("Mooshroom") -mooshroom_def.mesh = "mobs_mc_cow.b3d" mooshroom_def.spawn_in_group_min = 4 mooshroom_def.spawn_in_group = 8 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) - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:protect(self, clicker) then return end if self.child then @@ -143,7 +153,17 @@ mooshroom_def.on_rightclick = function(self, clicker) end mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end -mcl_mobs:register_mob("mobs_mc:mooshroom", mooshroom_def) + +mooshroom_def.on_lightning_strike = function(self, pos, pos2, objects) + if self.base_texture[1] == "mobs_mc_mooshroom_brown.png" then + self.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" } + else + self.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } + end + self.object:set_properties({ textures = self.base_texture }) + return true +end +mcl_mobs.register_mob("mobs_mc:mooshroom", mooshroom_def) -- Spawning @@ -211,5 +231,5 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn egg -mcl_mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0) -mcl_mobs:register_egg("mobs_mc:mooshroom", S("Mooshroom"), "mobs_mc_spawn_icon_mooshroom.png", 0) +mcl_mobs.register_egg("mobs_mc:cow", S("Cow"), "#443626", "#a1a1a1", 0) +mcl_mobs.register_egg("mobs_mc:mooshroom", S("Mooshroom"), "#a00f10", "#b7b7b7", 0) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 671a79977..6bbb37d5a 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -9,7 +9,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:creeper", { +mcl_mobs.register_mob("mobs_mc:creeper", { type = "monster", spawn_class = "hostile", spawn_in_group = 1, @@ -21,6 +21,9 @@ mcl_mobs:register_mob("mobs_mc:creeper", { pathfinding = 1, visual = "mesh", mesh = "mobs_mc_creeper.b3d", + head_swivel = "Head_Control", + bone_eye_height = 2.35, + curiosity = 2, textures = { {"mobs_mc_creeper.png", "mobs_mc_empty.png"}, @@ -78,7 +81,7 @@ mcl_mobs:register_mob("mobs_mc:creeper", { if self._forced_explosion_countdown_timer ~= nil then self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then - mcl_mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) + self:boom(mcl_util.get_object_center(self.object), self.explosion_strength) end end end, @@ -130,7 +133,7 @@ mcl_mobs:register_mob("mobs_mc:creeper", { view_range = 16, }) -mcl_mobs:register_mob("mobs_mc:creeper_charged", { +mcl_mobs.register_mob("mobs_mc:creeper_charged", { description = S("Creeper"), type = "monster", spawn_class = "hostile", @@ -200,7 +203,7 @@ mcl_mobs:register_mob("mobs_mc:creeper_charged", { if self._forced_explosion_countdown_timer ~= nil then self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then - mcl_mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) + self:boom(mcl_util.get_object_center(self.object), self.explosion_strength) end end end, @@ -216,6 +219,10 @@ mcl_mobs:register_mob("mobs_mc:creeper_charged", { end end end, + on_lightning_strike = function(self, pos, pos2, objects) + mcl_util.replace_mob(self.object, "mobs_mc:creeper_charged") + return true + end, maxdrops = 2, drops = { {name = "mcl_mobitems:gunpowder", @@ -404,4 +411,4 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0) +mcl_mobs.register_egg("mobs_mc:creeper", S("Creeper"), "#0da70a", "#000000", 0) diff --git a/mods/ENTITIES/mobs_mc/depends.txt b/mods/ENTITIES/mobs_mc/depends.txt deleted file mode 100644 index 674eb8094..000000000 --- a/mods/ENTITIES/mobs_mc/depends.txt +++ /dev/null @@ -1 +0,0 @@ -mcl_mobs \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/dolphin.lua b/mods/ENTITIES/mobs_mc/dolphin.lua index 2afe04c43..0e5c8e7ee 100644 --- a/mods/ENTITIES/mobs_mc/dolphin.lua +++ b/mods/ENTITIES/mobs_mc/dolphin.lua @@ -92,7 +92,7 @@ local dolphin = { end, } -mcl_mobs:register_mob("mobs_mc:dolphin", dolphin) +mcl_mobs.register_mob("mobs_mc:dolphin", dolphin) --spawning TO DO: in schools @@ -250,4 +250,4 @@ water-16, water+1) --spawn egg -mcl_mobs:register_egg("mobs_mc:dolphin", S("Dolphin"), "extra_mobs_spawn_icon_dolphin.png", 0) +mcl_mobs.register_egg("mobs_mc:dolphin", S("Dolphin"), "#223b4d", "#f9f9f9", 0) diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 015fbf25d..ef4c8f811 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -48,7 +48,7 @@ local function check_pos(self) end end -mcl_mobs:register_mob("mobs_mc:enderdragon", { +mcl_mobs.register_mob("mobs_mc:enderdragon", { description = S("Ender Dragon"), type = "monster", spawn_class = "hostile", @@ -142,7 +142,7 @@ mcl_mobs:register_mob("mobs_mc:enderdragon", { local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -- dragon fireball (projectile) -mcl_mobs:register_arrow("mobs_mc:dragon_fireball", { +mcl_mobs.register_arrow("mobs_mc:dragon_fireball", { visual = "sprite", visual_size = {x = 1.25, y = 1.25}, textures = {"mobs_mc_dragon_fireball.png"}, @@ -166,10 +166,11 @@ mcl_mobs:register_arrow("mobs_mc:dragon_fireball", { -- node hit, explode hit_node = function(self, pos, node) - mcl_mobs:boom(self, pos, 2) + mcl_mobs.mob_class.boom(self,pos, 2) end }) -mcl_mobs:register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "mobs_mc_spawn_icon_dragon.png", 0, true) +mcl_mobs.register_egg("mobs_mc:enderdragon", S("Ender Dragon"), "#252525", "#b313c9", 0, true) + mcl_wip.register_wip_item("mobs_mc:enderdragon") diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index 3d9f94d49..2688977fe 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -24,7 +24,25 @@ -- added rain damage. -- fixed the grass_with_dirt issue. +minetest.register_entity("mobs_mc:ender_eyes", { + visual = "mesh", + mesh = "mobs_mc_spider.b3d", + visual_size = {x=1.01/3, y=1.01/3}, + textures = { + "mobs_mc_enderman_eyes.png", + }, + on_step = function(self) + if self and self.object then + if not self.object:get_attach() then + self.object:remove() + end + end + end, + glow = 50, +}) + local S = minetest.get_translator("mobs_mc") +local enable_damage = minetest.settings:get_bool("enable_damage") local telesound = function(pos, is_source) local snd @@ -219,9 +237,25 @@ local select_enderman_animation = function(animation_type) end local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -local spawners = {} +local psdefs = {{ + amount = 5, + minpos = vector.new(-0.6,0,-0.6), + maxpos = vector.new(0.6,3,0.6), + minvel = vector.new(-0.25,-0.25,-0.25), + maxvel = vector.new(0.25,0.25,0.25), + minacc = vector.new(-0.5,-0.5,-0.5), + maxacc = vector.new(0.5,0.5,0.5), + minexptime = 0.2, + maxexptime = 3, + minsize = 0.2, + maxsize = 1.2, + collisiondetection = true, + vertical = false, + time = 0, + texture = "mcl_portals_particle"..math.random(1, 5)..".png", +}} -mcl_mobs:register_mob("mobs_mc:enderman", { +mcl_mobs.register_mob("mobs_mc:enderman", { description = S("Enderman"), type = "monster", spawn_class = "passive", @@ -237,6 +271,19 @@ mcl_mobs:register_mob("mobs_mc:enderman", { textures = create_enderman_textures(), visual_size = {x=3, y=3}, makes_footstep_sound = true, + on_spawn = function(self) + local spider_eyes=false + for n = 1, #self.object:get_children() do + local obj = self.object:get_children()[n] + if obj:get_luaentity() and self.object:get_luaentity().name == "mobs_mc:ender_eyes" then + spider_eyes = true + end + end + if not spider_eyes then + minetest.add_entity(self.object:get_pos(), "mobs_mc:ender_eyes"):set_attach(self.object, "head.top", vector.new(0,2.54,-1.99), vector.new(90,0,180)) + minetest.add_entity(self.object:get_pos(), "mobs_mc:ender_eyes"):set_attach(self.object, "head.top", vector.new(1,2.54,-1.99), vector.new(90,0,180)) + end + end, sounds = { -- TODO: Custom war cry sound war_cry = "mobs_sandmonster", @@ -249,6 +296,7 @@ mcl_mobs:register_mob("mobs_mc:enderman", { run_velocity = 3.4, damage = 7, reach = 2, + particlespawners = psdefs, drops = { {name = "mcl_throwing:ender_pearl", chance = 1, @@ -262,44 +310,8 @@ mcl_mobs:register_mob("mobs_mc:enderman", { return #minetest.find_nodes_in_area(vector.offset(pos,0,1,0),vector.offset(pos,0,3,0),{"air"}) > 2 end, do_custom = function(self, dtime) - -- PARTICLE BEHAVIOUR HERE. - local enderpos = self.object:get_pos() - if self._particle_timer and self._particle_timer >= 1 then - for _,player in pairs(minetest.get_connected_players()) do - if not spawners[player] then spawners[player] = {} end - local dst = vector.distance(player:get_pos(),enderpos) - if dst < 128 and not spawners[player][self.object] then - self._particle_timer = 0 - spawners[player][self.object] = minetest.add_particlespawner({ - amount = 5, - minpos = vector.new(-0.6,0,-0.6), - maxpos = vector.new(0.6,3,0.6), - minvel = vector.new(-0.25,-0.25,-0.25), - maxvel = vector.new(0.25,0.25,0.25), - minacc = vector.new(-0.5,-0.5,-0.5), - maxacc = vector.new(0.5,0.5,0.5), - minexptime = 0.2, - maxexptime = 3, - minsize = 0.2, - maxsize = 1.2, - collisiondetection = true, - vertical = false, - time = 0, - texture = "mcl_portals_particle"..math.random(1, 5)..".png", - attached = self.object, - playername = player:get_player_name(), - }) - elseif dst > 128 and spawners[player][self.object] then - minetest.delete_particlespawner(spawners[player][self.object]) - spawners[player][self.object] = nil - end - end - elseif not self._particle_timer then - self._particle_timer = 0 - end - self._particle_timer = self._particle_timer + dtime -- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE. - enderpos = self.object:get_pos() + local enderpos = self.object:get_pos() local dim = mcl_worlds.pos_to_dimension(enderpos) if dim == "overworld" then if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then @@ -382,7 +394,7 @@ mcl_mobs:register_mob("mobs_mc:enderman", { -- self:teleport(nil) -- self.state = "" --else - if self.attack ~= nil and not minetest.settings:get_bool("creative_mode") then + if self.attack ~= nil and enable_damage then self.state = 'attack' end --end @@ -485,7 +497,7 @@ mcl_mobs:register_mob("mobs_mc:enderman", { self.base_texture = create_enderman_textures(block_type, self._taken_node) self.object:set_properties({ textures = self.base_texture }) self.animation = select_enderman_animation("block") - mcl_mobs:set_animation(self, self.animation.current) + self:set_animation(self.animation.current) if def.sounds and def.sounds.dug then minetest.sound_play(def.sounds.dug, {pos = take_pos, max_hear_distance = 16}, true) end @@ -508,7 +520,7 @@ mcl_mobs:register_mob("mobs_mc:enderman", { local def = minetest.registered_nodes[self._taken_node] -- Update animation accordingly (removes visible block) self.animation = select_enderman_animation("normal") - mcl_mobs:set_animation(self, self.animation.current) + self:set_animation(self.animation.current) if def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {pos = place_pos, max_hear_distance = 16}, true) end @@ -617,15 +629,6 @@ mcl_mobs:register_mob("mobs_mc:enderman", { attack_type = "dogfight", }) -minetest.register_on_leaveplayer(function(player) - if not spawners[player] then return end - for _,s in pairs(spawners[player]) do - minetest.delete_particlespawner(s) - end - spawners[player] = nil -end) - - -- End spawn mcl_mobs:spawn_specific( "mobs_mc:enderman", @@ -829,4 +832,4 @@ mcl_vars.mg_nether_min, mcl_vars.mg_nether_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0) +mcl_mobs.register_egg("mobs_mc:enderman", S("Enderman"), "#252525", "#151515", 0) diff --git a/mods/ENTITIES/mobs_mc/endermite.lua b/mods/ENTITIES/mobs_mc/endermite.lua index 53200da70..612054be8 100644 --- a/mods/ENTITIES/mobs_mc/endermite.lua +++ b/mods/ENTITIES/mobs_mc/endermite.lua @@ -4,7 +4,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:endermite", { +mcl_mobs.register_mob("mobs_mc:endermite", { description = S("Endermite"), type = "monster", spawn_class = "hostile", @@ -38,4 +38,4 @@ mcl_mobs:register_mob("mobs_mc:endermite", { reach = 1, }) -mcl_mobs:register_egg("mobs_mc:endermite", S("Endermite"), "mobs_mc_spawn_icon_endermite.png", 0) +mcl_mobs.register_egg("mobs_mc:endermite", S("Endermite"), "#161616", "#6d6d6d", 0) diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 35e9bcd01..0f7e73344 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -10,7 +10,7 @@ local S = minetest.get_translator("mobs_mc") --################### -mcl_mobs:register_mob("mobs_mc:ghast", { +mcl_mobs.register_mob("mobs_mc:ghast", { description = S("Ghast"), type = "monster", spawn_class = "hostile", @@ -103,7 +103,7 @@ mcl_vars.mg_nether_min, mcl_vars.mg_nether_max) -- fireball (projectile) -mcl_mobs:register_arrow("mobs_mc:fireball", { +mcl_mobs.register_arrow("mobs_mc:fireball", { visual = "sprite", visual_size = {x = 1, y = 1}, textures = {"mcl_fire_fire_charge.png"}, @@ -118,9 +118,9 @@ mcl_mobs:register_arrow("mobs_mc:fireball", { }, nil) local p = self.object:get_pos() if p then - mcl_mobs:boom(self, p, 1, true) + mcl_mobs.mob_class.boom(self,p, 1, true) else - mcl_mobs:boom(self, player:get_pos(), 1, true) + mcl_mobs.mob_class.boom(self,player:get_pos(), 1, true) end end, @@ -129,11 +129,11 @@ mcl_mobs:register_arrow("mobs_mc:fireball", { full_punch_interval = 1.0, damage_groups = {fleshy = 6}, }, nil) - mcl_mobs:boom(self, self.object:get_pos(), 1, true) + mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1, true) end, hit_node = function(self, pos, node) - mcl_mobs:boom(self, pos, 1, true) + mcl_mobs.mob_class.boom(self,pos, 1, true) end }) @@ -141,4 +141,4 @@ mcl_mobs:register_arrow("mobs_mc:fireball", { -- spawn eggs -mcl_mobs:register_egg("mobs_mc:ghast", S("Ghast"), "mobs_mc_spawn_icon_ghast.png", 0) +mcl_mobs.register_egg("mobs_mc:ghast", S("Ghast"), "#f9f9f9", "#bcbcbc", 0) diff --git a/mods/ENTITIES/mobs_mc/glow_squid.lua b/mods/ENTITIES/mobs_mc/glow_squid.lua new file mode 100644 index 000000000..9f3a45e34 --- /dev/null +++ b/mods/ENTITIES/mobs_mc/glow_squid.lua @@ -0,0 +1,246 @@ +--MCmobs v0.4 +--maikerumine +--made for MC like Survival game +--License for code WTFPL and otherwise stated in readmes + +local S = minetest.get_translator("mobs_mc") + +local base_psdef = { + amount = 8, + time=0, + minpos = vector.new(-1,-1,-1), + maxpos = vector.new(1,1,1), + minvel = vector.new(-0.25,-0.25,-0.25), + maxvel = vector.new(0.25,0.25,0.25), + minacc = vector.new(-0.5,-0.5,-0.5), + maxacc = vector.new(0.5,0.5,0.5), + minexptime = 1, + maxexptime = 2, + minsize = 0.8, + maxsize= 1.5, + glow = 5, + collisiondetection = true, + collision_removal = true, +} +local psdefs = {} +for i=1,4 do + local p = table.copy(base_psdef) + p.texture = "extra_mobs_glow_squid_glint"..i..".png" + table.insert(psdefs,p) +end + +mcl_mobs.register_mob("mobs_mc:glow_squid", { + type = "animal", + spawn_class = "water", + can_despawn = true, + passive = true, + hp_min = 10, + hp_max = 10, + xp_min = 1, + xp_max = 3, + armor = 100, + rotate = 0, + -- tilt_swim breaks the animations. + --tilt_swim = true, + -- FIXME: If the qlow squid is near the floor, it turns black + collisionbox = { -0.4, 0.0, -0.4, 0.4, 0.9, 0.4 }, + visual = "mesh", + mesh = "extra_mobs_glow_squid.b3d", + textures = { + { "extra_mobs_glow_squid.png" } + }, + sounds = { + damage = { name = "mobs_mc_squid_hurt", gain = 0.3 }, + death = { name = "mobs_mc_squid_death", gain = 0.4 }, + flop = "mobs_mc_squid_flop", + distance = 16, + }, + animation = { + stand_start = 1, + stand_end = 60, + walk_start = 1, + walk_end = 60, + run_start = 1, + run_end = 60, + }, + drops = { + { name = "mcl_mobitems:glow_ink_sac", + chance = 1, + min = 1, + max = 3, + looting = "common", }, + }, + visual_size = { x = 3, y = 3 }, + makes_footstep_sound = false, + swim = true, + breathes_in_water = true, + jump = false, + view_range = 16, + runaway = true, + fear_height = 4, + fly = true, + fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" }, + -- don't add "mcl_core:water_flowing", or it won't move vertically. + + glow = minetest.LIGHT_MAX, + particlespawners = psdefs, +}) + +-- spawning +local water = mobs_mc.water_level - 1 +-- local water = mobs_mc.spawn_height.water + 1 +mcl_mobs:spawn_specific( + "mobs_mc:glow_squid", + "overworld", + "water", + { + "Mesa", + "FlowerForest", + "Swampland", + "Taiga", + "ExtremeHills", + "Jungle", + "Savanna", + "BirchForest", + "MegaSpruceTaiga", + "MegaTaiga", + "ExtremeHills+", + "Forest", + "Plains", + "Desert", + "ColdTaiga", + "MushroomIsland", + "IcePlainsSpikes", + "SunflowerPlains", + "IcePlains", + "RoofedForest", + "ExtremeHills+_snowtop", + "MesaPlateauFM_grasstop", + "JungleEdgeM", + "ExtremeHillsM", + "JungleM", + "BirchForestM", + "MesaPlateauF", + "MesaPlateauFM", + "MesaPlateauF_grasstop", + "MesaBryce", + "JungleEdge", + "SavannaM", + "FlowerForest_beach", + "Forest_beach", + "StoneBeach", + "ColdTaiga_beach_water", + "Taiga_beach", + "Savanna_beach", + "Plains_beach", + "ExtremeHills_beach", + "ColdTaiga_beach", + "Swampland_shore", + "MushroomIslandShore", + "JungleM_shore", + "Jungle_shore", + "MesaPlateauFM_sandlevel", + "MesaPlateauF_sandlevel", + "MesaBryce_sandlevel", + "Mesa_sandlevel", + "RoofedForest_ocean", + "JungleEdgeM_ocean", + "BirchForestM_ocean", + "BirchForest_ocean", + "IcePlains_deep_ocean", + "Jungle_deep_ocean", + "Savanna_ocean", + "MesaPlateauF_ocean", + "ExtremeHillsM_deep_ocean", + "Savanna_deep_ocean", + "SunflowerPlains_ocean", + "Swampland_deep_ocean", + "Swampland_ocean", + "MegaSpruceTaiga_deep_ocean", + "ExtremeHillsM_ocean", + "JungleEdgeM_deep_ocean", + "SunflowerPlains_deep_ocean", + "BirchForest_deep_ocean", + "IcePlainsSpikes_ocean", + "Mesa_ocean", + "StoneBeach_ocean", + "Plains_deep_ocean", + "JungleEdge_deep_ocean", + "SavannaM_deep_ocean", + "Desert_deep_ocean", + "Mesa_deep_ocean", + "ColdTaiga_deep_ocean", + "Plains_ocean", + "MesaPlateauFM_ocean", + "Forest_deep_ocean", + "JungleM_deep_ocean", + "FlowerForest_deep_ocean", + "MushroomIsland_ocean", + "MegaTaiga_ocean", + "StoneBeach_deep_ocean", + "IcePlainsSpikes_deep_ocean", + "ColdTaiga_ocean", + "SavannaM_ocean", + "MesaPlateauF_deep_ocean", + "MesaBryce_deep_ocean", + "ExtremeHills+_deep_ocean", + "ExtremeHills_ocean", + "MushroomIsland_deep_ocean", + "Forest_ocean", + "MegaTaiga_deep_ocean", + "JungleEdge_ocean", + "MesaBryce_ocean", + "MegaSpruceTaiga_ocean", + "ExtremeHills+_ocean", + "Jungle_ocean", + "RoofedForest_deep_ocean", + "IcePlains_ocean", + "FlowerForest_ocean", + "ExtremeHills_deep_ocean", + "MesaPlateauFM_deep_ocean", + "Desert_ocean", + "Taiga_ocean", + "BirchForestM_deep_ocean", + "Taiga_deep_ocean", + "JungleM_ocean", + "FlowerForest_underground", + "JungleEdge_underground", + "StoneBeach_underground", + "MesaBryce_underground", + "Mesa_underground", + "RoofedForest_underground", + "Jungle_underground", + "Swampland_underground", + "MushroomIsland_underground", + "BirchForest_underground", + "Plains_underground", + "MesaPlateauF_underground", + "ExtremeHills_underground", + "MegaSpruceTaiga_underground", + "BirchForestM_underground", + "SavannaM_underground", + "MesaPlateauFM_underground", + "Desert_underground", + "Savanna_underground", + "Forest_underground", + "SunflowerPlains_underground", + "ColdTaiga_underground", + "IcePlains_underground", + "IcePlainsSpikes_underground", + "MegaTaiga_underground", + "Taiga_underground", + "ExtremeHills+_underground", + "JungleM_underground", + "ExtremeHillsM_underground", + "JungleEdgeM_underground", + }, + 0, + minetest.LIGHT_MAX + 1, + 30, + 10000, + 3, + water - 16, + water) + +-- spawn egg +mcl_mobs.register_egg("mobs_mc:glow_squid", S("Glow Squid"), "#095757", "#87f6c0", 0) diff --git a/mods/ENTITIES/mobs_mc/guardian.lua b/mods/ENTITIES/mobs_mc/guardian.lua index dd5f3a83e..e9a15264b 100644 --- a/mods/ENTITIES/mobs_mc/guardian.lua +++ b/mods/ENTITIES/mobs_mc/guardian.lua @@ -4,7 +4,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:guardian", { +mcl_mobs.register_mob("mobs_mc:guardian", { description = S("Guardian"), type = "monster", spawn_class = "hostile", @@ -104,4 +104,4 @@ mcl_mobs:register_mob("mobs_mc:guardian", { --mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:guardian", S("Guardian"), "mobs_mc_spawn_icon_guardian.png", 0) +mcl_mobs.register_egg("mobs_mc:guardian", S("Guardian"), "#5a8272", "#f17d31", 0) diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index f33576fb9..d08cc1846 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -6,7 +6,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:guardian_elder", { +mcl_mobs.register_mob("mobs_mc:guardian_elder", { description = S("Elder Guardian"), type = "monster", spawn_class = "hostile", @@ -112,5 +112,6 @@ mcl_mobs:register_mob("mobs_mc:guardian_elder", { -- mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "mobs_mc_spawn_icon_guardian_elder.png", 0) +mcl_mobs.register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "#ceccba", "#747693", 0) + diff --git a/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua new file mode 100644 index 000000000..e5cdcc8a8 --- /dev/null +++ b/mods/ENTITIES/mobs_mc/hoglin+zoglin.lua @@ -0,0 +1,135 @@ +--MCmobs v0.4 +--maikerumine +--made for MC like Survival game +--License for code WTFPL and otherwise stated in readmes + +local S = minetest.get_translator("mobs_mc") + +--################### +--################### hoglin +--################### + +local hoglin = { + type = "monster", + passive = false, + spawn_class = "hostile", + hp_min = 40, + hp_max = 40, + xp_min = 9, + xp_max = 9, + armor = {fleshy = 90}, + attack_type = "dogfight", + damage = 4, + reach = 3, + collisionbox = {-.6, -0.01, -.6, .6, 1.4, .6}, + visual = "mesh", + mesh = "extra_mobs_hoglin.b3d", + textures = { { + "extra_mobs_hoglin.png", + } }, + visual_size = {x=3, y=3}, + sounds = { + random = "extra_mobs_hoglin", + damage = "extra_mobs_hoglin_hurt", + distance = 16, + }, + jump = true, + makes_footstep_sound = true, + walk_velocity = 1, + run_velocity = 4, + drops = { + {name = "mobs_mcitems:leather", + chance = 1, + min = 0, + max = 1,}, + }, + drops = { + {name = "mcl_mobitems:porkchop", + chance = 1, + min = 2, + max = 4,}, + }, + animation = { + stand_speed = 7, + walk_speed = 7, + run_speed = 15, + stand_start = 24, + stand_end = 24, + walk_start = 11, + walk_end = 21, + run_start = 1, + run_end = 10, + punch_start = 22, + punch_end = 32, + }, + fear_height = 4, + view_range = 32, + floats = 0, + custom_attack = function(self) + if self.state == "attack" and self.reach > vector.distance(self.object:get_pos(), self.attack:get_pos()) then + self.attack:add_velocity({x=0,y=13,z=0}) + self.attack:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self.damage} + }, nil) + end + end, + do_custom = function(self) + if self.object:get_pos().y > -100 then + local zog = minetest.add_entity(self.object:get_pos(), "mobs_mc:zoglin") + zog:set_rotation(self.object:get_rotation()) + self.object:remove() + end + end, + attack_animals = true, +} + +mcl_mobs.register_mob("mobs_mc:hoglin", hoglin) + +local zoglin = table.copy(hoglin) +zoglin.fire_resistant = 1 +zoglin.textures = {"extra_mobs_zoglin.png"} +zoglin.do_custom = function() + return +end +zoglin.attacks_monsters = true +zoglin.lava_damage = 0 +zoglin.fire_damage = 0 +mcl_mobs.register_mob("mobs_mc:zoglin", zoglin) + +-- Baby hoglin. + +local baby_hoglin = table.copy(hoglin) +baby_hoglin.collisionbox = {-.3, -0.01, -.3, .3, 0.94, .3} +baby_hoglin.xp_min = 20 +baby_hoglin.xp_max = 20 +baby_hoglin.visual_size = {x=hoglin.visual_size.x/2, y=hoglin.visual_size.y/2} +textures = { { + "extra_mobs_hoglin.png", + "extra_mobs_trans.png", +} } +baby_hoglin.walk_velocity = 1.2 +baby_hoglin.run_velocity = 2.4 +baby_hoglin.child = 1 + +mcl_mobs.register_mob("mobs_mc:baby_hoglin", baby_hoglin) + +-- Regular spawning in the Nether +mcl_mobs:spawn_specific( +"mobs_mc:hoglin", +"nether", +"ground", +{ +"Nether", +"CrimsonForest" +}, +0, +minetest.LIGHT_MAX+1, +30, +6000, +3, +mcl_vars.mg_nether_min, +mcl_vars.mg_nether_max) + +-- spawn eggs +mcl_mobs.register_egg("mobs_mc:hoglin", S("Hoglin"), "#85682e", "#2b2140", 0) diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index 30c8e7d94..7f61627bc 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -34,6 +34,30 @@ local horse_extra_texture = function(horse) return textures end + +local function get_drops(self) + self.drops = {} + table.insert(self.drops, + {name = "mcl_mobitems:leather", + chance = 1, + min = 0, + max = 2, + looting = "common", + }) + if self._saddle then + table.insert(self.drops,{name = "mcl_mobitems:saddle", + chance = 1, + min = 1, + max = 1,}) + end + if self._chest then + table.insert(self.drops,{name = "mcl_chests:chest", + chance = 1, + min = 1, + max = 1,}) + end +end + -- Helper functions to determine equipment rules local can_equip_horse_armor = function(entity_id) return entity_id == "mobs_mc:horse" or entity_id == "mobs_mc:skeleton_horse" or entity_id == "mobs_mc:zombie_horse" @@ -157,6 +181,12 @@ local horse = { on_spawn = update_textures, do_custom = function(self, dtime) + if not self._horse_speed then + self._horse_speed = math.random(486, 1457)/100 + elseif self.run_velocity ~= self._horse_speed then + self.run_velocity = self._horse_speed + end + -- set needed values if not already present if not self._regentimer then self._regentimer = 0 @@ -237,6 +267,27 @@ local horse = { local iname = item:get_name() local heal = 0 + if self._inv_id then + if not self._chest and item:get_name() == "mcl_chests:chest" then + item:take_item() + clicker:set_wielded_item(item) + self._chest = true + -- Update texture + if not self._naked_texture then + -- Base horse texture without chest or saddle + self._naked_texture = self.base_texture[2] + end + local tex = horse_extra_texture(self) + self.base_texture = tex + self.object:set_properties({textures = self.base_texture}) + get_drops(self) + return + elseif self._chest and clicker:get_player_control().sneak then + mcl_entity_invs.show_inv_form(self,clicker) + return + end + end + -- Taming self.temper = self.temper or (math.random(1,100)) @@ -286,7 +337,7 @@ local horse = { elseif (iname == "mcl_farming:carrot_item_gold") then heal = 4 end - if heal > 0 and mcl_mobs:feed_tame(self, clicker, heal, true, false) then + if heal > 0 and self:feed_tame(clicker, heal, true, false) then return end end @@ -301,7 +352,7 @@ local horse = { elseif (iname == "mcl_farming:hay_block") then heal = 20 end - if heal > 0 and mcl_mobs:feed_tame(self, clicker, heal, false, false) then + if heal > 0 and self:feed_tame(clicker, heal, false, false) then return end @@ -340,6 +391,7 @@ local horse = { self.base_texture = tex self.object:set_properties({textures = self.base_texture}) minetest.sound_play({name = "mcl_armor_equip_leather"}, {gain=0.5, max_hear_distance=12, pos=self.object:get_pos()}, true) + get_drops(self) -- Put on horse armor if tamed elseif can_equip_horse_armor(self.name) and not self.driver and not self._horse_armor @@ -389,7 +441,7 @@ local horse = { on_breed = function(parent1, parent2) local pos = parent1.object:get_pos() - local child = mcl_mobs:spawn_child(pos, parent1.name) + local child = mcl_mobs.spawn_child(pos, parent1.name) if child then local ent_c = child:get_luaentity() local p = math.random(1, 2) @@ -438,7 +490,7 @@ local horse = { end, } -mcl_mobs:register_mob("mobs_mc:horse", horse) +mcl_mobs.register_mob("mobs_mc:horse", horse) -- Skeleton horse local skeleton_horse = table.copy(horse) @@ -461,7 +513,7 @@ skeleton_horse.sounds = { distance = 16, } skeleton_horse.harmed_by_heal = true -mcl_mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse) +mcl_mobs.register_mob("mobs_mc:skeleton_horse", skeleton_horse) -- Zombie horse local zombie_horse = table.copy(horse) @@ -485,7 +537,7 @@ zombie_horse.sounds = { distance = 16, } zombie_horse.harmed_by_heal = true -mcl_mobs:register_mob("mobs_mc:zombie_horse", zombie_horse) +mcl_mobs.register_mob("mobs_mc:zombie_horse", zombie_horse) -- Donkey local d = 0.86 -- donkey scale @@ -518,8 +570,9 @@ donkey.collisionbox = { donkey.jump = true donkey.jump_height = 3.75 -- can clear 1 block height -mcl_mobs:register_mob("mobs_mc:donkey", donkey) +mcl_mobs.register_mob("mobs_mc:donkey", donkey) +mcl_entity_invs.register_inv("mobs_mc:donkey","Donkey",15,true) -- Mule local m = 0.94 local mule = table.copy(donkey) @@ -536,7 +589,8 @@ mule.collisionbox = { horse.collisionbox[5] * m, horse.collisionbox[6] * m, } -mcl_mobs:register_mob("mobs_mc:mule", mule) +mcl_mobs.register_mob("mobs_mc:mule", mule) +mcl_entity_invs.register_inv("mobs_mc:mule","Mule",15,true) --=========================== --Spawn Function @@ -587,8 +641,8 @@ mobs_mc.water_level+3, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0) -mcl_mobs:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0) ---mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0) -mcl_mobs:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0) -mcl_mobs:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0) +mcl_mobs.register_egg("mobs_mc:horse", S("Horse"), "#c09e7d", "#eee500", 0) +mcl_mobs.register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "#68684f", "#e5e5d8", 0) +--mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "#2a5a37", "#84d080", 0) +mcl_mobs.register_egg("mobs_mc:donkey", S("Donkey"), "#534539", "#867566", 0) +mcl_mobs.register_egg("mobs_mc:mule", S("Mule"), "#1b0200", "#51331d", 0) diff --git a/mods/ENTITIES/mobs_mc/init.lua b/mods/ENTITIES/mobs_mc/init.lua index f32255d39..c2b3d8ed0 100644 --- a/mods/ENTITIES/mobs_mc/init.lua +++ b/mods/ENTITIES/mobs_mc/init.lua @@ -96,6 +96,7 @@ mobs_mc.water_level = tonumber(minetest.settings:get("water_level")) or 0 -- Animals local path = minetest.get_modpath("mobs_mc") +dofile(path .. "/axolotl.lua") -- Mesh and animation by JoeEnderman, Textures by Nova Wustra, modified by JoeEnderman dofile(path .. "/bat.lua") -- Mesh and animation by toby109tt / https://github.com/22i dofile(path .. "/rabbit.lua") -- Mesh and animation byExeterDad dofile(path .. "/chicken.lua") -- Mesh and animation by Pavel_S @@ -148,3 +149,11 @@ dofile(path .. "/cod.lua") dofile(path .. "/salmon.lua") dofile(path .. "/tropical_fish.lua") dofile(path .. "/dolphin.lua") + + +dofile(path .. "/glow_squid.lua") + +dofile(path .. "/piglin.lua") +dofile(path .. "/hoglin+zoglin.lua") + +dofile(path .. "/strider.lua") diff --git a/mods/ENTITIES/mobs_mc/iron_golem.lua b/mods/ENTITIES/mobs_mc/iron_golem.lua index 81c7ed4bb..7ca4dd88a 100644 --- a/mods/ENTITIES/mobs_mc/iron_golem.lua +++ b/mods/ENTITIES/mobs_mc/iron_golem.lua @@ -11,7 +11,7 @@ local S = minetest.get_translator("mobs_mc") local etime = 0 -mcl_mobs:register_mob("mobs_mc:iron_golem", { +mcl_mobs.register_mob("mobs_mc:iron_golem", { description = S("Iron Golem"), type = "npc", spawn_class = "passive", @@ -22,6 +22,9 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", { collisionbox = {-0.7, -0.01, -0.7, 0.7, 2.69, 0.7}, visual = "mesh", mesh = "mobs_mc_iron_golem.b3d", + head_swivel = "head.control", + bone_eye_height = 3.38, + curiosity = 10, textures = { {"mobs_mc_iron_golem.png"}, }, @@ -45,13 +48,14 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", { _got_poppy = false, pick_up = {"mcl_flowers:poppy"}, on_pick_up = function(self,n) - if n.itemstring:find("mcl_flowers:poppy") then + local it = ItemStack(n.itemstring) + if it:get_name() == "mcl_flowers:poppy" then if not self._got_poppy then self._got_poppy=true - return + it:take_item(1) end - return true end + return it end, replace_what = {"mcl_flowers:poppy"}, replace_with = {"air"}, @@ -85,7 +89,7 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", { etime = etime + dtime if etime > 10 then if self._home and vector.distance(self._home,self.object:get_pos()) > 50 then - mcl_mobs:gopath(self,self._home) + self:gopath(self._home) end end end, @@ -93,8 +97,7 @@ mcl_mobs:register_mob("mobs_mc:iron_golem", { -- spawn eggs -mcl_mobs:register_egg("mobs_mc:iron_golem", S("Iron Golem"), "mobs_mc_spawn_icon_iron_golem.png", 0) - +mcl_mobs.register_egg("mobs_mc:iron_golem", S("Iron Golem"), "#3b3b3b", "#f57223", 0) --[[ This is to be called when a pumpkin or jack'o lantern has been placed. Recommended: In the on_construct function of the node. This summons an iron golen if placing the pumpkin created an iron golem summon pattern: diff --git a/mods/ENTITIES/mobs_mc/llama.lua b/mods/ENTITIES/mobs_mc/llama.lua index f1f757e06..503f4207b 100644 --- a/mods/ENTITIES/mobs_mc/llama.lua +++ b/mods/ENTITIES/mobs_mc/llama.lua @@ -24,7 +24,30 @@ local carpets = { unicolor_light_blue = { "mcl_wool:light_blue_carpet", "light_blue" }, } -mcl_mobs:register_mob("mobs_mc:llama", { +local function get_drops(self) + self.drops = {} + table.insert(self.drops, + {name = "mcl_mobitems:leather", + chance = 1, + min = 0, + max = 2, + looting = "common", + }) + if self.carpet then + table.insert(self.drops,{name = self.carpet, + chance = 1, + min = 1, + max = 1,}) + end + if self._has_chest then + table.insert(self.drops,{name = "mcl_chests:chest", + chance = 1, + min = 1, + max = 1,}) + end +end + +mcl_mobs.register_mob("mobs_mc:llama", { description = S("Llama"), type = "animal", spawn_class = "passive", @@ -35,6 +58,14 @@ mcl_mobs:register_mob("mobs_mc:llama", { 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 = 6, + + head_swivel = "head.control", + bone_eye_height = 11, + head_eye_height = 3, + horrizonatal_head_height=0, + curiosity = 60, + head_yaw = "z", + hp_min = 15, hp_max = 30, xp_min = 1, @@ -49,7 +80,6 @@ mcl_mobs:register_mob("mobs_mc:llama", { {"blank.png", "blank.png", "mobs_mc_llama_white.png"}, {"blank.png", "blank.png", "mobs_mc_llama.png"}, }, - visual_size = {x=3, y=3}, makes_footstep_sound = true, runaway = false, walk_velocity = 1, @@ -71,36 +101,28 @@ mcl_mobs:register_mob("mobs_mc:llama", { distance = 16, }, animation = { - speed_normal = 24, - run_speed = 60, - run_start = 0, - run_end = 40, - stand_start = 0, - stand_end = 0, - walk_start = 0, - walk_end = 40, - hurt_start = 118, - hurt_end = 154, - death_start = 154, - death_end = 179, - eat_start = 49, - eat_end = 78, - look_start = 78, - look_end = 108, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 35, + run_start = 0, run_end = 40, run_speed = 50, + }, + child_animations = { + stand_start = 41, stand_end = 41, + walk_start = 41, walk_end = 81, walk_speed = 50, + run_start = 41, run_end = 81, run_speed = 75, }, follow = { "mcl_farming:wheat_item", "mcl_farming:hay_block" }, view_range = 16, do_custom = function(self, dtime) -- set needed values if not already present - if not self.v2 then - self.v2 = 0 + if not self.v3 then + self.v3 = 0 self.max_speed_forward = 4 self.max_speed_reverse = 2 self.accel = 4 self.terrain_type = 3 - self.driver_attach_at = {x = 0, y = 4.17, z = -1.5} - self.driver_eye_offset = {x = 0, y = 3, z = 0} + self.driver_attach_at = {x = 0, y = 12.7, z = -5} + self.driver_eye_offset = {x = 0, y = 6, z = 0} self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y} end @@ -134,62 +156,59 @@ mcl_mobs:register_mob("mobs_mc:llama", { local item = clicker:get_wielded_item() if item:get_name() == "mcl_farming:hay_block" then -- Breed with hay bale - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end + elseif not self._has_chest and item:get_name() == "mcl_chests:chest" then + item:take_item() + clicker:set_wielded_item(item) + self._has_chest = true + self.base_texture = table.copy(self.base_texture) + self.base_texture[1] = self.base_texture[3] + self.object:set_properties({ + textures = self.base_texture, + }) + get_drops(self) + return + elseif self._has_chest and clicker:get_player_control().sneak then + mcl_entity_invs.show_inv_form(self,clicker," - Strength "..math.floor(self._inv_size / 3)) + return else -- Feed with anything else - if mcl_mobs:feed_tame(self, clicker, 1, false, true) then return end + if self:feed_tame(clicker, 1, false, true) then return end end if mcl_mobs:protect(self, clicker) then return end -- Make sure tamed llama is mature and being clicked by owner only if self.tamed and not self.child and self.owner == clicker:get_player_name() then - - -- Place carpet - if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then - for group, carpetdata in pairs(carpets) do - if minetest.get_item_group(item:get_name(), group) == 1 then - if not minetest.is_creative_enabled(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) + -- Place carpet + if minetest.get_item_group(item:get_name(), "carpet") == 1 and not self.carpet then + for group, carpetdata in pairs(carpets) do + if minetest.get_item_group(item:get_name(), group) == 1 then + if not minetest.is_creative_enabled(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + local substr = carpetdata[2] + local tex_carpet = "mobs_mc_llama_decor_"..substr..".png" + self.base_texture = table.copy(self.base_texture) + self.base_texture[2] = tex_carpet + self.object:set_properties({ + textures = self.base_texture, + }) + self.carpet = item:get_name() + get_drops(self) + return end - local substr = carpetdata[2] - local tex_carpet = "mobs_mc_llama_decor_"..substr..".png" - self.base_texture = table.copy(self.base_texture) - self.base_texture[2] = tex_carpet - self.object:set_properties({ - textures = self.base_texture, - }) - self.carpet = item:get_name() - self.drops = { - {name = "mcl_mobitems:leather", - chance = 1, - min = 0, - max = 2,}, - {name = item:get_name(), - chance = 1, - min = 1, - max = 1,}, - } - return end end - end - -- detatch player already riding llama - if self.driver and clicker == self.driver then - - mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1}) - - -- attach player to llama - elseif not self.driver then - - self.object:set_properties({stepheight = 1.1}) - mcl_mobs.attach(self, clicker) - end - - -- Used to capture llama - elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then - mcl_mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) + -- detatch player already riding llama + if self.driver and clicker == self.driver then + mcl_mobs.detach(clicker, {x = 1, y = 0, z = 1}) + -- attach player to llama + elseif not self.driver then + self.object:set_properties({stepheight = 1.1}) + mcl_mobs.attach(self, clicker) + end end end, @@ -202,7 +221,7 @@ mcl_mobs:register_mob("mobs_mc:llama", { else parent = parent2 end - child = mcl_mobs:spawn_child(pos, parent.name) + child = mcl_mobs.spawn_child(pos, parent.name) if child then local ent_c = child:get_luaentity() ent_c.base_texture = table.copy(ent_c.base_texture) @@ -214,11 +233,28 @@ mcl_mobs:register_mob("mobs_mc:llama", { return false end end, - + on_spawn = function(self) + if not self._inv_size then + local r = math.random(1000) + if r < 80 then + self._inv_size = 15 + elseif r < 160 then + self._inv_size = 12 + elseif r < 488 then + self._inv_size = 9 + elseif r < 816 then + self._inv_size = 6 + else + self._inv_size = 3 + end + end + end, }) +mcl_entity_invs.register_inv("mobs_mc:llama","Llama",nil,true) + -- spit arrow (weapon) -mcl_mobs:register_arrow("mobs_mc:llamaspit", { +mcl_mobs.register_arrow("mobs_mc:llamaspit", { visual = "sprite", visual_size = {x = 0.10, y = 0.10}, textures = {"mobs_mc_llama_spit.png"}, @@ -248,12 +284,10 @@ mcl_mobs:spawn_specific( "SavannaM_beach", "Savanna_beach", "Savanna_ocean", - "JungleEdge", - "JungleEdgeM", "ExtremeHills", "ExtremeHills_beach", "ExtremeHillsM", -}, +}, --FIXME: Needs Windswept Forest when that is added. 0, minetest.LIGHT_MAX+1, 30, @@ -263,4 +297,4 @@ mobs_mc.water_level+15, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0) +mcl_mobs.register_egg("mobs_mc:llama", S("Llama"), "#c09e7d", "#995f40", 0) diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 493e2cb6e..38c6111b5 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -1,5 +1,6 @@ # textdomain: mobs_mc Agent= +Axolotl= Bat= Blaze= Chicken= diff --git a/mods/ENTITIES/mobs_mc/mod.conf b/mods/ENTITIES/mobs_mc/mod.conf index 3d6a6928d..89964c835 100644 --- a/mods/ENTITIES/mobs_mc/mod.conf +++ b/mods/ENTITIES/mobs_mc/mod.conf @@ -1,6 +1,5 @@ name = mobs_mc author = maikerumine description = Adds Minecraft-like monsters and animals. -depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_core +depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_core, mcl_util optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, mobs_mc_gameconfig, doc_items - diff --git a/mods/ENTITIES/mobs_mc/models/extra_mobs_glow_squid.b3d b/mods/ENTITIES/mobs_mc/models/extra_mobs_glow_squid.b3d new file mode 100644 index 000000000..887576b28 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/extra_mobs_glow_squid.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/extra_mobs_hoglin.b3d b/mods/ENTITIES/mobs_mc/models/extra_mobs_hoglin.b3d new file mode 100644 index 000000000..d3886e089 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/extra_mobs_hoglin.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/extra_mobs_piglin.b3d b/mods/ENTITIES/mobs_mc/models/extra_mobs_piglin.b3d new file mode 100644 index 000000000..e07bd15aa Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/extra_mobs_piglin.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/extra_mobs_strider.b3d b/mods/ENTITIES/mobs_mc/models/extra_mobs_strider.b3d new file mode 100644 index 000000000..72f4e254e Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/extra_mobs_strider.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/extra_mobs_sword_piglin.b3d b/mods/ENTITIES/mobs_mc/models/extra_mobs_sword_piglin.b3d new file mode 100644 index 000000000..1988f4082 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/extra_mobs_sword_piglin.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_agent.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_agent.b3d deleted file mode 100644 index 3e79c009b..000000000 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_agent.b3d and /dev/null differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_axolotl.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_axolotl.b3d new file mode 100644 index 000000000..3e4c8119e Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/mobs_mc_axolotl.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_blaze.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_blaze.b3d index 2328c8a64..7593baa2f 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_blaze.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_blaze.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_cat.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_cat.b3d index 1a6ecbbe8..84cc91652 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_cat.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_cat.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_chicken.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_chicken.b3d index 6d839a459..623a467b9 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_chicken.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_chicken.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_cow.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_cow.b3d index c00983919..f29c6a961 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_cow.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_cow.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_creeper.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_creeper.b3d index e04ffc7b0..72887d8d4 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_creeper.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_creeper.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_evoker.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_evoker.b3d index 6e1017e0c..4a429f7c3 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_evoker.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_evoker.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_illusioner.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_illusioner.b3d index 7bb719ffb..6bdcbf339 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_illusioner.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_illusioner.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_iron_golem.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_iron_golem.b3d index a7fbd352b..db87e6540 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_iron_golem.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_iron_golem.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_llama.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_llama.b3d index 5d6dd6b37..8e1da8b24 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_llama.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_llama.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_mooshroom.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_mooshroom.b3d deleted file mode 100644 index c00983919..000000000 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_mooshroom.b3d and /dev/null differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_parrot.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_parrot.b3d index 7cb326d3d..2f59c313b 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_parrot.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_parrot.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_pig.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_pig.b3d index 8ba5b6a84..4bbaf6e23 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_pig.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_pig.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_polarbear.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_polarbear.b3d index bb64b2b79..cbda1f8c9 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_polarbear.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_polarbear.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_rabbit.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_rabbit.b3d index ad2067d7b..d28aa5368 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_rabbit.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_rabbit.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_sheepfur.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_sheepfur.b3d index 1db15ddba..7ee15fb55 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_sheepfur.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_sheepfur.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_skeleton.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_skeleton.b3d index aa1681dbe..f5e8d4917 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_skeleton.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_skeleton.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_spider.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_spider.b3d index aec461a6b..0d71f6377 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_spider.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_spider.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_villager.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_villager.b3d index a941ca8ef..1d46a162b 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_villager.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_villager.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_villager_zombie.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_villager_zombie.b3d index b7dd9d7ee..a45eac602 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_villager_zombie.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_villager_zombie.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_vindicator.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_vindicator.b3d index ae14e8edb..d220e895c 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_vindicator.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_vindicator.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_witherskeleton.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_witherskeleton.b3d index c1b808307..ec2952cf5 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_witherskeleton.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_witherskeleton.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_wolf.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_wolf.b3d index 28bdb3b49..82684e303 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_wolf.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_wolf.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_zombie_pigman.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_zombie_pigman.b3d index 0b9f4f7c9..0f1d6ea24 100644 Binary files a/mods/ENTITIES/mobs_mc/models/mobs_mc_zombie_pigman.b3d and b/mods/ENTITIES/mobs_mc/models/mobs_mc_zombie_pigman.b3d differ diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index 7d8b444da..8a7ea7545 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -36,11 +36,16 @@ local ocelot = { hp_max = 10, xp_min = 1, xp_max = 3, + head_swivel = "head.control", + bone_eye_height = 6.2, + head_eye_height = 0.4, + horrizonatal_head_height=-0, + head_yaw="z", + curiosity = 4, collisionbox = {-0.3, -0.01, -0.3, 0.3, 0.69, 0.3}, visual = "mesh", mesh = "mobs_mc_cat.b3d", textures = {"mobs_mc_cat_ocelot.png"}, - visual_size = {x=2.0, y=2.0}, makes_footstep_sound = true, walk_chance = default_walk_chance, walk_velocity = 1, @@ -57,14 +62,16 @@ local ocelot = { distance = 16, }, animation = { - speed_normal = 25, - run_speed = 50, - stand_start = 0, - stand_end = 0, - walk_start = 0, - walk_end = 40, - run_start = 0, - run_end = 40, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 40, + run_start = 0, run_end = 40, run_speed = 50, + sit_start = 50, sit_end = 50, + }, + child_animations = { + stand_start = 51, stand_end = 51, + walk_start = 51, walk_end = 91, walk_speed = 60, + run_start = 51, run_end = 91, run_speed = 75, + sit_start = 101, sit_end = 101, }, follow = follow, view_range = 12, @@ -100,7 +107,7 @@ local ocelot = { end, } -mcl_mobs:register_mob("mobs_mc:ocelot", ocelot) +mcl_mobs.register_mob("mobs_mc:ocelot", ocelot) -- Cat local cat = table.copy(ocelot) @@ -123,7 +130,7 @@ cat.sounds = { distance = 16, } cat.on_rightclick = function(self, clicker) - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end if mcl_mobs:protect(self, clicker) then return end @@ -150,7 +157,17 @@ cat.on_rightclick = function(self, clicker) end -mcl_mobs:register_mob("mobs_mc:cat", cat) +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 @@ -232,5 +249,4 @@ mobs:spawn({ ]]-- -- spawn eggs --- FIXME: The spawn icon shows a cat texture, not an ocelot texture -mcl_mobs:register_egg("mobs_mc:ocelot", S("Ocelot"), "mobs_mc_spawn_icon_cat.png", 0) +mcl_mobs.register_egg("mobs_mc:ocelot", S("Ocelot"), "#efde7d", "#564434", 0) diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index c2f34c5a6..ed2892aca 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -87,7 +87,7 @@ local function perch(self,player) local shoulder = get_shoulder(player) if not shoulder then return true end self.object:set_attach(player,"",shoulder,vector.new(0,0,0),true) - mcl_mobs:set_animation(self, "stand") + self:set_animation("stand") end end @@ -125,7 +125,7 @@ local function check_perch(self,dtime) end end -mcl_mobs:register_mob("mobs_mc:parrot", { +mcl_mobs.register_mob("mobs_mc:parrot", { description = S("Parrot"), type = "animal", spawn_class = "passive", @@ -135,6 +135,10 @@ mcl_mobs:register_mob("mobs_mc:parrot", { hp_max = 6, xp_min = 1, xp_max = 3, + head_swivel = "head.control", + bone_eye_height = 1.1, + horrizonatal_head_height=0, + curiosity = 10, collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25}, visual = "mesh", mesh = "mobs_mc_parrot.b3d", @@ -203,7 +207,7 @@ mcl_mobs:register_mob("mobs_mc:parrot", { return end -- Feed to tame, but not breed - if mcl_mobs:feed_tame(self, clicker, 1, false, true) then return end + if self:feed_tame(clicker, 1, false, true) then return end perch(self,clicker) end, do_custom = function(self,dtime) @@ -237,4 +241,4 @@ mobs_mc.water_level+7, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0) +mcl_mobs.register_egg("mobs_mc:parrot", S("Parrot"), "#0da70a", "#ff0000", 0) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index b88e88d49..99e05391f 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:pig", { +mcl_mobs.register_mob("mobs_mc:pig", { description = S("Pig"), type = "animal", spawn_class = "passive", @@ -15,11 +15,15 @@ mcl_mobs:register_mob("mobs_mc:pig", { visual = "mesh", mesh = "mobs_mc_pig.b3d", textures = {{ - "blank.png", -- baby "mobs_mc_pig.png", -- base "blank.png", -- saddle }}, - visual_size = {x=2.5, y=2.5}, + head_swivel = "head.control", + bone_eye_height = 7.5, + head_eye_height = 0.8, + horrizonatal_head_height=-1, + curiosity = 3, + head_yaw="z", makes_footstep_sound = true, walk_velocity = 1, run_velocity = 3, @@ -40,15 +44,14 @@ mcl_mobs:register_mob("mobs_mc:pig", { distance = 16, }, animation = { - stand_speed = 40, - walk_speed = 40, - run_speed = 90, - stand_start = 0, - stand_end = 0, - walk_start = 0, - walk_end = 40, - run_start = 0, - run_end = 40, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 60, + run_start = 0, run_end = 40, run_speed = 90, + }, + child_animations = { + stand_start = 41, stand_end = 41, + walk_start = 41, walk_end = 81, walk_speed = 90, + run_start = 41, run_end = 81, run_speed = 135, }, follow = { "mcl_farming:potato_item", @@ -57,18 +60,24 @@ mcl_mobs:register_mob("mobs_mc:pig", { "mcl_mobitems:carrot_on_a_stick" }, view_range = 8, + on_lightning_strike = function(self, pos, pos2, objects) + mcl_util.replace_mob(self.object, "mobs_mc:zombified_piglin") + return true + end, do_custom = function(self, dtime) -- set needed values if not already present - if not self.v2 then - self.v2 = 0 + if not self.v3 then + self.v3 = 0 self.max_speed_forward = 4 self.max_speed_reverse = 2 self.accel = 4 self.terrain_type = 3 - self.driver_attach_at = {x = 0.0, y = 2.75, z = -1.5} + self.driver_attach_at = {x = 0.0, y = 6.5, z = -3.75} self.driver_eye_offset = {x = 0, y = 3, z = 0} self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y} + self.base_texture = self.texture_list[1] + self.object:set_properties({textures = self.base_texture}) end -- if driver present allow control of horse @@ -99,7 +108,7 @@ mcl_mobs:register_mob("mobs_mc:pig", { local wielditem = clicker:get_wielded_item() -- Feed pig if wielditem:get_name() ~= "mcl_mobitems:carrot_on_a_stick" then - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end end if mcl_mobs:protect(self, clicker) then return end @@ -111,7 +120,6 @@ mcl_mobs:register_mob("mobs_mc:pig", { local item = clicker:get_wielded_item() if item:get_name() == "mcl_mobitems:saddle" and self.saddle ~= "yes" then self.base_texture = { - "blank.png", -- baby "mobs_mc_pig.png", -- base "mobs_mc_pig_saddle.png", -- saddle } @@ -178,7 +186,7 @@ mcl_mobs:register_mob("mobs_mc:pig", { on_breed = function(parent1, parent2) local pos = parent1.object:get_pos() - local child = mcl_mobs:spawn_child(pos, parent1.name) + local child = mcl_mobs.spawn_child(pos, parent1.name) if child then local ent_c = child:get_luaentity() ent_c.tamed = true @@ -234,4 +242,4 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:pig", S("Pig"), "mobs_mc_spawn_icon_pig.png", 0) +mcl_mobs.register_egg("mobs_mc:pig", S("Pig"), "#f0a5a2", "#db635f", 0) diff --git a/mods/ENTITIES/mobs_mc/piglin.lua b/mods/ENTITIES/mobs_mc/piglin.lua new file mode 100644 index 000000000..90e19ef02 --- /dev/null +++ b/mods/ENTITIES/mobs_mc/piglin.lua @@ -0,0 +1,320 @@ +--MCmobs v0.4 +--maikerumine +--made for MC like Survival game +--License for code WTFPL and otherwise stated in readmes + +local trading_items = { + { itemstring = "mcl_core:obsidian", amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_core:gravel", amount_min = 8, amount_max = 16 }, + { itemstring = "mcl_mobitems:leather", amount_min = 4, amount_max = 10 }, + { itemstring = "mcl_nether:soul_sand", amount_min = 4, amount_max = 16 }, + { itemstring = "mcl_nether:nether_brick", amount_min = 4, amount_max = 16 }, + { itemstring = "mcl_mobitems:string", amount_min = 3, amount_max = 9 }, + { itemstring = "mcl_nether:quartz", amount_min = 4, amount_max = 10 }, + { itemstring = "mcl_potions:water", amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_core:iron_nugget", amount_min = 10, amount_max = 36 }, + { itemstring = "mcl_throwing:ender_pearl", amount_min = 2, amount_max = 6 }, + { itemstring = "mcl_potions:fire_resistance", amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_potions:fire_resistance_splash", amount_min = 1, amount_max = 1 }, +} + +local S = minetest.get_translator("mobs_mc") +local mod_bows = minetest.get_modpath("mcl_bows") ~= nil + +function mobs_mc.player_wears_gold(player) + for i=1, 6 do + local stack = player:get_inventory():get_stack("armor", i) + local item = stack:get_name() + if item == "mcl_armor:chestplate_gold" or item == "mcl_armor:leggings_gold" or item == "mcl_armor:helmet_gold" or item == "mcl_armor:boots_gold" then + return true + end + end +end + +--################### +--################### piglin +--################### +local piglin = { + type = "monster", + passive = false, + spawn_class = "hostile", + hp_min = 16, + hp_max = 16, + xp_min = 9, + xp_max = 9, + armor = {fleshy = 90}, + damage = 4, + reach = 3, + collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, + visual = "mesh", + mesh = "extra_mobs_piglin.b3d", + spawn_in_group = 4, + spawn_in_group_min = 2, + textures = { { + "extra_mobs_piglin.png", + "mcl_bows_bow_2.png", + } }, + visual_size = {x=1, y=1}, + sounds = { + random = "extra_mobs_piglin", + damage = "extra_mobs_piglin_hurt", + distance = 16, + }, + jump = true, + makes_footstep_sound = true, + walk_velocity = 4.317, + run_velocity = 5.6121, + drops = { + {name = "mcl_bows:crossbow", + chance = 10, + min = 1, + max = 1,}, + }, + animation = { + stand_speed = 30, + walk_speed = 30, + run_speed = 30, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 187, + run_start = 440, + run_end = 459, + }, + fear_height = 4, + view_range = 16, + pick_up = {"mcl_core:gold_ingot"}, + on_spawn = function(self) + self.weapon = self.base_texture[2] + self.gold_items = 0 + end, + do_custom = function(self) + if self.object:get_pos().y > mcl_vars.mg_overworld_min then + local zog = minetest.add_entity(self.object:get_pos(), "mobs_mc:zombified_piglin") + zog:set_rotation(self.object:get_rotation()) + self.object:remove() + return + elseif self.trading == true then + self.state = "trading" + self.object:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(20,-20,18)) + self.object:set_bone_position("Head", vector.new(0,6.3,0), vector.new(-40,0,0)) + self.base_texture[2] = "default_gold_ingot.png" + self.object:set_properties({textures = self.base_texture}) + else + self.object:set_bone_position("Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20)) + self.base_texture[2] = self.weapon + self.object:set_properties({textures = self.base_texture}) + self.object:set_bone_position("Head", vector.new(0,6.3,0), vector.new(0,0,0)) + self.object:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0)) + end + + if self.state ~= "attack" then + self._attacked_by_player = false + elseif self.attack:is_player() and mobs_mc.player_wears_gold(self.attack) then + if self._attacked_by_player == false then + self.state = "stand" + end + end + end, + on_pick_up = function(self, itementity) + local item = itementity.itemstring:split(" ")[1] + local it = ItemStack(itementity.itemstring) + if item == "mcl_core:gold_ingot" and self.state ~= "attack" and self.gold_items and self.gold_items < 3 then + it:take_item(1) + self.state = "stand" + self.object:set_animation({x=0,y=79}) + self.trading = true + self.gold_items = self.gold_items + 1 + self.object:set_bone_position("Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90)) + minetest.after(5, function() + self.gold_items = self.gold_items - 1 + if self.gold_items == 0 then + self.trading = false + self.state = "stand" + end + local c_pos = self.object:get_pos() + if c_pos then + self.what_traded = trading_items[math.random(#trading_items)] + for x = 1, math.random(self.what_traded.amount_min, self.what_traded.amount_max) do + local p = c_pos + local nn=minetest.find_nodes_in_area_under_air(vector.offset(c_pos,-1,-1,-1),vector.offset(c_pos,1,1,1),{"group:solid"}) + if nn and #nn > 0 then + p = vector.offset(nn[math.random(#nn)],0,1,0) + end + minetest.add_item(p, self.what_traded.itemstring) + end + end + end) + end + return it + end, + do_punch = function(self, hitter) + if hitter:is_player() then + self._attacked_by_player = true + end + end, + attack_type = "dogshoot", + arrow = "mcl_bows:arrow_entity", + shoot_arrow = function(self, pos, dir) + if mod_bows then + if self.attack then + self.object:set_yaw(minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.attack:get_pos()))) + end + -- 2-4 damage per arrow + local dmg = math.max(4, math.random(2, 8)) + mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + end + end, + shoot_interval = 2, + shoot_offset = 1.5, + dogshoot_switch = 1, + dogshoot_count_max =1.8, + attacks_monsters = true, + attack_animals = true, + specific_attack = { "player", "mobs_mc:hoglin" }, +} + +mcl_mobs.register_mob("mobs_mc:piglin", piglin) + + +local sword_piglin = table.copy(piglin) +sword_piglin.mesh = "extra_mobs_sword_piglin.b3d" +sword_piglin.textures = {"extra_mobs_piglin.png", "default_tool_goldsword.png"} +sword_piglin.on_spawn = function(self) + self.gold_items = 0 + self.weapon = self.base_texture[2] + self.object:set_bone_position("Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0)) +end +sword_piglin.drops = { + {name = "mcl_tools:sword_gold", + chance = 10, + min = 1, + max = 1,}, +} +sword_piglin.attack_type = "dogfight" +sword_piglin.animation = { + stand_speed = 30, + walk_speed = 30, + punch_speed = 45, + run_speed = 30, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 187, + run_start = 440, + run_end = 459, + punch_start = 189, + punch_end = 198, +} +mcl_mobs.register_mob("mobs_mc:sword_piglin", sword_piglin) + +local zombified_piglin = table.copy(piglin) +zombified_piglin.fire_resistant = 1 +zombified_piglin.do_custom = function() + return +end +zombified_piglin.on_spawn = function() + return +end +zombified_piglin.on_rightclick = function() + return +end +zombified_piglin.lava_damage = 0 +zombified_piglin.fire_damage = 0 +zombified_piglin.attack_animals = true +zombified_piglin.mesh = "extra_mobs_sword_piglin.b3d" +zombified_piglin.textures = {"extra_mobs_zombified_piglin.png", "default_tool_goldsword.png", "extra_mobs_trans.png"} +zombified_piglin.attack_type = "dogfight" +zombified_piglin.animation = { + stand_speed = 30, + walk_speed = 30, + punch_speed = 45, + run_speed = 30, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 187, + run_start = 440, + run_end = 459, + punch_start = 189, + punch_end = 198, +} +mcl_mobs.register_mob("mobs_mc:zombified_piglin", zombified_piglin) + + +local piglin_brute = table.copy(piglin) +piglin_brute.xp_min = 20 +piglin_brute.xp_max = 20 +piglin_brute.hp_min = 50 +piglin_brute.hp_max = 50 +piglin_brute.fire_resistant = 1 +piglin_brute.do_custom = function() + return +end +piglin_brute.on_spawn = function() + return +end +piglin_brute.on_rightclick = function() + return +end +piglin_brute.attacks_monsters = true +piglin_brute.lava_damage = 0 +piglin_brute.fire_damage = 0 +piglin_brute.attack_animals = true +piglin_brute.mesh = "extra_mobs_sword_piglin.b3d" +piglin_brute.textures = {"extra_mobs_piglin_brute.png", "default_tool_goldaxe.png", "extra_mobs_trans.png"} +piglin_brute.attack_type = "dogfight" +piglin_brute.animation = { + stand_speed = 30, + walk_speed = 30, + punch_speed = 45, + run_speed = 30, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 187, + run_start = 440, + run_end = 459, + punch_start = 189, + punch_end = 198, +} +piglin_brute.can_despawn = false +piglin_brute.group_attack = { "mobs_mc:piglin", "mobs_mc:piglin_brute" } +mcl_mobs.register_mob("mobs_mc:piglin_brute", piglin_brute) + + +-- Regular spawning in the Nether +mcl_mobs:spawn_specific( +"mobs_mc:piglin", +"nether", +"ground", +{ +"Nether", +"CrimsonForest" +}, +0, +minetest.LIGHT_MAX+1, +30, +6000, +3, +mcl_vars.mg_lava_nether_max, +mcl_vars.mg_nether_max) + +mcl_mobs:spawn_specific( +"mobs_mc:sword_piglin", +"nether", +"ground", +{ +"Nether", +"CrimsonForest" +}, +0, +minetest.LIGHT_MAX+1, +30, +6000, +3, +mcl_vars.mg_lava_nether_max, +mcl_vars.mg_nether_max) +-- spawn eggs +mcl_mobs.register_egg("mobs_mc:piglin", S("Piglin"), "#7b4a17","#d5c381", 0) +mcl_mobs.register_egg("mobs_mc:piglin_brute", S("Piglin Brute"), "#562b0c","#ddc89d", 0) diff --git a/mods/ENTITIES/mobs_mc/pillager.lua b/mods/ENTITIES/mobs_mc/pillager.lua index 37122aa18..0b6b036f7 100644 --- a/mods/ENTITIES/mobs_mc/pillager.lua +++ b/mods/ENTITIES/mobs_mc/pillager.lua @@ -12,7 +12,7 @@ end local function reset_animation(self, animation) if not self.object:get_pos() or self._current_animation ~= animation then return end self._current_animation = "stand_reload" -- Mobs Redo won't set the animation unless we do this - mcl_mobs:set_animation(self, animation) + self:set_animation(animation) end pillager = { @@ -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, @@ -95,29 +96,29 @@ pillager = { self.object:set_properties(props) local old_anim = self._current_animation if old_anim == "run" or old_anim == "walk" then - mcl_mobs:set_animation(self, "reload_run") + self:set_animation("reload_run") end if old_anim == "stand" then - mcl_mobs:set_animation(self, "reload_stand") + self:set_animation("reload_stand") end self._current_animation = old_anim -- Mobs Redo will imediately reset the animation otherwise minetest.after(1, reload, self) minetest.after(2, reset_animation, self, old_anim) - + -- 2-4 damage per arrow local dmg = math.max(4, math.random(2, 8)) mcl_bows_s.shoot_arrow_crossbow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) - + -- While we are at it, change the sounds since there is no way to do this in Mobs Redo if self.sounds and self.sounds.random then self.sounds = table.copy(self.sounds) self.sounds.random = "mobs_mc_pillager_grunt" .. math.random(2) end - + -- Randomize reload time self.shoot_interval = math.random(3, 4) end, } -mcl_mobs:register_mob("mobs_mc:pillager", pillager) -mcl_mobs:register_egg("mobs_mc:pillager", S("Pillager"), "mobs_mc_spawn_icon_pillager.png", 0) +mcl_mobs.register_mob("mobs_mc:pillager", pillager) +mcl_mobs.register_egg("mobs_mc:pillager", S("Pillager"), "#532f36", "#959b9b", 0) diff --git a/mods/ENTITIES/mobs_mc/polar_bear.lua b/mods/ENTITIES/mobs_mc/polar_bear.lua index 4b2f338b2..d6667a256 100644 --- a/mods/ENTITIES/mobs_mc/polar_bear.lua +++ b/mods/ENTITIES/mobs_mc/polar_bear.lua @@ -7,7 +7,7 @@ local S = minetest.get_translator("mobs_mc") --################### -mcl_mobs:register_mob("mobs_mc:polar_bear", { +mcl_mobs.register_mob("mobs_mc:polar_bear", { description = S("Polar Bear"), type = "animal", spawn_class = "passive", @@ -24,6 +24,12 @@ mcl_mobs:register_mob("mobs_mc:polar_bear", { textures = { {"mobs_mc_polarbear.png"}, }, + head_swivel = "head.control", + bone_eye_height = 2.6, + head_eye_height = 1, + horrizonatal_head_height = 0, + curiosity = 20, + head_yaw="z", visual_size = {x=3.0, y=3.0}, makes_footstep_sound = true, damage = 6, @@ -86,4 +92,4 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn egg -mcl_mobs:register_egg("mobs_mc:polar_bear", S("Polar Bear"), "mobs_mc_spawn_icon_polarbear.png", 0) +mcl_mobs.register_egg("mobs_mc:polar_bear", S("Polar Bear"), "#f2f2f2", "#959590", 0) diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 2d7bc5e7e..6d13fbe22 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -15,7 +15,12 @@ local rabbit = { xp_min = 1, xp_max = 3, collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.49, 0.2}, - + head_swivel = "head.control", + bone_eye_height = 2, + head_eye_height = 0.5, + horrizonatal_head_height = -.3, + curiosity = 20, + head_yaw="z", visual = "mesh", mesh = "mobs_mc_rabbit.b3d", textures = { @@ -26,7 +31,6 @@ local rabbit = { {"mobs_mc_rabbit_salt.png"}, {"mobs_mc_rabbit_black.png"}, }, - visual_size = {x=1.5, y=1.5}, sounds = { random = "mobs_mc_rabbit_random", damage = "mobs_mc_rabbit_hurt", @@ -49,10 +53,14 @@ local rabbit = { }, fear_height = 4, animation = { - speed_normal = 25, speed_run = 50, - stand_start = 0, stand_end = 0, - walk_start = 0, walk_end = 20, - run_start = 0, run_end = 20, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 20, walk_speed = 20, + run_start = 0, run_end = 20, run_speed = 30, + }, + child_animations = { + stand_start = 21, stand_end = 21, + walk_start = 21, walk_end = 41, walk_speed = 30, + run_start = 21, run_end = 41, run_speed = 45, }, -- Follow (yellow) dangelions, carrots and golden carrots follow = { @@ -75,7 +83,7 @@ local rabbit = { }, on_rightclick = function(self, clicker) -- Feed, tame protect or capture - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:protect(self, clicker) then return end if mcl_mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end end, @@ -94,7 +102,7 @@ local rabbit = { end, } -mcl_mobs:register_mob("mobs_mc:rabbit", rabbit) +mcl_mobs.register_mob("mobs_mc:rabbit", rabbit) -- The killer bunny (Only with spawn egg) local killer_bunny = table.copy(rabbit) @@ -120,7 +128,7 @@ killer_bunny.do_custom = function(self) end end -mcl_mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) +mcl_mobs.register_mob("mobs_mc:killer_bunny", killer_bunny) -- Mob spawning rules. -- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out @@ -205,7 +213,7 @@ mcl_mobs:spawn(spawn_grass) ]]-- -- Spawn egg -mcl_mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) +mcl_mobs.register_egg("mobs_mc:rabbit", S("Rabbit"), "#995f40", "#734831", 0) -- Note: This spawn egg does not exist in Minecraft -mcl_mobs:register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "mobs_mc_spawn_icon_rabbit.png^[colorize:#FF0000:192", 0) -- TODO: Update inventory image +mcl_mobs.register_egg("mobs_mc:killer_bunny", S("Killer Bunny"), "#f2f2f2", "#ff0000", 0) diff --git a/mods/ENTITIES/mobs_mc/salmon.lua b/mods/ENTITIES/mobs_mc/salmon.lua index e337aef19..f53648244 100644 --- a/mods/ENTITIES/mobs_mc/salmon.lua +++ b/mods/ENTITIES/mobs_mc/salmon.lua @@ -58,7 +58,8 @@ local salmon = { runaway = true, fear_height = 4, on_rightclick = function(self, clicker) - if clicker:get_wielded_item():get_name() == "mcl_buckets:bucket_water" then + local bn = clicker:get_wielded_item():get_name() + if bn == "mcl_buckets:bucket_water" or bn == "mcl_buckets:bucket_river_water" then self.object:remove() clicker:set_wielded_item("mcl_buckets:bucket_salmon") awards.unlock(clicker:get_player_name(), "mcl:tacticalFishing") @@ -66,7 +67,7 @@ local salmon = { end } -mcl_mobs:register_mob("mobs_mc:salmon", salmon) +mcl_mobs.register_mob("mobs_mc:salmon", salmon) --spawning TODO: in schools @@ -225,4 +226,4 @@ water-16, water+1) --spawn egg -mcl_mobs:register_egg("mobs_mc:salmon", S("Salmon"), "extra_mobs_spawn_icon_salmon.png", 0) +mcl_mobs.register_egg("mobs_mc:salmon", S("Salmon"), "#a00f10", "#0e8474", 0) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 7e2027c6c..caa22205b 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -52,7 +52,7 @@ end local gotten_texture = { "blank.png", "mobs_mc_sheep.png" } --mcsheep -mcl_mobs:register_mob("mobs_mc:sheep", { +mcl_mobs.register_mob("mobs_mc:sheep", { description = S("Sheep"), type = "animal", spawn_class = "passive", @@ -61,9 +61,13 @@ mcl_mobs:register_mob("mobs_mc:sheep", { xp_min = 1, xp_max = 3, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45}, - + head_swivel = "head.control", + bone_eye_height = 3.3, + head_eye_height = 1.1, + horrizonatal_head_height=-.7, + curiosity = 6, + head_yaw="z", visual = "mesh", - visual_size = {x=3, y=3}, mesh = "mobs_mc_sheepfur.b3d", textures = { sheep_texture("unicolor_white") }, gotten_texture = gotten_texture, @@ -93,10 +97,14 @@ mcl_mobs:register_mob("mobs_mc:sheep", { distance = 16, }, animation = { - speed_normal = 25, run_speed = 65, - stand_start = 40, stand_end = 80, - walk_start = 0, walk_end = 40, - run_start = 0, run_end = 40, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 30, + run_start = 0, run_end = 40, run_speed = 40, + }, + child_animations = { + stand_start = 81, stand_end = 81, + walk_start = 81, walk_end = 121, walk_speed = 45, + run_start = 81, run_end = 121, run_speed = 60, }, follow = { "mcl_farming:wheat_item" }, view_range = 12, @@ -197,7 +205,7 @@ mcl_mobs:register_mob("mobs_mc:sheep", { on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then return end + if self:feed_tame(clicker, 1, true, false) then return end if mcl_mobs:protect(self, clicker) then return end if item:get_name() == "mcl_tools:shears" and not self.gotten and not self.child then @@ -259,7 +267,7 @@ mcl_mobs:register_mob("mobs_mc:sheep", { on_breed = function(parent1, parent2) -- Breed sheep and choose a fur color for the child. local pos = parent1.object:get_pos() - local child = mcl_mobs:spawn_child(pos, parent1.name) + local child = mcl_mobs.spawn_child(pos, parent1.name) if child then local ent_c = child:get_luaentity() local color1 = parent1.color @@ -357,4 +365,4 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0) +mcl_mobs.register_egg("mobs_mc:sheep", S("Sheep"), "#e7e7e7", "#ffb5b5", 0) diff --git a/mods/ENTITIES/mobs_mc/shulker.lua b/mods/ENTITIES/mobs_mc/shulker.lua index e988a7c73..46737e90f 100644 --- a/mods/ENTITIES/mobs_mc/shulker.lua +++ b/mods/ENTITIES/mobs_mc/shulker.lua @@ -30,7 +30,7 @@ local function check_spot(pos) end local pr = PseudoRandom(os.time()*(-334)) -- animation 45-80 is transition between passive and attack stance -mcl_mobs:register_mob("mobs_mc:shulker", { +mcl_mobs.register_mob("mobs_mc:shulker", { description = S("Shulker"), type = "monster", spawn_class = "hostile", @@ -83,10 +83,10 @@ mcl_mobs:register_mob("mobs_mc:shulker", { end if self.state == "walk" or self.state == "stand" then self.state = "stand" - mcl_mobs:set_animation(self, "stand") + self:set_animation("stand") end if self.state == "attack" then - mcl_mobs:set_animation(self, "punch") + self:set_animation("punch") end self.path.way = false self.look_at_players = false @@ -134,7 +134,7 @@ mcl_mobs:register_mob("mobs_mc:shulker", { for n=1, math.min(8, #nodes) do local r = pr:next(1, #nodes) local nodepos = nodes[r] - local tg = vector.offset(nodepos,0,1,0) + local tg = vector.offset(nodepos,0,0.5,0) if check_spot(tg) then self.object:set_pos(tg) node_ok = true @@ -152,7 +152,7 @@ mcl_mobs:register_mob("mobs_mc:shulker", { }) -- bullet arrow (weapon) -mcl_mobs:register_arrow("mobs_mc:shulkerbullet", { +mcl_mobs.register_arrow("mobs_mc:shulkerbullet", { visual = "sprite", visual_size = {x = 0.25, y = 0.25}, textures = {"mobs_mc_shulkerbullet.png"}, @@ -177,7 +177,8 @@ mcl_mobs:register_arrow("mobs_mc:shulkerbullet", { }) -mcl_mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0) +mcl_mobs.register_egg("mobs_mc:shulker", S("Shulker"), "#946694", "#4d3852", 0) + --[[ mcl_mobs:spawn_specific( "mobs_mc:shulker", diff --git a/mods/ENTITIES/mobs_mc/silverfish.lua b/mods/ENTITIES/mobs_mc/silverfish.lua index 857c9326e..e0bcc23aa 100644 --- a/mods/ENTITIES/mobs_mc/silverfish.lua +++ b/mods/ENTITIES/mobs_mc/silverfish.lua @@ -4,7 +4,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:silverfish", { +mcl_mobs.register_mob("mobs_mc:silverfish", { description = S("Silverfish"), type = "monster", spawn_class = "hostile", @@ -23,7 +23,7 @@ mcl_mobs:register_mob("mobs_mc:silverfish", { {"mobs_mc_silverfish.png"}, }, pathfinding = 1, - visual_size = {x=3, y=3}, + visual_size = {x = 3, y = 3}, sounds = { random = "mobs_mc_silverfish_idle", death = "mobs_mc_silverfish_death", @@ -45,96 +45,14 @@ mcl_mobs:register_mob("mobs_mc:silverfish", { }, replace_rate = 2, animation = { - speed_normal = 25, speed_run = 50, - stand_start = 0, stand_end = 20, - walk_start = 0, walk_end = 20, - run_start = 0, run_end = 20, + speed_normal = 25, speed_run = 50, + stand_start = 0, stand_end = 20, + walk_start = 0, walk_end = 20, + run_start = 0, run_end = 20, }, view_range = 16, attack_type = "dogfight", damage = 1, - reach = 1, }) -mcl_mobs:register_egg("mobs_mc:silverfish", S("Silverfish"), "mobs_mc_spawn_icon_silverfish.png", 0) - --- Monster egg blocks (Minetest Game) -if minetest.get_modpath("default") and mobs_mc.create_monster_egg_nodes then - local spawn_silverfish = function(pos, oldnode, oldmetadata, digger) - if not minetest.is_creative_enabled(digger:get_player_name()) then - minetest.add_entity(pos, "mobs_mc:silverfish") - end - end - minetest.register_node("mobs_mc:monster_egg_stone", { - description = "Stone Monster Egg", - tiles = {"default_stone.png"}, - groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = '', - is_ground_content = true, - sounds = default.node_sound_stone_defaults(), - after_dig_node = spawn_silverfish, - }) - - minetest.register_node("mobs_mc:monster_egg_cobble", { - description = "Cobblestone Monster Egg", - tiles = {"default_cobble.png"}, - is_ground_content = false, - groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = '', - sounds = default.node_sound_stone_defaults(), - after_dig_node = spawn_silverfish, - }) - - minetest.register_node("mobs_mc:monster_egg_mossycobble", { - description = "Mossy Cobblestone Monster Egg", - tiles = {"default_mossycobble.png"}, - is_ground_content = false, - groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = '', - sounds = default.node_sound_stone_defaults(), - after_dig_node = spawn_silverfish, - }) - - minetest.register_node("mobs_mc:monster_egg_stonebrick", { - description = "Stone Brick Monster Egg", - paramtype2 = "facedir", - place_param2 = 0, - tiles = {"default_stone_brick.png"}, - is_ground_content = false, - groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = '', - sounds = default.node_sound_stone_defaults(), - after_dig_node = spawn_silverfish, - }) - - minetest.register_node("mobs_mc:monster_egg_stone_block", { - description = "Stone Block Monster Egg", - tiles = {"default_stone_block.png"}, - is_ground_content = false, - groups = {oddly_breakable_by_hand = 2, spawns_silverfish = 1}, - drop = '', - sounds = default.node_sound_stone_defaults(), - after_dig_node = spawn_silverfish, - }) - - -- Randomly spawn stone monster eggs in the world - local mg_name = minetest.get_mapgen_setting("mg_name") - local scarcity - if mg_name == "v6" then - scarcity = 28 * 28 * 28 - else - scarcity = 22 * 22 * 22 - end - minetest.register_ore({ - ore_type = "scatter", - ore = "mobs_mc:monster_egg_stone", - wherein = "default:stone", - clust_scarcity = scarcity, - clust_num_ores = 3, - clust_size = 2, - y_min = -31000, - y_max = 31000, - biomes = { "grassland" }, - }) - -end +mcl_mobs.register_egg("mobs_mc:silverfish", S("Silverfish"), "#6d6d6d", "#313131", 0) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index fbf16961a..ca2fe25fa 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -25,13 +25,17 @@ local skeleton = { collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, pathfinding = 1, group_attack = true, + head_swivel = "Head_Control", + bone_eye_height = 2.38, + curiosity = 6, visual = "mesh", mesh = "mobs_mc_skeleton.b3d", + shooter_avoid_enemy = true, + strafes = true, textures = { { "mcl_bows_bow_0.png", -- bow "mobs_mc_skeleton.png", -- skeleton } }, - visual_size = {x=1, y=1}, makes_footstep_sound = true, textures = { { @@ -78,11 +82,31 @@ local skeleton = { run_speed = 30, shoot_start = 70, shoot_end = 90, + jockey_start = 172, + jockey_end = 172, die_start = 160, die_end = 170, die_speed = 15, die_loop = false, }, + jock = "mobs_mc:spider", + on_spawn = function(self) + minetest.after(1,function() + if self and self.object then + if math.random(100) == 1 or self.jockey == true then -- 1% like from MCwiki + self.jockey = true + local jock = minetest.add_entity(self.object:get_pos(), "mobs_mc:spider") + jock:get_luaentity().docile_by_day = false + self.object:set_attach(jock, "", vector.new(0,0,0), vector.new(0,0,0)) + end + self.jockey = false + return true + end + end) + end, + on_detach=function(self, parent) + self.jockey = false + end, ignited_by_sunlight = true, view_range = 16, fear_height = 4, @@ -90,6 +114,9 @@ local skeleton = { arrow = "mcl_bows:arrow_entity", shoot_arrow = function(self, pos, dir) if mod_bows then + if self.attack then + self.object:set_yaw(minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.attack:get_pos()))) + end -- 2-4 damage per arrow local dmg = math.max(4, math.random(2, 8)) mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) @@ -102,7 +129,7 @@ local skeleton = { harmed_by_heal = true, } -mcl_mobs:register_mob("mobs_mc:skeleton", skeleton) +mcl_mobs.register_mob("mobs_mc:skeleton", skeleton) --################### @@ -139,7 +166,7 @@ table.insert(stray.drops, { end, }) -mcl_mobs:register_mob("mobs_mc:stray", stray) +mcl_mobs.register_mob("mobs_mc:stray", stray) -- Overworld spawn mcl_mobs:spawn_specific( @@ -329,5 +356,6 @@ mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:skeleton", S("Skeleton"), "mobs_mc_spawn_icon_skeleton.png", 0) -mcl_mobs:register_egg("mobs_mc:stray", S("Stray"), "mobs_mc_spawn_icon_stray.png", 0) +mcl_mobs.register_egg("mobs_mc:skeleton", S("Skeleton"), "#c1c1c1", "#494949", 0) + +mcl_mobs.register_egg("mobs_mc:stray", S("Stray"), "#5f7476", "#dae8e7", 0) diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index 040f22d66..94fa78120 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -9,7 +9,7 @@ local S = minetest.get_translator("mobs_mc") --################### WITHER SKELETON --################### -mcl_mobs:register_mob("mobs_mc:witherskeleton", { +mcl_mobs.register_mob("mobs_mc:witherskeleton", { description = S("Wither Skeleton"), type = "monster", spawn_class = "hostile", @@ -24,11 +24,14 @@ mcl_mobs:register_mob("mobs_mc:witherskeleton", { collisionbox = {-0.35, -0.01, -0.35, 0.35, 2.39, 0.35}, visual = "mesh", mesh = "mobs_mc_witherskeleton.b3d", + head_swivel = "head.control", + bone_eye_height = 2.38, + curiosity = 60, textures = { { "mobs_mc_empty.png", -- armor - "mobs_mc_wither_skeleton.png", -- wither skeleton "default_tool_stonesword.png", -- sword + "mobs_mc_wither_skeleton.png", -- wither skeleton } }, visual_size = {x=1.2, y=1.2}, @@ -96,6 +99,7 @@ mcl_mobs:register_mob("mobs_mc:witherskeleton", { }) --spawn +--[[] mcl_mobs:spawn_specific( "mobs_mc:witherskeleton", "nether", @@ -111,6 +115,6 @@ mcl_mobs:spawn_specific( 5, mcl_vars.mg_nether_min, mcl_vars.mg_nether_max) - +--]] -- spawn eggs -mcl_mobs:register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "mobs_mc_spawn_icon_witherskeleton.png", 0) +mcl_mobs.register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "#141414", "#474d4d", 0) diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 701ae852a..c6de471e3 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -109,7 +109,7 @@ local slime_big = { on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5), use_texture_alpha = true, } -mcl_mobs:register_mob("mobs_mc:slime_big", slime_big) +mcl_mobs.register_mob("mobs_mc:slime_big", slime_big) local slime_small = table.copy(slime_big) slime_small.sounds.base_pitch = 1.15 @@ -126,7 +126,7 @@ slime_small.run_velocity = 1.3 slime_small.jump_height = 4.3 slime_small.spawn_small_alternative = "mobs_mc:slime_tiny" slime_small.on_die = spawn_children_on_die("mobs_mc:slime_tiny", 4, 0.6, 1.0) -mcl_mobs:register_mob("mobs_mc:slime_small", slime_small) +mcl_mobs.register_mob("mobs_mc:slime_small", slime_small) local slime_tiny = table.copy(slime_big) slime_tiny.sounds.base_pitch = 1.3 @@ -151,7 +151,7 @@ slime_tiny.jump_height = 3 slime_tiny.spawn_small_alternative = nil slime_tiny.on_die = nil -mcl_mobs:register_mob("mobs_mc:slime_tiny", slime_tiny) +mcl_mobs.register_mob("mobs_mc:slime_tiny", slime_tiny) local smin = mcl_vars.mg_overworld_min local smax = mobs_mc.water_level - 23 @@ -348,7 +348,7 @@ local magma_cube_big = { on_die = spawn_children_on_die("mobs_mc:magma_cube_small", 3, 0.8, 1.5), fire_resistant = true, } -mcl_mobs:register_mob("mobs_mc:magma_cube_big", magma_cube_big) +mcl_mobs.register_mob("mobs_mc:magma_cube_big", magma_cube_big) local magma_cube_small = table.copy(magma_cube_big) magma_cube_small.sounds.jump = "mobs_mc_magma_cube_small" @@ -369,7 +369,7 @@ magma_cube_small.reach = 2.75 magma_cube_small.armor = 66 magma_cube_small.spawn_small_alternative = "mobs_mc:magma_cube_tiny" magma_cube_small.on_die = spawn_children_on_die("mobs_mc:magma_cube_tiny", 4, 0.6, 1.0) -mcl_mobs:register_mob("mobs_mc:magma_cube_small", magma_cube_small) +mcl_mobs.register_mob("mobs_mc:magma_cube_small", magma_cube_small) local magma_cube_tiny = table.copy(magma_cube_big) magma_cube_tiny.sounds.jump = "mobs_mc_magma_cube_small" @@ -391,7 +391,7 @@ magma_cube_tiny.drops = {} magma_cube_tiny.spawn_small_alternative = nil magma_cube_tiny.on_die = nil -mcl_mobs:register_mob("mobs_mc:magma_cube_tiny", magma_cube_tiny) +mcl_mobs.register_mob("mobs_mc:magma_cube_tiny", magma_cube_tiny) local mmin = mcl_vars.mg_nether_min @@ -447,5 +447,6 @@ mmin, mmax) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:magma_cube_big", S("Magma Cube"), "mobs_mc_spawn_icon_magmacube.png") -mcl_mobs:register_egg("mobs_mc:slime_big", S("Slime"), "mobs_mc_spawn_icon_slime.png") +mcl_mobs.register_egg("mobs_mc:magma_cube_big", S("Magma Cube"), "#350000", "#fcfc00") + +mcl_mobs.register_egg("mobs_mc:slime_big", S("Slime"), "#52a03e", "#7ebf6d") diff --git a/mods/ENTITIES/mobs_mc/snowman.lua b/mods/ENTITIES/mobs_mc/snowman.lua index 816c96947..f9f0043c2 100644 --- a/mods/ENTITIES/mobs_mc/snowman.lua +++ b/mods/ENTITIES/mobs_mc/snowman.lua @@ -20,7 +20,7 @@ local gotten_texture = { "blank.png", } -mcl_mobs:register_mob("mobs_mc:snowman", { +mcl_mobs.register_mob("mobs_mc:snowman", { description = S("Snow Golem"), type = "npc", spawn_class = "passive", @@ -196,4 +196,4 @@ function mobs_mc.check_snow_golem_summon(pos) end -- Spawn egg -mcl_mobs:register_egg("mobs_mc:snowman", S("Snow Golem"), "mobs_mc_spawn_icon_snowman.png", 0) +mcl_mobs.register_egg("mobs_mc:snowman", S("Snow Golem"), "#f2f2f2", "#fd8f47", 0) diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl1.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl1.ogg new file mode 100644 index 000000000..b3d9c5967 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl1.ogg differ diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl2.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl2.ogg new file mode 100644 index 000000000..11141f6cc Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl2.ogg differ diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl_hurt.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl_hurt.ogg new file mode 100644 index 000000000..dddf298b6 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_axolotl_hurt.ogg differ diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index b39db1ea1..403edba6d 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -11,6 +11,23 @@ local S = minetest.get_translator("mobs_mc") -- Spider by AspireMint (fishyWET (CC-BY-SA 3.0 license for texture) +minetest.register_entity("mobs_mc:spider_eyes", { + pointable = false, + visual = "mesh", + mesh = "mobs_mc_spider.b3d", + visual_size = {x=1.01/3, y=1.01/3}, + textures = { + "mobs_mc_spider_eyes.png", + }, + on_step = function(self) + if self and self.object then + if not self.object:get_attach() then + self.object:remove() + end + end + end, + glow = 50, +}) local spider = { description = S("Spider"), @@ -27,13 +44,38 @@ local spider = { xp_min = 5, xp_max = 5, armor = {fleshy = 100, arthropod = 100}, + on_spawn = function(self) + self.object:set_properties({visual_size={x=1,y=1}}) + local spider_eyes=false + for n = 1, #self.object:get_children() do + local obj = self.object:get_children()[n] + if obj:get_luaentity() and self.object:get_luaentity().name == "mobs_mc:spider_eyes" then + spider_eyes = true + end + end + if not spider_eyes then + minetest.add_entity(self.object:get_pos(), "mobs_mc:spider_eyes"):set_attach(self.object, "body.head", vector.new(0,-0.98,2), vector.new(90,180,180)) + end + end, + on_die=function(self) + if self.object:get_children() and self.object:get_children()[1] then + self.object:get_children()[1]:set_detach() + end + end, + detach_child=function(self, child) + child:get_luaentity().jockey = false + end, + head_swivel = "Head_Control", + bone_eye_height = 1, + curiosity = 10, + head_yaw="z", collisionbox = {-0.7, -0.01, -0.7, 0.7, 0.89, 0.7}, visual = "mesh", mesh = "mobs_mc_spider.b3d", textures = { - {"mobs_mc_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"}, + {"mobs_mc_spider.png"}, }, - visual_size = {x=3, y=3}, + visual_size = {x=1, y=1}, makes_footstep_sound = false, sounds = { random = "mobs_mc_spider_random", @@ -69,7 +111,7 @@ local spider = { run_end = 20, }, } -mcl_mobs:register_mob("mobs_mc:spider", spider) +mcl_mobs.register_mob("mobs_mc:spider", spider) -- Cave spider local cave_spider = table.copy(spider) @@ -80,13 +122,26 @@ cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[mak cave_spider.damage = 3 -- damage increased to undo non-existing poison cave_spider.hp_min = 1 cave_spider.hp_max = 12 -cave_spider.collisionbox = {-0.35, -0.01, -0.35, 0.35, 0.49, 0.35} -cave_spider.visual_size = {x=1.66666, y=1.5} +cave_spider.collisionbox = {-0.35, -0.01, -0.35, 0.35, 0.46, 0.35} +cave_spider.visual_size = {x=0.55,y=0.5} +cave_spider.on_spawn = function(self) + self.object:set_properties({visual_size={x=0.55,y=0.5}}) + local spider_eyes=false + for n = 1, #self.object:get_children() do + local obj = self.object:get_children()[n] + if obj:get_luaentity() and self.object:get_luaentity().name == "mobs_mc:spider_eyes" then + spider_eyes = true + end + end + if not spider_eyes then + minetest.add_entity(self.object:get_pos(), "mobs_mc:spider_eyes"):set_attach(self.object, "body.head", vector.new(0,-0.98,2), vector.new(90,180,180)) + end +end cave_spider.walk_velocity = 1.3 cave_spider.run_velocity = 3.2 cave_spider.sounds = table.copy(spider.sounds) cave_spider.sounds.base_pitch = 1.25 -mcl_mobs:register_mob("mobs_mc:cave_spider", cave_spider) +mcl_mobs.register_mob("mobs_mc:cave_spider", cave_spider) mcl_mobs:spawn_specific( @@ -238,5 +293,5 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:spider", S("Spider"), "mobs_mc_spawn_icon_spider.png", 0) -mcl_mobs:register_egg("mobs_mc:cave_spider", S("Cave Spider"), "mobs_mc_spawn_icon_cave_spider.png", 0) +mcl_mobs.register_egg("mobs_mc:spider", S("Spider"), "#342d26", "#a80e0e", 0) +mcl_mobs.register_egg("mobs_mc:cave_spider", S("Cave Spider"), "#0c424e", "#a80e0e", 0) diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index 86b80976e..72f6702a5 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -6,7 +6,7 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:squid", { +mcl_mobs.register_mob("mobs_mc:squid", { description = S("Squid"), type = "animal", spawn_class = "water", @@ -217,4 +217,4 @@ water-16, water+1) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:squid", S("Squid"), "mobs_mc_spawn_icon_squid.png", 0) +mcl_mobs.register_egg("mobs_mc:squid", S("Squid"), "#223b4d", "#708999", 0) diff --git a/mods/ENTITIES/mobs_mc/strider.lua b/mods/ENTITIES/mobs_mc/strider.lua new file mode 100644 index 000000000..a49845f7e --- /dev/null +++ b/mods/ENTITIES/mobs_mc/strider.lua @@ -0,0 +1,248 @@ +--MCmobs v0.4 +--maikerumine +--made for MC like Survival game +--License for code WTFPL and otherwise stated in readmes + +local S = minetest.get_translator("mobs_mc") + +--################### +--################### STRIDER +--################### + + +local strider = { + type = "animal", + passive = true, + spawn_class = "passive", + hp_min = 20, + hp_max = 20, + xp_min = 9, + xp_max = 9, + armor = {fleshy = 90}, + attack_type = "dogfight", + damage = 2, + reach = 2, + collisionbox = {-.6, -0.01, -.6, .6, 1.94, .6}, + visual = "mesh", + mesh = "extra_mobs_strider.b3d", + textures = { { + "extra_mobs_strider.png", + } }, + visual_size = {x=3, y=3}, + sounds = { + }, + jump = true, + makes_footstep_sound = true, + walk_velocity = 2, + run_velocity = 4, + runaway = true, + drops = { + {name = "mcl_mobsitems:string", + chance = 1, + min = 2, + max = 5,}, + }, + animation = { + stand_speed = 15, + walk_speed = 15, + run_speed = 30, + stand_start = 5, + stand_end = 5, + walk_start = 1, + walk_end = 20, + }, + lava_damage = 0, + fire_damage = 0, + light_damage = 0, + water_damage = 5, + fear_height = 4, + view_range = 16, + fire_resistant = true, + floats_on_lava = 1, + floats = 0, + can_spawn = function(pos) + local l = minetest.find_node_near(pos,2,{"mcl_nether:nether_lava_source","mcl_nether:nether_lava_flowing"}) + return l ~= nil + end, + do_custom = function(self, dtime) + + if minetest.find_node_near(self.object:get_pos(), 2, {"mcl_core:lava_source","mcl_core:lava_flowing","mcl_nether:nether_lava_source","mcl_nether:nether_lava_flowing"}) then + self.walk_velocity = 2 + self.run_velocity = 4 + self.base_texture[1] = "extra_mobs_strider.png" + self.shaking = false + else + self.base_texture[1] = "extra_mobs_strider_cold.png" + self.walk_velocity = .5 + self.run_velocity = 1 + self.shaking = true + end + + self.object:set_properties({textures=self.base_texture, shaking=self.shaking, run_velocity=self.run_velocity, walk_velocity=self.walk_velocity}) + + -- set needed values if not already present + if not self.v2 then + self.v2 = 0 + self.max_speed_forward = 8 + self.max_speed_reverse = 4 + self.accel = 2 + self.terrain_type = 3 + self.driver_attach_at = {x = 0, y = 5.5, z = -1.75} + self.driver_eye_offset = {x = 0, y = 10, z = 0} + self.driver_scale = {x = 1/self.visual_size.x, y = 1/self.visual_size.y} + end + + -- if driver present allow control of horse + if self.driver then + local pos = self.object:get_pos() + local v = self.object:get_velocity() + self.object:set_velocity(vector.new(v.x,0,v.z)) + mcl_mobs.drive(self, "walk", "stand", false, dtime) + local l = minetest.find_node_near(pos,2,{"group:lava"}) + if l then self.object:set_pos(vector.new(pos.x,l.y+0.5,pos.z)) end + return false -- skip rest of mob functions + end + + return true + end, + + on_die = function(self, pos) + + -- drop saddle when horse is killed while riding + -- also detach from horse properly + if self.driver then + mcl_mobs.detach(self.driver, {x = 1, y = 0, z = 1}) + end + end, + + on_rightclick = function(self, clicker) + if not clicker or not clicker:is_player() then + return + end + + local wielditem = clicker:get_wielded_item() + + if wielditem:get_name() ~= "mcl_crimson:warped_fungus" then + if self:feed_tame(clicker, 1, true, true) then return end + end + + if self.child then + return + end + + local item = clicker:get_wielded_item() + if item:get_name() == "mcl_mobitems:saddle" and self.saddle ~= "yes" then + self.base_texture = { + "extra_mobs_strider.png", + "mobs_mc_pig_saddle.png", -- saddle + } + self.object:set_properties({ + textures = self.base_texture + }) + self.saddle = "yes" + self.tamed = true + self.drops = { + {name = "mcl_mobitems:string", + chance = 1, + min = 1, + max = 3,}, + {name = "mcl_mobitems:saddle", + chance = 1, + min = 1, + max = 1,}, + } + if not minetest.is_creative_enabled(clicker:get_player_name()) then + wielditem:take_item(1) + clicker:get_inventory():set_stack("main", clicker:get_wield_index(), wielditem) + end + minetest.sound_play({name = "mcl_armor_equip_leather"}, {gain=0.5, max_hear_distance=8, pos=self.object:get_pos()}, true) + return + end + + -- Mount or detach player + local name = clicker:get_player_name() + if self.driver and clicker == self.driver then + -- Detach if already attached + mcl_mobs.detach(clicker, {x=1, y=0, z=0}) + return + + elseif not self.driver and self.saddle == "yes" and wielditem:get_name() == "mcl_mobitems:warped_fungus_on_a_stick" then + -- Ride pig if it has a saddle and player uses a carrot on a stick + + mcl_mobs.attach(self, clicker) + + if not minetest.is_creative_enabled(clicker:get_player_name()) then + + local inv = self.driver:get_inventory() + -- 26 uses + if wielditem:get_wear() > 63000 then + -- Break carrot on a stick + local def = wielditem:get_definition() + if def.sounds and def.sounds.breaks then + minetest.sound_play(def.sounds.breaks, {pos = clicker:get_pos(), max_hear_distance = 8, gain = 0.5}, true) + end + wielditem = {name = mobs_mc.items.fishing_rod, count = 1} + else + wielditem:add_wear(2521) + end + inv:set_stack("main",self.driver:get_wield_index(), wielditem) + end + return + end + end, +} + +mcl_mobs.register_mob("mobs_mc:strider", strider) + +-- Baby strider. + +local baby_strider = table.copy(strider) +baby_strider.collisionbox = {-.3, -0.01, -.3, .3, 0.94, .3} +baby_strider.xp_min = 13 +baby_strider.xp_max = 13 +textures = { { + "extra_mobs_strider.png", + "extra_mobs_trans.png", +} } +baby_strider.walk_velocity = 1.2 +baby_strider.run_velocity = 2.4 +baby_strider.child = 1 + +mcl_mobs.register_mob("mobs_mc:baby_strider", baby_strider) + +-- Regular spawning in the Nether + +mcl_mobs:spawn_setup({ + name = "mobs_mc:strider", + type_of_spawning = "lava", + dimension = "nether", + biomes = { + "Nether", + "BasaltDelta", + "WarpedForest", + "CrimsonForest", + "SoulsandValley" + }, + min_height = mcl_vars.mg_nether_min, + max_height = mcl_vars.mg_nether_max, + chance = 2000, +}) + +mcl_mobs:spawn_setup({ + name = "mobs_mc:baby_strider", + type_of_spawning = "lava", + dimension = "nether", + biomes = { + "Nether", + "BasaltDelta", + "WarpedForest", + "CrimsonForest", + "SoulsandValley" + }, + min_height = mcl_vars.mg_nether_min, + max_height = mcl_vars.mg_nether_max, + chance = 100, +}) + +-- spawn eggs +mcl_mobs.register_egg("mobs_mc:strider", S("Strider"), "#000000", "#FF0000", 0) diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_cod.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_cod.png index ce6f6dea9..0da300c6e 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_cod.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_cod.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid.png new file mode 100644 index 000000000..ccbdb9707 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint1.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint1.png new file mode 100644 index 000000000..2ed9a013c Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint1.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint2.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint2.png new file mode 100644 index 000000000..deed54099 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint2.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint3.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint3.png new file mode 100644 index 000000000..e0fe8919a Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint3.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint4.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint4.png new file mode 100644 index 000000000..966589fa8 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_glow_squid_glint4.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_hoglin.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_hoglin.png new file mode 100644 index 000000000..c85d6a25b Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_hoglin.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin.png new file mode 100644 index 000000000..c38606550 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin_brute.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin_brute.png new file mode 100644 index 000000000..4a757e61e Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_piglin_brute.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_salmon.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_salmon.png index ed62d950b..5ce4d6cc3 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_salmon.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_salmon.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_tropical_fish.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_tropical_fish.png deleted file mode 100644 index 48dd8f986..000000000 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_tropical_fish.png and /dev/null differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider.png new file mode 100644 index 000000000..5039afe36 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider_cold.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider_cold.png new file mode 100644 index 000000000..ecf6bbb90 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_strider_cold.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_a.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_a.png index 7d90a3e33..3f9abe3dc 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_a.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_a.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_b.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_b.png index d6471addc..587ada083 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_b.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_b.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_1.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_1.png index be50aa837..89787fcce 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_1.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_1.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_2.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_2.png index 05a555836..1403e277c 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_2.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_2.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_3.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_3.png index 0894fc226..a1a7cfd88 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_3.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_3.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_4.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_4.png index c43b4c8fc..417ba86cf 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_4.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_4.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_5.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_5.png index 0f81fbb72..63ec19567 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_5.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_5.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_6.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_6.png index f0deaf7c2..0b2ce4f71 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_6.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_a_6.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_1.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_1.png index 783f6b702..f33aaa803 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_1.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_1.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_2.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_2.png index 913776284..1834146bb 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_2.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_2.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_3.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_3.png index bd5f3f2e9..4878e813a 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_3.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_3.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_4.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_4.png index cab054aac..9a4315be6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_4.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_4.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_5.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_5.png index 31789172f..6288da9a5 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_5.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_5.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_6.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_6.png index 87afb666b..ea82ed883 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_6.png and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_tropical_fish_pattern_b_6.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_zoglin.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_zoglin.png new file mode 100644 index 000000000..6f5367550 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_zoglin.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_zombified_piglin.png b/mods/ENTITIES/mobs_mc/textures/extra_mobs_zombified_piglin.png new file mode 100644 index 000000000..358c22bc3 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/extra_mobs_zombified_piglin.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_chicken_egg.png b/mods/ENTITIES/mobs_mc/textures/mobs_chicken_egg.png index 9c6545452..346dac7ab 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_chicken_egg.png and b/mods/ENTITIES/mobs_mc/textures/mobs_chicken_egg.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_TEMP_wither_projectile.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_TEMP_wither_projectile.png index df8b24c12..d9ddd9bba 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_TEMP_wither_projectile.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_TEMP_wither_projectile.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_arrow_particle.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_arrow_particle.png index 1d0cd9b1c..b7105877c 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_arrow_particle.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_arrow_particle.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_black.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_black.png new file mode 100644 index 000000000..8f13938f8 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_black.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_brown.png new file mode 100644 index 000000000..b90ba3c88 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_green.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_green.png new file mode 100644 index 000000000..4dca4fdf5 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_green.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_pink.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_pink.png new file mode 100644 index 000000000..193a8e087 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_pink.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_purple.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_purple.png new file mode 100644 index 000000000..bd7f67c6f Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_purple.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_white.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_white.png new file mode 100644 index 000000000..15b3ba43d Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_white.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_yellow.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_yellow.png new file mode 100644 index 000000000..6b3fd6157 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_axolotl_yellow.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_cat_black.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_cat_black.png index 8d1322565..02e84f3db 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_cat_black.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_cat_black.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_chicken.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_chicken.png index b9d69278e..a9e516c6b 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_chicken.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_chicken.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_creeper_charge.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_creeper_charge.png index a5e8ab443..f80392bc0 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_creeper_charge.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_creeper_charge.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_diamond.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_diamond.png new file mode 100644 index 000000000..32f0c05f3 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_diamond.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_donkey.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_donkey.png index e3f04ffd3..549d4d5ce 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_donkey.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_donkey.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_dragon_fireball.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_dragon_fireball.png index 69e643b13..77a282727 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_dragon_fireball.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_dragon_fireball.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_emerald.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_emerald.png new file mode 100644 index 000000000..bdb1ef667 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_emerald.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_empty.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_empty.png index 809f22b69..4c3d3ea87 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_empty.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_empty.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_enderman_cactus_background.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_enderman_cactus_background.png index e2f7ad9a2..576684878 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_enderman_cactus_background.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_enderman_cactus_background.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_evoker.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_evoker.png index eec707c5c..af793b59b 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_evoker.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_evoker.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast.png index dc2addc1d..d3c14bbcc 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png index 3e5b41c32..9516fa0ed 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_ghast_firing.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_gold.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_gold.png new file mode 100644 index 000000000..e136dad54 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_gold.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_black.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_black.png index 91159c9d8..a1b3f7aae 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_black.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_black.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_brown.png index 2d1733af9..9024f9564 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_brown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_chestnut.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_chestnut.png index ef051a009..1a39e0bbf 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_chestnut.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_chestnut.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_darkbrown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_darkbrown.png index 5fa6dd45a..8298d8047 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_darkbrown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_darkbrown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_gray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_gray.png index fb6c1c6b6..733ca4e2a 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_gray.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_gray.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_skeleton.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_skeleton.png index 615eb67a8..922090afc 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_skeleton.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_skeleton.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_white.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_white.png index 264fffd26..dc8df13c6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_white.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_white.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_zombie.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_zombie.png new file mode 100644 index 000000000..b6f3522f3 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_horse_zombie.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_illusionist.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_illusionist.png index e6a0f86a6..f6be747d4 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_illusionist.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_illusionist.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_iron.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_iron.png new file mode 100644 index 000000000..8573938f3 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_iron.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama.png index 4a08544cf..2fba8db66 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_brown.png index 6cf366deb..b0e830f94 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_brown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_creamy.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_creamy.png index e1df4612f..fae25c341 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_creamy.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_creamy.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_black.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_black.png index 9a06b5871..e380a6bd6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_black.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_black.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_blue.png index 74db6eb32..b15cdf11f 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_blue.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_blue.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png index 3ed90ca0d..b879f18e2 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png index b66df4571..c41324867 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_cyan.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png index b74dd86af..d850c7ec8 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_gray.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png index e956a3023..c0ffc074d 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_green.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png index 6c3b2a795..025c923be 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_blue.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png index 33b9376dd..715b954d4 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_light_gray.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png index f201bc4fa..4ac62011b 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_lime.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png index d05057fbb..cba899ca1 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_magenta.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png index a261eada2..42fe00c8a 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_orange.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png index 108aab155..fe5296db4 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_pink.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png index 3b3e472ce..ede94f98e 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_purple.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png index 18b9fbcff..09b419194 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_red.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png index b70b55419..94852fac4 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_white.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png index 50962e99d..e082fe7b5 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_llama_decor_yellow.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mooshroom_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mooshroom_brown.png index 115416a53..c274c2fa6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mooshroom_brown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mooshroom_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mule.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mule.png index 328018f5d..98ab5d45f 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mule.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mule.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_brown.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_brown.png index fac0f56ef..84e8c89b5 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_brown.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_brown.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_red.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_red.png index 8c22bd62a..391392f20 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_red.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_mushroom_red.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_blue.png index 9181de260..e8b44a9ef 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_blue.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_blue.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_green.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_green.png index 152acb8f4..63cdc02af 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_green.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_green.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_grey.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_grey.png index ce723561c..d621282cc 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_grey.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_grey.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_red_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_red_blue.png index 2f14ef1a5..2d61a8371 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_red_blue.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_red_blue.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_yellow_blue.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_yellow_blue.png index f35adfd02..bc6ab8525 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_yellow_blue.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_parrot_yellow_blue.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png index b46f16e1b..1fe768ac1 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep.png index 13496a3c5..6fdd83197 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep_fur.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep_fur.png index fa447031d..1763f4f6f 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep_fur.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_sheep_fur.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_silverfish.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_silverfish.png index 956af9ce7..d1af41064 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_silverfish.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_silverfish.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_slime.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_slime.png index 5a30e16fd..eb45eec10 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_slime.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_slime.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_bat.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_bat.png index 9720b7679..820b58dac 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_bat.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_bat.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_blaze.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_blaze.png index aaa8de0ae..94a5014fb 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_blaze.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_blaze.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cat.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cat.png index 3f975c19d..123ffc337 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cat.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cat.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cave_spider.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cave_spider.png index dea6dc92b..d5f453de8 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cave_spider.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cave_spider.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_chicken.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_chicken.png index 58fc64136..70717aed3 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_chicken.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_chicken.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cod.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cod.png new file mode 100644 index 000000000..e82b889d2 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cod.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cow.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cow.png index ac3e7a2d1..619547a4b 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cow.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_cow.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_creeper.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_creeper.png index 99b766881..51477b201 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_creeper.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_creeper.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_donkey.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_donkey.png index 10bd751fb..a3ed2c9b1 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_donkey.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_donkey.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_dragon.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_dragon.png index 5519d4de7..7f7558241 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_dragon.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_dragon.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_enderman.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_enderman.png index 36983ce33..da9ad3555 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_enderman.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_enderman.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_endermite.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_endermite.png index f2d3b4065..8e0fdba94 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_endermite.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_endermite.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_evoker.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_evoker.png index c6aec4f43..01908a557 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_evoker.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_evoker.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_ghast.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_ghast.png index 3c0422cae..ed3370dec 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_ghast.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_ghast.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian.png index 10bcbcffb..019a9dee8 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian_elder.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian_elder.png index fac4ac819..a524502b0 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian_elder.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_guardian_elder.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse.png index 38d88e8b6..17b2460f7 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_skeleton.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_skeleton.png index bea0c518d..0f11de7c9 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_skeleton.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_skeleton.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_zombie.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_zombie.png index ab981289b..9c7db2249 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_zombie.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_horse_zombie.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_husk.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_husk.png index 48945d89e..7d1b75769 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_husk.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_husk.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_illusioner.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_illusioner.png index 7b9dc99e3..953e90f44 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_illusioner.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_illusioner.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_iron_golem.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_iron_golem.png index 6de2cccb9..f0b1cf745 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_iron_golem.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_iron_golem.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_killer_bunny.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_killer_bunny.png new file mode 100644 index 000000000..51dbdaa7c Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_killer_bunny.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_llama.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_llama.png index f3daba200..752c9a570 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_llama.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_llama.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_magmacube.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_magmacube.png index 9c38e1b38..5d6d58d3f 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_magmacube.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_magmacube.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mooshroom.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mooshroom.png index 552b70389..2fc8300f6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mooshroom.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mooshroom.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mule.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mule.png index 741df99f3..4086a361d 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mule.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_mule.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_parrot.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_parrot.png index b52c390f7..a9a2895f8 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_parrot.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_parrot.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pig.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pig.png index 692d1714d..c431de73b 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pig.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pig.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png deleted file mode 100644 index 67dbfe418..000000000 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png and /dev/null differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_polarbear.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_polarbear.png index 7570cacc8..b287317d3 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_polarbear.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_polarbear.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit.png index 1c77e4199..9382accbf 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_rabbit.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_salmon.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_salmon.png new file mode 100644 index 000000000..a4b80e757 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_salmon.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_sheep.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_sheep.png index 72ddb1702..26c8c81f6 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_sheep.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_sheep.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_shulker.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_shulker.png index 491f840d6..be6a00de9 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_shulker.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_shulker.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_silverfish.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_silverfish.png index d0bca5664..5561016fc 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_silverfish.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_silverfish.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_skeleton.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_skeleton.png index d0225da21..ad6d9f228 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_skeleton.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_skeleton.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_slime.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_slime.png index 0366bd267..6f2e39702 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_slime.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_slime.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_snowman.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_snowman.png index f518f0cfe..d14af8fa1 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_snowman.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_snowman.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_spider.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_spider.png index 7877d0bb0..f89a6ade2 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_spider.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_spider.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_squid.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_squid.png index 40fa44080..73e475f46 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_squid.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_squid.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_stray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_stray.png index 67e5bbe3c..9b8dafa93 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_stray.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_stray.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vex.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vex.png index 93bfa7b92..8d01c05c2 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vex.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vex.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_villager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_villager.png index cf8ce28cc..6b0d0c083 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_villager.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_villager.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vindicator.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vindicator.png index 24316e0f9..a8b208c83 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vindicator.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_vindicator.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witch.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witch.png index cd1db520f..2b3cf8d87 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witch.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witch.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wither.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wither.png index 5ce5c44bf..c1f01c3de 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wither.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wither.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witherskeleton.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witherskeleton.png index 9055548bb..75694303d 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witherskeleton.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_witherskeleton.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wolf.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wolf.png index 7098285b6..a42bd0925 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wolf.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_wolf.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie.png index 0b4da4163..3d16dbb93 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_pigman.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_pigman.png index ba27c85d3..461ffcfa7 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_pigman.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_pigman.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_villager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_villager.png index 9430af7ef..f092e6f5f 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_villager.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_zombie_villager.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_stone.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stone.png new file mode 100644 index 000000000..3e4e4485c Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stone.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray.png index 21f15614d..94c9f3c47 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray_overlay.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray_overlay.png index b4b47a9fb..881bfbda5 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray_overlay.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_stray_overlay.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_trading_formspec_bg.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_trading_formspec_bg.png index e271ddb24..05b8f5741 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_trading_formspec_bg.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_trading_formspec_bg.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_mason.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_mason.png new file mode 100644 index 000000000..a09e79b2a Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_mason.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_vindicator.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_vindicator.png index 512eae60a..c47a157a5 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_vindicator.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_vindicator.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_witch.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_witch.png index acdf2ff93..abae57aa4 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_witch.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_witch.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither.png index d0b299ee9..3895ded6e 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png index f6353400c..edce2e987 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_half_health.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_skeleton.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_skeleton.png index d0d6afe77..3cd240e2a 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_skeleton.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wither_skeleton.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_roam.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_roam.png index fc09566a5..cf9671f70 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_roam.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_roam.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_sit.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_sit.png index 7dde7e5a8..50d764502 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_sit.png and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_wolf_icon_sit.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/spawn_egg.png b/mods/ENTITIES/mobs_mc/textures/spawn_egg.png new file mode 100644 index 000000000..aa9045e67 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/spawn_egg.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/spawn_egg_overlay.png b/mods/ENTITIES/mobs_mc/textures/spawn_egg_overlay.png new file mode 100644 index 000000000..fd0aa48a1 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/spawn_egg_overlay.png differ diff --git a/mods/ENTITIES/mobs_mc/tropical_fish.lua b/mods/ENTITIES/mobs_mc/tropical_fish.lua index fb321de96..47f59a92e 100644 --- a/mods/ENTITIES/mobs_mc/tropical_fish.lua +++ b/mods/ENTITIES/mobs_mc/tropical_fish.lua @@ -103,16 +103,22 @@ local tropical_fish = { runaway = true, fear_height = 4, on_rightclick = function(self, clicker) - if clicker:get_wielded_item():get_name() == "mcl_buckets:bucket_water" then - self.object:remove() - clicker:set_wielded_item("mcl_buckets:bucket_tropical_fish") + local bn = clicker:get_wielded_item():get_name() + if bn == "mcl_buckets:bucket_water" or bn == "mcl_buckets:bucket_river_water" then + if clicker:set_wielded_item("mcl_buckets:bucket_tropical_fish") then + local it = clicker:get_wielded_item() + local m = it:get_meta() + m:set_string("properties",minetest.serialize(self.object:get_properties())) + clicker:set_wielded_item(it) + self.object:remove() + end awards.unlock(clicker:get_player_name(), "mcl:tacticalFishing") end end, on_spawn = set_textures, } -mcl_mobs:register_mob("mobs_mc:tropical_fish", tropical_fish) +mcl_mobs.register_mob("mobs_mc:tropical_fish", tropical_fish) local water = 0 mcl_mobs:spawn_specific( @@ -183,4 +189,4 @@ water-16, water+1) --spawn egg -mcl_mobs:register_egg("mobs_mc:tropical_fish", S("Tropical fish"), "extra_mobs_spawn_icon_tropical_fish.png", 0) +mcl_mobs.register_egg("mobs_mc:tropical_fish", S("Tropical fish"), "#ef6915", "#fff9ef", 0) diff --git a/mods/ENTITIES/mobs_mc/vex.lua b/mods/ENTITIES/mobs_mc/vex.lua index 9a5455425..f2cd6f14b 100644 --- a/mods/ENTITIES/mobs_mc/vex.lua +++ b/mods/ENTITIES/mobs_mc/vex.lua @@ -9,7 +9,7 @@ local S = minetest.get_translator("mobs_mc") --################### VEX --################### -mcl_mobs:register_mob("mobs_mc:vex", { +mcl_mobs.register_mob("mobs_mc:vex", { description = S("Vex"), type = "monster", spawn_class = "hostile", @@ -94,4 +94,4 @@ mcl_mobs:register_mob("mobs_mc:vex", { -- spawn eggs -mcl_mobs:register_egg("mobs_mc:vex", S("Vex"), "mobs_mc_spawn_icon_vex.png", 0) +mcl_mobs.register_egg("mobs_mc:vex", S("Vex"), "#7a90a4", "#e8edf1", 0) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 79002d5f9..bf2a07d51 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -15,6 +15,8 @@ -- TODO: Internal inventory, trade with other villagers -- TODO: Schedule stuff (work,sleep,father) +local weather_mod = minetest.get_modpath("mcl_weather") + local S = minetest.get_translator("mobs_mc") local N = function(s) return s end local F = minetest.formspec_escape @@ -28,6 +30,10 @@ local DEFAULT_WALK_CHANCE = 33 -- chance to walk in percent, if no player nearby local PLAYER_SCAN_INTERVAL = 5 -- every X seconds, villager looks for players nearby local PLAYER_SCAN_RADIUS = 4 -- scan radius for looking for nearby players +local RESETTLE_DISTANCE = 100 -- If a mob is transported this far from home, it gives up bed and job and resettles + +local PATHFINDING = "gowp" + --[=======[ TRADING ]=======] -- LIST OF VILLAGER PROFESSIONS AND TRADES @@ -40,6 +46,13 @@ local PLAYER_SCAN_RADIUS = 4 -- scan radius for looking for nearby players -- these items should be implemented as single items, then everything -- will be much easier. +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false) +local function mcl_log (message) + if LOGGING_ON then + mcl_util.mcl_log (message, "[Mobs - Villager]", true) + end +end + local COMPASS = "mcl_compass:compass" if minetest.registered_aliases[COMPASS] then COMPASS = minetest.registered_aliases[COMPASS] @@ -66,11 +79,11 @@ local tiernames = { } local badges = { - "default_wood.png", - "default_steel_block.png", - "default_gold_block.png", - "mcl_core_emerald_block.png", - "default_diamond_block.png", + "mobs_mc_stone.png", + "mobs_mc_iron.png", + "mobs_mc_gold.png", + "mobs_mc_emerald.png", + "mobs_mc_diamond.png", } local professions = { @@ -84,10 +97,7 @@ local professions = { }, farmer = { name = N("Farmer"), - textures = { - "mobs_mc_villager_farmer.png", - "mobs_mc_villager_farmer.png", - }, + texture = "mobs_mc_villager_farmer.png", jobsite = "mcl_composters:composter", trades = { { @@ -98,7 +108,7 @@ local professions = { }, { - { { "mcl_farming:pumpkin", 8, 13 }, E1 }, + { { "mcl_farming:pumpkin", 6, 7 }, E1 }, { E1, { "mcl_farming:pumpkin_pie", 2, 3} }, { E1, { "mcl_core:apple", 2, 3} }, }, @@ -121,10 +131,7 @@ local professions = { }, fisherman = { name = N("Fisherman"), - textures = { - "mobs_mc_villager_fisherman.png", - "mobs_mc_villager_fisherman.png", - }, + texture = "mobs_mc_villager_fisherman.png", jobsite = "mcl_barrels:barrel_closed", trades = { { @@ -158,10 +165,7 @@ local professions = { }, fletcher = { name = N("Fletcher"), - textures = { - "mobs_mc_villager_fletcher.png", - "mobs_mc_villager_fletcher.png", - }, + texture = "mobs_mc_villager_fletcher.png", jobsite = "mcl_fletching_table:fletching_table", trades = { { @@ -200,10 +204,7 @@ local professions = { }, shepherd ={ name = N("Shepherd"), - textures = { - "mobs_mc_villager_sheperd.png", - "mobs_mc_villager_sheperd.png", - }, + texture = "mobs_mc_villager_sheperd.png", jobsite = "mcl_loom:loom", trades = { { @@ -233,10 +234,7 @@ local professions = { }, librarian = { name = N("Librarian"), - textures = { - "mobs_mc_villager_librarian.png", - "mobs_mc_villager_librarian.png", - }, + texture = "mobs_mc_villager_librarian.png", jobsite = "mcl_books:bookshelf", --FIXME: lectern trades = { { @@ -271,10 +269,7 @@ local professions = { }, cartographer = { name = N("Cartographer"), - textures = { - "mobs_mc_villager_cartographer.png", - "mobs_mc_villager_cartographer.png", - }, + texture = "mobs_mc_villager_cartographer.png", jobsite = "mcl_cartography_table:cartography_table", trades = { { @@ -283,7 +278,7 @@ local professions = { }, { -- compass subject to special checks - { { "xpanes:pane_natural_flat", 1, 1 }, E1 }, + { { "xpanes:pane_natural_flat", 11, 11 }, E1 }, --{ { "mcl_core:emerald", 13, 13, "mcl_compass:compass", 1, 1 }, { "FIXME:ocean explorer map" 1, 1} }, }, { @@ -317,10 +312,7 @@ local professions = { }, armorer = { name = N("Armorer"), - textures = { - "mobs_mc_villager_armorer.png", - "mobs_mc_villager_armorer.png", - }, + texture = "mobs_mc_villager_armorer.png", jobsite = "mcl_blast_furnace:blast_furnace", trades = { { @@ -357,10 +349,7 @@ local professions = { }, leatherworker = { name = N("Leatherworker"), - textures = { - "mobs_mc_villager_leatherworker.png", - "mobs_mc_villager_leatherworker.png", - }, + texture = "mobs_mc_villager_leatherworker.png", jobsite = "mcl_cauldrons:cauldron", trades = { { @@ -389,10 +378,7 @@ local professions = { }, butcher = { name = N("Butcher"), - textures = { - "mobs_mc_villager_butcher.png", - "mobs_mc_villager_butcher.png", - }, + texture = "mobs_mc_villager_butcher.png", jobsite = "mcl_smoker:smoker", trades = { { @@ -422,10 +408,7 @@ local professions = { }, weapon_smith = { name = N("Weapon Smith"), - textures = { - "mobs_mc_villager_weaponsmith.png", - "mobs_mc_villager_weaponsmith.png", - }, + texture = "mobs_mc_villager_weaponsmith.png", jobsite = "mcl_grindstone:grindstone", trades = { { @@ -453,10 +436,7 @@ local professions = { }, tool_smith = { name = N("Tool Smith"), - textures = { - "mobs_mc_villager_toolsmith.png", - "mobs_mc_villager_toolsmith.png", - }, + texture = "mobs_mc_villager_toolsmith.png", jobsite = "mcl_smithing_table:table", trades = { { @@ -490,10 +470,7 @@ local professions = { }, cleric = { name = N("Cleric"), - textures = { - "mobs_mc_villager_priest.png", - "mobs_mc_villager_priest.png", - }, + texture = "mobs_mc_villager_priest.png", jobsite = "mcl_brewing:stand_000", trades = { { @@ -520,27 +497,88 @@ local professions = { }, }, }, + mason = { + name = N("Mason"), + texture = "mobs_mc_villager_mason.png", + jobsite = "mcl_stonecutter:stonecutter", + trades = { + { + { { "mcl_core:clay_lump", 10, 10 }, E1 }, + { E1, { "mcl_core:brick", 10, 10 } }, + }, + { + { { "mcl_core:stone", 20, 20 }, E1 }, + { E1, { "mcl_core:stonebrickcarved", 4, 4 } }, + }, + { + { { "mcl_core:granite", 16, 16 }, E1 }, + { { "mcl_core:andesite", 16, 16 }, E1 }, + { { "mcl_core:diorite", 16, 16 }, E1 }, + { E1, { "mcl_core:granite_smooth", 4, 4 } }, + { E1, { "mcl_core:andesite_smooth", 4, 4 } }, + { E1, { "mcl_core:diorite_smooth", 4, 4 } }, + }, + { + { { "mcl_nether:quartz", 12, 12 }, E1 }, + { E1, { "mcl_colorblocks:hardened_clay", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_white", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_grey", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_silver", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_black", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_red", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_yellow", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_green", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_cyan", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_blue", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_magenta", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_orange", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_brown", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_pink", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_light_blue", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_lime", 1, 1} }, + { E1, { "mcl_colorblocks:hardened_clay_purple", 1, 1 } }, + }, + { + { E1, { "mcl_nether:quartz_pillar", 1, 1 } }, + { E1, { "mcl_nether:quartz_block", 1, 1 } }, + }, + }, + }, nitwit = { name = N("Nitwit"), - textures = { - "mobs_mc_villager_nitwit.png", - "mobs_mc_villager_nitwit.png", - }, + texture = "mobs_mc_villager_nitwit.png", -- No trades for nitwit trades = nil, } } +local WORK = "work" +local SLEEP = "sleep" +local GATHERING = "gathering" + local profession_names = {} for id, _ in pairs(professions) do table.insert(profession_names, id) end -local jobsites={} -for _,n in pairs(profession_names) do - table.insert(jobsites,professions[n].jobsite) +local function populate_jobsites (profession) + if profession then + mcl_log("populate_jobsites: ".. tostring(profession)) + end + local jobsites_requested={} + for _,n in pairs(profession_names) do + if n and professions[n].jobsite then + if not profession or (profession and profession == n) then + --minetest.log("populate_jobsites. Adding: ".. tostring(n)) + table.insert(jobsites_requested,professions[n].jobsite) + end + end + end + return jobsites_requested end +jobsites = populate_jobsites() + local function stand_still(self) self.walk_chance = 0 self.jump = false @@ -559,36 +597,285 @@ local function init_trader_vars(self) end local function get_badge_textures(self) - local t = professions[self._profession].textures + local t = professions[self._profession].texture + if self._profession == "unemployed" then + t = professions[self._profession].textures -- ideally both scenarios should be textures with a list containing 1 or multiple + --mcl_log("t: " .. tostring(t)) + end + if self._profession == "unemployed" or self._profession == "nitwit" then return t end local tier = self._max_trade_tier or 1 return { - "[combine:64x64:0,0="..t[1]..":11,55=".. badges[tier].."\\^[resize\\:2x2", - t[2] + t .. "^" .. badges[tier] } end local function set_textures(self) - self.object:set_properties({textures=get_badge_textures(self)}) + local badge_textures = get_badge_textures(self) + --mcl_log("Setting textures: " .. tostring(badge_textures)) + self.object:set_properties({textures=badge_textures}) end -local function go_home(entity) - entity.state = "go_home" - local b=entity._bed - if not b then return end - mcl_mobs:gopath(entity,b,function(entity,b) - if vector.distance(entity.object:get_pos(),b) < 2 then - entity.state = "stand" - set_velocity(entity,0) - entity.object:set_pos(b) - local n=minetest.get_node(b) - if n and n.name ~= "mcl_beds:bed_red_bottom" then - entity._bed=nil --the stormtroopers have killed uncle owen +function get_activity(tod) + -- night hours = tod > 18541 or tod < 5458 + if not tod then + tod = minetest.get_timeofday() + end + tod = ( tod * 24000 ) % 24000 + + local lunch_start = 11000 + local lunch_end = 13500 + local work_start = 7000 + local work_end = 16500 + + local activity = nil + if weather_mod and mcl_weather.get_weather() == "thunder" then + mcl_log("Better get to bed. Weather is: " .. mcl_weather.get_weather()) + activity = SLEEP + elseif (tod > work_start and tod < lunch_start) or (tod > lunch_end and tod < work_end) then + activity = WORK + elseif mcl_beds.is_night() then + activity = SLEEP + elseif tod > lunch_start and tod < lunch_end then + activity = GATHERING + else + activity = "chill" + end + mcl_log("Time is " .. tod ..". Activity is: ".. activity) + return activity + +end + +local function find_closest_bed (self) + local p = self.object:get_pos() + + --local spawnable_bed={} + --table.insert(spawnable_bed, "mcl_beds:bed_red_bottom") + --local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), spawnable_bed) + --if nn then + -- mcl_log("Red beds: " .. #nn) + --end + + local unclaimed_beds = {} + local nn2 = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), {"group:bed"}) + if nn2 then + --mcl_log("All bed parts: " .. #nn2) + + for a,b in pairs(nn2) do + mcl_log("b: " .. minetest.pos_to_string(b)) + + local bed_node = minetest.get_node(b) + local bed_name = bed_node.name + local is_bed_bottom = string.find(bed_name,"_bottom") + + local bed_meta = minetest.get_meta(b) + local owned_by = bed_meta:get_string("villager") + --mcl_log("Owned by villager: ".. tostring(owned_by)) + + if (owned_by and owned_by == self._id) then + mcl_log("Clear as already owned by me.") + bed_meta:set_string("villager", nil) + owned_by = nil + end + + if is_bed_bottom then + local bed_top = mcl_beds.get_bed_top (b) + mcl_log("bed_top: " .. tostring(bed_top)) + + local bed_top_node = minetest.get_node(bed_top) + if bed_top_node then + mcl_log("There is a block here for bed top: ".. bed_top_node.name) + else + mcl_log("There is no block here for bed top") + end + + local bed_top_meta = minetest.get_meta(bed_top) + local owned_by_player = bed_top_meta:get_string("player") + if bed_top_meta then + mcl_log("Player: " .. tostring(owned_by_player)) + else + mcl_log("No bed top meta") + end + + if owned_by == "" and (not owned_by_player or owned_by_player == "") then + table.insert(unclaimed_beds, b) + mcl_log("is an unowned bed bottom") + else + + end + else + --mcl_log("bed_node name: " .. bed_name) + end + end + end + + local distance_to_closest_block = nil + local closest_block = nil + + if unclaimed_beds then + mcl_log("All unclaimed bed bottoms: " .. #unclaimed_beds) + + for i,b in pairs(unclaimed_beds) do + mcl_log("b: " .. minetest.pos_to_string(b)) + local distance_to_block = vector.distance(p, b) + mcl_log("Distance to block ".. i .. ": ".. distance_to_block) + + if not distance_to_closest_block or distance_to_closest_block > distance_to_block then + mcl_log("This block is closer than the last.") + closest_block = b + distance_to_closest_block = distance_to_block + end + + local bed_node = minetest.get_node(b) + local bed_name = bed_node.name + mcl_log("bed_node name: " .. bed_name) + end + end + + return closest_block +end + +local function find_closest_unclaimed_block (p, requested_block_types) + local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), requested_block_types) + + local distance_to_closest_block = nil + local closest_block = nil + + for i,n in pairs(nn) do + local m = minetest.get_meta(n) + + if m:get_string("villager") == "" then + mcl_log("Block: " .. minetest.pos_to_string(n).. ", owner: ".. m:get_string("villager")) + + local distance_to_block = vector.distance(p, n) + mcl_log("Distance to block ".. i .. ": ".. distance_to_block) + + if not distance_to_closest_block or distance_to_closest_block > distance_to_block then + mcl_log("This block is closer than the last.") + closest_block = n + distance_to_closest_block = distance_to_block + end + end + end + return closest_block +end + +local function check_bed (entity) + local b = entity._bed + if not b then + --minetest.log("No bed set on villager") + return false + end + + local n = minetest.get_node(b) + + local is_bed_bottom = string.find(n.name,"_bottom") + mcl_log("" .. tostring(is_bed_bottom)) + if n and not is_bed_bottom then + mcl_log("Where did my bed go?!") + entity._bed = nil --the stormtroopers have killed uncle owen + return false + else + return true + end +end + +local function go_home(entity, sleep) + + if not check_bed (entity) then + mcl_log("Cannot find bed, so cannot go home") + end + + local b = entity._bed + if not b then + return + end + + local bed_node = minetest.get_node(b) + if not bed_node then + entity._bed = nil + mcl_log("Cannot find bed. Unset it") + return + end + + if vector.distance(entity.object:get_pos(),b) < 2 then + if sleep then + entity.order = SLEEP + mcl_log("Sleep time!") + end + else + if sleep and entity.order == SLEEP then + entity.order = nil + return + end + + entity:gopath(b,function(entity,b) + local b = entity._bed + + if not b then + --minetest.log("NO BED, problem") return false end - return true + + if not minetest.get_node(b) then + --minetest.log("NO BED NODE, problem") + return false + end + + if vector.distance(entity.object:get_pos(),b) < 2 then + --minetest.log("Managed to walk home callback!") + return true + else + --minetest.log("Need to walk to home") + end + end) + end +end + + + +local function take_bed (entity) + if not entity then return end + + local p = entity.object:get_pos() + + local closest_block = find_closest_bed (entity) + + if closest_block then + mcl_log("Can we path to bed: "..minetest.pos_to_string(closest_block) ) + local distance_to_block = vector.distance(p, closest_block) + mcl_log("Distance: " .. distance_to_block) + if distance_to_block < 2 then + local m = minetest.get_meta(closest_block) + local owner = m:get_string("villager") + mcl_log("owner: ".. owner) + if owner and owner ~= "" and owner ~= entity._id then + mcl_log("Already taken") + if entity.order == "stand" then entity.order = nil end + return + end + + if entity.order ~= SLEEP then + mcl_log("Sleepy time" ) + entity.order = SLEEP + m:set_string("villager", entity._id) + entity._bed = closest_block + else + --entity.order = nil + mcl_log("Set as sleep already..." ) + end + else + local gp = entity:gopath(closest_block,function(self) end) + if gp then + mcl_log("Nice bed. I'll defintely take it as I can path") + else + mcl_log("Awww. I can't find my bed.") + end end - end) + else + mcl_log("Cannot find a bed to claim.") + if entity.order == "stand" then entity.order = nil end + end end local function has_golem(pos) @@ -599,11 +886,18 @@ local function has_golem(pos) end end +local function monsters_near(self) + for _,o in pairs(minetest.get_objects_inside_radius(self.object:get_pos(),10)) do + local l = o:get_luaentity() + if l and l.type =="monster" then return true end + end +end + local function has_summon_participants(self) local r = 0 for _,o in pairs(minetest.get_objects_inside_radius(self.object:get_pos(),10)) do local l = o:get_luaentity() - --TODO check for panicking or gossiping + --TODO check for gossiping if l and l.name == "mobs_mc:villager" then r = r + 1 end end return r > 2 @@ -627,7 +921,8 @@ local function check_summon(self,dtime) if self._summon_timer and self._summon_timer > 30 then local pos = self.object:get_pos() self._summon_timer = 0 - if has_golem(pos) then return false end + if has_golem(pos) then return end + if not monsters_near(self) then return end if not has_summon_participants(self) then return end summon_golem(self) elseif self._summon_timer == nil then @@ -636,6 +931,71 @@ local function check_summon(self,dtime) self._summon_timer = self._summon_timer + dtime end +local function debug_trades(self) + mcl_log("Start debug trades") + if not self or not self._trades then return end + local trades = minetest.deserialize(self._trades) + if trades and type(trades) == "table" then + for trader, trade in pairs(trades) do + --mcl_log("Current record: ".. tostring(trader)) + for tr3, tr4 in pairs (trade) do + mcl_log("Key: ".. tostring(tr3)) + mcl_log("Value: ".. tostring(tr4)) + end + end + end + mcl_log("End debug trades") +end + +local function has_traded (self) + if not self._trades then + mcl_log("No trades set. has_traded is false") + return false + end + local cur_trades_tab = minetest.deserialize(self._trades) + if cur_trades_tab and type(cur_trades_tab) == "table" then + for trader, trades in pairs(cur_trades_tab) do + if trades.traded_once then + mcl_log("Villager has traded before. Returning true") + return true + end + end + end + mcl_log("Villager has not traded before") + return false +end + +local function unlock_trades (self) + if not self._trades then + mcl_log("No trades set. has_traded is false") + return false + end + mcl_log("Unlocking trades") + local has_unlocked = false + + local trades = minetest.deserialize(self._trades) + if trades and type(trades) == "table" then + for trader, trade in pairs(trades) do + local trade_tier_too_high = trade.tier > self._max_trade_tier + --mcl_log("Max trade tier of villager: ".. tostring(self._max_trade_tier)) + --mcl_log("current trade.tier: ".. tostring(trade.tier)) + --mcl_log("trade tier too high: ".. tostring(trade_tier_too_high)) + --mcl_log("locked: ".. tostring(trade["locked"])) + if not trade_tier_too_high then + if trade["locked"] == true then + trade.locked = false + trade.trade_counter = 0 + has_unlocked = true + mcl_log("Villager has a locked trade. Unlocking") + end + end + end + if has_unlocked then + self._trades = minetest.serialize(trades) + end + end +end + ----- JOBSITE LOGIC local function get_profession_by_jobsite(js) for k,v in pairs(professions) do @@ -648,48 +1008,314 @@ local function employ(self,jobsite_pos) local m = minetest.get_meta(jobsite_pos) local p = get_profession_by_jobsite(n.name) if p and m:get_string("villager") == "" then - self._profession=p + mcl_log("Taking this jobsite") + m:set_string("villager",self._id) self._jobsite = jobsite_pos + + if not has_traded(self) then + self._profession=p + set_textures(self) + end + return true + else + mcl_log("I can not steal someone's job!") + end +end + + +local function look_for_job(self, requested_jobsites) + mcl_log("Looking for jobs") + + local p = self.object:get_pos() + + local closest_block = find_closest_unclaimed_block(p, requested_jobsites) + + if closest_block then + mcl_log("It's a free job for me (" .. minetest.pos_to_string(p) .. ")! I might be interested: ".. minetest.pos_to_string(closest_block) ) + + local gp = self:gopath(closest_block,function(self) + mcl_log("Arrived at block callback") + if self and self.state == "stand" then + self.order = WORK + else + mcl_log("no self. passing param to callback failed") + end + end) + + if gp then + if closest_block then + mcl_log("We can path to this block.. " .. tostring(closest_block)) + end + return closest_block + else + mcl_log("We could not path to block or it's not ready to path yet.") + end + else + mcl_log("We don't have a job block to path to") + end + + return nil +end + + + +local function get_a_job(self) + if self.order == WORK then self.order = nil end + + mcl_log("I'm unemployed or lost my job block and have traded. Can I get a job?") + + local requested_jobsites = jobsites + if has_traded (self) then + mcl_log("Has traded so look for job of my type") + requested_jobsites = populate_jobsites(self._profession) + -- Only pass in my jobsite to two functions here + end + + local p = self.object:get_pos() + local n = minetest.find_node_near(p,1,requested_jobsites) + if n and employ(self,n) then return true end + + if self.state ~= PATHFINDING then + mcl_log("Nothing near. Need to look for a job") + look_for_job(self, requested_jobsites) + end +end + +local function retrieve_my_jobsite (self) + if not self or not self._jobsite then + mcl_log("find_jobsite. Invalid params. Should not happen") + return + end + local n = mcl_vars.get_node(self._jobsite) + local m = minetest.get_meta(self._jobsite) + if m:get_string("villager") == self._id then + --mcl_log("find_jobsite. is my job.") + return n + else + mcl_log("This isn't my jobsite") + end + return +end + +local function remove_job (self) + self._jobsite = nil + if not has_traded(self) then + mcl_log("Cannot retrieve my jobsite. I am now unemployed.") + self._profession = "unemployed" + self._trades = nil set_textures(self) + else + mcl_log("Cannot retrieve my jobsite but I've traded so only remove jobsite.") + end +end + +local function validate_jobsite(self) + if self._profession == "unemployed" then return false end + + local job_block = retrieve_my_jobsite (self) + if not job_block then + if self.order == WORK then + self.order = nil + end + + remove_job (self) + return false + else + local resettle = vector.distance(self.object:get_pos(),self._jobsite) > RESETTLE_DISTANCE + mcl_log("Jobsite far, so resettle: " .. tostring(resettle)) + if resettle then + local m = minetest.get_meta(self._jobsite) + m:set_string("villager", nil) + remove_job (self) + return false + end return true end end -local function look_for_job(self) - if self.last_jobhunt and os.time() - self.last_jobhunt < 360 then return end - self.last_jobhunt = os.time() + math.random(0,60) - local p = self.object:get_pos() - local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48),jobsites) - for _,n in pairs(nn) do - local m=minetest.get_meta(n) - if m:get_string("villager") == "" then - --minetest.log("goingt to jobsite "..minetest.pos_to_string(n) ) - local gp = mcl_mobs:gopath(self,n,function() - --minetest.log("arrived jobsite "..minetest.pos_to_string(n) ) - end) - if gp then return end +local function do_work (self) + --debug_trades(self) + if self.child then + mcl_log("A child so don't send to work") + return + end + --mcl_log("Time for work") + + -- Don't try if looking_for_work, or gowp possibly + if validate_jobsite(self) then + --mcl_log("My jobsite is valid. Do i need to travel?") + + local jobsite2 = retrieve_my_jobsite (self) + local jobsite = self._jobsite + + if self and jobsite2 and self._jobsite then + local distance_to_jobsite = vector.distance(self.object:get_pos(),self._jobsite) + --mcl_log("Villager: ".. minetest.pos_to_string(self.object:get_pos()) .. ", jobsite: " .. minetest.pos_to_string(self._jobsite) .. ", distance to jobsite: ".. distance_to_jobsite) + + if distance_to_jobsite < 2 then + if self.state ~= PATHFINDING and self.order ~= WORK then + mcl_log("Setting order to work.") + self.order = WORK + unlock_trades(self) + else + --mcl_log("Still pathfinding.") + end + else + mcl_log("Not at job block. Need to commute.") + if self.order == WORK then + self.order = nil + return + end + self:gopath(jobsite, function(self,jobsite) + if not self then + --mcl_log("missing self. not good") + return false + end + if not self._jobsite then + --mcl_log("Jobsite not valid") + return false + end + if vector.distance(self.object:get_pos(),self._jobsite) < 2 then + --mcl_log("Made it to work ok callback!") + return true + else + --mcl_log("Need to walk to work. Not sure we can get here.") + end + end) + end end + elseif self._profession == "unemployed" or has_traded(self) then + get_a_job(self) end end -local function get_a_job(self) - if self.child then return end +local function go_to_town_bell(self) + if self.order == GATHERING then + mcl_log("Already gathering") + return + else + mcl_log("Current order" .. self.order) + end + mcl_log("Go to town bell") + + local looking_for_type={} + table.insert(looking_for_type, "mcl_bells:bell") + local p = self.object:get_pos() - local n = minetest.find_node_near(p,1,jobsites) - if n and employ(self,n) then return true end - if self.state ~= "gowp" then look_for_job(self) end + local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), looking_for_type) + + --Ideally should check for closest available. It'll make pathing easier. + for _,n in pairs(nn) do + mcl_log("Found bell") + + local gp = self:gopath(n,function(self) + if self then + self.order = GATHERING + mcl_log("Callback has a self") + end + mcl_log("Arrived at block callback") + end) + + if gp then + if n then + mcl_log("We can path to this block.. " .. tostring(n)) + end + return n + else + mcl_log("We could not path to block or it's not ready to path yet.") + end + + end + + return nil end -local function check_jobsite(self) - if self._traded or not self._jobsite then return end - local n = mcl_vars.get_node(self._jobsite) - local m = minetest.get_meta(self._jobsite) - if m:get_string("villager") ~= self._id then - self._profession = "unemployed" - self._trades = nil - set_textures(self) +local function validate_bed(self) + if not self or not self._bed then + return false end + local n = mcl_vars.get_node(self._bed) + if not n then + self._bed = nil + return false + end + + local bed_valid = true + + local m = minetest.get_meta(self._bed) + + local resettle = vector.distance(self.object:get_pos(),self._bed) > RESETTLE_DISTANCE + mcl_log("Bed far, so resettle: " .. tostring(resettle)) + if resettle then + mcl_log("Resettled. Ditch bed.") + m:set_string("villager", nil) + self._bed = nil + bed_valid = false + return false + end + + local owned_by_player = m:get_string("player") + mcl_log("Player owner: " .. owned_by_player) + if owned_by_player ~= "" then + mcl_log("Player owns this. Villager won't take this.") + m:set_string("villager", nil) + self._bed = nil + bed_valid = false + return false + end + + if m:get_string("villager") ~= self._id then + mcl_log("This bed is owned by another player. I'll unclaim.") + self._bed = nil + return false + else + mcl_log("Bed is valid") + return true + end + +end + +local function do_activity (self) + -- Maybe just check we're pathfinding first? + if self.following then + mcl_log("Following, so do not do activity.") + return + end + + if not validate_bed(self) and self.state ~= PATHFINDING then + if self.order == SLEEP then self.order = nil end + mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos())) + take_bed (self) + end + + -- Only check in day or during thunderstorm but wandered_too_far code won't work + local wandered_too_far = false + if check_bed (self) then + wandered_too_far = ( self.state ~= PATHFINDING ) and (vector.distance(self.object:get_pos(),self._bed) > 50 ) + end + + if wandered_too_far then + --mcl_log("Wandered too far! Return home ") + go_home(self, false) + elseif get_activity() == SLEEP then + go_home(self, true) + elseif get_activity() == WORK then + do_work(self) + elseif get_activity() == GATHERING then + go_to_town_bell(self) + else + mcl_log("No order, so remove it.") + self.order = nil + end + + -- Daytime is work and play time + if not mcl_beds.is_night() then + if self.order == SLEEP then self.order = nil end + else + if self.order == WORK then self.order = nil end + end + end local function update_max_tradenum(self) @@ -764,7 +1390,7 @@ local function set_trade(trader, player, inv, concrete_tradenum) init_trades(trader) trades = minetest.deserialize(trader._trades) if not trades then - minetest.log("error", "[mobs_mc] Failed to select villager trade!") + --minetest.log("error", "Failed to select villager trade!") return end end @@ -1158,6 +1784,7 @@ local trade_inventory = { -- END OF SPECIAL HANDLING FOR COMPASS local trader = player_trading_with[name] local tradenum = player_tradenum[name] + local trades trader._traded = true if trader and trader._trades then @@ -1197,6 +1824,7 @@ local trade_inventory = { trader.health = math.min(trader.hp_max, trader.health + 4) end trade.trade_counter = trade.trade_counter + 1 + mcl_log("Trade counter is: ".. trade.trade_counter) -- Semi-randomly lock trade for repeated trade (not if there's only 1 trade) if trader._max_tradenum > 1 then if trade.trade_counter >= 12 then @@ -1269,12 +1897,18 @@ end) local pick_up = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" } -mcl_mobs:register_mob("mobs_mc:villager", { +mcl_mobs.register_mob("mobs_mc:villager", { description = S("Villager"), type = "npc", spawn_class = "passive", + passive = true, hp_min = 20, hp_max = 20, + head_swivel = "head.control", + bone_eye_height = 6.3, + head_eye_height = 2.2, + curiosity = 10, + runaway = true, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_villager.b3d", @@ -1282,7 +1916,6 @@ mcl_mobs:register_mob("mobs_mc:villager", { "mobs_mc_villager.png", "mobs_mc_villager.png", --hat }, - visual_size = {x=2.75, y=2.75}, makes_footstep_sound = true, walk_velocity = 1.2, run_velocity = 2.4, @@ -1295,21 +1928,18 @@ mcl_mobs:register_mob("mobs_mc:villager", { distance = 10, }, animation = { - stand_speed = 25, - stand_start = 40, - stand_end = 59, - walk_speed = 25, - walk_start = 0, - walk_end = 40, - run_speed = 25, - run_start = 0, - run_end = 40, - head_shake_start = 210, - head_shake_end = 220, - head_shake_loop = false, - head_nod_start = 210, - head_nod_end = 220, - head_nod_loop = false, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 25, + run_start = 0, run_end = 40, run_speed = 25, + head_shake_start = 60, head_shake_end = 70, head_shake_loop = false, + head_nod_start = 50, head_nod_end = 60, head_nod_loop = false, + }, + child_animations = { + stand_start = 71, stand_end = 71, + walk_start = 71, walk_end = 111, walk_speed = 37, + run_start = 71, run_end = 111, run_speed = 37, + head_shake_start = 131, head_shake_end = 141, head_shake_loop = false, + head_nod_start = 121, head_nod_end = 131, head_nod_loop = false, }, follow = pick_up, nofollow = true, @@ -1325,36 +1955,56 @@ mcl_mobs:register_mob("mobs_mc:villager", { can_open_doors = true, on_pick_up = function(self,itementity) local clicker + local it = ItemStack(itementity.itemstring) for _,p in pairs(minetest.get_connected_players()) do if vector.distance(p:get_pos(),self.object:get_pos()) < 10 then clicker = p end end - if clicker then - mcl_mobs:feed_tame(self, clicker, 1, true, false, true) - return + if clicker and not self.horny then + self:feed_tame(clicker, 1, true, false, true) + it:take_item(1) end - return true --do not pick up + return it end, on_rightclick = function(self, clicker) - if self._jobsite then - mcl_mobs:gopath(self,self._jobsite,function() - --minetest.log("arrived at jobsite") - end) - end if self.child or self._profession == "unemployed" or self._profession == "nitwit" then + self.order = nil return end + + if self.state == PATHFINDING then + self.state = "stand" + end + -- Can we remove now we possibly have fixed root cause + if self.state == "attack" then + mcl_log("Somehow villager got into an invalid attack state. Removed attack state.") + -- Need to stop villager getting in attack state. This is a workaround to allow players to fix broken villager. + self.state = "stand" + self.attack = nil + end + -- Don't do at night. Go to bed? Maybe do_activity needs it's own method + if validate_jobsite(self) and not self.order == WORK then + --self:gopath(self._jobsite,function() + -- minetest.log("sent to jobsite") + --end) + else + self.state = "stand" -- cancel gowp in case it has messed up + --self.order = nil -- cancel work if working + end + -- Initiate trading init_trader_vars(self) local name = clicker:get_player_name() self._trading_players[name] = true - if self._trades == nil then + if self._trades == nil or self._trades == false then + --minetest.log("Trades is nil so init") init_trades(self) end update_max_tradenum(self) if self._trades == false then + --minetest.log("Trades is false. no right click op") -- Villager has no trades, rightclick is a no-op return end @@ -1383,18 +2033,21 @@ mcl_mobs:register_mob("mobs_mc:villager", { _trading_players = {}, -- list of playernames currently trading with villager (open formspec) do_custom = function(self, dtime) check_summon(self,dtime) + -- Stand still if player is nearby. if not self._player_scan_timer then self._player_scan_timer = 0 end - self._player_scan_timer = self._player_scan_timer + dtime + -- Check infrequently to keep CPU load low if self._player_scan_timer > PLAYER_SCAN_INTERVAL then + self._player_scan_timer = 0 local selfpos = self.object:get_pos() local objects = minetest.get_objects_inside_radius(selfpos, PLAYER_SCAN_RADIUS) local has_player = false + for o, obj in pairs(objects) do if obj:is_player() then has_player = true @@ -1402,21 +2055,16 @@ mcl_mobs:register_mob("mobs_mc:villager", { end end if has_player then - minetest.log("verbose", "[mobs_mc] Player near villager found!") + --minetest.log("verbose", "[mobs_mc] Player near villager found!") stand_still(self) else - minetest.log("verbose", "[mobs_mc] No player near villager found!") + --minetest.log("verbose", "[mobs_mc] No player near villager found!") self.walk_chance = DEFAULT_WALK_CHANCE self.jump = true end - if self._bed and ( self.state ~= "go_home" and vector.distance(self.object:get_pos(),self._bed) > 50 ) then - go_home(self) - end - if self._profession == "unemployed" then - get_a_job(self) - else - check_jobsite(self) - end + + do_activity (self) + end end, @@ -1434,7 +2082,7 @@ mcl_mobs:register_mob("mobs_mc:villager", { self._id=minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random())) set_textures(self) end, - on_die = function(self, pos) + on_die = function(self, pos, cmi_cause) -- Close open trade formspecs and give input back to players local trading_players = self._trading_players if trading_players then @@ -1446,6 +2094,31 @@ mcl_mobs:register_mob("mobs_mc:villager", { end end end + + local bed = self._bed + if bed then + local bed_meta = minetest.get_meta(bed) + bed_meta:set_string("villager", nil) + mcl_log("Died, so bye bye bed") + end + local jobsite = self._jobsite + if jobsite then + local jobsite_meta = minetest.get_meta(jobsite) + jobsite_meta:set_string("villager", nil) + mcl_log("Died, so bye bye jobsite") + end + + if cmi_cause and cmi_cause.puncher then + local l = cmi_cause.puncher:get_luaentity() + if l and math.random(2) == 1 and( l.name == "mobs_mc:zombie" or l.name == "mobs_mc:baby_zombie" or l.name == "mobs_mc:villager_zombie" or l.name == "mobs_mc:husk") then + mcl_util.replace_mob(self.object,"mobs_mc:villager_zombie") + return true + end + end + end, + on_lightning_strike = function(self, pos, pos2, objects) + mcl_util.replace_mob(self.object, "mobs_mc:witch") + return true end, }) @@ -1483,4 +2156,4 @@ mobs_mc.water_level+1, mcl_vars.mg_overworld_max) --]] -- spawn eggs -mcl_mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0) +mcl_mobs.register_egg("mobs_mc:villager", S("Villager"), "#563d33", "#bc8b72", 0) diff --git a/mods/ENTITIES/mobs_mc/villager_evoker.lua b/mods/ENTITIES/mobs_mc/villager_evoker.lua index 6e62e00b6..4d46a7260 100644 --- a/mods/ENTITIES/mobs_mc/villager_evoker.lua +++ b/mods/ENTITIES/mobs_mc/villager_evoker.lua @@ -11,16 +11,23 @@ local S = minetest.get_translator("mobs_mc") local pr = PseudoRandom(os.time()*666) -mcl_mobs:register_mob("mobs_mc:evoker", { +local spawned_vexes = {} --this is stored locally so the mobs engine doesn't try to store it in staticdata + +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, hp_max = 24, xp_min = 10, xp_max = 10, + head_swivel = "head.control", + bone_eye_height = 6.3, + head_eye_height = 2.2, + curiosity = 10, collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.95, 0.4}, visual = "mesh", mesh = "mobs_mc_villager.b3d", @@ -29,7 +36,6 @@ mcl_mobs:register_mob("mobs_mc:evoker", { "blank.png", --no hat -- TODO: Attack glow } }, - visual_size = {x=2.75, y=2.75}, makes_footstep_sound = true, damage = 6, walk_velocity = 0.2, @@ -38,16 +44,24 @@ mcl_mobs:register_mob("mobs_mc:evoker", { attack_type = "dogfight", -- Summon vexes custom_attack = function(self, to_attack) - local r = pr:next(2,4) + if not spawned_vexes[self] then spawned_vexes[self] = {} end + if #spawned_vexes[self] >= 7 then return end + for k,v in pairs(spawned_vexes[self]) do + if not v or v.health <= 0 then table.remove(spawned_vexes[self],k) end + end + local r = pr:next(1,4) local basepos = self.object:get_pos() basepos.y = basepos.y + 1 for i=1, r do local spawnpos = vector.add(basepos, minetest.yaw_to_dir(pr:next(0,360))) local vex = minetest.add_entity(spawnpos, "mobs_mc:vex") local ent = vex:get_luaentity() + -- Mark vexes as summoned and start their life clock (they take damage it reaches 0) ent._summoned = true ent._lifetimer = pr:next(33, 108) + + table.insert(spawned_vexes[self],ent) end end, shoot_interval = 15, @@ -65,23 +79,14 @@ mcl_mobs:register_mob("mobs_mc:evoker", { }, -- TODO: sounds animation = { - stand_speed = 25, - stand_start = 40, - stand_end = 59, - walk_speed = 25, - walk_start = 0, - walk_end = 40, - run_speed = 25, - shoot_start = 120, --magic arm swinging - shoot_end = 140, - die_speed = 15, - die_start = 190, - die_end = 200, - die_loop = false, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 6, + run_start = 0, run_end = 40, run_speed = 24, + shoot_start = 142, shoot_end = 152, -- Magic arm swinging }, view_range = 16, fear_height = 4, }) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:evoker", S("Evoker"), "mobs_mc_spawn_icon_evoker.png", 0) +mcl_mobs.register_egg("mobs_mc:evoker", S("Evoker"), "#959b9b", "#1e1c1a", 0) diff --git a/mods/ENTITIES/mobs_mc/villager_illusioner.lua b/mods/ENTITIES/mobs_mc/villager_illusioner.lua index 4af0c4024..f7c034eb0 100644 --- a/mods/ENTITIES/mobs_mc/villager_illusioner.lua +++ b/mods/ENTITIES/mobs_mc/villager_illusioner.lua @@ -6,7 +6,7 @@ local S = minetest.get_translator("mobs_mc") local mod_bows = minetest.get_modpath("mcl_bows") ~= nil -mcl_mobs:register_mob("mobs_mc:illusioner", { +mcl_mobs.register_mob("mobs_mc:illusioner", { description = S("Illusioner"), type = "monster", spawn_class = "hostile", @@ -33,6 +33,10 @@ mcl_mobs:register_mob("mobs_mc:illusioner", { "mobs_mc_illusionist.png", --hat "mcl_bows_bow.png", }, }, + head_swivel = "head.control", + bone_eye_height = 2.2, + head_eye_height = 2.2, + curiosity = 10, sounds = { -- TODO: more sounds distance = 16, @@ -61,4 +65,4 @@ mcl_mobs:register_mob("mobs_mc:illusioner", { fear_height = 4, }) -mcl_mobs:register_egg("mobs_mc:illusioner", S("Illusioner"), "mobs_mc_spawn_icon_illusioner.png", 0) +mcl_mobs.register_egg("mobs_mc:illusioner", S("Illusioner"), "#3f5cbb", "#8a8686", 0) diff --git a/mods/ENTITIES/mobs_mc/villager_vindicator.lua b/mods/ENTITIES/mobs_mc/villager_vindicator.lua index 4b7173d36..b2dcb827a 100644 --- a/mods/ENTITIES/mobs_mc/villager_vindicator.lua +++ b/mods/ENTITIES/mobs_mc/villager_vindicator.lua @@ -10,7 +10,7 @@ local S = minetest.get_translator("mobs_mc") --################### -mcl_mobs:register_mob("mobs_mc:vindicator", { +mcl_mobs.register_mob("mobs_mc:vindicator", { description = S("Vindicator"), type = "monster", spawn_class = "hostile", @@ -23,14 +23,18 @@ mcl_mobs:register_mob("mobs_mc:vindicator", { collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_vindicator.b3d", - textures = { - { - "mobs_mc_vindicator.png", - "blank.png", --no hat - "default_tool_steelaxe.png", - -- TODO: Glow when attacking (mobs_mc_vindicator.png) - }, - }, + head_swivel = "head.control", + bone_eye_height = 2.2, + head_eye_height = 2.2, + curiosity = 10, + textures = { + { + "mobs_mc_vindicator.png", + "blank.png", --no hat + "default_tool_steelaxe.png", + -- TODO: Glow when attacking (mobs_mc_vindicator.png) + }, + }, visual_size = {x=2.75, y=2.75}, makes_footstep_sound = true, damage = 13, @@ -73,4 +77,4 @@ mcl_mobs:register_mob("mobs_mc:vindicator", { }) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:vindicator", S("Vindicator"), "mobs_mc_spawn_icon_vindicator.png", 0) +mcl_mobs.register_egg("mobs_mc:vindicator", S("Vindicator"), "#959b9b", "#275e61", 0) diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index cbb4fa1d3..9a1e30e70 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -25,7 +25,7 @@ local professions = { nitwit = "mobs_mc_villager.png", } -mcl_mobs:register_mob("mobs_mc:villager_zombie", { +mcl_mobs.register_mob("mobs_mc:villager_zombie", { description = S("Zombie Villager"), type = "monster", spawn_class = "hostile", @@ -39,13 +39,16 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", { collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_villager_zombie.b3d", + head_swivel = "Head_Control", + bone_eye_height = 2.35, + curiosity = 2, textures = { - {"mobs_mc_empty.png", "mobs_mc_zombie_butcher.png", "mobs_mc_empty.png"}, - {"mobs_mc_empty.png", "mobs_mc_zombie_farmer.png", "mobs_mc_empty.png"}, - {"mobs_mc_empty.png", "mobs_mc_zombie_librarian.png", "mobs_mc_empty.png"}, - {"mobs_mc_empty.png", "mobs_mc_zombie_priest.png", "mobs_mc_empty.png"}, - {"mobs_mc_empty.png", "mobs_mc_zombie_smith.png", "mobs_mc_empty.png"}, - {"mobs_mc_empty.png", "mobs_mc_zombie_villager.png", "mobs_mc_empty.png"}, + {"mobs_mc_zombie_butcher.png"}, + {"mobs_mc_zombie_farmer.png"}, + {"mobs_mc_zombie_librarian.png"}, + {"mobs_mc_zombie_priest.png"}, + {"mobs_mc_zombie_smith.png"}, + {"mobs_mc_zombie_villager.png"}, }, visual_size = {x=2.75, y=2.75}, makes_footstep_sound = true, @@ -228,4 +231,4 @@ mcl_vars.mg_overworld_max) --mcl_mobs:spawn_specific("mobs_mc:villager_zombie", "overworld", "ground", 0, 7, 30, 60000, 4, mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:villager_zombie", S("Zombie Villager"), "mobs_mc_spawn_icon_zombie_villager.png", 0) +mcl_mobs.register_egg("mobs_mc:villager_zombie", S("Zombie Villager"), "#563d33", "#799c66", 0) diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index f61fdb2d1..266d5b0c3 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -12,10 +12,11 @@ local S = minetest.get_translator("mobs_mc") -mcl_mobs:register_mob("mobs_mc:witch", { +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, @@ -72,7 +73,7 @@ mcl_mobs:register_mob("mobs_mc:witch", { }) -- potion projectile (EXPERIMENTAL) -mcl_mobs:register_arrow("mobs_mc:potion_arrow", { +mcl_mobs.register_arrow("mobs_mc:potion_arrow", { visual = "sprite", visual_size = {x = 0.5, y = 0.5}, --textures = {"vessels_glass_bottle.png"}, --TODO fix to else if default @@ -104,6 +105,6 @@ mcl_mobs:register_arrow("mobs_mc:potion_arrow", { --mcl_mobs:spawn_specific("mobs_mc:witch", { "mcl_core:jungletree", "mcl_core:jungleleaves", "mcl_flowers:fern", "mcl_core:vine" }, {"air"}, 0, minetest.LIGHT_MAX-6, 12, 20000, 2, mobs_mc.water_level-6, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:witch", S("Witch"), "mobs_mc_spawn_icon_witch.png", 0, true) +mcl_mobs.register_egg("mobs_mc:witch", S("Witch"), "#340000", "#51a03e", 0, true) mcl_wip.register_wip_item("mobs_mc:witch") diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 3b47d0752..dda2beafa 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -9,7 +9,7 @@ local S = minetest.get_translator("mobs_mc") --################### WITHER --################### -mcl_mobs:register_mob("mobs_mc:wither", { +mcl_mobs.register_mob("mobs_mc:wither", { description = S("Wither"), type = "monster", spawn_class = "hostile", @@ -42,7 +42,7 @@ mcl_mobs:register_mob("mobs_mc:wither", { fly = true, makes_footstep_sound = false, dogshoot_switch = 1, - dogshoot_count_max =1, + dogshoot_count_max = 1, attack_animals = true, can_despawn = false, drops = { @@ -79,11 +79,13 @@ mcl_mobs:register_mob("mobs_mc:wither", { on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) end, + }) local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local wither_rose_soil = { "group:grass_block", "mcl_core:dirt", "mcl_core:coarse_dirt", "mcl_nether:netherrack", "group:soul_block", "mcl_mud:mud", "mcl_moss:moss" } -mcl_mobs:register_arrow("mobs_mc:wither_skull", { +mcl_mobs.register_arrow("mobs_mc:wither_skull", { visual = "sprite", visual_size = {x = 0.75, y = 0.75}, -- TODO: 3D projectile, replace tetxture @@ -96,7 +98,7 @@ mcl_mobs:register_arrow("mobs_mc:wither_skull", { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) - mcl_mobs:boom(self, self.object:get_pos(), 1) + mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) end, hit_mob = function(self, mob) @@ -104,17 +106,29 @@ mcl_mobs:register_arrow("mobs_mc:wither_skull", { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, }, nil) - mcl_mobs:boom(self, self.object:get_pos(), 1) + mcl_mobs.mob_class.boom(self,self.object:get_pos(), 1) + local l = mob:get_luaentity() + if l and l.health - 8 <= 0 then + local n = minetest.find_node_near(mob:get_pos(),2,wither_rose_soil) + if n then + local p = vector.offset(n,0,1,0) + if minetest.get_node(p).name == "air" then + if not ( mobs_griefing and minetest.place_node(p,{name="mcl_flowers:wither_rose"}) ) then + minetest.add_item(p,"mcl_flowers:wither_rose") + end + end + end + end end, -- node hit, explode hit_node = function(self, pos, node) - mcl_mobs:boom(self, pos, 1) + mcl_mobs.mob_class.boom(self,pos, 1) end }) -- TODO: Add blue wither skull --Spawn egg -mcl_mobs:register_egg("mobs_mc:wither", S("Wither"), "mobs_mc_spawn_icon_wither.png", 0, true) +mcl_mobs.register_egg("mobs_mc:wither", S("Wither"), "#4f4f4f", "#4f4f4f", 0, true) mcl_wip.register_wip_item("mobs_mc:wither") diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index 87b21eeb7..922069508 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -25,8 +25,13 @@ local wolf = { textures = { {"mobs_mc_wolf.png"}, }, - visual_size = {x=3, y=3}, makes_footstep_sound = true, + head_swivel = "head.control", + bone_eye_height = 3.5, + head_eye_height = 1.1, + horrizonatal_head_height=0, + curiosity = 3, + head_yaw="z", sounds = { attack = "mobs_mc_wolf_bark", war_cry = "mobs_mc_wolf_growl", @@ -66,7 +71,7 @@ local wolf = { ent = dog:get_luaentity() ent.owner = clicker:get_player_name() ent.tamed = true - mcl_mobs:set_animation(ent, "sit") + ent:set_animation("sit") ent.walk_chance = 0 ent.jump = false ent.health = self.health @@ -78,11 +83,16 @@ local wolf = { end end, animation = { - speed_normal = 50, speed_run = 100, - stand_start = 0, stand_end = 40, - walk_start = 40, walk_end = 80, - run_start = 80, run_end = 120, - sit_start = 121, sit_end = 140, + stand_start = 0, stand_end = 0, + walk_start = 0, walk_end = 40, walk_speed = 50, + run_start = 0, run_end = 40, run_speed = 100, + sit_start = 45, sit_end = 45, + }, + child_animations = { + stand_start = 46, stand_end = 46, + walk_start = 46, walk_end = 86, walk_speed = 75, + run_start = 46, run_end = 86, run_speed = 150, + sit_start = 91, sit_end = 91, }, jump = true, attacks_monsters = true, @@ -90,7 +100,7 @@ local wolf = { specific_attack = { "player", "mobs_mc:sheep" }, } -mcl_mobs:register_mob("mobs_mc:wolf", wolf) +mcl_mobs.register_mob("mobs_mc:wolf", wolf) -- Tamed wolf @@ -157,7 +167,7 @@ end dog.on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() - if mcl_mobs:feed_tame(self, clicker, 1, true, false) then + if self:feed_tame(clicker, 1, true, false) then return elseif mcl_mobs:protect(self, clicker) then return @@ -184,45 +194,17 @@ dog.on_rightclick = function(self, clicker) end end else - -- Toggle sitting order - if not self.owner or self.owner == "" then - -- Huh? This wolf has no owner? Let's fix this! This should never happen. + -- Huh? This dog has no owner? Let's fix this! This should never happen. self.owner = clicker:get_player_name() end - - local pos = self.object:get_pos() - local particle - if not self.order or self.order == "" or self.order == "sit" then - particle = "mobs_mc_wolf_icon_roam.png" - self.order = "roam" - self.state = "stand" - self.walk_chance = default_walk_chance - self.jump = true - mcl_mobs:set_animation(self, "stand") - -- TODO: Add sitting model - else - particle = "mobs_mc_wolf_icon_sit.png" - self.order = "sit" - self.state = "stand" - self.walk_chance = 0 - self.jump = false - mcl_mobs:set_animation(self, "sit") + if not minetest.settings:get_bool("mcl_extended_pet_control",true) then + self:toggle_sit(clicker,-0.4) end - -- Display icon to show current order (sit or roam) - minetest.add_particle({ - pos = vector.add(pos, {x=0,y=1,z=0}), - velocity = {x=0,y=0.2,z=0}, - expirationtime = 1, - size = 4, - texture = particle, - playername = self.owner, - glow = minetest.LIGHT_MAX, - }) end end -mcl_mobs:register_mob("mobs_mc:dog", dog) +mcl_mobs.register_mob("mobs_mc:dog", dog) -- Spawn mcl_mobs:spawn_specific( "mobs_mc:wolf", @@ -248,4 +230,4 @@ minetest.LIGHT_MAX+1, mobs_mc.water_level+3, mcl_vars.mg_overworld_max) -mcl_mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0) +mcl_mobs.register_egg("mobs_mc:wolf", S("Wolf"), "#d7d3d3", "#ceaf96", 0) diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 5ae7e922f..358579dbd 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -53,7 +53,13 @@ local zombie = { hp_max = 20, xp_min = 5, xp_max = 5, + head_swivel = "head.control", + bone_eye_height = 6.3, + head_eye_height = 2.2, + curiosity = 7, + head_pitch_multiplier=-1, breath_max = -1, + wears_armor = 1, armor = {undead = 90, fleshy = 90}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.8, 0.3}, visual = "mesh", @@ -62,7 +68,6 @@ local zombie = { { "mobs_mc_empty.png", -- armor "mobs_mc_zombie.png", -- texture - "mobs_mc_empty.png", -- wielded_item } }, makes_footstep_sound = true, @@ -94,17 +99,10 @@ local zombie = { view_range = 16, attack_type = "dogfight", harmed_by_heal = true, - on_spawn = function(self) - -- Remove saved visual_size on old existing entites. - -- Old entities were 3 now it's 1. - self.visual_size = nil - self.object:set_properties({visual_size = self.visual_size}) - self.base_size = self.visual_size - end, attack_npcs = true, } -mcl_mobs:register_mob("mobs_mc:zombie", zombie) +mcl_mobs.register_mob("mobs_mc:zombie", zombie) -- Baby zombie. -- A smaller and more dangerous variant of the zombie @@ -114,7 +112,6 @@ baby_zombie.description = S("Baby Zombie") baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 1, 0.25} baby_zombie.xp_min = 12 baby_zombie.xp_max = 12 -baby_zombie.visual_size = {x = 1 / 2, y = 1 / 2} baby_zombie.walk_velocity = 1.2 baby_zombie.run_velocity = 2.4 baby_zombie.child = 1 @@ -126,7 +123,7 @@ baby_zombie.animation = { punch_start = 109, punch_end = 119 } -mcl_mobs:register_mob("mobs_mc:baby_zombie", baby_zombie) +mcl_mobs.register_mob("mobs_mc:baby_zombie", baby_zombie) -- Husk. -- Desert variant of the zombie @@ -136,7 +133,6 @@ husk.textures = { { "mobs_mc_empty.png", -- armor "mobs_mc_husk.png", -- texture - "mobs_mc_empty.png", -- wielded_item } } husk.ignited_by_sunlight = false @@ -144,22 +140,21 @@ husk.sunlight_damage = 0 husk.drops = drops_common -- TODO: Husks avoid water -mcl_mobs:register_mob("mobs_mc:husk", husk) +mcl_mobs.register_mob("mobs_mc:husk", husk) -- Baby husk. -- A smaller and more dangerous variant of the husk local baby_husk = table.copy(baby_zombie) baby_husk.description = S("Baby Husk") baby_husk.textures = {{ - "mobs_mc_empty.png", -- armor - "mobs_mc_husk.png", -- texture "mobs_mc_empty.png", -- wielded_item + "mobs_mc_husk.png", -- texture }} baby_husk.ignited_by_sunlight = false baby_husk.sunlight_damage = 0 baby_husk.drops = drops_common -mcl_mobs:register_mob("mobs_mc:baby_husk", baby_husk) +mcl_mobs.register_mob("mobs_mc:baby_husk", baby_husk) -- Spawning @@ -373,5 +368,5 @@ mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- Spawn eggs -mcl_mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0) -mcl_mobs:register_egg("mobs_mc:zombie", S("Zombie"), "mobs_mc_spawn_icon_zombie.png", 0) +mcl_mobs.register_egg("mobs_mc:husk", S("Husk"), "#777361", "#ded88f", 0) +mcl_mobs.register_egg("mobs_mc:zombie", S("Zombie"), "#00afaf", "#799c66", 0) diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 33838a9b5..4e89db4f6 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -25,6 +25,10 @@ local pigman = { group_attack = { "mobs_mc:pigman", "mobs_mc:baby_pigman" }, damage = 9, reach = 2, + head_swivel = "head.control", + bone_eye_height = 2.4, + head_eye_height = 1.4, + curiosity = 15, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_zombie_pigman.b3d", @@ -89,7 +93,7 @@ local pigman = { fire_damage_resistant = true, } -mcl_mobs:register_mob("mobs_mc:pigman", pigman) +mcl_mobs.register_mob("mobs_mc:pigman", pigman) -- Baby pigman. -- A smaller and more dangerous variant of the pigman @@ -99,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 @@ -110,7 +113,7 @@ baby_pigman.run_velocity = 2.4 baby_pigman.light_damage = 0 baby_pigman.child = 1 -mcl_mobs:register_mob("mobs_mc:baby_pigman", baby_pigman) +mcl_mobs.register_mob("mobs_mc:baby_pigman", baby_pigman) -- Regular spawning in the Nether mcl_mobs:spawn_specific( @@ -149,4 +152,4 @@ mcl_vars.mg_nether_max) --mobs:spawn_specific("mobs_mc:pigman", {"mcl_portals:portal"}, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mcl_vars.mg_overworld_min, mcl_vars.mg_overworld_max) -- spawn eggs -mcl_mobs:register_egg("mobs_mc:pigman", S("Zombie Pigman"), "mobs_mc_spawn_icon_zombie_pigman.png", 0) +mcl_mobs.register_egg("mobs_mc:pigman", S("Zombie Pigman"), "#ea9393", "#4c7129", 0) diff --git a/mods/ENVIRONMENT/lightning/init.lua b/mods/ENVIRONMENT/lightning/init.lua index 32ff721b2..59591b061 100644 --- a/mods/ENVIRONMENT/lightning/init.lua +++ b/mods/ENVIRONMENT/lightning/init.lua @@ -107,29 +107,7 @@ local function choose_pos(pos) return pos, pos2 end --- * pos: optional, if not given a random pos will be chosen --- * returns: bool - success if a strike happened -function lightning.strike(pos) - if lightning.auto then - after(rng:next(lightning.interval_low, lightning.interval_high), lightning.strike) - end - - local pos2 - pos, pos2 = choose_pos(pos) - - if not pos then - return false - end - if lightning.on_strike_functions then - for _, func in pairs(lightning.on_strike_functions) do - -- allow on_strike callbacks to destroy entities by re-obtaining objects for each callback - local objects = get_objects_inside_radius(pos2, 3.5) - func(pos, pos2, objects) - end - end -end - -lightning.register_on_strike(function(pos, pos2, objects) +function lightning.strike_func(pos, pos2, objects) local particle_pos = vector.offset(pos2, 0, (lightning.size / 2) + 0.5, 0) local particle_size = lightning.size * 10 local time = 0.2 @@ -157,25 +135,11 @@ lightning.register_on_strike(function(pos, pos2, objects) -- damage nearby objects, transform mobs for _, obj in pairs(objects) do local lua = obj:get_luaentity() - if lua and lua._on_strike then - lua._on_strike(lua, pos, pos2, objects) - end - -- remove this when mob API is done - if lua and lua.name == "mobs_mc:pig" then - mcl_util.replace_mob(obj, "mobs_mc:pigman") - elseif lua and lua.name == "mobs_mc:mooshroom" then - if lua.base_texture[1] == "mobs_mc_mooshroom.png" then - lua.base_texture = { "mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } - else - lua.base_texture = { "mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png" } + if lua then + if not lua.on_lightning_strike or ( lua.on_lightning_strike and lua.on_lightning_strike(lua, pos, pos2, objects) ~= true ) then + mcl_util.deal_damage(obj, 5, { type = "lightning_bolt" }) end - obj:set_properties({ textures = lua.base_texture }) - elseif lua and lua.name == "mobs_mc:villager" then - mcl_util.replace_mob(obj, "mobs_mc:witch") - elseif lua and lua.name == "mobs_mc:creeper" then - mcl_util.replace_mob(obj, "mobs_mc:creeper_charged") else - -- WARNING: unsafe entity handling. object may be removed immediately mcl_util.deal_damage(obj, 5, { type = "lightning_bolt" }) end end @@ -230,7 +194,38 @@ lightning.register_on_strike(function(pos, pos2, objects) end end end -end) +end + +-- * pos: optional, if not given a random pos will be chosen +-- * returns: bool - success if a strike happened +function lightning.strike(pos) + if lightning.auto then + after(rng:next(lightning.interval_low, lightning.interval_high), lightning.strike) + end + + local pos2 + pos, pos2 = choose_pos(pos) + + if not pos then + return false + end + local do_strike = true + if lightning.on_strike_functions then + for _, func in pairs(lightning.on_strike_functions) do + -- allow on_strike callbacks to destroy entities by re-obtaining objects for each callback + local objects = get_objects_inside_radius(pos2, 3.5) + local p,stop = func(pos, pos2, objects) + if p then + pos = p + pos2 = choose_pos(p) + end + do_strike = do_strike and not stop + end + end + if do_strike then + lightning.strike_func(pos,pos2,get_objects_inside_radius(pos2, 3.5)) + end +end -- if other mods disable auto lightning during initialization, don't trigger the first lightning. after(5, function(dtime) diff --git a/mods/ENVIRONMENT/mcl_raids/init.lua b/mods/ENVIRONMENT/mcl_raids/init.lua new file mode 100644 index 000000000..f96e90c8e --- /dev/null +++ b/mods/ENVIRONMENT/mcl_raids/init.lua @@ -0,0 +1,394 @@ +-- mcl_raids +mcl_raids = {} +local S = minetest.get_translator(minetest.get_current_modname()) + +-- Define the amount of illagers to spawn each wave. +local waves = { + { + ["mobs_mc:pillager"] = 5, + ["mobs_mc:vindicator"] = 1, + }, + { + ["mobs_mc:pillager"] = 4, + ["mobs_mc:vindicator"] = 3, + }, + { + ["mobs_mc:pillager"] = 4, + ["mobs_mc:vindicator"] = 1, + ["mobs_mc:witch"] = 1, + --["mobs_mc:ravager"] = 1, + }, + { + ["mobs_mc:pillager"] = 5, + ["mobs_mc:vindicator"] = 2, + ["mobs_mc:witch"] = 3, + }, + { + ["mobs_mc:pillager"] = 5, + ["mobs_mc:vindicator"] = 5, + ["mobs_mc:witch"] = 1, + ["mobs_mc:evoker"] = 1, + }, +} + +local extra_wave = { + ["mobs_mc:pillager"] = 5, + ["mobs_mc:vindicator"] = 5, + ["mobs_mc:witch"] = 1, + ["mobs_mc:evoker"] = 1, + --["mobs_mc:ravager"] = 2, +} + +local oban_layers = { + { + pattern = "rhombus", + color = "unicolor_cyan" + }, + { + color = "unicolor_grey", + pattern = "stripe_bottom" + }, + { + pattern = "stripe_center", + color = "unicolor_darkgrey" + }, + { + color = "unicolor_black", + pattern = "stripe_middle" + }, + { + pattern = "half_horizontal", + color = "unicolor_grey" + }, + { + color = "unicolor_grey", + pattern = "circle" + }, + { + pattern = "border", + color = "unicolor_black" + } +} + + +local oban_def = table.copy(minetest.registered_entities["mcl_banners:standing_banner"]) +oban_def.visual_size = { x=1, y=1 } +local old_step = oban_def.on_step +oban_def.on_step = function(self,dtime) + if not self.object:get_attach() then return self.object:remove() end + if old_step then return old_step(self.dtime) end +end + +minetest.register_entity(":mcl_raids:ominous_banner",oban_def) + +function mcl_raids.drop_obanner(pos) + local it = ItemStack("mcl_banners:banner_item_white") + it:get_meta():set_string("layers",minetest.serialize(oban_layers)) + it:get_meta():set_string("name",S("Ominous Banner")) + minetest.add_item(pos,it) +end + +function mcl_raids.promote_to_raidcaptain(c) -- object + if not c or not c:get_pos() then return end + local pos = c:get_pos() + local l = c:get_luaentity() + l._banner = minetest.add_entity(pos,"mcl_raids:ominous_banner") + l._banner:set_properties({textures = {mcl_banners.make_banner_texture("unicolor_white", oban_layers)}}) + l._banner:set_attach(c,"",vector.new(-1,5.5,0),vector.new(0,0,0),true) + l._raidcaptain = true + local old_ondie = l.on_die + l.on_die = function(self, pos, cmi_cause) + if l._banner then + l._banner:remove() + l._banner = nil + mcl_raids.drop_obanner(pos) + if cmi_cause and cmi_cause.type == "punch" and cmi_cause.puncher:is_player() then + awards.unlock(cmi_cause.puncher:get_player_name(), "mcl:voluntary_exile") + local lv = mcl_potions.player_get_effect(cmi_cause.puncher, "bad_omen") + if not lv then lv = 0 + else lv = lv.factor end + lv = math.max(5,lv + 1) + mcl_potions.bad_omen_func(cmi_cause.puncher,lv,6000) + end + end + if old_ondie then return old_ondie(self,pos,cmi_cause) end + end +end + +function mcl_raids.is_raidcaptain_near(pos) + for k,v in pairs(minetest.get_objects_inside_radius(pos,32)) do + local l = v:get_luaentity() + if l and l._raidcaptain then return true end + end +end + +function mcl_raids.register_possible_raidcaptain(mob) + local old_on_spawn = minetest.registered_entities[mob].on_spawn + local old_on_pick_up = minetest.registered_entities[mob].on_pick_up + if not minetest.registered_entities[mob].pick_up then minetest.registered_entities[mob].pick_up = {} end + table.insert(minetest.registered_entities[mob].pick_up,"mcl_banners:banner_item_white") + minetest.registered_entities[mob].on_pick_up = function(self,e) + local stack = ItemStack(e.itemstring) + if not self._raidcaptain and stack:get_meta():get_string("name"):find("Ominous Banner") then + stack:take_item(1) + mcl_raids.promote_to_raidcaptain(self.object) + return stack + end + if old_on_pick_up then return old_on_pick_up(self,e) end + end + minetest.registered_entities[mob].on_spawn = function(self) + if not mcl_raids.is_raidcaptain_near(self.object:get_pos()) then + mcl_raids.promote_to_raidcaptain(self.object) + end + if old_on_spawn then return old_on_spawn(self) end + end +end + +mcl_raids.register_possible_raidcaptain("mobs_mc:pillager") +mcl_raids.register_possible_raidcaptain("mobs_mc:vindicator") +mcl_raids.register_possible_raidcaptain("mobs_mc:evoker") + +function mcl_raids.spawn_raid(event) + local pos = event.pos + local wave = event.stage + local illager_count = 0 + local spawnable = false + local r = 32 + local n = 12 + local i = math.random(1, n) + local raid_pos = vector.offset(pos,r * math.cos(((i-1)/n) * (2*math.pi)),0, r * math.sin(((i-1)/n) * (2*math.pi))) + local sn = minetest.find_nodes_in_area_under_air(vector.offset(raid_pos,-5,-50,-5), vector.offset(raid_pos,5,50,5), {"group:grass_block", "group:grass_block_snow", "group:snow_cover", "group:sand", "mcl_core:ice"}) + mcl_bells.ring_once(pos) + if sn and #sn > 0 then + local spawn_pos = sn[math.random(#sn)] + if spawn_pos then + minetest.log("action", "[mcl_raids] Raid Spawn Position chosen at " .. minetest.pos_to_string(spawn_pos) .. ".") + event.health_max = 0 + local w + if event.stage <= #waves then + w= waves[event.stage] + else + w = extra_wave + end + for m,c in pairs(w) do + for i=1,c do + local p = vector.offset(spawn_pos,0,1,0) + local mob = mcl_mobs.spawn(p,m) + local l = mob:get_luaentity() + if l then + l.raidmob = true + event.health_max = event.health_max + l.health + table.insert(event.mobs,mob) + --minetest.log("action", "[mcl_raids] Here we go. Raid time") + l:gopath(pos) + end + end + end + if event.stage == 1 then + table.shuffle(event.mobs) + mcl_raids.promote_to_raidcaptain(event.mobs[1]) + end + minetest.log("action", "[mcl_raids] Raid Spawned. Illager Count: " .. #event.mobs .. ".") + return #event.mobs == 0 + else + minetest.log("action", "[mcl_raids] Raid Spawn Postion not chosen.") + end + elseif not sn then + minetest.log("action", "[mcl_raids] Raid Spawn Position error, no appropriate site found.") + end + return true +end + +function mcl_raids.find_villager(pos) + local obj = minetest.get_objects_inside_radius(pos, 8) + for _, objects in ipairs(obj) do + local object = objects:get_luaentity() + if object then + if object.name ~= "mobs_mc:villager" then + return + elseif object.name == "mobs_mc:villager" then + --minetest.log("action", "[mcl_raids] Villager Found.") + return true + else + --minetest.log("action", "[mcl_raids] No Villager Found.") + return false + end + end + end +end + +function mcl_raids.find_bed(pos) + return minetest.find_node_near(pos,128,{"mcl_beds:bed_red_bottom"}) +end + +function mcl_raids.find_village(pos) + local bed = mcl_raids.find_bed(pos) + if bed and mcl_raids.find_villager(bed) then + return bed + end +end + +local function get_point_on_circle(pos,r,n) + local rt = {} + for i=1, n do + table.insert(rt,vector.offset(pos,r * math.cos(((i-1)/n) * (2*math.pi)),0, r* math.sin(((i-1)/n) * (2*math.pi)) )) + end + table.shuffle(rt) + return rt[1] +end + +local function start_firework_rocket(pos) + local p = get_point_on_circle(pos,math.random(32,64),32) + local n = minetest.get_node(p) + local l = minetest.get_natural_light(pos,0.5) + if n.name ~= "air" or l <= minetest.LIGHT_MAX then return end + local o = minetest.add_entity(p,"mcl_bows:rocket_entity") + o:get_luaentity()._harmless = true + o:set_acceleration(vector.new(math.random(0,2),math.random(30,50),math.random(0,2))) +end + +local function make_firework(pos,stime) + if os.time() - stime > 60 then return end + for i=1,math.random(25) do + minetest.after(math.random(i),start_firework_rocket,pos) + end + minetest.after(10,make_firework,pos,stime) +end + +local function is_player_near(self) + for _,pl in pairs(minetest.get_connected_players()) do + if self.pos and vector.distance(pl:get_pos(),self.pos) < 64 then return true end + end +end + +local function check_mobs(self) + local m = {} + local h = 0 + for k,o in pairs(self.mobs) do + if o and o:get_pos() then + local l = o:get_luaentity() + h = h + l.health + table.insert(m,o) + end + end + if #m == 0 then --if no valid mobs in table search if there are any (reloaded ones) in the area + for k,o in pairs(minetest.get_objects_inside_radius(self.pos,64)) do + local l = o:get_luaentity() + if l and l.raidmob then + local l = o:get_luaentity() + h = h + l.health + table.insert(m,o) + end + end + end + self.mobs = m + return h +end + +mcl_events.register_event("raid",{ + readable_name = "Raid", + max_stage = 5, + health = 1, + health_max = 1, + exclusive_to_area = 128, + enable_bossbar = true, + cond_start = function(self) + local r = {} + for _,p in pairs(minetest.get_connected_players()) do + if mcl_potions.player_has_effect(p,"bad_omen") then + local raid_pos = mcl_raids.find_village(p:get_pos()) + if raid_pos then + table.insert(r,{ player = p:get_player_name(), pos = raid_pos }) + end + end + end + if #r > 0 then return r end + end, + on_start = function(self) + self.mobs = {} + self.health_max = 1 + self.health = 0 + local lv = mcl_potions.player_get_effect(minetest.get_player_by_name(self.player), "bad_omen") + if lv and lv.factor and lv.factor > 1 then self.max_stage = 6 end + end, + cond_progress = function(self) + if not is_player_near(self) then return false end + self.health = check_mobs(self) + self.percent = math.max(0,(self.health / self.health_max ) * 100) + if #self.mobs < 1 then + return true end + end, + on_stage_begin = mcl_raids.spawn_raid, + cond_complete = function(self) + if not is_player_near(self) then return false end + --let the event api handle cancel the event when no players are near + --without this check it would sort out the unloaded mob entities and + --think the raid is defeated. + check_mobs(self) + return self.stage >= self.max_stage and #self.mobs < 1 + end, + on_complete = function(self) + awards.unlock(self.player,"mcl:hero_of_the_village") + mcl_potions.player_clear_effect(minetest.get_player_by_name(self.player),"bad_omen") + make_firework(self.pos,os.time()) + end, +}) + +minetest.register_chatcommand("raidcap",{ + privs = {debug = true}, + func = function(pname,param) + local c = minetest.add_entity(minetest.get_player_by_name(pname):get_pos(),"mobs_mc:pillager") + mcl_raids.promote_to_raidcaptain(c) + end, +}) + +minetest.register_chatcommand("dump_banner_layers",{ + privs = {debug = true}, + func = function(pname,param) + local p = minetest.get_player_by_name(pname) + mcl_raids.drop_obanner(vector.offset(p:get_pos(),1,1,1)) + for k,v in pairs(minetest.get_objects_inside_radius(p:get_pos(),5)) do + local l = v:get_luaentity() + if l and l.name == "mcl_banners:standing_banner" then + minetest.log(dump(l._base_color)) + minetest.log(dump(l._layers)) + end + end + end +}) + +local function is_new_years() + local d = os.date("*t") + return d.month == 1 and d.day == 1 and d.hour < 1 +end + +mcl_events.register_event("new_years",{ + stage = 0, + max_stage = 1, + readable_name = "New Years", + pos = vector.new(0,0,0), + exclusive_to_area = 256, + cond_start = function(event) + if not is_new_years() then return false end + local r = {} + for _,p in pairs(minetest.get_connected_players()) do + table.insert(r,{ player = p:get_player_name(), pos = p:get_pos()}) + end + return r + end, + on_start = function(self) + minetest.chat_send_player(self.player," Happy new year <3") + end, + on_step = function(self,dtime) + if not self.timer or self.timer < 0 then + self.timer = math.random(1,5) + for i=1,math.random(8) do + minetest.after(math.random(i),start_firework_rocket,minetest.get_player_by_name(self.player):get_pos()) + end + end + self.timer = self.timer - dtime + end, + cond_complete = function(event) + return not is_new_years() + end, --return success +}) diff --git a/mods/ENVIRONMENT/mcl_raids/mod.conf b/mods/ENVIRONMENT/mcl_raids/mod.conf new file mode 100644 index 000000000..b4616e56b --- /dev/null +++ b/mods/ENVIRONMENT/mcl_raids/mod.conf @@ -0,0 +1,3 @@ +name = mcl_raids +author = PrairieWind +depends = mcl_events, mobs_mc, mcl_potions, mcl_bells, mcl_achievements diff --git a/mods/ENVIRONMENT/mcl_raids/textures/mcl_raids_hero_of_the_village_icon.png b/mods/ENVIRONMENT/mcl_raids/textures/mcl_raids_hero_of_the_village_icon.png new file mode 100644 index 000000000..0db5d9613 Binary files /dev/null and b/mods/ENVIRONMENT/mcl_raids/textures/mcl_raids_hero_of_the_village_icon.png differ diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index a4108598f..6fb8ab56c 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -1,7 +1,11 @@ local mods_loaded = false local NIGHT_VISION_RATIO = 0.45 +local water_color = "#0b4880" + function mcl_weather.set_sky_box_clear(player) + local pos = player:get_pos() + if minetest.get_item_group(minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name, "water") ~= 0 then return end player:set_sky({ type = "regular", sky_color = { @@ -16,6 +20,16 @@ function mcl_weather.set_sky_box_clear(player) }) end +function mcl_weather.set_sky_color(player, def) + local pos = player:get_pos() + if minetest.get_item_group(minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name, "water") ~= 0 then return end + player:set_sky({ + type = def.type, + sky_color = def.sky_color, + clouds = def.clouds, + }) +end + mcl_weather.skycolor = { -- Should be activated before do any effect. active = true, @@ -96,6 +110,19 @@ mcl_weather.skycolor = { local pos = player:get_pos() local dim = mcl_worlds.pos_to_dimension(pos) local has_weather = (mcl_worlds.has_weather(pos) and (mcl_weather.state == "snow" or mcl_weather.state =="rain" or mcl_weather.state == "thunder") and mcl_weather.has_snow(pos)) or ((mcl_weather.state =="rain" or mcl_weather.state == "thunder") and mcl_weather.has_rain(pos)) + if minetest.get_item_group(minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name, "water") ~= 0 then + player:set_sky({ type = "regular", + sky_color = { + day_sky = water_color, + day_horizon = water_color, + dawn_sky = water_color, + dawn_horizon = water_color, + night_sky = water_color, + night_horizon = water_color, + }, + clouds = true, + }) + end if dim == "overworld" then if (mcl_weather.state == "none") then -- Clear weather @@ -108,7 +135,8 @@ mcl_weather.skycolor = { local day_color = mcl_weather.skycolor.get_sky_layer_color(0.15) local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.27) local night_color = mcl_weather.skycolor.get_sky_layer_color(0.1) - player:set_sky({ type = "regular", + mcl_weather.set_sky_color(player, { + type = "regular", sky_color = { day_sky = day_color, day_horizon = day_color, @@ -127,7 +155,8 @@ mcl_weather.skycolor = { local day_color = mcl_weather.skycolor.get_sky_layer_color(0.5) local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.75) local night_color = mcl_weather.skycolor.get_sky_layer_color(0) - player:set_sky({ type = "regular", + mcl_weather.set_sky_color(player, { + type = "regular", sky_color = { day_sky = day_color, day_horizon = day_color, @@ -178,7 +207,7 @@ mcl_weather.skycolor = { } local biometint = nether_sky[minetest.get_biome_name(minetest.get_biome_data(player:get_pos()).biome)] - player:set_sky({ + mcl_weather.set_sky_color(player, { type = "regular", sky_color = { day_sky = "#300808", diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index a756c6e7f..8de0dc0ae 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -153,12 +153,17 @@ minetest.register_abm({ neighbors = {"air"}, interval = 27, chance = 33, + min_y = mcl_vars.mg_overworld_min, action = function(pos, node, active_object_count, active_object_count_wider) - if node.name == "mcl_core:snowblock" then return end + if (mcl_weather.state ~= "rain" and mcl_weather.state ~= "thunder" and mcl_weather.state ~= "snow") + or not mcl_weather.has_snow(pos) + or node.name == "mcl_core:snowblock" then + return end + local above = vector.offset(pos,0,1,0) local above_node = minetest.get_node(above) - if above_node.name ~= "air" then return end - if (mcl_weather.state == "rain" or mcl_weather.state == "thunder" or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos) and mcl_weather.has_snow(pos) then + + if above_node.name == "air" and mcl_weather.is_outdoor(pos) then local nn = nil if node.name:find("snow") then local l = node.name:sub(-1) diff --git a/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua b/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua new file mode 100644 index 000000000..bf6e17dfa --- /dev/null +++ b/mods/ENVIRONMENT/mcl_zombie_sieges/init.lua @@ -0,0 +1,77 @@ + +local function check_spawn_pos(pos) + return minetest.get_natural_light(pos) < 7 +end + +local function spawn_zombies(self) + local nn = minetest.find_nodes_in_area_under_air(vector.offset(self.pos,-16,-16,-16),vector.offset(self.pos,16,16,16),{"group:solid"}) + table.shuffle(nn) + for i=1,20 do + local p = vector.offset(nn[i%#nn],0,1,0) + if check_spawn_pos(p) then + local m = mcl_mobs.spawn(p,"mobs_mc:zombie") + local l = m:get_luaentity() + l:gopath(self.pos) + table.insert(self.mobs,m) + self.health_max = self.health_max + l.health + end + end +end + +mcl_events.register_event("zombie_siege",{ + readable_name = "Zombie Siege", + max_stage = 1, + health = 1, + health_max = 1, + exclusive_to_area = 128, + enable_bossbar = false, + cond_start = function(self) + local pr = PseudoRandom(minetest.get_day_count()) + local rnd = pr:next(1,10) + local t = minetest.get_timeofday() + local r = {} + for _,p in pairs(minetest.get_connected_players()) do + local village = mcl_raids.find_village(p:get_pos()) + if t < 0.04 and village and rnd == 1 then + table.insert(r,{ player = p:get_player_name(), pos = village}) + end + end + if #r > 0 then return r end + end, + on_start = function(self) + self.mobs = {} + self.health_max = 1 + self.health = 0 + end, + cond_progress = function(self) + local m = {} + local h = 0 + for k,o in pairs(self.mobs) do + if o and o:get_pos() then + local l = o:get_luaentity() + h = h + l.health + table.insert(m,o) + end + end + self.mobs = m + self.health = h + self.percent = math.max(0,(self.health / self.health_max ) * 100) + if #m < 1 then + return true end + end, + on_stage_begin = spawn_zombies, + cond_complete = function(self) + local m = {} + for k,o in pairs(self.mobs) do + if o and o:get_pos() then + local l = o:get_luaentity() + table.insert(m,o) + end + end + return self.stage >= self.max_stage and #m < 1 + end, + on_complete = function(self) + --minetest.log("SIEGE complete") + --awards.unlock(self.player,"mcl:hero_of_the_village") + end, +}) diff --git a/mods/ENVIRONMENT/mcl_zombie_sieges/mod.conf b/mods/ENVIRONMENT/mcl_zombie_sieges/mod.conf new file mode 100644 index 000000000..0263d367a --- /dev/null +++ b/mods/ENVIRONMENT/mcl_zombie_sieges/mod.conf @@ -0,0 +1,3 @@ +name = mcl_zombie_sieges +author = cora +depends = mcl_events, mcl_raids diff --git a/mods/HUD/awards/api.lua b/mods/HUD/awards/api.lua index 49b11a6cf..2bbea3c9b 100644 --- a/mods/HUD/awards/api.lua +++ b/mods/HUD/awards/api.lua @@ -217,7 +217,7 @@ function awards.unlock(name, award) -- Get award minetest.log("action", name.." has gotten award "..award) - minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize(mcl_colors.GREEN, "[" .. (awdef.title or award) .. "]"))) + minetest.chat_send_all(S("@1 has made the advancement @2", name, minetest.colorize(mcl_colors.GREEN, "[" .. (awdef.title or award) .. "]"))) data.unlocked[award] = award awards.save() @@ -257,9 +257,13 @@ function awards.unlock(name, award) local custom_announce = awdef.custom_announce if not custom_announce then if awdef.secret then - custom_announce = S("Secret achievement gotten:") + custom_announce = S("Secret Advancement Made:") + elseif awdef.type == "Goal" then + custom_announce = S("Goal Completed:") + elseif awdef.type == "Challenge" then + custom_announce = S("Challenge Completed:") else - custom_announce = S("Achievement gotten:") + custom_announce = S("Advancement Made:") end end @@ -283,9 +287,13 @@ function awards.unlock(name, award) elseif awards.show_mode == "chat" then local chat_announce if awdef.secret == true then - chat_announce = S("Secret achievement gotten: @1") + chat_announce = S("Secret Advancement Made: @1") + elseif awdef.type == "Goal" then + chat_announce = S("Goal Completed: @1") + elseif awdef.type == "Challenge" then + chat_announce = S("Challenge Completed: @1") else - chat_announce = S("Achievement gotten: @1") + chat_announce = S("Advancement Made: @1") end -- use the chat console to send it minetest.chat_send_player(name, string.format(chat_announce, title)) @@ -306,9 +314,13 @@ function awards.unlock(name, award) }) local hud_announce if awdef.secret == true then - hud_announce = S("Secret achievement gotten!") + hud_announce = S("Secret Advancement Made!") + elseif awdef.type == "Goal" then + hud_announce = S("Goal Completed!") + elseif awdef.type == "Challenge" then + hud_announce = S("Challenge Completed!") else - hud_announce = S("Achievement gotten!") + hud_announce = S("Advancement Made!") end local two = player:hud_add({ hud_elem_type = "text", @@ -389,10 +401,10 @@ function awards.getFormspec(name, to, sid) local def = awards.def[item.name] if def and def.secret and not item.got then - formspec = formspec .. "label[1,2.75;"..minetest.formspec_escape(S("(Secret achievement)")).."]".. + formspec = formspec .. "label[1,2.75;"..minetest.formspec_escape(S("(Secret Advancement)")).."]".. "image[1,0;3,3;awards_unknown.png]" if def and def.description then - formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(S("Get this achievement to find out what it is."))..";]" + formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(S("Make this advancement to find out what it is."))..";]" end else local title = item.name @@ -450,7 +462,7 @@ function awards.getFormspec(name, to, sid) first = false if def.secret and not award.got then - formspec = formspec .. "#707070" .. minetest.formspec_escape(S("(Secret Award)")) + formspec = formspec .. "#707070" .. minetest.formspec_escape(S("(Secret Advancement)")) else local title = award.name if def and def.title then @@ -472,7 +484,7 @@ function awards.show_to(name, to, sid, text) name = to end if name == to and awards.player(to).disabled then - minetest.chat_send_player(S("You've disabled awards. Type /awards enable to reenable.")) + minetest.chat_send_player(name,S("You've disabled awards. Type /awards enable to reenable.")) return end if text then diff --git a/mods/HUD/awards/chat_commands.lua b/mods/HUD/awards/chat_commands.lua index 9b990fd0c..04371139f 100644 --- a/mods/HUD/awards/chat_commands.lua +++ b/mods/HUD/awards/chat_commands.lua @@ -18,48 +18,42 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("awards", { params = S("[c|clear|disable|enable]"), - description = S("Show, clear, disable or enable your achievements"), + description = S("Show, clear, disable or enable your advancements."), func = function(name, param) + if param == "enable" then + awards.enable(name) + minetest.chat_send_player(name, S("You have enabled your advancements.")) + return + end + + if awards.player(name).disabled then + minetest.chat_send_player(name, S("Awards are disabled, enable them first by using /awards enable!")) + return + end + if param == "clear" then - if awards.player(name).disabled ~= nil then - minetest.chat_send_player(name, S("Awards are disabled, enable them first by using /awards enable!")) - else - awards.clear_player(name) - minetest.chat_send_player(name, - S("All your awards and statistics have been cleared. You can now start again.")) - end + awards.clear_player(name) + minetest.chat_send_player(name, + S("All your awards and statistics have been cleared. You can now start again.")) elseif param == "disable" then awards.disable(name) - minetest.chat_send_player(name, S("You have disabled your achievements.")) - elseif param == "enable" then - awards.enable(name) - minetest.chat_send_player(name, S("You have enabled your achievements.")) - elseif param == "c" then - if awards.player(name).disabled ~= nil then - minetest.chat_send_player(name, S("Awards are disabled, enable them first by using /awards enable!")) - else - awards.show_to(name, name, nil, true) - end + minetest.chat_send_player(name, S("You have disabled your advancements.")) else - if awards.player(name).disabled ~= nil then - minetest.chat_send_player(name, S("Awards are disabled, enable them first by using /awards enable!")) - else - awards.show_to(name, name, nil, false) - end + awards.show_to(name, name, nil, false) end end }) -minetest.register_privilege("achievements", { - description = S("Can give achievements to any player"), +minetest.register_privilege("advancements", { + description = S("Can give advancements to any player"), give_to_singleplayer = false, give_to_admin = false, }) -minetest.register_chatcommand("achievement", { - params = S("(grant ( | all)) | list"), - privs = { achievements = true }, - description = S("Give achievement to player or list all achievements"), +minetest.register_chatcommand("advancement", { + params = S("(grant ( | all)) | list"), + privs = { advancements = true }, + description = S("Give advancement to player or list all advancements"), func = function(name, param) if param == "list" then local list = {} @@ -92,7 +86,7 @@ minetest.register_chatcommand("achievement", { awards.unlock(playername, achievement) return true, S("Done.") else - return false, S("Achievement “@1” does not exist.", achievement) + return false, S("Advancement “@1” does not exist.", achievement) end end }) diff --git a/mods/HUD/awards/locale/template.txt b/mods/HUD/awards/locale/template.txt index fa05b22b3..5312c2ba7 100644 --- a/mods/HUD/awards/locale/template.txt +++ b/mods/HUD/awards/locale/template.txt @@ -11,9 +11,9 @@ (Secret Award)= = = -Achievement gotten!= -Achievement gotten:= -Achievement gotten: @1= +Advancement Made!= +Advancement Made:= +Advancement: @1= Achievement not found.= All your awards and statistics have been cleared. You can now start again.= Awards= @@ -27,16 +27,16 @@ Join the game.= List awards in chat (deprecated)= Place a block: @1= Place blocks: @1×@2= -Secret achievement gotten!= -Secret achievement gotten:= -Secret achievement gotten: @1= +Secret Advancement Made!= +Secret Advancement Made:= +Secret Advancement Made: @1= Show details of an achievement= -Show, clear, disable or enable your achievements= -Get this achievement to find out what it is.= +Show, clear, disable or enable your advancements.= +Make this advancement to find out what it is.= Write @1 chat messages.= Write something in chat.= -You have disabled your achievements.= -You have enabled your achievements.= +You have disabled your advancements.= +You have enabled your advancements.= You have not gotten any awards.= You've disabled awards. Type /awards enable to reenable.= [c|clear|disable|enable]= @@ -49,16 +49,22 @@ Place @1 block(s).= Dig @1 block(s).= Eat @1 item(s).= Craft @1 item(s).= -Can give achievements to any player= -(grant ( | all)) | list= -Give achievement to player or list all achievements= +Can give advancements to any player= +(grant ( | all)) | list= +Give advancement to player or list all advancements= @1 (@2)= Invalid syntax.= Invalid action.= Player is not online.= Done.= -Achievement “@1” does not exist.= -@1 has made the achievement @2= +Advancement “@1” does not exist.= +@1 has made the advancement @2= Mine a block: @1= Mine blocks: @1×@2= Awards are disabled, enable them first by using /awards enable!= +Goal Completed:= +Goal Completed!= +Goal Completed: @1= +Challenge Completed:= +Challenge Completed!= +Challenge Completed: @1= diff --git a/mods/HUD/mcl_achievements/init.lua b/mods/HUD/mcl_achievements/init.lua index 8f0c8dd89..ced758948 100644 --- a/mods/HUD/mcl_achievements/init.lua +++ b/mods/HUD/mcl_achievements/init.lua @@ -15,7 +15,9 @@ awards.register_achievement("mcl_buildWorkBench", { type = "craft", item = "mcl_crafting_table:crafting_table", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:buildPickaxe", { title = S("Time to Mine!"), @@ -25,7 +27,9 @@ awards.register_achievement("mcl:buildPickaxe", { type = "craft", item = "mcl_tools:pick_wood", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:buildFurnace", { title = S("Hot Topic"), @@ -35,7 +39,9 @@ awards.register_achievement("mcl:buildFurnace", { type = "craft", item = "mcl_furnaces:furnace", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:buildHoe", { title = S("Time to Farm!"), @@ -45,7 +51,9 @@ awards.register_achievement("mcl:buildHoe", { type = "craft", item = "mcl_farming:hoe_wood", target = 1 - } + }, + type = "Advancement", + group = "Husbandry", }) awards.register_achievement("mcl:makeBread", { title = S("Bake Bread"), @@ -55,7 +63,9 @@ awards.register_achievement("mcl:makeBread", { type = "craft", item = "mcl_farming:bread", target = 1 - } + }, + type = "Advancement", + group = "Husbandry", }) awards.register_achievement("mcl:bakeCake", { @@ -66,7 +76,9 @@ awards.register_achievement("mcl:bakeCake", { type = "craft", item = "mcl_cake:cake", target = 1 - } + }, + type = "Advancement", + group = "Husbandry", }) awards.register_achievement("mcl:buildBetterPickaxe", { title = S("Getting an Upgrade"), @@ -77,7 +89,9 @@ awards.register_achievement("mcl:buildBetterPickaxe", { type = "craft", item = "mcl_tools:pick_stone", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:buildSword", { title = S("Time to Strike!"), @@ -87,7 +101,9 @@ awards.register_achievement("mcl:buildSword", { type = "craft", item = "mcl_tools:sword_wood", target = 1 - } + }, + type = "Advancement", + group = "Adventure", }) awards.register_achievement("mcl:bookcase", { @@ -98,7 +114,9 @@ awards.register_achievement("mcl:bookcase", { type = "craft", item = "mcl_books:bookshelf", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:buildIronPickaxe", { @@ -109,7 +127,9 @@ awards.register_achievement("mcl:buildIronPickaxe", { type = "craft", item = "mcl_tools:pick_iron", target = 1 - } + }, + type = "Advancement", + group = "Overworld", }) -- Item pickup achievements: These are awarded when picking up a certain item. @@ -118,46 +138,61 @@ awards.register_achievement("mcl:diamonds", { title = S("DIAMONDS!"), description = S("Pick up a diamond from the floor."), icon = "mcl_core_diamond_ore.png", + type = "Advancement", }) awards.register_achievement("mcl:blazeRod", { title = S("Into Fire"), description = S("Pick up a blaze rod from the floor."), icon = "mcl_mobitems_blaze_rod.png", + type = "Advancement", + group = "Nether", }) awards.register_achievement("mcl:killCow", { title = S("Cow Tipper"), description = S("Pick up leather from the floor.\nHint: Cows and some other animals have a chance to drop leather, when killed."), icon = "mcl_mobitems_leather.png", + type = "Advancement", + group = "Adventure", }) awards.register_achievement("mcl:mineWood", { title = S("Getting Wood"), description = S("Pick up a wood item from the ground.\nHint: Punch a tree trunk until it pops out as an item."), icon = "default_tree.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:whosCuttingOnions", { title = S("Who is Cutting Onions?"), description = S("Pick up a crying obsidian from the floor."), icon = "default_obsidian.png^mcl_core_crying_obsidian.png", + type = "Advancement", + group = "Nether", }) awards.register_achievement("mcl:hiddenInTheDepths", { title = S("Hidden in the Depths"), description = S("Pick up an Ancient Debris from the floor."), icon = "mcl_nether_ancient_debris_side.png", + type = "Advancement", + group = "Nether", }) awards.register_achievement("mcl:PickUpDragonEgg", { title = S("The Next Generation"), description = S("Hold the Dragon Egg.\nHint: Pick up the egg from the ground and have it in your inventory."), icon = "mcl_end_dragon_egg.png", + type = "Goal", + group = "End", }) awards.register_achievement("mcl:skysTheLimit", { title = S("Sky's the Limit"), description = S("Find the elytra and prepare to fly above and beyond!"), icon = "mcl_armor_inv_elytra.png", + type = "Goal", + group = "End", }) -- TODO: Make also unlock when moved to inventory, not just picking up from ground -- Smelting achivements: These are awarded when picking up an item from a furnace @@ -166,11 +201,15 @@ awards.register_achievement("mcl:acquireIron", { title = S("Aquire Hardware"), description = S("Take an iron ingot from a furnace's output slot.\nHint: To smelt an iron ingot, put a fuel (like coal) and iron ore into a furnace."), icon = "default_steel_ingot.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:cookFish", { title = S("Delicious Fish"), description = S("Take a cooked fish from a furnace.\nHint: Use a fishing rod to catch a fish and cook it in a furnace."), icon = "mcl_fishing_fish_cooked.png", + type = "Advancement", + group = "Husbandry", }) -- Other achievements triggered outside of mcl_achievements @@ -180,6 +219,8 @@ awards.register_achievement("mcl:onARail", { title = S("On A Rail"), description = S("Travel by minecart for at least 1000 meters from your starting point in a single ride."), icon = "default_rail.png", + type = "Challenge", + group = "Adventure", }) -- Triggered in mcl_bows @@ -189,6 +230,8 @@ awards.register_achievement("mcl:snipeSkeleton", { -- TODO: The range should be 50, not 20. Nerfed because of reduced bow range description = S("Hit a skeleton, wither skeleton or stray by bow and arrow from a distance of at least 20 meters."), icon = "mcl_bows_bow.png", + type = "Challenge", + group = "Adventure", }) -- Triggered in mcl_portals @@ -196,18 +239,24 @@ awards.register_achievement("mcl:buildNetherPortal", { title = S("We Need to Go Deeper"), description = S("Use obsidian and a fire starter to construct a Nether portal."), icon = "mcl_fire_flint_and_steel.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:enterEndPortal", { title = S("The End?"), description = S("Or the beginning?\nHint: Enter an end portal."), icon = "mcl_end_end_stone.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:theNether", { title = S("The Nether"), description = S("Bring summer clothes.\nHint: Enter the Nether."), icon = "mcl_nether_netherrack.png", + type = "Advancement", + group = "Nether", }) -- Triggered in mcl_totems @@ -215,19 +264,25 @@ awards.register_achievement("mcl:postMortal", { title = S("Postmortal"), description = S("Use a Totem of Undying to cheat death."), icon = "mcl_totems_totem.png", + type = "Goal", + group = "Adventure", }) -- Triggered in mcl_beds awards.register_achievement("mcl:sweetDreams", { title = S("Sweet Dreams"), description = S("Sleep in a bed to change your respawn point."), - icon = "mcl_beds_bed_red.png", + icon = "mcl_beds_bed_red_inv.png", + type = "Advancement", + group = "Adventure", }) awards.register_achievement("mcl:notQuiteNineLives", { title = S('Not Quite "Nine" Lives'), description = S("Charge a Respawn Anchor to the maximum."), icon = "respawn_anchor_side4.png", + type = "Advancement", + group = "Nether", }) -- Triggered in mobs_mc @@ -235,24 +290,40 @@ awards.register_achievement("mcl:whatAdeal", { title = S("What A Deal!"), description = S("Successfully trade with a Villager."), icon = "mcl_core_emerald.png", + type = "Advancement", + group = "Adventure", }) awards.register_achievement("mcl:tacticalFishing", { title = S("Tactical Fishing"), description = S("Catch a fish... without a fishing rod!"), icon = "pufferfish_bucket.png", + type = "Advancement", + group = "Husbandry", +}) + +awards.register_achievement("mcl:cutestPredator", { + title = S("The Cutest Predator"), + description = S("Catch an Axolotl with a bucket!"), + icon = "axolotl_bucket.png", + type = "Advancement", + group = "Husbandry", }) awards.register_achievement("mcl:witheringHeights", { title = S("Withering Heights"), description = S("Summon the wither from the dead."), icon = "mcl_mobitems_nether_star.png", + type = "Advancement", + group = "Nether", }) awards.register_achievement("mcl:freeTheEnd", { title = S("Free the End"), description = S("Kill the ender dragon. Good Luck!"), - icon = "mobs_mc_spawn_icon_dragon.png", -- TODO: Dragon Head Icon + icon = "(spawn_egg.png^[multiply:#252525)^(spawn_egg_overlay.png^[multiply:#b313c9)", -- TODO: Dragon Head Icon + type = "Advancement", + group = "End", }) -- Triggered in mcl_fishing @@ -260,6 +331,8 @@ awards.register_achievement("mcl:fishyBusiness", { title = S("Fishy Business"), description = S("Catch a fish.\nHint: Catch a fish, salmon, clownfish, or pufferfish."), icon = "mcl_fishing_fishing_rod.png", + type = "Advancement", + group = "Husbandry", }) -- Triggered in mcl_compass @@ -267,6 +340,8 @@ awards.register_achievement("mcl:countryLode", { title = S("Country Lode,\nTake Me Home"), description = S("Use a compass on a Lodestone."), icon = "lodestone_side4.png", + type = "Advancement", + group = "Nether", }) -- Triggered in mcl_smithing_table @@ -274,6 +349,8 @@ awards.register_achievement("mcl:seriousDedication", { title = S("Serious Dedication"), description = S("Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices."), icon = "farming_tool_netheritehoe.png", + type = "Challenge", + group = "Husbandry", }) -- Triggered in mcl_brewing @@ -281,6 +358,8 @@ awards.register_achievement("mcl:localBrewery", { title = S("Local Brewery"), description = S("Brew a Potion.\nHint: Take a potion or glass bottle out of the brewing stand."), icon = "mcl_potions_potion_overlay.png^[colorize:#F82423:"..tostring(127).."^mcl_potions_potion_bottle.png", + type = "Advancement", + group = "Nether", }) -- Triggered in mcl_enchanting @@ -288,6 +367,8 @@ awards.register_achievement("mcl:enchanter", { title = S("Enchanter"), description = S("Enchant an item using an Enchantment Table."), icon = "mcl_enchanting_book_enchanted.png", + type = "Advancement", + group = "Overworld", }) --Triggered in mcl_beacons @@ -295,12 +376,16 @@ awards.register_achievement("mcl:beacon", { title = S("Bring Home the Beacon"), description = S("Use a beacon."), icon = "beacon_achievement_icon.png", + type = "Advancement", + group = "Nether", }) awards.register_achievement("mcl:maxed_beacon", { title = S("Beaconator"), description = S("Use a fully powered beacon."), icon = "beacon_achievement_icon.png", + type = "Goal", + group = "Nether", }) -- Triggered in mcl_end @@ -308,6 +393,42 @@ awards.register_achievement("mcl:theEndAgain", { title = S("The End... Again..."), description = S("Respawn the Ender Dragon."), icon = "mcl_end_crystal_item.png", + type = "Goal", + group = "End", +}) + +-- Triggered in mcl_beehives +awards.register_achievement("mcl:bee_our_guest", { + title = S("Bee Our Guest"), + description = S("Use a campfire to collect a bottle of honey from a beehive without aggrivating the bees inside."), + icon = "mcl_honey_honey_bottle.png", + type = "Advancement", + group = "Husbandry", +}) + +awards.register_achievement("mcl:total_beelocation", { + title = S("Total Beelocation"), + description = S("Move a bee nest, with 3 bees inside, using a silk touch enchanted tool."), + icon = "mcl_beehives_bee_nest_front_honey.png", + type = "Advancement", + group = "Husbandry", +}) + +-- Triggered in mcl_copper +awards.register_achievement("mcl:wax_on", { + title = S("Wax On"), + description = S("Apply honeycomb to a copper block to protect it from the elements."), + icon = "mcl_honey_honeycomb.png", + type = "Advancement", + group = "Husbandry", +}) + +awards.register_achievement("mcl:wax_off", { + title = S("Wax Off"), + description = S("Scrape wax off of a copper block."), + icon = "default_tool_stoneaxe.png", + type = "Advancement", + group = "Husbandry", }) -- NON-PC ACHIEVEMENTS (XBox, Pocket Edition, etc.) @@ -391,14 +512,38 @@ awards.register_achievement("mcl:stoneAge", { title = S("Stone Age"), description = S("Mine a stone with new pickaxe."), icon = "default_cobble.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:hotStuff", { title = S("Hot Stuff"), description = S("Put lava in a bucket."), icon = "bucket_lava.png", + type = "Advancement", + group = "Overworld", }) awards.register_achievement("mcl:obsidian", { title = S("Ice Bucket Challenge"), description = S("Obtain an obsidian block."), icon = "default_obsidian.png", + type = "Advancement", + group = "Overworld", +}) + +awards.register_achievement("mcl:hero_of_the_village", { + title = S("Hero of the Village"), + description = S("Successfully defend a village from a raid"), + icon = "mcl_raids_hero_of_the_village_icon.png", + type = "Advancement", + group = "Adventure", + secret = true, +}) + +awards.register_achievement("mcl:voluntary_exile", { + title = S("Voluntary Exile"), + description = S("Kill a raid captain. Maybe consider staying away from the local villages for the time being..."), + icon = "mcl_potions_effect_bad_omen.png", + type = "Advancement", + group = "Adventure", + secret = true, }) diff --git a/mods/HUD/mcl_achievements/locale/template.txt b/mods/HUD/mcl_achievements/locale/template.txt index cd3726b05..f229b2152 100644 --- a/mods/HUD/mcl_achievements/locale/template.txt +++ b/mods/HUD/mcl_achievements/locale/template.txt @@ -65,6 +65,8 @@ What A Deal!= Successfully trade with a Villager.= Withering Heights= Summon the wither from the dead.= +The Cutest Predator= +Catch an Axolotl with a bucket! Fishy Business= Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.= Country Lode,@nTake Me Home= @@ -87,3 +89,11 @@ Sky's The Limit= Find the elytra and prepare to fly above and beyond!= Free the End= Kill the ender dragon. Good Luck!= +Bee Our Guest= +Use a campfire to collect a bottle of honey from a beehive without aggrivating the bees inside.= +Total Beelocation= +Move a bee nest, with 3 bees inside, using a silk touch enchanted tool.= +Wax On= +Apply honeycomb to a copper block to protect it from the elements.= +Wax Off= +Scrape wax off of a copper block.= diff --git a/mods/HUD/mcl_base_textures/textures/crack_anylength.png b/mods/HUD/mcl_base_textures/textures/crack_anylength.png index 7fe8721d9..07e5df8fd 100644 Binary files a/mods/HUD/mcl_base_textures/textures/crack_anylength.png and b/mods/HUD/mcl_base_textures/textures/crack_anylength.png differ diff --git a/mods/HUD/mcl_bossbars/init.lua b/mods/HUD/mcl_bossbars/init.lua index 96b6b4896..1ff981456 100644 --- a/mods/HUD/mcl_bossbars/init.lua +++ b/mods/HUD/mcl_bossbars/init.lua @@ -13,13 +13,13 @@ function mcl_bossbars.recalculate_colors() local frame_count = color_count * 2 for i, color in ipairs(colors) do local idx = i * 2 - 1 - local image = "mcl_bossbars.png" + local image = "(mcl_bossbars.png" .. "^[transformR270" .. "^[verticalframe:" .. frame_count .. ":" .. (idx - 1) .. "^(mcl_bossbars_empty.png" .. "^[lowpart:%d:mcl_bossbars.png" .. "^[transformR270" - .. "^[verticalframe:" .. frame_count .. ":" .. idx .. ")" + .. "^[verticalframe:" .. frame_count .. ":" .. idx .. "))^[resize:1456x40" local _, hex = mcl_util.get_color(color) sorted[color] = { image = image, @@ -162,7 +162,7 @@ minetest.register_globalstep(function(dtime) position = {x = 0.5, y = 0}, alignment = {x = 0, y = 1}, offset = {x = 0, y = i * 40 + 25}, - scale = {x = 3, y = 3}, + scale = {x = 0.375, y = 0.375}, }), } end diff --git a/mods/HUD/mcl_credits/people.lua b/mods/HUD/mcl_credits/people.lua index 8c0d45485..6b674e0c8 100644 --- a/mods/HUD/mcl_credits/people.lua +++ b/mods/HUD/mcl_credits/people.lua @@ -34,6 +34,9 @@ return { "RandomLegoBrick", "SumianVoice", "MrRar", + "talamh", + "Faerraven", + "AncientMariner", }}, {S("Contributors"), 0x52FF00, { "Laurent Rocher", @@ -67,7 +70,6 @@ return { "Benjamin Schötz", "Doloment", "Sydney Gems", - "talamh", "Emily2255", "Emojigit", "FinishedFragment", @@ -86,6 +88,14 @@ return { "opfromthestart", "snowyu", "FaceDeer", + "Faerraven / Michieal", + "FossFanatic", + "Herbert West", + "GuyLiner", + "3raven", + "anarquimico", + "TheOnlyJoeEnderman", + "Ranko Saotome", }}, {S("MineClone5"), 0xA60014, { "kay27", @@ -96,7 +106,7 @@ return { "chmodsayshello", "3raven", "PrairieWind", - "Gustavo1", + "Gustavo6046 / wallabra", "CableGuy67", "MrRar", }}, @@ -155,6 +165,7 @@ return { "MysticTempest", "RandomLegoBrick", "cora", + "Faerraven / Michieal", }}, {S("Translations"), 0x00FF60, { "Wuzzy", @@ -179,4 +190,4 @@ return { "The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game", "Notch and Jeb for being the major forces behind Minecraft", }}, -} \ No newline at end of file +} diff --git a/mods/HUD/mcl_experience/init.lua b/mods/HUD/mcl_experience/init.lua index 37250ee2f..359e68918 100644 --- a/mods/HUD/mcl_experience/init.lua +++ b/mods/HUD/mcl_experience/init.lua @@ -136,7 +136,7 @@ end function mcl_experience.throw_xp(pos, total_xp) local i, j = 0, 0 - + local obs = {} while i < total_xp and j < 100 do local xp = math.min(math.random(1, math.min(32767, total_xp - math.floor(i / 2))), total_xp - i) local obj = minetest.add_entity(pos, "mcl_experience:orb", tostring(xp)) @@ -153,7 +153,9 @@ function mcl_experience.throw_xp(pos, total_xp) i = i + xp j = j + 1 + table.insert(obs,obj) end + return obs end function mcl_experience.remove_hud(player) @@ -179,7 +181,7 @@ function mcl_experience.setup_hud(player) hud_elem_type = "image", position = {x = 0.5, y = 1}, offset = {x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5)}, - scale = {x = 2.8, y = 3.0}, + scale = {x = 0.35, y = 0.375}, alignment = {x = 1, y = 1}, z_index = 11, }) @@ -204,9 +206,10 @@ function mcl_experience.update(player) if not hud_bars[player] then mcl_experience.setup_hud(player) end - player:hud_change(hud_bars[player], "text", "mcl_experience_bar_background.png^[lowpart:" + + player:hud_change(hud_bars[player], "text", "(mcl_experience_bar_background.png^[lowpart:" .. math.floor(math.floor(xp_to_bar(xp, cache.level) * 18) / 18 * 100) - .. ":mcl_experience_bar.png^[transformR270" + .. ":mcl_experience_bar.png)^[resize:40x1456^[transformR270" ) if cache.level == 0 then diff --git a/mods/HUD/mcl_info/init.lua b/mods/HUD/mcl_info/init.lua index 71f8d8ad0..b6f69255c 100644 --- a/mods/HUD/mcl_info/init.lua +++ b/mods/HUD/mcl_info/init.lua @@ -1,22 +1,15 @@ mcl_info = {} -local refresh_interval = .63 -local huds = {} -local default_debug = 0 -local after = minetest.after -local get_connected_players = minetest.get_connected_players -local get_biome_name = minetest.get_biome_name -local get_biome_data = minetest.get_biome_data -local format = string.format - -local min1, min2, min3 = mcl_vars.mg_overworld_min, mcl_vars.mg_end_min, mcl_vars.mg_nether_min -local max1, max2, max3 = mcl_vars.mg_overworld_max, mcl_vars.mg_end_max, mcl_vars.mg_nether_max + 128 +local format, pairs,ipairs,table,vector,minetest,mcl_info,tonumber,tostring = string.format,pairs,ipairs,table,vector,minetest,mcl_info,tonumber,tostring local modname = minetest.get_current_modname() -local modpath = minetest.get_modpath(modname) local S = minetest.get_translator(modname) local storage = minetest.get_mod_storage() local player_dbg = {} +local refresh_interval = .63 +local huds = {} +local default_debug = 0 + local function check_setting(s) return s end @@ -58,21 +51,24 @@ end local function get_text(player, bits) local pos = vector.offset(player:get_pos(),0,0.5,0) local bits = bits - if bits == 0 then return "" end + if bits == -1 then return "" end local r = "" for _,key in ipairs(fields_keyset) do local def = mcl_info.registered_debug_fields[key] - if def.level == nil or def.level <= bits then - r = r ..key..": "..tostring(def.func(player,pos)).."\n" + if def then + if def.level == nil or def.level <= bits then + r = r ..key..": "..tostring(def.func(player,pos)).."\n" + end + else + r = r ..key..": \n" end end - return r end local function info() - for _, player in pairs(get_connected_players()) do + for _, player in pairs(minetest.get_connected_players()) do local name = player:get_player_name() local s = player_setting(player) local pos = player:get_pos() @@ -104,7 +100,7 @@ local function info() player:hud_change(huds[name][2], "text", text) end end - after(refresh_interval, info) + minetest.after(refresh_interval, info) end minetest.after(0,info) @@ -115,21 +111,40 @@ minetest.register_on_leaveplayer(function(p) end) minetest.register_chatcommand("debug",{ - description = S("Set debug bit mask: 0 = disable, 1 = biome name, 2 = coordinates, 3 = all"), + description = S("Set debug bit mask: 0 = disable, 1 = player coords, 2 = coordinates, 3 = biome name, 4 = all"), params = S(""), privs = { debug = true }, func = function(name, params) local player = minetest.get_player_by_name(name) if params == "" then return true, "Debug bitmask is "..player_setting(player) end local dbg = math.floor(tonumber(params) or default_debug) - if dbg < 0 or dbg > 4 then - minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 4)) + if dbg < -1 or dbg > 4 then + minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", -1, 4)) return false,"Current bitmask: "..player_setting(player) end return true, "Debug bit mask set to "..player_setting(player,dbg) end }) +-- register normal user access to debug levels 1 and 0. +minetest.register_chatcommand("whereami", { + description = S("Set location bit mask: 0 = disable, 1 = coordinates"), + params = S(""), + -- privs = { }, + func = function(name, params) + local player = minetest.get_player_by_name(name) + if params == "" then + return true, "Location bitmask is " .. player_setting(player) + end + local loc_lev = math.floor(tonumber(params) or default_debug) + if loc_lev < 0 or loc_lev > 4 then + minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 1)) + return false, "Current bitmask: " .. player_setting(player) + end + return true, "Location bit mask set to " .. player_setting(player, loc_lev) + end +}) + mcl_info.register_debug_field("Node feet",{ level = 4, func = function(pl,pos) @@ -145,17 +160,45 @@ mcl_info.register_debug_field("Node below",{ mcl_info.register_debug_field("Biome",{ level = 3, func = function(pl,pos) - local biome_data = get_biome_data(pos) - local biome = biome_data and get_biome_name(biome_data.biome) or "No biome" + local biome_data = minetest.get_biome_data(pos) + local biome = biome_data and minetest.get_biome_name(biome_data.biome) or "No biome" if biome_data then return format("%s (%s), Humidity: %.1f, Temperature: %.1f",biome, biome_data.biome, biome_data.humidity, biome_data.heat) end return "No biome" end }) -mcl_info.register_debug_field("Coords",{ + +mcl_info.register_debug_field("Coords", { level = 2, - func = function(pl,pos) + func = function(pl, pos) return format("x:%.1f y:%.1f z:%.1f", pos.x, pos.y, pos.z) end }) + +mcl_info.register_debug_field("Location", { + level = 1, + func = function(pl, pos) + local report_y = 0 + -- overworld + if (pos.y >= mcl_vars.mg_overworld_min) and (pos.y <= mcl_vars.mg_overworld_max) then + return format("Overworld: x:%.1f y:%.1f z:%.1f", pos.x, pos.y, pos.z) + end + + -- nether + if (pos.y >= mcl_vars.mg_nether_min) and (pos.y <= mcl_vars.mg_nether_max) then + report_y = pos.y - mcl_vars.mg_nether_min + return format("Nether: x:%.1f y:%.1f z:%.1f", pos.x, report_y, pos.z) + end + + -- end + if (pos.y >= mcl_vars.mg_end_min) and (pos.y <= mcl_vars.mg_end_max) then + report_y = pos.y - mcl_vars.mg_end_min + return format("End: x:%.1f y:%.1f z:%.1f", pos.x, report_y, pos.z) + end + + -- outside of scoped bounds. + return format("Void: x:%.1f y:%.1f z:%.1f", pos.x, pos.y, pos.z) + + end +}) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 278ca87b1..517622333 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -117,7 +117,7 @@ local function filter_item(name, description, lang, filter) else desc = string.lower(minetest.get_translated_string(lang, description)) end - return string.find(name, filter) or string.find(desc, filter) + return string.find(name, filter, nil, true) or string.find(desc, filter, nil, true) end local function set_inv_search(filter, player) @@ -392,7 +392,7 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, -- Achievements button "image_button[9,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. --"style_type[image_button;border=;bgimg=;bgimg_pressed=]" .. - "tooltip[__mcl_achievements;"..F(S("Achievements")) .. "]" .. + "tooltip[__mcl_achievements;"..F(S("Advancements")) .. "]" .. -- Switch stack size button "image_button[9,4;1,1;default_apple.png;__switch_stack;]" .. diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index c8caaab2c..4f50a3ef5 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -119,7 +119,7 @@ local function set_inventory(player, armor_change_only) form = form .. -- Achievements button "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. - "tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]" .. + "tooltip[__mcl_achievements;" .. F(S("Advancements")) .. "]" .. -- For shortcuts "listring[current_player;main]" .. @@ -189,9 +189,10 @@ minetest.register_on_joinplayer(function(player) return_fields(player, "enchanting_lapis") end) - dofile(minetest.get_modpath(minetest.get_current_modname()).."/creative.lua") +mcl_player.register_on_visual_change(mcl_inventory.update_inventory_formspec) + local mt_is_creative_enabled = minetest.is_creative_enabled function minetest.is_creative_enabled(name) @@ -207,14 +208,12 @@ 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 - if minetest.is_creative_enabled() 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 - if def.on_destruct then def.on_destruct(pos) end - minetest.remove_node(pos) + minetest.node_dig(pos,node,puncher) return true end end) @@ -254,10 +253,13 @@ minetest.register_chatcommand("gamemode",{ privs = { server = true }, func = function(n,param) -- Full input validation ( just for @erlehmann <3 ) - local p = minetest.get_player_by_name(n) + local p local args = param:split(" ") if args[2] ~= nil then p = minetest.get_player_by_name(args[2]) + n = args[2] + else + p = minetest.get_player_by_name(n) end if not p then return false, S("Player not online") @@ -267,6 +269,7 @@ minetest.register_chatcommand("gamemode",{ elseif args[1] ~= nil then mcl_inventory.player_set_gamemode(p,args[1]) end + --Result message - show effective game mode local gm = p:get_meta():get_string("gamemode") if gm == "" then gm = gamemodes[1] end diff --git a/mods/HUD/mcl_inventory/locale/template.txt b/mods/HUD/mcl_inventory/locale/template.txt index 7f1c9769d..fcbe68580 100644 --- a/mods/HUD/mcl_inventory/locale/template.txt +++ b/mods/HUD/mcl_inventory/locale/template.txt @@ -2,7 +2,7 @@ Recipe book= Help= Select player skin= -Achievements= +Advancements= Building Blocks= Decoration Blocks= Redstone= diff --git a/mods/HUD/mcl_inventory/mod.conf b/mods/HUD/mcl_inventory/mod.conf index 10e669265..e42213d4f 100644 --- a/mods/HUD/mcl_inventory/mod.conf +++ b/mods/HUD/mcl_inventory/mod.conf @@ -1,5 +1,5 @@ name = mcl_inventory author = BlockMen description = Adds the player inventory and creative inventory. -depends = mcl_init, mcl_formspec, mcl_enchanting -optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide, mcl_player +depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_player +optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide diff --git a/mods/HUD/mcl_offhand/init.lua b/mods/HUD/mcl_offhand/init.lua index 5f48eede9..98954b4f5 100644 --- a/mods/HUD/mcl_offhand/init.lua +++ b/mods/HUD/mcl_offhand/init.lua @@ -70,8 +70,8 @@ minetest.register_globalstep(function(dtime) hud_elem_type = "image", position = position, offset = offset, - scale = {x = 2.75, y = 2.75}, - text = "mcl_offhand_slot.png", + scale = {x = 0.46875, y = 0.46875}, + text = "mcl_offhand_slot.png" .. "^[resize:" .. max_offhand_px .. "x" .. max_offhand_px, z_index = 0, }) end @@ -80,7 +80,7 @@ minetest.register_globalstep(function(dtime) hud_elem_type = "image", position = position, offset = offset, - scale = {x = 0.4, y = 0.4}, + scale = {x = 0.375, y = 0.375}, text = item_texture, z_index = 1, }) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 2ea1571c8..2e8397fc1 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -11,8 +11,10 @@ --Note that the table storing timeouts use playername as index insteed of player objects (faster) --This is intended in order to speedup the process of removing HUD elements the the timeout is up +---@type table> local huds_idx = {} +---@type table> local hud_hide_timeouts = {} hud_hide_timeouts.title = {} @@ -24,17 +26,19 @@ huds_idx.subtitle = {} huds_idx.actionbar = {} mcl_title = {} -mcl_title.defaults = {fadein = 10, stay = 70, fadeout = 20} +mcl_title.defaults = { fadein = 10, stay = 70, fadeout = 20 } mcl_title.layout = {} -mcl_title.layout.title = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = -1.3}, size = 7} -mcl_title.layout.subtitle = {position = {x = 0.5, y = 0.5}, alignment = {x = 0, y = 1.7}, size = 4} -mcl_title.layout.actionbar = {position = {x = 0.5, y = 1}, alignment = {x = 0, y = 0}, size = 1} +mcl_title.layout.title = { position = { x = 0.5, y = 0.5 }, alignment = { x = 0, y = -1.3 }, size = 7 } +mcl_title.layout.subtitle = { position = { x = 0.5, y = 0.5 }, alignment = { x = 0, y = 1.7 }, size = 4 } +mcl_title.layout.actionbar = { position = { x = 0.5, y = 1 }, alignment = { x = 0, y = 0 }, size = 1 } local get_color = mcl_util.get_color --local string = string local pairs = pairs +---@param gametick integer +---@return number? local function gametick_to_secondes(gametick) if gametick then return gametick / 20 @@ -44,7 +48,10 @@ local function gametick_to_secondes(gametick) end --https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477 ---[[ + +---@param bold? boolean +---@param italic? boolean +---@return integer local function style_to_bits(bold, italic) if bold then if italic then @@ -60,9 +67,11 @@ local function style_to_bits(bold, italic) end end end -]] ---PARAMS SYSTEM +local no_style = style_to_bits(false, false) + +---PARAMS SYSTEM +---@type table local player_params = {} minetest.register_on_joinplayer(function(player) @@ -75,34 +84,34 @@ minetest.register_on_joinplayer(function(player) local _, hex_color = get_color("white") huds_idx.title[player] = player:hud_add({ hud_elem_type = "text", - position = mcl_title.layout.title.position, - alignment = mcl_title.layout.title.alignment, - text = "", - --style = 0, - size = {x = mcl_title.layout.title.size}, - number = hex_color, - z_index = 100, + position = mcl_title.layout.title.position, + alignment = mcl_title.layout.title.alignment, + text = "", + style = no_style, + size = { x = mcl_title.layout.title.size }, + number = hex_color, + z_index = 100, }) huds_idx.subtitle[player] = player:hud_add({ hud_elem_type = "text", - position = mcl_title.layout.subtitle.position, - alignment = mcl_title.layout.subtitle.alignment, - text = "", - --style = 0, - size = {x = mcl_title.layout.subtitle.size}, - number = hex_color, - z_index = 100, + position = mcl_title.layout.subtitle.position, + alignment = mcl_title.layout.subtitle.alignment, + text = "", + style = no_style, + size = { x = mcl_title.layout.subtitle.size }, + number = hex_color, + z_index = 100, }) huds_idx.actionbar[player] = player:hud_add({ hud_elem_type = "text", - position = mcl_title.layout.actionbar.position, - offset = {x = 0, y = -210}, - alignment = mcl_title.layout.actionbar.alignment, - --style = 0, - text = "", - size = {x = mcl_title.layout.actionbar.size}, - number = hex_color, - z_index = 100, + position = mcl_title.layout.actionbar.position, + offset = { x = 0, y = -210 }, + alignment = mcl_title.layout.actionbar.alignment, + style = no_style, + text = "", + size = { x = mcl_title.layout.actionbar.size }, + number = hex_color, + z_index = 100, }) end) @@ -123,6 +132,8 @@ minetest.register_on_leaveplayer(function(player) hud_hide_timeouts.actionbar[playername] = nil end) +---@param player ObjectRef +---@param data {stay: integer} function mcl_title.params_set(player, data) player_params[player] = { stay = data.stay or mcl_title.defaults.stay, @@ -131,12 +142,18 @@ function mcl_title.params_set(player, data) } end +---@param player ObjectRef +---@return {stay: integer} function mcl_title.params_get(player) return player_params[player] end --API FUNCTIONS +---@param player ObjectRef +---@param type '"title"'|'"subtitle"'|'"actionbar"' +---@param data {text: string, color: string, stay: integer, bold: boolean, italic: boolean} +---@return boolean function mcl_title.set(player, type, data) if not data.color then data.color = "white" @@ -149,20 +166,25 @@ function mcl_title.set(player, type, data) player:hud_change(huds_idx[type][player], "text", data.text) player:hud_change(huds_idx[type][player], "number", hex_color) - --apply bold and italic - --player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) + -- Apply bold and italic + player:hud_change(huds_idx[type][player], "style", style_to_bits(data.bold, data.italic)) + + hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or + gametick_to_secondes(mcl_title.params_get(player).stay) - hud_hide_timeouts[type][player:get_player_name()] = gametick_to_secondes(data.stay) or gametick_to_secondes(mcl_title.params_get(player).stay) return true end +---@param player ObjectRef? +---@param type '"title"'|'"subtitle"'|'"actionbar"' function mcl_title.remove(player, type) if player then player:hud_change(huds_idx[type][player], "text", "") - --player:hud_change(huds_idx[type][player], "style", 0) --no styling + player:hud_change(huds_idx[type][player], "style", no_style) end end +---@param player ObjectRef function mcl_title.clear(player) mcl_title.remove(player, "title") mcl_title.remove(player, "subtitle") @@ -179,6 +201,7 @@ minetest.register_globalstep(function(dtime) subtitle = {}, actionbar = {}, } + for element, content in pairs(hud_hide_timeouts) do for name, timeout in pairs(content) do timeout = timeout - dtime @@ -190,47 +213,95 @@ minetest.register_globalstep(function(dtime) end end end + hud_hide_timeouts = new_timeouts end) --DEBUG STUFF!! ---[[ +--TODO:Proper /title command that can send the title to other players. +--These commands are just for debugging right now. +local dbg_msg = "Note that these are just debug commands right now. e.g. the title is only sent to he player issuing the command. Proper /title commands will be added in the future." minetest.register_chatcommand("title", { + privs = { debug = true }, func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.set(player, "title", {text=param, color="gold", bold=true, italic=true}) + if player then + mcl_title.set(player, "title", { text = param, color = "gold", bold = true, italic = true }) + return true, dbg_msg + else + return false, dbg_msg + end end, }) minetest.register_chatcommand("subtitle", { + privs = { debug = true }, func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.set(player, "subtitle", {text=param, color="gold"}) + if player then + mcl_title.set(player, "subtitle", { text = param, color = "gold" }) + return true, dbg_msg + else + return false, dbg_msg + end end, }) minetest.register_chatcommand("actionbar", { + privs = { debug = true }, func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.set(player, "actionbar", {text=param, color="gold"}) + if player then + mcl_title.set(player, "actionbar", { text = param, color = "gold", bold = true, italic = true }) + return true, dbg_msg + else + return false, dbg_msg + end end, }) -minetest.register_chatcommand("timeout", { +minetest.register_chatcommand("title_timeout", { + privs = { debug = true }, func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.params_set(player, {stay = 600}) + if player then + mcl_title.params_set(player, { stay = 600 }) + return true, dbg_msg + else + return false, dbg_msg + end end, }) -minetest.register_chatcommand("all", { +minetest.register_chatcommand("title_all", { + privs = { debug = true }, func = function(name, param) local player = minetest.get_player_by_name(name) - mcl_title.params_set(player, {stay = 600}) - mcl_title.set(player, "title", {text=param, color="gold"}) - mcl_title.set(player, "subtitle", {text=param, color="gold"}) - mcl_title.set(player, "actionbar", {text=param, color="gold"}) + if player then + mcl_title.params_set(player, { stay = 600 }) + mcl_title.set(player, "title", { text = param, color = "gold" }) + mcl_title.set(player, "subtitle", { text = param, color = "gold" }) + mcl_title.set(player, "actionbar", { text = param, color = "gold" }) + return true, dbg_msg + else + return false, dbg_msg + end + end, +}) + +minetest.register_chatcommand("title_all_styles", { + privs = { debug = true }, + func = function(name, param) + local player = minetest.get_player_by_name(name) + if player then + mcl_title.params_set(player, { stay = 600 }) + mcl_title.set(player, "title", { text = param, color = "gold" }) + mcl_title.set(player, "subtitle", { text = param, color = "gold", bold = true }) + mcl_title.set(player, "actionbar", { text = param, color = "gold", italic = true }) + return true, dbg_msg + else + return false, dbg_msg + end end, }) -]] \ No newline at end of file diff --git a/mods/HUD/mcl_ver_info/init.lua b/mods/HUD/mcl_ver_info/init.lua new file mode 100644 index 000000000..632847275 --- /dev/null +++ b/mods/HUD/mcl_ver_info/init.lua @@ -0,0 +1,65 @@ +--- +--- Generated by EmmyLua +--- Created by Michieal. +--- DateTime: 11/28/22 4:38 PM +--- +local modname = minetest.get_current_modname() +local S = minetest.get_translator(modname) + +local function xpcall_ver (error) + minetest.log("info", "mcl_ver_info:: Gamepath not supported in this version of Minetest.") +end + +local function get_game_info () + local game_info + + if xpcall(minetest.get_game_info, xpcall_ver) then + game_info = minetest.get_game_info() + else + minetest.log( S("Sorry, but your version of Minetest doesn't support the latest API. Please upgrade your minetest.")) + return false + end + + return game_info +end + +-- register normal user access to debug levels 1 and 0. +minetest.register_chatcommand("ver", { + description = S("Display Mineclone 2 game version."), + func = function(name, params) + --[[ get_game_info's table data: + { + id = string, + title = string, + author = string, + -- The root directory of the game + path = string, + } + --]] + local game_info = get_game_info () + + if game_info == false then + return true + end + + local conf = Settings(game_info.path .. "/game.conf") + local version = conf:get("version") + + if game_info.title == nil or game_info.title == "" then + game_info.title = "Mineclone 2" + end + -- Notes: "game.conf doesn't support id currently, this is planned in the future" - rubenwardy from the github issue. + -- TODO: Remove workaround after minetest.get_game_info().id is implemented. + if version == nil or version == "" then -- workaround for id = not being implemented yet. + if game_info.id == nil or game_info.id == "" then + game_info.id = " Please upgrade your version to the newest version for the /ver command to work." + end + else + game_info.id = version + end + + minetest.chat_send_player(name, string.format("Version: %s - %s", game_info.title, game_info.id)) + return true + end +}) + diff --git a/mods/HUD/mcl_ver_info/locale/template.txt b/mods/HUD/mcl_ver_info/locale/template.txt new file mode 100644 index 000000000..75febe815 --- /dev/null +++ b/mods/HUD/mcl_ver_info/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain: mcl_ver_info +Sorry, but your version of Minetest doesn't support the latest API. Please upgrade your minetest.= \ No newline at end of file diff --git a/mods/HUD/mcl_ver_info/mod.conf b/mods/HUD/mcl_ver_info/mod.conf new file mode 100644 index 000000000..b6f6dca98 --- /dev/null +++ b/mods/HUD/mcl_ver_info/mod.conf @@ -0,0 +1,4 @@ +name = mcl_ver_info +description = Prints game version information; /ver command. +depends = mcl_init +author = Michieal diff --git a/mods/ITEMS/REDSTONE/mesecons_button/init.lua b/mods/ITEMS/REDSTONE/mesecons_button/init.lua index 2812b2758..fb01b7bb7 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_button/init.lua @@ -223,6 +223,10 @@ local woods = { { "darkwood", "mcl_core:darkwood", "mcl_core_planks_big_oak.png", S("Dark Oak Button") }, { "sprucewood", "mcl_core:sprucewood", "mcl_core_planks_spruce.png", S("Spruce Button") }, { "junglewood", "mcl_core:junglewood", "default_junglewood.png", S("Jungle Button") }, + + { "mangrove_wood", "mcl_mangrove:mangrove_wood", "mcl_mangrove_planks.png", S("Mangrove Button") }, + { "crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", "crimson_hyphae_wood.png", S("Crimson Button") }, + { "warped_hyphae_wood", "mcl_crimson:warped_hyphae_wood", "warped_hyphae_wood.png", S("Warped Button") }, } for w=1, #woods do diff --git a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua index a27904e48..b2ff0916e 100644 --- a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua @@ -364,7 +364,7 @@ function mesecon.mvps_move_objects(pos, dir, nodestack) for _, r in ipairs(mesecon.rules.alldirs) do local adjpos = vector.add(np, r) local adjnode = minetest.get_node(adjpos) - if minetest.registered_nodes[adjnode.name] and minetest.registered_nodes[adjnode.name].mvps_sticky then + if minetest.registered_nodes[adjnode.name] and minetest.registered_nodes[adjnode.name].mvps_sticky and adjnode.name == "mcl_core:slimeblock" then local np = vector.add(obj:get_pos(), dir) -- Reset acceleration of all objects before launching. diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua index 495fbd048..9248e693e 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua @@ -12,6 +12,16 @@ local pp_box_on = { fixed = { -7/16, -8/16, -7/16, 7/16, -7.5/16, 7/16 }, } +local function pp_on_rightclick(pos, node) + local basename = minetest.registered_nodes[node.name].pressureplate_basename + if node.name == basename .. "_off" then + minetest.set_node(pos, { name = basename .. "_on" }) + mesecon.receptor_on(pos, mesecon.rules.pplate) + else + minetest.get_meta(pos):set_string("deact_time", "") + end +end + local function pp_on_timer(pos, elapsed) local node = minetest.get_node(pos) local basename = minetest.registered_nodes[node.name].pressureplate_basename @@ -37,34 +47,80 @@ local function pp_on_timer(pos, elapsed) end end - local objs = minetest.get_objects_inside_radius(pos, 1) + local function obj_touching_plate_pos(obj_ref, plate_pos) + local obj_pos = obj_ref:get_pos() + local props = obj_ref:get_properties() + local parent = obj_ref:get_attach() + if props and obj_pos and not parent then + local collisionbox = props.collisionbox + local physical = props.physical + local is_player = obj_ref:is_player() + local luaentity = obj_ref:get_luaentity() + local is_item = luaentity and luaentity.name == "__builtin:item" + if collisionbox and physical or is_player or is_item then + local plate_x_min = plate_pos.x - 7 / 16 + local plate_x_max = plate_pos.x + 7 / 16 + local plate_z_min = plate_pos.z - 7 / 16 + local plate_z_max = plate_pos.z + 7 / 16 + local plate_y_max = plate_pos.y - 7 / 16 - if node.name == basename .. "_on" then - local disable - if #objs == 0 then - disable = true - elseif not activated_by.any then - disable = true - for k, obj in pairs(objs) do - if obj_does_activate(obj, activated_by) then - disable = false - break + local obj_x_min = obj_pos.x + collisionbox[1] + local obj_x_max = obj_pos.x + collisionbox[4] + local obj_z_min = obj_pos.z + collisionbox[3] + local obj_z_max = obj_pos.z + collisionbox[6] + local obj_y_min = obj_pos.y + collisionbox[2] + + if + obj_y_min <= plate_y_max and + not (obj_x_min >= plate_x_max) and + not (obj_x_max <= plate_x_min) and + not (obj_z_min >= plate_z_max) and + not (obj_z_max <= plate_z_min) + then + return true end end end + return false + end + + local objs = minetest.get_objects_inside_radius(pos, 1) + + if node.name == basename .. "_on" then + local disable = true + for k, obj in pairs(objs) do + if + obj_does_activate(obj, activated_by) and + obj_touching_plate_pos(obj, pos) + then + disable = false + minetest.get_meta(pos):set_string("deact_time", "") + break + end + end if disable then - minetest.set_node(pos, {name = basename .. "_off"}) - mesecon.receptor_off(pos, mesecon.rules.pplate) + local meta = minetest.get_meta(pos) + local deact_time = meta:get_float("deact_time") + local current_time = minetest.get_us_time() + if deact_time == 0 then + deact_time = current_time + 1 * 1000 * 1000 + meta:set_float("deact_time", deact_time) + end + if deact_time <= current_time then + minetest.set_node(pos, { name = basename .. "_off" }) + mesecon.receptor_off(pos, mesecon.rules.pplate) + meta:set_string("deact_time", "") + end end elseif node.name == basename .. "_off" then for k, obj in pairs(objs) do - local objpos = obj:get_pos() - if obj_does_activate(obj, activated_by) then - if objpos.y > pos.y-1 and objpos.y < pos.y then - minetest.set_node(pos, {name = basename .. "_on"}) - mesecon.receptor_on(pos, mesecon.rules.pplate) - break - end + if + obj_does_activate(obj, activated_by) and + obj_touching_plate_pos(obj, pos) + then + minetest.set_node(pos, { name = basename .. "_on" }) + mesecon.receptor_on(pos, mesecon.rules.pplate) + break end end end @@ -118,6 +174,7 @@ function mesecon.register_pressure_plate(basename, description, textures_off, te walkable = false, description = description, on_timer = pp_on_timer, + on_rightclick = pp_on_rightclick, on_construct = function(pos) minetest.get_node_timer(pos):start(PRESSURE_PLATE_INTERVAL) end, @@ -164,6 +221,10 @@ local woods = { { "darkwood", "mcl_core:darkwood", "mcl_core_planks_big_oak.png", S("Dark Oak Pressure Plate" )}, { "sprucewood", "mcl_core:sprucewood", "mcl_core_planks_spruce.png", S("Spruce Pressure Plate") }, { "junglewood", "mcl_core:junglewood", "default_junglewood.png", S("Jungle Pressure Plate") }, + + { "mangrove_wood", "mcl_mangrove:mangrove_wood", "mcl_mangrove_planks.png", S("Mangrove Pressure Plate") }, + { "crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", "crimson_hyphae_wood.png", S("Crimson Pressure Plate") }, + { "warped_hyphae_wood", "mcl_crimson:warped_hyphae_wood", "warped_hyphae_wood.png", S("Warped Pressure Plate") }, } for w=1, #woods do diff --git a/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_off.png b/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_off.png index cecdaf8fa..fff9a53a9 100644 Binary files a/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_off.png and b/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_off.png differ diff --git a/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_on.png b/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_on.png index 24d0a94d9..705f3db94 100644 Binary files a/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_on.png and b/mods/ITEMS/REDSTONE/mesecons_torch/textures/jeija_torches_on.png differ diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index 86cc079fe..36c4a907a 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -129,27 +129,24 @@ if minetest.get_modpath("mcl_sounds") then end function mcl_beds.register_bed(name, def) - local node_box_bottom, selection_box_bottom, collision_box_bottom - if def.nodebox and def.nodebox.bottom then - node_box_bottom = { type = "fixed", fixed = def.nodebox.bottom } - end - if def.selectionbox and def.selectionbox.bottom then - selection_box_bottom = { type = "fixed", fixed = def.selectionbox.bottom } - end - if def.collisionbox and def.collisionbox.bottom then - collision_box_bottom = { type = "fixed", fixed = def.collisionbox.bottom } - end + local common_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + } + minetest.register_node(name .. "_bottom", { description = def.description, _tt_help = S("Allows you to sleep"), + _doc_items_longdesc = def._doc_items_longdesc or beddesc, _doc_items_usagehelp = def._doc_items_usagehelp or beduse, _doc_items_create_entry = def._doc_items_create_entry, _doc_items_entry_name = def._doc_items_entry_name, inventory_image = def.inventory_image, wield_image = def.wield_image, - drawtype = "nodebox", - tiles = def.tiles.bottom, + drawtype = "mesh", + mesh = "mcl_beds_bed_bottom.obj", + tiles = def.tiles, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", paramtype2 = "facedir", @@ -159,11 +156,11 @@ function mcl_beds.register_bed(name, def) _mcl_hardness = 0.2, _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, - node_box = node_box_bottom, - selection_box = selection_box_bottom, - collision_box = collision_box_bottom, + selection_box = common_box, + collision_box = common_box, drop = "", node_placement_prediction = "", + on_place = function(itemstack, placer, pointed_thing) local under = pointed_thing.under @@ -229,20 +226,12 @@ function mcl_beds.register_bed(name, def) on_rotate = rotate, }) - local node_box_top, selection_box_top, collision_box_top - if def.nodebox and def.nodebox.top then - node_box_top = { type = "fixed", fixed = def.nodebox.top } - end - if def.selectionbox and def.selectionbox.top then - selection_box_top = { type = "fixed", fixed = def.selectionbox.top } - end - if def.collisionbox and def.collisionbox.top then - collision_box_top = { type = "fixed", fixed = def.collisionbox.top } - end + minetest.register_node(name .. "_top", { - drawtype = "nodebox", - tiles = def.tiles.top, + drawtype = "mesh", + mesh = "mcl_beds_bed_top.obj", + tiles = def.tiles, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", paramtype2 = "facedir", @@ -253,13 +242,14 @@ function mcl_beds.register_bed(name, def) _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, drop = "", - node_box = node_box_top, - selection_box = selection_box_top, - collision_box = collision_box_top, + selection_box = common_box, + collision_box = common_box, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) mcl_beds.on_rightclick(pos, clicker, true) return itemstack end, + on_rotate = rotate, after_destruct = destruct_bed, }) diff --git a/mods/ITEMS/mcl_beds/beds.lua b/mods/ITEMS/mcl_beds/beds.lua index 5043c85d2..7aa49f8c7 100644 --- a/mods/ITEMS/mcl_beds/beds.lua +++ b/mods/ITEMS/mcl_beds/beds.lua @@ -1,18 +1,6 @@ local S = minetest.get_translator(minetest.get_current_modname()) local mod_doc = minetest.get_modpath("doc") -local nodebox = { - bottom = { - {-0.5, -5/16, -0.5, 0.5, 0.06, 0.5}, - {-0.5, -0.5, -0.5, -5/16, -5/16, -5/16}, - {0.5, -0.5, -0.5, 5/16, -5/16, -5/16}, - }, - top = { - {-0.5, -5/16, -0.5, 0.5, 0.06, 0.5}, - {-0.5, -0.5, 0.5, -5/16, -5/16, 5/16}, - {0.5, -0.5, 0.5, 5/16, -5/16, 5/16}, - }, -} local colors = { -- { ID, decription, wool, dye } @@ -70,36 +58,13 @@ for c=1, #colors do description = colors[c][2], _doc_items_entry_name = entry_name, _doc_items_create_entry = create_entry, - inventory_image = "mcl_beds_bed_"..colorid..".png", - wield_image = "mcl_beds_bed_"..colorid..".png", + inventory_image = "mcl_beds_bed_"..colorid.."_inv.png", + wield_image = "mcl_beds_bed_"..colorid.."_inv.png", + tiles = { - bottom = { - "mcl_beds_bed_top_bottom_"..colorid..".png^[transformR90", - "default_wood.png^mcl_beds_bed_bottom_bottom.png", - "mcl_beds_bed_side_bottom_r_"..colorid..".png", - "mcl_beds_bed_side_bottom_r_"..colorid..".png^[transformfx", - "mcl_beds_bed_side_top_"..colorid..".png", - "mcl_beds_bed_side_bottom_"..colorid..".png" - }, - top = { - "mcl_beds_bed_top_top_"..colorid..".png^[transformR90", - "default_wood.png^mcl_beds_bed_bottom_top.png", - "mcl_beds_bed_side_top_r_"..colorid..".png", - "mcl_beds_bed_side_top_r_"..colorid..".png^[transformfx", - "mcl_beds_bed_side_top_"..colorid..".png", - "mcl_beds_bed_side_bottom_"..colorid..".png" - } - }, - nodebox = nodebox, - selectionbox = { - bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, - top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, - }, - -- Simplified collision box because Minetest acts weird if we use the nodebox one - collisionbox = { - bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, - top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + "mcl_beds_bed_"..colorid..".png" }, + recipe = main_recipe, }) if mod_doc and not is_canonical then diff --git a/mods/ITEMS/mcl_beds/functions.lua b/mods/ITEMS/mcl_beds/functions.lua index c745b5f0c..7199c7b7e 100644 --- a/mods/ITEMS/mcl_beds/functions.lua +++ b/mods/ITEMS/mcl_beds/functions.lua @@ -10,6 +10,10 @@ local explosions_mod = minetest.get_modpath("mcl_explosions") local spawn_mod = minetest.get_modpath("mcl_spawn") local worlds_mod = minetest.get_modpath("mcl_worlds") +local function mcl_log (message) + mcl_util.mcl_log (message, "[Beds]") +end + -- Helper functions local function get_look_yaw(pos) @@ -300,6 +304,37 @@ function mcl_beds.skip_night() minetest.set_timeofday(0.25) -- tod = 6000 end +function mcl_beds.get_bed_top (pos) + local node = minetest.get_node(pos) + local dir = minetest.facedir_to_dir(node.param2) + local bed_top_pos = vector.add(pos, dir) + local bed_top = minetest.get_node(bed_top_pos) + + if bed_top then + --mcl_log("Has a bed top") + else + --mcl_log("No bed top") + end + return bed_top_pos +end + +function mcl_beds.get_bed_bottom (pos) + local node = minetest.get_node(pos) + local dir = minetest.facedir_to_dir(node.param2) + mcl_log("Dir: " .. tostring(dir)) + local bed_bottom = vector.add(pos, -dir) + mcl_log("bed_bottom: " .. tostring(bed_bottom)) + + local bed_bottom_node = minetest.get_node(bed_bottom) + if bed_bottom_node then + mcl_log("Bed bottom node name:" .. bed_bottom_node.name) + else + mcl_log("Didn't get bed bottom") + end + + return bed_bottom +end + function mcl_beds.on_rightclick(pos, player, is_top) -- Anti-Inception: Don't allow to sleep while you're sleeping if player:get_meta():get_string("mcl_beds:sleeping") == "true" then @@ -329,9 +364,7 @@ function mcl_beds.on_rightclick(pos, player, is_top) if is_top then message = select(2, lay_down(player, ppos, pos)) else - local node = minetest.get_node(pos) - local dir = minetest.facedir_to_dir(node.param2) - local other = vector.add(pos, dir) + local other = mcl_beds.get_bed_top (pos) message = select(2, lay_down(player, ppos, other)) end if message then diff --git a/mods/ITEMS/mcl_beds/models/mcl_beds_bed_bottom.obj b/mods/ITEMS/mcl_beds/models/mcl_beds_bed_bottom.obj new file mode 100644 index 000000000..0e2fe2da9 --- /dev/null +++ b/mods/ITEMS/mcl_beds/models/mcl_beds_bed_bottom.obj @@ -0,0 +1,290 @@ +# Made in Blockbench 3.6.6 +mtllib mcl_beds_bed_bottom.mtl +o cube +v 0.5 0.0625 0.5 +v 0.5 0.0625 -0.5 +v 0.5 -0.3125 0.5 +v 0.5 -0.3125 -0.5 +v -0.5 0.0625 -0.5 +v -0.5 0.0625 0.5 +v -0.5 -0.3125 -0.5 +v -0.5 -0.3125 0.5 +vt 0.09375 0.5625 +vt 0 0.5625 +vt 0.09375 0.3125 +vt 0 0.5625 +vt 0 0.3125 +vt 0.09375 0.3125 +vt 0.34375 0.3125 +vt 0.4375 0.3125 +vt 0.34375 0.5625 +vt 0.4375 0.3125 +vt 0.4375 0.5625 +vt 0.34375 0.5625 +vt 0.34375 0.3125 +vt 0.34375 0.5625 +vt 0.09375 0.3125 +vt 0.34375 0.5625 +vt 0.09375 0.5625 +vt 0.09375 0.3125 +vt 0.43750000000000006 0.5625 +vt 0.43750000000000006 0.3125 +vt 0.6875 0.5625 +vt 0.43750000000000006 0.3125 +vt 0.6875 0.3125 +vt 0.6875 0.5625 +vt 0 0.015625 +vt 0 0 +vt 0.125 0.015625 +vt 0 0 +vt 0.125 0 +vt 0.125 0.015625 +vt 0.59375 0.5625 +vt 0.59375 0.65625 +vt 0.34374999999999994 0.5625 +vt 0.59375 0.65625 +vt 0.34374999999999994 0.65625 +vt 0.34374999999999994 0.5625 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_0 +f 1/1/1 3/2/2 2/3/3 +f 3/4/4 4/5/5 2/6/6 +usemtl m_0 +f 5/7/7 7/8/8 6/9/9 +f 7/10/10 8/11/11 6/12/12 +usemtl m_0 +f 5/13/13 6/14/14 2/15/15 +f 6/16/16 1/17/17 2/18/18 +usemtl m_0 +f 8/19/19 7/20/20 3/21/21 +f 7/22/22 4/23/23 3/24/24 +usemtl m_0 +f 2/31/31 4/32/32 5/33/33 +f 4/34/34 7/35/35 5/36/36 +o cube +v -0.3125 -0.3125 -0.3125 +v -0.3125 -0.3125 -0.5 +v -0.3125 -0.5 -0.3125 +v -0.3125 -0.5 -0.5 +v -0.5 -0.3125 -0.5 +v -0.5 -0.3125 -0.3125 +v -0.5 -0.5 -0.5 +v -0.5 -0.5 -0.3125 +vt 0.921875 0.671875 +vt 0.921875 0.625 +vt 0.96875 0.671875 +vt 0.921875 0.625 +vt 0.96875 0.625 +vt 0.96875 0.671875 +vt 0.828125 0.765625 +vt 0.828125 0.71875 +vt 0.875 0.765625 +vt 0.828125 0.71875 +vt 0.875 0.71875 +vt 0.875 0.765625 +vt 0.046875 0.953125 +vt 0.046875 1 +vt 0 0.953125 +vt 0.046875 1 +vt 0 1 +vt 0 0.953125 +vt 0.921875 0.765625 +vt 0.921875 0.8125 +vt 0.875 0.765625 +vt 0.921875 0.8125 +vt 0.875 0.8125 +vt 0.875 0.765625 +vt 0.875 0.765625 +vt 0.875 0.71875 +vt 0.921875 0.765625 +vt 0.875 0.71875 +vt 0.921875 0.71875 +vt 0.921875 0.765625 +vt 0.78125 0.765625 +vt 0.78125 0.71875 +vt 0.828125 0.765625 +vt 0.78125 0.71875 +vt 0.828125 0.71875 +vt 0.828125 0.765625 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_0 +f 9/37/37 11/38/38 10/39/39 +f 11/40/40 12/41/41 10/42/42 +usemtl m_0 +f 13/43/43 15/44/44 14/45/45 +f 15/46/46 16/47/47 14/48/48 +usemtl m_0 +f 16/55/55 15/56/56 11/57/57 +f 15/58/58 12/59/59 11/60/60 +usemtl m_0 +f 14/61/61 16/62/62 9/63/63 +f 16/64/64 11/65/65 9/66/66 +usemtl m_0 +f 10/67/67 12/68/68 13/69/69 +f 12/70/70 15/71/71 13/72/72 +o cube +v 0.5 -0.3125 -0.3125 +v 0.5 -0.3125 -0.5 +v 0.5 -0.5 -0.3125 +v 0.5 -0.5 -0.5 +v 0.3125 -0.3125 -0.5 +v 0.3125 -0.3125 -0.3125 +v 0.3125 -0.5 -0.5 +v 0.3125 -0.5 -0.3125 +vt 0.78125 0.953125 +vt 0.78125 0.90625 +vt 0.828125 0.953125 +vt 0.78125 0.90625 +vt 0.828125 0.90625 +vt 0.828125 0.953125 +vt 0.875 0.953125 +vt 0.875 0.90625 +vt 0.921875 0.953125 +vt 0.875 0.90625 +vt 0.921875 0.90625 +vt 0.921875 0.953125 +vt 0.046875 0.953125 +vt 0.046875 1 +vt 0 0.953125 +vt 0.046875 1 +vt 0 1 +vt 0 0.953125 +vt 0.921875 0.953125 +vt 0.921875 1 +vt 0.875 0.953125 +vt 0.921875 1 +vt 0.875 1 +vt 0.875 0.953125 +vt 0.921875 0.953125 +vt 0.921875 0.90625 +vt 0.96875 0.953125 +vt 0.921875 0.90625 +vt 0.96875 0.90625 +vt 0.96875 0.953125 +vt 0.828125 0.953125 +vt 0.828125 0.90625 +vt 0.875 0.953125 +vt 0.828125 0.90625 +vt 0.875 0.90625 +vt 0.875 0.953125 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_0 +f 17/73/73 19/74/74 18/75/75 +f 19/76/76 20/77/77 18/78/78 +usemtl m_0 +f 21/79/79 23/80/80 22/81/81 +f 23/82/82 24/83/83 22/84/84 +usemtl m_0 +f 24/91/91 23/92/92 19/93/93 +f 23/94/94 20/95/95 19/96/96 +usemtl m_0 +f 22/97/97 24/98/98 17/99/99 +f 24/100/100 19/101/101 17/102/102 +usemtl m_0 +f 18/103/103 20/104/104 21/105/105 +f 20/106/106 23/107/107 21/108/108 diff --git a/mods/ITEMS/mcl_beds/models/mcl_beds_bed_top.obj b/mods/ITEMS/mcl_beds/models/mcl_beds_bed_top.obj new file mode 100644 index 000000000..9a34a27ec --- /dev/null +++ b/mods/ITEMS/mcl_beds/models/mcl_beds_bed_top.obj @@ -0,0 +1,299 @@ +# Made in Blockbench 3.6.6 +mtllib mcl_beds_bed_top.mtl +o cube +v -0.5000000000000001 0.0625 -0.49999999999999994 +v -0.49999999999999994 0.0625 0.5000000000000001 +v -0.5000000000000001 -0.3125 -0.49999999999999994 +v -0.49999999999999994 -0.3125 0.5000000000000001 +v 0.5000000000000001 0.0625 0.49999999999999994 +v 0.49999999999999994 0.0625 -0.5000000000000001 +v 0.5000000000000001 -0.3125 0.49999999999999994 +v 0.49999999999999994 -0.3125 -0.5000000000000001 +vt 0.34374999999999994 0.65625 +vt 0.43749999999999994 0.65625 +vt 0.34374999999999994 0.90625 +vt 0.43749999999999994 0.65625 +vt 0.43749999999999994 0.90625 +vt 0.34374999999999994 0.90625 +vt 0.09375 0.90625 +vt 0 0.90625 +vt 0.09375 0.65625 +vt 0 0.90625 +vt 0 0.65625 +vt 0.09375 0.65625 +vt 0.09375 0.90625 +vt 0.09375 0.65625 +vt 0.34375 0.90625 +vt 0.09375 0.65625 +vt 0.34375 0.65625 +vt 0.34375 0.90625 +vt 0.6874843749999999 0.6562812499999999 +vt 0.6874843749999999 0.90628125 +vt 0.437484375 0.6562812499999999 +vt 0.6874843749999999 0.90628125 +vt 0.437484375 0.90628125 +vt 0.437484375 0.6562812499999999 +vt 0 1 +vt 0 0.875 +vt 0.1875 1 +vt 0 0.875 +vt 0.1875 0.875 +vt 0.1875 1 +vt 0.34375 0.90625 +vt 0.34375 1 +vt 0.09375 0.90625 +vt 0.34375 1 +vt 0.09375 1 +vt 0.09375 0.90625 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +usemtl m_0 +f 1/1/1 3/2/2 2/3/3 +f 3/4/4 4/5/5 2/6/6 +usemtl m_0 +f 5/7/7 7/8/8 6/9/9 +f 7/10/10 8/11/11 6/12/12 +usemtl m_0 +f 5/13/13 6/14/14 2/15/15 +f 6/16/16 1/17/17 2/18/18 +usemtl m_0 +f 8/19/19 7/20/20 3/21/21 +f 7/22/22 4/23/23 3/24/24 +usemtl none +f 6/25/25 8/26/26 1/27/27 +f 8/28/28 3/29/29 1/30/30 +usemtl m_0 +f 2/31/31 4/32/32 5/33/33 +f 4/34/34 7/35/35 5/36/36 +o cube +v 0.31250000000000006 -0.3125 0.31249999999999994 +v 0.31250000000000006 -0.3125 0.49999999999999994 +v 0.31250000000000006 -0.5 0.31249999999999994 +v 0.31250000000000006 -0.5 0.49999999999999994 +v 0.5000000000000001 -0.3125 0.49999999999999994 +v 0.5 -0.3125 0.31249999999999994 +v 0.5000000000000001 -0.5 0.49999999999999994 +v 0.5 -0.5 0.31249999999999994 +vt 0.921875 0.859375 +vt 0.921875 0.8125 +vt 0.96875 0.859375 +vt 0.921875 0.8125 +vt 0.96875 0.8125 +vt 0.96875 0.859375 +vt 0.828125 0.859375 +vt 0.828125 0.8125 +vt 0.875 0.859375 +vt 0.828125 0.8125 +vt 0.875 0.8125 +vt 0.875 0.859375 +vt 0 1 +vt 0 0.953125 +vt 0.046875 1 +vt 0 0.953125 +vt 0.046875 0.953125 +vt 0.046875 1 +vt 0.875 0.90625 +vt 0.875 0.859375 +vt 0.921875 0.90625 +vt 0.875 0.859375 +vt 0.921875 0.859375 +vt 0.921875 0.90625 +vt 0.875 0.859375 +vt 0.875 0.8125 +vt 0.921875 0.859375 +vt 0.875 0.8125 +vt 0.921875 0.8125 +vt 0.921875 0.859375 +vt 0.78125 0.859375 +vt 0.78125 0.8125 +vt 0.828125 0.859375 +vt 0.78125 0.8125 +vt 0.828125 0.8125 +vt 0.828125 0.859375 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +usemtl m_0 +f 9/37/37 11/38/38 10/39/39 +f 11/40/40 12/41/41 10/42/42 +usemtl m_0 +f 13/43/43 15/44/44 14/45/45 +f 15/46/46 16/47/47 14/48/48 +usemtl none +f 13/49/49 14/50/50 10/51/51 +f 14/52/52 9/53/53 10/54/54 +usemtl m_0 +f 16/55/55 15/56/56 11/57/57 +f 15/58/58 12/59/59 11/60/60 +usemtl m_0 +f 14/61/61 16/62/62 9/63/63 +f 16/64/64 11/65/65 9/66/66 +usemtl m_0 +f 10/67/67 12/68/68 13/69/69 +f 12/70/70 15/71/71 13/72/72 +o cube +v -0.5 -0.3125 0.31249999999999994 +v -0.4999999999999999 -0.3125 0.49999999999999994 +v -0.5 -0.5 0.31249999999999994 +v -0.4999999999999999 -0.5 0.49999999999999994 +v -0.3124999999999999 -0.3125 0.4999999999999999 +v -0.3125 -0.3125 0.3124999999999999 +v -0.3124999999999999 -0.5 0.4999999999999999 +v -0.3125 -0.5 0.3124999999999999 +vt 0.78125 0.671875 +vt 0.78125 0.625 +vt 0.828125 0.671875 +vt 0.78125 0.625 +vt 0.828125 0.625 +vt 0.828125 0.671875 +vt 0.875 0.671875 +vt 0.875 0.625 +vt 0.921875 0.671875 +vt 0.875 0.625 +vt 0.921875 0.625 +vt 0.921875 0.671875 +vt 0 1 +vt 0 0.953125 +vt 0.046875 1 +vt 0 0.953125 +vt 0.046875 0.953125 +vt 0.046875 1 +vt 0.87496875 0.7187656250000001 +vt 0.87496875 0.6719062499999999 +vt 0.921828125 0.7187656250000001 +vt 0.87496875 0.6719062499999999 +vt 0.921828125 0.6719062499999999 +vt 0.921828125 0.7187656250000001 +vt 0.921875 0.671875 +vt 0.921875 0.625 +vt 0.96875 0.671875 +vt 0.921875 0.625 +vt 0.96875 0.625 +vt 0.96875 0.671875 +vt 0.828125 0.671875 +vt 0.828125 0.625 +vt 0.875 0.671875 +vt 0.828125 0.625 +vt 0.875 0.625 +vt 0.875 0.671875 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn -1 0 1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 1 0 -1.2246467991473532e-16 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn -1.2246467991473532e-16 0 -1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +vn 1.2246467991473532e-16 0 1 +usemtl m_0 +f 17/73/73 19/74/74 18/75/75 +f 19/76/76 20/77/77 18/78/78 +usemtl m_0 +f 21/79/79 23/80/80 22/81/81 +f 23/82/82 24/83/83 22/84/84 +usemtl none +f 21/85/85 22/86/86 18/87/87 +f 22/88/88 17/89/89 18/90/90 +usemtl m_0 +f 24/91/91 23/92/92 19/93/93 +f 23/94/94 20/95/95 19/96/96 +usemtl m_0 +f 22/97/97 24/98/98 17/99/99 +f 24/100/100 19/101/101 17/102/102 +usemtl m_0 +f 18/103/103 20/104/104 21/105/105 +f 20/106/106 23/107/107 21/108/108 diff --git a/mods/ITEMS/mcl_beds/respawn_anchor.lua b/mods/ITEMS/mcl_beds/respawn_anchor.lua index bb36fe9d0..565c2b665 100644 --- a/mods/ITEMS/mcl_beds/respawn_anchor.lua +++ b/mods/ITEMS/mcl_beds/respawn_anchor.lua @@ -67,7 +67,10 @@ for i=0,4 do minetest.register_node("mcl_beds:respawn_anchor_charged_"..i,{ description=S("Respawn Anchor"), tiles = { - "portal.png", + { + image="respawn_anchor_top_on.png", + animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} + }, "respawn_anchor_bottom.png", "respawn_anchor_side"..i ..".png" }, diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black.png index 6da9b5690..6e79589ce 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black_inv.png new file mode 100644 index 000000000..6da9b5690 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_black_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue.png index d6bee0a72..7be362c2c 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue_inv.png new file mode 100644 index 000000000..d6bee0a72 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_blue_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_bottom.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_bottom.png deleted file mode 100644 index 35c9d59ca..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_bottom.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_top.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_top.png deleted file mode 100644 index 87a0e2abd..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_bottom_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown.png index 5cb0e4196..734ca550e 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown_inv.png new file mode 100644 index 000000000..5cb0e4196 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_brown_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan.png index 03eec9c70..61a9f9ce4 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan_inv.png new file mode 100644 index 000000000..03eec9c70 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_cyan_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green.png index a2fa4bff5..e70331fcc 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green_inv.png new file mode 100644 index 000000000..a2fa4bff5 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_green_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey.png index a53dec153..da586dccf 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey_inv.png new file mode 100644 index 000000000..a53dec153 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_grey_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue.png index 2e70475ae..ee8d68a03 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue_inv.png new file mode 100644 index 000000000..2e70475ae Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_light_blue_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime.png index 9bfb2f9c4..bde92dd81 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime_inv.png new file mode 100644 index 000000000..9bfb2f9c4 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_lime_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta.png index b223b591e..3d790fb16 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta_inv.png new file mode 100644 index 000000000..b223b591e Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_magenta_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange.png index df14acbf9..6cb474dd9 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange_inv.png new file mode 100644 index 000000000..df14acbf9 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_orange_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink.png index e0f6365ba..5336fc74a 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink_inv.png new file mode 100644 index 000000000..e0f6365ba Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_pink_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple.png index abf4c3593..ec5df9693 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple_inv.png new file mode 100644 index 000000000..abf4c3593 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_purple_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red.png index 20fcd7ca6..d6cfef4c4 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red_inv.png new file mode 100644 index 000000000..20fcd7ca6 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_red_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_black.png deleted file mode 100644 index 302bc5b40..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_blue.png deleted file mode 100644 index 0d5b3f412..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_brown.png deleted file mode 100644 index 25983a530..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_cyan.png deleted file mode 100644 index 94614b075..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_green.png deleted file mode 100644 index f4990d58f..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_grey.png deleted file mode 100644 index 40727ca8e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_light_blue.png deleted file mode 100644 index dec15108d..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_lime.png deleted file mode 100644 index fef72ce3b..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_magenta.png deleted file mode 100644 index f1cfdde62..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_orange.png deleted file mode 100644 index e8faf315e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_pink.png deleted file mode 100644 index f536a7960..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_purple.png deleted file mode 100644 index acdf05e87..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_black.png deleted file mode 100644 index 84c1b31f2..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_blue.png deleted file mode 100644 index 474a8f6fb..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_brown.png deleted file mode 100644 index fe1e8e425..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_cyan.png deleted file mode 100644 index 5eacdf654..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_green.png deleted file mode 100644 index d98f4263a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_grey.png deleted file mode 100644 index 02e80ed96..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_light_blue.png deleted file mode 100644 index c3ca6ed88..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_lime.png deleted file mode 100644 index d33985789..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_magenta.png deleted file mode 100644 index 273f0f570..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_orange.png deleted file mode 100644 index 65333f73a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_pink.png deleted file mode 100644 index 5907ad86f..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_purple.png deleted file mode 100644 index 0bfa0a1b7..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_red.png deleted file mode 100644 index b324086d6..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_silver.png deleted file mode 100644 index 0269dc778..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_white.png deleted file mode 100644 index 1ed1e0239..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_yellow.png deleted file mode 100644 index 378b63341..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_r_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_red.png deleted file mode 100644 index 103570e14..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_silver.png deleted file mode 100644 index 490298dd1..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_white.png deleted file mode 100644 index 8cdbd2b1d..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_yellow.png deleted file mode 100644 index fed97cded..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_bottom_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_black.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_blue.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_brown.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_cyan.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_green.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_grey.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_light_blue.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_lime.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_magenta.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_orange.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_pink.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_purple.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_black.png deleted file mode 100644 index 5bfa983c3..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_blue.png deleted file mode 100644 index ecf58cd03..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_brown.png deleted file mode 100644 index f1473c36a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_cyan.png deleted file mode 100644 index e3c466ece..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_green.png deleted file mode 100644 index e59981a4c..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_grey.png deleted file mode 100644 index 65052ad02..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_light_blue.png deleted file mode 100644 index 974ac6566..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_lime.png deleted file mode 100644 index 88c367407..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_magenta.png deleted file mode 100644 index 04bdc7ddf..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_orange.png deleted file mode 100644 index 5271b820a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_pink.png deleted file mode 100644 index ca6b5047a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_purple.png deleted file mode 100644 index 740824b38..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_red.png deleted file mode 100644 index 638bdd508..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_silver.png deleted file mode 100644 index b0739432e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_white.png deleted file mode 100644 index 1e536432e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_yellow.png deleted file mode 100644 index a3d9c8c2b..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_r_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_red.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_silver.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_white.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_yellow.png deleted file mode 100644 index 39fb8c580..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_side_top_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver.png index 73de606f2..35691660a 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver_inv.png new file mode 100644 index 000000000..73de606f2 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_silver_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_black.png deleted file mode 100644 index 046e847a6..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_blue.png deleted file mode 100644 index 0c6affda8..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_brown.png deleted file mode 100644 index cf3eaa405..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_cyan.png deleted file mode 100644 index 2963d1da2..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_gray.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_gray.png deleted file mode 100644 index d1cd63897..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_gray.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_green.png deleted file mode 100644 index 4eda85f33..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_grey.png deleted file mode 100644 index 1aa01946e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_light_blue.png deleted file mode 100644 index 949efb20e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_lime.png deleted file mode 100644 index 14ad57bd1..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_magenta.png deleted file mode 100644 index ce9e6a3de..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_orange.png deleted file mode 100644 index 036ec1169..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_pink.png deleted file mode 100644 index b94a3d989..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_purple.png deleted file mode 100644 index bf053e334..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_red.png deleted file mode 100644 index 77668f201..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_silver.png deleted file mode 100644 index d17a506e3..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_white.png deleted file mode 100644 index ee8105119..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_yellow.png deleted file mode 100644 index d10fb92fa..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_bottom_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_black.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_black.png deleted file mode 100644 index 1c2c0abcd..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_black.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_blue.png deleted file mode 100644 index ccc492158..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_brown.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_brown.png deleted file mode 100644 index d18faece8..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_brown.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_cyan.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_cyan.png deleted file mode 100644 index 0bddf475e..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_cyan.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_green.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_green.png deleted file mode 100644 index 00b23cd8a..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_green.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_grey.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_grey.png deleted file mode 100644 index 1c4903075..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_grey.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_light_blue.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_light_blue.png deleted file mode 100644 index df13cf007..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_light_blue.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_lime.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_lime.png deleted file mode 100644 index b9194be16..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_lime.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_magenta.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_magenta.png deleted file mode 100644 index 215ef796c..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_magenta.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_orange.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_orange.png deleted file mode 100644 index 473caf37f..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_orange.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_pink.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_pink.png deleted file mode 100644 index ac8b29b9b..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_pink.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_purple.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_purple.png deleted file mode 100644 index e29210540..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_purple.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_red.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_red.png deleted file mode 100644 index a418835b5..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_red.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_silver.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_silver.png deleted file mode 100644 index 51609fb0c..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_silver.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_white.png deleted file mode 100644 index d2dc47702..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_white.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_yellow.png deleted file mode 100644 index 10edecc3b..000000000 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_top_top_yellow.png and /dev/null differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white.png index f4ed87dac..f4fda7032 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white_inv.png new file mode 100644 index 000000000..f4ed87dac Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_white_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow.png index 6705b4a80..4e00bb2e0 100644 Binary files a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow.png and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow.png differ diff --git a/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow_inv.png b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow_inv.png new file mode 100644 index 000000000..6705b4a80 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/mcl_beds_bed_yellow_inv.png differ diff --git a/mods/ITEMS/mcl_beds/textures/respawn_anchor_top_on.png b/mods/ITEMS/mcl_beds/textures/respawn_anchor_top_on.png new file mode 100644 index 000000000..ce84dedf2 Binary files /dev/null and b/mods/ITEMS/mcl_beds/textures/respawn_anchor_top_on.png differ diff --git a/mods/ITEMS/mcl_beehives/init.lua b/mods/ITEMS/mcl_beehives/init.lua new file mode 100644 index 000000000..a7a1a7623 --- /dev/null +++ b/mods/ITEMS/mcl_beehives/init.lua @@ -0,0 +1,230 @@ +------------------ +---- Beehives ---- +------------------ + +-- Variables +local S = minetest.get_translator(minetest.get_current_modname()) + +-- Function to allow harvesting honey and honeycomb from the beehive and bee nest. +local honey_harvest = function(pos, node, player, itemstack, pointed_thing) + local inv = player:get_inventory() + local shears = player:get_wielded_item():get_name() == "mcl_tools:shears" + local bottle = player:get_wielded_item():get_name() == "mcl_potions:glass_bottle" + local beehive = "mcl_beehives:beehive" + local is_creative = minetest.is_creative_enabled(player:get_player_name()) + + if node.name == "mcl_beehives:beehive_5" then + beehive = "mcl_beehives:beehive" + elseif node.name == "mcl_beehives:bee_nest_5" then + beehive = "mcl_beehives:bee_nest" + end + + local campfire_area = vector.offset(pos, 0, -5, 0) + local campfire = minetest.find_nodes_in_area(pos, campfire_area, "group:lit_campfire") + + if bottle then + local honey = "mcl_honey:honey_bottle" + if inv:room_for_item("main", honey) then + node.name = beehive + minetest.set_node(pos, node) + inv:add_item("main", "mcl_honey:honey_bottle") + if not is_creative then + itemstack:take_item() + end + if not campfire[1] then mcl_util.deal_damage(player, 10) else awards.unlock(player:get_player_name(), "mcl:bee_our_guest") end + end + elseif shears then + minetest.add_item(pos, "mcl_honey:honeycomb 3") + node.name = beehive + minetest.set_node(pos, node) + if not campfire[1] then mcl_util.deal_damage(player, 10) end + end +end + +-- Dig Function for Beehives +local dig_hive = function(pos, node, oldmetadata, digger) + local wield_item = digger:get_wielded_item() + local beehive = string.find(node.name, "mcl_beehives:beehive") + local beenest = string.find(node.name, "mcl_beehives:bee_nest") + local silk_touch = mcl_enchanting.has_enchantment(wield_item, "silk_touch") + local is_creative = minetest.is_creative_enabled(digger:get_player_name()) + + if beehive then + minetest.add_item(pos, "mcl_beehives:beehive") + if not silk_touch and not is_creative then mcl_util.deal_damage(digger, 10) end + elseif beenest then + if silk_touch or is_creative then + minetest.add_item(pos, "mcl_beehives:bee_nest") + awards.unlock(digger:get_player_name(), "mcl:total_beelocation") + else + mcl_util.deal_damage(digger, 10) + end + end +end + +-- Beehive +minetest.register_node("mcl_beehives:beehive", { + description = S("Beehive"), + _doc_items_longdesc = S("Artificial bee nest."), + tiles = { + "mcl_beehives_beehive_end.png", "mcl_beehives_beehive_end.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_side.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_front.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 5, material_wood = 1, beehive = 1 }, + _mcl_blast_resistance = 0.6, + _mcl_hardness = 0.6, + drop = "", + after_dig_node = dig_hive, +}) + +for l = 1, 4 do + minetest.register_node("mcl_beehives:beehive_" .. l, { + description = S("Beehive"), + _doc_items_longdesc = S("Artificial bee nest."), + tiles = { + "mcl_beehives_beehive_end.png", "mcl_beehives_beehive_end.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_side.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_front.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 5, material_wood = 1, not_in_creative_inventory = 1, beehive = 1 }, + _mcl_blast_resistance = 0.6, + _mcl_hardness = 0.6, + drop = "", + after_dig_node = dig_hive, + }) +end + +minetest.register_node("mcl_beehives:beehive_5", { + description = S("Beehive"), + _doc_items_longdesc = S("Artificial bee nest."), + tiles = { + "mcl_beehives_beehive_end.png", "mcl_beehives_beehive_end.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_side.png", + "mcl_beehives_beehive_side.png", "mcl_beehives_beehive_front_honey.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 5, material_wood = 1, not_in_creative_inventory = 1, beehive = 1 }, + _mcl_blast_resistance = 0.6, + _mcl_hardness = 0.6, + on_rightclick = honey_harvest, + drop = "", + after_dig_node = dig_hive, +}) + +-- Bee Nest +minetest.register_node("mcl_beehives:bee_nest", { + description = S("Bee Nest"), + _doc_items_longdesc = S("A naturally generating block that houses bees and a tasty treat...if you can get it."), + tiles = { + "mcl_beehives_bee_nest_top.png", "mcl_beehives_bee_nest_bottom.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_side.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_front.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 30, bee_nest = 1 }, + _mcl_blast_resistance = 0.3, + _mcl_hardness = 0.3, + drop = "", + after_dig_node = dig_hive, +}) + +for i = 1, 4 do + minetest.register_node("mcl_beehives:bee_nest_"..i, { + description = S("Bee Nest"), + _doc_items_longdesc = S("A naturally generating block that houses bees and a tasty treat...if you can get it."), + tiles = { + "mcl_beehives_bee_nest_top.png", "mcl_beehives_bee_nest_bottom.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_side.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_front.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 30, not_in_creative_inventory = 1, bee_nest = 1 }, + _mcl_blast_resistance = 0.3, + _mcl_hardness = 0.3, + drop = "", + after_dig_node = dig_hive, + }) +end + +minetest.register_node("mcl_beehives:bee_nest_5", { + description = S("Bee Nest"), + _doc_items_longdesc = S("A naturally generating block that houses bees and a tasty treat...if you can get it."), + tiles = { + "mcl_beehives_bee_nest_top.png", "mcl_beehives_bee_nest_bottom.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_side.png", + "mcl_beehives_bee_nest_side.png", "mcl_beehives_bee_nest_front_honey.png", + }, + paramtype2 = "facedir", + groups = { axey = 1, deco_block = 1, flammable = 0, fire_flammability = 30, not_in_creative_inventory = 1, bee_nest = 1 }, + _mcl_blast_resistance = 0.3, + _mcl_hardness = 0.3, + on_rightclick = honey_harvest, + drop = "", + after_dig_node = dig_hive, +}) + +-- Crafting +minetest.register_craft({ + output = "mcl_beehives:beehive", + recipe = { + { "group:wood", "group:wood", "group:wood" }, + { "mcl_honey:honeycomb", "mcl_honey:honeycomb", "mcl_honey:honeycomb" }, + { "group:wood", "group:wood", "group:wood" }, + }, +}) + +-- Temporary ABM to update honey levels +minetest.register_abm({ + label = "Update Beehive Honey Levels", + nodenames = "group:beehive", + interval = 500, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local beehive = "mcl_beehives:beehive" + if node.name == beehive then + node.name = beehive.."_1" + minetest.set_node(pos, node) + elseif node.name == beehive.."_1" then + node.name = beehive.."_2" + minetest.set_node(pos, node) + elseif node.name == beehive.."_2" then + node.name = beehive.."_3" + minetest.set_node(pos, node) + elseif node.name == beehive.."_3" then + node.name = beehive.."_4" + minetest.set_node(pos, node) + elseif node.name == beehive.."_4" then + node.name = beehive.."_5" + minetest.set_node(pos, node) + end + end, +}) + +minetest.register_abm({ + label = "Update Bee Nest Honey Levels", + nodenames = "group:bee_nest", + interval = 500, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local beehive = "mcl_beehives:bee_nest" + if node.name == beehive then + node.name = beehive.."_1" + minetest.set_node(pos, node) + elseif node.name == beehive.."_1" then + node.name = beehive.."_2" + minetest.set_node(pos, node) + elseif node.name == beehive.."_2" then + node.name = beehive.."_3" + minetest.set_node(pos, node) + elseif node.name == beehive.."_3" then + node.name = beehive.."_4" + minetest.set_node(pos, node) + elseif node.name == beehive.."_4" then + node.name = beehive.."_5" + minetest.set_node(pos, node) + end + end, +}) diff --git a/mods/ITEMS/mcl_beehives/locale/template.txt b/mods/ITEMS/mcl_beehives/locale/template.txt new file mode 100644 index 000000000..135786c7c --- /dev/null +++ b/mods/ITEMS/mcl_beehives/locale/template.txt @@ -0,0 +1,4 @@ +Beehive= +Artificial bee nest.= +Bee Nest= +A naturally generating block that houses bees and a tasty treat...if you can get it.= \ No newline at end of file diff --git a/mods/ITEMS/mcl_beehives/mod.conf b/mods/ITEMS/mcl_beehives/mod.conf new file mode 100644 index 000000000..0a7855bec --- /dev/null +++ b/mods/ITEMS/mcl_beehives/mod.conf @@ -0,0 +1,4 @@ +name = mcl_beehives +author = PrairieWind +description = Adds beehives and bee nests to MineClone 2. +depends = mcl_util, mcl_enchanting diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_bottom.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_bottom.png new file mode 100644 index 000000000..f3ad4a418 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_bottom.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front.png new file mode 100644 index 000000000..023e79d92 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front_honey.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front_honey.png new file mode 100644 index 000000000..d88dd6555 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_front_honey.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_salmon.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_side.png similarity index 54% rename from mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_salmon.png rename to mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_side.png index ce5dcf971..9c0de93d7 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_salmon.png and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_side.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_top.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_top.png new file mode 100644 index 000000000..5f80eb98e Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_bee_nest_top.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_end.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_end.png new file mode 100644 index 000000000..3ee339135 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_end.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front.png new file mode 100644 index 000000000..94e14d9f9 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front_honey.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front_honey.png new file mode 100644 index 000000000..e47a7c776 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_front_honey.png differ diff --git a/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_side.png b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_side.png new file mode 100644 index 000000000..820acb491 Binary files /dev/null and b/mods/ITEMS/mcl_beehives/textures/mcl_beehives_beehive_side.png differ diff --git a/mods/ITEMS/mcl_bells/init.lua b/mods/ITEMS/mcl_bells/init.lua index f1fce85e9..32bdfe3d7 100644 --- a/mods/ITEMS/mcl_bells/init.lua +++ b/mods/ITEMS/mcl_bells/init.lua @@ -9,7 +9,7 @@ function mcl_bells.ring_once(pos) local vv=minetest.get_objects_inside_radius(pos,150) for _,o in pairs(vv) do if o.type == "npc" then - mcl_mobs:gopath(o:get_luaentity(),pos,function() end) + o:get_luaentity():gopath(pos,function() end) end end end diff --git a/mods/ITEMS/mcl_blackstone/init.lua b/mods/ITEMS/mcl_blackstone/init.lua index 3f8e9334f..00b9819f8 100644 --- a/mods/ITEMS/mcl_blackstone/init.lua +++ b/mods/ITEMS/mcl_blackstone/init.lua @@ -25,11 +25,12 @@ minetest.register_node("mcl_blackstone:blackstone_gilded", { drop = { max_items = 1, items = { - {items = {"mcl_core:gold_nugget 2"},rarity = 5}, - {items = {"mcl_core:gold_nugget 3"},rarity = 5}, - {items = {"mcl_core:gold_nugget 4"},rarity = 5}, - {items = {"mcl_core:gold_nugget 5"},rarity = 5}, - {items = {"mcl_blackstone:blackstone_gilded"}, rarity = 8}, + {items = {"mcl_core:gold_nugget 2"},rarity = 40}, + {items = {"mcl_core:gold_nugget 3"},rarity = 40}, + {items = {"mcl_core:gold_nugget 4"},rarity = 40}, + {items = {"mcl_core:gold_nugget 5"},rarity = 40}, + -- 4x 1 in 40 chance adds up to a 10% chance + {items = {"mcl_blackstone:blackstone_gilded"}, rarity = 1}, } }, _mcl_blast_resistance = 2, @@ -46,11 +47,11 @@ minetest.register_node("mcl_blackstone:nether_gold", { drop = { max_items = 1, items = { - {items = {"mcl_core:gold_nugget 2"},rarity = 5}, - {items = {"mcl_core:gold_nugget 3"},rarity = 5}, - {items = {"mcl_core:gold_nugget 4"},rarity = 5}, + {items = {"mcl_core:gold_nugget 6"},rarity = 5}, {items = {"mcl_core:gold_nugget 5"},rarity = 5}, - {items = {"mcl_blackstone:nether_gold"}, rarity = 8}, + {items = {"mcl_core:gold_nugget 4"},rarity = 5}, + {items = {"mcl_core:gold_nugget 3"},rarity = 5}, + {items = {"mcl_core:gold_nugget 2"},rarity = 1}, } }, _mcl_blast_resistance = 3, @@ -195,12 +196,14 @@ mcl_stairs.register_stair_and_slab_simple("blackstone_brick_polished", "mcl_blac mcl_walls.register_wall("mcl_blackstone:wall", S("Blackstone Wall"), "mcl_blackstone:blackstone") --lavacooling + minetest.register_abm({ label = "Lava cooling (basalt)", nodenames = {"group:lava"}, neighbors = {"mcl_core:ice"}, interval = 1, chance = 1, + min_y = mcl_vars.mg_end_min, action = function(pos, node, active_object_count, active_object_count_wider) local water = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, "mcl_core:ice") local lavatype = minetest.registered_nodes[node.name].liquidtype @@ -224,6 +227,7 @@ minetest.register_abm({ neighbors = {"mcl_core:packed_ice"}, interval = 1, chance = 1, + min_y = mcl_vars.mg_end_min, action = function(pos, node, active_object_count, active_object_count_wider) local water = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, "mcl_core:packed_ice") local lavatype = minetest.registered_nodes[node.name].liquidtype @@ -341,6 +345,7 @@ mcl_torches.register_torch({ groups = {dig_immediate = 3, deco_block = 1}, sounds = mcl_sounds.node_sound_wood_defaults(), particles = true, + flame_type = 2, }) minetest.register_craft({ diff --git a/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor.png b/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor.png index 81bdddc07..fc93c82d8 100644 Binary files a/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor.png and b/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor.png differ diff --git a/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor_animated.png b/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor_animated.png index b125743b0..2193d4610 100644 Binary files a/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor_animated.png and b/mods/ITEMS/mcl_blackstone/textures/soul_torch_on_floor_animated.png differ diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index ad4a3f30e..2181d7b98 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -171,27 +171,23 @@ function ARROW_ENTITY.on_step(self, dtime) if self._damage >= 9 and self._in_player == false then minetest.add_particlespawner({ - amount = 1, - time = .001, - minpos = pos, - maxpos = pos, + amount = 20, + time = .2, + minpos = vector.new(0,0,0), + maxpos = vector.new(0,0,0), minvel = vector.new(-0.1,-0.1,-0.1), maxvel = vector.new(0.1,0.1,0.1), minexptime = 0.5, maxexptime = 0.5, minsize = 2, maxsize = 2, + attached = self.object, collisiondetection = false, vertical = false, texture = "mobs_mc_arrow_particle.png", glow = 1, }) end - -- We just check for any hurtable objects nearby. - -- The radius of 3 is fairly liberal, but anything lower than than will cause - -- arrow to hilariously go through mobs often. - -- TODO: Implement an ACTUAL collision detection (engine support needed). - local closest_object local closest_distance diff --git a/mods/ITEMS/mcl_bows/rocket.lua b/mods/ITEMS/mcl_bows/rocket.lua index 6180472c1..e71c0c122 100644 --- a/mods/ITEMS/mcl_bows/rocket.lua +++ b/mods/ITEMS/mcl_bows/rocket.lua @@ -19,6 +19,7 @@ local function dir_to_pitch(dir) end local function damage_explosion(self, damagemulitplier) + if self._harmless then return end local p = self.object:get_pos() if not p then return end mcl_explosions.explode(p, 3, {}) diff --git a/mods/ITEMS/mcl_buckets/fishbuckets.lua b/mods/ITEMS/mcl_buckets/fishbuckets.lua new file mode 100644 index 000000000..9eb966084 --- /dev/null +++ b/mods/ITEMS/mcl_buckets/fishbuckets.lua @@ -0,0 +1,71 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +-- Fish Buckets +local fish_names = { + ["cod"] = "Cod", + ["salmon"] = "Salmon", + ["tropical_fish"] = "Tropical Fish", + ["axolotl"] = "Axolotl", + --["pufferfish"] = "Pufferfish", --FIXME add pufferfish +} + +local fishbucket_prefix = "mcl_buckets:bucket_" + +local function on_place_fish(itemstack, placer, pointed_thing) + + local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pointed_thing) + if new_stack then + return new_stack + end + + local pos = pointed_thing.above or pointed_thing.under + if not pos then return end + local n = minetest.get_node_or_nil(pos) + if n.name and minetest.registered_nodes[n.name].buildable_to or n.name == "mcl_portals:portal" then + local fish = itemstack:get_name():gsub(fishbucket_prefix,"") + if fish_names[fish] then + local o = minetest.add_entity(pos, "mobs_mc:" .. fish) + local props = itemstack:get_meta():get_string("properties") + if props ~= "" then + o:set_properties(minetest.deserialize(props)) + end + local water = "mcl_core:water_source" + if n.name == "mclx_core:river_water_source" then + water = n.name + elseif n.name == "mclx_core:river_water_flowing" then + water = nil + end + if mcl_worlds.pos_to_dimension(pos) == "nether" then + water = nil + minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) + end + if water then + minetest.set_node(pos,{name = water}) + end + if not placer or not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack = ItemStack("mcl_buckets:bucket_empty") + end + end + end + return itemstack +end + +for techname, fishname in pairs(fish_names) do + minetest.register_craftitem(fishbucket_prefix .. techname, { + description = S("Bucket of @1", S(fishname)), + _doc_items_longdesc = S("This bucket is filled with water and @1.", S(fishname)), + _doc_items_usagehelp = S("Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 with a bucket of water.", S(fishname), S(fishname)), + _tt_help = S("Places a water source and a @1.", S(fishname)), + inventory_image = techname .. "_bucket.png", + stack_max = 1, + groups = {bucket = 1, fish_bucket = 1}, + liquids_pointable = false, + on_place = on_place_fish, + on_secondary_use = on_place_fish, + _on_dispense = function(stack, pos, droppos, dropnode, dropdir) + return on_place_fish(stack, nil, {above=droppos}) + end, + }) + + minetest.register_alias("mcl_fishing:bucket_" .. techname, "mcl_buckets:bucket_" .. techname) +end diff --git a/mods/ITEMS/mcl_buckets/init.lua b/mods/ITEMS/mcl_buckets/init.lua index 148df7711..0851c3757 100644 --- a/mods/ITEMS/mcl_buckets/init.lua +++ b/mods/ITEMS/mcl_buckets/init.lua @@ -2,6 +2,7 @@ local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) +local use_select_box = minetest.settings:get_bool("mcl_buckets_use_select_box", false) -- Compatibility with old bucket mod minetest.register_alias("bucket:bucket_empty", "mcl_buckets:bucket_empty") @@ -87,24 +88,6 @@ end local pointable_sources = {} -local function bucket_raycast(user) - local pos = user:get_pos() - pos.y = pos.y + user:get_properties().eye_height - local look_dir = user:get_look_dir() - look_dir = vector.multiply(look_dir, 5) - local pos2 = vector.add(pos, look_dir) - - local ray = raycast(pos, pos2, false, true) - if ray then - for pointed_thing in ray do - if pointed_thing and pointable_sources[get_node(pointed_thing.above).name] then - return {under=pointed_thing.under,above=pointed_thing.above} - end - end - end - return nil -end - local function get_node_place(source_place, place_pos) local node_place if type(source_place) == "function" then @@ -152,71 +135,76 @@ local function get_bucket_drop(itemstack, user, take_bucket) end end -local function on_place_bucket(itemstack, user, pointed_thing, def) - -- Must be pointing to node - if pointed_thing.type ~= "node" then - return - end - -- Call on_rightclick if the pointed node defines it - local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) - if new_stack then - return new_stack - end +local function bucket_get_pointed_thing(user) + local start = user:get_pos() + start.y = start.y + user:get_properties().eye_height + local look_dir = user:get_look_dir() + _end = vector.add(start, vector.multiply(look_dir, 5)) - local undernode = get_node(pointed_thing.under) - local abovenode = get_node(pointed_thing.above) - - if registered_nodes[undernode.name] and registered_nodes[undernode.name].buildable_to or get_item_group(undernode.name, "cauldron") == 1 then - local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.under, user) - if result then - local node_place = get_node_place(def.source_place, pointed_thing.under) - local pns = user:get_player_name() - - -- Check protection - if is_protected(pointed_thing.under, pns) then - record_protection_violation(pointed_thing.under, pns) - return itemstack - end - - -- Place liquid - place_liquid(pointed_thing.under, node_place) - - -- Update doc mod - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end + local ray = raycast(start, _end, false, true) + for pointed_thing in ray do + local name = get_node(pointed_thing.under).name + local def = registered_nodes[name] + if not def or def.drawtype ~= "flowingliquid" then + return pointed_thing end - return get_bucket_drop(itemstack, user, take_bucket) - elseif registered_nodes[abovenode.name] and registered_nodes[abovenode.name].buildable_to or get_item_group(abovenode.name, "cauldron") == 1 then - local result, take_bucket = get_extra_check(def.extra_check, pointed_thing.above, user) - if result then - local node_place = get_node_place(def.source_place, pointed_thing.above) - local pns = user:get_player_name() - - -- Check protection - if is_protected(pointed_thing.above, pns) then - record_protection_violation(pointed_thing.above, pns) - return itemstack - end - - -- Place liquid - place_liquid(pointed_thing.above, node_place) - - -- Update doc mod - if mod_doc and doc.entry_exists("nodes", node_place) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) - end - end - return get_bucket_drop(itemstack, user, take_bucket) - else - return itemstack end end +local function on_place_bucket(itemstack, user, pointed_thing) + if not use_select_box then + pointed_thing = bucket_get_pointed_thing(user) + end + + -- Must be pointing to node + if not pointed_thing or pointed_thing.type ~= "node" then + return + end + + -- Call on_rightclick if the pointed node defines it + local new_stack = mcl_util.call_on_rightclick(itemstack, user, pointed_thing) + if new_stack then + return new_stack + end + + local bucket_def = mcl_buckets.buckets[itemstack:get_name()] + for _, pos in pairs({ pointed_thing.under, pointed_thing.above }) do + local node = get_node(pos) + local node_def = registered_nodes[node.name] + + if node_def and node_def.buildable_to or get_item_group(node.name, "cauldron") == 1 then + local result, take_bucket = get_extra_check(bucket_def.extra_check, pos, user) + if result then + local node_place = get_node_place(bucket_def.source_place, pos) + local player_name = user:get_player_name() + + -- Check protection + if is_protected(pos, player_name) then + record_protection_violation(pos, player_name) + return itemstack + end + + -- Place liquid + place_liquid(pos, node_place) + + -- Update doc mod + if mod_doc and doc.entry_exists("nodes", node_place) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place) + end + end + return get_bucket_drop(itemstack, user, take_bucket) + end + end + return itemstack +end local function on_place_bucket_empty(itemstack, user, pointed_thing) + if not use_select_box then + pointed_thing = bucket_get_pointed_thing(user) + end + -- Must be pointing to node - if pointed_thing.type ~= "node" then + if not pointed_thing or pointed_thing.type ~= "node" then return itemstack end @@ -226,64 +214,59 @@ local function on_place_bucket_empty(itemstack, user, pointed_thing) return new_stack end - local node = get_node(pointed_thing.under) - local nn = node.name - local new_bucket - local liquid_node = bucket_raycast(user) - if liquid_node then - if is_protected(liquid_node.above, user:get_player_name()) then - record_protection_violation(liquid_node.above, user:get_player_name()) + local under = pointed_thing.under + local node_name = get_node(under).name + if pointable_sources[node_name] then + if is_protected(under, user:get_player_name()) then + record_protection_violation(under, user:get_player_name()) end - local liquid_name = get_node(liquid_node.above).name - if liquid_name then - local liquid_def = mcl_buckets.liquids[liquid_name] - if liquid_def then - -- Fill bucket, but not in Creative Mode - -- FIXME: remove this line - --if not is_creative_enabled(user:get_player_name()) then - if not false then - new_bucket = ItemStack({name = liquid_def.bucketname}) - if liquid_def.on_take then - liquid_def.on_take(user) - end + local liquid_def = mcl_buckets.liquids[node_name] + if liquid_def then + -- Fill bucket, but not in Creative Mode + -- FIXME: remove this line + --if not is_creative_enabled(user:get_player_name()) then + if not false then + new_bucket = ItemStack({name = liquid_def.bucketname}) + if liquid_def.on_take then + liquid_def.on_take(user) end - add_node(liquid_node.above, {name="air"}) - sound_take(nn, liquid_node.above) - - if mod_doc and doc.entry_exists("nodes", liquid_name) then - doc.mark_entry_as_revealed(user:get_player_name(), "nodes", liquid_name) - end - if new_bucket then - return give_bucket(new_bucket, itemstack, user) - end - else - minetest.log("error", string.format("[mcl_buckets] Node [%s] has invalid group [_mcl_bucket_pointable]!", liquid_name)) end + add_node(under, {name="air"}) + sound_take(node_name, under) + + if mod_doc and doc.entry_exists("nodes", node_name) then + doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_name) + end + if new_bucket then + return give_bucket(new_bucket, itemstack, user) + end + else + minetest.log("error", string.format("[mcl_buckets] Node [%s] has invalid group [_mcl_bucket_pointable]!", node_name)) end return itemstack else -- FIXME: replace this ugly code by cauldrons API - if nn == "mcl_cauldrons:cauldron_3" then + if node_name == "mcl_cauldrons:cauldron_3" then -- Take water out of full cauldron - set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + set_node(under, {name="mcl_cauldrons:cauldron"}) if not is_creative_enabled(user:get_player_name()) then new_bucket = ItemStack("mcl_buckets:bucket_water") end - sound_take("mcl_core:water_source", pointed_thing.under) - elseif nn == "mcl_cauldrons:cauldron_3r" then + sound_take("mcl_core:water_source", under) + elseif node_name == "mcl_cauldrons:cauldron_3r" then -- Take river water out of full cauldron - set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + set_node(under, {name="mcl_cauldrons:cauldron"}) if not is_creative_enabled(user:get_player_name()) then new_bucket = ItemStack("mcl_buckets:bucket_river_water") end - sound_take("mclx_core:river_water_source", pointed_thing.under) - elseif nn == "mcl_cauldrons:cauldron_3_lava" then - set_node(pointed_thing.under, {name="mcl_cauldrons:cauldron"}) + sound_take("mclx_core:river_water_source", under) + elseif node_name == "mcl_cauldrons:cauldron_3_lava" then + set_node(under, {name="mcl_cauldrons:cauldron"}) if not is_creative_enabled(user:get_player_name()) then new_bucket = ItemStack("mcl_buckets:bucket_lava") end - sound_take("mcl_core:lava_source", pointed_thing.under) + sound_take("mcl_core:lava_source", under) end if new_bucket then return give_bucket(new_bucket, itemstack, user) @@ -292,34 +275,6 @@ local function on_place_bucket_empty(itemstack, user, pointed_thing) return itemstack end -controls.register_on_press(function(player, key) - if key ~= "RMB" then - return - end - - local wielded_item = player:get_wielded_item() - local itemname = wielded_item:get_name() - local def = mcl_buckets.buckets[itemname] - - if itemname == "mcl_buckets:bucket_empty" then - local pointed_thing = mcl_util.get_pointed_thing(player, true) - - if not pointed_thing then - return - end - wielded_item = on_place_bucket_empty(wielded_item, player, pointed_thing) - elseif def then - local pointed_thing = mcl_util.get_pointed_thing(player, false) - - if not pointed_thing then - return - end - wielded_item = on_place_bucket(wielded_item, player, pointed_thing, def) - end - - player:set_wielded_item(wielded_item) -end) - function mcl_buckets.register_liquid(def) for _,source in ipairs(def.source_take) do mcl_buckets.liquids[source] = { @@ -348,6 +303,9 @@ function mcl_buckets.register_liquid(def) inventory_image = def.inventory_image, stack_max = 1, groups = def.groups, + liquids_pointable = use_select_box, + on_place = on_place_bucket, + on_secondary_use = on_place_bucket, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) local buildable = registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal" if not buildable then return stack end @@ -370,6 +328,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { _tt_help = S("Collects liquids"), inventory_image = "bucket.png", stack_max = 16, + liquids_pointable = use_select_box, + on_place = on_place_bucket_empty, + on_secondary_use = on_place_bucket_empty, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Fill empty bucket with liquid or drop bucket if no liquid local collect_liquid = false @@ -397,3 +358,4 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", { }) dofile(modpath.."/register.lua") +dofile(modpath.."/fishbuckets.lua") diff --git a/mods/ITEMS/mcl_buckets/locale/template.txt b/mods/ITEMS/mcl_buckets/locale/template.txt index 86b7b10b5..29aaeace9 100644 --- a/mods/ITEMS/mcl_buckets/locale/template.txt +++ b/mods/ITEMS/mcl_buckets/locale/template.txt @@ -15,10 +15,11 @@ Collects liquids= Places a lava source= Places a water source= Places a river water source= +Axolotl= Cod= Salmon= Tropical Fish= Bucket of @1= This bucket is filled with water and @1.= -Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 fish with a bucket of water.= -Places a water source and a @1 fish.= +Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 with a bucket of water.= +Places a water source and a @1.= diff --git a/mods/ITEMS/mcl_buckets/register.lua b/mods/ITEMS/mcl_buckets/register.lua index b54d0d2bf..365966724 100644 --- a/mods/ITEMS/mcl_buckets/register.lua +++ b/mods/ITEMS/mcl_buckets/register.lua @@ -118,38 +118,3 @@ minetest.register_craft({ burntime = 1000, replacements = {{"mcl_buckets:bucket_lava", "mcl_buckets:bucket_empty"}}, }) - --- Fish Buckets -fish_names = { - { techname = "cod", name = "Cod" }, - { techname = "salmon", name = "Salmon" }, - --{ techname = "pufferfish", name = "Pufferfish" } FIXME: Uncomment when pufferfish mobs are added. - { techname = "tropical_fish", name = "Tropical Fish" } -} - -for _, fish in pairs(fish_names) do - mcl_buckets.register_liquid({ - bucketname = "mcl_buckets:bucket_" .. fish.techname, - source_place = function(pos) - minetest.add_entity(pos, "mobs_mc:" .. fish.techname) - return "mcl_core:water_source" - end, - source_take = {"mobs_mc:" .. fish.techname}, - inventory_image = fish.techname .. "_bucket.png", - name = S("Bucket of @1", S(fish.name)), - longdesc = S("This bucket is filled with water and @1.", S(fish.name)), - usagehelp = S("Place it to empty the bucket and place a @1. Obtain by right clicking on a @2 fish with a bucket of water.", S(fish.name), S(fish.name)), - tt_help = S("Places a water source and a @1 fish.", S(fish.name)), - extra_check = function(pos, placer) - local dim = mcl_worlds.pos_to_dimension(pos) - if dim == "nether" then - minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) - return false, true - else - return true, true - end - end, - }) - minetest.register_alias("mcl_fishing:bucket_" .. fish.techname, "mcl_buckets:bucket_" .. fish.techname) -end - diff --git a/mods/ITEMS/mcl_buckets/textures/axolotl_bucket.png b/mods/ITEMS/mcl_buckets/textures/axolotl_bucket.png new file mode 100644 index 000000000..1923991c1 Binary files /dev/null and b/mods/ITEMS/mcl_buckets/textures/axolotl_bucket.png differ diff --git a/mods/ITEMS/mcl_campfires/init.lua b/mods/ITEMS/mcl_campfires/init.lua index 195612533..083fbce57 100644 --- a/mods/ITEMS/mcl_campfires/init.lua +++ b/mods/ITEMS/mcl_campfires/init.lua @@ -59,18 +59,18 @@ for _, campfire in pairs(campfires) do drawtype = "mesh", mesh = "mcl_campfires_campfire_lit.obj", tiles = {{ - name="mcl_campfires_" .. campfire.techname .. "_fire.png", + name="mcl_campfires_" .. campfire.techname .. "_fire.png", animation={ - type="vertical_frames", - aspect_w=16, - aspect_h=16, + type="vertical_frames", + aspect_w=16, + aspect_h=16, length=2.0 }}, - {name="mcl_campfires_" .. campfire.techname .. "_log_lit.png", + {name="mcl_campfires_" .. campfire.techname .. "_log_lit.png", animation={ - type="vertical_frames", - aspect_w=16, - aspect_h=16, + type="vertical_frames", + aspect_w=16, + aspect_h=16, length=2.0 }} }, diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index 9fe3a81e2..af9b41ea7 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -54,7 +54,6 @@ local entity_animations = { minetest.register_entity("mcl_chests:chest", { initial_properties = { visual = "mesh", - visual_size = {x = 3, y = 3}, pointable = false, physical = false, static_save = false, @@ -140,7 +139,6 @@ minetest.register_entity("mcl_chests:chest", { local function get_entity_pos(pos, dir, double) pos = vector.new(pos) - pos.y = pos.y - 0.49 if double then local add, mul, vec, cross = vector.add, vector.multiply, vector.new, vector.cross pos = add(pos, mul(cross(dir, vec(0, 1, 0)), -0.5)) @@ -363,7 +361,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile _doc_items_usagehelp = usagehelp, _doc_items_hidden = hidden, drawtype = "mesh", - mesh = "mcl_chests_chest.obj", + mesh = "mcl_chests_chest.b3d", tiles = small_textures, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", @@ -401,7 +399,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile type = "fixed", fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375}, }, - tiles = {"mcl_chests_blank.png"}, + tiles = {"blank.png^[resize:16x16"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, _chest_entity_textures = small_textures, _chest_entity_sound = "default_chest", @@ -527,7 +525,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile type = "fixed", fixed = {-0.4375, -0.5, -0.4375, 0.5, 0.375, 0.4375}, }, - tiles = {"mcl_chests_blank.png"}, + tiles = {"blank.png^[resize:16x16"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, _chest_entity_textures = left_textures, _chest_entity_sound = "default_chest", @@ -684,7 +682,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile type = "fixed", fixed = {-0.5, -0.5, -0.4375, 0.4375, 0.375, 0.4375}, }, - tiles = {"mcl_chests_blank.png"}, + tiles = {"blank.png^[resize:16x16"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, groups = {handy=1,axey=1, container=6,not_in_creative_inventory=1, material_wood=1,flammable=-1,double_chest=2}, drop = drop, @@ -842,15 +840,6 @@ register_chest("chest", { small = tiles_chest_normal_small, double = tiles_chest_normal_double, - inv = {"default_chest_top.png", "mcl_chests_chest_bottom.png", - "mcl_chests_chest_right.png", "mcl_chests_chest_left.png", - "mcl_chests_chest_back.png", "default_chest_front.png"}, - --[[left = {"default_chest_top_big.png", "default_chest_top_big.png", - "mcl_chests_chest_right.png", "mcl_chests_chest_left.png", - "default_chest_side_big.png^[transformFX", "default_chest_front_big.png"}, - right = {"default_chest_top_big.png^[transformFX", "default_chest_top_big.png^[transformFX", - "mcl_chests_chest_right.png", "mcl_chests_chest_left.png", - "default_chest_side_big.png", "default_chest_front_big.png^[transformFX"},]]-- }, false ) @@ -858,15 +847,6 @@ register_chest("chest", local traptiles = { small = tiles_chest_trapped_small, double = tiles_chest_trapped_double, - inv = {"mcl_chests_chest_trapped_top.png", "mcl_chests_chest_trapped_bottom.png", - "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png", - "mcl_chests_chest_trapped_back.png", "mcl_chests_chest_trapped_front.png"}, - --[[left = {"mcl_chests_chest_trapped_top_big.png", "mcl_chests_chest_trapped_top_big.png", - "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png", - "mcl_chests_chest_trapped_side_big.png^[transformFX", "mcl_chests_chest_trapped_front_big.png"}, - right = {"mcl_chests_chest_trapped_top_big.png^[transformFX", "mcl_chests_chest_trapped_top_big.png^[transformFX", - "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png", - "mcl_chests_chest_trapped_side_big.png", "mcl_chests_chest_trapped_front_big.png^[transformFX"},]]-- } register_chest("trapped_chest", @@ -992,7 +972,7 @@ minetest.register_node("mcl_chests:ender_chest", { _doc_items_longdesc = S("Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This inventory is the same no matter from which ender chest you access it from. If you put one item into one ender chest, you will find it in all other ender chests. Each player will only see their own items, but not the items of other players."), _doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."), drawtype = "mesh", - mesh = "mcl_chests_chest.obj", + mesh = "mcl_chests_chest.b3d", tiles = tiles_chest_ender_small, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", @@ -1028,17 +1008,14 @@ minetest.register_node("mcl_chests:ender_chest_small", { drawtype = "nodebox", node_box = { type = "fixed", - fixed = {-0.4375, -0.5, -0.4375, 0.5, 0.375, 0.4375}, + fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375}, }, _chest_entity_textures = {"mcl_chests_ender.png"}, _chest_entity_sound = "mcl_chests_enderchest", _chest_entity_mesh = "mcl_chests_chest", _chest_entity_animation_type = "chest", - tiles = {"mcl_chests_blank.png"}, + tiles = {"blank.png^[resize:16x16"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, - --[[{"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png", - "mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png", - "mcl_chests_ender_chest_back.png", "mcl_chests_ender_chest_front.png"},]]-- -- Note: The “container” group is missing here because the ender chest does not -- have an inventory on its own groups = {pickaxey=1, deco_block=1, material_stone=1, chest_entity=1, not_in_creative_inventory=1}, @@ -1188,13 +1165,7 @@ for color, desc in pairs(boxtypes) do tiles = {mob_texture}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, drawtype = "mesh", - mesh = "mcl_chests_shulker.obj", - --[["mcl_chests_"..color.."_shulker_box_top.png", -- top - "[combine:16x16:-32,-28="..mob_texture, -- bottom - "[combine:16x16:0,-36="..mob_texture..":0,-16="..mob_texture, -- side - "[combine:16x16:-32,-36="..mob_texture..":-32,-16="..mob_texture, -- side - "[combine:16x16:-16,-36="..mob_texture..":-16,-16="..mob_texture, -- side - "[combine:16x16:-48,-36="..mob_texture..":-48,-16="..mob_texture, -- side]]-- + mesh = "mcl_chests_shulker.b3d", groups = {handy=1,pickaxey=1, container=3, deco_block=1, dig_by_piston=1, shulker_box=1, old_shulker_box_node=1}, is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), @@ -1250,7 +1221,11 @@ for color, desc in pairs(boxtypes) do _doc_items_longdesc = longdesc, _doc_items_usagehelp = usagehelp, drawtype = "nodebox", - tiles = {"mcl_chests_blank.png"}, + node_box = { + type = "fixed", + fixed = {-0.48, -0.5, -0.48, 0.48, 0.489, 0.48}, + }, + tiles = {"blank.png^[resize:16x16"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, _chest_entity_textures = {mob_texture}, _chest_entity_sound = "mcl_chests_shulker", diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_chest.b3d b/mods/ITEMS/mcl_chests/models/mcl_chests_chest.b3d index e82c7e363..5cc1b8edc 100644 Binary files a/mods/ITEMS/mcl_chests/models/mcl_chests_chest.b3d and b/mods/ITEMS/mcl_chests/models/mcl_chests_chest.b3d differ diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_chest.obj b/mods/ITEMS/mcl_chests/models/mcl_chests_chest.obj deleted file mode 100644 index 36268146f..000000000 --- a/mods/ITEMS/mcl_chests/models/mcl_chests_chest.obj +++ /dev/null @@ -1,91 +0,0 @@ -# Blender v2.76 (sub 0) OBJ File: 'chest.small.facedir.blend' -# www.blender.org -mtllib chest.small.facedir.mtl -o chest_upper_upper -v 0.062513 -0.063134 -0.500468 -v 0.062513 0.186920 -0.500468 -v 0.062514 -0.063134 -0.437955 -v 0.062514 0.186920 -0.437955 -v -0.062514 -0.063134 -0.500468 -v -0.062514 0.186920 -0.500468 -v -0.062514 -0.063134 -0.437955 -v -0.062514 0.186920 -0.437955 -v 0.437907 0.061263 -0.438085 -v 0.437907 0.373830 -0.438085 -v 0.437907 0.061263 0.437729 -v 0.437907 0.373830 0.437729 -v -0.437907 0.061263 -0.438085 -v -0.437907 0.373830 -0.438085 -v -0.437907 0.061263 0.437729 -v -0.437907 0.373830 0.437729 -v 0.437595 -0.500754 -0.437772 -v 0.437595 0.124381 -0.437772 -v 0.437595 -0.500754 0.437417 -v 0.437595 0.124381 0.437417 -v -0.437595 -0.500754 -0.437772 -v -0.437595 0.124381 -0.437772 -v -0.437595 -0.500754 0.437417 -v -0.437595 0.124381 0.437417 -vt 0.015625 0.921875 -vt 0.015625 0.984375 -vt 0.000000 0.984375 -vt 0.000000 0.921875 -vt 0.093750 0.921875 -vt 0.093750 0.984375 -vt 0.062500 0.984375 -vt 0.062500 0.921875 -vt 0.046875 0.984375 -vt 0.046875 0.921875 -vt 0.078125 0.984375 -vt 0.078125 1.000000 -vt 0.046875 1.000000 -vt 0.015625 1.000000 -vt 0.218750 0.703125 -vt 0.218750 0.781250 -vt 0.000000 0.781250 -vt 0.000000 0.703125 -vt 0.875000 0.703125 -vt 0.875000 0.781250 -vt 0.656250 0.781250 -vt 0.656250 0.703125 -vt 0.437500 0.781250 -vt 0.437500 0.703125 -vt 0.656250 1.000000 -vt 0.437500 1.000000 -vt 0.218750 1.000000 -vt 0.218750 0.328125 -vt 0.218750 0.484375 -vt -0.000000 0.484375 -vt -0.000000 0.328125 -vt 0.875000 0.328125 -vt 0.875000 0.484375 -vt 0.656250 0.484375 -vt 0.656250 0.328125 -vt 0.437500 0.484375 -vt 0.437500 0.328125 -vn 1.000000 0.000000 -0.000000 -vn 0.000000 0.000000 1.000000 -vn -1.000000 0.000000 0.000000 -vn 0.000000 0.000000 -1.000000 -vn 0.000000 -1.000000 0.000000 -vn 0.000000 1.000000 0.000000 -usemtl None -s off -f 1/1/1 2/2/1 4/3/1 3/4/1 -f 3/5/2 4/6/2 8/7/2 7/8/2 -f 7/8/3 8/7/3 6/9/3 5/10/3 -f 5/10/4 6/9/4 2/2/4 1/1/4 -f 3/9/5 7/11/5 5/12/5 1/13/5 -f 8/13/6 4/14/6 2/2/6 6/9/6 -f 9/15/1 10/16/1 12/17/1 11/18/1 -f 11/19/2 12/20/2 16/21/2 15/22/2 -f 15/22/3 16/21/3 14/23/3 13/24/3 -f 13/24/4 14/23/4 10/16/4 9/15/4 -f 11/25/5 15/26/5 13/23/5 9/21/5 -f 16/26/6 12/27/6 10/16/6 14/23/6 -f 17/28/1 18/29/1 20/30/1 19/31/1 -f 19/32/2 20/33/2 24/34/2 23/35/2 -f 23/35/3 24/34/3 22/36/3 21/37/3 -f 21/37/4 22/36/4 18/29/4 17/28/4 -f 19/22/5 23/24/5 21/36/5 17/34/5 -f 24/24/6 20/15/6 18/29/6 22/36/6 diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_chest_double.b3d b/mods/ITEMS/mcl_chests/models/mcl_chests_chest_double.b3d index 8d79b8ff7..578b3cb72 100644 Binary files a/mods/ITEMS/mcl_chests/models/mcl_chests_chest_double.b3d and b/mods/ITEMS/mcl_chests/models/mcl_chests_chest_double.b3d differ diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d index 2592f86a0..58508348a 100644 Binary files a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d and b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d differ diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj deleted file mode 100644 index ca12b682e..000000000 --- a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj +++ /dev/null @@ -1,159 +0,0 @@ -# Blender v2.79 (sub 0) OBJ File: 'shulkerbox2.blend' -# www.blender.org -mtllib shulkerbox2.mtl -o low1_Cube.006 -v -0.500000 -0.500001 0.500000 -v -0.500000 0.062499 0.500000 -v -0.500000 -0.500001 -0.500000 -v -0.500000 0.062499 -0.500000 -v 0.500000 -0.500001 0.500000 -v 0.500000 0.062499 0.500000 -v 0.500000 -0.500001 -0.500000 -v 0.500000 0.062499 -0.500000 -vt 0.250000 0.187500 -vt -0.000000 0.187500 -vt -0.000000 0.312500 -vt 0.250000 0.312500 -vt 1.000000 0.187500 -vt 0.750000 0.187500 -vt 0.750000 0.312500 -vt 1.000000 0.312500 -vt 0.500000 0.187500 -vt 0.500000 0.312500 -vt 0.750000 0.562500 -vt 0.750000 0.312500 -vt 0.500000 0.312500 -vt 0.500000 0.562500 -vt 0.500000 0.562500 -vt 0.250000 0.562500 -vn 1.0000 0.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn -1.0000 0.0000 0.0000 -vn 0.0000 0.0000 -1.0000 -vn 0.0000 1.0000 0.0000 -vn 0.0000 -1.0000 0.0000 -usemtl None -s off -f 1/1/1 3/2/1 4/3/1 2/4/1 -f 3/5/2 7/6/2 8/7/2 4/8/2 -f 7/6/3 5/9/3 6/10/3 8/7/3 -f 5/9/4 1/1/4 2/4/4 6/10/4 -f 3/11/5 1/12/5 5/13/5 7/14/5 -f 8/15/6 6/10/6 2/4/6 4/16/6 -o top1_Cube.005 -v -0.500313 -0.220552 0.500313 -v -0.500313 0.530073 0.500313 -v -0.500313 -0.220552 -0.500313 -v -0.500313 0.530073 -0.500313 -v 0.500313 -0.220552 0.500313 -v 0.500313 0.530073 0.500313 -v 0.500313 -0.220552 -0.500313 -v 0.500313 0.530073 -0.500313 -vt 0.250000 0.562500 -vt -0.000000 0.562500 -vt -0.000000 0.750000 -vt 0.250000 0.750000 -vt 1.000000 0.562500 -vt 0.750000 0.562500 -vt 0.750000 0.750000 -vt 1.000000 0.750000 -vt 0.500000 0.562500 -vt 0.500000 0.750000 -vt 0.750000 1.000000 -vt 0.750000 0.750000 -vt 0.500000 0.750000 -vt 0.500000 1.000000 -vt 0.500000 1.000000 -vt 0.250000 1.000000 -vn 1.0000 0.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn -1.0000 0.0000 0.0000 -vn 0.0000 0.0000 -1.0000 -vn 0.0000 1.0000 0.0000 -vn 0.0000 -1.0000 0.0000 -usemtl None -s off -f 9/17/7 11/18/7 12/19/7 10/20/7 -f 11/21/8 15/22/8 16/23/8 12/24/8 -f 15/22/9 13/25/9 14/26/9 16/23/9 -f 13/25/10 9/17/10 10/20/10 14/26/10 -f 11/27/11 9/28/11 13/29/11 15/30/11 -f 16/31/12 14/26/12 10/20/12 12/32/12 -o top2_Cube.002 -v -0.500247 -0.220392 0.500247 -v -0.500247 0.530234 0.500247 -v -0.500247 -0.220392 -0.500378 -v -0.500247 0.530234 -0.500378 -v 0.500378 -0.220392 0.500247 -v 0.500378 0.530234 0.500247 -v 0.500378 -0.220392 -0.500378 -v 0.500378 0.530234 -0.500378 -vt 0.250000 0.562500 -vt 0.250000 0.750000 -vt -0.000000 0.750000 -vt -0.000000 0.562500 -vt 1.000000 0.562500 -vt 1.000000 0.750000 -vt 0.750000 0.750000 -vt 0.750000 0.562500 -vt 0.500000 0.750000 -vt 0.500000 0.562500 -vt 0.750000 1.000000 -vt 0.500000 1.000000 -vt 0.500000 0.750000 -vt 0.750000 0.750000 -vt 0.500000 1.000000 -vt 0.250000 1.000000 -vn -1.0000 0.0000 0.0000 -vn 0.0000 0.0000 -1.0000 -vn 1.0000 0.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn 0.0000 -1.0000 0.0000 -vn 0.0000 1.0000 0.0000 -usemtl None -s off -f 17/33/13 18/34/13 20/35/13 19/36/13 -f 19/37/14 20/38/14 24/39/14 23/40/14 -f 23/40/15 24/39/15 22/41/15 21/42/15 -f 21/42/16 22/41/16 18/34/16 17/33/16 -f 19/43/17 23/44/17 21/45/17 17/46/17 -f 24/47/18 20/48/18 18/34/18 22/41/18 -o low2_Cube.001 -v -0.499935 -0.499936 0.499935 -v -0.499935 0.062565 0.499935 -v -0.499935 -0.499936 -0.500066 -v -0.499935 0.062565 -0.500066 -v 0.500066 -0.499936 0.499935 -v 0.500066 0.062565 0.499935 -v 0.500066 -0.499936 -0.500066 -v 0.500066 0.062565 -0.500066 -vt 0.250000 0.187500 -vt 0.250000 0.312500 -vt -0.000000 0.312500 -vt -0.000000 0.187500 -vt 1.000000 0.187500 -vt 1.000000 0.312500 -vt 0.750000 0.312500 -vt 0.750000 0.187500 -vt 0.500000 0.312500 -vt 0.500000 0.187500 -vt 0.750000 0.562500 -vt 0.500000 0.562500 -vt 0.500000 0.312500 -vt 0.750000 0.312500 -vt 0.500000 0.562500 -vt 0.250000 0.562500 -vn -1.0000 0.0000 0.0000 -vn 0.0000 0.0000 -1.0000 -vn 1.0000 0.0000 0.0000 -vn 0.0000 0.0000 1.0000 -vn 0.0000 -1.0000 0.0000 -vn 0.0000 1.0000 0.0000 -usemtl None -s off -f 25/49/19 26/50/19 28/51/19 27/52/19 -f 27/53/20 28/54/20 32/55/20 31/56/20 -f 31/56/21 32/55/21 30/57/21 29/58/21 -f 29/58/22 30/57/22 26/50/22 25/49/22 -f 27/59/23 31/60/23 29/61/23 25/62/23 -f 32/63/24 28/64/24 26/50/24 30/57/24 diff --git a/mods/ITEMS/mcl_chests/textures/default_chest_front.png b/mods/ITEMS/mcl_chests/textures/default_chest_front.png deleted file mode 100644 index 866a33984..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/default_chest_front.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/default_chest_front_big.png b/mods/ITEMS/mcl_chests/textures/default_chest_front_big.png deleted file mode 100644 index bde286673..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/default_chest_front_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/default_chest_side_big.png b/mods/ITEMS/mcl_chests/textures/default_chest_side_big.png deleted file mode 100644 index deb006807..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/default_chest_side_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/default_chest_top.png b/mods/ITEMS/mcl_chests/textures/default_chest_top.png deleted file mode 100644 index 5c1beb4b5..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/default_chest_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/default_chest_top_big.png b/mods/ITEMS/mcl_chests/textures/default_chest_top_big.png deleted file mode 100644 index de56e2cab..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/default_chest_top_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_black_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_black_shulker_box_top.png deleted file mode 100644 index a8564e42e..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_black_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_blank.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_blank.png deleted file mode 100644 index baee128d4..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_blank.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_blue_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_blue_shulker_box_top.png deleted file mode 100644 index 608887df4..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_blue_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_brown_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_brown_shulker_box_top.png deleted file mode 100644 index 95b6cbdc8..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_brown_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_back.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_back.png deleted file mode 100644 index f347e921a..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_back.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_bottom.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_bottom.png deleted file mode 100644 index cb43e55e2..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_bottom.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_left.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_left.png deleted file mode 100644 index d420aaba0..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_left.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_right.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_right.png deleted file mode 100644 index 4536ada86..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_right.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_back.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_back.png deleted file mode 100644 index f347e921a..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_back.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_bottom.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_bottom.png deleted file mode 100644 index cb43e55e2..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_bottom.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front.png deleted file mode 100644 index 67cc716bd..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front_big.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front_big.png deleted file mode 100644 index b65bfc231..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_front_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_left.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_left.png deleted file mode 100644 index d420aaba0..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_left.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_right.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_right.png deleted file mode 100644 index 4536ada86..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_right.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_side_big.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_side_big.png deleted file mode 100644 index deb006807..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_side_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top.png deleted file mode 100644 index 5c1beb4b5..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top_big.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top_big.png deleted file mode 100644 index de56e2cab..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_chest_trapped_top_big.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_cyan_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_cyan_shulker_box_top.png deleted file mode 100644 index d8fe60f50..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_cyan_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_green_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_green_shulker_box_top.png deleted file mode 100644 index a0d32088b..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_green_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_grey_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_grey_shulker_box_top.png deleted file mode 100644 index 8859361ec..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_dark_grey_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_back.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_back.png deleted file mode 100644 index 7cfbe1d7d..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_back.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_bottom.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_bottom.png deleted file mode 100644 index 03a61a59c..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_bottom.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_front.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_front.png deleted file mode 100644 index bbc68e78b..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_front.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_left.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_left.png deleted file mode 100644 index 1a0ceaef2..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_left.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_right.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_right.png deleted file mode 100644 index f547532f2..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_right.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_top.png deleted file mode 100644 index c109aa826..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_ender_chest_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_green_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_green_shulker_box_top.png deleted file mode 100644 index 513612da9..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_green_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_grey_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_grey_shulker_box_top.png deleted file mode 100644 index e483f6ed7..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_grey_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_lightblue_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_lightblue_shulker_box_top.png deleted file mode 100644 index 9efc68fe0..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_lightblue_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_magenta_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_magenta_shulker_box_top.png deleted file mode 100644 index 9f167d4d9..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_magenta_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_orange_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_orange_shulker_box_top.png deleted file mode 100644 index 166f9c3da..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_orange_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_pink_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_pink_shulker_box_top.png deleted file mode 100644 index a69548c31..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_pink_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_red_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_red_shulker_box_top.png deleted file mode 100644 index 8c458cdd9..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_red_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_violet_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_violet_shulker_box_top.png deleted file mode 100644 index eb461d395..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_violet_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_white_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_white_shulker_box_top.png deleted file mode 100644 index 8c12525bd..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_white_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_yellow_shulker_box_top.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_yellow_shulker_box_top.png deleted file mode 100644 index 5e657412d..000000000 Binary files a/mods/ITEMS/mcl_chests/textures/mcl_chests_yellow_shulker_box_top.png and /dev/null differ diff --git a/mods/ITEMS/mcl_cocoas/init.lua b/mods/ITEMS/mcl_cocoas/init.lua index 60ea9e573..cc3b88705 100644 --- a/mods/ITEMS/mcl_cocoas/init.lua +++ b/mods/ITEMS/mcl_cocoas/init.lua @@ -66,32 +66,19 @@ end -- Cocoa definition -- 1st stage - ---[[ TODO: Use a mesh for cocoas for perfect texture compability. ]] local crop_def = { description = S("Premature Cocoa Pod"), _doc_items_create_entry = true, _doc_items_longdesc = S("Cocoa pods grow on the side of jungle trees in 3 stages."), - drawtype = "nodebox", - tiles = { - "[combine:16x16:6,1=mcl_cocoas_cocoa_stage_0.png", "[combine:16x16:6,11=mcl_cocoas_cocoa_stage_0.png", - "mcl_cocoas_cocoa_stage_0.png", "mcl_cocoas_cocoa_stage_0.png^[transformFX", - "[combine:16x16:-5,0=mcl_cocoas_cocoa_stage_0.png", "[combine:16x16:-5,0=mcl_cocoas_cocoa_stage_0.png", - }, + drawtype = "mesh", + mesh = "mcl_cocoas_cocoa_stage_0.obj", + tiles = {"mcl_cocoas_cocoa_stage_0.png"}, use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, paramtype = "light", sunlight_propagates = true, paramtype2 = "facedir", walkable = true, drop = "mcl_dye:brown", - node_box = { - type = "fixed", - fixed = { - {-0.125, -0.0625, 0.1875, 0.125, 0.25, 0.4375}, -- Pod - -- FIXME: This has a thickness of 0. Is this OK in Minetest? - {0, 0.25, 0.25, 0, 0.5, 0.5}, -- Stem - }, - }, collision_box = { type = "fixed", fixed = { @@ -119,18 +106,8 @@ minetest.register_node("mcl_cocoas:cocoa_1", table.copy(crop_def)) crop_def.description = S("Medium Cocoa Pod") crop_def._doc_items_create_entry = false crop_def.groups.cocoa = 2 -crop_def.tiles = { - "[combine:16x16:5,1=mcl_cocoas_cocoa_stage_1.png", "[combine:16x16:5,9=mcl_cocoas_cocoa_stage_1.png", - "mcl_cocoas_cocoa_stage_1.png", "mcl_cocoas_cocoa_stage_1.png^[transformFX", - "[combine:16x16:-4,0=mcl_cocoas_cocoa_stage_1.png", "[combine:16x16:-4,0=mcl_cocoas_cocoa_stage_1.png", -} -crop_def.node_box = { - type = "fixed", - fixed = { - {-0.1875, -0.1875, 0.0625, 0.1875, 0.25, 0.4375}, -- Pod - {0, 0.25, 0.25, 0, 0.5, 0.5}, -- Stem - }, -} +crop_def.mesh = "mcl_cocoas_cocoa_stage_1.obj" +crop_def.tiles = {"mcl_cocoas_cocoa_stage_1.png"} crop_def.collision_box = { type = "fixed", fixed = { @@ -151,20 +128,8 @@ crop_def.description = S("Mature Cocoa Pod") crop_def._doc_items_longdesc = S("A mature cocoa pod grew on a jungle tree to its full size and it is ready to be harvested for cocoa beans. It won't grow any further.") crop_def._doc_items_create_entry = true crop_def.groups.cocoa = 3 -crop_def.tiles = { - -- The following 2 textures were derived from the original because the size of the top/bottom is slightly different :-( - -- TODO: Find a way to *only* use the base texture - "mcl_cocoas_cocoa_top_stage_2.png", "mcl_cocoas_cocoa_top_stage_2.png^[transformFY", - "mcl_cocoas_cocoa_stage_2.png", "mcl_cocoas_cocoa_stage_2.png^[transformFX", - "[combine:16x16:-3,0=mcl_cocoas_cocoa_stage_2.png", "[combine:16x16:-3,0=mcl_cocoas_cocoa_stage_2.png", -} -crop_def.node_box = { - type = "fixed", - fixed = { - {-0.25, -0.3125, -0.0625, 0.25, 0.25, 0.4375}, -- Pod - {0, 0.25, 0.25, 0, 0.5, 0.5}, -- Stem - }, -} +crop_def.mesh = "mcl_cocoas_cocoa_stage_2.obj" +crop_def.tiles = {"mcl_cocoas_cocoa_stage_2.png"} crop_def.collision_box = { type = "fixed", fixed = { @@ -197,4 +162,3 @@ minetest.register_abm({ if minetest.get_modpath("doc") then doc.add_entry_alias("nodes", "mcl_cocoas:cocoa_1", "nodes", "mcl_cocoas:cocoa_2") end - diff --git a/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_0.obj b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_0.obj new file mode 100644 index 000000000..35dbb2d00 --- /dev/null +++ b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_0.obj @@ -0,0 +1,95 @@ +# Made in Blockbench 4.5.1 +mtllib Cocoa Pod 0.mtl + +o cube +v 0.125 0.25 0.4375 +v 0.125 0.25 0.1875 +v 0.125 -0.0625 0.4375 +v 0.125 -0.0625 0.1875 +v -0.125 0.25 0.1875 +v -0.125 0.25 0.4375 +v -0.125 -0.0625 0.1875 +v -0.125 -0.0625 0.4375 +vt 0.6875 0.75 +vt 0.9375 0.75 +vt 0.9375 0.4375 +vt 0.6875 0.4375 +vt 0.6875 0.75 +vt 0.9375 0.75 +vt 0.9375 0.4375 +vt 0.6875 0.4375 +vt 0.6875 0.75 +vt 0.9375 0.75 +vt 0.9375 0.4375 +vt 0.6875 0.4375 +vt 0.6875 0.75 +vt 0.9375 0.75 +vt 0.9375 0.4375 +vt 0.6875 0.4375 +vt 0 1 +vt 0.25 1 +vt 0.25 0.75 +vt 0 0.75 +vt 0 1 +vt 0.25 1 +vt 0.25 0.75 +vt 0 0.75 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_a7cd0525-4079-c203-6c53-7d43da5fa1e5 +f 4/4/1 7/3/1 5/2/1 2/1/1 +f 3/8/2 4/7/2 2/6/2 1/5/2 +f 8/12/3 3/11/3 1/10/3 6/9/3 +f 7/16/4 8/15/4 6/14/4 5/13/4 +f 6/20/5 1/19/5 2/18/5 5/17/5 +f 7/24/6 4/23/6 3/22/6 8/21/6 +o cube +v 0 0.5 0.5 +v 0 0.5 0.25 +v 0 0.25 0.5 +v 0 0.25 0.25 +v 0 0.5 0.25 +v 0 0.5 0.5 +v 0 0.25 0.25 +v 0 0.25 0.5 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0.75 1 +vt 1 1 +vt 1 0.75 +vt 0.75 0.75 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_a7cd0525-4079-c203-6c53-7d43da5fa1e5 +f 12/28/7 15/27/7 13/26/7 10/25/7 +f 11/32/8 12/31/8 10/30/8 9/29/8 +f 16/36/9 11/35/9 9/34/9 14/33/9 +f 15/40/10 16/39/10 14/38/10 13/37/10 +f 14/44/11 9/43/11 10/42/11 13/41/11 +f 15/48/12 12/47/12 11/46/12 16/45/12 \ No newline at end of file diff --git a/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_1.obj b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_1.obj new file mode 100644 index 000000000..2a5277856 --- /dev/null +++ b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_1.obj @@ -0,0 +1,95 @@ +# Made in Blockbench 4.5.1 +mtllib Cocoa Pod 1.mtl + +o cube +v 0.1875 0.25 0.4375 +v 0.1875 0.25 0.0625 +v 0.1875 -0.1875 0.4375 +v 0.1875 -0.1875 0.0625 +v -0.1875 0.25 0.0625 +v -0.1875 0.25 0.4375 +v -0.1875 -0.1875 0.0625 +v -0.1875 -0.1875 0.4375 +vt 0.5625 0.75 +vt 0.9375 0.75 +vt 0.9375 0.3125 +vt 0.5625 0.3125 +vt 0.5625 0.75 +vt 0.9375 0.75 +vt 0.9375 0.3125 +vt 0.5625 0.3125 +vt 0.5625 0.75 +vt 0.9375 0.75 +vt 0.9375 0.3125 +vt 0.5625 0.3125 +vt 0.5625 0.75 +vt 0.9375 0.75 +vt 0.9375 0.3125 +vt 0.5625 0.3125 +vt 0 1 +vt 0.375 1 +vt 0.375 0.625 +vt 0 0.625 +vt 0 1 +vt 0.375 1 +vt 0.375 0.625 +vt 0 0.625 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_3316e529-b95a-149b-2db3-3eee58b06c25 +f 4/4/1 7/3/1 5/2/1 2/1/1 +f 3/8/2 4/7/2 2/6/2 1/5/2 +f 8/12/3 3/11/3 1/10/3 6/9/3 +f 7/16/4 8/15/4 6/14/4 5/13/4 +f 6/20/5 1/19/5 2/18/5 5/17/5 +f 7/24/6 4/23/6 3/22/6 8/21/6 +o cube +v 0 0.5 0.5 +v 0 0.5 0.25 +v 0 0.25 0.5 +v 0 0.25 0.25 +v 0 0.5 0.25 +v 0 0.5 0.5 +v 0 0.25 0.25 +v 0 0.25 0.5 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0.75 1 +vt 1 1 +vt 1 0.75 +vt 0.75 0.75 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_3316e529-b95a-149b-2db3-3eee58b06c25 +f 12/28/7 15/27/7 13/26/7 10/25/7 +f 11/32/8 12/31/8 10/30/8 9/29/8 +f 16/36/9 11/35/9 9/34/9 14/33/9 +f 15/40/10 16/39/10 14/38/10 13/37/10 +f 14/44/11 9/43/11 10/42/11 13/41/11 +f 15/48/12 12/47/12 11/46/12 16/45/12 \ No newline at end of file diff --git a/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_2.obj b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_2.obj new file mode 100644 index 000000000..8dfd20af1 --- /dev/null +++ b/mods/ITEMS/mcl_cocoas/models/mcl_cocoas_cocoa_stage_2.obj @@ -0,0 +1,95 @@ +# Made in Blockbench 4.5.1 +mtllib Cocoa Pod 2 Fixed.mtl + +o cube +v 0.25 0.25 0.4375 +v 0.25 0.25 -0.0625 +v 0.25 -0.3125 0.4375 +v 0.25 -0.3125 -0.0625 +v -0.25 0.25 -0.0625 +v -0.25 0.25 0.4375 +v -0.25 -0.3125 -0.0625 +v -0.25 -0.3125 0.4375 +vt 0.5 0.75 +vt 1 0.75 +vt 1 0.1875 +vt 0.5 0.1875 +vt 0.5 0.75 +vt 1 0.75 +vt 1 0.1875 +vt 0.5 0.1875 +vt 0.5 0.75 +vt 1 0.75 +vt 1 0.1875 +vt 0.5 0.1875 +vt 0.5 0.75 +vt 1 0.75 +vt 1 0.1875 +vt 0.5 0.1875 +vt 0 1 +vt 0.5 1 +vt 0.5 0.5 +vt 0 0.5 +vt 0 1 +vt 0.5 1 +vt 0.5 0.5 +vt 0 0.5 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_9809ffe0-030e-1955-c510-8df6b242b4e2 +f 4/4/1 7/3/1 5/2/1 2/1/1 +f 3/8/2 4/7/2 2/6/2 1/5/2 +f 8/12/3 3/11/3 1/10/3 6/9/3 +f 7/16/4 8/15/4 6/14/4 5/13/4 +f 6/20/5 1/19/5 2/18/5 5/17/5 +f 7/24/6 4/23/6 3/22/6 8/21/6 +o cube +v 0 0.5 0.5 +v 0 0.5 0.25 +v 0 0.25 0.5 +v 0 0.25 0.25 +v 0 0.5 0.25 +v 0 0.5 0.5 +v 0 0.25 0.25 +v 0 0.25 0.5 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0.75 1 +vt 1 1 +vt 1 0.75 +vt 0.75 0.75 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vt 0 0.25 +vt 0 0.25 +vt 0 0 +vt 0 0 +vn 0 0 -1 +vn 1 0 0 +vn 0 0 1 +vn -1 0 0 +vn 0 1 0 +vn 0 -1 0 +usemtl m_9809ffe0-030e-1955-c510-8df6b242b4e2 +f 12/28/7 15/27/7 13/26/7 10/25/7 +f 11/32/8 12/31/8 10/30/8 9/29/8 +f 16/36/9 11/35/9 9/34/9 14/33/9 +f 15/40/10 16/39/10 14/38/10 13/37/10 +f 14/44/11 9/43/11 10/42/11 13/41/11 +f 15/48/12 12/47/12 11/46/12 16/45/12 \ No newline at end of file diff --git a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_0.png b/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_0.png index de58245f4..37510cb52 100644 Binary files a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_0.png and b/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_0.png differ diff --git a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_2.png b/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_2.png index 47bc159b7..c5f2c17fc 100644 Binary files a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_2.png and b/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_stage_2.png differ diff --git a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_top_stage_2.png b/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_top_stage_2.png deleted file mode 100644 index 4e12f623b..000000000 Binary files a/mods/ITEMS/mcl_cocoas/textures/mcl_cocoas_cocoa_top_stage_2.png and /dev/null differ diff --git a/mods/ITEMS/mcl_compass/init.lua b/mods/ITEMS/mcl_compass/init.lua index 9ec1ba074..2905c0b3b 100644 --- a/mods/ITEMS/mcl_compass/init.lua +++ b/mods/ITEMS/mcl_compass/init.lua @@ -16,6 +16,13 @@ local compass_types = { tt = S("Points to a lodestone"), longdesc = S("Lodestone compasses resemble regular compasses, but they point to a specific lodestone."), usagehelp = S("A Lodestone compass can be made from an ordinary compass by using it on a lodestone. After becoming a lodestone compass, it always points to its linked lodestone, provided that they are in the same dimension. If not in the same dimension, the lodestone compass spins randomly, similarly to a regular compass when outside the overworld. A lodestone compass can be relinked with another lodestone."), + }, + { + name = "compass_recovery", + desc = S("Recovery Compass"), + tt = S("Points to your last death location"), + longdesc = S("Recovery Compasses are compasses that point to your last death location"), + usagehelp = S("Recovery Compasses always point to the location of your last death, in case you haven't died yet, it will just randomly spin around"), } } @@ -182,7 +189,7 @@ minetest.register_globalstep(function(dtime) inv = player:get_inventory() for j, stack in pairs(inv:get_list("main")) do compass_nr = get_item_group(stack:get_name(), "compass") - if compass_nr ~= 0 then + if compass_nr ~= 0 and not string_find(stack:get_name(), "_recovery") then -- check if current compass image still matches true orientation compass_frame = get_compass_frame(pos, dir, stack) if compass_nr - 1 ~= compass_frame then @@ -195,6 +202,22 @@ minetest.register_globalstep(function(dtime) end inv:set_stack("main", j, stack) end + elseif compass_nr ~= 0 then + local meta = player:get_meta() + local posstring = meta:get_string("mcl_compass:recovery_pos") + if not posstring or posstring == "" then + stack:set_name("mcl_compass:"..random_frame .. "_recovery") + else + local targetpos = minetest.string_to_pos(posstring) + local _, target_dim = y_to_layer(targetpos.y) + local _, p_dim = y_to_layer(pos.y) + if p_dim ~= target_dim then + stack:set_name("mcl_compass:"..random_frame.."_recovery") + else + stack:set_name("mcl_compass:"..get_compass_angle(pos,targetpos,dir).."_recovery") + end + end + inv:set_stack("main",j,stack) end end end @@ -213,6 +236,9 @@ for _, item in pairs(compass_types) do elseif item.name == "compass_lodestone" then name_fmt = "mcl_compass:%d_lodestone" img_fmt = "mcl_compass_compass_%02d.png^[colorize:purple:50" + elseif item.name == "compass_recovery" then + name_fmt = "mcl_compass:%d_recovery" + img_fmt = "mcl_compass_recovery_compass_%02d.png" end for i = 0, compass_frames - 1 do local itemstring = string.format(name_fmt, i) @@ -251,6 +277,16 @@ minetest.register_craft({ } }) +minetest.register_craft({ --TODO: update once echo shards are a thing + output = "mcl_compass:" .. random_frame .. "_recovery", + recipe = { + {"","mcl_nether:netherite_ingot",""}, + {"mcl_core:diamondblock","mcl_compass:" .. stereotype_frame ,"mcl_core:diamondblock"}, + {"mcl_core:diamondblock","mcl_core:diamondblock","mcl_core:diamondblock"} + + } +}) + minetest.register_alias("mcl_compass:compass", "mcl_compass:" .. stereotype_frame) @@ -289,3 +325,9 @@ minetest.register_craft({ {"mcl_core:stonebrickcarved", "mcl_core:stonebrickcarved", "mcl_core:stonebrickcarved"} } }) + +--set recovery meta +minetest.register_on_dieplayer(function(player) + local meta = player:get_meta(); + meta:set_string("mcl_compass:recovery_pos",minetest.pos_to_string(player:get_pos())) +end) \ No newline at end of file diff --git a/mods/ITEMS/mcl_compass/locale/mcl_compass.de.tr b/mods/ITEMS/mcl_compass/locale/mcl_compass.de.tr index 9e0366508..9ae821e2b 100644 --- a/mods/ITEMS/mcl_compass/locale/mcl_compass.de.tr +++ b/mods/ITEMS/mcl_compass/locale/mcl_compass.de.tr @@ -7,3 +7,7 @@ Lodestone Compass=Leitstein Kompass Points to a lodestone=Zeigt zu einem Leitstein Lodestone compasses resemble regular compasses, but they point to a specific lodestone.=Leitstein Kompasse ähneln normalen Kompassen, aber sie zeigen zu einen spezifischen Leitstein. A Lodestone compass can be made from an ordinary compass by using it on a lodestone. After becoming a lodestone compass, it always points to its linked lodestone, provided that they are in the same dimension. If not in the same dimension, the lodestone compass spins randomly, similarly to a regular compass when outside the overworld. A lodestone compass can be relinked with another lodestone.=Ein Leitstein Kompass kann mit einem normalen Kompass erstellt werden indem man ihn auf einem Leitstein benutzt. Nachdem er ein Leitstein Kompass geworden ist, wird er immer zu seinem Leitstein zeigen, sofern sie in der selben Dimension sind. Wenn sie nicht in der selben Dimension sind, dreht sich der Leitstein Kompass zufällig, wie ein normaler Kompass außerhalb der Oberwelt. Ein Leitstein Kompass kann mit einem anderem Leitstein verknüpft werden. +Recovery Compass=Wiederherstellungskompass +Points to your last death location=Zeigt zu dem Ort, an dem Sie zuletzt verendet sind +Recovery Compasses are compasses that point to your last death location=Wiederhelstellungskompasse sind Kompasse, die zu dem Ort zeigen, an dem Sie zuletzt gestorben sind +Recovery Compasses always point to the location of your last death, in case you haven't died yet, it will just randomly spin around=Wiederherstellungskompasse zeigen immer zu dem Ort Ihres letzten Todes, falls Sie noch nicht gestorben sind drehen sie sich zufällig diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_00.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_00.png new file mode 100644 index 000000000..c72810180 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_00.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_01.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_01.png new file mode 100644 index 000000000..e5a5d82b7 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_01.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_02.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_02.png new file mode 100644 index 000000000..6488b7e3a Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_02.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_03.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_03.png new file mode 100644 index 000000000..4696c8715 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_03.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_04.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_04.png new file mode 100644 index 000000000..594092651 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_04.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_05.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_05.png new file mode 100644 index 000000000..9d0963cfb Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_05.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_06.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_06.png new file mode 100644 index 000000000..a2f675fac Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_06.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_07.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_07.png new file mode 100644 index 000000000..1356e696a Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_07.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_08.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_08.png new file mode 100644 index 000000000..8690c1b15 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_08.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_09.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_09.png new file mode 100644 index 000000000..d13c518e7 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_09.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_10.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_10.png new file mode 100644 index 000000000..48ed5bcaa Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_10.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_11.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_11.png new file mode 100644 index 000000000..edbcfdb87 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_11.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_12.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_12.png new file mode 100644 index 000000000..7d24d84f3 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_12.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_13.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_13.png new file mode 100644 index 000000000..eee649a78 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_13.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_14.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_14.png new file mode 100644 index 000000000..f584f347d Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_14.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_15.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_15.png new file mode 100644 index 000000000..ab5c6ad8c Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_15.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_16.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_16.png new file mode 100644 index 000000000..bb2cf0049 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_16.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_17.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_17.png new file mode 100644 index 000000000..a06e85185 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_17.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_18.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_18.png new file mode 100644 index 000000000..441d58488 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_18.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_19.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_19.png new file mode 100644 index 000000000..98f88ed01 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_19.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_20.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_20.png new file mode 100644 index 000000000..d46801d27 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_20.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_21.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_21.png new file mode 100644 index 000000000..cea8ade47 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_21.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_22.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_22.png new file mode 100644 index 000000000..b6e55140c Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_22.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_23.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_23.png new file mode 100644 index 000000000..0463fc704 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_23.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_24.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_24.png new file mode 100644 index 000000000..210858af1 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_24.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_25.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_25.png new file mode 100644 index 000000000..6db230bb0 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_25.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_26.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_26.png new file mode 100644 index 000000000..6d86189a7 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_26.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_27.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_27.png new file mode 100644 index 000000000..90cceda72 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_27.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_28.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_28.png new file mode 100644 index 000000000..c325929cf Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_28.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_29.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_29.png new file mode 100644 index 000000000..86bec378a Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_29.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_30.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_30.png new file mode 100644 index 000000000..5e59db873 Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_30.png differ diff --git a/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_31.png b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_31.png new file mode 100644 index 000000000..ec95a2bdb Binary files /dev/null and b/mods/ITEMS/mcl_compass/textures/mcl_compass_recovery_compass_31.png differ diff --git a/mods/ITEMS/mcl_copper/crafting.lua b/mods/ITEMS/mcl_copper/crafting.lua index 7b1e183c7..ce280fcdf 100644 --- a/mods/ITEMS/mcl_copper/crafting.lua +++ b/mods/ITEMS/mcl_copper/crafting.lua @@ -47,6 +47,17 @@ minetest.register_craft({ }, }) +local waxable_blocks = { "block", "block_cut", "block_exposed", "block_exposed_cut", "block_weathered", "block_weathered_cut", "block_oxidized", "block_oxidized_cut" } + +for _, w in ipairs(waxable_blocks) do + minetest.register_craft({ + output = "mcl_copper:waxed_"..w, + recipe = { + { "mcl_copper:"..w, "mcl_honey:honeycomb" }, + }, + }) +end + minetest.register_craft({ output = "mcl_copper:copper_ingot 4", recipe = { @@ -73,4 +84,11 @@ minetest.register_craft({ output = "mcl_copper:copper_ingot", recipe = "mcl_copper:stone_with_copper", cooktime = 10, -}) \ No newline at end of file +}) + +minetest.register_craft({ + type = "cooking", + output = "mcl_copper:block", + recipe = "mcl_copper:block_raw", + cooktime = 90, +}) diff --git a/mods/ITEMS/mcl_copper/functions.lua b/mods/ITEMS/mcl_copper/functions.lua index b6e0cb7e2..81dfdb69d 100644 --- a/mods/ITEMS/mcl_copper/functions.lua +++ b/mods/ITEMS/mcl_copper/functions.lua @@ -12,6 +12,34 @@ local function register_oxidation_abm(abm_name, node_name, oxidized_variant) }) end +function waxing_copper_block(pos, node, player, itemstack, convert_to) + if itemstack:get_name() == "mcl_honey:honeycomb" then + node.name = convert_to + minetest.set_node(pos, node) + awards.unlock(player:get_player_name(), "mcl:wax_on") + if not minetest.is_creative_enabled(player:get_player_name()) then + itemstack:take_item() + end + else + return true + end +end + +function scraping_copper_block(pos, node, player, itemstack, convert_to) + if itemstack:get_name():find("axe") then + node.name = convert_to + minetest.set_node(pos, node) + awards.unlock(player:get_player_name(), "mcl:wax_off") + if not minetest.is_creative_enabled(player:get_player_name()) then + local tool = itemstack:get_name() + local wear = mcl_autogroup.get_wear(tool, "axey") + itemstack:add_wear(wear) + end + else + return true + end +end + --[[ local stairs = { {"stair", "exposed", "_inner", "cut_inner"}, diff --git a/mods/ITEMS/mcl_copper/init.lua b/mods/ITEMS/mcl_copper/init.lua index ea15e5827..a99d03f2c 100644 --- a/mods/ITEMS/mcl_copper/init.lua +++ b/mods/ITEMS/mcl_copper/init.lua @@ -1,6 +1,6 @@ local path = minetest.get_modpath("mcl_copper") +dofile(path .. "/functions.lua") dofile(path .. "/nodes.lua") dofile(path .. "/items.lua") dofile(path .. "/crafting.lua") -dofile(path .. "/functions.lua") \ No newline at end of file diff --git a/mods/ITEMS/mcl_copper/items.lua b/mods/ITEMS/mcl_copper/items.lua index 450ec8cb3..694e693dc 100644 --- a/mods/ITEMS/mcl_copper/items.lua +++ b/mods/ITEMS/mcl_copper/items.lua @@ -11,5 +11,5 @@ minetest.register_craftitem("mcl_copper:raw_copper", { description = S("Raw Copper"), _doc_items_longdesc = S("Raw Copper. Mine a Copper Ore to get it."), inventory_image = "mcl_copper_raw.png", - groups = { craftitem = 1 }, + groups = { craftitem = 1, blast_furnace_smeltable = 1 }, }) \ No newline at end of file diff --git a/mods/ITEMS/mcl_copper/locale/template.txt b/mods/ITEMS/mcl_copper/locale/template.txt index 050c099ee..7022780ff 100644 --- a/mods/ITEMS/mcl_copper/locale/template.txt +++ b/mods/ITEMS/mcl_copper/locale/template.txt @@ -2,36 +2,56 @@ A block of copper is mostly a decorative block.= A block used for compact raw copper storage.= Block of Copper= +Waxed Block of Copper= Block of Raw Copper= Copper Ingot= Copper Ore= Cut copper is a decorative block.= Cut Copper= +Waxed Cut Copper= Double Slab of Cut Copper= Double Slab of Exposed Cut Copper= Double Slab of Oxidized Cut Copper= Double Slab of Weathered Cut Copper= +Waxed Double Slab of Cut Copper= +Waxed Double Slab of Exposed Cut Copper= +Waxed Double Slab of Oxidized Cut Copper= +Waxed Double Slab of Weathered Cut Copper= Exposed copper is a decorative block.= Exposed Copper= +Waxed Exposed Copper= Exposed cut copper is a decorative block.= Exposed Cut Copper= +Waxed Exposed Cut Copper= Molten Raw Copper. It is used to craft blocks.= Oxidized copper is a decorative block.= Oxidized Copper= +Waxed Oxidized Copper= Oxidized cut copper is a decorative block.= Oxidized Cut Copper= +Waxed Oxidized Cut Copper= Raw Copper. Mine a Copper Ore to get it.= Raw Copper= Slab of Cut Copper= Slab of Exposed Cut Copper= Slab of Oxidized Cut Copper= Slab of Weathered Cut Copper= +Waxed Slab of Cut Copper= +Waxed Slab of Exposed Cut Copper= +Waxed Slab of Oxidized Cut Copper= +Waxed Slab of Weathered Cut Copper= Some copper contained in stone, it is pretty common and can be found below sea level.= Stairs of Cut Copper= Stairs of Exposed Cut Copper= Stairs of Oxidized Cut Copper= Stairs of Weathered Cut Copper= +Waxed Stairs of Cut Copper= +Waxed Stairs of Exposed Cut Copper= +Waxed Stairs of Oxidized Cut Copper= +Waxed Stairs of Weathered Cut Copper= Weathered copper is a decorative block.= Weathered Copper= +Waxed Weathered Copper= Weathered cut copper is a decorative block.= Weathered Cut Copper= +Waxed Weathered Cut Copper= diff --git a/mods/ITEMS/mcl_copper/nodes.lua b/mods/ITEMS/mcl_copper/nodes.lua index 22c1bf807..6c498f9f6 100644 --- a/mods/ITEMS/mcl_copper/nodes.lua +++ b/mods/ITEMS/mcl_copper/nodes.lua @@ -20,7 +20,7 @@ minetest.register_node("mcl_copper:block_raw", { _doc_items_longdesc = S("A block used for compact raw copper storage."), tiles = {"mcl_copper_block_raw.png"}, is_ground_content = false, - groups = {pickaxey = 2, building_block = 1}, + groups = {pickaxey = 2, building_block = 1, blast_furnace_smeltable = 1 }, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, @@ -35,6 +35,19 @@ minetest.register_node("mcl_copper:block", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 3, + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block") end, +}) + +minetest.register_node("mcl_copper:waxed_block", { + description = S("Waxed Block of Copper"), + _doc_items_longdesc = S("A block of copper is mostly a decorative block."), + tiles = {"mcl_copper_block.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 3, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block") end, }) minetest.register_node("mcl_copper:block_exposed", { @@ -47,18 +60,19 @@ minetest.register_node("mcl_copper:block_exposed", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_anti_oxidation_varient = "mcl_copper:block", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_exposed") end, }) -minetest.register_node("mcl_copper:block_oxidized", { - description = S("Oxidized Copper"), - _doc_items_longdesc = S("Oxidized copper is a decorative block."), - tiles = {"mcl_copper_oxidized.png"}, +minetest.register_node("mcl_copper:waxed_block_exposed", { + description = S("Waxed Exposed Copper"), + _doc_items_longdesc = S("Exposed copper is a decorative block."), + tiles = {"mcl_copper_exposed.png"}, is_ground_content = false, groups = {pickaxey = 2, building_block = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_anti_oxidation_varient = "mcl_copper:block_weathered", + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block") end, }) minetest.register_node("mcl_copper:block_weathered", { @@ -71,6 +85,44 @@ minetest.register_node("mcl_copper:block_weathered", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_anti_oxidation_varient = "mcl_copper:block_exposed", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_weathered") end, +}) + +minetest.register_node("mcl_copper:waxed_block_weathered", { + description = S("Waxed Weathered Copper"), + _doc_items_longdesc = S("Weathered copper is a decorative block."), + tiles = {"mcl_copper_weathered.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_exposed") end, +}) + +minetest.register_node("mcl_copper:block_oxidized", { + description = S("Oxidized Copper"), + _doc_items_longdesc = S("Oxidized copper is a decorative block."), + tiles = {"mcl_copper_oxidized.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + _mcl_anti_oxidation_varient = "mcl_copper:block_weathered", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_oxidized") end, +}) + +minetest.register_node("mcl_copper:waxed_block_oxidized", { + description = S("Waxed Oxidized Copper"), + _doc_items_longdesc = S("Oxidized copper is a decorative block."), + tiles = {"mcl_copper_oxidized.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_weathered") end, }) minetest.register_node("mcl_copper:block_cut", { @@ -82,6 +134,19 @@ minetest.register_node("mcl_copper:block_cut", { sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_cut") end, +}) + +minetest.register_node("mcl_copper:waxed_block_cut", { + description = S("Waxed Cut Copper"), + _doc_items_longdesc = S("Cut copper is a decorative block."), + tiles = {"mcl_copper_block_cut.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_cut") end, }) minetest.register_node("mcl_copper:block_exposed_cut", { @@ -94,18 +159,19 @@ minetest.register_node("mcl_copper:block_exposed_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_anti_oxidation_varient = "mcl_copper:block_cut", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_exposed_cut") end, }) -minetest.register_node("mcl_copper:block_oxidized_cut", { - description = S("Oxidized Cut Copper"), - _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), - tiles = {"mcl_copper_oxidized_cut.png"}, +minetest.register_node("mcl_copper:waxed_block_exposed_cut", { + description = S("Waxed Exposed Cut Copper"), + _doc_items_longdesc = S("Exposed cut copper is a decorative block."), + tiles = {"mcl_copper_exposed_cut.png"}, is_ground_content = false, groups = {pickaxey = 2, building_block = 1}, sounds = mcl_sounds.node_sound_metal_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 5, - _mcl_anti_oxidation_varient = "mcl_copper:block_weathered_cut", + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_cut") end, }) minetest.register_node("mcl_copper:block_weathered_cut", { @@ -118,6 +184,44 @@ minetest.register_node("mcl_copper:block_weathered_cut", { _mcl_blast_resistance = 6, _mcl_hardness = 5, _mcl_anti_oxidation_varient = "mcl_copper:block_exposed_cut", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_weathered_cut") end, +}) + +minetest.register_node("mcl_copper:waxed_block_weathered_cut", { + description = S("Waxed Weathered Cut Copper"), + _doc_items_longdesc = S("Weathered cut copper is a decorative block."), + tiles = {"mcl_copper_weathered_cut.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_exposed_cut") end, +}) + +minetest.register_node("mcl_copper:block_oxidized_cut", { + description = S("Oxidized Cut Copper"), + _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), + tiles = {"mcl_copper_oxidized_cut.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + _mcl_anti_oxidation_varient = "mcl_copper:block_weathered_cut", + on_rightclick = function(pos, node, player, itemstack) waxing_copper_block(pos, node, player, itemstack, "mcl_copper:waxed_block_oxidized_cut") end, +}) + +minetest.register_node("mcl_copper:waxed_block_oxidized_cut", { + description = S("Waxed Oxidized Cut Copper"), + _doc_items_longdesc = S("Oxidized cut copper is a decorative block."), + tiles = {"mcl_copper_oxidized_cut.png"}, + is_ground_content = false, + groups = {pickaxey = 2, building_block = 1}, + sounds = mcl_sounds.node_sound_metal_defaults(), + _mcl_blast_resistance = 6, + _mcl_hardness = 5, + on_rightclick = function(pos, node, player, itemstack) scraping_copper_block(pos, node, player, itemstack, "mcl_copper:block_weathered_cut") end, }) mcl_stairs.register_slab("copper_cut", "mcl_copper:block_cut", @@ -127,6 +231,13 @@ mcl_stairs.register_slab("copper_cut", "mcl_copper:block_cut", nil, nil, nil, S("Double Slab of Cut Copper")) +mcl_stairs.register_slab("waxed_copper_cut", "mcl_copper:waxed_block_cut", + {pickaxey = 2}, + {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, + S("Waxed Slab of Cut Copper"), + nil, nil, nil, + S("Waxed Double Slab of Cut Copper")) + mcl_stairs.register_slab("copper_exposed_cut", "mcl_copper:block_exposed_cut", {pickaxey = 2}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, @@ -134,12 +245,12 @@ mcl_stairs.register_slab("copper_exposed_cut", "mcl_copper:block_exposed_cut", nil, nil, nil, S("Double Slab of Exposed Cut Copper")) -mcl_stairs.register_slab("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", +mcl_stairs.register_slab("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exposed_cut", {pickaxey = 2}, - {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, - S("Slab of Oxidized Cut Copper"), + {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, + S("Waxed Slab of Exposed Cut Copper"), nil, nil, nil, - S("Double Slab of Oxidized Cut Copper")) + S("Waxed Double Slab of Exposed Cut Copper")) mcl_stairs.register_slab("copper_weathered_cut", "mcl_copper:block_weathered_cut", {pickaxey = 2}, @@ -148,6 +259,27 @@ mcl_stairs.register_slab("copper_weathered_cut", "mcl_copper:block_weathered_cut nil, nil, nil, S("Double Slab of Weathered Cut Copper")) +mcl_stairs.register_slab("waxed_copper_weathered_cut", "mcl_copper:waxed_block_weathered_cut", + {pickaxey = 2}, + {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, + S("Waxed Slab of Weathered Cut Copper"), + nil, nil, nil, + S("Waxed Double Slab of Weathered Cut Copper")) + +mcl_stairs.register_slab("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", + {pickaxey = 2}, + {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, + S("Slab of Oxidized Cut Copper"), + nil, nil, nil, + S("Double Slab of Oxidized Cut Copper")) + +mcl_stairs.register_slab("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_oxidized_cut", + {pickaxey = 2}, + {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, + S("Waxed Slab of Oxidized Cut Copper"), + nil, nil, nil, + S("Waxed Double Slab of Oxidized Cut Copper")) + mcl_stairs.register_stair("copper_cut", "mcl_copper:block_cut", {pickaxey = 2}, {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, @@ -155,6 +287,13 @@ mcl_stairs.register_stair("copper_cut", "mcl_copper:block_cut", nil, 6, nil, "woodlike") +mcl_stairs.register_stair("waxed_copper_cut", "mcl_copper:waxed_block_cut", + {pickaxey = 2}, + {"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"}, + S("Waxed Stairs of Cut Copper"), + nil, 6, nil, + "woodlike") + mcl_stairs.register_stair("copper_exposed_cut", "mcl_copper:block_exposed_cut", {pickaxey = 2}, {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, @@ -162,10 +301,10 @@ mcl_stairs.register_stair("copper_exposed_cut", "mcl_copper:block_exposed_cut", nil, 6, nil, "woodlike") -mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", +mcl_stairs.register_stair("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exposed_cut", {pickaxey = 2}, - {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, - S("Stairs of Oxidized Cut Copper"), + {"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"}, + S("Waxed Stairs of Exposed Cut Copper"), nil, 6, nil, "woodlike") @@ -174,4 +313,25 @@ mcl_stairs.register_stair("copper_weathered_cut", "mcl_copper:block_weathered_cu {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, S("Stairs of Weathered Cut Copper"), nil, 6, nil, - "woodlike") \ No newline at end of file + "woodlike") + +mcl_stairs.register_stair("waxed_copper_weathered_cut", "mcl_copper:waxed_block_weathered_cut", + {pickaxey = 2}, + {"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"}, + S("Waxed Stairs of Weathered Cut Copper"), + nil, 6, nil, + "woodlike") + +mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut", + {pickaxey = 2}, + {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, + S("Stairs of Oxidized Cut Copper"), + nil, 6, nil, + "woodlike") + +mcl_stairs.register_stair("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_oxidized_cut", + {pickaxey = 2}, + {"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"}, + S("Waxed Stairs of Oxidized Cut Copper"), + nil, 6, nil, + "woodlike") diff --git a/mods/ITEMS/mcl_copper/screenshot.png b/mods/ITEMS/mcl_copper/screenshot.png deleted file mode 100644 index 032d45fb1..000000000 Binary files a/mods/ITEMS/mcl_copper/screenshot.png and /dev/null differ diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index f5132d74b..5a01cd8c1 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -22,6 +22,7 @@ minetest.register_abm({ neighbors = {"group:water"}, interval = 1, chance = 1, + min_y = mcl_vars.mg_end_min, action = function(pos, node, active_object_count, active_object_count_wider) local water = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, "group:water") @@ -174,7 +175,7 @@ minetest.register_abm({ nodenames = {"group:destroy_by_lava_flow"}, neighbors = {"group:lava"}, interval = 1, - chance = 1, + chance = 5, action = function(pos, node, active_object_count, active_object_count_wider) liquid_flow_action(pos, "lava", function(pos) minetest.remove_node(pos) diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index 2f464a2fc..2a6192b72 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -88,10 +88,13 @@ minetest.register_node("mcl_core:stone_with_gold", { }) local redstone_timer = 68.28 -local function redstone_ore_activate(pos) +local function redstone_ore_activate(pos, node, puncher, pointed_thing) minetest.swap_node(pos, {name="mcl_core:stone_with_redstone_lit"}) local t = minetest.get_node_timer(pos) t:start(redstone_timer) + if puncher and pointed_thing then + return minetest.node_punch(pos, node, puncher, pointed_thing) + end end minetest.register_node("mcl_core:stone_with_redstone", { description = S("Redstone Ore"), @@ -126,9 +129,12 @@ minetest.register_node("mcl_core:stone_with_redstone", { } }) -local function redstone_ore_reactivate(pos) +local function redstone_ore_reactivate(pos, node, puncher, pointed_thing) local t = minetest.get_node_timer(pos) t:start(redstone_timer) + if puncher and pointed_thing then + return minetest.node_punch(pos, node, puncher, pointed_thing) + end end -- Light the redstone ore up when it has been touched minetest.register_node("mcl_core:stone_with_redstone_lit", { @@ -363,7 +369,7 @@ minetest.register_node("mcl_core:dirt_with_grass", { _doc_items_longdesc = S("A grass block is dirt with a grass cover. Grass blocks are resourceful blocks which allow the growth of all sorts of plants. They can be turned into farmland with a hoe and turned into grass paths with a shovel. In light, the grass slowly spreads onto dirt nearby. Under an opaque block or a liquid, a grass block may turn back to dirt."), _doc_items_hidden = false, paramtype2 = "color", - tiles = {"mcl_core_grass_block_top.png", { name="default_dirt.png^mcl_dirt_grass_shadow.png", color="white" }}, + tiles = {"mcl_core_grass_block_top.png", { name="default_dirt.png", color="white" }, { name="default_dirt.png^mcl_dirt_grass_shadow.png", color="white" }}, overlay_tiles = {"mcl_core_grass_block_top.png", "", {name="mcl_core_grass_block_side_overlay.png", tileable_vertical=false}}, palette = "mcl_core_palette_grass.png", palette_index = 0, @@ -428,7 +434,7 @@ minetest.register_node("mcl_core:mycelium", { tiles = {"mcl_core_mycelium_top.png", "default_dirt.png", {name="mcl_core_mycelium_side.png", tileable_vertical=false}}, is_ground_content = true, stack_max = 64, - groups = { handy = 1, shovely = 1, dirt = 2, spreading_dirt_type = 1, enderman_takable = 1, building_block = 1, soil_sapling = 2, path_creation_possible=1}, + groups = { handy = 1, shovely = 1, dirt = 2, spreading_dirt_type = 1, enderman_takable = 1, building_block = 1, soil_sapling = 2, path_creation_possible=1, mycelium=1}, drop = "mcl_core:dirt", sounds = mcl_sounds.node_sound_dirt_defaults({ footstep = {name="default_grass_footstep", gain=0.1}, @@ -442,6 +448,44 @@ minetest.register_node("mcl_core:mycelium", { }) mcl_core.register_snowed_node("mcl_core:mycelium_snow", "mcl_core:mycelium", nil, nil, false, S("Mycelium with Snow")) +local PARTICLE_ABM_DISTANCE = 16 + +--if minetest.settings:get("mcl_node_particles") == "full" then +minetest.register_abm({ + label = "Townaura particles", + nodenames = {"group:mycelium"}, + interval = 2, + chance = 30, + action = function(pos, node) + local player_near = false + for _,player in pairs(minetest.get_connected_players()) do + if vector.distance(player:get_pos(), pos) < PARTICLE_ABM_DISTANCE then + player_near = true + end + end + if player_near then + local apos = {x=pos.x-2, y=pos.y+0.51, z=pos.z-2} + local apos2 = {x=pos.x+2, y=pos.y+0.51, z=pos.z+2} + local acc = { x = 0, y = 0, z = 0 } + minetest.add_particlespawner({ + time = 2, + amount = 5, + minpos = apos, + maxpos = apos2, + minvel = vector.new(-3/10, 0, -3/10), + maxvel = vector.new(3/10, 10/60, 3/10), + minacc = acc, + expirationtime = 4, + collisiondetection = true, + collision_removal = true, + size = 1, + texture = "mcl_core_mycelium_particle.png", + }) + end + end, +}) +--end + minetest.register_node("mcl_core:podzol", { description = S("Podzol"), _doc_items_longdesc = S("Podzol is a type of dirt found in taiga forests. Only a few plants are able to survive on it."), diff --git a/mods/ITEMS/mcl_core/nodes_liquid.lua b/mods/ITEMS/mcl_core/nodes_liquid.lua index 68ae4a829..081f1978a 100644 --- a/mods/ITEMS/mcl_core/nodes_liquid.lua +++ b/mods/ITEMS/mcl_core/nodes_liquid.lua @@ -50,7 +50,7 @@ minetest.register_node("mcl_core:water_flowing", { liquid_viscosity = WATER_VISC, liquid_range = 7, waving = 3, - post_effect_color = {a=209, r=0x03, g=0x3C, b=0x5C}, + post_effect_color = {a=20, r=0x03, g=0x3C, b=0x5C}, groups = { water=3, liquid=3, puts_out_fire=1, not_in_creative_inventory=1, freezes=1, melt_around=1, dig_by_piston=1}, _mcl_blast_resistance = 100, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode @@ -95,7 +95,7 @@ S("• When water is directly below lava, the water turns into stone."), liquid_alternative_source = "mcl_core:water_source", liquid_viscosity = WATER_VISC, liquid_range = 7, - post_effect_color = {a=209, r=0x03, g=0x3C, b=0x5C}, + post_effect_color = {a=60, r=0x03, g=0x3C, b=0x5C}, stack_max = 64, groups = { water=3, liquid=3, puts_out_fire=1, freezes=1, not_in_creative_inventory=1, dig_by_piston=1}, _mcl_blast_resistance = 100, diff --git a/mods/ITEMS/mcl_core/schematics/mcl_core_birch_bee_nest.mts b/mods/ITEMS/mcl_core/schematics/mcl_core_birch_bee_nest.mts new file mode 100644 index 000000000..fff8fddc4 Binary files /dev/null and b/mods/ITEMS/mcl_core/schematics/mcl_core_birch_bee_nest.mts differ diff --git a/mods/ITEMS/mcl_core/schematics/mcl_core_oak_classic_bee_nest.mts b/mods/ITEMS/mcl_core/schematics/mcl_core_oak_classic_bee_nest.mts new file mode 100644 index 000000000..1f793f47c Binary files /dev/null and b/mods/ITEMS/mcl_core/schematics/mcl_core_oak_classic_bee_nest.mts differ diff --git a/mods/ITEMS/mcl_core/textures/mcl_core_mycelium_particle.png b/mods/ITEMS/mcl_core/textures/mcl_core_mycelium_particle.png new file mode 100644 index 000000000..abf43e33a Binary files /dev/null and b/mods/ITEMS/mcl_core/textures/mcl_core_mycelium_particle.png differ diff --git a/mods/ITEMS/mcl_crimson/init.lua b/mods/ITEMS/mcl_crimson/init.lua index 45710c152..bc5b450fc 100644 --- a/mods/ITEMS/mcl_crimson/init.lua +++ b/mods/ITEMS/mcl_crimson/init.lua @@ -13,18 +13,55 @@ function generate_crimson_tree(pos) minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_1.mts","random",nil,false,"place_center_x,place_center_z") end -function grow_twisting_vines(pos, moreontop) - local y = pos.y + 1 - while not (moreontop == 0) do - if minetest.get_node({x = pos.x, y = y, z = pos.z}).name == "air" then - minetest.set_node({x = pos.x, y = y, z = pos.z}, {name="mcl_crimson:twisting_vines"}) - moreontop = moreontop - 1 - y = y + 1 - elseif minetest.get_node({x = pos.x, y = y, z = pos.z}).name == "mcl_crimson:twisting_vines" then - y = y + 1 - else - moreontop = 0 +function grow_vines(pos, moreontop ,vine, dir) + if dir == nil then dir = 1 end + local n + repeat + pos = vector.offset(pos,0,dir,0) + n = minetest.get_node(pos) + if n.name == "air" then + for i=0,math.max(moreontop,1) do + if minetest.get_node(pos).name == "air" then + minetest.set_node(vector.offset(pos,0,i*dir,0),{name=vine}) + end end + break + end + until n.name ~= "air" and n.name ~= vine +end + +local nether_plants = { + ["mcl_crimson:crimson_nylium"] = { + "mcl_crimson:crimson_roots", + "mcl_crimson:crimson_fungus", + "mcl_crimson:warped_fungus", + }, + ["mcl_crimson:warped_nylium"] = { + "mcl_crimson:warped_roots", + "mcl_crimson:warped_fungus", + "mcl_crimson:twisting_vines", + "mcl_crimson:nether_sprouts", + }, +} + +local function has_nylium_neighbor(pos) + local p = minetest.find_node_near(pos,1,{"mcl_crimson:warped_nylium","mcl_crimson:crimson_nylium"}) + if p then + return minetest.get_node(p) + end +end + +local function spread_nether_plants(pos,node) + local n = node.name + local nn = minetest.find_nodes_in_area_under_air(vector.offset(pos,-5,-3,-5),vector.offset(pos,5,3,5),{n}) + table.shuffle(nn) + nn[1] = pos + for i=1,math.random(1,math.min(#nn,12)) do + local p = vector.offset(nn[i],0,1,0) + if minetest.get_node(p).name == "air" then + minetest.set_node(p,{name=nether_plants[n][math.random(#nether_plants[n])]}) + mcl_dye.add_bone_meal_particle(vector.offset(nn[i],0,1,0)) + end end end @@ -50,6 +87,7 @@ minetest.register_node("mcl_crimson:warped_fungus", { if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then local random = math.random(1, 5) if random == 1 then + minetest.remove_node(pos) generate_warped_tree(pos) end end @@ -58,6 +96,12 @@ minetest.register_node("mcl_crimson:warped_fungus", { _mcl_blast_resistance = 0, }) +mcl_flowerpots.register_potted_flower("mcl_crimson:warped_fungus", { + name = "warped fungus", + desc = S("Warped Fungus Mushroom"), + image = "farming_warped_fungus.png", +}) + minetest.register_node("mcl_crimson:twisting_vines", { description = S("Twisting Vines"), drawtype = "plantlike", @@ -74,14 +118,24 @@ minetest.register_node("mcl_crimson:twisting_vines", { fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 }, }, node_placement_prediction = "", - on_rightclick = function(pos, node, pointed_thing, itemstack) - if pointed_thing:get_wielded_item():get_name() == "mcl_crimson:twisting_vines" then - itemstack:take_item() - grow_twisting_vines(pos, 1) - elseif pointed_thing:get_wielded_item():get_name() == "mcl_dye:white" then - itemstack:take_item() - grow_twisting_vines(pos, math.random(1, 3)) + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local pn = clicker:get_player_name() + if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then + minetest.record_protection_violation(vector.offset(pos,0,1,0), pn) + return itemstack end + if clicker:get_wielded_item():get_name() == "mcl_crimson:twisting_vines" then + if not minetest.is_creative_enabled(clicker:get_player_name()) then + itemstack:take_item() + end + grow_vines(pos, 1, "mcl_crimson:twisting_vines") + elseif clicker:get_wielded_item():get_name() == "mcl_dye:white" then + if not minetest.is_creative_enabled(clicker:get_player_name()) then + itemstack:take_item() + end + grow_vines(pos, math.random(1, 3),"mcl_crimson:twisting_vines") + end + return itemstack end, drop = { max_items = 1, @@ -104,6 +158,62 @@ minetest.register_node("mcl_crimson:twisting_vines", { _mcl_blast_resistance = 0, }) +minetest.register_node("mcl_crimson:weeping_vines", { + description = S("Weeping Vines"), + drawtype = "plantlike", + tiles = { "mcl_crimson_weeping_vines.png" }, + inventory_image = "mcl_crimson_weeping_vines.png", + sunlight_propagates = true, + paramtype = "light", + walkable = false, + climbable = true, + buildable_to = true, + groups = {dig_immediate=3,vines=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,deco_block=1, shearsy = 1}, + selection_box = { + type = "fixed", + fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 }, + }, + node_placement_prediction = "", + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local pn = clicker:get_player_name() + if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then + minetest.record_protection_violation(vector.offset(pos,0,1,0), pn) + return itemstack + end + if clicker:get_wielded_item():get_name() == "mcl_crimson:weeping_vines" then + if not minetest.is_creative_enabled(clicker:get_player_name()) then + itemstack:take_item() + end + grow_vines(pos, 1, "mcl_crimson:weeping_vines", -1) + elseif clicker:get_wielded_item():get_name() == "mcl_dye:white" then + if not minetest.is_creative_enabled(clicker:get_player_name()) then + itemstack:take_item() + end + grow_vines(pos, math.random(1, 3),"mcl_crimson:weeping_vines", -1) + end + return itemstack + end, + drop = { + max_items = 1, + items = { + {items = {"mcl_crimson:weeping_vines"}, rarity = 3}, + }, + }, + _mcl_shears_drop = true, + _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + items = { + {items = {"mcl_crimson:weeping_vines"}, rarity = 3}, + }, + items = { + {items = {"mcl_crimson:weeping_vines"}, rarity = 1.8181818181818181}, + }, + "mcl_crimson:weeping_vines", + "mcl_crimson:weeping_vines", + }, + _mcl_blast_resistance = 0, +}) + minetest.register_node("mcl_crimson:nether_sprouts", { description = S("Nether Sprouts"), drawtype = "plantlike", @@ -144,6 +254,13 @@ minetest.register_node("mcl_crimson:warped_roots", { _mcl_blast_resistance = 0, }) +mcl_flowerpots.register_potted_flower("mcl_crimson:warped_roots", { + name = "warped roots", + desc = S("Warped Roots"), + image = "warped_roots.png", +}) + + minetest.register_node("mcl_crimson:warped_wart_block", { description = S("Warped Wart Block"), tiles = {"warped_wart_block.png"}, @@ -154,7 +271,7 @@ minetest.register_node("mcl_crimson:warped_wart_block", { minetest.register_node("mcl_crimson:shroomlight", { description = S("Shroomlight"), tiles = {"shroomlight.png"}, - groups = {handy = 1, hoe = 7, swordy = 1, leafdecay = 5, leaves = 1, deco_block = 1}, + groups = {handy = 1, hoe = 7, swordy = 1, deco_block = 1}, light_source = minetest.LIGHT_MAX, _mcl_hardness = 2, }) @@ -224,7 +341,7 @@ minetest.register_craft({ }) minetest.register_node("mcl_crimson:stripped_warped_hyphae", { - description = S("Stripped warped hyphae"), + description = S("Stripped Warped Hyphae"), _doc_items_longdesc = S("The stripped hyphae of a warped fungus"), _doc_items_hidden = false, tiles = {"warped_stem_stripped_top.png", "warped_stem_stripped_top.png", "warped_stem_stripped_side.png"}, @@ -237,9 +354,9 @@ minetest.register_node("mcl_crimson:stripped_warped_hyphae", { }) minetest.register_node("mcl_crimson:stripped_warped_hyphae_bark", { - description = S("Stripped warped hyphae bark"), + description = S("Stripped Warped Hyphae Bark"), _doc_items_longdesc = S("The stripped hyphae bark of a warped fungus"), - tiles = {"crimson_stem_stripped_side.png"}, + tiles = {"warped_stem_stripped_side.png"}, paramtype2 = "facedir", on_place = mcl_util.rotate_axis, groups = {handy = 1, axey = 1, bark = 1, building_block = 1, material_wood = 1}, @@ -261,7 +378,7 @@ minetest.register_node("mcl_crimson:warped_hyphae_wood", { description = S("Warped Hyphae Wood"), tiles = {"warped_hyphae_wood.png"}, groups = {handy = 5,axey = 1, flammable = 3, wood=1,building_block = 1, material_wood = 1, fire_encouragement = 5, fire_flammability = 20}, - paramtype2 = "facedir", + sounds = mcl_sounds.node_sound_wood_defaults(), _mcl_hardness = 2, }) @@ -282,21 +399,6 @@ minetest.register_craft({ }, }) -minetest.register_abm({ - label = "mcl_crimson:warped_fungus", - nodenames = {"mcl_crimson:warped_fungus"}, - interval = 11, - chance = 128, - action = function(pos) - local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0)) - if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then - if pos.y < -28400 then - generate_warped_tree(pos) - end - end - end -}) - minetest.register_node("mcl_crimson:crimson_fungus", { description = S("Crimson Fungus Mushroom"), drawtype = "plantlike", @@ -319,6 +421,7 @@ minetest.register_node("mcl_crimson:crimson_fungus", { if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then local random = math.random(1, 5) if random == 1 then + minetest.remove_node(pos) generate_crimson_tree(pos) end end @@ -327,6 +430,12 @@ minetest.register_node("mcl_crimson:crimson_fungus", { _mcl_blast_resistance = 0, }) +mcl_flowerpots.register_potted_flower("mcl_crimson:crimson_fungus", { + name = "crimson fungus", + desc = S("Crimson Fungus Mushroom"), + image = "farming_crimson_fungus.png", +}) + minetest.register_node("mcl_crimson:crimson_roots", { description = S("Crimson Roots"), drawtype = "plantlike", @@ -346,6 +455,12 @@ minetest.register_node("mcl_crimson:crimson_roots", { _mcl_blast_resistance = 0, }) +mcl_flowerpots.register_potted_flower("mcl_crimson:crimson_roots", { + name = "crimson roots", + desc = S("Crimson Roots"), + image = "crimson_roots.png", +}) + minetest.register_node("mcl_crimson:crimson_hyphae", { description = S("Crimson Hyphae"), _doc_items_longdesc = S("The stem of a crimson hyphae"), @@ -429,7 +544,7 @@ minetest.register_node("mcl_crimson:crimson_hyphae_wood", { description = S("Crimson Hyphae Wood"), tiles = {"crimson_hyphae_wood.png"}, groups = {handy = 5, axey = 1, wood = 1, building_block = 1, material_wood = 1}, - paramtype2 = "facedir", + sounds = mcl_sounds.node_sound_wood_defaults(), _mcl_hardness = 2, }) @@ -469,17 +584,160 @@ minetest.register_craft({ mcl_stairs.register_stair_and_slab_simple("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", S("Crimson Stair"), S("Crimson Slab"), S("Double Crimson Slab")) -minetest.register_abm({ - label = "mcl_crimson:crimson_fungus", - nodenames = {"mcl_crimson:crimson_fungus"}, - interval = 11, - chance = 128, - action = function(pos) - local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0)) - if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then - if pos.y < -28400 then - generate_crimson_tree(pos) - end +mcl_dye.register_on_bone_meal_apply(function(pt,user) + if not pt.type == "node" then return end + local node = minetest.get_node(pt.under) + if node.name == "mcl_nether:netherrack" then + local n = has_nylium_neighbor(pt.under) + if n then + minetest.set_node(pt.under,n) end + elseif node.name == "mcl_crimson:warped_nylium" or node.name == "mcl_crimson:crimson_nylium" then + spread_nether_plants(pt.under,node) end +end) + +mcl_doors:register_door("mcl_crimson:crimson_door", { + description = S("Crimson Door"), + _doc_items_longdesc = S("Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal."), + _doc_items_usagehelp = S("To open or close a wooden door, rightclick it or supply its lower half with a redstone signal."), + inventory_image = "mcl_crimson_crimson_door.png", + groups = {handy=1,axey=1, material_wood=1, flammable=-1}, + _mcl_hardness = 3, + _mcl_blast_resistance = 3, + tiles_bottom = {"mcl_crimson_crimson_door_bottom.png", "crimson_hyphae_wood.png"}, + tiles_top = {"mcl_crimson_crimson_door_top.png", "crimson_hyphae_wood.png"}, + sounds = mcl_sounds.node_sound_wood_defaults(), +}) + +mcl_doors:register_trapdoor("mcl_crimson:crimson_trapdoor", { + description = S("Crimson Trapdoor"), + _doc_items_longdesc = S("Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder."), + _doc_items_usagehelp = S("To open or close the trapdoor, rightclick it or send a redstone signal to it."), + tile_front = "mcl_crimson_crimson_trapdoor.png", + tile_side = "crimson_hyphae_wood.png", + wield_image = "mcl_crimson_crimson_trapdoor.png", + groups = {handy=1,axey=1, mesecon_effector_on=1, material_wood=1, flammable=-1}, + _mcl_hardness = 3, + _mcl_blast_resistance = 3, + sounds = mcl_sounds.node_sound_wood_defaults(), +}) + +mcl_fences.register_fence_and_fence_gate( + "crimson_fence", + S("Crimson Fence"), + S("Crimson Fence Gate"), + "mcl_crimson_crimson_fence.png", + {handy=1,axey=1, flammable=2,fence_wood=1, fire_encouragement=5, fire_flammability=20}, + minetest.registered_nodes["mcl_crimson:crimson_hyphae"]._mcl_hardness, + minetest.registered_nodes["mcl_crimson:crimson_hyphae"]._mcl_blast_resistance, + {"group:fence_wood"}, + mcl_sounds.node_sound_wood_defaults()) + + +mcl_doors:register_door("mcl_crimson:warped_door", { + description = S("Warped Door"), + _doc_items_longdesc = S("Wooden doors are 2-block high barriers which can be opened or closed by hand and by a redstone signal."), + _doc_items_usagehelp = S("To open or close a wooden door, rightclick it or supply its lower half with a redstone signal."), + inventory_image = "mcl_crimson_warped_door.png", + groups = {handy=1,axey=1, material_wood=1, flammable=-1}, + _mcl_hardness = 3, + _mcl_blast_resistance = 3, + tiles_bottom = {"mcl_crimson_warped_door_bottom.png", "warped_hyphae_wood.png"}, + tiles_top = {"mcl_crimson_warped_door_top.png", "warped_hyphae_wood.png"}, + sounds = mcl_sounds.node_sound_wood_defaults(), +}) + +mcl_doors:register_trapdoor("mcl_crimson:warped_trapdoor", { + description = S("Warped Trapdoor"), + _doc_items_longdesc = S("Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder."), + _doc_items_usagehelp = S("To open or close the trapdoor, rightclick it or send a redstone signal to it."), + tile_front = "mcl_crimson_warped_trapdoor.png", + tile_side = "warped_hyphae_wood.png", + wield_image = "mcl_crimson_warped_trapdoor.png", + groups = {handy=1,axey=1, mesecon_effector_on=1, material_wood=1, flammable=-1}, + _mcl_hardness = 3, + _mcl_blast_resistance = 3, + sounds = mcl_sounds.node_sound_wood_defaults(), +}) + +mcl_fences.register_fence_and_fence_gate( + "warped_fence", + S("Warped Fence"), + S("Warped Fence Gate"), + "mcl_crimson_warped_fence.png", + {handy=1,axey=1, flammable=2,fence_wood=1, fire_encouragement=5, fire_flammability=20}, + minetest.registered_nodes["mcl_crimson:warped_hyphae"]._mcl_hardness, + minetest.registered_nodes["mcl_crimson:warped_hyphae"]._mcl_blast_resistance, + {"group:fence_wood"}, + mcl_sounds.node_sound_wood_defaults()) + +-- Door, Trapdoor, and Fence/Gate Crafting +local crimson_wood = "mcl_crimson:crimson_hyphae_wood" +local warped_wood = "mcl_crimson:warped_hyphae_wood" + +minetest.register_craft({ + output = "mcl_crimson:crimson_door 3", + recipe = { + {crimson_wood, crimson_wood}, + {crimson_wood, crimson_wood}, + {crimson_wood, crimson_wood} + } +}) + +minetest.register_craft({ + output = "mcl_crimson:warped_door 3", + recipe = { + {warped_wood, warped_wood}, + {warped_wood, warped_wood}, + {warped_wood, warped_wood} + } +}) + +minetest.register_craft({ + output = "mcl_crimson:crimson_trapdoor 2", + recipe = { + {crimson_wood, crimson_wood, crimson_wood}, + {crimson_wood, crimson_wood, crimson_wood}, + } +}) + +minetest.register_craft({ + output = "mcl_crimson:warped_trapdoor 2", + recipe = { + {warped_wood, warped_wood, warped_wood}, + {warped_wood, warped_wood, warped_wood}, + } +}) + +minetest.register_craft({ + output = "mcl_crimson:crimson_fence 3", + recipe = { + {crimson_wood, "mcl_core:stick", crimson_wood}, + {crimson_wood, "mcl_core:stick", crimson_wood}, + } +}) + +minetest.register_craft({ + output = "mcl_crimson:warped_fence 3", + recipe = { + {warped_wood, "mcl_core:stick", warped_wood}, + {warped_wood, "mcl_core:stick", warped_wood}, + } +}) + +minetest.register_craft({ + output = "mcl_crimson:crimson_fence_gate", + recipe = { + {"mcl_core:stick", crimson_wood, "mcl_core:stick"}, + {"mcl_core:stick", crimson_wood, "mcl_core:stick"}, + } +}) + +minetest.register_craft({ + output = "mcl_crimson:warped_fence_gate", + recipe = { + {"mcl_core:stick", warped_wood, "mcl_core:stick"}, + {"mcl_core:stick", warped_wood, "mcl_core:stick"}, + } }) diff --git a/mods/ITEMS/mcl_crimson/mod.conf b/mods/ITEMS/mcl_crimson/mod.conf index 4dbf770c3..89c60cd1e 100644 --- a/mods/ITEMS/mcl_crimson/mod.conf +++ b/mods/ITEMS/mcl_crimson/mod.conf @@ -1,4 +1,3 @@ name = mcl_crimson author = debiankaios -depends = mcl_stairs, mobs_mc, mcl_util - +depends = mcl_core, mcl_stairs, mobs_mc, mcl_util, mcl_dye, mcl_flowerpots diff --git a/mods/ITEMS/mcl_crimson/textures/crimson_hyphae.png b/mods/ITEMS/mcl_crimson/textures/crimson_hyphae.png index bf921d408..6b0d97669 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/crimson_hyphae.png and b/mods/ITEMS/mcl_crimson/textures/crimson_hyphae.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/crimson_nylium.png b/mods/ITEMS/mcl_crimson/textures/crimson_nylium.png index 0ba14eecb..de67faf94 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/crimson_nylium.png and b/mods/ITEMS/mcl_crimson/textures/crimson_nylium.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/crimson_roots.png b/mods/ITEMS/mcl_crimson/textures/crimson_roots.png index f173bfb00..3d19cca40 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/crimson_roots.png and b/mods/ITEMS/mcl_crimson/textures/crimson_roots.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/crimson_stem_stripped_top.png b/mods/ITEMS/mcl_crimson/textures/crimson_stem_stripped_top.png index 313ae0f5a..f54c851bf 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/crimson_stem_stripped_top.png and b/mods/ITEMS/mcl_crimson/textures/crimson_stem_stripped_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/farming_warped_fungus.png b/mods/ITEMS/mcl_crimson/textures/farming_warped_fungus.png index 5b465b6d1..4fda7c4cb 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/farming_warped_fungus.png and b/mods/ITEMS/mcl_crimson/textures/farming_warped_fungus.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door.png new file mode 100644 index 000000000..fd804c7a2 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_bottom.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_bottom.png new file mode 100644 index 000000000..288ce940b Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_bottom.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_top.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_top.png new file mode 100644 index 000000000..ed9ad1ef6 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_door_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence.png new file mode 100644 index 000000000..0f5c9a056 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_side.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_side.png new file mode 100644 index 000000000..c54dbe203 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_side.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_top.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_top.png new file mode 100644 index 000000000..555cdbcf8 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_fence_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_trapdoor.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_trapdoor.png new file mode 100644 index 000000000..f727586ce Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_crimson_trapdoor.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door.png new file mode 100644 index 000000000..8137cbe62 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_bottom.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_bottom.png new file mode 100644 index 000000000..e1b532d62 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_bottom.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_top.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_top.png new file mode 100644 index 000000000..8b2903788 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_door_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence.png new file mode 100644 index 000000000..2b87421db Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_side.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_side.png new file mode 100644 index 000000000..b3705f447 Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_side.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_top.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_top.png new file mode 100644 index 000000000..08eea724c Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_fence_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_trapdoor.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_trapdoor.png new file mode 100644 index 000000000..8fc7a120e Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_warped_trapdoor.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/mcl_crimson_weeping_vines.png b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_weeping_vines.png new file mode 100644 index 000000000..10dcf6ccd Binary files /dev/null and b/mods/ITEMS/mcl_crimson/textures/mcl_crimson_weeping_vines.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/stripped_crimson_stem.png b/mods/ITEMS/mcl_crimson/textures/stripped_crimson_stem.png index 3b25e2bad..58114233d 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/stripped_crimson_stem.png and b/mods/ITEMS/mcl_crimson/textures/stripped_crimson_stem.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/stripped_warped_stem.png b/mods/ITEMS/mcl_crimson/textures/stripped_warped_stem.png index 88a7a8d33..c0241f774 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/stripped_warped_stem.png and b/mods/ITEMS/mcl_crimson/textures/stripped_warped_stem.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/warped_hyphae.png b/mods/ITEMS/mcl_crimson/textures/warped_hyphae.png index 08dacdf58..46775336f 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/warped_hyphae.png and b/mods/ITEMS/mcl_crimson/textures/warped_hyphae.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/warped_stem_stripped_top.png b/mods/ITEMS/mcl_crimson/textures/warped_stem_stripped_top.png index 2e2c35b7c..1c534b7d1 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/warped_stem_stripped_top.png and b/mods/ITEMS/mcl_crimson/textures/warped_stem_stripped_top.png differ diff --git a/mods/ITEMS/mcl_crimson/textures/warped_wart_block.png b/mods/ITEMS/mcl_crimson/textures/warped_wart_block.png index 7b6ae1041..412a90492 100644 Binary files a/mods/ITEMS/mcl_crimson/textures/warped_wart_block.png and b/mods/ITEMS/mcl_crimson/textures/warped_wart_block.png differ diff --git a/mods/ITEMS/mcl_deepslate/init.lua b/mods/ITEMS/mcl_deepslate/init.lua index 3df4abc51..17beb6b52 100644 --- a/mods/ITEMS/mcl_deepslate/init.lua +++ b/mods/ITEMS/mcl_deepslate/init.lua @@ -116,15 +116,21 @@ end local redstone_timer = 68.28 -local function redstone_ore_activate(pos) +local function redstone_ore_activate(pos, node, puncher, pointed_thing) minetest.swap_node(pos, { name = "mcl_deepslate:deepslate_with_redstone_lit" }) local t = minetest.get_node_timer(pos) t:start(redstone_timer) + if puncher and pointed_thing then + return minetest.node_punch(pos, node, puncher, pointed_thing) + end end -local function redstone_ore_reactivate(pos) +local function redstone_ore_reactivate(pos, node, puncher, pointed_thing) local t = minetest.get_node_timer(pos) t:start(redstone_timer) + if puncher and pointed_thing then + return minetest.node_punch(pos, node, puncher, pointed_thing) + end end minetest.register_node("mcl_deepslate:deepslate_with_redstone", { diff --git a/mods/ITEMS/mcl_doors/api_doors.lua b/mods/ITEMS/mcl_doors/api_doors.lua index c2fc7c377..e6eef4e0d 100644 --- a/mods/ITEMS/mcl_doors/api_doors.lua +++ b/mods/ITEMS/mcl_doors/api_doors.lua @@ -155,10 +155,17 @@ function mcl_doors:register_door(name, def) end local left_node = minetest.get_node(pt_left) + local mirrored = false + local door_dir = 1 + if left_node.name:sub(1, #name) == name then + mirrored = true + door_dir = 2 + p2 = left_node.param2 + end -- Set door nodes - minetest.set_node(pt, {name=name.."_b_1", param2=p2}) - minetest.set_node(pt2, {name=name.."_t_1", param2=p2}) + minetest.set_node(pt, {name=name.."_b_"..door_dir, param2=p2}) + minetest.set_node(pt2, {name=name.."_t_"..door_dir, param2=p2}) if def.sounds and def.sounds.place then minetest.sound_play(def.sounds.place, {pos=pt}, true) @@ -174,7 +181,7 @@ function mcl_doors:register_door(name, def) local meta1 = minetest_get_meta(pt) local meta2 = minetest_get_meta(pt2) -- save mirror state for the correct door - if left_node.name:sub(1, #name) == name then + if mirrored then meta1:set_int("is_mirrored", 1) meta2:set_int("is_mirrored", 1) end diff --git a/mods/ITEMS/mcl_dye/init.lua b/mods/ITEMS/mcl_dye/init.lua index 727a78460..8296519ca 100644 --- a/mods/ITEMS/mcl_dye/init.lua +++ b/mods/ITEMS/mcl_dye/init.lua @@ -156,7 +156,7 @@ function mcl_dye.register_on_bone_meal_apply(func) table.insert(mcl_dye.bone_meal_callbacks, func) end -local function apply_bone_meal(pointed_thing) +local function apply_bone_meal(pointed_thing,user) -- Bone meal currently spawns all flowers found in the plains. local flowers_table_plains = { "mcl_flowers:dandelion", @@ -281,6 +281,13 @@ local function apply_bone_meal(pointed_thing) if math.random(1, 100) <= 75 then return mcl_farming:grow_plant("plant_beetroot", pos, n, 1, true) end + elseif string.find(n.name, "mcl_farming:sweet_berry_bush_") then + mcl_dye.add_bone_meal_particle(pos) + if n.name == "mcl_farming:sweet_berry_bush_3" then + return minetest.add_item(vector.offset(pos,math.random()-0.5,math.random()-0.5,math.random()-0.5),"mcl_farming:sweet_berry") + else + return mcl_farming:grow_plant("plant_sweet_berry_bush", pos, n, 1, true) + end elseif n.name == "mcl_cocoas:cocoa_1" or n.name == "mcl_cocoas:cocoa_2" then mcl_dye.add_bone_meal_particle(pos) -- Cocoa: Advance by 1 stage @@ -372,6 +379,8 @@ local function apply_bone_meal(pointed_thing) return false end +mcl_dye.apply_bone_meal = apply_bone_meal + minetest.register_craftitem("mcl_dye:white", { inventory_image = "mcl_dye_white.png", description = S("Bone Meal"), diff --git a/mods/ITEMS/mcl_enchanting/mod.conf b/mods/ITEMS/mcl_enchanting/mod.conf index 4d4741fb8..610492857 100644 --- a/mods/ITEMS/mcl_enchanting/mod.conf +++ b/mods/ITEMS/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = Enchanting for MineClone2 -depends = tt, walkover, mcl_sounds, mcl_colors +depends = tt, walkover, mcl_sounds, mcl_colors, mcl_experience optional_depends = screwdriver author = Fleckenstein diff --git a/mods/ITEMS/mcl_end/eye_of_ender.lua b/mods/ITEMS/mcl_end/eye_of_ender.lua index bc697e359..b5adc7cb6 100644 --- a/mods/ITEMS/mcl_end/eye_of_ender.lua +++ b/mods/ITEMS/mcl_end/eye_of_ender.lua @@ -87,7 +87,7 @@ minetest.register_craftitem("mcl_end:ender_eye", { end local origin = user:get_pos() origin.y = origin.y + 1.5 - local strongholds = mcl_structures.get_structure_data("stronghold") + local strongholds = mcl_structures.registered_structures["end_shrine"].static_pos local dim = mcl_worlds.pos_to_dimension(origin) local is_creative = minetest.is_creative_enabled(user:get_player_name()) @@ -105,7 +105,7 @@ minetest.register_craftitem("mcl_end:ender_eye", { local closest_stronghold local lowest_dist for s=1, #strongholds do - local h_pos = table.copy(strongholds[s].pos) + local h_pos = table.copy(strongholds[s]) local h_origin = table.copy(origin) h_pos.y = 0 h_origin.y = 0 @@ -128,14 +128,14 @@ minetest.register_craftitem("mcl_end:ender_eye", { if lowest_dist <= 25 then local velocity = 4 -- Stronghold is close: Fly directly to stronghold and take Y into account. - dir = vector.normalize(vector.direction(origin, closest_stronghold.pos)) + dir = vector.normalize(vector.direction(origin, closest_stronghold)) obj:set_velocity({x=dir.x*velocity, y=dir.y*velocity, z=dir.z*velocity}) else local velocity = 12 -- Don't care about Y if stronghold is still far away. -- Fly to direction of X/Z, and always upwards so it can be seen easily. local o = {x=origin.x, y=0, z=origin.z} - local s = {x=closest_stronghold.pos.x, y=0, z=closest_stronghold.pos.z} + local s = {x=closest_stronghold.x, y=0, z=closest_stronghold.z} dir = vector.normalize(vector.direction(o, s)) obj:set_acceleration({x=dir.x*-3, y=4, z=dir.z*-3}) obj:set_velocity({x=dir.x*velocity, y=3, z=dir.z*velocity}) diff --git a/mods/ITEMS/mcl_farming/README.txt b/mods/ITEMS/mcl_farming/README.txt index 5779d7035..02cdaf93a 100644 --- a/mods/ITEMS/mcl_farming/README.txt +++ b/mods/ITEMS/mcl_farming/README.txt @@ -1,16 +1,12 @@ ===FARMING MOD for MINETEST-C55=== by PilzAdam +Modified heavily by MineClone 2 Dev Team. + Introduction: This mod adds farming to Minetest. -How to install: -Unzip the archive an place it in minetest-base-directory/mods/minetest/ -if you have a windows client or a linux run-in-place client. If you have -a linux system-wide instalation place it in ~/.minetest/mods/minetest/. -If you want to install this mod only in one world create the folder -worldmods/ in your worlddirectory. -For further information or help see: +How to install see: http://wiki.minetest.com/wiki/Installing_Mods How to use the mod: @@ -25,22 +21,8 @@ For further information or help see: http://minetest.net/forum/viewtopic.php?id=2787 License: -Sourcecode: WTFPL (see below) -Graphics: WTFPL (see below) +Sourcecode: CC-BY-SA 4 (see below) +Graphics: CC-BY-SA 4 (see below) See also: http://minetest.net/ - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/mods/ITEMS/mcl_farming/init.lua b/mods/ITEMS/mcl_farming/init.lua index adce058ee..60b10105d 100644 --- a/mods/ITEMS/mcl_farming/init.lua +++ b/mods/ITEMS/mcl_farming/init.lua @@ -27,3 +27,6 @@ dofile(minetest.get_modpath("mcl_farming").."/potatoes.lua") -- ========= BEETROOT ========= dofile(minetest.get_modpath("mcl_farming").."/beetroot.lua") + +-- ========= SWEET BERRY ========= +dofile(minetest.get_modpath("mcl_farming").."/sweet_berry.lua") diff --git a/mods/ITEMS/mcl_farming/shared_functions.lua b/mods/ITEMS/mcl_farming/shared_functions.lua index 7b9784503..e2e42dd25 100644 --- a/mods/ITEMS/mcl_farming/shared_functions.lua +++ b/mods/ITEMS/mcl_farming/shared_functions.lua @@ -69,7 +69,7 @@ function mcl_farming:add_plant(identifier, full_grown, names, interval, chance) interval = interval, chance = chance, action = function(pos, node) - local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "mcl_farming:soil_wet" + local low_speed = minetest.get_node({ x = pos.x, y = pos.y - 1, z = pos.z }).name ~= "mcl_farming:soil_wet" mcl_farming:grow_plant(identifier, pos, node, false, false, low_speed) end, }) @@ -130,7 +130,7 @@ function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light, low stages = 1 end stages = stages + math.ceil(intervals_counter) - local new_node = {name = plant_info.names[step+stages]} + local new_node = { name = plant_info.names[step + stages] } if new_node.name == nil then new_node.name = plant_info.full_grown end @@ -157,14 +157,14 @@ function mcl_farming:place_seed(itemstack, placer, pointed_thing, plantname) end end - local pos = {x=pt.above.x, y=pt.above.y-1, z=pt.above.z} + local pos = { x = pt.above.x, y = pt.above.y - 1, z = pt.above.z } local farmland = minetest.get_node(pos) - pos= {x=pt.above.x, y=pt.above.y, z=pt.above.z} + pos = { x = pt.above.x, y = pt.above.y, z = pt.above.z } local place_s = minetest.get_node(pos) - if string.find(farmland.name, "mcl_farming:soil") and string.find(place_s.name, "air") then - minetest.sound_play(minetest.registered_nodes[plantname].sounds.place, {pos = pos}, true) - minetest.add_node(pos, {name=plantname, param2 = minetest.registered_nodes[plantname].place_param2}) + if string.find(farmland.name, "mcl_farming:soil") and string.find(place_s.name, "air") then + minetest.sound_play(minetest.registered_nodes[plantname].sounds.place, { pos = pos }, true) + minetest.add_node(pos, { name = plantname, param2 = minetest.registered_nodes[plantname].place_param2 }) --local intervals_counter = get_intervals_counter(pos, 1, 1) else return @@ -179,7 +179,7 @@ end --[[ Helper function to create a gourd (e.g. melon, pumpkin), the connected stem nodes as -- full_unconnected_stem: itemstring of the full-grown but unconnceted stem node. This node must already be done +- full_unconnected_stem: itemstring of the full-grown but unconnected stem node. This node must already be done - connected_stem_basename: prefix of the itemstrings used for the 4 connected stem nodes to create - stem_itemstring: Desired itemstring of the fully-grown unconnected stem node - stem_def: Partial node definition of the fully-grown unconnected stem node. Many fields are already defined. You need to add `tiles` and `description` at minimum. Don't define on_construct without good reason @@ -202,10 +202,10 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s } local neighbors = { - { x=-1, y=0, z=0 }, - { x=1, y=0, z=0 }, - { x=0, y=0, z=-1 }, - { x=0, y=0, z=1 }, + { x = -1, y = 0, z = 0 }, + { x = 1, y = 0, z = 0 }, + { x = 0, y = 0, z = -1 }, + { x = 0, y = 0, z = 1 }, } -- Connect the stem at stempos to the first neighboring gourd block. @@ -215,19 +215,19 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s if stem.name ~= full_unconnected_stem then return false end - for n=1, #neighbors do + for n = 1, #neighbors do local offset = neighbors[n] local blockpos = vector.add(stempos, offset) local block = minetest.get_node(blockpos) if block.name == gourd_itemstring then if offset.x == 1 then - minetest.set_node(stempos, {name=connected_stem_names[1]}) + minetest.set_node(stempos, { name = connected_stem_names[1] }) elseif offset.x == -1 then - minetest.set_node(stempos, {name=connected_stem_names[2]}) + minetest.set_node(stempos, { name = connected_stem_names[2] }) elseif offset.z == 1 then - minetest.set_node(stempos, {name=connected_stem_names[3]}) + minetest.set_node(stempos, { name = connected_stem_names[3] }) elseif offset.z == -1 then - minetest.set_node(stempos, {name=connected_stem_names[4]}) + minetest.set_node(stempos, { name = connected_stem_names[4] }) end return true end @@ -238,13 +238,13 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s if not gourd_def.after_destruct then gourd_def.after_destruct = function(blockpos, oldnode) -- Disconnect any connected stems, turning them back to normal stems - for n=1, #neighbors do + for n = 1, #neighbors do local offset = neighbors[n] local expected_stem = connected_stem_names[n] local stempos = vector.add(blockpos, offset) local stem = minetest.get_node(stempos) if stem.name == expected_stem then - minetest.add_node(stempos, {name=full_unconnected_stem}) + minetest.add_node(stempos, { name = full_unconnected_stem }) try_connect_stem(stempos) end end @@ -253,7 +253,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s if not gourd_def.on_construct then function gourd_def.on_construct(blockpos) -- Connect all unconnected stems at full size - for n=1, #neighbors do + for n = 1, #neighbors do local stempos = vector.add(blockpos, neighbors[n]) try_connect_stem(stempos) end @@ -272,7 +272,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s stem_def.selection_box = { type = "fixed", fixed = { - {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15} + { -0.15, -0.5, -0.15, 0.15, 0.5, 0.15 } }, } end @@ -292,7 +292,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s stem_def.drop = stem_drop end if stem_def.groups == nil then - stem_def.groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1,} + stem_def.groups = { dig_immediate = 3, not_in_creative_inventory = 1, plant = 1, attached_node = 1, dig_by_water = 1, destroy_by_lava_flow = 1, } end if stem_def.sounds == nil then stem_def.sounds = mcl_sounds.node_sound_leaves_defaults() @@ -310,48 +310,48 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s local connected_stem_tiles = { { "blank.png", --top - "blank.png", -- bottom - "blank.png", -- right - "blank.png", -- left - connected_stem_texture, -- back - connected_stem_texture.."^[transformFX90" --front + "blank.png", -- bottom + "blank.png", -- right + "blank.png", -- left + connected_stem_texture, -- back + connected_stem_texture .. "^[transformFX90" --front }, { "blank.png", --top - "blank.png", -- bottom - "blank.png", -- right - "blank.png", -- left - connected_stem_texture.."^[transformFX90", --back - connected_stem_texture, -- front + "blank.png", -- bottom + "blank.png", -- right + "blank.png", -- left + connected_stem_texture .. "^[transformFX90", --back + connected_stem_texture, -- front }, { "blank.png", --top - "blank.png", -- bottom - connected_stem_texture.."^[transformFX90", -- right - connected_stem_texture, -- left - "blank.png", --back - "blank.png", -- front + "blank.png", -- bottom + connected_stem_texture .. "^[transformFX90", -- right + connected_stem_texture, -- left + "blank.png", --back + "blank.png", -- front }, { "blank.png", --top - "blank.png", -- bottom - connected_stem_texture, -- right - connected_stem_texture.."^[transformFX90", -- left - "blank.png", --back - "blank.png", -- front + "blank.png", -- bottom + connected_stem_texture, -- right + connected_stem_texture .. "^[transformFX90", -- left + "blank.png", --back + "blank.png", -- front } } local connected_stem_nodebox = { - {-0.5, -0.5, 0, 0.5, 0.5, 0}, - {-0.5, -0.5, 0, 0.5, 0.5, 0}, - {0, -0.5, -0.5, 0, 0.5, 0.5}, - {0, -0.5, -0.5, 0, 0.5, 0.5}, + { -0.5, -0.5, 0, 0.5, 0.5, 0 }, + { -0.5, -0.5, 0, 0.5, 0.5, 0 }, + { 0, -0.5, -0.5, 0, 0.5, 0.5 }, + { 0, -0.5, -0.5, 0, 0.5, 0.5 }, } local connected_stem_selectionbox = { - {-0.1, -0.5, -0.1, 0.5, 0.2, 0.1}, - {-0.5, -0.5, -0.1, 0.1, 0.2, 0.1}, - {-0.1, -0.5, -0.1, 0.1, 0.2, 0.5}, - {-0.1, -0.5, -0.5, 0.1, 0.2, 0.1}, + { -0.1, -0.5, -0.1, 0.5, 0.2, 0.1 }, + { -0.5, -0.5, -0.1, 0.1, 0.2, 0.1 }, + { -0.1, -0.5, -0.1, 0.1, 0.2, 0.5 }, + { -0.1, -0.5, -0.5, 0.1, 0.2, 0.1 }, } - for i=1, 4 do + for i = 1, 4 do minetest.register_node(connected_stem_names[i], { _doc_items_create_entry = false, paramtype = "light", @@ -369,7 +369,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s }, tiles = connected_stem_tiles[i], use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, - groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1,}, + groups = { dig_immediate = 3, not_in_creative_inventory = 1, plant = 1, attached_node = 1, dig_by_water = 1, destroy_by_lava_flow = 1, }, sounds = mcl_sounds.node_sound_leaves_defaults(), _mcl_blast_resistance = 0, }) @@ -380,9 +380,9 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s end minetest.register_abm({ - label = "Grow gourd stem to gourd ("..full_unconnected_stem.." → "..gourd_itemstring..")", - nodenames = {full_unconnected_stem}, - neighbors = {"air"}, + label = "Grow gourd stem to gourd (" .. full_unconnected_stem .. " → " .. gourd_itemstring .. ")", + nodenames = { full_unconnected_stem }, + neighbors = { "air" }, interval = grow_interval, chance = grow_chance, action = function(stempos) @@ -390,20 +390,20 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s if light and light > 10 then -- Check the four neighbors and filter out neighbors where gourds can't grow local neighbors = { - { x=-1, y=0, z=0 }, - { x=1, y=0, z=0 }, - { x=0, y=0, z=-1 }, - { x=0, y=0, z=1 }, + { x = -1, y = 0, z = 0 }, + { x = 1, y = 0, z = 0 }, + { x = 0, y = 0, z = -1 }, + { x = 0, y = 0, z = 1 }, } local floorpos, floor - for n=#neighbors, 1, -1 do + for n = #neighbors, 1, -1 do local offset = neighbors[n] local blockpos = vector.add(stempos, offset) - floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z } + floorpos = vector.offset (blockpos, 0, -1,0) -- replaces { x = blockpos.x, y = blockpos.y - 1, z = blockpos.z } floor = minetest.get_node(floorpos) local block = minetest.get_node(blockpos) local soilgroup = minetest.get_item_group(floor.name, "soil") - if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name=="mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then + if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name == "mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then table.remove(neighbors, n) end end @@ -416,27 +416,35 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s local blockpos = vector.add(stempos, offset) local p2 if offset.x == 1 then - minetest.set_node(stempos, {name=connected_stem_names[1]}) + minetest.set_node(stempos, { name = connected_stem_names[1] }) p2 = 3 elseif offset.x == -1 then - minetest.set_node(stempos, {name=connected_stem_names[2]}) + minetest.set_node(stempos, { name = connected_stem_names[2] }) p2 = 1 elseif offset.z == 1 then - minetest.set_node(stempos, {name=connected_stem_names[3]}) + minetest.set_node(stempos, { name = connected_stem_names[3] }) p2 = 2 elseif offset.z == -1 then - minetest.set_node(stempos, {name=connected_stem_names[4]}) + minetest.set_node(stempos, { name = connected_stem_names[4] }) p2 = 0 end -- Place the gourd if gourd_def.paramtype2 == "facedir" then - minetest.add_node(blockpos, {name=gourd_itemstring, param2=p2}) + minetest.add_node(blockpos, { name = gourd_itemstring, param2 = p2 }) else - minetest.add_node(blockpos, {name=gourd_itemstring}) + minetest.add_node(blockpos, { name = gourd_itemstring }) end + -- Reset farmland, etc. to dirt when the gourd grows on top + + -- FIXED: The following 2 lines were missing, and wasn't being set (outside of the above loop that + -- finds the neighbors.) + -- FYI - don't factor this out thinking that the loop above is setting the positions correctly. + floorpos = vector.offset (blockpos, 0, -1,0) -- replaces { x = blockpos.x, y = blockpos.y - 1, z = blockpos.z } + floor = minetest.get_node(floorpos) + -- END OF FIX ------------------------------------- if minetest.get_item_group(floor.name, "dirtifies_below_solid") == 1 then - minetest.set_node(floorpos, {name = "mcl_core:dirt"}) + minetest.set_node(floorpos, { name = "mcl_core:dirt" }) end end end @@ -452,7 +460,7 @@ end function mcl_farming:stem_color(startcolor, endcolor, step, step_count) local color = {} local function get_component(startt, endd, step, step_count) - return math.floor(math.max(0, math.min(255, (startt + (((step-1)/step_count) * endd))))) + return math.floor(math.max(0, math.min(255, (startt + (((step - 1) / step_count) * endd))))) end color.r = get_component(startcolor.r, endcolor.r, step, step_count) color.g = get_component(startcolor.g, endcolor.g, step, step_count) @@ -464,14 +472,14 @@ end minetest.register_lbm({ label = "Add growth for unloaded farming plants", name = "mcl_farming:growth", - nodenames = {"group:plant"}, + nodenames = { "group:plant" }, run_at_every_load = true, action = function(pos, node) local identifier = plant_nodename_to_id_list[node.name] if not identifier then return end - local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "mcl_farming:soil_wet" + local low_speed = minetest.get_node({ x = pos.x, y = pos.y - 1, z = pos.z }).name ~= "mcl_farming:soil_wet" mcl_farming:grow_plant(identifier, pos, node, false, false, low_speed) end, }) diff --git a/mods/ITEMS/mcl_farming/sweet_berry.lua b/mods/ITEMS/mcl_farming/sweet_berry.lua new file mode 100644 index 000000000..be5c7ef2c --- /dev/null +++ b/mods/ITEMS/mcl_farming/sweet_berry.lua @@ -0,0 +1,117 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +local planton = {"mcl_core:dirt_with_grass", "mcl_core:dirt", "mcl_core:podzol", "mcl_core:coarse_dirt", "mcl_farming:soil", "mcl_farming:soil_wet", "mcl_moss:moss"} + +for i=0, 3 do + local texture = "mcl_farming_sweet_berry_bush_" .. i .. ".png" + local node_name = "mcl_farming:sweet_berry_bush_" .. i + local groups = {sweet_berry=1, dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1, flammable=3, fire_encouragement=60, fire_flammability=20, compostability=30} + if i > 0 then + groups.sweet_berry_thorny = 1 + end + minetest.register_node(node_name, { + drawtype = "plantlike", + tiles = {texture}, + description = S("Sweet Berry Bush (Stage @1)", i), + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "meshoptions", + place_param2 = 3, + liquid_viscosity = 15, + liquidtype = "source", + liquid_alternative_flowing = node_name, + liquid_alternative_source = node_name, + liquid_renewable = false, + liquid_range = 0, + walkable = false, + drop = (i>=2) and ("mcl_farming:sweet_berry" .. (i==3 and " 3" or "")) or "", + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, (-0.30 + (i*0.25)), 6 / 16}, + }, + inventory_image = texture, + wield_image = texture, + groups = groups, + sounds = mcl_sounds.node_sound_leaves_defaults(), + _mcl_blast_resistance = 0, + _mcl_hardness = 0, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local pn = clicker:get_player_name() + if clicker:is_player() and minetest.is_protected(pos, pn) then + minetest.record_protection_violation(pos, pn) + return itemstack + end + if mcl_dye and clicker:get_wielded_item():get_name() == "mcl_dye:white" then + mcl_dye.apply_bone_meal({under=pos},clicker) + itemstack:take_item() + return + end + local stage + if node.name:find("_2") then + stage = 2 + elseif node.name:find("_3") then + stage = 3 + end + if stage then + for i=1,math.random(stage) do + minetest.add_item(pos,"mcl_farming:sweet_berry") + end + minetest.swap_node(pos,{name = "mcl_farming:sweet_berry_bush_" .. stage - 1 }) + end + return itemstack + end, + }) + minetest.register_alias("mcl_sweet_berry:sweet_berry_bush_" .. i, node_name) +end + +minetest.register_craftitem("mcl_farming:sweet_berry", { + description = S("Sweet Berry"), + inventory_image = "mcl_farming_sweet_berry.png", + _mcl_saturation = 0.4, + groups = { food = 2, eatable = 1, compostability=30 }, + on_secondary_use = minetest.item_eat(1), + on_place = function(itemstack, placer, pointed_thing) + local pn = placer:get_player_name() + if placer:is_player() and minetest.is_protected(pointed_thing.above, pn or "") then + minetest.record_protection_violation(pointed_thing.above, pn) + return itemstack + end + if pointed_thing.type == "node" and table.indexof(planton,minetest.get_node(pointed_thing.under).name) ~= -1 and minetest.get_node(pointed_thing.above).name == "air" then + minetest.set_node(pointed_thing.above,{name="mcl_farming:sweet_berry_bush_0"}) + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + return itemstack + end + return minetest.do_item_eat(1, nil, itemstack, placer, pointed_thing) + end, +}) +minetest.register_alias("mcl_sweet_berry:sweet_berry", "mcl_farming:sweet_berry") + +-- TODO: Find proper interval and chance values for sweet berry bushes. Current interval and chance values are copied from mcl_farming:beetroot which has similar growth stages. +mcl_farming:add_plant("plant_sweet_berry_bush", "mcl_farming:sweet_berry_bush_3", {"mcl_farming:sweet_berry_bush_0", "mcl_farming:sweet_berry_bush_1", "mcl_farming:sweet_berry_bush_2"}, 68, 3) + +local function berry_damage_check(obj) + local p = obj:get_pos() + if not p then return end + if not minetest.find_node_near(p,0.4,{"group:sweet_berry_thorny"},true) then return end + local v = obj:get_velocity() + if v.x < 0.1 and v.y < 0.1 and v.z < 0.1 then return end + + mcl_util.deal_damage(obj, 0.5, {type = "sweet_berry"}) +end + +local etime = 0 +minetest.register_globalstep(function(dtime) + etime = dtime + etime + if etime < 0.5 then return end + etime = 0 + for _,pl in pairs(minetest.get_connected_players()) do + berry_damage_check(pl) + end + for _,ent in pairs(minetest.luaentities) do + if ent.is_mob then + berry_damage_check(ent.object) + end + end +end) diff --git a/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry.png b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry.png new file mode 100644 index 000000000..7c2349971 Binary files /dev/null and b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry.png differ diff --git a/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_0.png b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_0.png new file mode 100644 index 000000000..6f8c0d833 Binary files /dev/null and b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_0.png differ diff --git a/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_1.png b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_1.png new file mode 100644 index 000000000..2ac3c205d Binary files /dev/null and b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_1.png differ diff --git a/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_2.png b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_2.png new file mode 100644 index 000000000..5e9a6dd14 Binary files /dev/null and b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_2.png differ diff --git a/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_3.png b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_3.png new file mode 100644 index 000000000..a473882f4 Binary files /dev/null and b/mods/ITEMS/mcl_farming/textures/mcl_farming_sweet_berry_bush_3.png differ diff --git a/mods/ITEMS/mcl_fire/init.lua b/mods/ITEMS/mcl_fire/init.lua index 79b46a701..8827b9f9a 100644 --- a/mods/ITEMS/mcl_fire/init.lua +++ b/mods/ITEMS/mcl_fire/init.lua @@ -378,9 +378,9 @@ else -- Fire enabled minetest.register_abm({ label = "Ignite fire by lava", nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"}, - neighbors = {"air","group:flammable"}, - interval = 7, - chance = 3, + neighbors = {"group:flammable"}, + interval = 15, + chance = 9, catch_up = false, action = function(pos) local p=get_ignitable_by_lava(pos) diff --git a/mods/ITEMS/mcl_flowerpots/init.lua b/mods/ITEMS/mcl_flowerpots/init.lua index 578553b31..4d45e6ffd 100644 --- a/mods/ITEMS/mcl_flowerpots/init.lua +++ b/mods/ITEMS/mcl_flowerpots/init.lua @@ -2,8 +2,18 @@ local S = minetest.get_translator(minetest.get_current_modname()) local has_doc = minetest.get_modpath("doc") mcl_flowerpots = {} + +---@type table mcl_flowerpots.registered_pots = {} +---@type nodebox +local pot_box = { + type = "fixed", + fixed = { + { -0.1875, -0.5, -0.1875, 0.1875, -0.125, 0.1875 }, + }, +} + minetest.register_node("mcl_flowerpots:flower_pot", { description = S("Flower Pot"), _tt_help = S("Can hold a small flower or plant"), @@ -14,23 +24,16 @@ minetest.register_node("mcl_flowerpots:flower_pot", { tiles = { "mcl_flowerpots_flowerpot.png", }, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, + use_texture_alpha = "clip", visual_scale = 0.5, wield_image = "mcl_flowerpots_flowerpot_inventory.png", - wield_scale = {x=1.0, y=1.0, z=1.0}, paramtype = "light", sunlight_propagates = true, - selection_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, - collision_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, + selection_box = pot_box, + collision_box = pot_box, is_ground_content = false, inventory_image = "mcl_flowerpots_flowerpot_inventory.png", - groups = {dig_immediate=3, deco_block=1, attached_node=1, dig_by_piston=1, flower_pot=1}, + groups = { dig_immediate = 3, deco_block = 1, attached_node = 1, dig_by_piston = 1, flower_pot = 1 }, sounds = mcl_sounds.node_sound_stone_defaults(), on_rightclick = function(pos, node, clicker, itemstack) local name = clicker:get_player_name() @@ -40,7 +43,7 @@ minetest.register_node("mcl_flowerpots:flower_pot", { end local item = clicker:get_wielded_item():get_name() if mcl_flowerpots.registered_pots[item] then - minetest.swap_node(pos, {name="mcl_flowerpots:flower_pot_"..mcl_flowerpots.registered_pots[item]}) + minetest.swap_node(pos, { name = "mcl_flowerpots:flower_pot_" .. mcl_flowerpots.registered_pots[item] }) if not minetest.is_creative_enabled(clicker:get_player_name()) then itemstack:take_item() end @@ -51,37 +54,32 @@ minetest.register_node("mcl_flowerpots:flower_pot", { minetest.register_craft({ output = "mcl_flowerpots:flower_pot", recipe = { - {"mcl_core:brick", "", "mcl_core:brick"}, - {"", "mcl_core:brick", ""}, - {"", "", ""}, - } + { "mcl_core:brick", "", "mcl_core:brick" }, + { "", "mcl_core:brick", "" }, + { "", "", "" }, + }, }) +---@param name string +---@param def {name: string, desc: string, image: string} function mcl_flowerpots.register_potted_flower(name, def) mcl_flowerpots.registered_pots[name] = def.name - minetest.register_node(":mcl_flowerpots:flower_pot_"..def.name, { - description = def.desc.." "..S("Flower Pot"), + minetest.register_node(":mcl_flowerpots:flower_pot_" .. def.name, { + description = def.desc .. " " .. S("Flower Pot"), _doc_items_create_entry = false, drawtype = "mesh", mesh = "flowerpot.obj", tiles = { - "[combine:32x32:0,0=mcl_flowerpots_flowerpot.png:0,0="..def.image, + "[combine:32x32:0,0=mcl_flowerpots_flowerpot.png:0,0=" .. def.image, }, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, + use_texture_alpha = "clip", visual_scale = 0.5, - wield_scale = {x=1.0, y=1.0, z=1.0}, paramtype = "light", sunlight_propagates = true, - selection_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, - collision_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, + selection_box = pot_box, + collision_box = pot_box, is_ground_content = false, - groups = {dig_immediate=3, attached_node=1, dig_by_piston=1, not_in_creative_inventory=1, flower_pot=2}, + groups = { dig_immediate = 3, attached_node = 1, dig_by_piston = 1, not_in_creative_inventory = 1, flower_pot = 2 }, sounds = mcl_sounds.node_sound_stone_defaults(), on_rightclick = function(pos, item, clicker) local player_name = clicker:get_player_name() @@ -89,46 +87,41 @@ function mcl_flowerpots.register_potted_flower(name, def) minetest.record_protection_violation(pos, player_name) return end - minetest.add_item({x=pos.x, y=pos.y+0.5, z=pos.z}, name) - minetest.set_node(pos, {name="mcl_flowerpots:flower_pot"}) + minetest.add_item(vector.offset(pos, 0, 0.5, 0), name) + minetest.set_node(pos, { name = "mcl_flowerpots:flower_pot" }) end, drop = { items = { - { items = { "mcl_flowerpots:flower_pot", name } } - } + { items = { "mcl_flowerpots:flower_pot", name } }, + }, }, }) -- Add entry alias for the Help if has_doc then - doc.add_entry_alias("nodes", "mcl_flowerpots:flower_pot", "nodes", "mcl_flowerpots:flower_pot_"..name) + doc.add_entry_alias("nodes", "mcl_flowerpots:flower_pot", "nodes", "mcl_flowerpots:flower_pot_" .. name) end end +---@param name string +---@param def {name: string, desc: string, image: string} function mcl_flowerpots.register_potted_cube(name, def) mcl_flowerpots.registered_pots[name] = def.name - minetest.register_node(":mcl_flowerpots:flower_pot_"..def.name, { - description = def.desc.." "..S("Flower Pot"), + minetest.register_node(":mcl_flowerpots:flower_pot_" .. def.name, { + description = def.desc .. " " .. S("Flower Pot"), _doc_items_create_entry = false, drawtype = "mesh", mesh = "flowerpot_with_long_cube.obj", tiles = { def.image, }, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, + use_texture_alpha = "clip", visual_scale = 0.5, - wield_scale = {x=1.0, y=1.0, z=1.0}, paramtype = "light", sunlight_propagates = true, - selection_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, - collision_box = { - type = "fixed", - fixed = {-0.2, -0.5, -0.2, 0.2, -0.1, 0.2} - }, + selection_box = pot_box, + collision_box = pot_box, is_ground_content = false, - groups = {dig_immediate=3, attached_node=1, dig_by_piston=1, not_in_creative_inventory=1, flower_pot=2}, + groups = { dig_immediate = 3, attached_node = 1, dig_by_piston = 1, not_in_creative_inventory = 1, flower_pot = 2 }, sounds = mcl_sounds.node_sound_stone_defaults(), on_rightclick = function(pos, item, clicker) local player_name = "" @@ -139,18 +132,18 @@ function mcl_flowerpots.register_potted_cube(name, def) minetest.record_protection_violation(pos, player_name) return end - minetest.add_item({x=pos.x, y=pos.y+0.5, z=pos.z}, name) - minetest.set_node(pos, {name="mcl_flowerpots:flower_pot"}) + minetest.add_item(vector.offset(pos, 0, 0.5, 0), name) + minetest.set_node(pos, { name = "mcl_flowerpots:flower_pot" }) end, drop = { items = { - { items = { "mcl_flowerpots:flower_pot", name } } - } + { items = { "mcl_flowerpots:flower_pot", name } }, + }, }, }) -- Add entry alias for the Help if has_doc then - doc.add_entry_alias("nodes", "mcl_flowerpots:flower_pot", "nodes", "mcl_flowerpots:flower_pot_"..def.name) + doc.add_entry_alias("nodes", "mcl_flowerpots:flower_pot", "nodes", "mcl_flowerpots:flower_pot_" .. def.name) end end diff --git a/mods/ITEMS/mcl_flowers/init.lua b/mods/ITEMS/mcl_flowers/init.lua index 33ea531c5..d7b046cf5 100644 --- a/mods/ITEMS/mcl_flowers/init.lua +++ b/mods/ITEMS/mcl_flowers/init.lua @@ -51,6 +51,9 @@ local on_place_flower = mcl_util.generate_on_place_plant_function(function(pos, if (light_night and light_night >= 8) or (light_day and light_day >= minetest.LIGHT_MAX) then light_ok = true end + if itemstack:get_name() == "mcl_flowers:wither_rose" and ( minetest.get_item_group(soil_node.name, "grass_block") > 0 or soil_node.name == "mcl_core:dirt" or soil_node.name == "mcl_core:coarse_dirt" or soil_node.name == "mcl_mud:mud" or soil_node.name == "mcl_moss:moss" or soil_node.name == "mcl_nether:netherrack" or minetest.get_item_group(soil_node.name, "soul_block") > 0 ) then + return true,colorize + end local is_flower = minetest.get_item_group(itemstack:get_name(), "flower") == 1 local ok = (soil_node.name == "mcl_core:dirt" or minetest.get_item_group(soil_node.name, "grass_block") == 1 or (not is_flower and (soil_node.name == "mcl_core:coarse_dirt" or soil_node.name == "mcl_core:podzol" or soil_node.name == "mcl_core:podzol_snow"))) and light_ok return ok, colorize diff --git a/mods/ITEMS/mcl_flowers/register.lua b/mods/ITEMS/mcl_flowers/register.lua index b45f3e1ee..c1bd37878 100644 --- a/mods/ITEMS/mcl_flowers/register.lua +++ b/mods/ITEMS/mcl_flowers/register.lua @@ -59,4 +59,10 @@ mcl_flowers.register_simple_flower("blue_orchid", { image = "mcl_flowers_blue_orchid.png", selection_box = { -5/16, -0.5, -5/16, 5/16, 7/16, 5/16 }, potted = true, -}) \ No newline at end of file +}) +mcl_flowers.register_simple_flower("wither_rose", { + desc = S("Wither Rose"), + image = "mcl_flowers_wither_rose.png", + selection_box = { -3/16, -0.5, -3/16, 3/16, 6/16, 3/16 }, + potted = true, +}) diff --git a/mods/ITEMS/mcl_flowers/textures/mcl_flowers_wither_rose.png b/mods/ITEMS/mcl_flowers/textures/mcl_flowers_wither_rose.png new file mode 100644 index 000000000..539722a34 Binary files /dev/null and b/mods/ITEMS/mcl_flowers/textures/mcl_flowers_wither_rose.png differ diff --git a/mods/ITEMS/mcl_hamburger/init.lua b/mods/ITEMS/mcl_hamburger/init.lua new file mode 100644 index 000000000..7d4707bdd --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/init.lua @@ -0,0 +1,120 @@ +--- +--- Generated by EmmyLua(https://github.com/EmmyLua) +--- Created by michieal. +--- DateTime: 11/19/22 7:13 AM +--- + +--- +--- Generated by EmmyLua(https://github.com/EmmyLua) +--- Created by michieal. +--- DateTime: 10/23/22 4:50 AM +--- +-- LOCALIZATION + +local S = minetest.get_translator("mcl_hamburger") + +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local table = table +local DEBUG = false + +local enable_burger = minetest.settings:get_bool("mcl_enable_hamburger",true) +local use_alt = minetest.settings:get_bool("mcl_hamburger_alt_texture",false) + +mcl_hamburger = {} + +if DEBUG then + minetest.log("MCL_Hamburger::START.") +end + +-- call to register your hamburger. +function mcl_hamburger.register_burger_craft(cooked_meat) + minetest.register_craft({ + type = "fuel", + recipe = "mcl_hamburger:hamburger", + burntime = 2, + }) + + minetest.register_craft({ + output = "mcl_hamburger:hamburger", + recipe = { + { "mcl_farming:bread"}, + { cooked_meat }, -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac. + { "mcl_farming:bread" }, + }, + }) + minetest.register_craft({ + output = "mcl_hamburger:hamburger", + recipe = { + -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac. + { "mcl_farming:bread", cooked_meat, "mcl_farming:bread"}, + }, + }) + +end + +local hamburger_def = { + description = S("A Hamburger"), + _doc_items_longdesc = S("A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten."), + _doc_items_usagehelp = S("Wield this item to pull villagers to you."), + _tt_help = S("A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy."), + inventory_image = "mcl_hamburger.png", + wield_image = "mcl_hamburger.png", + on_place = minetest.item_eat(8), + on_secondary_use = minetest.item_eat(8), + groups = { food = 2, eatable = 8 }, + _mcl_saturation = 13.8, +} + +if not enable_burger then + hamburger_def.groups.not_in_creative_inventory = 1 +end + +if use_alt == false then + minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_def) +else + local hamburger_alt = table.copy(hamburger_def) + hamburger_alt.inventory_image = "mcl_hamburger_alt.png" + hamburger_alt.wield_image = "mcl_hamburger_alt.png" + minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_alt) +end + +local function register_achievements() + + awards.register_achievement("mcl_hamburger:hamburger", { + title = S("Burger Time!"), + description = S("Craft a Hamburger."), + icon = "mcl_hamburger_alt.png", + trigger = { + type = "craft", + item = "mcl_hamburger:hamburger", + target = 1 + }, + type = "Advancement", + group = "Overworld", + }) + +end + +local function register_doc_entry() + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("craftitems", "mcl_hamburger:hamburger", "craftitems", "mcl_hamburger:hamburger") + end + +end + +if enable_burger then + -- make the villagers follow the item + minetest.registered_entities["mobs_mc:villager"].nofollow = false + -- add it to the follow items. + table.insert(minetest.registered_entities["mobs_mc:villager"].follow,"mcl_hamburger:hamburger") + -- register the item and crafting recipe. + mcl_hamburger.register_burger_craft("mcl_mobitems:cooked_beef") + -- add in the super cool achievement(s)! + register_achievements() + register_doc_entry() +end + diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.de.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.de.tr new file mode 100644 index 000000000..8d375dbd5 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.de.tr @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger=Ein Hamburger + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=Ein leckerer Hamburger, der die Dorfbewohner sicher wie eine Leine anlocken wird. Kann gegessen werden. + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=Ein leckerer Hamburger, der die Dorfbewohner anlocken wird. "Ich bezahle dir gerne den Dienstag, für heute einen Hamburger." - Wimpy. + +Burger Time!=Burgerzeit! +Craft a Hamburger.=Stelle einen Hamburger her. +Wield this item to pull villagers to you.=Benutze diesen Gegenstand, um Dorfbewohner zu dir zu ziehen. diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.es.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.es.tr new file mode 100644 index 000000000..ad10560e4 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.es.tr @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger=Una hamburguesa + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=Una sabrosa hamburguesa que seguramente atraerá a los aldeanos como una pista. Se puede comer. + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=Una sabrosa hamburguesa que seguramente atraerá a los aldeanos. 'Con gusto te pago el martes, por una hamburguesa hoy.' - Wimpy. + +Burger Time!=¡Tiempo de hamburguesas! +Craft a Hamburger.=Elabora una hamburguesa. +Wield this item to pull villagers to you.=Utiliza este objeto para atraer a los aldeanos hacia ti. diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.fr.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.fr.tr new file mode 100644 index 000000000..1463a69ad --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.fr.tr @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger=Un hamburger + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=Un hamburger savoureux qui ne manquera pas d'attirer les villageois comme une piste. Peut être mangé. + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=Un hamburger savoureux qui ne manquera pas d'attirer les villageois. «Je vous paierai volontiers mardi, pour un hamburger aujourd'hui.» - Wimpy. + +Burger Time!=L'heure des burgers! +Craft a Hamburger.=Fabriquez un hamburger. +Wield this item to pull villagers to you.=Maniez cet objet pour attirer les villageois vers vous. \ No newline at end of file diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.pl.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.pl.tr new file mode 100644 index 000000000..09569a2ba --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.pl.tr @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger=Hamburger + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=Smaczny hamburger, który zwabi wieśniaków jak trop. Można jeść. + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=Smaczny hamburger, który z pewnością zwabi wieśniaków. - Chętnie zapłacę we wtorek za hamburgera dzisiaj. - Mięczak (Wimpy). + +Burger Time!=Czas na burgery! +Craft a Hamburger.=Stwórz hamburgera. +Wield this item to pull villagers to you.=Chwyć ten przedmiot, aby przyciągnąć wieśniaków do siebie. diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.ru.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.ru.tr new file mode 100644 index 000000000..736f182a5 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.ru.tr @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger=Гамбургер + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=Вкусный гамбургер, который обязательно привлечет жителей деревни, как наживку. Можно есть. + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=Вкусный гамбургер, который обязательно привлечет жителей деревни. — Я с радостью заплачу тебе во вторник за гамбургер сегодня. - Вимпи. + +Burger Time!=Время бургеров! +Craft a Hamburger.=Изготовить гамбургер. +Wield this item to pull villagers to you.=Используйте этот предмет, чтобы притягивать к себе жителей деревни. diff --git a/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.zh_TW.tr b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.zh_TW.tr new file mode 100644 index 000000000..46f30c88e --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/mcl_hamburger.zh_TW.tr @@ -0,0 +1,16 @@ +# textdomain: mcl_hamburger +A Hamburger=一個漢堡 +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.=一個美味的漢堡包,肯定會像鉛一樣吸引村民。 可以吃 +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.=一個美味的漢堡包,一定會吸引村民。 “我很樂意在星期二付錢給你,今天就買一個漢堡包。” - 懦弱。 +Burger Time!=漢堡時間! +Craft a Hamburger.=製作一個漢堡包。 +Wield this item to pull villagers to you.=使用此物品將村民拉到你身邊。 + + + + + + + + + diff --git a/mods/ITEMS/mcl_hamburger/locale/template.txt b/mods/ITEMS/mcl_hamburger/locale/template.txt new file mode 100644 index 000000000..850ff62b0 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/locale/template.txt @@ -0,0 +1,10 @@ +# textdomain: mcl_hamburger +A Hamburger= + +A tasty hamburger that is sure to lure villagers around like a lead. Can be eaten.= + +A tasty hamburger that is sure to lure villagers. 'I'll gladly pay you Tuesday, for a hamburger today.' - Wimpy.= + +Burger Time!= +Craft a Hamburger.= +Wield this item to pull villagers to you.= diff --git a/mods/ITEMS/mcl_hamburger/mod.conf b/mods/ITEMS/mcl_hamburger/mod.conf new file mode 100644 index 000000000..f5baca506 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/mod.conf @@ -0,0 +1,5 @@ +name = mcl_hamburger +author = Michieal +description = A cute (and easy to use) replacement for not having leashes in MC2 +depends = mcl_core, mcl_sounds, mobs_mc, mcl_mobitems, awards +optional_depends = doc diff --git a/mods/ITEMS/mcl_hamburger/readme.txt b/mods/ITEMS/mcl_hamburger/readme.txt new file mode 100644 index 000000000..e479c01b9 --- /dev/null +++ b/mods/ITEMS/mcl_hamburger/readme.txt @@ -0,0 +1,43 @@ +Tags: Hamburger +Icon set: Fugue 16px Additional Icons +Author: Yusuke Kamiyamane +License: CC Attribution 3.0 Unported +Readme file +Commercial usage: Allowed +Posted: November 22, 2011 +Icon Readme file: + +Fugue Icons + +(C) 2011 Yusuke Kamiyamane. All rights reserved. +These icons are licensed under a Creative Commons +Attribution 3.0 License. + + +If you can't or don't want to provide attribution, please +purchase a royalty-free license. + + +I'm unavailable for custom icon design work. But your +suggestions are always welcome! + + +------------------------------------------------------------ + +The images contained within have been altered to be more legible within the game and not rendered with weird +antialiasing by Michieal. All extraneous information in the images have been removed to decrease file size. + +This mod is licensed under CC-BY-SA 3, with the intent of it being used by the Mineclone 2 game for Minetest. +This code was written by Michieal, with additions included by Cora. + +The achievement "Burger Time!" is an homage to the classic coin-op arcade game BurgerTime, by Data East (1982) and +Bally Midway. + +Information about the BurgerTime Arcade Game: + +From https://thepinballgameroom.com/product/burgertime-arcade-machine/ on the original game: +BurgerTime Arcade Machine, originally released as Hamburger in Japan, is a 1982 arcade game developed by Data East +initially for its DECO Cassette System. In the United States, Data East USA licensed BurgerTime Arcade Machine for +distribution by Bally Midway as a standard dedicated arcade game. Data East also released its own version of BurgerTime +in the United States through its DECO Cassette System. The Data East and Midway versions are distinguished by the +manufacturer’s name on the title screen and by the marquee and cabinet artworks, as the game itself is identical. diff --git a/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger.png b/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger.png new file mode 100644 index 000000000..432d05bba Binary files /dev/null and b/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger.png differ diff --git a/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger_alt.png b/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger_alt.png new file mode 100644 index 000000000..70fd29448 Binary files /dev/null and b/mods/ITEMS/mcl_hamburger/textures/mcl_hamburger_alt.png differ diff --git a/mods/ITEMS/mcl_honey/init.lua b/mods/ITEMS/mcl_honey/init.lua new file mode 100644 index 000000000..e736320aa --- /dev/null +++ b/mods/ITEMS/mcl_honey/init.lua @@ -0,0 +1,136 @@ +--------------- +---- Honey ---- +--------------- + +-- Variables +local S = minetest.get_translator(minetest.get_current_modname()) +local alldirs = {{x=0,y=0,z=1}, {x=1,y=0,z=0}, {x=0,y=0,z=-1}, {x=-1,y=0,z=0}, {x=0,y=-1,z=0}, {x=0,y=1,z=0}} + +-- Honeycomb +minetest.register_craftitem("mcl_honey:honeycomb", { + description = S("Honeycomb"), + _doc_items_longdesc = S("Used to craft beehives and protect copper blocks from further oxidation."), + _doc_items_usagehelp = S("Use on copper blocks to prevent further oxidation."), + inventory_image = "mcl_honey_honeycomb.png", + groups = { craftitem = 1 }, +}) + +minetest.register_node("mcl_honey:honeycomb_block", { + description = S("Honeycomb Block"), + _doc_items_longdesc = S("Honeycomb Block. Used as a decoration."), + tiles = { + "mcl_honey_honeycomb_block.png" + }, + groups = { handy = 1, deco_block = 1 }, + _mcl_blast_resistance = 0.6, + _mcl_hardness = 0.6, +}) + +-- Honey +minetest.register_craftitem("mcl_honey:honey_bottle", { + description = S("Honey Bottle"), + _doc_items_longdesc = S("Honey Bottle is used to craft honey blocks and to restore hunger points."), + _doc_items_usagehelp = S("Drinking will restore 6 hunger points. Can also be used to craft honey blocks."), + inventory_image = "mcl_honey_honey_bottle.png", + groups = { craftitem = 1, food = 3, eatable = 6, can_eat_when_full=1 }, + on_place = minetest.item_eat(6, "mcl_potions:glass_bottle"), + on_secondary_use = minetest.item_eat(6, "mcl_potions:glass_bottle"), + _mcl_saturation = 1.2, + stack_max = 16, +}) + +minetest.register_node("mcl_honey:honey_block", { + description = S("Honey Block"), + _doc_items_longdesc = S("Honey Block. Used as a decoration and in redstone. Is sticky on some sides."), + tiles = {"mcl_honey_block_side.png"}, + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "blend" or true, + groups = { handy = 1, deco_block = 1, fall_damage_add_percent = -80 }, + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.4, -0.4, -0.4, 0.4, 0.4, 0.4}, + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + } + }, + selection_box = { + type = "regular", + }, + _mcl_blast_resistance = 0, + _mcl_hardness = 0, + mvps_sticky = function(pos, node, piston_pos) + local connected = {} + for n, v in ipairs(alldirs) do + local neighbor_pos = vector.add(pos, v) + local neighbor_node = minetest.get_node(neighbor_pos) + if neighbor_node then + if neighbor_node.name == "ignore" then + minetest.get_voxel_manip():read_from_map(neighbor_pos, neighbor_pos) + neighbor_node = minetest.get_node(neighbor_pos) + end + local name = neighbor_node.name + if name ~= "air" and name ~= "ignore" and not mesecon.mvps_unsticky[name] then + local piston, piston_side, piston_up, piston_down = false, false, false, false + if name == "mesecons_pistons:piston_sticky_off" or name == "mesecons_pistons:piston_normal_off" then + piston, piston_side = true, true + elseif name == "mesecons_pistons:piston_up_sticky_off" or name == "mesecons_pistons:piston_up_normal_off" then + piston, piston_up = true, true + elseif name == "mesecons_pistons:piston_down_sticky_off" or name == "mesecons_pistons:piston_down_normal_off" then + piston, piston_down = true, true + end + if not( (piston_side and (n-1==neighbor_node.param2)) or (piston_up and (n==5)) or (piston_down and (n==6)) ) then + if piston and piston_pos then + if piston_pos.x == neighbor_pos.x and piston_pos.y == neighbor_pos.y and piston_pos.z == neighbor_pos.z then + -- Loopback to the same piston! Preventing unwanted behavior: + return {}, true + end + end + table.insert(connected, neighbor_pos) + end + end + end + end + return connected, false + end, +}) + +-- Crafting +minetest.register_craft({ + output = "mcl_honey:honeycomb_block", + recipe = { + { "mcl_honey:honeycomb", "mcl_honey:honeycomb" }, + { "mcl_honey:honeycomb", "mcl_honey:honeycomb" }, + }, +}) + +minetest.register_craft({ + output = "mcl_honey:honey_block", + recipe = { + { "mcl_honey:honey_bottle", "mcl_honey:honey_bottle" }, + { "mcl_honey:honey_bottle", "mcl_honey:honey_bottle" }, + }, + replacements = { + { "mcl_honey:honey_bottle", "mcl_potions:glass_bottle" }, + { "mcl_honey:honey_bottle", "mcl_potions:glass_bottle" }, + { "mcl_honey:honey_bottle", "mcl_potions:glass_bottle" }, + { "mcl_honey:honey_bottle", "mcl_potions:glass_bottle" }, + }, +}) + +minetest.register_craft({ + output = "mcl_honey:honey_bottle 4", + recipe = { + { "mcl_potions:glass_bottle", "mcl_potions:glass_bottle", "mcl_honey:honey_block" }, + { "mcl_potions:glass_bottle", "mcl_potions:glass_bottle", "" }, + }, +}) + +minetest.register_craft({ + type = "shapeless", + output = "mcl_core:sugar 3", + recipe = { "mcl_honey:honey_bottle" }, + replacements = { + { "mcl_honey:honey_bottle", "mcl_potions:glass_bottle" }, + }, +}) diff --git a/mods/ITEMS/mcl_honey/locale/template.txt b/mods/ITEMS/mcl_honey/locale/template.txt new file mode 100644 index 000000000..a9814d617 --- /dev/null +++ b/mods/ITEMS/mcl_honey/locale/template.txt @@ -0,0 +1,10 @@ +Honeycomb= +Used to craft beehives and protect copper blocks from further oxidation.= +Use on copper blocks to prevent further oxidation.= +Honeycomb Block= +Honeycomb Block. Used as a decoration.= +Honey Bottle= +Honey Bottle is used to craft honey blocks and to restore hunger points.= +Drinking will restore 6 hunger points. Can also be used to craft honey blocks.= +Honey Block= +Honey Block. Used as a decoration and in redstone. Is sticky on some sides.= \ No newline at end of file diff --git a/mods/ITEMS/mcl_honey/mod.conf b/mods/ITEMS/mcl_honey/mod.conf new file mode 100644 index 000000000..436811291 --- /dev/null +++ b/mods/ITEMS/mcl_honey/mod.conf @@ -0,0 +1,4 @@ +name = mcl_honey +author = PrairieWind +description = MineClone 2 mod that adds honey and honeycomb and the respective block versions. +depends = mesecons_mvps diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_block_bottom.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_bottom.png new file mode 100644 index 000000000..9de965284 Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_bottom.png differ diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_block_side.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_side.png new file mode 100644 index 000000000..4cdecfb03 Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_side.png differ diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_block_top.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_top.png new file mode 100644 index 000000000..c2f330440 Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_block_top.png differ diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_honey_bottle.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_honey_bottle.png new file mode 100644 index 000000000..16956f56e Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_honey_bottle.png differ diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb.png new file mode 100644 index 000000000..a590d517a Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb.png differ diff --git a/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb_block.png b/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb_block.png new file mode 100644 index 000000000..42c4ce85e Binary files /dev/null and b/mods/ITEMS/mcl_honey/textures/mcl_honey_honeycomb_block.png differ diff --git a/mods/ITEMS/mcl_hoppers/init.lua b/mods/ITEMS/mcl_hoppers/init.lua index 87831490f..c204071a9 100644 --- a/mods/ITEMS/mcl_hoppers/init.lua +++ b/mods/ITEMS/mcl_hoppers/init.lua @@ -1,5 +1,12 @@ local S = minetest.get_translator(minetest.get_current_modname()) +local LOGGING_ON = minetest.settings:get_bool("mcl_logging_hoppers",false) +local function mcl_log (message) + if LOGGING_ON then + mcl_util.mcl_log (message, "[Hoppers]", true) + end +end + --[[ BEGIN OF NODE DEFINITIONS ]] local mcl_hoppers_formspec = @@ -331,8 +338,94 @@ minetest.register_node("mcl_hoppers:hopper_side_disabled", def_hopper_side_disab --[[ END OF NODE DEFINITIONS ]] +local function hopper_pull_from_mc (mc_ent, dest_pos, inv_size) + local inv = mcl_entity_invs.load_inv(mc_ent, inv_size) + if not inv then + mcl_log("No inv") + return false + end + + local dest_meta = minetest.get_meta(dest_pos) + local dest_inv = dest_meta:get_inventory() + if not dest_inv then + mcl_log("No dest inv") + return + end + + mcl_log("inv. size: " .. mc_ent._inv_size) + for i = 1, mc_ent._inv_size,1 do + local stack = inv:get_stack("main", i) + + mcl_log("i: " .. tostring(i)) + mcl_log("Name: [" .. tostring(stack:get_name()) .. "]") + mcl_log("Count: " .. tostring(stack:get_count())) + mcl_log("stack max: " .. tostring(stack:get_stack_max())) + + if not stack:get_name() or stack:get_name() ~= "" then + if dest_inv:room_for_item("main", stack:peek_item()) then + mcl_log("Room so unload") + dest_inv:add_item("main", stack:take_item()) + inv:set_stack("main", i, stack) + + -- Take one item and stop until next time + return + else + mcl_log("no Room") + end + + else + mcl_log("nothing there") + end + end +end + --[[ BEGIN OF ABM DEFINITONS ]] +minetest.register_abm({ + label = "Hoppers pull from minecart", + nodenames = {"mcl_hoppers:hopper","mcl_hoppers:hopper_side"}, + interval = 0.5, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + mcl_log("ABM for: " .. minetest.pos_to_string(pos)) + local objs = minetest.get_objects_inside_radius(pos, 3) + + if objs and #objs > 0 then + for k,v in pairs(objs) do + local entity = v:get_luaentity() + if entity and entity.name then + --mcl_log("Name of object near: " .. tostring(entity.name)) + + if entity.name == "mcl_minecarts:hopper_minecart" or entity.name == "mcl_minecarts:chest_minecart"then + local hm_pos = entity.object:get_pos() + mcl_log("We have a minecart with inventory close: ".. minetest.pos_to_string(hm_pos)) + + --if hm_pos.y == pos.y + 1 then mcl_log("y is correct") end + --if (hm_pos.x >= pos.x - DIST_FROM_MC and hm_pos.x <= pos.x + DIST_FROM_MC) then mcl_log("x is within range") end + --if (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then mcl_log("z is within range") end + + local DIST_FROM_MC = 1.5 + if (hm_pos.y == pos.y + 1) + and (hm_pos.x >= pos.x - DIST_FROM_MC and hm_pos.x <= pos.x + DIST_FROM_MC) + and (hm_pos.z >= pos.z - DIST_FROM_MC and hm_pos.z <= pos.z + DIST_FROM_MC) then + mcl_log("Minecart close enough") + if entity.name == "mcl_minecarts:hopper_minecart" then + hopper_pull_from_mc(entity, pos, 5) + elseif entity.name == "mcl_minecarts:chest_minecart" then + hopper_pull_from_mc(entity, pos, 27) + end + end + end + else + mcl_log("no entity") + end + end + else + mcl_log("objs missing") + end + end, +}) + -- Make hoppers suck in dropped items minetest.register_abm({ label = "Hoppers suck in dropped items", @@ -469,6 +562,103 @@ minetest.register_abm({ end }) +minetest.register_abm({ + label = "Bonemeal extraction from composter", + nodenames = {"mcl_hoppers:hopper", "mcl_hoppers:hopper_side"}, + neighbors = {"mcl_composters:composter_ready"}, + interval = 1.0, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local uppos = {x=pos.x,y=pos.y+1,z=pos.z} + local downpos = {x=pos.x,y=pos.y-1,z=pos.z} + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + -- Get bonemeal from composter above + local upnode = minetest.get_node(uppos) + if upnode.name == "mcl_composters:composter_ready" then + minetest.swap_node(uppos, {name="mcl_composters:composter"}) + inv:add_item("main", "mcl_dye:white") + end + end, +}) + +minetest.register_abm({ + label = "Add compostable items on composter", + nodenames = {"mcl_hoppers:hopper"}, + neighbors = {"mcl_composters:composter", "mcl_composters:composter_1", "mcl_composters:composter_2", + "mcl_composters:composter_3", "mcl_composters:composter_4", "mcl_composters:composter_5", + "mcl_composters:composter_6", "mcl_composters:composter_7",}, + interval = 1.0, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local uppos = {x=pos.x,y=pos.y+1,z=pos.z} + local downpos = {x=pos.x,y=pos.y-1,z=pos.z} + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + --Consume compostable items and update composter below + local downnode = minetest.get_node(downpos) + if downnode.name == "mcl_composters:composter" or downnode.name == "mcl_composters:composter_1" + or downnode.name == "mcl_composters:composter_2" or downnode.name == "mcl_composters:composter_3" + or downnode.name == "mcl_composters:composter_4" or downnode.name == "mcl_composters:composter_5" + or downnode.name == "mcl_composters:composter_6" or downnode.name == "mcl_composters:composter_7" then + local itemcomp = inv:get_list("main") + local hslot = mcl_util.get_first_occupied_inventory_slot(minetest.get_inventory({type="node", pos = pos}), "main") + if hslot == nil then return end + local compchance = minetest.get_item_group(itemcomp[hslot]:get_name(), "compostability") + if compchance == 0 then + hslot = hslot+1 + if hslot == 6 then return end + compchance = minetest.get_item_group(itemcomp[hslot]:get_name(), "compostability") + if compchance == 0 then + hslot = hslot+1 + if hslot == 6 then return end + compchance = minetest.get_item_group(itemcomp[hslot]:get_name(), "compostability") + if compchance == 0 then + hslot = hslot+1 + if hslot == 6 then return end + compchance = minetest.get_item_group(itemcomp[hslot]:get_name(), "compostability") + if compchance == 0 then + hslot = hslot+1 + if hslot == 6 then return end + compchance = minetest.get_item_group(itemcomp[hslot]:get_name(), "compostability") + end + end + end + end + if compchance > 0 then + itemcomp[hslot]:take_item() + inv:set_list("main", itemcomp) + local rand = math.random(0,100) + if compchance >= rand then + local level = 0 + if downnode.name == "mcl_composters:composter_1" then + level = 1 + elseif downnode.name == "mcl_composters:composter_2" then + level = 2 + elseif downnode.name == "mcl_composters:composter_3" then + level = 3 + elseif downnode.name == "mcl_composters:composter_4" then + level = 4 + elseif downnode.name == "mcl_composters:composter_5" then + level = 5 + elseif downnode.name == "mcl_composters:composter_6" then + level = 6 + elseif downnode.name == "mcl_composters:composter_7" then + level = 7 + end + mcl_dye.add_bone_meal_particle(vector.offset(downpos, 0, level/8, 0)) + if level < 7 then + level = level + 1 + else + level = "ready" + end + minetest.swap_node(downpos, {name="mcl_composters:composter_" .. level}) + end + end + end + end, +}) + minetest.register_craft({ output = "mcl_hoppers:hopper", recipe = { diff --git a/mods/ITEMS/mcl_itemframes/README.txt b/mods/ITEMS/mcl_itemframes/README.txt index d9514a03b..c2756a1c9 100644 --- a/mods/ITEMS/mcl_itemframes/README.txt +++ b/mods/ITEMS/mcl_itemframes/README.txt @@ -1,4 +1,13 @@ -This mod is originally by Zeg9, but heavily modified for MineClone 2. +This mod has been rewritten and revamped by Michieal / Faerraven. Based on the code originally done by Zeg9, and then +heavily modified by the Mineclone 2 dev team. + +This mod now supports all the base item frame functions, like rotating the displayed item, which it didn't do before it +was rewritten. Additionally, Glow Frames have been added in, and item frames now has an API to allow new item frames to +be created in other modules. +Now requires the Screwdriver to have full functionality. + +The code is licenced under the standard MineClone 2 license for usage, with the requirement that this readme is +included in the code / module. Model created by 22i, licensed under the GNU GPLv3 . diff --git a/mods/ITEMS/mcl_itemframes/init.lua b/mods/ITEMS/mcl_itemframes/init.lua index 6fda0176e..553198c67 100644 --- a/mods/ITEMS/mcl_itemframes/init.lua +++ b/mods/ITEMS/mcl_itemframes/init.lua @@ -1,348 +1,40 @@ -mcl_itemframes = {} +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + local S = minetest.get_translator(minetest.get_current_modname()) -local VISUAL_SIZE = 0.3 +-- mcl_itemframes API +dofile(modpath .. "/item_frames_API.lua") -minetest.register_entity("mcl_itemframes:item",{ - hp_max = 1, - visual = "wielditem", - visual_size = {x=VISUAL_SIZE, y=VISUAL_SIZE}, - physical = false, - pointable = false, - textures = { "blank.png" }, - _texture = "blank.png", - _scale = 1, +-- actual api initialization. +mcl_itemframes.create_base_definitions() - on_activate = function(self, staticdata) - if staticdata and staticdata ~= "" then - local data = staticdata:split(";") - if data and data[1] and data[2] then - self._nodename = data[1] - self._texture = data[2] - if data[3] then - self._scale = data[3] - else - self._scale = 1 - end - end - end - if self._texture then - self.object:set_properties({ - textures={self._texture}, - visual_size={x=VISUAL_SIZE/self._scale, y=VISUAL_SIZE/self._scale}, - }) - end - end, - get_staticdata = function(self) - if self._nodename and self._texture then - local ret = self._nodename .. ";" .. self._texture - if self._scale then - ret = ret .. ";" .. self._scale - end - return ret - end - return "" - end, +-- necessary to maintain compatibility amongst older versions. +mcl_itemframes.backwards_compatibility() - _update_texture = function(self) - if self._texture then - self.object:set_properties({ - textures={self._texture}, - visual_size={x=VISUAL_SIZE/self._scale, y=VISUAL_SIZE/self._scale}, - }) - end - end, -}) - -minetest.register_entity("mcl_itemframes:map", { - initial_properties = { - visual = "upright_sprite", - visual_size = {x = 1, y = 1}, - pointable = false, - physical = false, - collide_with_objects = false, - textures = {"blank.png"}, - }, - on_activate = function(self, staticdata) - self.id = staticdata - mcl_maps.load_map(self.id, function(texture) - -- will not crash even if self.object is invalid by now - self.object:set_properties({textures = {texture}}) - end) - end, - get_staticdata = function(self) - return self.id - end, -}) - - -local facedir = {} -facedir[0] = {x=0,y=0,z=1} -facedir[1] = {x=1,y=0,z=0} -facedir[2] = {x=0,y=0,z=-1} -facedir[3] = {x=-1,y=0,z=0} - -local remove_item_entity = function(pos, node) - if node.name == "mcl_itemframes:item_frame" then - for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do - local entity = obj:get_luaentity() - if entity and (entity.name == "mcl_itemframes:item" or entity.name == "mcl_itemframes:map") then - obj:remove() - end - end - end -end - -local update_item_entity = function(pos, node, param2) - remove_item_entity(pos, node) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - local item = inv:get_stack("main", 1) - if not item:is_empty() then - if not param2 then - param2 = node.param2 - end - if node.name == "mcl_itemframes:item_frame" then - local posad = facedir[param2] - pos.x = pos.x + posad.x*6.5/16 - pos.y = pos.y + posad.y*6.5/16 - pos.z = pos.z + posad.z*6.5/16 - end - local yaw = math.pi*2 - param2 * math.pi/2 - local map_id = item:get_meta():get_string("mcl_maps:id") - if map_id == "" then - local e = minetest.add_entity(pos, "mcl_itemframes:item") - local lua = e:get_luaentity() - lua._nodename = node.name - local itemname = item:get_name() - if itemname == "" or itemname == nil then - lua._texture = "blank.png" - lua._scale = 1 - else - lua._texture = itemname - local def = minetest.registered_items[itemname] - lua._scale = def and def.wield_scale and def.wield_scale.x or 1 - end - lua:_update_texture() - if node.name == "mcl_itemframes:item_frame" then - e:set_yaw(yaw) - end - else - local e = minetest.add_entity(pos, "mcl_itemframes:map", map_id) - e:set_yaw(yaw) - end - end -end -mcl_itemframes.update_item_entity = update_item_entity - -local drop_item = function(pos, node, meta, clicker) - local cname = "" - if clicker and clicker:is_player() then - cname = clicker:get_player_name() - end - if node.name == "mcl_itemframes:item_frame" and not minetest.is_creative_enabled(cname) then - local inv = meta:get_inventory() - local item = inv:get_stack("main", 1) - if not item:is_empty() then - minetest.add_item(pos, item) - end - end - meta:set_string("infotext", "") - remove_item_entity(pos, node) -end - -minetest.register_node("mcl_itemframes:item_frame",{ - description = S("Item Frame"), - _tt_help = S("Can hold an item"), - _doc_items_longdesc = S("Item frames are decorative blocks in which items can be placed."), - _doc_items_usagehelp = S("Just place any item on the item frame. Use the item frame again to retrieve the item."), - drawtype = "mesh", - is_ground_content = false, - mesh = "mcl_itemframes_itemframe1facedir.obj", - selection_box = { type = "fixed", fixed = {-6/16, -6/16, 7/16, 6/16, 6/16, 0.5} }, - collision_box = { type = "fixed", fixed = {-6/16, -6/16, 7/16, 6/16, 6/16, 0.5} }, - tiles = {"mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "mcl_itemframes_itemframe_background.png", "default_wood.png", "mcl_itemframes_itemframe_background.png"}, - inventory_image = "mcl_itemframes_item_frame.png", - wield_image = "mcl_itemframes_item_frame.png", - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - groups = { dig_immediate=3,deco_block=1,dig_by_piston=1,container=7,attached_node_facedir=1 }, - sounds = mcl_sounds.node_sound_defaults(), - node_placement_prediction = "", - on_timer = function(pos) - local inv = minetest.get_meta(pos):get_inventory() - local stack = inv:get_stack("main", 1) - local itemname = stack:get_name() - if minetest.get_item_group(itemname, "clock") > 0 then - local new_name = "mcl_clock:clock_" .. (mcl_worlds.clock_works(pos) and mcl_clock.old_time or mcl_clock.random_frame) - if itemname ~= new_name then - stack:set_name(new_name) - inv:set_stack("main", 1, stack) - local node = minetest.get_node(pos) - update_item_entity(pos, node, node.param2) - end - minetest.get_node_timer(pos):start(1.0) - end - end, - on_place = function(itemstack, placer, pointed_thing) - if pointed_thing.type ~= "node" then - return itemstack - end - - -- Use pointed node's on_rightclick function first, if present - local node = minetest.get_node(pointed_thing.under) - if placer and not placer:get_player_control().sneak then - if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then - return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack - end - end - - return minetest.item_place(itemstack, placer, pointed_thing, minetest.dir_to_facedir(vector.direction(pointed_thing.above, pointed_thing.under))) - end, - on_construct = function(pos) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - inv:set_size("main", 1) - end, - on_rightclick = function(pos, node, clicker, itemstack) - if not itemstack then - return - end - local pname = clicker:get_player_name() - if minetest.is_protected(pos, pname) then - minetest.record_protection_violation(pos, pname) - return - end - local meta = minetest.get_meta(pos) - drop_item(pos, node, meta, clicker) - local inv = meta:get_inventory() - if itemstack:is_empty() then - remove_item_entity(pos, node) - meta:set_string("infotext", "") - inv:set_stack("main", 1, "") - return itemstack - end - local put_itemstack = ItemStack(itemstack) - put_itemstack:set_count(1) - local itemname = put_itemstack:get_name() - if minetest.get_item_group(itemname, "compass") > 0 then - put_itemstack:set_name(mcl_compass.get_compass_itemname(pos, minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2)), put_itemstack)) - end - if minetest.get_item_group(itemname, "clock") > 0 then - minetest.get_node_timer(pos):start(1.0) - end - inv:set_stack("main", 1, put_itemstack) - update_item_entity(pos, node) - -- Add node infotext when item has been named - local imeta = itemstack:get_meta() - local iname = imeta:get_string("name") - if iname then - meta:set_string("infotext", iname) - end - - if not minetest.is_creative_enabled(clicker:get_player_name()) then - itemstack:take_item() - end - return itemstack - end, - allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) - local name = player:get_player_name() - if minetest.is_protected(pos, name) then - minetest.record_protection_violation(pos, name) - return 0 - else - return count - end - end, - allow_metadata_inventory_take = function(pos, listname, index, stack, player) - local name = player:get_player_name() - if minetest.is_protected(pos, name) then - minetest.record_protection_violation(pos, name) - return 0 - else - return stack:get_count() - end - end, - allow_metadata_inventory_put = function(pos, listname, index, stack, player) - local name = player:get_player_name() - if minetest.is_protected(pos, name) then - minetest.record_protection_violation(pos, name) - return 0 - else - return stack:get_count() - end - end, - on_destruct = function(pos) - local meta = minetest.get_meta(pos) - local node = minetest.get_node(pos) - drop_item(pos, node, meta) - end, - on_rotate = function(pos, node, user, mode, param2) - if mode == screwdriver.ROTATE_FACE then - -- Rotate face - --local meta = minetest.get_meta(pos) - local node = minetest.get_node(pos) - - local objs = nil - if node.name == "mcl_itemframes:item_frame" then - objs = minetest.get_objects_inside_radius(pos, 0.5) - end - if objs then - for _, obj in ipairs(objs) do - if obj and obj:get_luaentity() and obj:get_luaentity().name == "mcl_itemframes:item" then - update_item_entity(pos, node, (node.param2+1) % 4) - break - end - end - end - return - elseif mode == screwdriver.ROTATE_AXIS then - return false - end - end, -}) +-- Define the standard frames. +mcl_itemframes.create_custom_frame("false", "item_frame", false, + "mcl_itemframes_item_frame.png", mcl_colors.WHITE, "Can hold an item.", + "Item Frame", "") +mcl_itemframes.create_custom_frame("false", "glow_item_frame", true, + "mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, "Can hold an item and glows.", + "Glowing Item Frame", "") +-- Register the base frame's recipes. +-- was going to make it a specialized function, but minetest refuses to play nice. minetest.register_craft({ output = "mcl_itemframes:item_frame", recipe = { - {"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"}, - {"mcl_core:stick", "mcl_mobitems:leather", "mcl_core:stick"}, - {"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"}, + { "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" }, + { "mcl_core:stick", "mcl_mobitems:leather", "mcl_core:stick" }, + { "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" }, } }) -minetest.register_lbm({ - label = "Update legacy item frames", - name = "mcl_itemframes:update_legacy_item_frames", - nodenames = {"itemframes:frame"}, - action = function(pos, node) - -- Swap legacy node, then respawn entity - node.name = "mcl_itemframes:item_frame" - local meta = minetest.get_meta(pos) - local item = meta:get_string("item") - minetest.swap_node(pos, node) - if item ~= "" then - local itemstack = ItemStack(minetest.deserialize(meta:get_string("itemdata"))) - local inv = meta:get_inventory() - inv:set_size("main", 1) - if not itemstack:is_empty() then - inv:set_stack("main", 1, itemstack) - end - end - update_item_entity(pos, node) - end, +minetest.register_craft({ + type = "shapeless", + output = 'mcl_itemframes:glow_item_frame', + recipe = { 'mcl_mobitems:glow_ink_sac', 'mcl_itemframes:item_frame' }, }) --- FIXME: Item entities can get destroyed by /clearobjects -minetest.register_lbm({ - label = "Respawn item frame item entities", - name = "mcl_itemframes:respawn_entities", - nodenames = {"mcl_itemframes:item_frame"}, - run_at_every_load = true, - action = function(pos, node) - update_item_entity(pos, node) - end, -}) - -minetest.register_alias("itemframes:frame", "mcl_itemframes:item_frame") +mcl_itemframes.custom_register_lbm() diff --git a/mods/ITEMS/mcl_itemframes/item_frames_API.lua b/mods/ITEMS/mcl_itemframes/item_frames_API.lua new file mode 100644 index 000000000..231482800 --- /dev/null +++ b/mods/ITEMS/mcl_itemframes/item_frames_API.lua @@ -0,0 +1,889 @@ +--- +--- Generated by EmmyLua(https://github.com/EmmyLua) +--- Created by michieal. +--- DateTime: 10/26/22 1:16 AM +--- + +mcl_itemframes = {} +mcl_itemframes.item_frame_base = {} +mcl_itemframes.glow_frame_base = {} +mcl_itemframes.frames_registered = {} +mcl_itemframes.frames_registered.glowing = {} +mcl_itemframes.frames_registered.standard = {} + +-- Set to true to get all of the DEBUG messages. +mcl_itemframes.DEBUG = false + +if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] initialized.") +end + +local S = minetest.get_translator(minetest.get_current_modname()) +local table = table +local pairs = pairs + +if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] API initialized.") +end + +local VISUAL_SIZE = 0.3 +local facedir = {} +local pi = math.pi + +local glow_amount = 6 -- LIGHT_MAX is 15, but the items aren't supposed to be a light source. +local frame_item_base = {} +local map_item_base = {} + +local TIMER_INTERVAL = 40.0 + +-- Time to Fleckenstein! (it just sounds cool lol) + +--- self: the object to roll. +local function update_roll(self, pos) + + -- get the entity's metadata. + local meta = minetest.get_meta(pos) + + -- using an integer, as it's the number of 45 degree turns. ie, 0 to 7 + local current_roll = meta:get_int("roll", 0) + local new_roll = current_roll + 1 + + if new_roll == 8 then + new_roll = 0 + end + meta:set_int("roll", new_roll) + + local new_roll_deg = new_roll * 45 + + -- * `get_rotation()`: returns the rotation, a vector (radians) + local rot = self:get_rotation() + local Radians = 0 + + -- Radians = Degrees * (pi / 180) degrees to radian formula + -- Radian quick chart + -- One full revolution is equal to 2π rad (or) 360°. + -- 1° = 0.017453 radians and 1 rad = 57.2958°. + -- To convert an angle from degrees to radians, we multiply it by π/180°. + -- To convert an angle from radians to degrees, we multiply it by 180°/π. + + Radians = new_roll_deg * (pi / 180) + rot.z = Radians + + self:set_rotation(rot) + +end + +--- self: the object to roll. +--- faceDeg: 0-7, inclusive. +local function set_roll(self, faceDeg) + -- get the entity's metadata. + local meta = minetest.get_meta(self:get_pos()) + + -- using an integer, as it's the number of 45 degree turns. ie, 0 to 7 + local new_roll = faceDeg + + if new_roll >= 8 then + new_roll = 7 + end + if new_roll <= 0 then + new_roll = 0 + end + + meta:set_int("roll", new_roll) + + local new_roll_deg = new_roll * 45 + + -- * `get_rotation()`: returns the rotation, a vector (radians) + local rot = self:get_rotation() + local Radians = 0 + + -- Radians = Degrees * (pi / 180) degrees to radian formula + -- Radian quick chart + -- One full revolution is equal to 2π rad (or) 360°. + -- 1° = 0.017453 radians and 1 rad = 57.2958°. + -- To convert an angle from degrees to radians, we multiply it by π/180°. + -- To convert an angle from radians to degrees, we multiply it by 180°/π. + + Radians = new_roll_deg * (pi / 180) + + rot.z = Radians + + self:set_rotation(rot) +end + +local function update_map_texture (self, staticdata) + self.id = staticdata + local result = true + result = mcl_maps.load_map(self.id, function(texture) + -- will not crash even if self.object is invalid by now + -- update... quite possibly will screw up with each version of Minetest. >.< + if not texture then + minetest.log("error", "Failed to load the map texture using mcl_maps.") + end + + self.object:set_properties({ textures = { texture } }) + end) + if result ~= nil and result == false then + mintest.log("error", "[mcl_itemframes] Error setting up Map Item.") + end + +end + +local remove_item_entity = function(pos, node) + + local name_found = false + local found_name_to_use = "" + + for k, v in pairs(mcl_itemframes.frames_registered.glowing) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + + -- try to cut down on excess looping, if possible. + if name_found == false then + for k, v in pairs(mcl_itemframes.frames_registered.standard) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + end + + if mcl_itemframes.DEBUG then + minetest.log("action", "mcl_itemframes] remove_item_entity: " .. found_name_to_use .. "'s displayed item.") + end + + -- node.name == "mcl_itemframes:item_frame" or node.name == "mcl_itemframes:glow_item_frame" or + if node.name == found_name_to_use then + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do + local entity = obj:get_luaentity() + if entity then + -- remove old entities + if entity.name == "mcl_itemframes:item" or entity.name == "mcl_itemframes:glow_item" or entity.name == "mcl_itemframes:map" or entity.name == "mcl_itemframes:glow_map" then + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local item = inv:get_stack("main", 1) + if not item:is_empty() then + if (node.name == found_name_to_use) then + minetest.add_item(pos, item) + end + meta:set_string("infotext", "") + end + obj:remove() + end + if entity.name == found_name_to_use .. "_item" or entity.name == found_name_to_use .. "_map" then + if mcl_itemframes.DEBUG then + minetest.log("action", "mcl_itemframes] remove_item_entity: " .. entity.name .. "-- the item.") + end + obj:remove() + end + end + end + end +end + +mcl_itemframes.update_item_entity = function(pos, node, param2) + + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] Update_Generic_Item:\nPosition: " .. dump(pos) .. "\nNode: " .. dump(node)) + end + + remove_item_entity(pos, node) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local item = inv:get_stack("main", 1) + + local name_found = false + local found_name_to_use = "" + local has_glow = false + + for k, v in pairs(mcl_itemframes.frames_registered.glowing) do + if node.name == v then + name_found = true + has_glow = true + found_name_to_use = v + break + end + end + + -- try to cut down on excess looping, if possible. + if name_found == false then + for k, v in pairs(mcl_itemframes.frames_registered.standard) do + if node.name == v then + name_found = true + has_glow = false + found_name_to_use = v + break + end + end + end + + if name_found == false then + minetest.log("error", "[mcl_itemframes] Update_Generic_Item:\nFailed to find registered node:\nNode name - " .. node.name) + minetest.log("error", "[mcl_itemframes] Update_Generic_Item:\nRegistry definition:" .. dump(mcl_itemframes.frames_registered)) + return + end + + if not item:is_empty() then + -- update existing items placed. + if not param2 then + param2 = node.param2 + end + local pos_adj = facedir[param2] + + if node.name == found_name_to_use then + pos.x = pos.x + pos_adj.x * 6.5 / 16 + pos.y = pos.y + pos_adj.y * 6.5 / 16 + pos.z = pos.z + pos_adj.z * 6.5 / 16 + + if mcl_itemframes.DEBUG then + minetest.log("[mcl_itemframes] Update_Generic_Item:\nFound Name in Registry: " .. found_name_to_use) + end + end + local yaw = pi * 2 - param2 * pi / 2 + local map_id = item:get_meta():get_string("mcl_maps:id") + local map_id_entity = {} + local map_id_lua = {} + + local timer = minetest.get_node_timer(pos) + if map_id == "" then + -- handle regular items placed into custom frame. + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] Update_Generic_Item:\nAdding entity: " .. node.name .. "_item") + end + + if node.name == found_name_to_use then + map_id_entity = minetest.add_entity(pos, node.name .. "_item") + else + local debug_string = "[mcl_itemframes] Update_Generic_Item:\nCouldn't find node name in registry: " + minetest.log("error", debug_string .. found_name_to_use "\nregistry: " .. dump(mcl_itemframes.frames_registered)) + return + end + + map_id_lua = map_id_entity:get_luaentity() + map_id_lua._nodename = node.name + + local itemname = item:get_name() + if itemname == "" or itemname == nil then + map_id_lua._texture = "blank.png" + map_id_lua._scale = 1 + + -- set up glow, as this is the default/initial clause on placement. + if has_glow then + map_id_lua.glow = glow_amount + end + + -- if there's nothing to display, then kill the timer. + if timer:is_started() == true then + timer:stop() + end + else + map_id_lua._texture = itemname + local def = minetest.registered_items[itemname] + map_id_lua._scale = def and def.wield_scale and def.wield_scale.x or 1 + + -- fix for /ClearObjects + if minetest.get_item_group(itemname, "clock") == 0 then + -- Do timer related stuff - but only if there is something to display... and it's not a clock. + if timer:is_started() == false then + timer:start(TIMER_INTERVAL) + else + timer:stop() + timer:start(TIMER_INTERVAL) + end + end + + end + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] Update_Generic_Item: item's name: " .. itemname) + end + map_id_lua:_update_texture() + if node.name == found_name_to_use then + map_id_entity:set_yaw(yaw) + else + minetest.log("error", "[mcl_itemframes] Update_Generic_Item: Failed to set Display Item's yaw. " .. node.name) + end + else + -- handle map items placed into custom frame. + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] Update_Generic_Item: Placing map in a " .. found_name_to_use .. " frame.") + end + + if node.name == found_name_to_use then + map_id_entity = minetest.add_entity(pos, found_name_to_use .. "_map", map_id) + map_id_entity:set_yaw(yaw) + else + minetest.log("error", "[mcl_itemframes] Update_Generic_Item: Failed to set Map Item in " .. found_name_to_use .. "'s frame.") + end + + -- give maps a refresh timer. + if timer:is_started() == false then + timer:start(TIMER_INTERVAL) + else + timer:stop() + timer:start(TIMER_INTERVAL) + end + + end + + -- finally, set the rotation (roll) of the displayed object. + local roll = meta:get_int("roll", 0) + set_roll(map_id_entity, roll) + end + +end + +function mcl_itemframes.drop_generic_item(pos, node, meta, clicker) + local name_found = false + local found_name_to_use = "" + + for k, v in pairs(mcl_itemframes.frames_registered.glowing) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + + -- try to cut down on excess looping, if possible. + if name_found == false then + for k, v in pairs(mcl_itemframes.frames_registered.standard) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + end + + local cname = "" + if clicker and clicker:is_player() then + cname = clicker:get_player_name() + end + if not minetest.is_creative_enabled(cname) then + if (node.name == found_name_to_use) then + local inv = meta:get_inventory() + local item = inv:get_stack("main", 1) + if not item:is_empty() then + minetest.add_item(pos, item) + end + end + end + + meta:set_string("infotext", "") + remove_item_entity(pos, node) + +end + +--- reworked to set up the base item definitions. +function mcl_itemframes.create_base_item_entity() + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] create_item_entity.") + end + + --"mcl_itemframes:item", + frame_item_base = { + hp_max = 1, + visual = "wielditem", + visual_size = { x = VISUAL_SIZE, y = VISUAL_SIZE }, + physical = false, + pointable = false, + textures = { "blank.png" }, + _texture = "blank.png", + _scale = 1, + groups = { immortal = 1, }, + on_activate = function(self, staticdata) + if staticdata and staticdata ~= "" then + local data = staticdata:split(";") + if data and data[1] and data[2] then + self._nodename = data[1] + self._texture = data[2] + if data[3] then + self._scale = data[3] + else + self._scale = 1 + end + end + end + if self._texture then + self.object:set_properties({ + textures = { self._texture }, + visual_size = { x = VISUAL_SIZE / self._scale, y = VISUAL_SIZE / self._scale }, + }) + end + end, + get_staticdata = function(self) + if self._nodename and self._texture then + local ret = self._nodename .. ";" .. self._texture + if self._scale then + ret = ret .. ";" .. self._scale + end + return ret + end + return "" + end, + on_punch = function() return true end, + _update_texture = function(self) + if self._texture then + self.object:set_properties({ + textures = { self._texture }, + visual_size = { x = VISUAL_SIZE / self._scale, y = VISUAL_SIZE / self._scale }, + }) + end + end, + } + -- "mcl_itemframes:map", + map_item_base = { + initial_properties = { + visual = "upright_sprite", + visual_size = { x = 1, y = 1 }, + pointable = false, + physical = false, + collide_with_objects = false, + textures = { "blank.png" }, + }, + on_activate = function(self, staticdata) + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] map_item:on_activate.") + end + update_map_texture(self, staticdata) + end, + + get_staticdata = function(self) + return self.id + end, + } + +end + +function mcl_itemframes.create_custom_items(name, has_glow) + local custom_frame_item = table.copy(frame_item_base) + local custom_frame_map_item = table.copy(map_item_base) + if has_glow then + custom_frame_map_item.glow = glow_amount + custom_frame_item.glow = glow_amount + if mcl_itemframes.DEBUG then + minetest.log("action", "\n[mcl_itemframes] create_custom_item_entity: glow name: " .. name .. "_item") + minetest.log("action", "[mcl_itemframes] create_custom_item_entity: glow name: " .. name .. "_map\n") + end + else + if mcl_itemframes.DEBUG then + minetest.log("action", "\n[mcl_itemframes] create_custom_item_entity: name: " .. name .. "_item") + minetest.log("action", "[mcl_itemframes] create_custom_item_entity: name: " .. name .. "_map\n") + end + end + minetest.register_entity(":" .. name .. "_item", custom_frame_item) + minetest.register_entity(":" .. name .. "_map", custom_frame_map_item) +end + +function mcl_itemframes.update_frame_registry(modname, name, has_glow) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + + local frame = name -- should only be called within the create_frames functions. + if has_glow == true then + table.insert(mcl_itemframes.frames_registered.glowing, frame) + else + table.insert(mcl_itemframes.frames_registered.standard, frame) + end + +end + +--- name: The name used to distinguish the item frame. Prepends "mcl_itemframes:" to the name. Example usage: +--- "glow_item_frame" creates a node named ":mcl_itemframes:glow_item_frame". +function mcl_itemframes.create_custom_frame(modname, name, has_glow, tiles, color, ttframe, description, inv_wield_image) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + if name == nil then + name = "" + end + + if name == "" then + minetest.log("error", "attempted to create an item frame WITHOUT a name!") + return + end + + if has_glow == nil or has_glow == "" then + has_glow = false + end + + if tiles == nil or tiles == "" then + minetest.log("error", "No textures passed to Create_Custom_Frame!! Exiting frame creation.") + return + end + + local working_name = "mcl_itemframes:" .. name + + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] create_custom_frame: " .. working_name) + minetest.log("action", "[mcl_itemframes] create_custom_frame - calling create_custom_items " .. working_name) + end + + -- make any special frame items. + mcl_itemframes.create_custom_items(working_name, has_glow) + + local custom_itemframe_definition = {} + + if has_glow == false then + custom_itemframe_definition = table.copy(mcl_itemframes.item_frame_base) + else + custom_itemframe_definition = table.copy(mcl_itemframes.glow_frame_base) + end + + if inv_wield_image ~= nil and inv_wield_image ~= "" then + custom_itemframe_definition.glow_frame_base.inventory_image = { "(" .. inv_wield_image .. "^[multiply:" .. color .. ")" } + custom_itemframe_definition.glow_frame_base.wield_image = { "(" .. inv_wield_image .. "^[multiply:" .. color .. ")" } + end + + custom_itemframe_definition.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + custom_itemframe_definition._tt_help = ttframe + custom_itemframe_definition.description = description + + minetest.register_node(":" .. working_name, custom_itemframe_definition) + + mcl_itemframes.update_frame_registry(modname, working_name, has_glow) + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mcl_itemframes:item_frame", "nodes", working_name) + end + +end + +function mcl_itemframes.custom_register_lbm() + + local registered_frame_nodenames = {} + + for i = 0, #mcl_itemframes.frames_registered.glowing do + table.insert(registered_frame_nodenames, mcl_itemframes.frames_registered.glowing[i]) + end + + for i = 0, #mcl_itemframes.frames_registered.standard do + table.insert(registered_frame_nodenames, mcl_itemframes.frames_registered.standard[i]) + end + + minetest.register_lbm({ + label = "Respawn item frame item entities", + name = "mcl_itemframes:respawn_entities", + nodenames = registered_frame_nodenames, + run_at_every_load = true, + action = function(pos, node) + mcl_itemframes.update_item_entity(pos, node) + end, + }) + +end + +local function register_frame_achievements() + + awards.register_achievement("mcl_itemframes:glowframe", { + title = S("Glow and Behold!"), + description = S("Craft a glow item frame."), + icon = "mcl_itemframes_glow_item_frame.png", + trigger = { + type = "craft", + item = "mcl_itemframes:glow_item_frame", + target = 1 + }, + type = "Advancement", + group = "Overworld", + }) + +end + +function mcl_itemframes.create_base_definitions() + if mcl_itemframes.DEBUG then + minetest.log("action", "[mcl_itemframes] create_base_definitions.") + end + + -- set up the facedir information. + facedir[0] = { x = 0, y = 0, z = 1 } + facedir[1] = { x = 1, y = 0, z = 0 } + facedir[2] = { x = 0, y = 0, z = -1 } + facedir[3] = { x = -1, y = 0, z = 0 } + + mcl_itemframes.item_frame_base = { + description = S("Item Frame"), + name = "mcl_itemframes:item_frame", + _tt_help = S("Can hold an item"), + _doc_items_longdesc = S("Item frames are decorative blocks in which items can be placed."), + _doc_items_usagehelp = S("Just place any item on the item frame. Use the item frame again to retrieve the item."), + drawtype = "mesh", + is_ground_content = false, + mesh = "mcl_itemframes_itemframe1facedir.obj", + selection_box = { type = "fixed", fixed = { -6 / 16, -6 / 16, 7 / 16, 6 / 16, 6 / 16, 0.5 } }, + collision_box = { type = "fixed", fixed = { -6 / 16, -6 / 16, 7 / 16, 6 / 16, 6 / 16, 0.5 } }, + tiles = { "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "mcl_itemframes_item_frame_back.png", "default_wood.png", "mcl_itemframes_item_frame_back.png" }, + inventory_image = "mcl_itemframes_item_frame.png", + wield_image = "mcl_itemframes_item_frame.png", + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + groups = { dig_immediate = 3, deco_block = 1, dig_by_piston = 1, container = 7, }, -- attached_node_facedir = 1 }, -- allows for more placement options. + sounds = mcl_sounds.node_sound_defaults(), + node_placement_prediction = "", + + on_timer = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + local stack = inv:get_stack("main", 1) + local itemname = stack:get_name() + local node = {} + if minetest.get_item_group(itemname, "clock") > 0 then + local new_name = "mcl_clock:clock_" .. (mcl_worlds.clock_works(pos) and mcl_clock.old_time or mcl_clock.random_frame) + if itemname ~= new_name then + stack:set_name(new_name) + inv:set_stack("main", 1, stack) + node = minetest.get_node(pos) + mcl_itemframes.update_item_entity(pos, node, node.param2) + end + minetest.get_node_timer(pos):start(1.0) + else + node = minetest.get_node(pos) + mcl_itemframes.update_item_entity(pos, node, node.param2) + end + end, + + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local dir = vector.subtract(pointed_thing.under, pointed_thing.above) + local wdir = minetest.dir_to_wallmounted(dir) + + -- remove bottom and top of objects. + if wdir == 0 or wdir == 1 then + return itemstack + end + + -- Use pointed node's on_rightclick function first, if present + local node = minetest.get_node(pointed_thing.under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack + end + end + + return minetest.item_place(itemstack, placer, pointed_thing, minetest.dir_to_facedir(vector.direction(pointed_thing.above, pointed_thing.under))) + end, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("main", 1) + end, + + on_rightclick = function(pos, node, clicker, itemstack) + if not itemstack then + return + end + local pname = clicker:get_player_name() + if minetest.is_protected(pos, pname) then + minetest.record_protection_violation(pos, pname) + return + end + local meta = minetest.get_meta(pos) + mcl_itemframes.drop_generic_item(pos, node, meta, clicker) + + local inv = meta:get_inventory() + if itemstack:is_empty() then + remove_item_entity(pos, node) + meta:set_string("infotext", "") + inv:set_stack("main", 1, "") + return itemstack + end + local put_itemstack = ItemStack(itemstack) + put_itemstack:set_count(1) + local itemname = put_itemstack:get_name() + if minetest.get_item_group(itemname, "compass") > 0 then + put_itemstack:set_name(mcl_compass.get_compass_itemname(pos, minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2)), put_itemstack)) + end + if minetest.get_item_group(itemname, "clock") > 0 then + minetest.get_node_timer(pos):start(1.0) + end + + inv:set_stack("main", 1, put_itemstack) + mcl_itemframes.update_item_entity(pos, node) + + -- Add node infotext when item has been named + local imeta = itemstack:get_meta() + local iname = imeta:get_string("name") + if iname then + meta:set_string("infotext", iname) + end + + if not minetest.is_creative_enabled(clicker:get_player_name()) then + itemstack:take_item() + end + return itemstack + end, + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + else + return count + end + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + else + return stack:get_count() + end + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + else + return stack:get_count() + end + end, + + on_destruct = function(pos) + local meta = minetest.get_meta(pos) + local node = minetest.get_node(pos) + + mcl_itemframes.drop_generic_item(pos, node, meta) + + end, + + on_rotate = function(pos, node, user, mode, param2) + --local meta = minetest.get_meta(pos) + local node = minetest.get_node(pos) + + local objs = nil + local name_found = false + local found_name_to_use = "" + name_found = false + found_name_to_use = "" + + for k, v in pairs(mcl_itemframes.frames_registered.glowing) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + + -- try to cut down on excess looping, if possible. + if name_found == false then + for k, v in pairs(mcl_itemframes.frames_registered.standard) do + if node.name == v then + name_found = true + found_name_to_use = v + break + end + end + end + + if node.name == found_name_to_use then + objs = minetest.get_objects_inside_radius(pos, 0.5) + else + return -- short circuit if it's somehow not the right thing. + end + + if objs then + if mode == screwdriver.ROTATE_FACE or mode == screwdriver.ROTATE_AXIS then + for _, obj in ipairs(objs) do + if obj and obj:get_luaentity() then + local obj_name = obj:get_luaentity().name + if obj_name == found_name_to_use .. "_item" then + if mode == screwdriver.ROTATE_AXIS then + update_roll(obj, pos) + end + break + end + end + end + return false + end + end + end, + } + + -- make the base items for the base frames. + mcl_itemframes.create_base_item_entity() + + -- minetest.register_node("mcl_itemframes:item_frame", mcl_itemframes.item_frame_base) + + -- make glow frame from the base item_frame. + mcl_itemframes.glow_frame_base = table.copy(mcl_itemframes.item_frame_base) + mcl_itemframes.glow_frame_base.description = S("Glowing Item Frame") + mcl_itemframes.glow_frame_base._tt_help = S("Can hold an item and glows.") + mcl_itemframes.glow_frame_base.longdesc = S("Glowing item frames are decorative blocks in which items can be placed and made to glow.") + mcl_itemframes.glow_frame_base.tiles = { "mcl_itemframes_glow_item_frame.png" } + mcl_itemframes.glow_frame_base.inventory_image = "mcl_itemframes_glow_item_frame_item.png" + mcl_itemframes.glow_frame_base.wield_image = "mcl_itemframes_glow_item_frame.png" + mcl_itemframes.glow_frame_base.mesh = "mcl_itemframes_glow_item_frame.obj" + mcl_itemframes.glow_frame_base.glow = 1 --make the glow frames have some glow at night, but not enough to be a light source. + + -- set up the achievement for glow frames. + register_frame_achievements() + +end + +-- for compatibility: +function mcl_itemframes.backwards_compatibility () + minetest.register_lbm({ + label = "Update legacy item frames", + name = "mcl_itemframes:update_legacy_item_frames", + nodenames = { "itemframes:frame" }, + action = function(pos, node) + -- Swap legacy node, then respawn entity + node.name = "mcl_itemframes:item_frame" + local meta = minetest.get_meta(pos) + local item = meta:get_string("item") + minetest.swap_node(pos, node) + if item ~= "" then + local itemstack = ItemStack(minetest.deserialize(meta:get_string("itemdata"))) + local inv = meta:get_inventory() + inv:set_size("main", 1) + if not itemstack:is_empty() then + inv:set_stack("main", 1, itemstack) + end + end + mcl_itemframes.update_item_entity(pos, node) + end, + }) + minetest.register_alias("itemframes:frame", "mcl_itemframes:item_frame") + + -- adds backwards compatibility + minetest.register_alias("mcl_itemframes:item", "mcl_itemframes:item_frame_item") + minetest.register_alias("mcl_itemframes:map", "mcl_itemframes:item_frame_map") + minetest.register_alias("mcl_itemframes:glow_item", "mcl_itemframes:glow_item_frame_item") + minetest.register_alias("mcl_itemframes:glow_map", "mcl_itemframes:glow_item_frame_map") + + minetest.register_entity("mcl_itemframes:item", frame_item_base) + minetest.register_entity("mcl_itemframes:map", map_item_base) + minetest.register_entity("mcl_itemframes:glow_item", frame_item_base) + minetest.register_entity("mcl_itemframes:glow_map", map_item_base) + +end diff --git a/mods/ITEMS/mcl_itemframes/item_frames_api_doc.txt b/mods/ITEMS/mcl_itemframes/item_frames_api_doc.txt new file mode 100644 index 000000000..7510b15b5 --- /dev/null +++ b/mods/ITEMS/mcl_itemframes/item_frames_api_doc.txt @@ -0,0 +1,36 @@ +The item frames use case is a very specific one, but... in the event that there is need for a new item frame then that +is where this api will shine. + +As long as the api has been initialized (which it does in its own init.lua) then you really only need to call one +function. That function being mcl_itemframes.create_custom_frame(modname, name, has_glow, tiles, color, ttframe, +description, inv_wield_image). Note: unlike the Signs API, this API does not automatically create the recipe for you. + +Here's an explanation of create_custom_frame and an example of using it. + +This function is responsible for creating each frame, and handling the creation of its underlying entities. + +Parameters: +* modname: Used to make sure that a specific module is installed before running the code contained within. Set to "" or + false, if there's not a mod to check for. +* name: The name used to distinguish the item frame. Prepends "mcl_itemframes:" to the name. Example usage: + "glow_item_frame" creates a node named "mcl_itemframes:glow_item_frame". +* has_glow: Does the frame cause the item within to glow? true / false. +* tiles: The image files used for the item frame's object texturing. +* color: Colorizes the frame / wield / inventory image to a specific color. Use White (#FFFFFF) to ignore. +* ttframe: The tooltip to show for the frame. +* description: The frame's description. +* inv_wield_image: Optionally the image to use as the inventory and the wield image. Colorized. set to "" or nil to use + the default frame / glow frame images. Note: must be set if you want the inventory / wield image to be colored. + +example: +-- Register the Glow Frame +mcl_itemframes.create_custom_frame("false", "glow_item_frame", true, + "mcl_itemframes_glow_item_frame.png", mcl_colors.WHITE, "Glowing Item Frame", + "Can hold an item and glows.","") + +-- Register the Glow Frame's recipe +minetest.register_craft({ + type = "shapeless", + output = 'mcl_itemframes:glow_item_frame', + recipe = { 'mcl_mobitems:glow_ink_sac', 'mcl_itemframes:item_frame' }, +}) diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.de.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.de.tr index 07d7812f6..b9bf40e1a 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.de.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.de.tr @@ -1,5 +1,8 @@ # textdomain: mcl_itemframes -Item Frame=Rahmen -Item frames are decorative blocks in which items can be placed.=Rahmen sind dekorative Blöcke, in denen man Gegenstände platzieren kann. -Just place any item on the item frame. Use the item frame again to retrieve the item.=Platzieren Sie einfach einen beliebigen Gegenstand in den Rahmen. Benutzen Sie den Rahmen erneut, um den Gegenstand zurück zu erhalten. -Can hold an item=Kann einen Gegenstand halten +Item Frame=Artikel Rahmen +Item frames are decorative blocks in which items can be placed.=Artikelrahmen sind dekorative Blöcke, in denen Artikel platziert werden können. +Just place any item on the item frame. Use the item frame again to retrieve the item.=Platzieren Sie einfach einen beliebigen Gegenstand auf dem Gegenstandsrahmen. Verwenden Sie den Artikelrahmen erneut, um den Artikel abzurufen. +Can hold an item.=Kann einen Gegenstand halten. +Glowing Item Frame=Leuchtender Gegenstandsrahmen +Glowing item frames are decorative blocks in which items can be placed and made to glow.=Leuchtende Gegenstandsrahmen sind dekorative Blöcke, in denen Gegenstände platziert und zum Leuchten gebracht werden können. +Can hold an item and glows.=Kann einen Gegenstand halten und leuchtet. diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.es.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.es.tr index 0803234b0..d5c3aed71 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.es.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.es.tr @@ -1,5 +1,8 @@ # textdomain: mcl_itemframes -Item Frame=Marco +Item Frame=Cuadro de artículo Item frames are decorative blocks in which items can be placed.=Los marcos de elementos son bloques decorativos en los que se pueden colocar elementos. -Just place any item on the item frame. Use the item frame again to retrieve the item.=Simplemente coloque cualquier artículo en el marco del artículo. Use el marco del artículo nuevamente para recuperar el artículo. - +Just place any item on the item frame. Use the item frame again to retrieve the item.=Simplemente coloque cualquier elemento en el marco del elemento. Use el marco del elemento nuevamente para recuperar el elemento. +Can hold an item.=Puede contener un artículo. +Glowing Item Frame=Marco de artículo brillante +Glowing item frames are decorative blocks in which items can be placed and made to glow.=Los marcos de elementos brillantes son bloques decorativos en los que se pueden colocar elementos y hacer que brillen. +Can hold an item and glows.=Puede sostener un artículo y brilla. diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr index 180c5555f..e847779f2 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.fr.tr @@ -1,5 +1,8 @@ # textdomain: mcl_itemframes -Item Frame=Cadre -Item frames are decorative blocks in which items can be placed.=Les cadres sont des blocs décoratifs dans lesquels les objets peuvent être placés. -Just place any item on the item frame. Use the item frame again to retrieve the item.=Placez simplement n'importe quel objet sur le cadre. Utilisez à nouveau le cadre décoré pour récupérer l'élément. -Can hold an item=Peut contenir un objet +Item Frame=Cadre de l'article +Item frames are decorative blocks in which items can be placed.=Les cadres d'objets sont des blocs décoratifs dans lesquels des objets peuvent être placés. +Just place any item on the item frame. Use the item frame again to retrieve the item.=Placez simplement n'importe quel élément sur le cadre de l'élément. Utilisez à nouveau le cadre de l'objet pour récupérer l'objet. +Can hold an item.=Peut contenir un objet. +Glowing Item Frame=Cadre d'objet lumineux +Glowing item frames are decorative blocks in which items can be placed and made to glow.=Les cadres d'objets lumineux sont des blocs décoratifs dans lesquels des objets peuvent être placés et rendus brillants. +Can hold an item and glows.=Peut contenir un objet et brille. diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.pl.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.pl.tr index 8de889471..87b83c27d 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.pl.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.pl.tr @@ -3,3 +3,10 @@ Item Frame=Ramka na przedmiot Item frames are decorative blocks in which items can be placed.=Ramki na przedmiot to dekoracyjne bloki w których można umieszczać przedmioty. Just place any item on the item frame. Use the item frame again to retrieve the item.=Umieść dowolny przedmiot w ramce. Użyj ramki ponownie aby odzyskać przedmiot. Can hold an item=Może przetrzymywać przedmiot +Item Frame=Rama przedmiotu +Item frames are decorative blocks in which items can be placed.=Ramki na przedmioty to klocki ozdobne, w których można umieszczać przedmioty. +Just place any item on the item frame. Use the item frame again to retrieve the item.=Wystarczy umieścić dowolny przedmiot na ramie przedmiotu. Użyj ponownie ramki elementu, aby pobrać element. +Can hold an item.=Może pomieścić przedmiot. +Glowing Item Frame=Świecąca ramka na przedmiot +Glowing item frames are decorative blocks in which items can be placed and made to glow.=Świecące ramki na przedmioty to ozdobne bloki, w których można umieścić przedmioty i sprawić, by świeciły. +Can hold an item and glows.=Może trzymać przedmiot i świeci. diff --git a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.ru.tr b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.ru.tr index 7d3d90cc4..bf9076815 100644 --- a/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.ru.tr +++ b/mods/ITEMS/mcl_itemframes/locale/mcl_itemframes.ru.tr @@ -3,3 +3,10 @@ Item Frame=Рамка Item frames are decorative blocks in which items can be placed.=Рамки это декоративные блоки, в которые можно помещать предметы. Just place any item on the item frame. Use the item frame again to retrieve the item.=Просто поместите в рамку любой предмет. Используйте рамку вновь, чтобы заполучить из неё предмет обратно. Can hold an item=Может хранить предмет +Item Frame=Рамка предмета +Item frames are decorative blocks in which items can be placed.=Рамки предметов — это декоративные блоки, в которые можно помещать предметы. +Just place any item on the item frame. Use the item frame again to retrieve the item.=Просто поместите любой предмет на рамку предмета. Используйте рамку предмета снова, чтобы получить предмет. +Can hold an item.=Может держать предмет. +Glowing Item Frame=Светящаяся рамка предмета +Glowing item frames are decorative blocks in which items can be placed and made to glow.=Светящиеся рамки предметов — это декоративные блоки, в которые можно помещать предметы и заставлять их светиться. +Can hold an item and glows.=Может держать предмет и светится. diff --git a/mods/ITEMS/mcl_itemframes/locale/template.txt b/mods/ITEMS/mcl_itemframes/locale/template.txt index bacbfaa69..87cd55c65 100644 --- a/mods/ITEMS/mcl_itemframes/locale/template.txt +++ b/mods/ITEMS/mcl_itemframes/locale/template.txt @@ -3,3 +3,6 @@ Item Frame= Item frames are decorative blocks in which items can be placed.= Just place any item on the item frame. Use the item frame again to retrieve the item.= Can hold an item= +Glow Item Frame= +Glow item frames are decorative blocks in which items can be placed.= +Can hold an item and glows= diff --git a/mods/ITEMS/mcl_itemframes/mod.conf b/mods/ITEMS/mcl_itemframes/mod.conf index ff09c3bcc..f9421e657 100644 --- a/mods/ITEMS/mcl_itemframes/mod.conf +++ b/mods/ITEMS/mcl_itemframes/mod.conf @@ -1,3 +1,2 @@ name = mcl_itemframes -depends = mcl_core, mcl_sounds, mcl_compass, mcl_maps -optional_depends = screwdriver +depends = mcl_core, mcl_sounds, mcl_compass, mcl_maps, screwdriver diff --git a/mods/ITEMS/mcl_itemframes/models/mcl_itemframes_glow_item_frame.obj b/mods/ITEMS/mcl_itemframes/models/mcl_itemframes_glow_item_frame.obj new file mode 100644 index 000000000..d0a5b0c5f --- /dev/null +++ b/mods/ITEMS/mcl_itemframes/models/mcl_itemframes_glow_item_frame.obj @@ -0,0 +1,156 @@ +# Blender v2.76 (sub 0) OBJ File: 'itemframe1facedir.blend' +# www.blender.org +mtllib itemframe1facedir.mtl +o right.frame_Cube.005 +v -0.313413 -0.313413 0.435326 +v -0.313413 0.313413 0.435326 +v -0.313413 -0.313413 0.498008 +v -0.313413 0.313413 0.498008 +v -0.376095 -0.313413 0.435326 +v -0.376095 0.313413 0.435326 +v -0.376095 -0.313413 0.498008 +v -0.376095 0.313413 0.498008 +vt 0.875000 0.812500 +vt 0.812500 0.812500 +vt 0.812500 0.187500 +vt 0.875000 0.187500 +vt 1.000000 0.812500 +vt 0.937500 0.812500 +vt 0.937500 0.187500 +vt 1.000000 0.187500 +vt -0.000000 0.937500 +vt 0.062500 0.937500 +vt 0.062500 1.000000 +vt -0.000000 1.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn -0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 2/1/1 4/2/1 3/3/1 1/4/1 +f 4/1/2 8/2/2 7/3/2 3/4/2 +f 8/5/3 6/6/3 5/7/3 7/8/3 +f 6/1/4 2/2/4 1/3/4 5/4/4 +f 1/9/5 3/10/5 7/11/5 5/12/5 +f 6/9/6 8/10/6 4/11/6 2/12/6 +o left.frame_Cube.004 +v 0.376095 -0.313413 0.435326 +v 0.376095 0.313413 0.435326 +v 0.376095 -0.313413 0.498008 +v 0.376095 0.313413 0.498008 +v 0.313413 -0.313413 0.435326 +v 0.313413 0.313413 0.435326 +v 0.313413 -0.313413 0.498008 +v 0.313413 0.313413 0.498008 +vt 0.875000 0.812500 +vt 0.812500 0.812500 +vt 0.812500 0.187500 +vt 0.875000 0.187500 +vt 1.000000 0.812500 +vt 0.937500 0.812500 +vt 0.937500 0.187500 +vt 1.000000 0.187500 +vt -0.000000 0.937500 +vt 0.062500 0.937500 +vt 0.062500 1.000000 +vt -0.000000 1.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 10/13/7 12/14/7 11/15/7 9/16/7 +f 12/13/8 16/14/8 15/15/8 11/16/8 +f 16/17/9 14/18/9 13/19/9 15/20/9 +f 14/13/10 10/14/10 9/15/10 13/16/10 +f 9/21/11 11/22/11 15/23/11 13/24/11 +f 14/21/12 16/22/12 12/23/12 10/24/12 +o lower.frame_Cube.003 +v 0.376095 -0.376095 0.435326 +v 0.376095 -0.313413 0.435326 +v 0.376095 -0.376095 0.498008 +v 0.376095 -0.313413 0.498008 +v -0.376095 -0.376095 0.435326 +v -0.376095 -0.313413 0.435326 +v -0.376095 -0.376095 0.498008 +v -0.376095 -0.313413 0.498008 +vt 0.187500 0.187500 +vt 0.125000 0.187500 +vt 0.125000 0.125000 +vt 0.187500 0.125000 +vt 0.875000 0.187500 +vt 0.875000 0.125000 +vt 0.812500 0.187500 +vt 0.812500 0.125000 +vt 0.875000 0.937500 +vt 0.875000 1.000000 +vt 0.125000 1.000000 +vt 0.125000 0.937500 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn -0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 18/25/13 20/26/13 19/27/13 17/28/13 +f 20/29/14 24/26/14 23/27/14 19/30/14 +f 24/29/15 22/31/15 21/32/15 23/30/15 +f 22/29/16 18/26/16 17/27/16 21/30/16 +f 17/33/17 19/34/17 23/35/17 21/36/17 +f 22/30/18 24/29/18 20/26/18 18/27/18 +o upper.frame_Cube.002 +v 0.376095 0.313413 0.435326 +v 0.376095 0.376095 0.435326 +v 0.376095 0.313413 0.498008 +v 0.376095 0.376095 0.498008 +v -0.376095 0.313413 0.435326 +v -0.376095 0.376095 0.435326 +v -0.376095 0.313413 0.498008 +v -0.376095 0.376095 0.498008 +vt 0.187500 0.875000 +vt 0.125000 0.875000 +vt 0.125000 0.812500 +vt 0.187500 0.812500 +vt 0.875000 0.875000 +vt 0.875000 0.812500 +vt 0.812500 0.875000 +vt 0.812500 0.812500 +vt 0.875000 0.937500 +vt 0.875000 1.000000 +vt 0.125000 1.000000 +vt 0.125000 0.937500 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn -0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 26/37/19 28/38/19 27/39/19 25/40/19 +f 28/41/20 32/38/20 31/39/20 27/42/20 +f 32/41/21 30/43/21 29/44/21 31/42/21 +f 30/41/22 26/38/22 25/39/22 29/42/22 +f 25/45/23 27/46/23 31/47/23 29/48/23 +f 30/48/24 32/38/24 28/41/24 26/45/24 +o background_Plane +v 0.313413 -0.313413 0.466667 +v -0.313413 -0.313413 0.466667 +v 0.313413 0.313413 0.466667 +v -0.313413 0.313413 0.466667 +vt 0.187500 0.187500 +vt 0.812500 0.187500 +vt 0.812500 0.812500 +vt 0.187500 0.812500 +vn -0.000000 0.000000 -1.000000 +usemtl None +s off +f 33/49/25 34/50/25 36/51/25 35/52/25 diff --git a/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame.png b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame.png new file mode 100644 index 000000000..e83b4e060 Binary files /dev/null and b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame.png differ diff --git a/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_border.png b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_border.png new file mode 100644 index 000000000..9062c679f Binary files /dev/null and b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_border.png differ diff --git a/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_item.png b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_item.png new file mode 100644 index 000000000..e83b4e060 Binary files /dev/null and b/mods/ITEMS/mcl_itemframes/textures/mcl_itemframes_glow_item_frame_item.png differ diff --git a/mods/ITEMS/mcl_jukebox/README.md b/mods/ITEMS/mcl_jukebox/README.md index bc261270a..6376362bb 100644 --- a/mods/ITEMS/mcl_jukebox/README.md +++ b/mods/ITEMS/mcl_jukebox/README.md @@ -10,7 +10,7 @@ to play. And that's it! `mcl_jukebox_track_2.ogg`: “The Energetic Rat (Jordach's Mix)” by SoundHelix (CC0) `mcl_jukebox_track_3.ogg`: “Eastern Feeling” by Jordach (CC0) `mcl_jukebox_track_4.ogg`: “Minetest” by Jordach (CC0) -`mcl_jukebox_track_5.ogg`: “Credit Roll (Jordach's HD Mix)” by Junichi Masuda (CC0) +`mcl_jukebox_track_5.ogg`: "Soaring over the sea" by mactonite http://ccmixter.org/files/mactonite/65379 (CC-BY) `mcl_jukebox_track_6.ogg`: “Winter Feeling" by Tom Peter (CC BY-SA 3.0) `mcl_jukebox_track_7.ogg`: “Synthgroove (Jordach's Mix)” by HeroOfTheWinds (CC0) `mcl_jukebox_track_8.ogg`: “The Clueless Frog (Jordach's Mix)” by SoundHelix (CC0) diff --git a/mods/ITEMS/mcl_jukebox/init.lua b/mods/ITEMS/mcl_jukebox/init.lua index 6c51a6c94..d817bdac7 100644 --- a/mods/ITEMS/mcl_jukebox/init.lua +++ b/mods/ITEMS/mcl_jukebox/init.lua @@ -234,7 +234,7 @@ mcl_jukebox.register_record("The Evil Sister (Jordach's Mix)", "SoundHelix", "13 mcl_jukebox.register_record("The Energetic Rat (Jordach's Mix)", "SoundHelix", "wait", "mcl_jukebox_record_wait.png", "mcl_jukebox_track_2") mcl_jukebox.register_record("Eastern Feeling", "Jordach", "blocks", "mcl_jukebox_record_blocks.png", "mcl_jukebox_track_3") mcl_jukebox.register_record("Minetest", "Jordach", "far", "mcl_jukebox_record_far.png", "mcl_jukebox_track_4") -mcl_jukebox.register_record("Credit Roll (Jordach's HD Mix)", "Junichi Masuda", "chirp", "mcl_jukebox_record_chirp.png", "mcl_jukebox_track_5") +mcl_jukebox.register_record("Soaring over the sea", "mactonite", "chirp", "mcl_jukebox_record_chirp.png", "mcl_jukebox_track_5") mcl_jukebox.register_record("Winter Feeling", "Tom Peter", "strad", "mcl_jukebox_record_strad.png", "mcl_jukebox_track_6") mcl_jukebox.register_record("Synthgroove (Jordach's Mix)", "HeroOfTheWinds", "mellohi", "mcl_jukebox_record_mellohi.png", "mcl_jukebox_track_7") mcl_jukebox.register_record("The Clueless Frog (Jordach's Mix)", "SoundHelix", "mall", "mcl_jukebox_record_mall.png", "mcl_jukebox_track_8") diff --git a/mods/ITEMS/mcl_jukebox/sounds/mcl_jukebox_track_5.ogg b/mods/ITEMS/mcl_jukebox/sounds/mcl_jukebox_track_5.ogg index dcad499d9..0a635207c 100644 Binary files a/mods/ITEMS/mcl_jukebox/sounds/mcl_jukebox_track_5.ogg and b/mods/ITEMS/mcl_jukebox/sounds/mcl_jukebox_track_5.ogg differ diff --git a/mods/ITEMS/mcl_lightning_rods/init.lua b/mods/ITEMS/mcl_lightning_rods/init.lua new file mode 100644 index 000000000..82e04db0c --- /dev/null +++ b/mods/ITEMS/mcl_lightning_rods/init.lua @@ -0,0 +1,118 @@ +local S = minetest.get_translator("mcl_lightning_rods") + +---@type nodebox +local cbox = { + type = "fixed", + fixed = { + { -0.0625, -0.5, -0.0625, 0.0625, 0.25, 0.0625 }, + { -0.125, 0.25, -0.125, 0.125, 0.5, 0.125 }, + }, +} + +---@type node_definition +local rod_def = { + description = S("Lightning Rod"), + _doc_items_longdesc = S("A block that attracts lightning"), + tiles = { "mcl_lightning_rods_rod.png" }, + drawtype = "mesh", + mesh = "mcl_lightning_rods_rod.obj", + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + use_texture_alpha = "opaque", + groups = { pickaxey = 2, attracts_lightning = 1 }, + sounds = mcl_sounds.node_sound_metal_defaults(), + selection_box = cbox, + collision_box = cbox, + node_placement_prediction = "", + mesecons = { + receptor = { + state = mesecon.state.off, + rules = mesecon.rules.alldirs, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + local param2 = 0 + + local placer_pos = placer:get_pos() + if placer_pos then + param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) + end + + if p0.y - 1 == p1.y then + param2 = 20 + elseif p0.x - 1 == p1.x then + param2 = 16 + elseif p0.x + 1 == p1.x then + param2 = 12 + elseif p0.z - 1 == p1.z then + param2 = 8 + elseif p0.z + 1 == p1.z then + param2 = 4 + end + + return minetest.item_place(itemstack, placer, pointed_thing, param2) + end, + + _mcl_blast_resistance = 0, +} + +minetest.register_node("mcl_lightning_rods:rod", rod_def) + +local rod_def_a = table.copy(rod_def) + +rod_def_a.tiles = { "mcl_lightning_rods_rod.png^[brighten" } + +rod_def_a.groups.not_in_creative_inventory = 1 + +rod_def_a.mesecons = { + receptor = { + state = mesecon.state.on, + rules = mesecon.rules.alldirs, + }, +} + +rod_def_a.on_timer = function(pos, elapsed) + local node = minetest.get_node(pos) + + if node.name == "mcl_lightning_rods:rod_powered" then --has not been dug + minetest.set_node(pos, { name = "mcl_lightning_rods:rod" }) + mesecon.receptor_off(pos, mesecon.rules.alldirs) + end + + return false +end + +minetest.register_node("mcl_lightning_rods:rod_powered", rod_def_a) + + +lightning.register_on_strike(function(pos, pos2, objects) + local lr = minetest.find_node_near(pos, 128, { "group:attracts_lightning" }, true) + + if lr then + local node = minetest.get_node(lr) + + if node.name == "mcl_lightning_rods:rod" then + minetest.set_node(lr, { name = "mcl_lightning_rods:rod_powered" }) + mesecon.receptor_on(lr, mesecon.rules.alldirs) + minetest.get_node_timer(lr):start(0.4) + end + end + + return lr, nil +end) + +minetest.register_craft({ + output = "mcl_lightning_rods:rod", + recipe = { + { "", "mcl_copper:copper_ingot", "" }, + { "", "mcl_copper:copper_ingot", "" }, + { "", "mcl_copper:copper_ingot", "" }, + }, +}) diff --git a/mods/ITEMS/mcl_lightning_rods/locale/mcl_lightning_rods.fr.tr b/mods/ITEMS/mcl_lightning_rods/locale/mcl_lightning_rods.fr.tr new file mode 100644 index 000000000..8f99047f6 --- /dev/null +++ b/mods/ITEMS/mcl_lightning_rods/locale/mcl_lightning_rods.fr.tr @@ -0,0 +1,3 @@ +# textdomain: mcl_lightning_rods +Lightning Rod=Paratonnerre +A block that attracts lightning=Un bloc qui attire la foudre \ No newline at end of file diff --git a/mods/ITEMS/mcl_lightning_rods/locale/template.txt b/mods/ITEMS/mcl_lightning_rods/locale/template.txt new file mode 100644 index 000000000..5b2bbbcd2 --- /dev/null +++ b/mods/ITEMS/mcl_lightning_rods/locale/template.txt @@ -0,0 +1,3 @@ +# textdomain: mcl_lightning_rods +Lightning Rod= +A block that attracts lightning= \ No newline at end of file diff --git a/mods/ITEMS/mcl_lightning_rods/mod.conf b/mods/ITEMS/mcl_lightning_rods/mod.conf new file mode 100644 index 000000000..dd30d7aa7 --- /dev/null +++ b/mods/ITEMS/mcl_lightning_rods/mod.conf @@ -0,0 +1,3 @@ +name = mcl_lightning_rods +author = cora +depends = mcl_sounds, lightning, mesecons diff --git a/mods/ITEMS/mcl_lightning_rods/models/mcl_lightning_rods_rod.obj b/mods/ITEMS/mcl_lightning_rods/models/mcl_lightning_rods_rod.obj new file mode 100644 index 000000000..7870fc5bd --- /dev/null +++ b/mods/ITEMS/mcl_lightning_rods/models/mcl_lightning_rods_rod.obj @@ -0,0 +1,90 @@ +# Blender 3.3.1 +# www.blender.org +o Cube +v -0.062500 -0.500000 0.062500 +v -0.062500 0.250000 0.062500 +v -0.062500 -0.500000 -0.062500 +v -0.062500 0.250000 -0.062500 +v 0.062500 -0.500000 0.062500 +v 0.062500 0.250000 0.062500 +v 0.062500 -0.500000 -0.062500 +v 0.062500 0.250000 -0.062500 +v -0.125000 0.250000 0.125000 +v -0.125000 0.250000 -0.125000 +v 0.125000 0.250000 -0.125000 +v 0.125000 0.250000 0.125000 +v -0.125000 0.500000 0.125000 +v -0.125000 0.500000 -0.125000 +v 0.125000 0.500000 -0.125000 +v 0.125000 0.500000 0.125000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0000 1.0000 -0.0000 +vt 0.000000 0.750000 +vt 0.125000 0.750000 +vt 0.062500 0.937500 +vt 0.000000 0.000000 +vt 0.125000 0.000000 +vt 0.187500 0.812500 +vt 0.062500 0.937500 +vt 0.125000 0.750000 +vt -0.000000 0.750000 +vt 0.062500 0.812500 +vt 0.125000 0.000000 +vt 0.000000 -0.000000 +vt 0.062500 0.812500 +vt 0.187500 0.937500 +vt 0.125000 0.750000 +vt -0.000000 0.750000 +vt 0.187500 0.937500 +vt 0.125000 -0.000000 +vt 0.000000 -0.000000 +vt 0.062500 0.812500 +vt 0.187500 0.937500 +vt 0.125000 0.750000 +vt 0.000000 0.750000 +vt 0.187500 0.812500 +vt 0.125000 -0.000000 +vt -0.000000 0.000000 +vt 0.187500 0.812500 +vt 0.062500 0.937500 +vt 0.000000 1.000000 +vt 0.250000 0.750000 +vt -0.000000 0.750000 +vt 0.250025 0.999950 +vt -0.000000 0.750000 +vt 0.250000 0.750000 +vt 0.250000 0.750000 +vt 0.000000 1.000000 +vt -0.000000 0.750000 +vt 0.000000 0.750000 +vt 0.250000 1.000000 +vt 0.250000 0.750000 +vt 0.250000 1.000000 +vt -0.000000 1.000000 +vt 0.250000 0.750000 +vt 0.000100 0.999900 +vt 0.250000 1.000000 +vt 0.250000 1.000000 +vt 0.000000 0.750000 +vt 0.000100 0.999900 +vt 0.000000 1.000000 +vt 0.250000 1.000000 +s 0 +f 1/1/1 2/4/1 4/11/1 3/8/1 +f 3/9/2 4/12/2 8/25/2 7/22/2 +f 7/23/3 8/26/3 6/18/3 5/15/3 +f 5/16/4 6/19/4 2/5/4 1/2/4 +f 3/10/5 7/24/5 5/17/5 1/3/5 +f 8/27/5 4/13/5 10/33/5 11/35/5 +f 12/38/3 11/35/3 15/46/3 16/49/3 +f 6/20/5 8/28/5 11/36/5 12/38/5 +f 4/14/5 2/6/5 9/30/5 10/32/5 +f 2/7/5 6/21/5 12/39/5 9/29/5 +f 15/47/6 14/43/6 13/41/6 16/49/6 +f 10/33/1 9/30/1 13/41/1 14/44/1 +f 9/31/4 12/40/4 16/50/4 13/42/4 +f 11/37/2 10/34/2 14/45/2 15/48/2 diff --git a/mods/ITEMS/mcl_lightning_rods/textures/mcl_lightning_rods_rod.png b/mods/ITEMS/mcl_lightning_rods/textures/mcl_lightning_rods_rod.png new file mode 100644 index 000000000..355b2bd01 Binary files /dev/null and b/mods/ITEMS/mcl_lightning_rods/textures/mcl_lightning_rods_rod.png differ diff --git a/mods/ITEMS/mcl_mangrove/init.lua b/mods/ITEMS/mcl_mangrove/init.lua index b122ea8f6..666b471de 100644 --- a/mods/ITEMS/mcl_mangrove/init.lua +++ b/mods/ITEMS/mcl_mangrove/init.lua @@ -96,6 +96,7 @@ minetest.register_node("mcl_mangrove:mangroveleaves", { tiles = {"mcl_mangrove_leaves.png"}, paramtype = "light", groups = {handy=1,shearsy=1,swordy=1, leafdecay=10, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60}, + drop = get_drops(0), _mcl_shears_drop = true, sounds = mcl_sounds.node_sound_leaves_defaults(), _mcl_blast_resistance = 0.2, @@ -307,7 +308,7 @@ local wlroots = { }, sounds = mcl_sounds.node_sound_water_defaults(), drawtype = "allfaces_optional", - use_texture_alpha = "clip", + use_texture_alpha = "blend", is_ground_content = false, paramtype = "light", walkable = true, @@ -316,8 +317,7 @@ local wlroots = { buildable_to = false, liquids_pointable = true, drop = "mcl_mangrove:mangrove_roots", - - groups = { + groups = { handy = 1, hoey = 1, water=3, liquid=3, puts_out_fire=1, dig_by_piston = 1, deco_block = 1, not_in_creative_inventory=1 }, _mcl_blast_resistance = 100, _mcl_hardness = -1, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode diff --git a/mods/ITEMS/mcl_mangrove/schematics/mcl_mangrove_bee_nest.mts b/mods/ITEMS/mcl_mangrove/schematics/mcl_mangrove_bee_nest.mts new file mode 100644 index 000000000..630117463 Binary files /dev/null and b/mods/ITEMS/mcl_mangrove/schematics/mcl_mangrove_bee_nest.mts differ diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index 09dcd4f95..84f4019ea 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -62,7 +62,7 @@ function mcl_maps.create_map(pos) local emin, emax = vm:read_from_map(minp, maxp) local data = vm:get_data() local param2data = vm:get_param2_data() - local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) + local area = VoxelArea:new({ MinEdge = emin, MaxEdge = emax }) local pixels = {} local last_heightmap for x = 1, 128 do @@ -94,7 +94,7 @@ function mcl_maps.create_map(pos) end if def.palette then local palette = palettes[texture] - color = palette and {palette = palette} + color = palette and { palette = palette } else color = texture_colors[texture] end @@ -129,7 +129,7 @@ function mcl_maps.create_map(pos) end heightmap[z] = height or minp.y pixels[z] = pixels[z] or {} - pixels[z][x] = color or {0, 0, 0} + pixels[z][x] = color or { 0, 0, 0 } end last_heightmap = heightmap end @@ -141,30 +141,43 @@ end function mcl_maps.load_map(id, callback) if id == "" or creating_maps[id] then - return + return false end local texture = "mcl_maps_map_texture_" .. id .. ".tga" + local result = true + if not loaded_maps[id] then if not minetest.features.dynamic_add_media_table then -- minetest.dynamic_add_media() blocks in -- Minetest 5.3 and 5.4 until media loads loaded_maps[id] = true - dynamic_add_media(map_textures_path .. texture, function() end) - if callback then callback(texture) end + result = dynamic_add_media(map_textures_path .. texture, function() + end) + if callback then + callback(texture) + end else -- minetest.dynamic_add_media() never blocks -- in Minetest 5.5, callback runs after load - dynamic_add_media(map_textures_path .. texture, function() + result = dynamic_add_media(map_textures_path .. texture, function() loaded_maps[id] = true - if callback then callback(texture) end + if callback then + callback(texture) + end end) end end + if result == false then + return false + end + if loaded_maps[id] then - if callback then callback(texture) end + if callback then + callback(texture) + end return texture end end @@ -213,7 +226,7 @@ local filled_def = { _doc_items_usagehelp = S("Hold the map in your hand. This will display a map on your screen."), inventory_image = "mcl_maps_map_filled.png^(mcl_maps_map_filled_markings.png^[colorize:#000000)", stack_max = 64, - groups = {not_in_creative_inventory = 1, filled_map = 1, tool = 1}, + groups = { not_in_creative_inventory = 1, filled_map = 1, tool = 1 }, } minetest.register_craftitem("mcl_maps:filled_map", filled_def) @@ -221,7 +234,7 @@ minetest.register_craftitem("mcl_maps:filled_map", filled_def) local filled_wield_def = table.copy(filled_def) filled_wield_def.use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false filled_wield_def.visual_scale = 1 -filled_wield_def.wield_scale = {x = 1, y = 1, z = 1} +filled_wield_def.wield_scale = { x = 1, y = 1, z = 1 } filled_wield_def.paramtype = "light" filled_wield_def.drawtype = "mesh" filled_wield_def.node_placement_prediction = "" @@ -239,20 +252,20 @@ if mcl_skins_enabled then local female = table.copy(filled_wield_def) female._mcl_hand_id = skin.id female.mesh = "mcl_meshhand_female.b3d" - female.tiles = {skin.texture} + female.tiles = { skin.texture } minetest.register_node("mcl_maps:filled_map_" .. skin.id, female) else local male = table.copy(filled_wield_def) male._mcl_hand_id = skin.id male.mesh = "mcl_meshhand.b3d" - male.tiles = {skin.texture} + male.tiles = { skin.texture } minetest.register_node("mcl_maps:filled_map_" .. skin.id, male) end end else filled_wield_def._mcl_hand_id = "hand" filled_wield_def.mesh = "mcl_meshhand.b3d" - filled_wield_def.tiles = {"character.png"} + filled_wield_def.tiles = { "character.png" } minetest.register_node("mcl_maps:filled_map_hand", filled_wield_def) end @@ -286,7 +299,7 @@ minetest.register_craft({ minetest.register_craft({ type = "shapeless", output = "mcl_maps:filled_map 2", - recipe = {"group:filled_map", "mcl_maps:empty_map"}, + recipe = { "group:filled_map", "mcl_maps:empty_map" }, }) local function on_craft(itemstack, player, old_craft_grid, craft_inv) @@ -310,13 +323,13 @@ minetest.register_on_joinplayer(function(player) local map_def = { hud_elem_type = "image", text = "blank.png", - position = {x = 0.75, y = 0.8}, - alignment = {x = 0, y = -1}, - offset = {x = 0, y = 0}, - scale = {x = 2, y = 2}, + position = { x = 0.75, y = 0.8 }, + alignment = { x = 0, y = -1 }, + offset = { x = 0, y = 0 }, + scale = { x = 2, y = 2 }, } local marker_def = table.copy(map_def) - marker_def.alignment = {x = 0, y = 0} + marker_def.alignment = { x = 0, y = 0 } huds[player] = { map = player:hud_add(map_def), marker = player:hud_add(marker_def), @@ -376,7 +389,7 @@ minetest.register_globalstep(function(dtime) end player:hud_change(hud.marker, "text", marker) - player:hud_change(hud.marker, "offset", {x = (6 - 140 / 2 + pos.x - minp.x) * 2, y = (6 - 140 + maxp.z - pos.z) * 2}) + player:hud_change(hud.marker, "offset", { x = (6 - 140 / 2 + pos.x - minp.x) * 2, y = (6 - 140 + maxp.z - pos.z) * 2 }) elseif maps[player] then player:hud_change(hud.map, "text", "blank.png") player:hud_change(hud.marker, "text", "blank.png") diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index d5b43058e..e1b39660f 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -327,6 +327,17 @@ minetest.register_tool("mcl_mobitems:carrot_on_a_stick", { _mcl_toollike_wield = true, }) +minetest.register_tool("mcl_mobitems:warped_fungus_on_a_stick", { + description = S("Warped fungus on a Stick"), + _tt_help = S("Lets you ride a strider"), + _doc_items_longdesc = S("A warped fungus on a stick can be used on saddled striders to ride them."), + _doc_items_usagehelp = S("Place it on a saddled strider to mount it. You can now ride the strider like a horse. Striders will also walk towards you when you just wield the carrot on a stick."), + wield_image = "mcl_mobitems_warped_fungus_on_a_stick.png^[transformFY^[transformR90", + inventory_image = "mcl_mobitems_warped_fungus_on_a_stick.png", + groups = { transport = 1 }, + _mcl_toollike_wield = true, +}) + minetest.register_craftitem("mcl_mobitems:nautilus_shell", { description = S("Nautilus Shell"), _tt_help = S("Used to craft a conduit"), @@ -390,6 +401,15 @@ minetest.register_alias("mobs_mc:iron_horse_armor", "mcl_mobitems:iron_horse_arm minetest.register_alias("mobs_mc:gold_horse_armor", "mcl_mobitems:gold_horse_armor") minetest.register_alias("mobs_mc:diamond_horse_armor", "mcl_mobitems:diamond_horse_armor") +minetest.register_craftitem("mcl_mobitems:glow_ink_sac", { + description = S("Glow Ink Sac"), + _doc_items_longdesc = S("Use it to craft the Glow Item Frame."), + _doc_items_usagehelp = S("Use the Glow Ink Sac and the normal Item Frame to craft the Glow Item Frame."), + inventory_image = "extra_mobs_glow_ink_sac.png", + groups = { craftitem = 1 }, +}) + + ----------- -- Crafting ----------- @@ -441,6 +461,22 @@ minetest.register_craft({ }, }) +minetest.register_craft({ + output = "mcl_mobitems:warped_fungus_on_a_stick", + recipe = { + { "mcl_fishing:fishing_rod", "", }, + { "", "mcl_crimson:warped_fungus" }, + }, +}) + +minetest.register_craft({ + output = "mcl_mobitems:warped_fungus_on_a_stick", + recipe = { + { "","mcl_fishing:fishing_rod", }, + { "mcl_crimson:warped_fungus", "" }, + }, +}) + minetest.register_craft({ type = "shapeless", output = "mcl_mobitems:magma_cream", diff --git a/mods/ITEMS/mcl_mobitems/textures/extra_mobs_glow_ink_sac.png b/mods/ITEMS/mcl_mobitems/textures/extra_mobs_glow_ink_sac.png new file mode 100644 index 000000000..6628e6abb Binary files /dev/null and b/mods/ITEMS/mcl_mobitems/textures/extra_mobs_glow_ink_sac.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_dolphin.png b/mods/ITEMS/mcl_mobitems/textures/mcl_mobitems_warped_fungus_on_a_stick.png similarity index 52% rename from mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_dolphin.png rename to mods/ITEMS/mcl_mobitems/textures/mcl_mobitems_warped_fungus_on_a_stick.png index 54819ada6..9f20bf787 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_dolphin.png and b/mods/ITEMS/mcl_mobitems/textures/mcl_mobitems_warped_fungus_on_a_stick.png differ diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index 5536d3d29..d300df5fd 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -77,7 +77,6 @@ minetest.register_node("mcl_nether:netheriteblock", { _mcl_blast_resistance = 1200, _mcl_hardness = 50, _mcl_silk_touch_drop = true, - _mcl_fortune_drop = mcl_core.fortune_drop_ore }) -- For eternal fire on top of netherrack and magma blocks diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua index 5cddabd30..5957bafb2 100644 --- a/mods/ITEMS/mcl_ocean/kelp.lua +++ b/mods/ITEMS/mcl_ocean/kelp.lua @@ -741,7 +741,7 @@ minetest.register_craftitem("mcl_ocean:kelp", { inventory_image = "mcl_ocean_kelp_item.png", wield_image = "mcl_ocean_kelp_item.png", on_place = kelp.kelp_on_place, - groups = {deco_block = 1, compostability = 30}, + groups = {deco_block = 1, compostability = 30, smoker_cookable = 1}, }) if mod_doc then diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 1fbf591d9..76ac71e72 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -19,6 +19,7 @@ get_chat_function["water_breathing"] = mcl_potions.water_breathing_func get_chat_function["leaping"] = mcl_potions.leaping_func get_chat_function["swiftness"] = mcl_potions.swiftness_func get_chat_function["heal"] = mcl_potions.healing_func +get_chat_function["bad_omen"] = mcl_potions.bad_omen_func minetest.register_chatcommand("effect",{ params = S(" []"), diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index b7102d8a4..de3f6df10 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -9,6 +9,7 @@ EF.leaping = {} EF.swift = {} -- for swiftness AND slowness EF.night_vision = {} EF.fire_proof = {} +EF.bad_omen = {} local EFFECT_TYPES = 0 for _,_ in pairs(EF) do @@ -41,7 +42,7 @@ local function potions_init_icons(player) text = "blank.png", position = { x = 1, y = 0 }, offset = { x = x, y = 3 }, - scale = { x = 3, y = 3 }, + scale = { x = 0.375, y = 0.375 }, alignment = { x = 1, y = 1 }, z_index = 100, }) @@ -70,7 +71,7 @@ local function potions_set_icons(player) if effect_name == nil then player:hud_change(icon, "text", "blank.png") else - player:hud_change(icon, "text", "mcl_potions_effect_"..effect_name..".png") + player:hud_change(icon, "text", "mcl_potions_effect_"..effect_name..".png^[resize:128x128") end end @@ -350,6 +351,26 @@ minetest.register_globalstep(function(dtime) end + -- Check for Bad Omen + for player, vals in pairs(EF.bad_omen) do + + is_player = player:is_player() + + EF.bad_omen[player].timer = EF.bad_omen[player].timer + dtime + + if player:get_pos() then mcl_potions._add_spawner(player, "#0b6138") end + + if EF.bad_omen[player] and EF.bad_omen[player].timer >= EF.bad_omen[player].dur then + EF.bad_omen[player] = nil + if is_player then + meta = player:get_meta() + meta:set_string("_has_bad_omen", minetest.serialize(EF.bad_omen[player])) + potions_set_hud(player) + end + end + + end + end) -- Prevent damage to player with Fire Resistance enabled @@ -386,7 +407,8 @@ function mcl_potions._clear_cached_player_data(player) EF.swift[player] = nil EF.night_vision[player] = nil EF.fire_proof[player] = nil - + EF.bad_omen[player] = nil + meta = player:get_meta() meta:set_int("night_vision", 0) end @@ -400,16 +422,16 @@ function mcl_potions._reset_player_effects(player, set_hud) mcl_potions.make_invisible(player, false) playerphysics.remove_physics_factor(player, "jump", "mcl_potions:leaping") - + playerphysics.remove_physics_factor(player, "speed", "mcl_potions:swiftness") - + mcl_weather.skycolor.update_sky_color({player}) + mcl_potions._clear_cached_player_data(player) + if set_hud ~= false then potions_set_hud(player) end - - mcl_potions._clear_cached_player_data(player) end function mcl_potions._save_player_effects(player) @@ -429,6 +451,7 @@ function mcl_potions._save_player_effects(player) meta:set_string("_is_swift", minetest.serialize(EF.swift[player])) meta:set_string("_is_cat", minetest.serialize(EF.night_vision[player])) meta:set_string("_is_fire_proof", minetest.serialize(EF.fire_proof[player])) + meta:set_string("_has_bad_omen", minetest.serialize(EF.bad_omen[player])) end @@ -480,6 +503,10 @@ function mcl_potions._load_player_effects(player) EF.fire_proof[player] = minetest.deserialize(meta:get_string("_is_fire_proof")) end + if minetest.deserialize(meta:get_string("_has_bad_omen")) then + EF.bad_omen[player] = minetest.deserialize(meta:get_string("_has_bad_omen")) + end + end -- Returns true if player has given effect @@ -490,6 +517,18 @@ function mcl_potions.player_has_effect(player, effect_name) return EF[effect_name][player] ~= nil end +function mcl_potions.player_get_effect(player, effect_name) + if not EF[effect_name] or not EF[effect_name][player] then + return false + end + return EF[effect_name][player] +end + +function mcl_potions.player_clear_effect(player,effect) + EF[effect][player] = nil + potions_set_icons(player) +end + minetest.register_on_leaveplayer( function(player) mcl_potions._save_player_effects(player) mcl_potions._clear_cached_player_data(player) -- clearout the buffer to prevent looking for a player not there @@ -561,45 +600,24 @@ function mcl_potions.is_obj_hit(self, pos) end -function mcl_potions.make_invisible(player, toggle) - - if not player then - return false +function mcl_potions.make_invisible(obj_ref, hide) + if obj_ref:is_player() then + if hide then + mcl_player.player_set_visibility(obj_ref, false) + obj_ref:set_nametag_attributes({ color = { a = 0 } }) + else + mcl_player.player_set_visibility(obj_ref, true) + obj_ref:set_nametag_attributes({ color = { r = 255, g = 255, b = 255, a = 255 } }) + end + else + if hide then + local luaentity = obj_ref:get_luaentity() + EF.invisible[obj_ref].old_size = luaentity.visual_size + obj_ref:set_properties({ visual_size = { x = 0, y = 0 } }) + else + obj_ref:set_properties({ visual_size = EF.invisible[obj_ref].old_size }) + end end - - local is_player = player:is_player() - local entity = player:get_luaentity() - --local playername = player:get_player_name() - local skin_file - - if toggle then -- hide player - - skin_file = "mobs_mc_empty.png" - - if entity then - EF.invisible[player].old_size = entity.visual_size - elseif not is_player then -- if not a player or entity, do nothing - return - end - - if is_player then - mcl_player.player_set_skin(player, skin_file) - elseif not is_player then - player:set_properties({visual_size = {x = 0, y = 0}}) - end - player:set_nametag_attributes({color = {a = 0}}) - - elseif EF.invisible[player] then -- show player - - if is_player then - mcl_skins.update_player_skin(player) - elseif not is_player then - player:set_properties({visual_size = EF.invisible[player].old_size}) - end - player:set_nametag_attributes({color = {r = 255, g = 255, b = 255, a = 255}}) - - end - end @@ -987,3 +1005,18 @@ function mcl_potions._extinguish_nearby_fire(pos, radius) end return exting end + +function mcl_potions.bad_omen_func(player, factor, duration) + if not EF.bad_omen[player] then + EF.bad_omen[player] = {dur = duration, timer = 0, factor = factor} + else + local victim = EF.bad_omen[player] + victim.dur = math.max(duration, victim.dur - victim.timer) + victim.timer = 0 + victim.factor = factor + end + + if player:is_player() then + potions_set_icons(player) + end +end diff --git a/mods/ITEMS/mcl_potions/textures/mcl_potions_effect_bad_omen.png b/mods/ITEMS/mcl_potions/textures/mcl_potions_effect_bad_omen.png new file mode 100644 index 000000000..dfe8f0332 Binary files /dev/null and b/mods/ITEMS/mcl_potions/textures/mcl_potions_effect_bad_omen.png differ diff --git a/mods/ITEMS/mcl_sculk/init.lua b/mods/ITEMS/mcl_sculk/init.lua new file mode 100644 index 000000000..765a01051 --- /dev/null +++ b/mods/ITEMS/mcl_sculk/init.lua @@ -0,0 +1,267 @@ +local S = minetest.get_translator(minetest.get_current_modname()) +local mt_sound_play = minetest.sound_play + +local spread_to = {"mcl_core:stone","mcl_core:dirt","mcl_core:sand","mcl_core:dirt_with_grass","group:grass_block","mcl_core:andesite","mcl_core:diorite","mcl_core:granite","mcl_core:mycelium","group:dirt","mcl_end:end_stone","mcl_nether:netherrack","mcl_blackstone:basalt","mcl_nether:soul_sand","mcl_blackstone:soul_soil","mcl_crimson:warped_nylium","mcl_crimson:crimson_nylium","mcl_core:gravel"} + +local sounds = { + footstep = {name = "mcl_sculk_block", }, + dug = {name = "mcl_sculk_block", }, +} + +local SPREAD_RANGE = 8 +local SENSOR_RANGE = 8 +local SENSOR_DELAY = 0.5 +local SHRIEKER_COOLDOWN = 10 + +local adjacents = { + vector.new(1,0,0), + vector.new(-1,0,0), + vector.new(0,1,0), + vector.new(0,-1,0), + vector.new(0,0,1), + vector.new(0,0,-1), +} + +--[[ +local function sensor_action(p,tp) + local s = minetest.find_node_near(p,SPREAD_RANGE,{"mcl_sculk:shrieker"}) + local n = minetest.get_node(s) + if s and n.param2 ~= 1 then + minetest.sound_play("mcl_sculk_shrieker", {pos=s, gain=1.5, max_hear_distance = 16}, true) + n.param2 = 1 + minetest.set_node(s,n) + minetest.after(SHRIEKER_COOLDOWN,function(s) + minetest.set_node(s,{name = "mcl_sculk:shrieker",param2=0}) + end,s) + end + --local p1 = vector.offset(p,-SENSOR_RANGE,-SENSOR_RANGE,-SENSOR_RANGE) + --local p2 = vector.offset(p,SENSOR_RANGE,SENSOR_RANGE,SENSOR_RANGE) + --darken_area(p1,p2) +end + +function minetest.sound_play(spec, parameters, ephemeral) + local rt = mt_sound_play(spec, parameters, ephemeral) + if parameters.pos then + pos = parameters.pos + elseif parameters.to_player then + pos = minetest.get_player_by_name(parameters.to_player):get_pos() + end + if not pos then return rt end + local s = minetest.find_node_near(pos,SPREAD_RANGE,{"mcl_sculk:sensor"}) + if s then + --minetest.after(SENSOR_DELAY,sensor_action,s,pos) + end + return rt +end + +walkover.register_global(function(pos, node, player) + local s = minetest.find_node_near(pos,SPREAD_RANGE,{"mcl_sculk:sensor"}) + if not s then return end + local v = player:get_velocity() + if v.x == 0 and v.y == 0 and v.z == 0 then return end + if player:get_player_control().sneak then return end + local def = minetest.registered_nodes[node.name] + if def and def.sounds then + minetest.log("walkover "..node.name) + minetest.after(SENSOR_DELAY,sensor_action,s,pos) + end +end) +--]] + +local function get_node_xp(pos) + local meta = minetest.get_meta(pos) + return meta:get_int("xp") +end +local function set_node_xp(pos,xp) + local meta = minetest.get_meta(pos) + return meta:set_int("xp",xp) +end + +local function sculk_on_destruct(pos) + local xp = get_node_xp(pos) + local n = minetest.get_node(pos) + if n.param2 == 1 then + xp = 1 + end + local obs = mcl_experience.throw_xp(pos,xp) + for _,v in pairs(obs) do + local l = v:get_luaentity() + l._sculkdrop = true + end +end + +local function has_air(pos) + for _,v in pairs(adjacents) do + if minetest.get_item_group(minetest.get_node(vector.add(pos,v)).name,"solid") <= 0 then return true end + end +end + +local function has_nonsculk(pos) + for _,v in pairs(adjacents) do + local p = vector.add(pos,v) + if minetest.get_item_group(minetest.get_node(p).name,"sculk") <= 0 and minetest.get_item_group(minetest.get_node(p).name,"solid") > 0 then return p end + end +end + +local old_on_step = minetest.registered_entities["mcl_experience:orb"].on_step + +minetest.registered_entities["mcl_experience:orb"].on_step = function(self,dtime) + local p = self.object:get_pos() + local nu = minetest.get_node(vector.offset(p,0,-1,0)) + local ret = old_on_step(self,dtime) + if not self._sculkdrop then + local c = minetest.find_node_near(p,SPREAD_RANGE,{"mcl_sculk:catalyst"}) + if c then + local nnn = minetest.find_nodes_in_area(vector.offset(p,-SPREAD_RANGE,-SPREAD_RANGE,-SPREAD_RANGE),vector.offset(p,SPREAD_RANGE,SPREAD_RANGE,SPREAD_RANGE),spread_to) + local nn={} + for _,v in pairs(nnn) do + if has_air(v) then + table.insert(nn,v) + end + end + table.sort(nn,function(a, b) + return vector.distance(p, a) < vector.distance(p, b) + end) + if nn and #nn > 0 and self._xp > 0 then + local d = math.random(100) + --[[ --enable to generate shriekers and sensors + if d <= 1 then + minetest.set_node(nn[1],{name = "mcl_sculk:shrieker"}) + set_node_xp(nn[1],math.min(1,self._xp - 10)) + self.object:remove() + return ret + elseif d <= 9 then + minetest.set_node(nn[1],{name = "mcl_sculk:sensor"}) + set_node_xp(nn[1],math.min(1,self._xp - 5)) + self.object:remove() + return ret + else --]] + local r = math.min(math.random(#nn),self._xp) + for i=1,r do + minetest.set_node(nn[i],{name = "mcl_sculk:sculk" }) + set_node_xp(nn[i],math.floor(self._xp / r)) + end + for i=1,r do + local p = has_nonsculk(nn[i]) + if p and has_air(p) then + minetest.set_node(vector.offset(p,0,1,0),{name = "mcl_sculk:vein", param2 = 1}) + end + end + set_node_xp(nn[1],get_node_xp(nn[1]) + self._xp % r) + self.object:remove() + return ret + --end + end + end + end + return ret +end + +minetest.register_node("mcl_sculk:sculk", { + description = S("Sculk"), + tiles = { + { name = "mcl_sculk_sculk.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0, + }, }, + }, + drop = "", + groups = {handy = 1, hoey = 1, building_block=1, sculk = 1,}, + place_param2 = 1, + sounds = sounds, + is_ground_content = false, + on_destruct = sculk_on_destruct, + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, +}) + +minetest.register_node("mcl_sculk:vein", { + description = S("Sculk Vein"), + _doc_items_longdesc = S("Sculk vein."), + drawtype = "signlike", + tiles = {"mcl_sculk_vein.png"}, + inventory_image = "mcl_sculk_vein.png", + wield_image = "mcl_sculk_vein.png", + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "wallmounted", + walkable = false, + climbable = true, + buildable_to = true, + selection_box = { + type = "wallmounted", + }, + groups = { + handy = 1, axey = 1, shearsy = 1, swordy = 1, deco_block = 1, + dig_by_piston = 1, destroy_by_lava_flow = 1, sculk = 1, dig_by_water = 1, + }, + sounds = sounds, + drop = "", + _mcl_shears_drop = true, + node_placement_prediction = "", + _mcl_blast_resistance = 0.2, + _mcl_hardness = 0.2, + on_rotate = false, +}) + +minetest.register_node("mcl_sculk:catalyst", { + description = S("Sculk Catalyst"), + tiles = { + "mcl_sculk_catalyst_top.png", + "mcl_sculk_catalyst_bottom.png", + "mcl_sculk_catalyst_side.png" + }, + drop = "", + sounds = sounds, + groups = {handy = 1, hoey = 1, building_block=1, sculk = 1,}, + place_param2 = 1, + is_ground_content = false, + on_destruct = sculk_on_destruct, + _mcl_blast_resistance = 3, + light_source = 6, + _mcl_hardness = 3, + _mcl_silk_touch_drop = true, +}) + +--[[ +minetest.register_node("mcl_sculk:sensor", { + description = S("Sculk Sensor"), + tiles = { + "mcl_sculk_sensor_top.png", + "mcl_sculk_sensor_bottom.png", + "mcl_sculk_sensor_side.png" + }, + drop = "", + sounds = sounds, + groups = {handy = 1, hoey = 1, building_block=1, sculk = 1,}, + place_param2 = 1, + is_ground_content = false, + on_destruct = sculk_on_destruct, + _mcl_blast_resistance = 3, + light_source = 6, + _mcl_hardness = 3, + _mcl_silk_touch_drop = true, +}) +minetest.register_node("mcl_sculk:shrieker", { + description = S("Sculk Shrieker"), + tiles = { + "mcl_sculk_shrieker_top.png", + "mcl_sculk_shrieker_bottom.png", + "mcl_sculk_shrieker_side.png" + }, + drop = "", + sounds = sounds, + groups = {handy = 1, hoey = 1, building_block=1, sculk = 1,}, + place_param2 = 0, + is_ground_content = false, + on_destruct = sculk_on_destruct, + _mcl_blast_resistance = 3, + light_source = 6, + _mcl_hardness = 3, + _mcl_silk_touch_drop = true, +}) +--]] diff --git a/mods/ITEMS/mcl_sculk/mod.conf b/mods/ITEMS/mcl_sculk/mod.conf new file mode 100644 index 000000000..e9fc71e9a --- /dev/null +++ b/mods/ITEMS/mcl_sculk/mod.conf @@ -0,0 +1,3 @@ +name = mcl_sculk +author = cora +depends = mcl_core, mcl_sounds, mcl_experience, walkover diff --git a/mods/ITEMS/mcl_sculk/sounds/mcl_sculk.ogg b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk.ogg new file mode 100644 index 000000000..ca211128d Binary files /dev/null and b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk.ogg differ diff --git a/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_2.ogg b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_2.ogg new file mode 100644 index 000000000..352342880 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_2.ogg differ diff --git a/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_block.ogg b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_block.ogg new file mode 100644 index 000000000..e71425d4b Binary files /dev/null and b/mods/ITEMS/mcl_sculk/sounds/mcl_sculk_block.ogg differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_bottom.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_bottom.png new file mode 100644 index 000000000..1e50bfaae Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_bottom.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_side.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_side.png new file mode 100644 index 000000000..1a4edb6ed Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_side.png differ diff --git a/mods/ITEMS/mcl_beds/textures/portal.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_top.png similarity index 50% rename from mods/ITEMS/mcl_beds/textures/portal.png rename to mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_top.png index 160ad95f3..f3b4ebb95 100644 Binary files a/mods/ITEMS/mcl_beds/textures/portal.png and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_catalyst_top.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sculk.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sculk.png new file mode 100644 index 000000000..75edbae9a Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sculk.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_bottom.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_bottom.png new file mode 100644 index 000000000..e1f5e9242 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_bottom.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_side.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_side.png new file mode 100644 index 000000000..1041bf367 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_side.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_top.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_top.png new file mode 100644 index 000000000..3bdb0e7f5 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_sensor_top.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_bottom.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_bottom.png new file mode 100644 index 000000000..e1f5e9242 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_bottom.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_side.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_side.png new file mode 100644 index 000000000..b5a176dd6 Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_side.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_cod.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_top.png similarity index 57% rename from mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_cod.png rename to mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_top.png index 3026890f7..6bd98fb53 100644 Binary files a/mods/ENTITIES/mobs_mc/textures/extra_mobs_spawn_icon_cod.png and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_shrieker_top.png differ diff --git a/mods/ITEMS/mcl_sculk/textures/mcl_sculk_vein.png b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_vein.png new file mode 100644 index 000000000..53d62f70b Binary files /dev/null and b/mods/ITEMS/mcl_sculk/textures/mcl_sculk_vein.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png index 4286d3e83..f4d0b080f 100644 Binary files a/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png and b/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png differ diff --git a/mods/ITEMS/mcl_signs/README.txt b/mods/ITEMS/mcl_signs/README.txt index ee161fc95..e4fbead8a 100644 --- a/mods/ITEMS/mcl_signs/README.txt +++ b/mods/ITEMS/mcl_signs/README.txt @@ -1,4 +1,21 @@ -Mod based on reworked signs mod by PilzAdam: + +--- +# Mineclone2-Signs +--- +A reworking of MineClone 2's mcl_signs to be colorable and made to glow. Requires Minetest and Mineclone2. +--- + +Created by Michieal (FaerRaven) @ DateTime: 10/14/22 4:05 PM + + +Reworked to be an API and to allow players to color, and/or make the lettering for the signs glow (be bright at night). +Reworked by Michieal (FaerRaven), including the sign textures batch changed to be white instead of the original black. + +A special thanks to Cora for pointing me in the right direction (as always). + + +The original Mod, MCL_SIGNS is based on reworked signs mod by PilzAdam: + https://forum.minetest.net/viewtopic.php?t=3289 License of code and font: MIT License @@ -6,8 +23,22 @@ License of code and font: MIT License Font source: 04.jp.org, some modifications and additions were made (added support for Latin-1 Supplement) Original font license text states: “YOU MAY USE THEM AS YOU LIKE” (in about.gif file distributed with the font) -License of textures: See README.md in top directory of MineClone 2. +License of textures: See README.md in top directory of MineClone 2, with the exception of the following: +default_sign.png, default_sign_dark.png, default_sign_greyscale.png, mcl_signs_sign_dark.png, +mcl_signs_sign_greyscale.png are licensed as follows: +Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) (https://creativecommons.org/licenses/by-sa/4.0/). +Credit Michieal (Faerraven). The extra sign textures are provided for you to use, modify, etc., with the goal being to +make the game better. (All of these textures were changed / created by me, to make them usable / better.) License of models: GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html) + Models author: 22i. + Source: https://github.com/22i/amc + +Mineclone 2 source code: +https://git.minetest.land/MineClone2/MineClone2 + +--- +NOTE: This MODule requires Glow Squids in order for all features to work 100% correctly. Glow Squids are currently +in review by the MineClone 2 Team, and should be available soon after this initial release of the new signs. \ No newline at end of file diff --git a/mods/ITEMS/mcl_signs/SIGNS_API_DOC.txt b/mods/ITEMS/mcl_signs/SIGNS_API_DOC.txt new file mode 100644 index 000000000..e98741137 --- /dev/null +++ b/mods/ITEMS/mcl_signs/SIGNS_API_DOC.txt @@ -0,0 +1,122 @@ +--- +--- Generated by EmmyLua. +--- Created by Michieal (FaerRaven). +--- DateTime: 10/22/22 3:44 PM +--- + +SIGNS API + +--- How to Use: + +The simplest way to create a new sign is to use mcl_signs.register_sign [mcl_signs.register_sign (modname, color, _name, +ttsign)]. It's an all-in-one sign creator. It makes use of the standard textures for the signs, and colors them based on +the color code that you give it, and names it "mcl_signs:wall_sign" + _name. So, using the spruce sign to illustrate, it +would be named "mcl_signs:wall_sign_sprucewood", as we made _name equal to "_sprucewood" after the name of the +registered wood. + +To create a sign with specific textures: use the mcl_signs.register_sign_custom [mcl_signs.register_sign_custom +(modname, _name, tiles, color, inventory_image, wield_image, ttsign)]. Like the register_sign() function, this is also an +all-in-one sign creation function. With this function you can designate what textures to use, and give them a specified +color. This function follows the same naming conventions. + +If you wish to override / recreate one of the predefined signs, you may also do that. The reregister_sign() and +reregister_sign_custom() functions will replace an existing sign's definition with a new one. Caution, ONLY use this on +existing signs. If the sign doesn't exist, use the regular register_sign* functions. + +--- What the parameters mean, and what they do: + +* modname: optional (pass "" or "false" to ignore), for using mcl_signs with other mods to allow the creation of a sign +from the mod's wood (if installed). Use this to prevent failures of the specific mod is not installed that has the needed +information (textures, wood, etc.) Setting this is important, because it prevents items from being registered if the +mod in not installed. + +* tiles: the texture file to use for the sign's node. + +* color: color the texture file to use with this color. Use white (#FFFFFF) to negate the color, and just use the +texture as is. + +* inventory_image: the texture file to use for the sign's display in inventory. + +* wield_image: the texture file to use for the sign's weilded (in hand) object. + +* _name: the sign's name suffix, such as "_dark" or "_sprucewood", etc., appended to "wall_sign" or "standing_sign" + +* ttsign: the tool tip of the sign that gets translated. Shown when the mouse hovers the inventory sign. ttsign stands +for translated tooltip sign. + +* wood_item_string: example: "mcl_core:wood", "mcl_core:sprucewood" or "mymod:mywood". This is used when defining the +recipe for the sign. + +--- Other Functions of Importance: + +* register_dye [mcl_signs.register_dye (modname, item_name, color_code)] -- this registers a new dye that the sign knows +about so that the player can color their signs with the dye. +Parameters: + modname: your mod / module's name. make sure to use this for compatibility. + item_name: the item_string of the dye to register. + color_code: the hex code for the color to make the lettering. Also called HTML color code. Ex. "#FFFFFF" is white. + +* register_sign_craft [mcl_signs.register_sign_craft(modname, wood_item_string, _name)] -- this is what creates the +recipes for the sign, and makes the sign "burnable". Typically called right after the register_sign* functions. +Parameters: + _name: MUST be the same name as used for the sign. So, if your sign _name is "_sprucewood" then this should be too. + wood_item_string: the item_string of the wood to use for the sign's recipe. Example: "mcl_core:wood" (default oak). + modname: like with the other functions that has this parameter, used to make sure that nothing breaks. + +* make_lbm() [mcl_signs.make_lbm()] -- This innocuous function is very important. This is the function that makes the +signs work after reloading the game. This function is the last to be called in your sign creation work flow. Note, you +do not need to call this function after every definition, just at the end of the last definition. +(See Example WorkFlow below.) + +--- Example Workflow for sign creation. + +* these are, at the time of writing, a selection of the actual signs' definitions. Note the functions called, and when. + +-- ---------------------------- -- +-- Register Signs for use. -- +-- ---------------------------- -- + +-- sprucewood Sign +mcl_signs.register_sign_custom("mcl_core", "_sprucewood", + "mcl_signs_sign_dark.png","#ffffff", "default_sign_dark.png", + "default_sign_dark.png", "Spruce Sign" +) +mcl_signs.register_sign_craft("mcl_core", "mcl_core:sprucewood", "_sprucewood") + +-- darkwood Sign +mcl_signs.register_sign_custom("mcl_core", "_darkwood", + "mcl_signs_sign_greyscale.png","#856443", "default_sign_greyscale.png", + "default_sign_greyscale.png", "Dark Oak Sign" +) +mcl_signs.register_sign_craft("mcl_core", "mcl_core:darkwood", "_darkwood") + +-- acaciawood Sign +mcl_signs.register_sign("mcl_core", "#ea7479", "_acaciawood", "Acacia Sign") +mcl_signs.register_sign_craft("mcl_core", "mcl_core:acaciawood", "_acaciawood") + +-- junglewood Sign +mcl_signs.register_sign("mcl_core", "#866249", "_junglewood", "Jungle Sign") +mcl_signs.register_sign_craft("mcl_core", "mcl_core:junglewood", "_junglewood") + +-- Register the LBMs for the created signs. +mcl_signs.make_lbm() + +--- ----------------------------------------------------------------------------- + +* If you wish to use a recipe other than the standard sign recipe, you will need to define your own recipe. In doing so, +use this output line: + output = "mcl_signs:wall_sign" .. _name .. " 3", +where _name is the same string that you have used throughout your sign's workflow. That way, when players make the recipe, +they get your sign (x3). + +--- Future landmarks on the horizon for the Signs API: + +* Once the forthcoming Hanging Signs are in Minecraft, and we implement the code for them in here, hanging signs will +automatically exist as part of the signs' package. You won't have to change any of your code, it'll just be more +functional. :) + +* if you have suggestions, comments, etc., please contact me on MineClone 2's Discord server. + +And that... is all there is to it! + +-- written by Michieal. \ No newline at end of file diff --git a/mods/ITEMS/mcl_signs/init.lua b/mods/ITEMS/mcl_signs/init.lua index b6bfb3fe8..e724def68 100644 --- a/mods/ITEMS/mcl_signs/init.lua +++ b/mods/ITEMS/mcl_signs/init.lua @@ -1,580 +1,158 @@ +--- +--- Generated by EmmyLua. +--- Created by Michieal (FaerRaven). +--- DateTime: 10/14/22 4:05 PM +--- + local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) + +-- Signs API +dofile(modpath .. "/signs_api.lua") + +-- LOCALIZATION local S = minetest.get_translator(modname) -local F = minetest.formspec_escape - -local table = table - --- Load the characters map (characters.txt) ---[[ File format of characters.txt: -It's an UTF-8 encoded text file that contains metadata for all supported characters. It contains a sequence of info blocks, one for each character. Each info block is made out of 3 lines: -Line 1: The literal UTF-8 encoded character -Line 2: Name of the texture file for this character minus the “.png” suffix; found in the “textures/” sub-directory -Line 3: Currently ignored. Previously this was for the character width in pixels - -After line 3, another info block may follow. This repeats until the end of the file. - -All character files must be 5 or 6 pixels wide (5 pixels are preferred) -]] - -local chars_file = io.open(modpath.."/characters.txt", "r") --- FIXME: Support more characters (many characters are missing). Currently ASCII and Latin-1 Supplement are supported. -local charmap = {} -if not chars_file then - minetest.log("error", "[mcl_signs] : character map file not found") -else - while true do - local char = chars_file:read("*l") - if char == nil then - break - end - local img = chars_file:read("*l") - chars_file:read("*l") - charmap[char] = img - end -end - --- CONSTANTS -local SIGN_WIDTH = 115 - -local LINE_LENGTH = 15 -local NUMBER_OF_LINES = 4 - -local LINE_HEIGHT = 14 -local CHAR_WIDTH = 5 - - --- Helper functions -local function round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - -local function string_to_array(str) - local tab = {} - for i=1,string.len(str) do - table.insert(tab, string.sub(str, i,i)) - end - return tab -end - -local function string_to_line_array(str) - local tab = {} - local current = 1 - local linechar = 1 - tab[1] = "" - for _,char in ipairs(string_to_array(str)) do - -- New line - if char == "\n" then - current = current + 1 - tab[current] = "" - linechar = 1 - else - tab[current] = tab[current]..char - linechar = linechar + 1 - end - end - return tab -end - -local function create_lines(text) - local line_num = 1 - local tab = {} - for _, line in ipairs(string_to_line_array(text)) do - if line_num > NUMBER_OF_LINES then - break - end - table.insert(tab, line) - line_num = line_num + 1 - end - return tab -end - -local function generate_line(s, ypos) - local i = 1 - local parsed = {} - local width = 0 - local chars = 0 - local printed_char_width = CHAR_WIDTH + 1 - while chars < LINE_LENGTH and i <= #s do - local file - -- Get and render character - if charmap[s:sub(i, i)] then - file = charmap[s:sub(i, i)] - i = i + 1 - elseif i < #s and charmap[s:sub(i, i + 1)] then - file = charmap[s:sub(i, i + 1)] - i = i + 2 - else - -- No character image found. - -- Use replacement character: - file = "_rc" - i = i + 1 - minetest.log("verbose", "[mcl_signs] Unknown symbol in '"..s.."' at "..i) - end - if file then - width = width + printed_char_width - table.insert(parsed, file) - chars = chars + 1 - end - end - width = width - 1 - - local texture = "" - local xpos = math.floor((SIGN_WIDTH - width) / 2) - for i = 1, #parsed do - texture = texture..":"..xpos..","..ypos.."="..parsed[i]..".png" - xpos = xpos + printed_char_width - end - return texture -end - -local function generate_texture(lines, signnodename) - local texture = "[combine:"..SIGN_WIDTH.."x"..SIGN_WIDTH - local ypos - if signnodename == "mcl_signs:wall_sign" then - ypos = 30 - else - ypos = 0 - end - for i = 1, #lines do - texture = texture..generate_line(lines[i], ypos) - ypos = ypos + LINE_HEIGHT - end - return texture -end - -local n = 23/56 - 1/128 - -local signtext_info_wall = { - {delta = {x = 0, y = 0, z = n}, yaw = 0}, - {delta = {x = n, y = 0, z = 0}, yaw = math.pi / -2}, - {delta = {x = 0, y = 0, z = -n}, yaw = math.pi}, - {delta = {x = -n, y = 0, z = 0}, yaw = math.pi / 2}, -} - -local signtext_info_standing = {} - -local m = -1/16 + 1/64 - -for rot=0, 15 do - local yaw = math.pi*2 - (((math.pi*2) / 16) * rot) - local delta = vector.multiply(minetest.yaw_to_dir(yaw), m) - -- Offset because sign is a bit above node boundaries - delta.y = delta.y + 2/28 - table.insert(signtext_info_standing, { delta = delta, yaw = yaw }) -end - -local function get_rotation_level(facedir, nodename) - local rl = facedir * 4 - if nodename == "mcl_signs:standing_sign22_5" then - rl = rl + 1 - elseif nodename == "mcl_signs:standing_sign45" then - rl = rl + 2 - elseif nodename == "mcl_signs:standing_sign67_5" then - rl = rl + 3 - end - return rl -end - -local function get_wall_signtext_info(param2, nodename) - local dir = minetest.wallmounted_to_dir(param2) - if dir.x > 0 then - return 2 - elseif dir.z > 0 then - return 1 - elseif dir.x < 0 then - return 4 - else - return 3 - end -end - -local sign_groups = {handy=1,axey=1, deco_block=1, material_wood=1, attached_node=1, dig_by_piston=1, flammable=-1} - -local function destruct_sign(pos) - local objects = minetest.get_objects_inside_radius(pos, 0.5) - for _, v in ipairs(objects) do - local ent = v:get_luaentity() - if ent and ent.name == "mcl_signs:text" then - v:remove() - end - end - local players = minetest.get_connected_players() - for p=1, #players do - if vector.distance(players[p]:get_pos(), pos) <= 30 then - minetest.close_formspec(players[p]:get_player_name(), "mcl_signs:set_text_"..pos.x.."_"..pos.y.."_"..pos.z) - end - end -end - -local function update_sign(pos, fields, sender, force_remove) - local meta = minetest.get_meta(pos) - if not meta then - return - end - local text = meta:get_string("text") - if fields and (text == "" and fields.text) then - meta:set_string("text", fields.text) - text = fields.text - end - if text == nil then - text = "" - end - - local sign_info - local n = minetest.get_node(pos) - local nn = n.name - if nn == "mcl_signs:standing_sign" or nn == "mcl_signs:standing_sign22_5" or nn == "mcl_signs:standing_sign45" or nn == "mcl_signs:standing_sign67_5" then - sign_info = signtext_info_standing[get_rotation_level(n.param2, nn) + 1] - elseif nn == "mcl_signs:wall_sign" then - sign_info = signtext_info_wall[get_wall_signtext_info(n.param2)] - end - if sign_info == nil then - minetest.log("error", "[mcl_signs] Missing sign_info!") - return - end - - local objects = minetest.get_objects_inside_radius(pos, 0.5) - local text_entity - for _, v in ipairs(objects) do - local ent = v:get_luaentity() - if ent and ent.name == "mcl_signs:text" then - if force_remove then - v:remove() - else - text_entity = v - break - end - end - end - - if not text_entity then - text_entity = minetest.add_entity({ - x = pos.x + sign_info.delta.x, - y = pos.y + sign_info.delta.y, - z = pos.z + sign_info.delta.z}, "mcl_signs:text") - end - text_entity:get_luaentity()._signnodename = nn - text_entity:set_properties({textures={generate_texture(create_lines(text), nn)}}) - - text_entity:set_yaw(sign_info.yaw) -end - -local function show_formspec(player, pos) - minetest.show_formspec( - player:get_player_name(), - "mcl_signs:set_text_"..pos.x.."_"..pos.y.."_"..pos.z, - "size[6,3]textarea[0.25,0.25;6,1.5;text;"..F(S("Enter sign text:"))..";]label[0,1.5;"..F(S("Maximum line length: 15")).."\n"..F(S("Maximum lines: 4")).."]button_exit[0,2.5;6,1;submit;"..F(S("Done")).."]" - ) -end +-- HANDLE THE FORMSPEC CALLBACK minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname:find("mcl_signs:set_text_") == 1 then - local x, y, z = formname:match("mcl_signs:set_text_(.-)_(.-)_(.*)") - local pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)} - if not pos or not pos.x or not pos.y or not pos.z then return end - update_sign(pos, fields, player) - end + if formname:find("mcl_signs:set_text_") == 1 then + local x, y, z = formname:match("mcl_signs:set_text_(.-)_(.-)_(.*)") + local pos = { x = tonumber(x), y = tonumber(y), z = tonumber(z) } + if not pos or not pos.x or not pos.y or not pos.z then + return + end + mcl_signs:update_sign(pos, fields, player) + end end) -local node_sounds -if minetest.get_modpath("mcl_sounds") then - node_sounds = mcl_sounds.node_sound_wood_defaults() -end - -minetest.register_node("mcl_signs:wall_sign", { - description = S("Sign"), - _tt_help = S("Can be written"), - _doc_items_longdesc = S("Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them."), - _doc_items_usagehelp = S("After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again."), - inventory_image = "default_sign.png", - walkable = false, - is_ground_content = false, - wield_image = "default_sign.png", - node_placement_prediction = "", - paramtype = "light", - sunlight_propagates = true, - paramtype2 = "wallmounted", - drawtype = "mesh", - mesh = "mcl_signs_signonwallmount.obj", - selection_box = {type = "wallmounted", wall_side = {-0.5, -7/28, -0.5, -23/56, 7/28, 0.5}}, - tiles = {"mcl_signs_sign.png"}, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, - groups = sign_groups, - stack_max = 16, - sounds = node_sounds, - - on_place = function(itemstack, placer, pointed_thing) - local above = pointed_thing.above - local under = pointed_thing.under - - -- Use pointed node's on_rightclick function first, if present - local node_under = minetest.get_node(under) - if placer and not placer:get_player_control().sneak then - if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then - return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack - end - end - - local dir = vector.subtract(under, above) - - -- Only build when it's legal - local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] - if not abovenodedef or abovenodedef.buildable_to == false then - return itemstack - end - - local wdir = minetest.dir_to_wallmounted(dir) - - --local placer_pos = placer:get_pos() - - local fdir = minetest.dir_to_facedir(dir) - - local sign_info - local nodeitem = ItemStack(itemstack) - -- Ceiling - if wdir == 0 then - --how would you add sign to ceiling? - return itemstack - -- Floor - elseif wdir == 1 then - -- Standing sign - - -- Determine the sign rotation based on player's yaw - local yaw = math.pi*2 - placer:get_look_horizontal() - - -- Select one of 16 possible rotations (0-15) - local rotation_level = round((yaw / (math.pi*2)) * 16) - - if rotation_level > 15 then - rotation_level = 0 - elseif rotation_level < 0 then - rotation_level = 15 - end - - -- The actual rotation is a combination of predefined mesh and facedir (see node definition) - if rotation_level % 4 == 0 then - nodeitem:set_name("mcl_signs:standing_sign") - elseif rotation_level % 4 == 1 then - nodeitem:set_name("mcl_signs:standing_sign22_5") - elseif rotation_level % 4 == 2 then - nodeitem:set_name("mcl_signs:standing_sign45") - elseif rotation_level % 4 == 3 then - nodeitem:set_name("mcl_signs:standing_sign67_5") - end - fdir = math.floor(rotation_level / 4) - - -- Place the node! - local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) - if not success then - return itemstack - end - if not minetest.is_creative_enabled(placer:get_player_name()) then - itemstack:take_item() - end - sign_info = signtext_info_standing[rotation_level + 1] - -- Side - else - -- Wall sign - local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) - if not success then - return itemstack - end - sign_info = signtext_info_wall[fdir + 1] - end - - -- Determine spawn position of entity - local place_pos - if minetest.registered_nodes[node_under.name].buildable_to then - place_pos = under - else - place_pos = above - end - - local text_entity = minetest.add_entity({ - x = place_pos.x + sign_info.delta.x, - y = place_pos.y + sign_info.delta.y, - z = place_pos.z + sign_info.delta.z}, "mcl_signs:text") - text_entity:set_yaw(sign_info.yaw) - text_entity:get_luaentity()._signnodename = nodeitem:get_name() - - minetest.sound_play({name="default_place_node_hard", gain=1.0}, {pos = place_pos}, true) - - show_formspec(placer, place_pos) - return itemstack - end, - on_destruct = destruct_sign, - on_punch = function(pos, node, puncher) - update_sign(pos) - end, - on_rotate = function(pos, node, user, mode) - if mode == screwdriver.ROTATE_FACE then - local r = screwdriver.rotate.wallmounted(pos, node, mode) - node.param2 = r - minetest.swap_node(pos, node) - update_sign(pos, nil, nil, true) - return true - else - return false - end - end, - _mcl_hardness = 1, - _mcl_blast_resistance = 1, -}) - --- Standing sign nodes. --- 4 rotations at 0°, 22.5°, 45° and 67.5°. --- These are 4 out of 16 possible rotations. --- With facedir the remaining 12 rotations are constructed. - --- 0° -local ssign = { - paramtype = "light", - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, - sunlight_propagates = true, - walkable = false, - is_ground_content = false, - paramtype2 = "facedir", - drawtype = "mesh", - mesh = "mcl_signs_sign.obj", - selection_box = {type = "fixed", fixed = {-0.2, -0.5, -0.2, 0.2, 0.5, 0.2}}, - tiles = {"mcl_signs_sign.png"}, - groups = sign_groups, - drop = "mcl_signs:wall_sign", - stack_max = 16, - sounds = node_sounds, - - on_destruct = destruct_sign, - on_punch = function(pos, node, puncher) - update_sign(pos) - end, - on_rotate = function(pos, node, user, mode) - if mode == screwdriver.ROTATE_FACE then - node.name = "mcl_signs:standing_sign22_5" - minetest.swap_node(pos, node) - elseif mode == screwdriver.ROTATE_AXIS then - return false - end - update_sign(pos, nil, nil, true) - return true - end, - - _mcl_hardness = 1, - _mcl_blast_resistance = 1, -} - -minetest.register_node("mcl_signs:standing_sign", ssign) - --- 22.5° -local ssign22_5 = table.copy(ssign) -ssign22_5.mesh = "mcl_signs_sign22.5.obj" -ssign22_5.on_rotate = function(pos, node, user, mode) - if mode == screwdriver.ROTATE_FACE then - node.name = "mcl_signs:standing_sign45" - minetest.swap_node(pos, node) - elseif mode == screwdriver.ROTATE_AXIS then - return false - end - update_sign(pos, nil, nil, true) - return true -end -minetest.register_node("mcl_signs:standing_sign22_5", ssign22_5) - --- 45° -local ssign45 = table.copy(ssign) -ssign45.mesh = "mcl_signs_sign45.obj" -ssign45.on_rotate = function(pos, node, user, mode) - if mode == screwdriver.ROTATE_FACE then - node.name = "mcl_signs:standing_sign67_5" - minetest.swap_node(pos, node) - elseif mode == screwdriver.ROTATE_AXIS then - return false - end - update_sign(pos, nil, nil, true) - return true -end -minetest.register_node("mcl_signs:standing_sign45", ssign45) - --- 67.5° -local ssign67_5 = table.copy(ssign) -ssign67_5.mesh = "mcl_signs_sign67.5.obj" -ssign67_5.on_rotate = function(pos, node, user, mode) - if mode == screwdriver.ROTATE_FACE then - node.name = "mcl_signs:standing_sign" - node.param2 = (node.param2 + 1) % 4 - minetest.swap_node(pos, node) - elseif mode == screwdriver.ROTATE_AXIS then - return false - end - update_sign(pos, nil, nil, true) - return true -end -minetest.register_node("mcl_signs:standing_sign67_5", ssign67_5) - +-- This defines the text entity for the lettering of the sign. -- FIXME: Prevent entity destruction by /clearobjects minetest.register_entity("mcl_signs:text", { - pointable = false, - visual = "upright_sprite", - textures = {}, - physical = false, - collide_with_objects = false, + pointable = false, + visual = "upright_sprite", + textures = {}, + physical = false, + collide_with_objects = false, - _signnodename = nil, -- node name of sign node to which the text belongs + _signnodename = nil, -- node name of sign node to which the text belongs - on_activate = function(self, staticdata) - if staticdata and staticdata ~= "" then - local des = minetest.deserialize(staticdata) - if des then - self._signnodename = des._signnodename - end - end - local meta = minetest.get_meta(self.object:get_pos()) - local text = meta:get_string("text") - self.object:set_properties({ - textures={generate_texture(create_lines(text), self._signnodename)}, - }) - self.object:set_armor_groups({ immortal = 1 }) - end, - get_staticdata = function(self) - local out = { _signnodename = self._signnodename } - return minetest.serialize(out) - end, + on_activate = function(self, staticdata) + + local meta = minetest.get_meta(self.object:get_pos()) + local text = meta:get_string("text") + local text_color = meta:get_string("mcl_signs:text_color") + local glowing_sign = meta:get_string("mcl_signs:glowing_sign") + if staticdata and staticdata ~= "" then + local des = minetest.deserialize(staticdata) + if des then + self._signnodename = des._signnodename + if des._text_color ~= nil and des._text_color ~= "" then + self.text_color = des._text_color + end + if des._glowing_sign ~= nil and des._glowing_sign ~= "" then + self.glowing_sign = des._glowing_sign + end + end + end + + if text_color == "" or text_color == nil then + text_color = "#000000" -- default to black text. + meta:set_string("mcl_signs:text_color", text_color) + end + + if glowing_sign == "" or glowing_sign == nil then + glowing_sign = "false" -- default to not glowing. + meta:set_string("mcl_signs:glowing_sign", glowing_sign) + end + + self.object:set_properties({ + textures = { mcl_signs:create_lettering(text, self._signnodename, text_color) }, + }) + if glowing_sign == "true" then + self.object:set_properties({ + glow = 6, --sign_glow, + }) + end + + self.object:set_armor_groups({ immortal = 1 }) + + end, + get_staticdata = function(self) + local out = { + _signnodename = self._signnodename, + } + return minetest.serialize(out) + end, }) -minetest.register_craft({ - type = "fuel", - recipe = "mcl_signs:wall_sign", - burntime = 10, -}) +-- Build the signs x,y,z & rotations so that they work. (IE, do not remove!) +mcl_signs.build_signs_info() -if minetest.get_modpath("mcl_core") then - minetest.register_craft({ - output = "mcl_signs:wall_sign 3", - recipe = { - {"group:wood", "group:wood", "group:wood"}, - {"group:wood", "group:wood", "group:wood"}, - {"", "mcl_core:stick", ""}, - } - }) +-- ---------------------------- -- +-- Register Signs for use. -- +-- ---------------------------- -- + +-- Standard (original) Sign +mcl_signs.register_sign("mcl_core", "#ffffff", "", "Sign") +mcl_signs.register_sign_craft("mcl_core", "mcl_core:wood", "") + +-- birchwood Sign "#d5cb8d" / "#ffdba7" +mcl_signs.register_sign_custom("mcl_core", "_birchwood", + "mcl_signs_sign_greyscale.png","#ffdba7", "default_sign_greyscale.png", + "default_sign_greyscale.png", "Birch Sign" +) +mcl_signs.register_sign_craft("mcl_core", "mcl_core:birchwood", "_birchwood") + +-- sprucewood Sign +mcl_signs.register_sign_custom("mcl_core", "_sprucewood", + "mcl_signs_sign_dark.png","#ffffff", "default_sign_dark.png", + "default_sign_dark.png", "Spruce Sign" +) +mcl_signs.register_sign_craft("mcl_core", "mcl_core:sprucewood", "_sprucewood") + +-- darkwood Sign "#291f1a" / "#856443" +mcl_signs.register_sign_custom("mcl_core", "_darkwood", + "mcl_signs_sign_greyscale.png","#856443", "default_sign_greyscale.png", + "default_sign_greyscale.png", "Dark Oak Sign" +) +mcl_signs.register_sign_craft("mcl_core", "mcl_core:darkwood", "_darkwood") + +-- junglewood Sign +mcl_signs.register_sign("mcl_core", "#866249", "_junglewood", "Jungle Sign") +mcl_signs.register_sign_craft("mcl_core", "mcl_core:junglewood", "_junglewood") + +-- acaciawood Sign "b8693d" +mcl_signs.register_sign("mcl_core", "#ea7479", "_acaciawood", "Acacia Sign") +mcl_signs.register_sign_craft("mcl_core", "mcl_core:acaciawood", "_acaciawood") + +if minetest.get_modpath("mcl_mangrove") then + -- mangrove_wood Sign "#c7545c" + mcl_signs.register_sign("mcl_mangrove", "#b8693d", "_mangrove_wood", "Mangrove Sign") + mcl_signs.register_sign_craft("mcl_mangrove", "mcl_mangrove:mangrove_wood", "_mangrove_wood") end -if minetest.get_modpath("doc") then - doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign") - doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign22_5") - doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign45") - doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign67_5") +-- add in the nether wood signs +if minetest.get_modpath("mcl_crimson") then + + -- warped_hyphae_wood Sign + mcl_signs.register_sign_custom("mcl_crimson","_warped_hyphae_wood", "mcl_signs_sign_greyscale.png", + "#9f7dcf", "default_sign_greyscale.png", "default_sign_greyscale.png", + "Warped Hyphae Sign") + mcl_signs.register_sign_craft("mcl_crimson", "mcl_crimson:warped_hyphae_wood", "_warped_hyphae_wood") + + -- crimson_hyphae_wood Sign + mcl_signs.register_sign_custom("mcl_crimson", "_crimson_hyphae_wood","mcl_signs_sign_greyscale.png", + "#c35f51","default_sign_greyscale.png", "default_sign_greyscale.png", + "Crimson Hyphae Sign") + mcl_signs.register_sign_craft("mcl_crimson", "mcl_crimson:crimson_hyphae_wood", "_crimson_hyphae_wood") + end +-- Register the LBMs for the created signs. +mcl_signs.make_lbm() + +-- really ancient compatibility. minetest.register_alias("signs:sign_wall", "mcl_signs:wall_sign") minetest.register_alias("signs:sign_yard", "mcl_signs:standing_sign") - -minetest.register_lbm({ - name = "mcl_signs:respawn_entities", - label = "Respawn sign text entities", - run_at_every_load = true, - nodenames = { "mcl_signs:wall_sign", "mcl_signs:standing_sign", "mcl_signs:standing_sign22_5", "mcl_signs:standing_sign45", "mcl_signs:standing_sign67_5" }, - action = function(pos, node) - update_sign(pos) - end, -}) +minetest.register_alias("mcl_signs:wall_sign_dark", "mcl_signs:wall_sign_sprucewood") +minetest.register_alias("mcl_signs:standing_sign_dark", "mcl_signs:standing_sign_sprucewood") diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.de.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.de.tr index a7513659b..323e90364 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.de.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.de.tr @@ -1,9 +1,18 @@ # textdomain: mcl_signs -Sign=Schild +Sign=Zeichen / Schild Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=Schilder können beschrieben werden und kommen in zwei Varianten: Wandschild und stehendes Schild. Sie können auf und an den Seiten von anderen Blöclen platziert werden, aber nicht unter ihnen. -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=Nachdem das Schild platziert wurde, kann man etwas darauf schreiben. 4 Zeilen mit je 15 Zeichen pro Zeile sind verfügbar, alles darüber geht verloren. Es werden nicht alle Zeichen unterstützt. Der Text kann nicht geändert werden, sobald er geschrieben wurde; man muss das Schild erneut platzieren. +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=Nachdem das Schild platziert wurde, kann man etwas darauf schreiben. 4 Zeilen mit je 15 Zeichen pro Zeile sind verfügbar, alles darüber geht verloren. Es werden nicht alle Zeichen unterstützt. Der Text kann nicht geändert werden, sobald er geschrieben wurde; man muss das Schild erneut platzieren. Kann gefärbt und zum Leuchten gebracht werden. Enter sign text:=Schildtext eingeben: Maximum line length: 15=Maximale Zeilenlänge: 15 Maximum lines: 4=Maximale Zeilen: 4 Done=Fertig Can be written=Kann beschriftet werden +Oak Sign=Eichezeichen +Birch Sign=Birke Zeichen +Spruce Sign=Fichtenzeichen +Dark Oak Sign=Dunkles Eichenschild +Jungle Sign=Dschungelzeichen +Acacia Sign=Akazienzeichen +Mangrove Sign=Mangroven-Zeichen +Warped Hyphae Sign=Verzerrtes Hyphen-Zeichen +Crimson Hyphae Sign=Hochrotes Hyphen-Zeichen diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.es.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.es.tr index d67e2da0d..87f737935 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.es.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.es.tr @@ -1,8 +1,18 @@ # textdomain: mcl_signs -Sign=Firmar +Sign=Signo / Firmar Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=Los letreros se pueden escribir y vienen en dos variantes: letrero de muro y letrero en un poste de letrero. Los letreros se pueden colocar en la parte superior y en los costados de otros bloques, pero no debajo de ellos. -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=Después de colocar el letrero, puede escribir algo en él. Tiene 4 líneas de texto con hasta 15 caracteres para cada línea; todo lo que esté más allá de estos límites se pierde. No todos los personajes son compatibles. El texto no se puede cambiar una vez que se ha escrito; tienes que romper y colocar el letrero nuevamente. +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=Después de colocar el letrero, puede escribir algo en él. Tiene 4 líneas de texto con hasta 15 caracteres para cada línea; todo lo que esté más allá de estos límites se pierde. No todos los personajes son compatibles. El texto no se puede cambiar una vez que se ha escrito; tienes que romper y colocar el letrero nuevamente. Enter sign text:=Inserte el texto del letrero: Maximum line length: 15=Longitud máxima de línea: 15 Maximum lines: 4=Líneas máximas: 4 +Can be written=Los letreros se pueden escribir Done=Escribir cartel +Oak Sign=Signo de roble +Birch Sign=Signo de abedul +Spruce Sign=Signo de abeto +Dark Oak Sign=Signo de roble oscuro +Jungle Sign= Signo de la selva +Acacia Sign= Signo de acacia +Mangrove Sign= Signo de manglar +Warped Hyphae Sign=Signo de hifas deformadas +Crimson Hyphae Sign=Signo de hifas carmesí diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr index 158640dae..0cc571e70 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.fr.tr @@ -1,9 +1,18 @@ # textdomain: mcl_signs -Sign=Panneau +Sign=Panneau / signe Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=Les panneaux peuvent être écrits et se déclinent en deux variantes: panneau mural et panneau sur poteau. Des panneaux peuvent être placés en haut et sur les côtés des autres blocs, mais pas en dessous. -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=Après avoir placé le panneau, vous pouvez écrire quelque chose dessus. Vous avez 4 lignes de texte avec jusqu'à 15 caractères pour chaque ligne; tout ce qui dépasse ces limites est perdu. Tous les caractères ne sont pas pris en charge. Le texte ne peut pas être modifié une fois qu'il a été écrit; vous devez casser et placer à nouveau le panneau. +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=Après avoir placé le panneau, vous pouvez écrire quelque chose dessus. Vous avez 4 lignes de texte avec jusqu'à 15 caractères pour chaque ligne; tout ce qui dépasse ces limites est perdu. Tous les caractères ne sont pas pris en charge. Le texte ne peut pas être modifié une fois qu'il a été écrit; vous devez casser et placer à nouveau le panneau. Peut être coloré et rendu brillant. Enter sign text:=Saisir le texte du panneau: Maximum line length: 15=Longueur maximum des lignes: 15 Maximum lines: 4=Nombre maximum de lignes: 4 Done=Terminé Can be written=Peut être écrit +Oak Sign=Signe de chêne +Birch Sign=Signe de bouleau +Spruce Sign=Signe d'épinette +Dark Oak Sign=Enseigne Chêne Foncé +Jungle Sign=Signe de la jungle +Acacia Sign=Signe d'acacia +Mangrove Sign=Signe de la mangrove +Warped Hyphae Sign=Signe hyphe déformé +Crimson Hyphae Sign=Signe d'hyphes cramoisi \ No newline at end of file diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.pl.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.pl.tr index bf3bbf3c8..b9fbcd1bf 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.pl.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.pl.tr @@ -1,9 +1,18 @@ # textdomain: mcl_signs Sign=Znak Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=Na znakach można pisać i postawić je w dwóch wariantach: znak ścienny i znak na patyku. Znaki mogą być stawiane na górze i na bokach bloków, ale nie pod nimi. -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=Po postawieniu znaku możesz coś na nim napisać. Masz miejsce na cztery linie tekstu po 15 znaków każda; cokolwiek poza limitami będzie utracone. Nie wszystkie znaki są wspierane. Tekstu nie można zmienić po napisaniu; musisz zniszczyć znak i postawić go ponownie. +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=Po postawieniu znaku możesz coś na nim napisać. Masz miejsce na cztery linie tekstu po 15 znaków każda; cokolwiek poza limitami będzie utracone. Nie wszystkie znaki są wspierane. Tekstu nie można zmienić po napisaniu; musisz zniszczyć znak i postawić go ponownie. Może być pokolorowany i rozświetlony. Enter sign text:=Wpisz tekst znaku: Maximum line length: 15=Maksymalna długość linii: 15 Maximum lines: 4=Maksymalna liczba linii: 4 Done=Skończone Can be written=Można na nim coś napisać +Oak Sign=Znak dębu +Birch Sign=Brzoza Znak +Spruce Sign=Świerk Znak +Dark Oak Sign=Znak ciemnego dębu +Jungle Sign=Znak Dżungli +Acacia Sign=Znak akacji +Mangrove Sign=Znak namorzynowy +Warped Hyphae Sign=Wypaczony znak strzępek +Crimson Hyphae Sign=Karmazynowy znak strzępek diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.ru.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.ru.tr index 354e556a8..279bde614 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.ru.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.ru.tr @@ -1,9 +1,18 @@ # textdomain: mcl_signs Sign=Табличка Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=На табличках можно писать. Таблички бывают двух видов: настенные и отдельно стоящие. Таблички можно размещать на верхушках и сторонах блоков, но не под блоками. -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=После установки таблички вы можете написать на ней что-то. Вам доступны 4 строки текста, до 15 символов в каждой; всё, что вы напишете сверх лимита, потеряется. Поддерживаются не все символы. Текст нельзя изменить. Чтобы изменить его, вам придётся сломать табличку и подписать её снова. +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=После установки таблички вы можете написать на ней что-то. Вам доступны 4 строки текста, до 15 символов в каждой; всё, что вы напишете сверх лимита, потеряется. Поддерживаются не все символы. Текст нельзя изменить. Чтобы изменить его, вам придётся сломать табличку и подписать её снова. Можно раскрасить и заставить светиться. Enter sign text:=Текст на табличке: Maximum line length: 15=Максимальная длина строки: 15 Maximum lines: 4=Максимум строк: 4 Done=Готово Can be written=Может быть подписана +Oak Sign=Дубовый знак +Birch Sign=Березовый знак +Spruce Sign=Ель Знак +Dark Oak Sign=Знак темного дуба +Jungle Sign=Знак джунглей +Acacia Sign=Знак акации +Mangrove Sign=Знак мангровых зарослей +Warped Hyphae Sign=Знак искривленных гиф +Crimson Hyphae Sign=Багровый знак гиф diff --git a/mods/ITEMS/mcl_signs/locale/mcl_signs.zh_TW.tr b/mods/ITEMS/mcl_signs/locale/mcl_signs.zh_TW.tr index 62994bc3d..d2cabe04e 100644 --- a/mods/ITEMS/mcl_signs/locale/mcl_signs.zh_TW.tr +++ b/mods/ITEMS/mcl_signs/locale/mcl_signs.zh_TW.tr @@ -1,9 +1,16 @@ # textdomain: mcl_signs Sign=告示牌 Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.=告示牌可以寫字,有兩種變體:牆上的告示牌和柱上的告示牌。告示牌可以放在其他方塊的頂部和側面,但不能放在下面。 -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.=放置告示牌後,你可以在上面寫東西。你最多可以寫4行文字,每行最多可以寫15個字符;超過這些限制的文字就會丟失。不是所有的字符都被支持。文字一旦寫完就不能更改;你必須打破並重新放置標誌。 +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.=放置告示牌後,你可以在上面寫東西。你最多可以寫4行文字,每行最多可以寫15個字符;超過這些限制的文字就會丟失。不是所有的字符都被支持。文字一旦寫完就不能更改;你必須打破並重新放置標誌。可以著色並發光。 Enter sign text:=輸入告示牌文字: Maximum line length: 15=每行最多可以寫15個字符 Maximum lines: 4=最多可以寫4行文字 Done=確認 Can be written=可以寫字 +Oak Sign=橡木標誌 +Birch Sign=樺木標誌 +Spruce Sign=雲杉標誌 +Dark Oak Sign=深色橡木標誌 +Jungle Sign=叢林標誌 +Acacia Sign=相思標誌 +Mangrove Sign=紅樹林標誌 diff --git a/mods/ITEMS/mcl_signs/locale/template.txt b/mods/ITEMS/mcl_signs/locale/template.txt index 6635e989f..137cc44cd 100644 --- a/mods/ITEMS/mcl_signs/locale/template.txt +++ b/mods/ITEMS/mcl_signs/locale/template.txt @@ -1,9 +1,16 @@ # textdomain: mcl_signs Sign= Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them.= -After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again.= +After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow.= Enter sign text:= Maximum line length: 15= Maximum lines: 4= Done= Can be written= +Oak Sign= +Birch Sign= +Spruce Sign= +Dark Oak Sign= +Jungle Sign= +Acacia Sign= +Mangrove Sign= diff --git a/mods/ITEMS/mcl_signs/mod.conf b/mods/ITEMS/mcl_signs/mod.conf index 1af689d7b..ada0ae58a 100644 --- a/mods/ITEMS/mcl_signs/mod.conf +++ b/mods/ITEMS/mcl_signs/mod.conf @@ -1,2 +1,4 @@ name = mcl_signs -optional_depends = mcl_sounds, mcl_core, doc +description = New and Improved signs - can be colored and made to glow. +depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors +optional_depends = doc diff --git a/mods/ITEMS/mcl_signs/signs_api.lua b/mods/ITEMS/mcl_signs/signs_api.lua new file mode 100644 index 000000000..1f7369ba3 --- /dev/null +++ b/mods/ITEMS/mcl_signs/signs_api.lua @@ -0,0 +1,2003 @@ +--- +--- Generated by EmmyLua. +--- Created by Michieal (FaerRaven). +--- DateTime: 10/14/22 4:05 PM +--- + +--local logging = minetest.settings:get_bool("mcl_logging_mcl_signs",true) + +local DEBUG = minetest.settings:get_bool("mcl_logging_mcl_signs", false) -- special debug setting. + +if DEBUG then + minetest.log("action", "[mcl_signs] Signs API Loading") +end + +-- LOCALIZATION +local S = minetest.get_translator("mcl_signs") +-- Signs form +local F = minetest.formspec_escape + +-- PATHs +local modpath = minetest.get_modpath("mcl_signs") + +-- CONSTANTS +local SIGN_WIDTH = 115 + +local LINE_LENGTH = 15 +local NUMBER_OF_LINES = 4 + +local LINE_HEIGHT = 14 +local CHAR_WIDTH = 5 +local TIMER_INTERVAL = 40.0 +-- ----------------------- +-- CACHE LOCAL COPIES +local table = table +local string = string + +-- CACHE NODE_SOUNDS +local node_sounds +if minetest.get_modpath("mcl_sounds") then + node_sounds = mcl_sounds.node_sound_wood_defaults() +end + +-- SET UP THE CHARACTER MAPPING +-- Load the characters map (characters.txt) +--[[ File format of characters.txt: +It's an UTF-8 encoded text file that contains metadata for all supported characters. It contains a sequence of info + blocks, one for each character. Each info block is made out of 3 lines: +Line 1: The literal UTF-8 encoded character +Line 2: Name of the texture file for this character minus the “.png” suffix; found in the “textures/” sub-directory +Line 3: Currently ignored. Previously this was for the character width in pixels + +After line 3, another info block may follow. This repeats until the end of the file. + +All character files must be 5 or 6 pixels wide (5 pixels are preferred) +]] + +local chars_file = io.open(modpath .. "/characters.txt", "r") +-- FIXME: Support more characters (many characters are missing). Currently ASCII and Latin-1 Supplement are supported. +local charmap = {} +if not chars_file then + minetest.log("error", "[mcl_signs] : character map file not found") +else + while true do + local char = chars_file:read("*l") + if char == nil then + break + end + local img = chars_file:read("*l") + chars_file:read("*l") + charmap[char] = img + end +end + +local pi = 3.1415926 -- enough accuracy, to build an engine for a car. + +local math = math + +-- locally cached copy of the official colors; this way, it updates as mcl_colors updates. +local mcl_colors_official = mcl_colors +if DEBUG then + minetest.log("verbose", "[mcl_signs]Official MCL_Colors:\n" .. dump(mcl_colors_official)) +end + +-- INITIALIZE THE GLOBAL API FOR SIGNS. +mcl_signs = {} + +-- GLOBALS +mcl_signs.sign_groups = { handy = 1, axey = 1, deco_block = 1, material_wood = 1, attached_node = 1, dig_by_piston = 1, flammable = -1 } +--- colors used for wools. +mcl_signs.mcl_wool_colors = { + unicolor_white = "#FFFFFF", + unicolor_dark_orange = "#502A00", + unicolor_grey = "#5B5B5B", + unicolor_darkgrey = "#303030", + unicolor_blue = "#0000CC", + unicolor_dark_green = "#005000", + unicolor_green_or_lime = "#50CC00", + unicolor_violet_purple = "#5000CC", + unicolor_light_red_pink = "#FF5050", + unicolor_yellow = "#CCCC00", + unicolor_orange = "#CC5000", + unicolor_red = "#CC0000", + unicolor_cyan = "#00CCCC", + unicolor_red_violet_magenta = "#CC0050", + unicolor_black = "#000000", + unicolor_light_blue = "#5050FF", +} +mcl_signs.signtext_info_wall = {} +mcl_signs.signtext_info_standing = {} -- built in build_signs_info(). +-- the rotational levels for all of the standing signs. +mcl_signs.standing_rotation_levels = {} + +-- data structure block for dynamically registered signs. +mcl_signs.registered_signs = {} +mcl_signs.registered_signs.wall_signs = {} +mcl_signs.registered_signs.standing_signs = {} +mcl_signs.registered_signs.hanging_signs = {} -- unused. prepping for future use. +-- DEFINE SIGN BASE TYPES +mcl_signs.wall_standard = {} -- initialize +mcl_signs.standing_standard = {} -- initialize + +function mcl_signs.build_signs_info() + local n = 23 / 56 - 1 / 128 -- some required magic number from the original code. + local m = -1 / 16 + 1 / 64 -- " " " " " " " " + + mcl_signs.signtext_info_wall = { + { delta = { x = 0, y = 0, z = n }, yaw = 0 }, + { delta = { x = n, y = 0, z = 0 }, yaw = pi / -2 }, + { delta = { x = 0, y = 0, z = -n }, yaw = pi }, + { delta = { x = -n, y = 0, z = 0 }, yaw = pi / 2 }, + } + + -- PLACE YAW VALUES INTO THE TABLE. + for rot = 0, 15 do + local yaw = pi * 2 - (((pi * 2) / 16) * rot) + local delta = vector.multiply(minetest.yaw_to_dir(yaw), m) + -- Offset because sign is a bit above node boundaries + delta.y = delta.y + 2 / 28 + table.insert(mcl_signs.signtext_info_standing, { delta = delta, yaw = yaw }) + end + +end + +-- wall signs' & hanging signs' base (definition) +mcl_signs.wall_standard = { + description = S("Sign"), + _tt_help = S("Can be written"), + _doc_items_longdesc = S("Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them."), + _doc_items_usagehelp = S("After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. Not all characters are supported. The text can not be changed once it has been written; you have to break and place the sign again. Can be colored and made to glow."), + inventory_image = "default_sign.png", + walkable = false, + is_ground_content = false, + wield_image = "default_sign.png", + node_placement_prediction = "", + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "wallmounted", + drawtype = "mesh", + mesh = "mcl_signs_signonwallmount.obj", + selection_box = { type = "wallmounted", wall_side = { -0.5, -7 / 28, -0.5, -23 / 56, 7 / 28, 0.5 } }, + tiles = { "mcl_signs_sign.png" }, + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + groups = mcl_signs.sign_groups, + stack_max = 16, + sounds = node_sounds, + + on_timer = function(pos) + -- fix for /ClearObjects + mcl_signs:update_sign(pos) + -- note: update_sign decides to keep the timer running based on if there is text. + -- This prevents every sign from having a timer, when not needed. + end, + + on_place = function(itemstack, placer, pointed_thing) + local above = pointed_thing.above + local under = pointed_thing.under + + -- Use pointed node's on_rightclick function first, if present + local node_under = minetest.get_node(under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then + return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack + end + end + + local dir = vector.subtract(under, above) + + -- Only build when it's legal + local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] + if not abovenodedef or abovenodedef.buildable_to == false then + return itemstack + end + + local wdir = minetest.dir_to_wallmounted(dir) + + --local placer_pos = placer:get_pos() + + local fdir = minetest.dir_to_facedir(dir) + + local sign_info + local nodeitem = ItemStack(itemstack) + -- Ceiling + if wdir == 0 then + --how would you add sign to ceiling? + return itemstack + -- Floor + end + + if wdir == 1 then + -- Standing sign + + -- Determine the sign rotation based on player's yaw + local yaw = pi * 2 - placer:get_look_horizontal() + + -- Select one of 16 possible rotations (0-15) + local rotation_level = mcl_signs:round((yaw / (pi * 2)) * 16) + + if rotation_level > 15 then + rotation_level = 0 + elseif rotation_level < 0 then + rotation_level = 15 + end + + -- The actual rotation is a combination of predefined mesh and facedir (see node definition) + if rotation_level % 4 == 0 then + nodeitem:set_name("mcl_signs:standing_sign") + elseif rotation_level % 4 == 1 then + nodeitem:set_name("mcl_signs:standing_sign22_5") + elseif rotation_level % 4 == 2 then + nodeitem:set_name("mcl_signs:standing_sign45") + elseif rotation_level % 4 == 3 then + nodeitem:set_name("mcl_signs:standing_sign67_5") + end + fdir = math.floor(rotation_level / 4) + + -- Place the node! + local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) + if not success then + return itemstack + end + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + sign_info = mcl_signs.signtext_info_standing[rotation_level + 1] + -- Side + else + -- Wall sign + local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + if not success then + return itemstack + end + sign_info = mcl_signs.signtext_info_wall[fdir + 1] + end + + -- Determine spawn position of entity + local place_pos + if minetest.registered_nodes[node_under.name].buildable_to then + place_pos = under + else + place_pos = above + end + + local text_entity = minetest.add_entity({ + x = place_pos.x + sign_info.delta.x, + y = place_pos.y + sign_info.delta.y, + z = place_pos.z + sign_info.delta.z }, "mcl_signs:text") + text_entity:set_yaw(sign_info.yaw) + text_entity:get_luaentity()._signnodename = nodeitem:get_name() + if DEBUG then + minetest.log("verbose", "[mcl_signs]Placed position:" .. dump(place_pos) .. "\nSign_info: " .. dump(sign_info)) + end + + minetest.sound_play({ name = "default_place_node_hard", gain = 1.0 }, { pos = place_pos }, true) + + mcl_signs:show_formspec(placer, place_pos) + return itemstack + end, + on_destruct = function(pos) + mcl_signs:destruct_sign(pos) + end, + + -- Not Useless Code. force updates the sign. + on_punch = function(pos, node, puncher) + mcl_signs:update_sign(pos) + end, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + local r = screwdriver.rotate.wallmounted(pos, node, mode) + node.param2 = r + minetest.swap_node(pos, node) + mcl_signs:update_sign(pos, nil, nil, true) + return true + else + return false + end + end, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if DEBUG then + minetest.log("verbose", "[mcl_signs] Wall_Sign Right Click event.") + end + + -- make sure player is clicking + if not clicker or not clicker:is_player() then + return + end + + local item = clicker:get_wielded_item() + local iname = item:get_name() + + if node then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Wall_Sign Right Click event on valid node.") + end + + -- handle glow from glow_ink_sac *first* + if (iname == "mcl_mobitems:glow_ink_sac") then + clicker:set_wielded_item(item) + local success = mcl_signs:glow_sign(pos) + if success then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Sign Glow Success.") + end + itemstack:take_item() + end + return + end + + -- "mcl_dye:black" is a special case: it makes the sign's lettering black AND removes glow. + if (iname == "mcl_dye:black") then + clicker:set_wielded_item(item) + local success = mcl_signs:glow_sign(pos, true) + mcl_signs:color_sign(pos, mcl_colors.BLACK) + if success then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Sign Glow removal Success.") + end + + itemstack:take_item() + end + return + end + + -- check the wielded item to make sure that it is a dye. + local txt_color = mcl_signs:get_color_for_sign(iname) + if txt_color ~= "false" then + clicker:set_wielded_item(item) + local success = mcl_signs:color_sign(pos, txt_color) + if success then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Sign Color Success.") + end + itemstack:take_item() + end + end + end + end, + + _mcl_hardness = 1, + _mcl_blast_resistance = 1, +} +-- standing sign base (definition) +mcl_signs.standing_standard = { + paramtype = "light", + use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, + sunlight_propagates = true, + walkable = false, + is_ground_content = false, + paramtype2 = "facedir", + drawtype = "mesh", + mesh = "mcl_signs_sign.obj", + selection_box = { type = "fixed", fixed = { -0.2, -0.5, -0.2, 0.2, 0.5, 0.2 } }, + tiles = { "mcl_signs_sign.png" }, + groups = mcl_signs.sign_groups, + drop = "mcl_signs:wall_sign", + stack_max = 16, + sounds = node_sounds, + + on_destruct = function(pos) + mcl_signs:destruct_sign(pos) + end, + + on_timer = function(pos) + -- fix for /ClearObjects + mcl_signs:update_sign(pos) + minetest.get_node_timer(pos):start(40.0) + end, + + -- Not Useless Code. this force updates the sign. + on_punch = function(pos, node, puncher) + mcl_signs:update_sign(pos) + end, + on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign22_5" + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end, + + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + + if DEBUG then + minetest.log("verbose", "[mcl_signs] Standing_Sign Right Click event.") + end + + -- make sure player is clicking + if not clicker or not clicker:is_player() then + return + end + + local item = clicker:get_wielded_item() + local iname = item:get_name() + + if node then + -- handle glow from glow_ink_sac *first* + if DEBUG then + minetest.log("verbose", "[mcl_signs] Standing_Sign Right Click event on valid node.") + end + + if (iname == "mcl_mobitems:glow_ink_sac") then + clicker:set_wielded_item(item) + local success = mcl_signs:glow_sign(pos) + if success then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Sign Glow Success.") + end + itemstack:take_item() + end + return + end + + -- check the wielded item to make sure that it is a dye. + local txt_color = mcl_signs:get_color_for_sign(iname) + if txt_color ~= "false" then + clicker:set_wielded_item(item) + local success = mcl_signs:color_sign(pos, txt_color) + if success then + if DEBUG then + minetest.log("verbose", "[mcl_signs] Sign Color Success.") + end + itemstack:take_item() + end + end + end + end, + + _mcl_hardness = 1, + _mcl_blast_resistance = 1, +} + +-- HELPER FUNCTIONS' VARIABLES +local sign_glow = 6 +local Dyes_table = { + { "mcl_dye:aqua", mcl_colors_official.AQUA }, + { "mcl_dye:black", mcl_colors_official.BLACK }, + { "mcl_dye:blue", mcl_colors_official.BLUE }, + { "mcl_dye:brown", mcl_colors_official.brown }, + { "mcl_dye:cyan", mcl_signs.mcl_wool_colors.unicolor_cyan }, + { "mcl_dye:green", mcl_colors_official.GREEN }, + { "mcl_dye:dark_green", mcl_colors_official.DARK_GREEN }, + { "mcl_dye:grey", mcl_colors_official.GRAY }, + { "mcl_dye:dark_grey", mcl_colors_official.DARK_GRAY }, + { "mcl_dye:lightblue", mcl_signs.mcl_wool_colors.unicolor_light_blue }, + { "mcl_dye:lime", mcl_signs.unicolor_green_or_lime }, + { "mcl_dye:magenta", mcl_colors_official.LIGHT_PURPLE }, + { "mcl_dye:orange", mcl_signs.mcl_wool_colors.unicolor_orange }, + { "mcl_dye:pink", mcl_signs.mcl_wool_colors.unicolor_light_red_pink }, + { "mcl_dye:purple", mcl_colors_official.LIGHT_PURPLE }, + { "mcl_dye:red", mcl_signs.mcl_wool_colors.unicolor_red }, + { "mcl_dye:silver", mcl_signs.mcl_wool_colors.unicolor_grey }, + { "mcl_dye:violet", mcl_colors_official.DARK_PURPLE }, + { "mcl_dye:white", mcl_colors_official.WHITE }, + { "mcl_dye:yellow", mcl_colors_official.YELLOW }, +} + +local function update_sign_registry(type, name) + if type == "wall" then + table.insert(mcl_signs.registered_signs.wall_signs, name) + end + if type == "standing" then + table.insert(mcl_signs.registered_signs.standing_signs, name) + end + if type == "hanging" then + table.insert(mcl_signs.registered_signs.hanging_signs, name) + end +end + +function mcl_signs.make_lbm() + + local registered_sign_nodenames = {} + + for i = 0, #mcl_signs.registered_signs.wall_signs do + table.insert(registered_sign_nodenames, mcl_signs.registered_signs.wall_signs[i]) + end + + for i = 0, #mcl_signs.registered_signs.standing_signs do + table.insert(registered_sign_nodenames, mcl_signs.registered_signs.standing_signs[i]) + end + + for i = 0, #mcl_signs.registered_signs.hanging_signs do + table.insert(registered_sign_nodenames, mcl_signs.registered_signs.hanging_signs[i]) + end + + -- the above is not yet used. + minetest.register_lbm({ + name = "mcl_signs:respawn_entities", + label = "Respawn sign text entities", + run_at_every_load = true, + nodenames = registered_sign_nodenames, + action = function(pos, node) + mcl_signs:update_sign(pos) + end, + }) + +end + +function mcl_signs.register_dye (modname, item_name, color_code) + if minetest.get_modpath(modname) then + table.insert(Dyes_table, { item_name, color_code }) + end +end + +--- Register a new sign, tint the textures, and gives it an unique node name. Creates both wall and standing signs. +--- modname: optional (pass "" or "false" to ignore), for use with other mods to +--- allow the creation of a sign from the mod's wood (if installed). +--- +--- color: the color code to color the base sign textures. must be a valid html color code. +--- +--- _name: the sign's name suffix, such as "_dark" or "_red", etc., appended to "wall_sign" or "standing_sign" +--- +--- ttsign: the tool tip of the sign that gets translated. Shown when the mouse hovers the inventory sign. +--- For example: the basic, default oak (wood) sign is just "Sign"; and a spruce sign would be "Spruce Sign" +function mcl_signs.register_sign (modname, color, _name, ttsign) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + local new_sign = {} + + if color == nil or color == "" then + color = "#FFFFFF" + end + + new_sign = table.copy(mcl_signs.wall_standard) + new_sign.description = S(ttsign) + + new_sign.wield_image = "(default_sign.png^[multiply:" .. color .. ")" + new_sign.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(default_sign.png^[multiply:" .. color .. ")" + + -- currently have to do this, because of how the base node placement works. + new_sign.on_place = function(itemstack, placer, pointed_thing) + local above = pointed_thing.above + local under = pointed_thing.under + + -- Use pointed node's on_rightclick function first, if present + local node_under = minetest.get_node(under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then + return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack + end + end + + local dir = vector.subtract(under, above) + + -- Only build when it's legal + local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] + if not abovenodedef or abovenodedef.buildable_to == false then + return itemstack + end + + local wdir = minetest.dir_to_wallmounted(dir) + local fdir = minetest.dir_to_facedir(dir) + + local sign_info + local nodeitem = ItemStack(itemstack) + + local yaw = 0 + + -- Ceiling + if wdir == 0 then + --how would you add sign to ceiling? simple - hanging sign. + -- add code for placement underneath a node. + + return itemstack + -- Floor + elseif wdir == 1 then + -- Standing sign + + -- Determine the sign rotation based on player's yaw + yaw = pi * 2 - placer:get_look_horizontal() + + -- Select one of 16 possible rotations (0-15) + local rotation_level = mcl_signs:round((yaw / (pi * 2)) * 16) + + if rotation_level > 15 then + rotation_level = 0 + elseif rotation_level < 0 then + rotation_level = 15 + end + + -- The actual rotation is a combination of predefined mesh and facedir (see node definition) + if rotation_level % 4 == 0 then + nodeitem:set_name("mcl_signs:standing_sign" .. _name) + elseif rotation_level % 4 == 1 then + nodeitem:set_name("mcl_signs:standing_sign22_5" .. _name) + elseif rotation_level % 4 == 2 then + nodeitem:set_name("mcl_signs:standing_sign45" .. _name) + elseif rotation_level % 4 == 3 then + nodeitem:set_name("mcl_signs:standing_sign67_5" .. _name) + end + fdir = math.floor(rotation_level / 4) + + -- Place the node! + local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) + if not success then + return itemstack + end + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + sign_info = mcl_signs.signtext_info_standing[rotation_level + 1] + -- Side + else + -- Wall sign + local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + if not success then + return itemstack + end + sign_info = mcl_signs.signtext_info_wall[fdir + 1] + end + + -- Determine spawn position of entity + local place_pos + if minetest.registered_nodes[node_under.name].buildable_to then + place_pos = under + else + place_pos = above + end + + if DEBUG then + minetest.log("action", "[mcl_signs] Register_Sign::Placed position:" .. dump(place_pos) .. "\nSign_info: " .. dump(sign_info)) + end + + local text_entity = minetest.add_entity({ + x = place_pos.x + sign_info.delta.x, + y = place_pos.y + sign_info.delta.y, + z = place_pos.z + sign_info.delta.z }, "mcl_signs:text") + text_entity:set_yaw(sign_info.yaw) + text_entity:get_luaentity()._signnodename = nodeitem:get_name() + + minetest.sound_play({ name = "default_place_node_hard", gain = 1.0 }, { pos = place_pos }, true) + + mcl_signs:show_formspec(placer, place_pos) + return itemstack + end + + minetest.register_node(":mcl_signs:wall_sign" .. _name, new_sign) + update_sign_registry("wall", "mcl_signs:wall_sign" .. _name) + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Registered: mcl_signs:wall_sign" .. _name .. color .. "\n" .. dump(new_sign)) + minetest.log("action", "[mcl_signs] mcl_signs:wall_sign_standard\n" .. dump(mcl_signs.wall_standard)) + end + + -- standing sign base. + local new_sign_standing = {} + new_sign_standing = table.copy(mcl_signs.standing_standard) + new_sign_standing.drop = "mcl_signs:wall_sign" .. _name + new_sign_standing.wield_image = "(default_sign.png^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(default_sign.png^[multiply:" .. color .. ")" + + new_sign_standing.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign22_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end, + + minetest.register_node(":mcl_signs:standing_sign" .. _name, new_sign_standing) + update_sign_registry("standing", "mcl_signs:standing_sign" .. _name) + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Registered: mcl_signs:standing_sign" .. _name .. color .. "\n" .. dump(new_sign_standing)) + end + + -- 22.5° + local ssign22_5d = table.copy(new_sign_standing) + ssign22_5d.mesh = "mcl_signs_sign22.5.obj" + ssign22_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign45" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign22_5" .. _name, ssign22_5d) + update_sign_registry("standing", "mcl_signs:standing_sign22_5" .. _name) + + -- 45° + local ssign45d = table.copy(new_sign_standing) + ssign45d.mesh = "mcl_signs_sign45.obj" + ssign45d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign67_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign45" .. _name, ssign45d) + update_sign_registry("standing", "mcl_signs:standing_sign45" .. _name) + + -- 67.5° + local ssign67_5d = table.copy(new_sign_standing) + ssign67_5d.mesh = "mcl_signs_sign67.5.obj" + ssign67_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign" .. _name + node.param2 = (node.param2 + 1) % 4 + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign67_5" .. _name, ssign67_5d) + update_sign_registry("standing", "mcl_signs:standing_sign67_5" .. _name) + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:wall_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign22_5" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign45" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign67_5" .. _name) + end + + --register standing sign's rotation_levels + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign22_5" .. _name, 1 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign45" .. _name, 2 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign67_5" .. _name, 3 }) +end + +--- The same as register_sign, except caller defines the textures. Note, there is a greyscale version of the sign, +--- called "default_sign_greyscale.png" and "mcl_signs_sign_greyscale.png" for optional use in the textures directory. +--- +--- modname: optional (pass "" or "false" to ignore), for use with other mods to +--- allow the creation of a sign from the mod's wood (if installed). +--- +--- _name: the sign's name suffix, such as "_dark" or "_red", etc., appended to "wall_sign" or "standing_sign" +--- +--- tiles: the texture file to use for the sign. +--- +--- color: color the texture file to use with this color. Use white (#FFFFFF) to negate the color, +--- and just use the texture as is +--- +--- inventory_image: the texture file to use for the sign's display in inventory. +--- +--- wield_image: the texture file to use for the sign's weilded (in hand) object. +--- +--- inventory_image: the image used for in-inventory and in hand. +--- +--- ttsign: the tool tip of the sign that gets translated. Shown when the mouse hovers the inventory sign. +--- For example: the basic, default oak (wood) sign is just "Sign"; and a spruce sign would be "Spruce Sign" +function mcl_signs.register_sign_custom (modname, _name, tiles, color, inventory_image, wield_image, ttsign) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + local new_sign = {} + + new_sign = table.copy(mcl_signs.wall_standard) + + new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + new_sign.description = S(ttsign) + -- currently have to do this, because of how the base node placement works. + new_sign.on_place = function(itemstack, placer, pointed_thing) + local above = pointed_thing.above + local under = pointed_thing.under + + -- Use pointed node's on_rightclick function first, if present + local node_under = minetest.get_node(under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then + return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack + end + end + + local dir = vector.subtract(under, above) + + -- Only build when it's legal + local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] + if not abovenodedef or abovenodedef.buildable_to == false then + return itemstack + end + + local wdir = minetest.dir_to_wallmounted(dir) + local fdir = minetest.dir_to_facedir(dir) + + local sign_info + local nodeitem = ItemStack(itemstack) + -- Ceiling + if wdir == 0 then + --how would you add sign to ceiling? + return itemstack + -- Floor + elseif wdir == 1 then + -- Standing sign + + -- Determine the sign rotation based on player's yaw + local yaw = pi * 2 - placer:get_look_horizontal() + + -- Select one of 16 possible rotations (0-15) + local rotation_level = mcl_signs:round((yaw / (pi * 2)) * 16) + + if rotation_level > 15 then + rotation_level = 0 + elseif rotation_level < 0 then + rotation_level = 15 + end + + -- The actual rotation is a combination of predefined mesh and facedir (see node definition) + if rotation_level % 4 == 0 then + nodeitem:set_name("mcl_signs:standing_sign" .. _name) + elseif rotation_level % 4 == 1 then + nodeitem:set_name("mcl_signs:standing_sign22_5" .. _name) + elseif rotation_level % 4 == 2 then + nodeitem:set_name("mcl_signs:standing_sign45" .. _name) + elseif rotation_level % 4 == 3 then + nodeitem:set_name("mcl_signs:standing_sign67_5" .. _name) + end + fdir = math.floor(rotation_level / 4) + + -- Place the node! + local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) + if not success then + return itemstack + end + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + sign_info = mcl_signs.signtext_info_standing[rotation_level + 1] + -- Side + else + -- Wall sign + local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + if not success then + return itemstack + end + sign_info = mcl_signs.signtext_info_wall[fdir + 1] + end + + -- Determine spawn position of entity + local place_pos + if minetest.registered_nodes[node_under.name].buildable_to then + place_pos = under + else + place_pos = above + end + + local text_entity = minetest.add_entity({ + x = place_pos.x + sign_info.delta.x, + y = place_pos.y + sign_info.delta.y, + z = place_pos.z + sign_info.delta.z }, "mcl_signs:text") + text_entity:set_yaw(sign_info.yaw) + text_entity:get_luaentity()._signnodename = nodeitem:get_name() + + minetest.sound_play({ name = "default_place_node_hard", gain = 1.0 }, { pos = place_pos }, true) + + mcl_signs:show_formspec(placer, place_pos) + return itemstack + end + minetest.register_node(":mcl_signs:wall_sign" .. _name, new_sign) + update_sign_registry("wall", "mcl_signs:wall_sign" .. _name) + + -- standing sign base. + local new_sign_standing = {} + new_sign_standing = table.copy(mcl_signs.standing_standard) + new_sign_standing.drop = "mcl_signs:wall_sign" .. _name + new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + new_sign_standing.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign22_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end, + minetest.register_node(":mcl_signs:standing_sign" .. _name, new_sign_standing) + update_sign_registry("standing", "mcl_signs:standing_sign" .. _name) + + -- 22.5° + local ssign22_5d = table.copy(new_sign_standing) + ssign22_5d.mesh = "mcl_signs_sign22.5.obj" + ssign22_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign45" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign22_5" .. _name, ssign22_5d) + update_sign_registry("standing", "mcl_signs:standing_sign22_5" .. _name) + + -- 45° + local ssign45d = table.copy(new_sign_standing) + ssign45d.mesh = "mcl_signs_sign45.obj" + ssign45d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign67_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign45" .. _name, ssign45d) + update_sign_registry("standing", "mcl_signs:standing_sign45" .. _name) + + -- 67.5° + local ssign67_5d = table.copy(new_sign_standing) + ssign67_5d.mesh = "mcl_signs_sign67.5.obj" + ssign67_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign" .. _name + node.param2 = (node.param2 + 1) % 4 + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.register_node(":mcl_signs:standing_sign67_5" .. _name, ssign67_5d) + update_sign_registry("standing", "mcl_signs:standing_sign67_5" .. _name) + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:wall_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign22_5" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign45" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign67_5" .. _name) + end + + --register standing sign's rotation_levels + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign22_5" .. _name, 1 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign45" .. _name, 2 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign67_5" .. _name, 3 }) + +end + +--- Override an existing sign, tint the textures, and gives it an unique node name. Creates both wall and standing signs. +--- modname: optional (pass "" or "false" to ignore), for use with other mods to +--- allow the creation of a sign from the mod's wood (if installed). +--- +--- color: the color code to color the base sign textures. must be a valid html color code. +--- +--- _name: the sign's name suffix, such as "_dark" or "_red", etc., appended to "wall_sign" or "standing_sign" +--- +--- ttsign: the tool tip of the sign that gets translated. Shown when the mouse hovers the inventory sign. +--- For example: the basic, default oak (wood) sign is just "Sign"; and a spruce sign would be "Spruce Sign" +function mcl_signs.reregister_sign (modname, color, _name, ttsign) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + local new_sign = {} + + if color == nil or color == "" then + color = "#FFFFFF" + end + + new_sign = table.copy(mcl_signs.wall_standard) + new_sign.description = S(ttsign) + + new_sign.wield_image = "(default_sign.png^[multiply:" .. color .. ")" + new_sign.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(default_sign.png^[multiply:" .. color .. ")" + + -- currently have to do this, because of how the base node placement works. + new_sign.on_place = function(itemstack, placer, pointed_thing) + local above = pointed_thing.above + local under = pointed_thing.under + + -- Use pointed node's on_rightclick function first, if present + local node_under = minetest.get_node(under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then + return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack + end + end + + local dir = vector.subtract(under, above) + + -- Only build when it's legal + local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] + if not abovenodedef or abovenodedef.buildable_to == false then + return itemstack + end + + local wdir = minetest.dir_to_wallmounted(dir) + local fdir = minetest.dir_to_facedir(dir) + + local sign_info + local nodeitem = ItemStack(itemstack) + -- Ceiling + if wdir == 0 then + --how would you add sign to ceiling? + return itemstack + -- Floor + elseif wdir == 1 then + -- Standing sign + + -- Determine the sign rotation based on player's yaw + local yaw = pi * 2 - placer:get_look_horizontal() + + -- Select one of 16 possible rotations (0-15) + local rotation_level = mcl_signs:round((yaw / (pi * 2)) * 16) + + if rotation_level > 15 then + rotation_level = 0 + elseif rotation_level < 0 then + rotation_level = 15 + end + + -- The actual rotation is a combination of predefined mesh and facedir (see node definition) + if rotation_level % 4 == 0 then + nodeitem:set_name("mcl_signs:standing_sign" .. _name) + elseif rotation_level % 4 == 1 then + nodeitem:set_name("mcl_signs:standing_sign22_5" .. _name) + elseif rotation_level % 4 == 2 then + nodeitem:set_name("mcl_signs:standing_sign45" .. _name) + elseif rotation_level % 4 == 3 then + nodeitem:set_name("mcl_signs:standing_sign67_5" .. _name) + end + fdir = math.floor(rotation_level / 4) + + -- Place the node! + local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) + if not success then + return itemstack + end + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + sign_info = mcl_signs.signtext_info_standing[rotation_level + 1] + -- Side + else + -- Wall sign + local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + if not success then + return itemstack + end + sign_info = mcl_signs.signtext_info_wall[fdir + 1] + end + + -- Determine spawn position of entity + local place_pos + if minetest.registered_nodes[node_under.name].buildable_to then + place_pos = under + else + place_pos = above + end + + if DEBUG then + minetest.log("action", "[mcl_signs] Register_Sign::Placed position:" .. dump(place_pos) .. "\nSign_info: " .. dump(sign_info)) + end + + local text_entity = minetest.add_entity({ + x = place_pos.x + sign_info.delta.x, + y = place_pos.y + sign_info.delta.y, + z = place_pos.z + sign_info.delta.z }, "mcl_signs:text") + text_entity:set_yaw(sign_info.yaw) + text_entity:get_luaentity()._signnodename = nodeitem:get_name() + + minetest.sound_play({ name = "default_place_node_hard", gain = 1.0 }, { pos = place_pos }, true) + + mcl_signs:show_formspec(placer, place_pos) + return itemstack + end + + minetest.override_item("mcl_signs:wall_sign" .. _name, new_sign) + update_sign_registry("wall", "mcl_signs:wall_sign" .. _name) + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Registered: mcl_signs:wall_sign" .. _name .. color .. "\n" .. dump(new_sign)) + minetest.log("action", "[mcl_signs] mcl_signs:wall_sign_standard\n" .. dump(mcl_signs.wall_standard)) + end + + -- standing sign base. + local new_sign_standing = {} + new_sign_standing = table.copy(mcl_signs.standing_standard) + new_sign_standing.drop = "mcl_signs:wall_sign" .. _name + new_sign_standing.wield_image = "(default_sign.png^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(mcl_signs_sign.png^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(default_sign.png^[multiply:" .. color .. ")" + new_sign_standing.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign22_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end, + minetest.override_item("mcl_signs:standing_sign" .. _name, new_sign_standing) + update_sign_registry("standing", "mcl_signs:standing_sign" .. _name) + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Registered: mcl_signs:standing_sign" .. _name .. color .. "\n" .. dump(new_sign_standing)) + end + + -- 22.5° + local ssign22_5d = table.copy(new_sign_standing) + ssign22_5d.mesh = "mcl_signs_sign22.5.obj" + ssign22_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign45" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign22_5" .. _name, ssign22_5d) + update_sign_registry("standing", "mcl_signs:standing_sign22_5" .. _name) + + -- 45° + local ssign45d = table.copy(new_sign_standing) + ssign45d.mesh = "mcl_signs_sign45.obj" + ssign45d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign67_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign45" .. _name, ssign45d) + update_sign_registry("standing", "mcl_signs:standing_sign45" .. _name) + + -- 67.5° + local ssign67_5d = table.copy(new_sign_standing) + ssign67_5d.mesh = "mcl_signs_sign67.5.obj" + ssign67_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign" .. _name + node.param2 = (node.param2 + 1) % 4 + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign67_5" .. _name, ssign67_5d) + update_sign_registry("standing", "mcl_signs:standing_sign67_5" .. _name) + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:wall_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign22_5" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign45" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign67_5" .. _name) + end + + --register standing sign's rotation_levels + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign22_5" .. _name, 1 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign45" .. _name, 2 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign67_5" .. _name, 3 }) +end + +--- The same as reregister_sign, except caller defines the textures. Note, there is a greyscale version of the sign, +--- called "default_sign_greyscale.png" and "mcl_signs_sign_greyscale.png" for optional use in the textures directory. +--- +--- modname: optional (pass "" or "false" to ignore), for use with other mods to +--- allow the creation of a sign from the mod's wood (if installed). +--- +--- _name: the sign's name suffix, such as "_dark" or "_red", etc., appended to "wall_sign" or "standing_sign" +--- +--- tiles: the texture file to use for the sign. +--- +--- color: color the texture file to use with this color. Use white (#FFFFFF) to negate the color, +--- and just use the texture as is +--- +--- inventory_image: the texture file to use for the sign's display in inventory. +--- +--- wield_image: the texture file to use for the sign's weilded (in hand) object. +--- +--- inventory_image: the image used for in-inventory and in hand. +--- +--- ttsign: the tool tip of the sign that gets translated. Shown when the mouse hovers the inventory sign. +--- For example: the basic, default oak (wood) sign is just "Sign"; and a spruce sign would be "Spruce Sign" +function mcl_signs.reregister_sign_custom (modname, _name, tiles, color, inventory_image, wield_image, ttsign) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + local new_sign = {} + + new_sign = table.copy(mcl_signs.wall_standard) + + new_sign.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + new_sign.description = S(ttsign) + -- currently have to do this, because of how the base node placement works. + new_sign.on_place = function(itemstack, placer, pointed_thing) + local above = pointed_thing.above + local under = pointed_thing.under + + -- Use pointed node's on_rightclick function first, if present + local node_under = minetest.get_node(under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node_under.name] and minetest.registered_nodes[node_under.name].on_rightclick then + return minetest.registered_nodes[node_under.name].on_rightclick(under, node_under, placer, itemstack) or itemstack + end + end + + local dir = vector.subtract(under, above) + + -- Only build when it's legal + local abovenodedef = minetest.registered_nodes[minetest.get_node(above).name] + if not abovenodedef or abovenodedef.buildable_to == false then + return itemstack + end + + local wdir = minetest.dir_to_wallmounted(dir) + local fdir = minetest.dir_to_facedir(dir) + + local sign_info + local nodeitem = ItemStack(itemstack) + -- Ceiling + if wdir == 0 then + --how would you add sign to ceiling? + return itemstack + -- Floor + elseif wdir == 1 then + -- Standing sign + + -- Determine the sign rotation based on player's yaw + local yaw = pi * 2 - placer:get_look_horizontal() + + -- Select one of 16 possible rotations (0-15) + local rotation_level = mcl_signs:round((yaw / (pi * 2)) * 16) + + if rotation_level > 15 then + rotation_level = 0 + elseif rotation_level < 0 then + rotation_level = 15 + end + + -- The actual rotation is a combination of predefined mesh and facedir (see node definition) + if rotation_level % 4 == 0 then + nodeitem:set_name("mcl_signs:standing_sign" .. _name) + elseif rotation_level % 4 == 1 then + nodeitem:set_name("mcl_signs:standing_sign22_5" .. _name) + elseif rotation_level % 4 == 2 then + nodeitem:set_name("mcl_signs:standing_sign45" .. _name) + elseif rotation_level % 4 == 3 then + nodeitem:set_name("mcl_signs:standing_sign67_5" .. _name) + end + fdir = math.floor(rotation_level / 4) + + -- Place the node! + local _, success = minetest.item_place_node(nodeitem, placer, pointed_thing, fdir) + if not success then + return itemstack + end + if not minetest.is_creative_enabled(placer:get_player_name()) then + itemstack:take_item() + end + sign_info = mcl_signs.signtext_info_standing[rotation_level + 1] + -- Side + else + -- Wall sign + local _, success = minetest.item_place_node(itemstack, placer, pointed_thing, wdir) + if not success then + return itemstack + end + sign_info = mcl_signs.signtext_info_wall[fdir + 1] + end + + -- Determine spawn position of entity + local place_pos + if minetest.registered_nodes[node_under.name].buildable_to then + place_pos = under + else + place_pos = above + end + + local text_entity = minetest.add_entity({ + x = place_pos.x + sign_info.delta.x, + y = place_pos.y + sign_info.delta.y, + z = place_pos.z + sign_info.delta.z }, "mcl_signs:text") + text_entity:set_yaw(sign_info.yaw) + text_entity:get_luaentity()._signnodename = nodeitem:get_name() + + minetest.sound_play({ name = "default_place_node_hard", gain = 1.0 }, { pos = place_pos }, true) + + mcl_signs:show_formspec(placer, place_pos) + return itemstack + end + minetest.override_item("mcl_signs:wall_sign" .. _name, new_sign) + update_sign_registry("wall", "mcl_signs:wall_sign" .. _name) + + -- standing sign base. + local new_sign_standing = {} + new_sign_standing = table.copy(mcl_signs.standing_standard) + new_sign_standing.drop = "mcl_signs:wall_sign" .. _name + new_sign_standing.wield_image = "(" .. wield_image .. "^[multiply:" .. color .. ")" + new_sign_standing.tiles = { "(" .. tiles .. "^[multiply:" .. color .. ")" } + new_sign_standing.inventory_image = "(" .. inventory_image .. "^[multiply:" .. color .. ")" + new_sign_standing.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign22_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end, + minetest.override_item("mcl_signs:standing_sign" .. _name, new_sign_standing) + update_sign_registry("standing", "mcl_signs:standing_sign" .. _name) + + -- 22.5° + local ssign22_5d = table.copy(new_sign_standing) + ssign22_5d.mesh = "mcl_signs_sign22.5.obj" + ssign22_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign45" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign22_5" .. _name, ssign22_5d) + update_sign_registry("standing", "mcl_signs:standing_sign22_5" .. _name) + + -- 45° + local ssign45d = table.copy(new_sign_standing) + ssign45d.mesh = "mcl_signs_sign45.obj" + ssign45d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign67_5" .. _name + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign45" .. _name, ssign45d) + update_sign_registry("standing", "mcl_signs:standing_sign45" .. _name) + + -- 67.5° + local ssign67_5d = table.copy(new_sign_standing) + ssign67_5d.mesh = "mcl_signs_sign67.5.obj" + ssign67_5d.on_rotate = function(pos, node, user, mode) + if mode == screwdriver.ROTATE_FACE then + node.name = "mcl_signs:standing_sign" .. _name + node.param2 = (node.param2 + 1) % 4 + minetest.swap_node(pos, node) + elseif mode == screwdriver.ROTATE_AXIS then + return false + end + mcl_signs:update_sign(pos, nil, nil, true) + return true + end + minetest.override_item("mcl_signs:standing_sign67_5" .. _name, ssign67_5d) + update_sign_registry("standing", "mcl_signs:standing_sign67_5" .. _name) + + -- register Doc entry + if minetest.get_modpath("doc") then + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:wall_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign22_5" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign45" .. _name) + doc.add_entry_alias("nodes", "mcl_signs:wall_sign", "nodes", "mcl_signs:standing_sign67_5" .. _name) + end + + --register standing sign's rotation_levels + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign22_5" .. _name, 1 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign45" .. _name, 2 }) + table.insert(mcl_signs.standing_rotation_levels, { "mcl_signs:standing_sign67_5" .. _name, 3 }) + +end + +--- Usage: Call this with the mod's name, the wood's item string (for the planks), and with the sign's suffix. +--- Registers the crafting recipe for that sign. for every registered sign, call this function to register the +--- standard recipe for the sign. Otherwise, you have to do your own register craft call. +--- +--- modname: optional (pass "" or "false" to ignore), for use with other mods to +--- allow the creation of a sign from the mod's wood (if installed). Example: "mcl_core". +--- +--- wood_item_string: example: "mcl_core:wood" or "mcl_core:sprucewood" +--- +--- _name: the sign's name suffix, such as "_dark" or "_red", etc., appended to "wall_sign" or "standing_sign" +function mcl_signs.register_sign_craft(modname, wood_item_string, _name) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + + minetest.register_craft({ + type = "fuel", + recipe = "mcl_signs:wall_sign" .. _name, + burntime = 10, + }) + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Register Sign Crafts: \n" .. modname .. "\n" .. wood_item_string .. "\n" .. _name) + end + + -- register crafts (actual recipe) + if minetest.get_modpath(modname) then + + local itemstring = "mcl_signs:wall_sign" + + minetest.register_craft({ + output = itemstring .. _name .. " 3", + recipe = { + { wood_item_string, wood_item_string, wood_item_string }, + { wood_item_string, wood_item_string, wood_item_string }, + { "", "mcl_core:stick", "" }, + }, + }) + end +end + +function mcl_signs.register_hanging_sign_craft(modname, wood_item_string, _name) + local mod_name_pass = false + if modname ~= "" and modname ~= "false" then + if minetest.get_modpath(modname) then + mod_name_pass = true + end + if mod_name_pass == false then + return + end + end + + minetest.register_craft({ + type = "fuel", + recipe = ":mcl_signs:wall_sign" .. _name, + burntime = 10, + }) + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Register Sign Crafts: \n" .. modname .. "\n" .. wood_item_string .. "\n" .. _name) + end + + -- register crafts (actual recipe) + if minetest.get_modpath(modname) then + + local itemstring = ":mcl_signs:hanging_sign" + local quantity = "6" + + local bamboo = string.find(wood_item_string, "bamboo") + if bamboo then + quantity = "2" + end + minetest.register_craft({ + output = itemstring .. _name .. " " .. quantity, + recipe = { + { "mcl_lanterns:chain", "", "mcl_lanterns:chain" }, + { wood_item_string, wood_item_string, wood_item_string }, + { wood_item_string, wood_item_string, wood_item_string }, + }, + }) + end +end + +-- Helper functions +local function string_to_array(str) + local string_table = {} + for i = 1, string.len(str) do + table.insert(string_table, string.sub(str, i, i)) + end + return string_table +end + +local function string_to_line_array(str) + local linechar_table = {} + local current = 1 + local linechar = 1 + linechar_table[1] = "" + for _, char in ipairs(string_to_array(str)) do + -- New line + if char == "\n" then + current = current + 1 + linechar_table[current] = "" + linechar = 1 + else + linechar_table[current] = linechar_table[current] .. char + linechar = linechar + 1 + end + end + return linechar_table +end + +local function get_rotation_level(facedir, nodename) + local nnames = mcl_signs.standing_rotation_levels -- functional copy... was easier this way. #LazyAF :P + + local rl + local offset = 0 + for x = 1, #nnames do + if nnames[x][1] == nodename then + offset = nnames[x][2] + break + end + end + rl = facedir * 4 + offset + if DEBUG then + minetest.log("action", "[mcl_signs] GetRotationLevel: NodeName: " .. nodename .. " RL value: " .. rl) + end + return rl +end + +function mcl_signs:round(num, idp) + local mult = 10 ^ (idp or 0) + return math.floor(num * mult + 0.5) / mult +end + +function mcl_signs:get_color_for_sign(item_name) + + for d = 1, #Dyes_table do + if Dyes_table[d][1] == item_name then + return Dyes_table[d][2] + end + end + return "false" +end + +function mcl_signs:color_sign (pos, text_color) + + local success = mcl_signs:update_sign(pos, nil, nil, true, text_color) + + -- debug step + local meta = minetest.get_meta(pos) + if not meta then + minetest.log("error", "[mcl_signs] Sign Color Fail - Metadata.") + + return false + end + if DEBUG then + minetest.log("verbose", "[mcl_signs] Post-Sign Color: " .. meta:get_string("mcl_signs:text_color") .. " " .. meta:get_string("mcl_signs:glowing_sign") .. ".\n" .. dump(pos)) + end + + return success + +end + +function mcl_signs:glow_sign (pos, remove_glow) + local success = true + -- Get Meta Data for the sign. + local meta = minetest.get_meta(pos) + + if not meta then + return false + end + local text = meta:get_string("text") + if text == nil then + text = "" + end + + -- we can't make the text glow if there isn't any text + if text == "" then + return false + end + + if remove_glow == nil then + remove_glow = false + end + + -- set up text glow + local objects = minetest.get_objects_inside_radius(pos, 0.5) + local text_entity + for _, v in ipairs(objects) do + local ent = v:get_luaentity() + if ent and ent.name == "mcl_signs:text" then + text_entity = v + break + end + end + if remove_glow == true then + text_entity:set_properties({ + glow = nil, + }) + meta:set_string("mcl_signs:glowing_sign", "false") + else + text_entity:set_properties({ + glow = sign_glow, + }) + meta:set_string("mcl_signs:glowing_sign", "true") + end + if not text_entity then + return false + end + text_entity:get_luaentity()._glowing_sign = meta:get_string("mcl_signs:glowing_sign") + + -- debug step + if DEBUG then + minetest.log("verbose", "[mcl_signs] Post-Sign Glow: " .. meta:get_string("mcl_signs:text_color") .. " " .. meta:get_string("mcl_signs:glowing_sign") .. ".\n" .. dump(pos)) + end + return success +end + +function mcl_signs:create_lettering(text, signnodename, sign_color) + if sign_color == nil then + sign_color = mcl_colors.BLACK + end + local texture = mcl_signs:generate_texture(mcl_signs:create_lines(text), signnodename, sign_color) + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Creating sign text; text:" .. text) + end + + return texture +end + +function mcl_signs:create_lines(text) + local line_num = 1 + local text_table = {} + for _, line in ipairs(string_to_line_array(text)) do + if line_num > NUMBER_OF_LINES then + break + end + table.insert(text_table, line) + line_num = line_num + 1 + end + return text_table +end + +function mcl_signs:generate_line(s, ypos) + local i = 1 + local parsed = {} + local width = 0 + local chars = 0 + local printed_char_width = CHAR_WIDTH + 1 + while chars < LINE_LENGTH and i <= #s do + local file + -- Get and render character + if charmap[s:sub(i, i)] then + file = charmap[s:sub(i, i)] + i = i + 1 + elseif i < #s and charmap[s:sub(i, i + 1)] then + file = charmap[s:sub(i, i + 1)] + i = i + 2 + else + -- No character image found. + -- Use replacement character: + file = "_rc" + i = i + 1 + if DEBUG then + minetest.log("verbose", "[mcl_signs] Unknown symbol in '" .. s .. "' at " .. i) + end + end + if file then + width = width + printed_char_width + table.insert(parsed, file) + chars = chars + 1 + end + end + width = width - 1 + + local texture = "" + local xpos = math.floor((SIGN_WIDTH - width) / 2) + + for j = 1, #parsed do + texture = texture .. ":" .. xpos .. "," .. ypos .. "=" .. parsed[j] .. ".png" + xpos = xpos + printed_char_width + end + return texture +end + +function mcl_signs:generate_texture(lines, signnodename, letter_color) + local texture = "[combine:" .. SIGN_WIDTH .. "x" .. SIGN_WIDTH + local ypos = 0 + + -- Handle all of the dynamically created signs. + for x = 1, #mcl_signs.registered_signs.wall_signs do + if signnodename == mcl_signs.registered_signs.wall_signs[x] then + ypos = 30 + break + end + end + for x = 1, #mcl_signs.registered_signs.standing_signs do + if signnodename == mcl_signs.registered_signs.standing_signs[x] then + ypos = 0 + break + end + end + -- for future inclusion, when the hanging sings are made. + --[[ + for x = 1, #mcl_signs.registered_signs.hanging_signs do + if signnodename == mcl_signs.registered_signs.hanging_signs[x] then + ypos = 30 + break + end + end + ]] + + -- kept in for now, compatibility with existing hard coded signs. TODO: Remove after done with api. + if signnodename == "mcl_signs:wall_sign" or signnodename == "mcl_signs:wall_sign_dark" then + ypos = 30 + end + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Generate_Texture::Debug_Data:\nSignNodeName: " .. dump(signnodename) .. "\nYPOS: " .. ypos) + end + + for i = 1, #lines do + texture = texture .. mcl_signs:generate_line(lines[i], ypos) + ypos = ypos + LINE_HEIGHT + end + + texture = "(" .. texture .. "^[multiply:" .. letter_color .. ")" + return texture +end + +function mcl_signs:get_wall_signtext_info(param2, nodename) + local dir = minetest.wallmounted_to_dir(param2) + if dir.x > 0 then + return 2 + elseif dir.z > 0 then + return 1 + elseif dir.x < 0 then + return 4 + else + return 3 + end +end + +function mcl_signs:destruct_sign(pos) + local objects = minetest.get_objects_inside_radius(pos, 0.5) + for _, v in ipairs(objects) do + local ent = v:get_luaentity() + if ent and ent.name == "mcl_signs:text" then + v:remove() + end + end + local players = minetest.get_connected_players() + for p = 1, #players do + if vector.distance(players[p]:get_pos(), pos) <= 30 then + minetest.close_formspec(players[p]:get_player_name(), "mcl_signs:set_text_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z) + end + end +end + +function mcl_signs:update_sign(pos, fields, sender, force_remove, text_color) + -- Get Meta Data for the sign. + local meta = minetest.get_meta(pos) + + if not meta then + return false + end + local text = meta:get_string("text", "") + if fields and (text == "" and fields.text) then + meta:set_string("text", fields.text) + text = fields.text + end + if text == nil then + text = "" + end + + -- find text color. + local sign_color + + if meta:get_string("mcl_signs:text_color") == "" then + -- if no sign text color has been assigned, make it black. + sign_color = mcl_colors.BLACK + meta:set_string("mcl_signs:text_color", sign_color) + else + sign_color = meta:get_string("mcl_signs:text_color") + end + + if text_color == nil or text == "" then + text_color = "false" + end + + if text_color == "false" then + text_color = sign_color --if a new color hasn't been chosen, then keep the existing color. + end + + -- find the sign's glow value + local has_glow = false + + if meta:get_string("mcl_signs:glowing_sign") == "" or meta:get_string("mcl_signs:glowing_sign") == "false" then + has_glow = false + meta:set_string("mcl_signs:glowing_sign", "false") + else + has_glow = true + end + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Update_Signs: Pre-Sign Update: " .. sign_color .. " " .. meta:get_string("mcl_signs:glowing_sign") .. ".\n" .. dump(pos)) + end + + local sign_info + local npos = minetest.get_node(pos) + local npos_name = npos.name + + -- Handle all of the dynamically created signs. + for x = 1, #mcl_signs.registered_signs.wall_signs do + if npos_name == mcl_signs.registered_signs.wall_signs[x] then + sign_info = mcl_signs.signtext_info_wall[mcl_signs:get_wall_signtext_info(npos.param2)] + break + end + end + for x = 1, #mcl_signs.registered_signs.standing_signs do + if npos_name == mcl_signs.registered_signs.standing_signs[x] then + sign_info = mcl_signs.signtext_info_standing[get_rotation_level(npos.param2, npos_name) + 1] + break + end + end + -- for future inclusion, when the hanging sings are made. + --[[ + for x = 1, #mcl_signs.registered_signs.hanging_signs do + if nn == mcl_signs.registered_signs.hanging_signs[x] then + sign_info = mcl_signs.signtext_info_wall[mcl_signs:get_wall_signtext_info(n.param2)] + break + end + end + ]] + + -- the following if..elseif..end block is here for compatibility with the old code. TODO: remove this block after the new api is complete. + if npos_name == "mcl_signs:standing_sign_dark" or npos_name == "mcl_signs:standing_sign22_5_dark" or npos_name == "mcl_signs:standing_sign45_dark" or npos_name == "mcl_signs:standing_sign67_5_dark" then + sign_info = mcl_signs.signtext_info_standing[get_rotation_level(npos.param2, npos_name) + 1] + elseif npos_name == "mcl_signs:wall_sign_dark" then + sign_info = mcl_signs.signtext_info_wall[mcl_signs:get_wall_signtext_info(npos.param2)] + end + if sign_info == nil then + minetest.log("error", "[mcl_signs] Update_Signs: Missing sign_info!") + return false + end + + local text_entity + text_entity = mcl_signs:get_text_entity(pos,force_remove) + + if not text_entity then + if DEBUG then + minetest.log("action", "[mcl_signs] Update_Sign: Text_Entity - does not exist, creating it now.") + end + text_entity = minetest.add_entity({ + x = pos.x + sign_info.delta.x, + y = pos.y + sign_info.delta.y, + z = pos.z + sign_info.delta.z }, "mcl_signs:text") + + if DEBUG then + minetest.log("action", "[mcl_signs] Update_Sign: Placed position:" .. dump(pos) .. "\nSign_info: " .. dump(sign_info)) + end + end + text_entity:get_luaentity()._signnodename = npos_name + + -- set up special case: Dark Oak Sign. Dark Oak signs are soooo dark, they start off with white lettering. + if npos_name == "mcl_signs:wall_sign_darkwood" or + npos_name == "mcl_signs:standing_sign67_5_darkwood" or + npos_name == "mcl_signs:standing_sign45_darkwood" or + npos_name == "mcl_signs:standing_sign22_5_darkwood" or + npos_name == "mcl_signs:standing_sign_darkwood" + then + if text_color == "#000000" then + text_color = "#ffffff" + end + end + + -- Set the actual properties for the sign + + text_entity:set_properties({ + textures = { mcl_signs:create_lettering(text, npos_name, text_color) }, + }) + + if has_glow then + text_entity:set_properties({ + glow = sign_glow, + }) + end + + text_entity:set_yaw(sign_info.yaw) + if DEBUG then + minetest.log("verbose", "[mcl_signs] Update_Sign: After texture recreation.") + minetest.log("action", "[mcl_signs] Update_Sign: " .. npos_name .. "\nPlaced position:" .. dump(pos) .. "\nSign_info: " .. dump(sign_info)) + end + + -- save sign metadata. + meta:set_string("mcl_signs:text_color", text_color) + + -- Moved timer stuff to here, to make sure that it's called and only has one set of code. + local timer = minetest.get_node_timer(pos) + if text_entity and text ~= "" then + -- Do timer related stuff - but only if there is text to display. + -- Also, prevent excessive use with punching. (see node def.) + if timer:is_started() == false then + timer:start(TIMER_INTERVAL) + else + timer:stop() + timer:start(TIMER_INTERVAL) + end + else + if timer:is_started() == true then + timer:stop() + end + end + + -- debug step + if DEBUG then + minetest.log("action", "[mcl_signs] Update_Sign: Post-Sign Update: " .. meta:get_string("mcl_signs:text_color") .. " " .. meta:get_string("mcl_signs:glowing_sign") .. ".\n" .. dump(pos)) + end + + return true + +end + +function mcl_signs:show_formspec(player, pos) + minetest.show_formspec( + player:get_player_name(), + "mcl_signs:set_text_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z, + "size[6,3]textarea[0.25,0.25;6,1.5;text;" .. F(S("Enter sign text:")) .. ";]label[0,1.5;" .. F(S("Maximum line length: 15")) .. "\n" .. F(S("Maximum lines: 4")) .. "]button_exit[0,2.5;6,1;submit;" .. F(S("Done")) .. "]" + ) +end + +function mcl_signs:get_text_entity (pos, force_remove) + local objects = minetest.get_objects_inside_radius(pos, 0.5) + local text_entity = false -- just to have a check for failure. + for _, v in ipairs(objects) do + local ent = v:get_luaentity() + if ent and ent.name == "mcl_signs:text" then + if force_remove ~= nil and force_remove == true then + v:remove() + else + text_entity = v + break + end + end + end + return text_entity +end \ No newline at end of file diff --git a/mods/ITEMS/mcl_signs/textures/_0.png b/mods/ITEMS/mcl_signs/textures/_0.png index e764f3d6a..7ec1aea7a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_0.png and b/mods/ITEMS/mcl_signs/textures/_0.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_1.png b/mods/ITEMS/mcl_signs/textures/_1.png index 7fae5fa4c..e4bf5c3ac 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_1.png and b/mods/ITEMS/mcl_signs/textures/_1.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_1_2.png b/mods/ITEMS/mcl_signs/textures/_1_2.png index 52d025e87..8bdc3f8cc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_1_2.png and b/mods/ITEMS/mcl_signs/textures/_1_2.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_1_4.png b/mods/ITEMS/mcl_signs/textures/_1_4.png index 220e65ef5..d32aa3027 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_1_4.png and b/mods/ITEMS/mcl_signs/textures/_1_4.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_1_sup.png b/mods/ITEMS/mcl_signs/textures/_1_sup.png index 6be5fdcb1..0e20bf3a6 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_1_sup.png and b/mods/ITEMS/mcl_signs/textures/_1_sup.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_2.png b/mods/ITEMS/mcl_signs/textures/_2.png index e32866d03..29583723f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_2.png and b/mods/ITEMS/mcl_signs/textures/_2.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_2_sup.png b/mods/ITEMS/mcl_signs/textures/_2_sup.png index 3db952179..ddc378772 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_2_sup.png and b/mods/ITEMS/mcl_signs/textures/_2_sup.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_3.png b/mods/ITEMS/mcl_signs/textures/_3.png index 4e7da5665..c58caaa8c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_3.png and b/mods/ITEMS/mcl_signs/textures/_3.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_3_4.png b/mods/ITEMS/mcl_signs/textures/_3_4.png index 46e171049..316909108 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_3_4.png and b/mods/ITEMS/mcl_signs/textures/_3_4.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_3_sup.png b/mods/ITEMS/mcl_signs/textures/_3_sup.png index add337326..eae28867d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_3_sup.png and b/mods/ITEMS/mcl_signs/textures/_3_sup.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_4.png b/mods/ITEMS/mcl_signs/textures/_4.png index 5f3d95656..38048937c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_4.png and b/mods/ITEMS/mcl_signs/textures/_4.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_5.png b/mods/ITEMS/mcl_signs/textures/_5.png index baf23b273..96da18b50 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_5.png and b/mods/ITEMS/mcl_signs/textures/_5.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_6.png b/mods/ITEMS/mcl_signs/textures/_6.png index 31fcd7d72..e34e190e1 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_6.png and b/mods/ITEMS/mcl_signs/textures/_6.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_7.png b/mods/ITEMS/mcl_signs/textures/_7.png index 7594eb9d6..2b078c134 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_7.png and b/mods/ITEMS/mcl_signs/textures/_7.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_8.png b/mods/ITEMS/mcl_signs/textures/_8.png index b61f4e294..d4580e83f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_8.png and b/mods/ITEMS/mcl_signs/textures/_8.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_9.png b/mods/ITEMS/mcl_signs/textures/_9.png index 5ed82070b..3077c7bb3 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_9.png and b/mods/ITEMS/mcl_signs/textures/_9.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a.png b/mods/ITEMS/mcl_signs/textures/_a.png index 4b9356ac4..d57502ddb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a.png and b/mods/ITEMS/mcl_signs/textures/_a.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_.png b/mods/ITEMS/mcl_signs/textures/_a_.png index 152beabd4..157565774 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_.png and b/mods/ITEMS/mcl_signs/textures/_a_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_acute.png b/mods/ITEMS/mcl_signs/textures/_a_acute.png index b72b4853e..552988e31 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_acute.png and b/mods/ITEMS/mcl_signs/textures/_a_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_acute_.png b/mods/ITEMS/mcl_signs/textures/_a_acute_.png index d038b45ce..2f8736226 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_acute_.png and b/mods/ITEMS/mcl_signs/textures/_a_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_circumflex.png b/mods/ITEMS/mcl_signs/textures/_a_circumflex.png index f9b80df66..224675375 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_circumflex.png and b/mods/ITEMS/mcl_signs/textures/_a_circumflex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_circumflex_.png b/mods/ITEMS/mcl_signs/textures/_a_circumflex_.png index 8b35bdf7c..146671315 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_circumflex_.png and b/mods/ITEMS/mcl_signs/textures/_a_circumflex_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_grave.png b/mods/ITEMS/mcl_signs/textures/_a_grave.png index 3f0de45a5..6ccb2088e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_grave.png and b/mods/ITEMS/mcl_signs/textures/_a_grave.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_grave_.png b/mods/ITEMS/mcl_signs/textures/_a_grave_.png index 8176f51c5..f973dec5d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_grave_.png and b/mods/ITEMS/mcl_signs/textures/_a_grave_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_ring.png b/mods/ITEMS/mcl_signs/textures/_a_ring.png index d3c06ae6d..4d1b1e896 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_ring.png and b/mods/ITEMS/mcl_signs/textures/_a_ring.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_ring_.png b/mods/ITEMS/mcl_signs/textures/_a_ring_.png index d3e9b7e96..0c28aadcc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_ring_.png and b/mods/ITEMS/mcl_signs/textures/_a_ring_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_sup.png b/mods/ITEMS/mcl_signs/textures/_a_sup.png index 4f4f9801c..c2a001016 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_sup.png and b/mods/ITEMS/mcl_signs/textures/_a_sup.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_tilde.png b/mods/ITEMS/mcl_signs/textures/_a_tilde.png index 567632c37..0600d53ad 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_tilde.png and b/mods/ITEMS/mcl_signs/textures/_a_tilde.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_a_tilde_.png b/mods/ITEMS/mcl_signs/textures/_a_tilde_.png index fd3d97784..baffca08e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_a_tilde_.png and b/mods/ITEMS/mcl_signs/textures/_a_tilde_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_acute.png b/mods/ITEMS/mcl_signs/textures/_acute.png index 0655de2dd..709cf70fb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_acute.png and b/mods/ITEMS/mcl_signs/textures/_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ae.png b/mods/ITEMS/mcl_signs/textures/_ae.png index 7f199e477..40bf3cd6b 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ae.png and b/mods/ITEMS/mcl_signs/textures/_ae.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ae_.png b/mods/ITEMS/mcl_signs/textures/_ae_.png index e19fdf1c8..2f6a56d00 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ae_.png and b/mods/ITEMS/mcl_signs/textures/_ae_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ae_lig.png b/mods/ITEMS/mcl_signs/textures/_ae_lig.png index a02bd30cf..0f721d8e0 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ae_lig.png and b/mods/ITEMS/mcl_signs/textures/_ae_lig.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ae_lig_.png b/mods/ITEMS/mcl_signs/textures/_ae_lig_.png index 0eb5d2f5c..8aba2a4bc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ae_lig_.png and b/mods/ITEMS/mcl_signs/textures/_ae_lig_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_am.png b/mods/ITEMS/mcl_signs/textures/_am.png index 76a886757..15ad80d73 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_am.png and b/mods/ITEMS/mcl_signs/textures/_am.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ap.png b/mods/ITEMS/mcl_signs/textures/_ap.png index bced380ac..e44b77a61 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ap.png and b/mods/ITEMS/mcl_signs/textures/_ap.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_as.png b/mods/ITEMS/mcl_signs/textures/_as.png index 702a519b8..fbf1494d4 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_as.png and b/mods/ITEMS/mcl_signs/textures/_as.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_at.png b/mods/ITEMS/mcl_signs/textures/_at.png index 1c7fa502c..b6b1ebe31 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_at.png and b/mods/ITEMS/mcl_signs/textures/_at.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_b.png b/mods/ITEMS/mcl_signs/textures/_b.png index 427f488e5..bb44b3c1a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_b.png and b/mods/ITEMS/mcl_signs/textures/_b.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_b_.png b/mods/ITEMS/mcl_signs/textures/_b_.png index c89961d1b..034f595ce 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_b_.png and b/mods/ITEMS/mcl_signs/textures/_b_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_bl.png b/mods/ITEMS/mcl_signs/textures/_bl.png index 422fcc586..a8e73c1b7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_bl.png and b/mods/ITEMS/mcl_signs/textures/_bl.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_br.png b/mods/ITEMS/mcl_signs/textures/_br.png index 88b1ba4a3..aebe3a025 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_br.png and b/mods/ITEMS/mcl_signs/textures/_br.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_broken_bar.png b/mods/ITEMS/mcl_signs/textures/_broken_bar.png index c733fd862..a2ec6ccc8 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_broken_bar.png and b/mods/ITEMS/mcl_signs/textures/_broken_bar.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_c.png b/mods/ITEMS/mcl_signs/textures/_c.png index 0ae311f3d..9d61a1c47 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_c.png and b/mods/ITEMS/mcl_signs/textures/_c.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_c_.png b/mods/ITEMS/mcl_signs/textures/_c_.png index 135260913..bd6d69d71 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_c_.png and b/mods/ITEMS/mcl_signs/textures/_c_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_c_cedille.png b/mods/ITEMS/mcl_signs/textures/_c_cedille.png index 9d5a4b564..a59faa4fb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_c_cedille.png and b/mods/ITEMS/mcl_signs/textures/_c_cedille.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_c_cedille_.png b/mods/ITEMS/mcl_signs/textures/_c_cedille_.png index 7eb654bc4..3dcffc8e4 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_c_cedille_.png and b/mods/ITEMS/mcl_signs/textures/_c_cedille_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ca.png b/mods/ITEMS/mcl_signs/textures/_ca.png index 79fa4345f..799333fcc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ca.png and b/mods/ITEMS/mcl_signs/textures/_ca.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_cedille.png b/mods/ITEMS/mcl_signs/textures/_cedille.png index 0de32ed0c..2fd6e557f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_cedille.png and b/mods/ITEMS/mcl_signs/textures/_cedille.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_cent.png b/mods/ITEMS/mcl_signs/textures/_cent.png index ecdb1f1d1..ac2265b05 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_cent.png and b/mods/ITEMS/mcl_signs/textures/_cent.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_cl.png b/mods/ITEMS/mcl_signs/textures/_cl.png index 38cad796c..71a046245 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_cl.png and b/mods/ITEMS/mcl_signs/textures/_cl.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_cm.png b/mods/ITEMS/mcl_signs/textures/_cm.png index 6b2b10a17..6a6a8bc5a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_cm.png and b/mods/ITEMS/mcl_signs/textures/_cm.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_co.png b/mods/ITEMS/mcl_signs/textures/_co.png index 6775d5eaf..73808a7d9 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_co.png and b/mods/ITEMS/mcl_signs/textures/_co.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_copyright.png b/mods/ITEMS/mcl_signs/textures/_copyright.png index 7cfdf217e..1f0e3c934 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_copyright.png and b/mods/ITEMS/mcl_signs/textures/_copyright.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_cr.png b/mods/ITEMS/mcl_signs/textures/_cr.png index cd6d6dac6..2fbbf790f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_cr.png and b/mods/ITEMS/mcl_signs/textures/_cr.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_currency.png b/mods/ITEMS/mcl_signs/textures/_currency.png index 1264c8945..45806c12b 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_currency.png and b/mods/ITEMS/mcl_signs/textures/_currency.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_d.png b/mods/ITEMS/mcl_signs/textures/_d.png index d7988e2be..f7bd840cb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_d.png and b/mods/ITEMS/mcl_signs/textures/_d.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_d_.png b/mods/ITEMS/mcl_signs/textures/_d_.png index 8803ea036..da46423c9 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_d_.png and b/mods/ITEMS/mcl_signs/textures/_d_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_d_dash.png b/mods/ITEMS/mcl_signs/textures/_d_dash.png index 73f5a1246..3f9b1e460 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_d_dash.png and b/mods/ITEMS/mcl_signs/textures/_d_dash.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_d_dash_.png b/mods/ITEMS/mcl_signs/textures/_d_dash_.png index e9c9e69c7..57e424f37 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_d_dash_.png and b/mods/ITEMS/mcl_signs/textures/_d_dash_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_degree.png b/mods/ITEMS/mcl_signs/textures/_degree.png index 64a7ee2b1..95b6c0800 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_degree.png and b/mods/ITEMS/mcl_signs/textures/_degree.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_diaresis.png b/mods/ITEMS/mcl_signs/textures/_diaresis.png index f8b75d38d..edbe9649c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_diaresis.png and b/mods/ITEMS/mcl_signs/textures/_diaresis.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_div.png b/mods/ITEMS/mcl_signs/textures/_div.png index 808343753..ab6888146 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_div.png and b/mods/ITEMS/mcl_signs/textures/_div.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_dl.png b/mods/ITEMS/mcl_signs/textures/_dl.png index 044e4f00b..c1706295a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_dl.png and b/mods/ITEMS/mcl_signs/textures/_dl.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_dt.png b/mods/ITEMS/mcl_signs/textures/_dt.png index 5dfa75349..b9a53650d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_dt.png and b/mods/ITEMS/mcl_signs/textures/_dt.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_dv.png b/mods/ITEMS/mcl_signs/textures/_dv.png index 2989d93db..86d22fea4 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_dv.png and b/mods/ITEMS/mcl_signs/textures/_dv.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e.png b/mods/ITEMS/mcl_signs/textures/_e.png index 316e966a1..431e2141b 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e.png and b/mods/ITEMS/mcl_signs/textures/_e.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_.png b/mods/ITEMS/mcl_signs/textures/_e_.png index 5ef88d282..f9b674b15 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_.png and b/mods/ITEMS/mcl_signs/textures/_e_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_acute.png b/mods/ITEMS/mcl_signs/textures/_e_acute.png index 911207f86..4566f2dbc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_acute.png and b/mods/ITEMS/mcl_signs/textures/_e_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_acute_.png b/mods/ITEMS/mcl_signs/textures/_e_acute_.png index b60193740..70502e82f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_acute_.png and b/mods/ITEMS/mcl_signs/textures/_e_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_circumflex.png b/mods/ITEMS/mcl_signs/textures/_e_circumflex.png index 2b5ace3c4..0aca71f43 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_circumflex.png and b/mods/ITEMS/mcl_signs/textures/_e_circumflex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_circumflex_.png b/mods/ITEMS/mcl_signs/textures/_e_circumflex_.png index c17d9dc29..02148554a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_circumflex_.png and b/mods/ITEMS/mcl_signs/textures/_e_circumflex_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_grave.png b/mods/ITEMS/mcl_signs/textures/_e_grave.png index c24ab4635..c9366cd83 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_grave.png and b/mods/ITEMS/mcl_signs/textures/_e_grave.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_e_grave_.png b/mods/ITEMS/mcl_signs/textures/_e_grave_.png index c71bb2ef6..1006e5fea 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_e_grave_.png and b/mods/ITEMS/mcl_signs/textures/_e_grave_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ee.png b/mods/ITEMS/mcl_signs/textures/_ee.png index 646c19e14..4871c31be 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ee.png and b/mods/ITEMS/mcl_signs/textures/_ee.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ee_.png b/mods/ITEMS/mcl_signs/textures/_ee_.png index 5db7bc66a..3e174052f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ee_.png and b/mods/ITEMS/mcl_signs/textures/_ee_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_eq.png b/mods/ITEMS/mcl_signs/textures/_eq.png index 166f7a30d..9135af0fe 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_eq.png and b/mods/ITEMS/mcl_signs/textures/_eq.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ex.png b/mods/ITEMS/mcl_signs/textures/_ex.png index 65a76aad1..e63ed21f2 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ex.png and b/mods/ITEMS/mcl_signs/textures/_ex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ex_inv.png b/mods/ITEMS/mcl_signs/textures/_ex_inv.png index 1e7bbfe87..af591188c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ex_inv.png and b/mods/ITEMS/mcl_signs/textures/_ex_inv.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_f.png b/mods/ITEMS/mcl_signs/textures/_f.png index 1e431df13..40318ea05 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_f.png and b/mods/ITEMS/mcl_signs/textures/_f.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_f_.png b/mods/ITEMS/mcl_signs/textures/_f_.png index d0dec2b35..9c234f7c0 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_f_.png and b/mods/ITEMS/mcl_signs/textures/_f_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_g.png b/mods/ITEMS/mcl_signs/textures/_g.png index 0b39fc95e..7ddd6e106 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_g.png and b/mods/ITEMS/mcl_signs/textures/_g.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_g_.png b/mods/ITEMS/mcl_signs/textures/_g_.png index bfe054638..881d06842 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_g_.png and b/mods/ITEMS/mcl_signs/textures/_g_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_gr.png b/mods/ITEMS/mcl_signs/textures/_gr.png index 3f806499a..92832f94e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_gr.png and b/mods/ITEMS/mcl_signs/textures/_gr.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_gt.png b/mods/ITEMS/mcl_signs/textures/_gt.png index 0449b44de..a4ff1b616 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_gt.png and b/mods/ITEMS/mcl_signs/textures/_gt.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_guill_left.png b/mods/ITEMS/mcl_signs/textures/_guill_left.png index 32b90c3e2..a9cf7c724 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_guill_left.png and b/mods/ITEMS/mcl_signs/textures/_guill_left.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_guill_right.png b/mods/ITEMS/mcl_signs/textures/_guill_right.png index d372e6a85..f4433eca4 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_guill_right.png and b/mods/ITEMS/mcl_signs/textures/_guill_right.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_h.png b/mods/ITEMS/mcl_signs/textures/_h.png index bd6f1891c..b4c9cf2cb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_h.png and b/mods/ITEMS/mcl_signs/textures/_h.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_h_.png b/mods/ITEMS/mcl_signs/textures/_h_.png index 08cb5d8b0..cdea24645 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_h_.png and b/mods/ITEMS/mcl_signs/textures/_h_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ha.png b/mods/ITEMS/mcl_signs/textures/_ha.png index 946ae4e5e..48323a28f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ha.png and b/mods/ITEMS/mcl_signs/textures/_ha.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_hs.png b/mods/ITEMS/mcl_signs/textures/_hs.png index 682a92a2d..60bce8e35 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_hs.png and b/mods/ITEMS/mcl_signs/textures/_hs.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i.png b/mods/ITEMS/mcl_signs/textures/_i.png index 9ba3e01a3..4abe22825 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i.png and b/mods/ITEMS/mcl_signs/textures/_i.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_.png b/mods/ITEMS/mcl_signs/textures/_i_.png index ffe090aa8..e8e5e1b58 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_.png and b/mods/ITEMS/mcl_signs/textures/_i_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_acute.png b/mods/ITEMS/mcl_signs/textures/_i_acute.png index 20bdafb62..b1ceff343 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_acute.png and b/mods/ITEMS/mcl_signs/textures/_i_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_acute_.png b/mods/ITEMS/mcl_signs/textures/_i_acute_.png index 4cdc943d9..d59d86398 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_acute_.png and b/mods/ITEMS/mcl_signs/textures/_i_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_circumflex.png b/mods/ITEMS/mcl_signs/textures/_i_circumflex.png index f0e712725..e7d5ab191 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_circumflex.png and b/mods/ITEMS/mcl_signs/textures/_i_circumflex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_circumflex_.png b/mods/ITEMS/mcl_signs/textures/_i_circumflex_.png index dc46f3ff5..a15c15336 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_circumflex_.png and b/mods/ITEMS/mcl_signs/textures/_i_circumflex_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_grave.png b/mods/ITEMS/mcl_signs/textures/_i_grave.png index 7254cd7d2..c0ae05825 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_grave.png and b/mods/ITEMS/mcl_signs/textures/_i_grave.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_i_grave_.png b/mods/ITEMS/mcl_signs/textures/_i_grave_.png index 1e2212679..7c68cb968 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_i_grave_.png and b/mods/ITEMS/mcl_signs/textures/_i_grave_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_j.png b/mods/ITEMS/mcl_signs/textures/_j.png index 7fec50215..118928bfc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_j.png and b/mods/ITEMS/mcl_signs/textures/_j.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_j_.png b/mods/ITEMS/mcl_signs/textures/_j_.png index 440af26d5..3983cec05 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_j_.png and b/mods/ITEMS/mcl_signs/textures/_j_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_k.png b/mods/ITEMS/mcl_signs/textures/_k.png index af07f4bf3..987d0e26a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_k.png and b/mods/ITEMS/mcl_signs/textures/_k.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_k_.png b/mods/ITEMS/mcl_signs/textures/_k_.png index 5e0a6b995..183c1d27c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_k_.png and b/mods/ITEMS/mcl_signs/textures/_k_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_l.png b/mods/ITEMS/mcl_signs/textures/_l.png index d28a863f3..f70432b50 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_l.png and b/mods/ITEMS/mcl_signs/textures/_l.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_l_.png b/mods/ITEMS/mcl_signs/textures/_l_.png index c40390194..89a5e1562 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_l_.png and b/mods/ITEMS/mcl_signs/textures/_l_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_lt.png b/mods/ITEMS/mcl_signs/textures/_lt.png index 54295121e..a1b9d2ff8 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_lt.png and b/mods/ITEMS/mcl_signs/textures/_lt.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_m.png b/mods/ITEMS/mcl_signs/textures/_m.png index e4110bbb0..9c9c691d8 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_m.png and b/mods/ITEMS/mcl_signs/textures/_m.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_m_.png b/mods/ITEMS/mcl_signs/textures/_m_.png index ac516a053..c7e9fa044 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_m_.png and b/mods/ITEMS/mcl_signs/textures/_m_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_macron.png b/mods/ITEMS/mcl_signs/textures/_macron.png index ffb9dfd77..738a4374e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_macron.png and b/mods/ITEMS/mcl_signs/textures/_macron.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_mn.png b/mods/ITEMS/mcl_signs/textures/_mn.png index 2230e1065..63a9e67ba 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_mn.png and b/mods/ITEMS/mcl_signs/textures/_mn.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_mu.png b/mods/ITEMS/mcl_signs/textures/_mu.png index 3d8c1b890..483936af8 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_mu.png and b/mods/ITEMS/mcl_signs/textures/_mu.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_n.png b/mods/ITEMS/mcl_signs/textures/_n.png index ca5ea2787..3f16f50bc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_n.png and b/mods/ITEMS/mcl_signs/textures/_n.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_n_.png b/mods/ITEMS/mcl_signs/textures/_n_.png index b96f27c62..430227892 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_n_.png and b/mods/ITEMS/mcl_signs/textures/_n_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_n_tilde.png b/mods/ITEMS/mcl_signs/textures/_n_tilde.png index 471669116..cfc1c626c 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_n_tilde.png and b/mods/ITEMS/mcl_signs/textures/_n_tilde.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_n_tilde_.png b/mods/ITEMS/mcl_signs/textures/_n_tilde_.png index 0dba0d471..404221056 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_n_tilde_.png and b/mods/ITEMS/mcl_signs/textures/_n_tilde_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_not.png b/mods/ITEMS/mcl_signs/textures/_not.png index a98f885e9..e7b1b7b66 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_not.png and b/mods/ITEMS/mcl_signs/textures/_not.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o.png b/mods/ITEMS/mcl_signs/textures/_o.png index 2a579385d..a59eacb8f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o.png and b/mods/ITEMS/mcl_signs/textures/_o.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_.png b/mods/ITEMS/mcl_signs/textures/_o_.png index 44ac3cbca..967c240b2 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_.png and b/mods/ITEMS/mcl_signs/textures/_o_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_acute.png b/mods/ITEMS/mcl_signs/textures/_o_acute.png index cda99b3a6..9094a80c7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_acute.png and b/mods/ITEMS/mcl_signs/textures/_o_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_acute_.png b/mods/ITEMS/mcl_signs/textures/_o_acute_.png index e25a3a7f4..9279670fa 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_acute_.png and b/mods/ITEMS/mcl_signs/textures/_o_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_circumflex.png b/mods/ITEMS/mcl_signs/textures/_o_circumflex.png index 2f7a188df..1240f1718 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_circumflex.png and b/mods/ITEMS/mcl_signs/textures/_o_circumflex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_circumflex_.png b/mods/ITEMS/mcl_signs/textures/_o_circumflex_.png index 5e4c6be6a..8acca66c9 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_circumflex_.png and b/mods/ITEMS/mcl_signs/textures/_o_circumflex_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_dash.png b/mods/ITEMS/mcl_signs/textures/_o_dash.png index 9e5de53d1..0f0d638ff 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_dash.png and b/mods/ITEMS/mcl_signs/textures/_o_dash.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_dash_.png b/mods/ITEMS/mcl_signs/textures/_o_dash_.png index badbe9b88..b6e98f1ee 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_dash_.png and b/mods/ITEMS/mcl_signs/textures/_o_dash_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_grave.png b/mods/ITEMS/mcl_signs/textures/_o_grave.png index b6b31a9a6..861327e27 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_grave.png and b/mods/ITEMS/mcl_signs/textures/_o_grave.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_grave_.png b/mods/ITEMS/mcl_signs/textures/_o_grave_.png index d34e9d71c..7ab9e374b 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_grave_.png and b/mods/ITEMS/mcl_signs/textures/_o_grave_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_sup.png b/mods/ITEMS/mcl_signs/textures/_o_sup.png index eeff0a295..bbabcf8c0 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_sup.png and b/mods/ITEMS/mcl_signs/textures/_o_sup.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_tilde.png b/mods/ITEMS/mcl_signs/textures/_o_tilde.png index 6cbd7cec0..3c95094bb 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_tilde.png and b/mods/ITEMS/mcl_signs/textures/_o_tilde.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_o_tilde_.png b/mods/ITEMS/mcl_signs/textures/_o_tilde_.png index bb0616918..8f980dd98 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_o_tilde_.png and b/mods/ITEMS/mcl_signs/textures/_o_tilde_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_oe.png b/mods/ITEMS/mcl_signs/textures/_oe.png index 9b6892155..693838ce7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_oe.png and b/mods/ITEMS/mcl_signs/textures/_oe.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_oe_.png b/mods/ITEMS/mcl_signs/textures/_oe_.png index 73b4da80e..c66b72ba2 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_oe_.png and b/mods/ITEMS/mcl_signs/textures/_oe_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_p.png b/mods/ITEMS/mcl_signs/textures/_p.png index 08f8534d0..8d0efe264 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_p.png and b/mods/ITEMS/mcl_signs/textures/_p.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_p_.png b/mods/ITEMS/mcl_signs/textures/_p_.png index 2ff300509..964387e64 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_p_.png and b/mods/ITEMS/mcl_signs/textures/_p_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_paragraph.png b/mods/ITEMS/mcl_signs/textures/_paragraph.png index 52c162120..cfbf0af51 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_paragraph.png and b/mods/ITEMS/mcl_signs/textures/_paragraph.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_pilcrow.png b/mods/ITEMS/mcl_signs/textures/_pilcrow.png index 9764ff8b5..cf9bbc778 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_pilcrow.png and b/mods/ITEMS/mcl_signs/textures/_pilcrow.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_plus_minus.png b/mods/ITEMS/mcl_signs/textures/_plus_minus.png index e7c3f1200..b9b79ec32 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_plus_minus.png and b/mods/ITEMS/mcl_signs/textures/_plus_minus.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_pound.png b/mods/ITEMS/mcl_signs/textures/_pound.png index 31d38d392..04a02d462 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_pound.png and b/mods/ITEMS/mcl_signs/textures/_pound.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_pr.png b/mods/ITEMS/mcl_signs/textures/_pr.png index c8783948d..21b8fbf80 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_pr.png and b/mods/ITEMS/mcl_signs/textures/_pr.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ps.png b/mods/ITEMS/mcl_signs/textures/_ps.png index 74b1f5b8e..37527155f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ps.png and b/mods/ITEMS/mcl_signs/textures/_ps.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_q.png b/mods/ITEMS/mcl_signs/textures/_q.png index b5fbcc27d..a48222e28 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_q.png and b/mods/ITEMS/mcl_signs/textures/_q.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_q_.png b/mods/ITEMS/mcl_signs/textures/_q_.png index 674799413..50f00af20 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_q_.png and b/mods/ITEMS/mcl_signs/textures/_q_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_qo.png b/mods/ITEMS/mcl_signs/textures/_qo.png index c7b87be68..9eaca2bd7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_qo.png and b/mods/ITEMS/mcl_signs/textures/_qo.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_qu.png b/mods/ITEMS/mcl_signs/textures/_qu.png index 1458c7e10..51dff64f3 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_qu.png and b/mods/ITEMS/mcl_signs/textures/_qu.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_qu_inv.png b/mods/ITEMS/mcl_signs/textures/_qu_inv.png index 757bd06db..b2fa4275e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_qu_inv.png and b/mods/ITEMS/mcl_signs/textures/_qu_inv.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_r.png b/mods/ITEMS/mcl_signs/textures/_r.png index 709c53889..6b80bb254 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_r.png and b/mods/ITEMS/mcl_signs/textures/_r.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_r_.png b/mods/ITEMS/mcl_signs/textures/_r_.png index f8b472755..3c1bafc58 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_r_.png and b/mods/ITEMS/mcl_signs/textures/_r_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_rc.png b/mods/ITEMS/mcl_signs/textures/_rc.png index 8b66915e6..b8ea5b70e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_rc.png and b/mods/ITEMS/mcl_signs/textures/_rc.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_re.png b/mods/ITEMS/mcl_signs/textures/_re.png index 8fdaf4d24..3f7dda14d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_re.png and b/mods/ITEMS/mcl_signs/textures/_re.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_registered.png b/mods/ITEMS/mcl_signs/textures/_registered.png index 9a78dda3c..0e510a2a7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_registered.png and b/mods/ITEMS/mcl_signs/textures/_registered.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_s.png b/mods/ITEMS/mcl_signs/textures/_s.png index 4c47aee01..43c314be1 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_s.png and b/mods/ITEMS/mcl_signs/textures/_s.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_s_.png b/mods/ITEMS/mcl_signs/textures/_s_.png index 08cf6ff68..4edf86115 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_s_.png and b/mods/ITEMS/mcl_signs/textures/_s_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_sl.png b/mods/ITEMS/mcl_signs/textures/_sl.png index 413aa5778..1b4cf0f58 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_sl.png and b/mods/ITEMS/mcl_signs/textures/_sl.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_sm.png b/mods/ITEMS/mcl_signs/textures/_sm.png index 460c5d6dd..2d7dc7310 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_sm.png and b/mods/ITEMS/mcl_signs/textures/_sm.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_sp.png b/mods/ITEMS/mcl_signs/textures/_sp.png index 4aae0ea85..27db127b7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_sp.png and b/mods/ITEMS/mcl_signs/textures/_sp.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_sr.png b/mods/ITEMS/mcl_signs/textures/_sr.png index afefa91b2..b40144656 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_sr.png and b/mods/ITEMS/mcl_signs/textures/_sr.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_sz.png b/mods/ITEMS/mcl_signs/textures/_sz.png index 56d2847a1..6e323629a 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_sz.png and b/mods/ITEMS/mcl_signs/textures/_sz.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_t.png b/mods/ITEMS/mcl_signs/textures/_t.png index e750dd98e..e175268c3 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_t.png and b/mods/ITEMS/mcl_signs/textures/_t.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_t_.png b/mods/ITEMS/mcl_signs/textures/_t_.png index d7aabd04a..6fbae7a18 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_t_.png and b/mods/ITEMS/mcl_signs/textures/_t_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_thorn.png b/mods/ITEMS/mcl_signs/textures/_thorn.png index e44f23d85..3d3b4359d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_thorn.png and b/mods/ITEMS/mcl_signs/textures/_thorn.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_thorn_.png b/mods/ITEMS/mcl_signs/textures/_thorn_.png index 1b6d2558b..add982bc1 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_thorn_.png and b/mods/ITEMS/mcl_signs/textures/_thorn_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_times_cross.png b/mods/ITEMS/mcl_signs/textures/_times_cross.png index 25af91b68..f6c6cd310 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_times_cross.png and b/mods/ITEMS/mcl_signs/textures/_times_cross.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_times_dot.png b/mods/ITEMS/mcl_signs/textures/_times_dot.png index 42dac52bc..92b5dae14 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_times_dot.png and b/mods/ITEMS/mcl_signs/textures/_times_dot.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_tl.png b/mods/ITEMS/mcl_signs/textures/_tl.png index 5f1b4fb43..e4eaf45a7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_tl.png and b/mods/ITEMS/mcl_signs/textures/_tl.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u.png b/mods/ITEMS/mcl_signs/textures/_u.png index 2665e5685..1c81b91cc 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u.png and b/mods/ITEMS/mcl_signs/textures/_u.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_.png b/mods/ITEMS/mcl_signs/textures/_u_.png index d04ff5481..06bac7dd9 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_.png and b/mods/ITEMS/mcl_signs/textures/_u_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_acute.png b/mods/ITEMS/mcl_signs/textures/_u_acute.png index 580f61042..04fe159d8 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_acute.png and b/mods/ITEMS/mcl_signs/textures/_u_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_acute_.png b/mods/ITEMS/mcl_signs/textures/_u_acute_.png index 9237d3caf..266731981 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_acute_.png and b/mods/ITEMS/mcl_signs/textures/_u_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_circumflex.png b/mods/ITEMS/mcl_signs/textures/_u_circumflex.png index 2b238be12..b402d9083 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_circumflex.png and b/mods/ITEMS/mcl_signs/textures/_u_circumflex.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_circumflex_.png b/mods/ITEMS/mcl_signs/textures/_u_circumflex_.png index 1608ecf17..6e2bb85d2 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_circumflex_.png and b/mods/ITEMS/mcl_signs/textures/_u_circumflex_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_grave.png b/mods/ITEMS/mcl_signs/textures/_u_grave.png index 051280428..51fff9c2e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_grave.png and b/mods/ITEMS/mcl_signs/textures/_u_grave.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_u_grave_.png b/mods/ITEMS/mcl_signs/textures/_u_grave_.png index 668685793..2605b3eca 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_u_grave_.png and b/mods/ITEMS/mcl_signs/textures/_u_grave_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ue.png b/mods/ITEMS/mcl_signs/textures/_ue.png index 6249aaebb..d6af6eb7b 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ue.png and b/mods/ITEMS/mcl_signs/textures/_ue.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_ue_.png b/mods/ITEMS/mcl_signs/textures/_ue_.png index 3193a9412..52b4c9298 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_ue_.png and b/mods/ITEMS/mcl_signs/textures/_ue_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_un.png b/mods/ITEMS/mcl_signs/textures/_un.png index d65f12d4e..5da6b09a7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_un.png and b/mods/ITEMS/mcl_signs/textures/_un.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_v.png b/mods/ITEMS/mcl_signs/textures/_v.png index 888b2f1cf..390e3aae3 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_v.png and b/mods/ITEMS/mcl_signs/textures/_v.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_v_.png b/mods/ITEMS/mcl_signs/textures/_v_.png index f2ecbf143..5e27b773e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_v_.png and b/mods/ITEMS/mcl_signs/textures/_v_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_vb.png b/mods/ITEMS/mcl_signs/textures/_vb.png index ca2e5667a..d23d3a074 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_vb.png and b/mods/ITEMS/mcl_signs/textures/_vb.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_w.png b/mods/ITEMS/mcl_signs/textures/_w.png index 6c2eea3e1..1b8dc528e 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_w.png and b/mods/ITEMS/mcl_signs/textures/_w.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_w_.png b/mods/ITEMS/mcl_signs/textures/_w_.png index f1e26c108..259b599b9 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_w_.png and b/mods/ITEMS/mcl_signs/textures/_w_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_x.png b/mods/ITEMS/mcl_signs/textures/_x.png index 3eb2d52d7..746fa1776 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_x.png and b/mods/ITEMS/mcl_signs/textures/_x.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_x_.png b/mods/ITEMS/mcl_signs/textures/_x_.png index bcb351d56..05300eca7 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_x_.png and b/mods/ITEMS/mcl_signs/textures/_x_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_y.png b/mods/ITEMS/mcl_signs/textures/_y.png index 7cd1d87b7..87b45d413 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_y.png and b/mods/ITEMS/mcl_signs/textures/_y.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_y_.png b/mods/ITEMS/mcl_signs/textures/_y_.png index b5f49850c..de9a88db4 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_y_.png and b/mods/ITEMS/mcl_signs/textures/_y_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_y_acute.png b/mods/ITEMS/mcl_signs/textures/_y_acute.png index 37cb54b30..1fd9679d1 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_y_acute.png and b/mods/ITEMS/mcl_signs/textures/_y_acute.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_y_acute_.png b/mods/ITEMS/mcl_signs/textures/_y_acute_.png index bcc15c41c..18c5a5528 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_y_acute_.png and b/mods/ITEMS/mcl_signs/textures/_y_acute_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_y_diaresis.png b/mods/ITEMS/mcl_signs/textures/_y_diaresis.png index 135a8ce25..ecb56c237 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_y_diaresis.png and b/mods/ITEMS/mcl_signs/textures/_y_diaresis.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_yen.png b/mods/ITEMS/mcl_signs/textures/_yen.png index ec4ad65ee..7ea4e0094 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_yen.png and b/mods/ITEMS/mcl_signs/textures/_yen.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_z.png b/mods/ITEMS/mcl_signs/textures/_z.png index 8a710780a..62a89e647 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_z.png and b/mods/ITEMS/mcl_signs/textures/_z.png differ diff --git a/mods/ITEMS/mcl_signs/textures/_z_.png b/mods/ITEMS/mcl_signs/textures/_z_.png index 6192800b4..dcdf0ab8d 100644 Binary files a/mods/ITEMS/mcl_signs/textures/_z_.png and b/mods/ITEMS/mcl_signs/textures/_z_.png differ diff --git a/mods/ITEMS/mcl_signs/textures/default_sign.png b/mods/ITEMS/mcl_signs/textures/default_sign.png index 077983118..8fcee7e9f 100644 Binary files a/mods/ITEMS/mcl_signs/textures/default_sign.png and b/mods/ITEMS/mcl_signs/textures/default_sign.png differ diff --git a/mods/ITEMS/mcl_signs/textures/default_sign_dark.png b/mods/ITEMS/mcl_signs/textures/default_sign_dark.png new file mode 100644 index 000000000..016098238 Binary files /dev/null and b/mods/ITEMS/mcl_signs/textures/default_sign_dark.png differ diff --git a/mods/ITEMS/mcl_signs/textures/default_sign_greyscale.png b/mods/ITEMS/mcl_signs/textures/default_sign_greyscale.png new file mode 100644 index 000000000..570851a6a Binary files /dev/null and b/mods/ITEMS/mcl_signs/textures/default_sign_greyscale.png differ diff --git a/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_dark.png b/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_dark.png new file mode 100644 index 000000000..6189e7709 Binary files /dev/null and b/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_dark.png differ diff --git a/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_greyscale.png b/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_greyscale.png new file mode 100644 index 000000000..845a8d857 Binary files /dev/null and b/mods/ITEMS/mcl_signs/textures/mcl_signs_sign_greyscale.png differ diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index 37fb5265f..b605b8a45 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -5,6 +5,7 @@ local eat = minetest.item_eat(6, "mcl_core:bowl") --6 hunger points, player receives mcl_core:bowl after eating local flower_effect = { + [ "mcl_flowers:allium" ] = "fire_resistance", [ "mcl_flowers:tulip_white" ] = "poison", [ "mcl_flowers:blue_orchid" ] = "hunger", [ "mcl_flowers:dandelion" ] = "hunger", @@ -14,6 +15,10 @@ local flower_effect = { } local effects = { + [ "fire_resistance" ] = function(itemstack, placer, pointed_thing) + mcl_potions.fire_resistance_func(placer, 1, 4) + return eat(itemstack, placer, pointed_thing) + end, [ "poison" ] = function(itemstack, placer, pointed_thing) mcl_potions.poison_func(placer, 1, 12) return eat(itemstack, placer, pointed_thing) @@ -77,6 +82,7 @@ minetest.register_craftitem("mcl_sus_stew:stew",{ inventory_image = "sus_stew.png", stack_max = 1, on_place = eat_stew, + on_secondary_use = eat_stew, groups = { food = 2, eatable = 4, can_eat_when_full = 1, not_in_creative_inventory=1,}, _mcl_saturation = 7.2, }) @@ -93,6 +99,12 @@ minetest.register_alias("mcl_sus_stew:night_vision_stew", "mcl_sus_stew:stew") -- ______________ --_________________________________________/ Crafts \________________________________ +minetest.register_craft({ + type = "shapeless", + output = "mcl_sus_stew:stew", + recipe = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown", "mcl_core:bowl", "mcl_flowers:allium"}, +}) + minetest.register_craft({ type = "shapeless", output = "mcl_sus_stew:stew", diff --git a/mods/ITEMS/mcl_sus_stew/mod.conf b/mods/ITEMS/mcl_sus_stew/mod.conf index 9e28bd300..c67a120ba 100644 --- a/mods/ITEMS/mcl_sus_stew/mod.conf +++ b/mods/ITEMS/mcl_sus_stew/mod.conf @@ -1,3 +1,3 @@ name = mcl_sus_stew -author = chmodsayshello +author = chmodsayshello, cora depends = mcl_core, mcl_mushrooms, mcl_flowers, mcl_potions, mcl_hunger diff --git a/mods/ITEMS/mcl_throwing/register.lua b/mods/ITEMS/mcl_throwing/register.lua index 53af28652..43dedd33b 100644 --- a/mods/ITEMS/mcl_throwing/register.lua +++ b/mods/ITEMS/mcl_throwing/register.lua @@ -140,24 +140,8 @@ local function egg_on_step(self, dtime) -- FIXME: Chicks have a quite good chance to spawn in walls local r = math.random(1,8) - -- Turn given object into a child - local function make_child(object) - local ent = object:get_luaentity() - object:set_properties({ - visual_size = { x = ent.base_size.x/2, y = ent.base_size.y/2 }, - collisionbox = { - ent.base_colbox[1]/2, - ent.base_colbox[2]/2, - ent.base_colbox[3]/2, - ent.base_colbox[4]/2, - ent.base_colbox[5]/2, - ent.base_colbox[6]/2, - } - }) - ent.child = true - end if r == 1 then - make_child(minetest.add_entity(self._lastpos, "mobs_mc:chicken")) + mcl_mobs.spawn_child(self._lastpos, "mobs_mc:chicken") -- BONUS ROUND: 1/32 chance to spawn 3 additional chicks local r = math.random(1,32) @@ -169,7 +153,7 @@ local function egg_on_step(self, dtime) } for o=1, 3 do local pos = vector.add(self._lastpos, offsets[o]) - make_child(minetest.add_entity(pos, "mobs_mc:chicken")) + mcl_mobs.spawn_child(pos, "mobs_mc:chicken") end end end diff --git a/mods/ITEMS/mcl_tnt/init.lua b/mods/ITEMS/mcl_tnt/init.lua index bf7b52385..83c962092 100644 --- a/mods/ITEMS/mcl_tnt/init.lua +++ b/mods/ITEMS/mcl_tnt/init.lua @@ -1,15 +1,25 @@ local S = minetest.get_translator(minetest.get_current_modname()) local tnt_griefing = minetest.settings:get_bool("mcl_tnt_griefing", true) -local function spawn_tnt(pos, entname) - minetest.sound_play("tnt_ignite", {pos = pos,gain = 1.0,max_hear_distance = 15,}, true) - local tnt = minetest.add_entity(pos, entname) - tnt:set_armor_groups({immortal=1}) - return tnt -end - tnt = {} +tnt.BOOMTIMER = 4 +tnt.BLINKTIMER = 0.25 + +---@param pos Vector +---@param entname string +---@return ObjectRef? +local function spawn_tnt(pos, entname) + minetest.sound_play("tnt_ignite", { pos = pos, gain = 1.0, max_hear_distance = 15 }, true) + local ent = minetest.add_entity(pos, entname) + if ent then + ent:set_armor_groups({ immortal = 1 }) + end + return ent +end + +---@param pos Vector +---@return ObjectRef? function tnt.ignite(pos) minetest.remove_node(pos) local e = spawn_tnt(pos, "mcl_tnt:tnt") @@ -17,61 +27,73 @@ function tnt.ignite(pos) return e end --- Add smoke particle of entity at pos. --- Intended to be called every step +---Add smoke particle of entity at pos. +--- +---Intended to be called every step. +---@param pos Vector function tnt.smoke_step(pos) minetest.add_particle({ - pos = {x=pos.x,y=pos.y+0.5,z=pos.z}, - velocity = vector.new(math.random() * 0.2 - 0.1, 1.0 + math.random(), math.random() * 0.2 - 0.1), - acceleration = vector.new(0, -0.1, 0), - expirationtime = 0.15 + math.random() * 0.25, - size = 1.0 + math.random(), + pos = vector.offset(pos, 0, 0.5, 0), + velocity = vector.new(math.random() * 0.2 - 0.1, 1.0 + math.random(), math.random() * 0.2 - 0.1), + acceleration = vector.new(0, -0.1, 0), + expirationtime = 0.15 + math.random() * 0.25, + size = 1.0 + math.random(), collisiondetection = false, - texture = "mcl_particles_smoke.png" + texture = "mcl_particles_smoke.png" }) end -tnt.BOOMTIMER = 4 -tnt.BLINKTIMER = 0.25 - local TNT_RANGE = 3 local sounds if minetest.get_modpath("mcl_sounds") then sounds = mcl_sounds.node_sound_wood_defaults() end + local tnt_mesecons if minetest.get_modpath("mesecons") then - tnt_mesecons = {effector = { - action_on = tnt.ignite, - rules = mesecon.rules.alldirs, - }} + tnt_mesecons = { + effector = { + action_on = tnt.ignite, + rules = mesecon.rules.alldirs, + }, + } end local longdesc if tnt_griefing then - longdesc = S("An explosive device. When it explodes, it will hurt living beings and destroy blocks around it. TNT has an explosion radius of @1. With a small chance, blocks may drop as an item (as if being mined) rather than being destroyed. TNT can be ignited by tools, explosions, fire, lava and redstone signals.", TNT_RANGE) + longdesc = S("An explosive device. When it explodes, it will hurt living beings and destroy blocks around it. TNT has an explosion radius of @1. With a small chance, blocks may drop as an item (as if being mined) rather than being destroyed. TNT can be ignited by tools, explosions, fire, lava and redstone signals." + , TNT_RANGE) else - longdesc = S("An explosive device. When it explodes, it will hurt living beings. TNT has an explosion radius of @1. TNT can be ignited by tools, explosions, fire, lava and redstone signals.", TNT_RANGE) + longdesc = S("An explosive device. When it explodes, it will hurt living beings. TNT has an explosion radius of @1. TNT can be ignited by tools, explosions, fire, lava and redstone signals." + , TNT_RANGE) end minetest.register_node("mcl_tnt:tnt", { - tiles = {"default_tnt_top.png", "default_tnt_bottom.png", - "default_tnt_side.png", "default_tnt_side.png", - "default_tnt_side.png", "default_tnt_side.png"}, + tiles = { + "default_tnt_top.png", + "default_tnt_bottom.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + }, is_ground_content = false, stack_max = 64, description = S("TNT"), paramtype = "light", sunlight_propagates = true, - _tt_help = S("Ignited by tools, explosions, fire, lava, redstone power").."\n"..S("Explosion radius: @1", tostring(TNT_RANGE)), + _tt_help = S("Ignited by tools, explosions, fire, lava, redstone power") .. + "\n" .. S("Explosion radius: @1", tostring(TNT_RANGE)), _doc_items_longdesc = longdesc, _doc_items_usagehelp = S("Place the TNT and ignite it with one of the methods above. Quickly get in safe distance. The TNT will start to be affected by gravity and explodes in 4 seconds."), - groups = { dig_immediate = 3, tnt = 1, enderman_takable=1, flammable=-1 }, + groups = { dig_immediate = 3, tnt = 1, enderman_takable = 1, flammable = -1 }, mesecons = tnt_mesecons, - on_blast = function(pos) - local e = tnt.ignite(pos) - e:get_luaentity().timer = tnt.BOOMTIMER - (0.5 + math.random()) + on_blast = function(pos, _) + local e = tnt.ignite(pos) + if e then + e:get_luaentity().timer = tnt.BOOMTIMER - (0.5 + math.random()) + end end, _on_ignite = function(player, pointed_thing) tnt.ignite(pointed_thing.under) @@ -84,7 +106,7 @@ minetest.register_node("mcl_tnt:tnt", { _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Place and ignite TNT if minetest.registered_nodes[dropnode.name].buildable_to then - minetest.set_node(droppos, {name = stack:get_name()}) + minetest.set_node(droppos, { name = stack:get_name() }) tnt.ignite(droppos) end end, @@ -94,24 +116,30 @@ minetest.register_node("mcl_tnt:tnt", { local TNT = { -- Static definition physical = true, -- Collides with things - --weight = -100, - collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, + --weight = -100, + collisionbox = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }, visual = "cube", - textures = {"default_tnt_top.png", "default_tnt_bottom.png", - "default_tnt_side.png", "default_tnt_side.png", - "default_tnt_side.png", "default_tnt_side.png"}, + textures = { + "default_tnt_top.png", + "default_tnt_bottom.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + }, -- Initial value for our timer timer = 0, blinktimer = 0, tnt_knockback = true, - blinkstatus = true,} + blinkstatus = true, +} -function TNT:on_activate(staticdata) - local phi = math.random(0, 65535) / 65535 * 2*math.pi +function TNT:on_activate(_, _) + local phi = math.random(0, 65535) / 65535 * 2 * math.pi local hdir_x = math.cos(phi) * 0.02 local hdir_z = math.sin(phi) * 0.02 - self.object:set_velocity({x=hdir_x, y=2, z=hdir_z}) - self.object:set_acceleration({x=0, y=-10, z=0}) + self.object:set_velocity(vector.new(hdir_x, 2, hdir_z)) + self.object:set_acceleration(vector.new(0, -10, 0)) self.object:set_texture_mod("^mcl_tnt_blink.png") end @@ -121,8 +149,8 @@ end time = 0.5, minpos = vector.subtract(pos, radius / 2), maxpos = vector.add(pos, radius / 2), - minvel = {x = -10, y = -10, z = -10}, - maxvel = {x = 10, y = 10, z = 10}, + minvel = vector.new(-10, -10, -10), + maxvel = vector.new(10, 10, 10), minacc = vector.new(), maxacc = vector.new(), minexptime = 1, @@ -152,9 +180,9 @@ end time = 0.1, minpos = vector.subtract(pos, radius / 2), maxpos = vector.add(pos, radius / 2), - minvel = {x = -3, y = 0, z = -3}, - maxvel = {x = 3, y = 5, z = 3}, - minacc = {x = 0, y = -10, z = 0}, + minvel = vector.new(-3, 0, -3), + maxvel = vector.new(3, 5, 3), + minacc = vector.new(0, -10, 0), minexptime = 0.8, maxexptime = 2.0, minsize = radius * 0.66, @@ -164,7 +192,7 @@ end }) end]] -function TNT:on_step(dtime) +function TNT:on_step(dtime, _) local pos = self.object:get_pos() tnt.smoke_step(pos) self.timer = self.timer + dtime @@ -190,10 +218,10 @@ if minetest.get_modpath("mcl_mobitems") then minetest.register_craft({ output = "mcl_tnt:tnt", recipe = { - {"mcl_mobitems:gunpowder", "group:sand", "mcl_mobitems:gunpowder"}, - {"group:sand", "mcl_mobitems:gunpowder", "group:sand"}, - {"mcl_mobitems:gunpowder", "group:sand", "mcl_mobitems:gunpowder"} - } + { "mcl_mobitems:gunpowder", "group:sand", "mcl_mobitems:gunpowder" }, + { "group:sand", "mcl_mobitems:gunpowder", "group:sand" }, + { "mcl_mobitems:gunpowder", "group:sand", "mcl_mobitems:gunpowder" } + }, }) end diff --git a/mods/ITEMS/mcl_tools/init.lua b/mods/ITEMS/mcl_tools/init.lua index 118020f0b..860ea756c 100644 --- a/mods/ITEMS/mcl_tools/init.lua +++ b/mods/ITEMS/mcl_tools/init.lua @@ -25,11 +25,11 @@ 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 = 10 + hand_range = tonumber(minetest.settings:get("mcl_hand_range_creative")) or 10 hand_groups = { dig_speed_class = 7 } else groupcaps = {} - hand_range = 4 + hand_range = tonumber(minetest.settings:get("mcl_hand_range")) or 4.5 hand_groups = { dig_speed_class = 1 } end minetest.register_tool(":", { diff --git a/mods/ITEMS/mcl_torches/api.lua b/mods/ITEMS/mcl_torches/api.lua index dab508795..a2e49aa0d 100644 --- a/mods/ITEMS/mcl_torches/api.lua +++ b/mods/ITEMS/mcl_torches/api.lua @@ -1,3 +1,5 @@ +local flame_texture = {"mcl_particles_flame.png", "mcl_particles_soul_fire_flame.png"} + local smoke_pdef = { amount = 0.5, maxexptime = 2.0, @@ -9,7 +11,8 @@ local smoke_pdef = { maxrelpos = { x = 1/16, y = 0.06, z = 1/16 }, } -local function spawn_flames_floor(pos) +local function spawn_flames_floor(pos, flame_type) + -- Flames mcl_particles.add_node_particlespawner(pos, { amount = 8, @@ -22,14 +25,14 @@ local function spawn_flames_floor(pos) maxexptime = 0.6, minsize = 0.7, maxsize = 2, - texture = "mcl_particles_flame.png", + texture = flame_texture[flame_type], glow = minetest.registered_nodes[minetest.get_node(pos).name].light_source, }, "low") -- Smoke mcl_particles.spawn_smoke(pos, "torch", smoke_pdef) end -local function spawn_flames_wall(pos) +local function spawn_flames_wall(pos, flame_type) --local minrelpos, maxrelpos local node = minetest.get_node(pos) local dir = minetest.wallmounted_to_dir(node.param2) @@ -37,17 +40,17 @@ local function spawn_flames_wall(pos) local smoke_pdef = table.copy(smoke_pdef) if dir.x < 0 then - smoke_pdef.minrelpos = { x = -0.38, y = 0.04, z = -0.1 } - smoke_pdef.maxrelpos = { x = -0.2, y = 0.14, z = 0.1 } + smoke_pdef.minrelpos = { x = -0.38, y = 0.24, z = -0.1 } + smoke_pdef.maxrelpos = { x = -0.2, y = 0.34, z = 0.1 } elseif dir.x > 0 then - smoke_pdef.minrelpos = { x = 0.2, y = 0.04, z = -0.1 } - smoke_pdef.maxrelpos = { x = 0.38, y = 0.14, z = 0.1 } + smoke_pdef.minrelpos = { x = 0.2, y = 0.24, z = -0.1 } + smoke_pdef.maxrelpos = { x = 0.38, y = 0.34, z = 0.1 } elseif dir.z < 0 then - smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = -0.38 } - smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = -0.2 } + smoke_pdef.minrelpos = { x = -0.1, y = 0.24, z = -0.38 } + smoke_pdef.maxrelpos = { x = 0.1, y = 0.34, z = -0.2 } elseif dir.z > 0 then - smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = 0.2 } - smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = 0.38 } + smoke_pdef.minrelpos = { x = -0.1, y = 0.24, z = 0.2 } + smoke_pdef.maxrelpos = { x = 0.1, y = 0.34, z = 0.38 } else return end @@ -65,13 +68,25 @@ local function spawn_flames_wall(pos) maxexptime = 0.6, minsize = 0.7, maxsize = 2, - texture = "mcl_particles_flame.png", + texture = flame_texture[flame_type], glow = minetest.registered_nodes[node.name].light_source, }, "low") -- Smoke mcl_particles.spawn_smoke(pos, "torch", smoke_pdef) end +local function set_flames(pos, flame_type, attached_to) + if attached_to == "wall" then + return function(pos) + spawn_flames_wall(pos, flame_type) + end + end + + return function(pos) + spawn_flames_floor(pos, flame_type) + end +end + local function remove_flames(pos) mcl_particles.delete_node_particlespawners(pos) end @@ -124,6 +139,7 @@ function mcl_torches.register_torch(def) def.light = def.light or minetest.LIGHT_MAX def.mesh_floor = def.mesh_floor or "mcl_torches_torch_floor.obj" def.mesh_wall = def.mesh_wall or "mcl_torches_torch_wall.obj" + def.flame_type = def.flame_type or 1 local groups = def.groups or {} @@ -133,6 +149,7 @@ function mcl_torches.register_torch(def) groups.dig_by_water = 1 groups.destroy_by_lava_flow = 1 groups.dig_by_piston = 1 + groups.flame_type = def.flame_type or 1 local floordef = { description = def.description, @@ -145,7 +162,6 @@ function mcl_torches.register_torch(def) inventory_image = def.icon, wield_image = def.icon, tiles = def.tiles, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, @@ -155,10 +171,10 @@ function mcl_torches.register_torch(def) light_source = def.light, groups = groups, drop = def.drop or itemstring, + use_texture_alpha = "clip", selection_box = { type = "wallmounted", - wall_top = {-1/16, -1/16, -1/16, 1/16, 0.5, 1/16}, - wall_bottom = {-1/16, -0.5, -1/16, 1/16, 1/16, 1/16}, + wall_bottom = {-2/16, -0.5, -2/16, 2/16, 1/16, 2/16}, }, sounds = def.sounds, node_placement_prediction = "", @@ -211,7 +227,11 @@ function mcl_torches.register_torch(def) return itemstack end, on_rotate = false, - on_construct = def.particles and spawn_flames_floor, + on_construct = function(pos) + if def.particles then + set_flames(pos, def.flame_type, "floor") + end + end, on_destruct = def.particles and remove_flames, } minetest.register_node(itemstring, floordef) @@ -223,7 +243,6 @@ function mcl_torches.register_torch(def) drawtype = "mesh", mesh = def.mesh_wall, tiles = def.tiles, - use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false, paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, @@ -232,15 +251,18 @@ function mcl_torches.register_torch(def) light_source = def.light, groups = groups_wall, drop = def.drop or itemstring, + use_texture_alpha = "clip", selection_box = { type = "wallmounted", - wall_top = {-0.1, -0.1, -0.1, 0.1, 0.5, 0.1}, - wall_bottom = {-0.1, -0.5, -0.1, 0.1, 0.1, 0.1}, - wall_side = {-0.5, -0.5, -0.1, -0.2, 0.1, 0.1}, + wall_side = {-0.5, -0.3, -0.1, -0.2, 0.325, 0.1}, }, sounds = def.sounds, on_rotate = false, - on_construct = def.particles and spawn_flames_wall, + on_construct = function(pos) + if def.particles then + set_flames(pos, def.flame_type, "wall") + end + end, on_destruct = def.particles and remove_flames, } minetest.register_node(itemstring_wall, walldef) @@ -259,9 +281,9 @@ minetest.register_lbm({ action = function(pos, node) local torch_group = minetest.get_item_group(node.name, "torch") if torch_group == 1 then - spawn_flames_floor(pos) + spawn_flames_floor(pos, minetest.get_item_group(node.name, "flame_type")) elseif torch_group == 2 then - spawn_flames_wall(pos) + spawn_flames_wall(pos, minetest.get_item_group(node.name, "flame_type")) end end, }) diff --git a/mods/ITEMS/mcl_torches/models/mcl_torches_torch_floor.obj b/mods/ITEMS/mcl_torches/models/mcl_torches_torch_floor.obj index ac4234d3e..b0683b59c 100644 --- a/mods/ITEMS/mcl_torches/models/mcl_torches_torch_floor.obj +++ b/mods/ITEMS/mcl_torches/models/mcl_torches_torch_floor.obj @@ -1,29 +1,72 @@ -# Blender v2.76 (sub 0) OBJ File: 'torch_on_floor_node.blend' +# Blender 3.3.1 # www.blender.org -o torch_Cube_Cube.001_Cube_Cube.001_Material.001 +mtllib mcl_torches_torch_floor.mtl +o cube.004 +v -0.062500 0.437500 -0.500000 +v -0.062500 -0.562500 -0.500000 +v -0.062500 0.437500 0.500000 +v -0.062500 -0.562500 0.500000 v 0.062500 0.062500 0.062500 v 0.062500 0.062500 -0.062500 +v 0.062500 -0.562500 0.062500 +v 0.062500 -0.562500 -0.062500 v -0.062500 0.062500 -0.062500 v -0.062500 0.062500 0.062500 -v -0.062500 -0.500000 0.062500 -v 0.062500 -0.500000 0.062500 -v 0.062500 -0.500000 -0.062500 -v -0.062500 -0.500000 -0.062500 +v -0.062500 -0.562500 -0.062500 +v -0.062500 -0.562500 0.062500 +v 0.500000 0.437500 0.062500 +v 0.500000 -0.562500 0.062500 +v -0.500000 0.437500 0.062500 +v -0.500000 -0.562500 0.062500 +v 0.500000 0.437500 -0.062500 +v 0.500000 -0.562500 -0.062500 +v -0.500000 0.437500 -0.062500 +v -0.500000 -0.562500 -0.062500 +v 0.062500 0.437500 -0.500000 +v 0.062500 -0.562500 -0.500000 +v 0.062500 0.437500 0.500000 +v 0.062500 -0.562500 0.500000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 vt 0.562500 0.500000 vt 0.562500 0.625000 +vt 0.562500 0.125000 +vt 0.562500 0.000063 vt 0.437500 0.625000 vt 0.437500 0.500000 -vt 0.437500 0.000000 -vt 0.562500 0.000000 -vt 0.562500 0.125000 +vt 0.437500 0.000063 vt 0.437500 0.125000 -vn 0.000000 1.000000 0.000000 -vn 0.000000 0.000000 -1.000000 -vn 1.000000 0.000000 0.000000 -s 1 -f 1/1/1 2/2/1 3/3/1 4/4/1 -f 5/5/1 6/6/1 7/7/1 8/8/1 -f 1/2/2 6/6/2 5/5/2 4/3/2 -f 2/3/3 1/2/3 6/6/3 7/5/3 -f 3/2/2 2/3/2 7/5/2 8/6/2 -f 4/3/3 5/5/3 8/6/3 3/2/3 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +s 0 +usemtl m_0.002 +f 3/3/1 4/4/1 1/1/1 +f 4/4/1 2/2/1 1/1/1 +f 9/9/2 10/10/2 6/6/2 +f 10/10/2 5/5/2 6/6/2 +f 12/12/3 11/11/3 7/7/3 +f 11/11/3 8/8/3 7/7/3 +f 13/13/4 14/14/4 15/15/4 +f 14/14/4 16/16/4 15/15/4 +f 19/19/5 20/20/5 17/17/5 +f 20/20/5 18/18/5 17/17/5 +f 21/21/6 22/22/6 23/23/6 +f 22/22/6 24/24/6 23/23/6 diff --git a/mods/ITEMS/mcl_torches/models/mcl_torches_torch_wall.obj b/mods/ITEMS/mcl_torches/models/mcl_torches_torch_wall.obj index 824223e6d..35c192c25 100644 --- a/mods/ITEMS/mcl_torches/models/mcl_torches_torch_wall.obj +++ b/mods/ITEMS/mcl_torches/models/mcl_torches_torch_wall.obj @@ -1,29 +1,72 @@ -# Blender v2.76 (sub 0) OBJ File: 'torch_on_wall_node.blend' +# Blender 3.3.1 # www.blender.org -o torch_wall_Cube_Cube.001_Cube_Cube.001_Material.001 -v 0.062469 -0.303502 0.086070 -v 0.062469 -0.195248 0.023570 -v -0.062531 -0.195248 0.023570 -v -0.062531 -0.303502 0.086070 -v -0.062531 -0.584752 -0.401070 -v 0.062469 -0.584752 -0.401070 -v 0.062469 -0.476498 -0.463570 -v -0.062531 -0.476498 -0.463570 +mtllib mcl_torches_torch_wall.mtl +o cube +v -0.062500 -0.198340 0.273825 +v -0.062500 -0.313825 0.321660 +v -0.062500 -0.437517 -0.303600 +v -0.062500 -0.553002 -0.255765 +v 0.062500 -0.313825 0.321660 +v 0.062500 -0.198340 0.273825 +v 0.062500 -0.553002 -0.255765 +v 0.062500 -0.437517 -0.303600 +v -0.500000 -0.054833 0.620280 +v -0.500000 -0.437517 -0.303600 +v 0.500000 -0.054834 0.620280 +v 0.500000 -0.437517 -0.303600 +v -0.500000 -0.170318 0.668115 +v -0.500000 -0.553002 -0.255765 +v 0.500000 -0.170318 0.668115 +v 0.500000 -0.553002 -0.255765 +v -0.062500 -0.574516 0.835539 +v -0.062500 -0.957199 -0.088340 +v -0.062500 0.349364 0.452856 +v -0.062500 -0.033320 -0.471024 +v 0.062500 -0.574516 0.835539 +v 0.062500 -0.957199 -0.088340 +v 0.062500 0.349364 0.452856 +v 0.062500 -0.033320 -0.471024 +vn -0.0000 0.3827 0.9239 +vn -0.0000 -0.3827 -0.9239 +vn -0.0000 -0.9239 0.3827 +vn -0.0000 0.9239 -0.3827 +vn 1.0000 -0.0000 -0.0000 +vn -1.0000 -0.0000 -0.0000 vt 0.562500 0.500000 vt 0.562500 0.625000 +vt 0.562500 0.125000 +vt 0.562500 0.000063 vt 0.437500 0.625000 vt 0.437500 0.500000 -vt 0.437500 0.000000 -vt 0.562500 0.000000 -vt 0.562500 0.125000 +vt 0.437500 0.000063 vt 0.437500 0.125000 -vn 0.000000 0.500000 0.866000 -vn 0.000000 0.866000 -0.500000 -vn 1.000000 -0.000000 0.000000 -s 1 -f 1/1/1 2/2/1 3/3/1 4/4/1 -f 5/5/1 6/6/1 7/7/1 8/8/1 -f 1/2/2 6/6/2 5/5/2 4/3/2 -f 2/3/3 1/2/3 6/6/3 7/5/3 -f 3/2/2 2/3/2 7/5/2 8/6/2 -f 4/3/3 5/5/3 8/6/3 3/2/3 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +s 0 +usemtl m_0.001 +f 5/5/1 6/6/1 2/2/1 +f 6/6/1 1/1/1 2/2/1 +f 8/8/2 7/7/2 3/3/2 +f 7/7/2 4/4/2 3/3/2 +f 9/9/3 10/10/3 11/11/3 +f 10/10/3 12/12/3 11/11/3 +f 15/15/4 16/16/4 13/13/4 +f 16/16/4 14/14/4 13/13/4 +f 17/17/5 18/18/5 19/19/5 +f 18/18/5 20/20/5 19/19/5 +f 23/23/6 24/24/6 21/21/6 +f 24/24/6 22/22/6 21/21/6 diff --git a/mods/ITEMS/mcl_torches/register.lua b/mods/ITEMS/mcl_torches/register.lua index f8c34e6b5..4eead4024 100644 --- a/mods/ITEMS/mcl_torches/register.lua +++ b/mods/ITEMS/mcl_torches/register.lua @@ -15,6 +15,7 @@ mcl_torches.register_torch({ groups = {dig_immediate = 3, deco_block = 1}, sounds = mcl_sounds.node_sound_wood_defaults(), particles = true, + flame_type = 1, }) minetest.register_craft({ diff --git a/mods/ITEMS/mcl_torches/textures/default_torch_on_floor.png b/mods/ITEMS/mcl_torches/textures/default_torch_on_floor.png index cb0ce15f1..e0656dbb0 100644 Binary files a/mods/ITEMS/mcl_torches/textures/default_torch_on_floor.png and b/mods/ITEMS/mcl_torches/textures/default_torch_on_floor.png differ diff --git a/mods/ITEMS/mcl_torches/textures/default_torch_on_floor_animated.png b/mods/ITEMS/mcl_torches/textures/default_torch_on_floor_animated.png index 28cdc64c7..a34b461c2 100644 Binary files a/mods/ITEMS/mcl_torches/textures/default_torch_on_floor_animated.png and b/mods/ITEMS/mcl_torches/textures/default_torch_on_floor_animated.png differ diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index 4aa843053..e39371651 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -1531,10 +1531,40 @@ local function register_dimension_biomes() --[[ REALMS ]] --[[ THE NETHER ]] + -- the following decoration is a hack to cover exposed bedrock in netherrack - be careful not to put any ceiling decorations in a way that would apply to this (they would get generated regardless of biome) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"mcl_core:bedrock"}, + sidelen = 16, + fill_ratio = 10, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_max + 15, + height = 6, + max_height = 10, + decoration = "mcl_nether:netherrack", + flags = "all_ceilings", + param2 = 0, + }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"mcl_core:bedrock"}, + sidelen = 16, + fill_ratio = 10, + y_min = mcl_vars.mg_nether_min - 10, + y_max = mcl_vars.mg_lava_nether_max, + height = 7, + max_height = 14, + decoration = "mcl_nether:netherrack", + flags = "all_floors,force_placement", + param2 = 0, + }) + + minetest.register_biome({ name = "Nether", node_filler = "mcl_nether:netherrack", node_stone = "mcl_nether:netherrack", + node_top = "mcl_nether:netherrack", node_water = "air", node_river_water = "air", node_cave_liquid = "air", @@ -1549,12 +1579,12 @@ local function register_dimension_biomes() minetest.register_decoration({ deco_type = "simple", - place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand"}, + place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand","mcl_nether:glowstone","mcl_nether:magma"}, sidelen = 16, fill_ratio = 10, biomes = { "Nether" }, - y_min = -31000, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, decoration = "mcl_nether:netherrack", flags = "all_floors", param2 = 0, @@ -1569,7 +1599,6 @@ local function register_dimension_biomes() node_river_water = "air", node_cave_liquid = "air", y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max + 80, heat_point = 77, humidity_point = 33, @@ -1578,12 +1607,12 @@ local function register_dimension_biomes() }) minetest.register_decoration({ deco_type = "simple", - place_on = {"mcl_nether:netherrack","mcl_nether:glowstone"}, + place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_nether:magma"}, sidelen = 16, fill_ratio = 10, biomes = { "SoulsandValley" }, - y_min = -31000, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, decoration = "mcl_blackstone:soul_soil", flags = "all_floors, all_ceilings", param2 = 0, @@ -1597,8 +1626,8 @@ local function register_dimension_biomes() clust_num_ores = 225, clust_size = 15, biomes = { "SoulsandValley" }, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max + 80, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, noise_params = { offset = 0, scale = 1, @@ -1619,7 +1648,6 @@ local function register_dimension_biomes() node_river_water = "air", node_cave_liquid = "air", y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max + 80, heat_point = 60, humidity_point = 47, @@ -1628,12 +1656,12 @@ local function register_dimension_biomes() }) minetest.register_decoration({ deco_type = "simple", - place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand"}, + place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand","mcl_nether:magma","mcl_blackstone:blackstone"}, sidelen = 16, fill_ratio = 10, biomes = { "CrimsonForest" }, - y_min = -31000, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, decoration = "mcl_crimson:crimson_nylium", flags = "all_floors", param2 = 0, @@ -1655,12 +1683,12 @@ local function register_dimension_biomes() }) minetest.register_decoration({ deco_type = "simple", - place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand"}, + place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand","mcl_nether:magma","mcl_blackstone:blackstone"}, sidelen = 16, fill_ratio = 10, biomes = { "WarpedForest" }, - y_min = -31000, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, decoration = "mcl_crimson:warped_nylium", flags = "all_floors", param2 = 0, @@ -1681,16 +1709,29 @@ local function register_dimension_biomes() _mcl_palette_index = 17, }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand","mcl_blackstone:blackstone","mcl_nether:magma"}, + sidelen = 16, + fill_ratio = 10, + biomes = { "BasaltDelta" }, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, + decoration = "mcl_blackstone:basalt", + flags = "all_floors", + param2 = 0, + }) + minetest.register_ore({ ore_type = "blob", ore = "mcl_blackstone:blackstone", - wherein = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_core:gravel","mcl_nether:soul_sand"}, + wherein = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_core:gravel"}, clust_scarcity = 100, clust_num_ores = 400, clust_size = 20, biomes = { "BasaltDelta" }, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max + 80, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_deco_max, noise_params = { offset = 0, scale = 1, @@ -1703,19 +1744,6 @@ local function register_dimension_biomes() } }) - minetest.register_decoration({ - deco_type = "simple", - place_on = {"mcl_nether:netherrack","mcl_nether:glowstone","mcl_blackstone:nether_gold","mcl_nether:quartz_ore","mcl_core:gravel","mcl_nether:soul_sand","mcl_blackstone:blackstone"}, - sidelen = 16, - fill_ratio = 10, - biomes = { "BasaltDelta" }, - y_min = -31000, - y_max = mcl_vars.mg_nether_max, - decoration = "mcl_blackstone:basalt", - flags = "all_floors", - param2 = 0, - }) - --[[ THE END ]] minetest.register_biome({ name = "End", @@ -1732,6 +1760,21 @@ local function register_dimension_biomes() _mcl_biome_type = "medium", _mcl_palette_index = 0, }) + minetest.register_biome({ + name = "EndBarrens", + node_stone = "air", + node_filler = "air", + node_water = "air", + node_river_water = "air", + node_cave_liquid = "air", + y_min = mcl_vars.mg_end_min, + y_max = mcl_vars.mg_end_max + 80, + heat_point = 1000, + humidity_point = 1000, + vertical_blend = 16, + _mcl_biome_type = "medium", + _mcl_palette_index = 0, + }) minetest.register_biome({ name = "EndMidlands", node_stone = "air", @@ -2342,7 +2385,7 @@ local function register_dimension_ores() clust_scarcity = 26 * 26 * 26, clust_size = 5, y_min = mcl_vars.mg_lava_nether_max + 10, - y_max = mcl_vars.mg_nether_max, + y_max = mcl_vars.mg_nether_max - 13, noise_threshold = 0.0, noise_params = { offset = 0.5, @@ -2405,11 +2448,24 @@ local function register_dimension_ores() ore_type = "scatter", ore = "mcl_nether:nether_lava_source", wherein = {"mcl_nether:netherrack", "mcl_core:stone"}, + clust_scarcity = 13500, --rare + clust_num_ores = 1, + clust_size = 1, + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_max - 13, + }) + + local lava_biomes = {"BasaltDelta","Nether"} + minetest.register_ore({ + ore_type = "scatter", + ore = "mcl_nether:nether_lava_source", + wherein = {"mcl_nether:netherrack", "mcl_core:stone"}, clust_scarcity = 500, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_lava_nether_max + 1, + biomes = lava_biomes, + y_min = mcl_vars.mg_nether_min, + y_max = mcl_vars.mg_lava_nether_max + 1, }) minetest.register_ore({ @@ -2419,6 +2475,7 @@ local function register_dimension_ores() clust_scarcity = 1000, clust_num_ores = 1, clust_size = 1, + biomes = lava_biomes, y_min = mcl_vars.mg_lava_nether_max + 2, y_max = mcl_vars.mg_lava_nether_max + 12, }) @@ -2430,6 +2487,7 @@ local function register_dimension_ores() clust_scarcity = 2000, clust_num_ores = 1, clust_size = 1, + biomes = lava_biomes, y_min = mcl_vars.mg_lava_nether_max + 13, y_max = mcl_vars.mg_lava_nether_max + 48, }) @@ -2440,8 +2498,9 @@ local function register_dimension_ores() clust_scarcity = 3500, clust_num_ores = 1, clust_size = 1, + biomes = lava_biomes, y_min = mcl_vars.mg_lava_nether_max + 49, - y_max = mcl_vars.mg_nether_max, + y_max = mcl_vars.mg_nether_max - 13, }) --[[ THE END ]] @@ -2851,6 +2910,25 @@ local function register_decorations() flags = "place_center_x,place_center_z, force_placement", }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"mcl_core:dirt_with_grass","mcl_core:podzol"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.012, + spread = {x = 100, y = 100, z = 100}, + seed = 354, + octaves = 1, + persist = 0.5, + lacunarity = 1.0, + flags = "absvalue" + }, + biomes = {"Taiga","ColdTaiga","MegaTaiga","MegaSpruceTaiga", "Forest"}, + y_max = mcl_vars.mg_overworld_max, + y_min = 2, + decoration = "mcl_sweet_berry:sweet_berry_bush_3" + }) -- Large ice spike minetest.register_decoration({ @@ -3097,7 +3175,48 @@ local function register_decorations() flags = "place_center_x, place_center_z", rotation = "random", }) - + minetest.register_decoration({ + deco_type = "schematic", + place_on = {"group:grass_block_no_snow", "mcl_core:dirt"}, + sidelen = 16, + --[[noise_params = { + offset = 0.01, + scale = 0.00001, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.33 + },]]-- + fill_ratio = 0.0002, + biomes = {"FlowerForest"}, + y_min = 1, + y_max = mcl_vars.mg_overworld_max, + schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic_bee_nest.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + spawn_by = "group:flower", + }) + minetest.register_decoration({ + deco_type = "schematic", + place_on = {"group:grass_block_no_snow", "mcl_core:dirt"}, + sidelen = 16, + --[[noise_params = { + offset = 0.01, + scale = 0.00001, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.33 + },]]-- + fill_ratio = 0.00002, + biomes = {"Forest"}, + y_min = 1, + y_max = mcl_vars.mg_overworld_max, + schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic_bee_nest.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + spawn_by = "group:flower", + }) -- Rare balloon oak minetest.register_decoration({ @@ -3206,7 +3325,27 @@ local function register_decorations() flags = "place_center_x, place_center_z, force_placement", rotation = "random", }) - + minetest.register_decoration({ + deco_type = "schematic", + place_on = {"mcl_mud:mud"}, + sidelen = 80, + --[[noise_params = { + offset = 0.01, + scale = 0.00001, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.33 + },]]-- + fill_ratio = 0.0005, + biomes = {"MangroveSwamp"}, + y_min = 1, + y_max = mcl_vars.mg_overworld_max, + schematic = mod_mcl_mangrove.."/schematics/mcl_mangrove_bee_nest.mts", + flags = "place_center_x, place_center_z, force_placement", + rotation = "random", + spawn_by = "group:flower", + }) minetest.register_decoration({ deco_type = "simple", place_on = {"mcl_mud:mud"}, @@ -3567,6 +3706,27 @@ local function register_decorations() schematic = mod_mcl_core.."/schematics/mcl_core_birch.mts", flags = "place_center_x, place_center_z", }) + minetest.register_decoration({ + deco_type = "schematic", + place_on = {"group:grass_block_no_snow", "mcl_core:dirt"}, + sidelen = 16, + --[[noise_params = { + offset = 0.01, + scale = 0.00001, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.33 + },]]-- + fill_ratio = 0.00002, + biomes = {"Forest", "BirchForest", "BirchForestM"}, + y_min = 1, + y_max = mcl_vars.mg_overworld_max, + schematic = mod_mcl_core.."/schematics/mcl_core_birch_bee_nest.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + spawn_by = "group:flower", + }) -- Dark Oak minetest.register_decoration({ @@ -4724,17 +4884,6 @@ local function register_dimension_decorations() flags = "all_floors", decoration = "mcl_mushrooms:mushroom_red", }) - minetest.register_decoration({ - deco_type = "simple", - place_on = {"mcl_nether:soul_sand"}, - sidelen = 16, - fill_ratio = 0.0032, - biomes = {"Nether","SoulsandValley"}, - y_min = mcl_vars.mg_lava_nether_max + 1, - y_max = mcl_vars.mg_nether_max - 1, - flags = "all_floors", - decoration = "mcl_nether:nether_wart", - }) -- WARPED FOREST minetest.register_decoration({ @@ -4794,7 +4943,7 @@ local function register_dimension_decorations() deco_type = "simple", place_on = {"mcl_crimson:warped_nylium","mcl_crimson:twisting_vines"}, sidelen = 16, - fill_ratio = 0.012, + fill_ratio = 0.032, biomes = {"WarpedForest"}, y_min = mcl_vars.mg_lava_nether_max + 1, flags = "all_floors", @@ -4831,7 +4980,7 @@ local function register_dimension_decorations() fill_ratio = 0.02, biomes = {"CrimsonForest"}, y_min = mcl_vars.mg_lava_nether_max + 1, - y_max = mcl_vars.mg_lava_nether_max - 10, + y_max = mcl_vars.mg_nether_max - 10, flags = "all_floors", decoration = "mcl_crimson:crimson_fungus", }) @@ -4877,6 +5026,19 @@ local function register_dimension_decorations() size = {x = 7, y = 13, z = 7}, rotation = "random", }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"mcl_crimson:warped_nylium","mcl_crimson:weeping_vines","mcl_nether:netherrack"}, + sidelen = 16, + fill_ratio = 0.063, + biomes = {"CrimsonForest"}, + y_min = mcl_vars.mg_lava_nether_max + 1, + y_max = mcl_vars.mg_nether_deco_max, + flags = "all_ceilings", + height = 2, + height_max = 8, + decoration = "mcl_crimson:weeping_vines", + }) minetest.register_decoration({ deco_type = "simple", place_on = {"mcl_crimson:crimson_nylium"}, @@ -4968,6 +5130,7 @@ local function register_dimension_decorations() }, biomes = {"BasaltDelta"}, y_min = mcl_vars.mg_lava_nether_max + 1, + y_max = mcl_vars.mg_nether_deco_max - 50, flags = "all_floors, all ceilings", }) minetest.register_decoration({ @@ -4988,6 +5151,19 @@ local function register_dimension_decorations() }, biomes = {"BasaltDelta"}, y_min = mcl_vars.mg_lava_nether_max + 1, + y_max = mcl_vars.mg_nether_deco_max - 15, + flags = "all_floors, all ceilings", + }) + minetest.register_decoration({ + deco_type = "simple", + decoration = "mcl_blackstone:basalt", + place_on = {"mcl_blackstone:basalt","mcl_nether:netherrack","mcl_blackstone:blackstone"}, + sidelen = 80, + height_max = 3, + fill_ratio = 0.4, + biomes = {"BasaltDelta"}, + y_min = mcl_vars.mg_lava_nether_max + 1, + y_max = mcl_vars.mg_nether_deco_max - 15, flags = "all_floors, all ceilings", }) minetest.register_decoration({ diff --git a/mods/MAPGEN/mcl_mapgen_core/api.lua b/mods/MAPGEN/mcl_mapgen_core/api.lua index 7e05afe12..630270444 100644 --- a/mods/MAPGEN/mcl_mapgen_core/api.lua +++ b/mods/MAPGEN/mcl_mapgen_core/api.lua @@ -15,7 +15,7 @@ minetest.register_on_generated(function(minp, maxp, blockseed) local t1 = os.clock() local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z} if lvm > 0 then - local lvm_used, shadow, deco_used = false, false, false + local lvm_used, shadow, deco_used, deco_table, ore_used, ore_table = false, false, false, false, false, false local lb2 = {} -- param2 local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z} @@ -28,16 +28,23 @@ minetest.register_on_generated(function(minp, maxp, blockseed) for _, rec in ipairs(registered_generators) do if rec.vf then - local lvm_used0, shadow0, deco = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed) + local lvm_used0, shadow0, deco, ore = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed) if lvm_used0 then lvm_used = true end if shadow0 then shadow = true end - if deco then + if deco and type(deco) == "table" then + deco_table = deco + elseif deco then deco_used = true end + if ore and type(ore) == "table" then + ore_table = ore + elseif deco then + ore_used = true + end end end @@ -47,9 +54,16 @@ minetest.register_on_generated(function(minp, maxp, blockseed) if param2 > 0 then vm:set_param2_data(data2) end - if deco_used then + if deco_table then + minetest.generate_decorations(vm,vector.new(minp.x,deco_table.min,minp.z),vector.new(maxp.x,deco_table.max,maxp.z)) + elseif deco_used then minetest.generate_decorations(vm) end + if ore_table then + minetest.generate_ores(vm,vector.new(minp.x,ore_table.min,minp.z),vector.new(maxp.x,ore_table.max,maxp.z)) + elseif ore_used then + minetest.generate_ores(vm) + end vm:calc_lighting(p1, p2, shadow) vm:write_to_map() vm:update_liquids() diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index c2fe2e31b..03c5aeb13 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -104,6 +104,25 @@ if superflat then minetest.set_mapgen_setting("mgflat_spflags", "nolakes,nohills", true) end +if mg_name == "v7" then + minetest.set_mapgen_setting("mgv7_cavern_threshold", "0.20", true) + mg_flags.caverns = true +elseif mg_name == "valleys" then + minetest.set_mapgen_setting("mgvalleys_cavern_threshold", "0.20", true) + mg_flags.caverns = true +elseif mg_name == "carpathian" then + minetest.set_mapgen_setting("mgcarpathian_cavern_threshold", "0.20", true) + mg_flags.caverns = true +elseif mg_name == "v5" then + minetest.set_mapgen_setting("mgv5_cavern_threshold", "0.20", true) + mg_flags.caverns = true +elseif mg_name == "fractal" then + minetest.set_mapgen_setting("mgfractal_cavern_threshold", "0.20", true) + mg_flags.caverns = true +end + + + local mg_flags_str = "" for k,v in pairs(mg_flags) do if v == false then @@ -251,6 +270,7 @@ end local function set_palette(minp,maxp,data2,area,biomemap,nodes) -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + if not biomemap then return end local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) local nodes = minetest.find_nodes_in_area(minp, maxp, nodes) for n=1, #nodes do @@ -312,8 +332,16 @@ local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, bl lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used, pr) end end - - return lvm_used, false + local deco = false + local ores = false + if minp.y > mcl_vars.mg_nether_deco_max - 64 and maxp.y < mcl_vars.mg_nether_max + 128 then + deco = {min=mcl_vars.mg_nether_deco_max,max=mcl_vars.mg_nether_max} + end + if minp.y < mcl_vars.mg_nether_min + 10 or maxp.y < mcl_vars.mg_nether_min + 60 then + deco = {min=mcl_vars.mg_nether_min - 10,max=mcl_vars.mg_nether_min + 20} + ores = {min=mcl_vars.mg_nether_min - 10,max=mcl_vars.mg_nether_min + 20} + end + return lvm_used, lvm_used, deco, ores end local function block_fixes(vm, data, data2, emin, emax, area, minp, maxp, blockseed) @@ -353,7 +381,7 @@ mcl_mapgen_core.register_generator("end_fixes", end_basic, function(minp,maxp) if maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max then return end end, 9999, true) -if mg_name ~= "v6" then +if mg_name ~= "v6" and mg_name ~= "singlenode" then mcl_mapgen_core.register_generator("block_fixes", block_fixes, nil, 9999, true) end diff --git a/mods/MAPGEN/mcl_nether_fortresses/init.lua b/mods/MAPGEN/mcl_nether_fortresses/init.lua index 8a5d97244..bf8f9c599 100644 --- a/mods/MAPGEN/mcl_nether_fortresses/init.lua +++ b/mods/MAPGEN/mcl_nether_fortresses/init.lua @@ -1,29 +1,212 @@ local modname = minetest.get_current_modname() +local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) +local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false) mcl_structures.register_structure("nether_outpost",{ - place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil"}, - noise_params = { - offset = 0, - scale = 0.00022, - spread = {x = 250, y = 250, z = 250}, - seed = 333, - octaves = 1, - persist = 0.0001, - flags = "absvalue", - }, + place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand"}, + fill_ratio = 0.01, + chunk_probability = 900, flags = "all_floors", biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest","BasaltDelta"}, - sidelen = 15, + sidelen = 24, solid_ground = true, make_foundation = true, y_min = mcl_vars.mg_lava_nether_max - 1, y_max = mcl_vars.mg_nether_max - 30, - filenames = { modpath.."/schematics/nether_outpost.mts" }, + filenames = { modpath.."/schematics/mcl_nether_fortresses_nether_outpost.mts" }, y_offset = 0, after_place = function(pos) local sp = minetest.find_nodes_in_area(pos,vector.offset(pos,0,20,0),{"mcl_mobspawners:spawner"}) if not sp[1] then return end - mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, minetest.LIGHT_MAX+1, 10, 3, -1) + mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, minetest.LIGHT_MAX+1, 10, 8, 0) end }) +local nbridges = { + modpath.."/schematics/mcl_nether_fortresses_nether_bridge_1.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bridge_2.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bridge_3.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bridge_4.mts", +} +mcl_structures.register_structure("nether_bridge",{ + place_on = {"mcl_nether:nether_lava_source","mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand","mcl_core:bedrock"}, + fill_ratio = 0.01, + chunk_probability = 500, + flags = "all_floors", + sidelen = 38, + solid_ground = false, + make_foundation = false, + y_min = mcl_vars.mg_nether_min - 4, + y_max = mcl_vars.mg_lava_nether_max - 20, + filenames = nbridges, + y_offset = function(pr) return pr:next(15,20) end, + after_place = function(pos,def,pr) + local p1 = vector.offset(pos,-14,0,-14) + local p2 = vector.offset(pos,14,24,14) + mcl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5) + end +}) + +mcl_structures.register_structure("nether_outpost_with_bridges",{ + place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand","mcl_nether:nether_lava_source"}, + fill_ratio = 0.01, + chunk_probability = 1300, + flags = "all_floors", + biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest","BasaltDelta"}, + sidelen = 24, + solid_ground = true, + make_foundation = true, + y_min = mcl_vars.mg_lava_nether_max - 1, + y_max = mcl_vars.mg_nether_max - 30, + filenames = { modpath.."/schematics/mcl_nether_fortresses_nether_outpost.mts" }, + daughters = {{ + files = { nbridges[1] }, + pos = vector.new(0,-2,-24), + rot = 180, + }, + { + files = { nbridges[1] }, + pos = vector.new(0,-2,24), + rot = 0, + }, + { + files = { nbridges[1] }, + pos = vector.new(-24,-2,0), + rot = 270, + }, + { + files = { nbridges[1] }, + pos = vector.new(24,-2,0), + rot = 90, + }, + }, + after_place = function(pos,def,pr) + local sp = minetest.find_nodes_in_area(pos,vector.offset(pos,0,20,0),{"mcl_mobspawners:spawner"}) + if not sp[1] then return end + mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, minetest.LIGHT_MAX+1, 10, 8, 0) + + local legs = minetest.find_nodes_in_area(vector.offset(pos,-45,-2,-45),vector.offset(pos,45,0,45), "mcl_nether:nether_brick") + local bricks = {} + for _,leg in pairs(legs) do + while minetest.get_item_group(mcl_vars.get_node(vector.offset(leg,0,-1,0), true, 333333).name, "solid") == 0 do + leg = vector.offset(leg,0,-1,0) + table.insert(bricks,leg) + end + end + minetest.bulk_set_node(bricks, {name = "mcl_nether:nether_brick", param2 = 2}) + + local p1 = vector.offset(pos,-45,13,-45) + local p2 = vector.offset(pos,45,13,45) + mcl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5) + end +},true) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:witherskeleton", + y_min = mcl_vars.mg_lava_nether_max, + y_max = mcl_vars.mg_nether_max, + chance = 15, + interval = 60, + limit = 4, + spawnon = { "mcl_blackstone:blackstone_chiseled_polished" }, +}) + +mcl_structures.register_structure("nether_bulwark",{ + place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand"}, + fill_ratio = 0.01, + chunk_probability = 900, + flags = "all_floors", + biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest"}, + sidelen = 36, + solid_ground = true, + make_foundation = true, + y_min = mcl_vars.mg_lava_nether_max - 1, + y_max = mcl_vars.mg_nether_max - 30, + filenames = { + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_1.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_2.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_3.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_4.mts", + }, + daughters = {{ + files = { + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_1.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_2.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_3.mts", + modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_4.mts", + }, + pos = vector.new(0,0,0), + }, + }, + y_offset = 0, + construct_nodes = {"group:wall"}, + after_place = function(pos,def,pr) + local p1 = vector.offset(pos,-14,0,-14) + local p2 = vector.offset(pos,14,24,14) + mcl_structures.spawn_mobs("mobs_mc:piglin",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr,5) + mcl_structures.spawn_mobs("mobs_mc:piglin_brute",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr) + mcl_structures.spawn_mobs("mobs_mc:hoglin",{"mcl_blackstone:nether_gold"},p1,p2,pr,4) + end, + loot = { + ["mcl_chests:chest_small" ] ={ + { + stacks_min = 1, + stacks_max = 2, + items = { + --{ itemstring = "FIXME:spectral_arrow", weight = 1, amount_min = 10, amount_max=28 }, + { itemstring = "mcl_blackstone:blackstone_gilded", weight = 1, amount_min = 8, amount_max=12 }, + { itemstring = "mcl_core:iron_ingot", weight = 1, amount_min = 4, amount_max=9 }, + { itemstring = "mcl_core:gold_ingot", weight = 1, amount_min = 4, amount_max=9 }, + { itemstring = "mcl_core:crying_obsidian", weight = 1, amount_min = 3, amount_max=8 }, + { itemstring = "mcl_bows:crossbow", weight = 1, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_core:goldblock", weight = 1, }, + { itemstring = "mcl_tools:sword_gold", weight = 1, }, + { itemstring = "mcl_tools:axe_gold", weight = 1, func = function(stack, pr)mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, + { itemstring = "mcl_armor:helmet_gold", weight = 1, func = function(stack, pr)mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, + { itemstring = "mcl_armor:chestplate_gold", weight = 1, func = function(stack, pr)mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, + { itemstring = "mcl_armor:leggings_gold", weight = 1, func = function(stack, pr)mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, + { itemstring = "mcl_armor:boots_gold", weight = 1, func = function(stack, pr)mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end }, + } + }, + { + stacks_min = 2, + stacks_max = 4, + items = { + { itemstring = "mcl_bows:arrow", weight = 4, amount_min = 5, amount_max=17 }, + { itemstring = "mcl_mobitems:string", weight = 4, amount_min = 1, amount_max=6 }, + { itemstring = "mcl_core:iron_nugget", weight = 1, amount_min = 2, amount_max = 6 }, + { itemstring = "mcl_core:gold_nugget", weight = 1, amount_min = 2, amount_max = 6 }, + { itemstring = "mcl_mobitems:leather", weight = 1, amount_min = 1, amount_max = 3 }, + } + }, + { + stacks_min = 1, + stacks_max = 1, + items = { + { itemstring = "mcl_compass:lodestone" }, + } + }} + }, +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:piglin", + y_min = mcl_vars.mg_nether_min, + y_max = mcl_vars.mg_nether_max, + chance = 10, + interval = 60, + limit = 9, + spawnon = {"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"}, +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:piglin_brute", + y_min = mcl_vars.mg_nether_min, + y_max = mcl_vars.mg_nether_max, + chance = 20, + interval = 60, + limit = 4, + spawnon = {"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"}, +}) diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_1.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_1.mts new file mode 100644 index 000000000..6923f6edb Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_1.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_2.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_2.mts new file mode 100644 index 000000000..ba04dfd2d Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_2.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_3.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_3.mts new file mode 100644 index 000000000..e62e298fd Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_3.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_4.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_4.mts new file mode 100644 index 000000000..6b66ac6a0 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bridge_4.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_1.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_1.mts new file mode 100644 index 000000000..a9522cce0 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_1.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_2.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_2.mts new file mode 100644 index 000000000..7cf4c0722 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_2.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_3.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_3.mts new file mode 100644 index 000000000..01f893dd7 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_3.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_4.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_4.mts new file mode 100644 index 000000000..1fc74c18b Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_4.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_1.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_1.mts new file mode 100644 index 000000000..9c09c3edb Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_1.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_2.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_2.mts new file mode 100644 index 000000000..b73a5a590 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_2.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_3.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_3.mts new file mode 100644 index 000000000..0a4c05425 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_3.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_4.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_4.mts new file mode 100644 index 000000000..d7e23f027 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_bulwark_interior_4.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_outpost.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_outpost.mts new file mode 100644 index 000000000..4fa3f1935 Binary files /dev/null and b/mods/MAPGEN/mcl_nether_fortresses/schematics/mcl_nether_fortresses_nether_outpost.mts differ diff --git a/mods/MAPGEN/mcl_nether_fortresses/schematics/nether_outpost.mts b/mods/MAPGEN/mcl_nether_fortresses/schematics/nether_outpost.mts deleted file mode 100644 index 7fba741bf..000000000 Binary files a/mods/MAPGEN/mcl_nether_fortresses/schematics/nether_outpost.mts and /dev/null differ diff --git a/mods/MAPGEN/mcl_strongholds/init.lua b/mods/MAPGEN/mcl_strongholds/init.lua index 2a362cc40..d5bc87963 100644 --- a/mods/MAPGEN/mcl_strongholds/init.lua +++ b/mods/MAPGEN/mcl_strongholds/init.lua @@ -16,25 +16,17 @@ local stronghold_rings = { } local strongholds = {} -local strongholds_inited = false local mg_name = minetest.get_mapgen_setting("mg_name") local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +local seed = tonumber(minetest.get_mapgen_setting("seed")) --- Determine the stronghold positions and store them into the strongholds table. --- The stronghold positions are based on the world seed. --- The actual position might be offset by a few blocks because it might be shifted --- to make sure the end portal room is completely within the boundaries of a mapchunk. local function init_strongholds() - if strongholds_inited then - return - end + local stronghold_positions = {} -- Don't generate strongholds in singlenode if mg_name == "singlenode" then - strongholds_inited = true - return + return {} end - local seed = tonumber(minetest.get_mapgen_setting("seed")) local pr = PseudoRandom(seed) for s=1, #stronghold_rings do local ring = stronghold_rings[s] @@ -53,17 +45,14 @@ local function init_strongholds() end local pos = { x = math.cos(angle) * dist, y = y, z = math.sin(angle) * dist } pos = vector.round(pos) - table.insert(strongholds, { pos = pos, generated = false }) + table.insert(stronghold_positions, pos) -- Rotate angle by (360 / amount) degrees. -- This will cause the angles to be evenly distributed in the stronghold ring angle = math.fmod(angle + ((math.pi*2) / ring.amount), math.pi*2) end end - - mcl_structures.register_structure_data("stronghold", table.copy(strongholds)) - - strongholds_inited = true + return stronghold_positions end -- Stronghold generation for register_on_generated. @@ -94,13 +83,94 @@ local function generate_strongholds(minp, maxp, blockseed) pos.z = maxp.z - 7 end - mcl_structures.call_struct(pos, "end_portal_shrine", nil, pr) + --mcl_structures.call_struct(pos, "end_portal_shrine", nil, pr) strongholds[s].generated = true end end end end -init_strongholds() +mcl_structures.register_structure("end_shrine",{ + static_pos = init_strongholds(), + filenames = { + minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_portal_room_simple.mts" + }, + after_place = function(pos,def,pr,blockseed,p1,p2,size,rotation) + local p1 = vector.subtract(pos,size) + local p2 = vector.add(pos,size) + local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") + for s=1, #spawners do + --local meta = minetest.get_meta(spawners[s]) + mcl_mobspawners.setup_spawner(spawners[s], "mobs_mc:silverfish") + end -mcl_mapgen_core.register_generator("strongholds", nil, generate_strongholds, 999999) + -- Shuffle stone brick types + local bricks = minetest.find_nodes_in_area(p1, p2, "mcl_core:stonebrick") + for b=1, #bricks do + local r_bricktype = pr:next(1, 100) + local r_infested = pr:next(1, 100) + local bricktype + if r_infested <= 5 then + if r_bricktype <= 30 then -- 30% + bricktype = "mcl_monster_eggs:monster_egg_stonebrickmossy" + elseif r_bricktype <= 50 then -- 20% + bricktype = "mcl_monster_eggs:monster_egg_stonebrickcracked" + else -- 50% + bricktype = "mcl_monster_eggs:monster_egg_stonebrick" + end + else + if r_bricktype <= 30 then -- 30% + bricktype = "mcl_core:stonebrickmossy" + elseif r_bricktype <= 50 then -- 20% + bricktype = "mcl_core:stonebrickcracked" + end + -- 50% stonebrick (no change necessary) + end + if bricktype then + minetest.set_node(bricks[b], { name = bricktype }) + end + end + + -- Also replace stairs + local stairs = minetest.find_nodes_in_area(p1, p2, {"mcl_stairs:stair_stonebrick", "mcl_stairs:stair_stonebrick_outer", "mcl_stairs:stair_stonebrick_inner"}) + for s=1, #stairs do + local stair = minetest.get_node(stairs[s]) + local r_type = pr:next(1, 100) + if r_type <= 30 then -- 30% mossy + if stair.name == "mcl_stairs:stair_stonebrick" then + stair.name = "mcl_stairs:stair_stonebrickmossy" + elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then + stair.name = "mcl_stairs:stair_stonebrickmossy_outer" + elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then + stair.name = "mcl_stairs:stair_stonebrickmossy_inner" + end + minetest.set_node(stairs[s], stair) + elseif r_type <= 50 then -- 20% cracky + if stair.name == "mcl_stairs:stair_stonebrick" then + stair.name = "mcl_stairs:stair_stonebrickcracked" + elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then + stair.name = "mcl_stairs:stair_stonebrickcracked_outer" + elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then + stair.name = "mcl_stairs:stair_stonebrickcracked_inner" + end + minetest.set_node(stairs[s], stair) + end + -- 50% no change + end + + -- Randomly add ender eyes into end portal frames, but never fill the entire frame + local frames = minetest.find_nodes_in_area(p1, p2, "mcl_portals:end_portal_frame") + local eyes = 0 + for f=1, #frames do + local r_eye = pr:next(1, 10) + if r_eye == 1 then + eyes = eyes + 1 + if eyes < #frames then + local frame_node = minetest.get_node(frames[f]) + frame_node.name = "mcl_portals:end_portal_frame_eye" + minetest.set_node(frames[f], frame_node) + end + end + end + end, +}) diff --git a/mods/MAPGEN/mcl_structures/api.lua b/mods/MAPGEN/mcl_structures/api.lua index 6b157717e..cf47b4e30 100644 --- a/mods/MAPGEN/mcl_structures/api.lua +++ b/mods/MAPGEN/mcl_structures/api.lua @@ -1,15 +1,91 @@ mcl_structures.registered_structures = {} +local place_queue = {} local disabled_structures = minetest.settings:get("mcl_disabled_structures") if disabled_structures then disabled_structures = disabled_structures:split(",") else disabled_structures = {} end +local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false) +local mob_cap_player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75 +local mob_cap_animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10 + local logging = minetest.settings:get_bool("mcl_logging_structures",true) +local mg_name = minetest.get_mapgen_setting("mg_name") + +local rotations = { + "0", + "90", + "180", + "270" +} + function mcl_structures.is_disabled(structname) return table.indexof(disabled_structures,structname) ~= -1 end +local function ecb_place(blockpos, action, calls_remaining, param) + if calls_remaining >= 1 then return end + minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags) + if param.after_placement_callback and param.p1 and param.p2 then + param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param) + end +end + +function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param) + if type(schematic) ~= "table" and not mcl_util.file_exists(schematic) then + minetest.log("warning","[mcl_structures] schematic file "..tostring(schematic).." does not exist.") + return end + local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")() + if s and s.size then + local x, z = s.size.x, s.size.z + if rotation then + if rotation == "random" and pr then + rotation = rotations[pr:next(1,#rotations)] + end + if rotation == "random" then + x = math.max(x, z) + z = x + elseif rotation == "90" or rotation == "270" then + x, z = z, x + end + end + local p1 = {x=pos.x , y=pos.y , z=pos.z } + local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1} + minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) + local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param} + minetest.emerge_area(p1, p2, ecb_place, param) + return true + end +end + +function mcl_structures.get_struct(file) + local localfile = modpath.."/schematics/"..file + local file, errorload = io.open(localfile, "rb") + if errorload then + minetest.log("error", "[mcl_structures] Could not open this struct: "..localfile) + return nil + end + + local allnode = file:read("*a") + file:close() + + return allnode +end + +-- Call on_construct on pos. +-- Useful to init chests from formspec. +local function init_node_construct(pos) + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + if def and def.on_construct then + def.on_construct(pos) + return true + end + return false +end +mcl_structures.init_node_construct = init_node_construct + function mcl_structures.fill_chests(p1,p2,loot,pr) for it,lt in pairs(loot) do local nodes = minetest.find_nodes_in_area(p1, p2, it) @@ -30,13 +106,17 @@ local function generate_loot(pos, def, pr) if def.loot then mcl_structures.fill_chests(p1,p2,def.loot,pr) end end -local function construct_nodes(pos,def,pr) - local nn = minetest.find_nodes_in_area(vector.offset(pos,-def.sidelen/2,0,-def.sidelen/2),vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2),def.construct_nodes) +function mcl_structures.construct_nodes(p1,p2,nodes) + local nn=minetest.find_nodes_in_area(p1,p2,nodes) for _,p in pairs(nn) do mcl_structures.init_node_construct(p) end end +local function construct_nodes(pos,def,pr) + return mcl_structures.construct_nodes(vector.offset(pos,-def.sidelen/2,0,-def.sidelen/2),vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2),def.construct_nodes) +end + function mcl_structures.find_lowest_y(pp) local y = 31000 @@ -115,7 +195,7 @@ local function foundation(ground_p1,ground_p2,pos,sidelen) local node_top = "mcl_core:dirt_with_grass" or minetest.get_node(ground_p1).name local node_dust = nil - if minetest.get_mapgen_setting("mg_name") ~= "v6" then + if mg_name ~= "v6" then local b = minetest.registered_biomes[minetest.get_biome_name(minetest.get_biome_data(pos).biome)] --minetest.log(dump(b.node_top)) if b then @@ -136,8 +216,45 @@ local function foundation(ground_p1,ground_p2,pos,sidelen) minetest.bulk_set_node(stone,{name=node_stone}) end -function mcl_structures.place_structure(pos, def, pr, blockseed) +local function process_queue() + if #place_queue < 1 then return end + local s = table.remove(place_queue) + mcl_structures.place_schematic(s.pos, s.file, s.rot, nil, true, "place_center_x,place_center_z",function(s) + if s.after_place then + s.after_place(s.pos,s.def,s.pr) + end + end,s.pr) + minetest.after(0.5,process_queue) +end + +function mcl_structures.spawn_mobs(mob,spawnon,p1,p2,pr,n,water) + n = n or 1 + local sp = {} + if water then + local nn = minetest.find_nodes_in_area(p1,p2,spawnon) + for k,v in pairs(nn) do + if minetest.get_item_group(minetest.get_node(vector.offset(v,0,1,0)).name,"water") > 0 then + table.insert(sp,v) + end + end + else + sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon) + end + table.shuffle(sp) + for i,node in pairs(sp) do + if not peaceful and i <= n then + local pos = vector.offset(node,0,1,0) + if pos then + minetest.add_entity(pos,mob) + end + end + minetest.get_meta(node):set_string("spawnblock","yes") + end +end + +function mcl_structures.place_structure(pos, def, pr, blockseed, rot) if not def then return end + if not rot then rot = "random" end local log_enabled = logging and not def.terrain_feature local y_offset = 0 if type(def.y_offset) == "function" then @@ -173,13 +290,32 @@ function mcl_structures.place_structure(pos, def, pr, blockseed) local r = pr:next(1,#def.filenames) local file = def.filenames[r] if file then + local rot = rotations[pr:next(1,#rotations)] local ap = function(pos,def,pr,blockseed) end - if def.after_place then ap = def.after_place end - mcl_structures.place_schematic(pp, file, "random", nil, true, "place_center_x,place_center_z",function(p) - if def.loot then generate_loot(pp,def,pr,blockseed) end - if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end - return ap(pp,def,pr,blockseed) + if def.daughters then + ap = function(pos,def,pr,blockseed) + for _,d in pairs(def.daughters) do + local p = vector.add(pos,d.pos) + local rot = d.rot or 0 + mcl_structures.place_schematic(p, d.files[pr:next(1,#d.files)], rot, nil, true, "place_center_x,place_center_z",function() + if def.loot then generate_loot(pp,def,pr,blockseed) end + if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end + if def.after_place then + def.after_place(pos,def,pr) + end + end,pr) + end + end + elseif def.after_place then + ap = def.after_place + end + mcl_structures.place_schematic(pp, file, rot, def.replacements, true, "place_center_x,place_center_z",function(p1, p2, size, rotation) + if not def.daughters then + if def.loot then generate_loot(pp,def,pr,blockseed) end + if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end + end + return ap(pp,def,pr,blockseed,p1,p2,size,rotation) end,pr) if log_enabled then minetest.log("action","[mcl_structures] "..def.name.." placed at "..minetest.pos_to_string(pp)) @@ -242,6 +378,35 @@ function mcl_structures.register_structure(name,def,nospawn) --nospawn means it mcl_structures.registered_structures[name] = def end +local structure_spawns = {} +function mcl_structures.register_structure_spawn(def) + --name,y_min,y_max,spawnon,biomes,chance,interval,limit + minetest.register_abm({ + label = "Spawn "..def.name, + nodenames = def.spawnon, + min_y = def.y_min or -31000, + max_y = def.y_max or 31000, + interval = def.interval or 60, + chance = def.chance or 5, + action = function(pos, node, active_object_count, active_object_count_wider) + local limit = def.limit or 7 + if active_object_count_wider > limit + mob_cap_animal then return end + if active_object_count_wider > mob_cap_player then return end + local p = vector.offset(pos,0,1,0) + if minetest.get_node(p).name ~= "air" then return end + if minetest.get_meta(pos):get_string("spawnblock") == "" then return end + if mg_name ~= "v6" and mg_name ~= "singlenode" and def.biomes then + if table.indexof(def.biomes,minetest.get_biome_name(minetest.get_biome_data(p).biome)) == -1 then + return + end + end + local mobdef = minetest.registered_entities[def.name] + if mobdef.can_spawn and not mobdef.can_spawn(p) then return end + minetest.add_entity(p,def.name) + end, + }) +end + --lbm for secondary structures (structblock included in base structure) minetest.register_lbm({ name = "mcl_structures:struct_lbm", diff --git a/mods/MAPGEN/mcl_structures/end_city.lua b/mods/MAPGEN/mcl_structures/end_city.lua index 942d81366..5f432a0eb 100644 --- a/mods/MAPGEN/mcl_structures/end_city.lua +++ b/mods/MAPGEN/mcl_structures/end_city.lua @@ -2,14 +2,13 @@ local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) +local spawnon = {"mcl_end:purpur_block"} + local function spawn_shulkers(pos,def,pr) - local nn = minetest.find_nodes_in_area_under_air(vector.offset(pos,-def.sidelen/2,-1,-def.sidelen/2),vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2),{"mcl_end:purpur_block"}) - if nn and #nn > 0 then - table.shuffle(nn) - for i = 1,pr:next(1,math.min(6,#nn)) do - minetest.add_entity(vector.offset(nn[i],0,0.5,0),"mobs_mc:shulker") - end - end + local p1 = vector.offset(pos,-def.sidelen/2,-1,-def.sidelen/2) + local p2 = vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2) + mcl_structures.spawn_mobs("mobs_mc:shulker",spawnon,p1,p2,pr,1) + local guard = minetest.find_node_near(pos,def.sidelen,{"mcl_itemframes:item_frame"}) if guard then minetest.add_entity(vector.offset(guard,0,-1.5,0),"mobs_mc:shulker") @@ -133,3 +132,13 @@ mcl_structures.register_structure("end_boat",{ }} } }) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:shulker", + y_min = mcl_vars.mg_end_min, + y_max = mcl_vars.mg_end_max, + chance = 10, + interval = 60, + limit = 6, + spawnon = spawnon, +}) diff --git a/mods/MAPGEN/mcl_structures/end_spawn.lua b/mods/MAPGEN/mcl_structures/end_spawn.lua index cf66e4b9f..5769ac487 100644 --- a/mods/MAPGEN/mcl_structures/end_spawn.lua +++ b/mods/MAPGEN/mcl_structures/end_spawn.lua @@ -107,8 +107,8 @@ mcl_structures.register_structure("end_spike",{ place_func = function(pos,def,pr) local d = pr:next(6,12) local h = d * pr:next(4,6) - local p1 = vector.add(pos,-d/2,0,-d/2) - local p2 = vector.add(pos,d/2,h+d,d/2) + local p1 = vector.offset(pos, -d / 2, 0, -d / 2) + local p2 = vector.offset(pos, d / 2, h + d, d / 2) minetest.emerge_area(p1, p2, function(blockpos, action, calls_remaining, param) if calls_remaining ~= 0 then return end local s = make_endspike(pos,d,h) diff --git a/mods/MAPGEN/mcl_structures/igloo.lua b/mods/MAPGEN/mcl_structures/igloo.lua index 49e3c879a..0fd8c6217 100644 --- a/mods/MAPGEN/mcl_structures/igloo.lua +++ b/mods/MAPGEN/mcl_structures/igloo.lua @@ -3,28 +3,44 @@ local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) function mcl_structures.generate_igloo_top(pos, pr) - -- FIXME: This spawns bookshelf instead of furnace. Fix this! - -- Furnace does ot work atm because apparently meta is not set. :-( + -- Furnace does ot work atm because apparently meta is not set. Need a bit of help with fixing this for furnaces, bookshelves, and brewing stands. local newpos = {x=pos.x,y=pos.y-2,z=pos.z} local path = modpath.."/schematics/mcl_structures_igloo_top.mts" local rotation = tostring(pr:next(0,3)*90) - return mcl_structures.place_schematic(newpos, path, rotation, nil, true), rotation + return mcl_structures.place_schematic(newpos, path, rotation, nil, true, nil, function() + local p1 = vector.offset(pos,-5,-5,-5) + local p2 = vector.offset(pos,5,5,5) + mcl_structures.construct_nodes(p1,p2,{"mcl_furnaces:furnace","mcl_books:bookshelf"}) + end), rotation +end + +local function spawn_mobs(p1,p2,vi,zv) + local mc = minetest.find_nodes_in_area_under_air(p1,p2,{"mcl_core:stonebrickmossy"}) + if #mc == 2 then + local vp = mc[1] + local zp = mc[2] + if not vi and zv and zv:get_pos() and vector.distance(mc[1],zv:get_pos()) < 2 then + vp = mc[2] + elseif not zv and vi and vi:get_pos() and vector.distance(mc[2],vi:get_pos()) < 2 then + zp = mc[1] + elseif zv and vi then + return + end + vi = minetest.add_entity(vector.offset(mc[1],0,1,0),"mobs_mc:villager") + zv = minetest.add_entity(vector.offset(mc[2],0,1,0),"mobs_mc:villager_zombie") + minetest.after(1,spawn_mobs,p1,p2,vi,zv) + end end function mcl_structures.generate_igloo_basement(pos, orientation, loot, pr) - -- TODO: Add brewing stand -- TODO: Add monster eggs local path = modpath.."/schematics/mcl_structures_igloo_basement.mts" mcl_structures.place_schematic(pos, path, orientation, nil, true, nil, function() local p1 = vector.offset(pos,-5,-5,-5) local p2 = vector.offset(pos,5,5,5) mcl_structures.fill_chests(p1,p2,loot,pr) - local mc = minetest.find_nodes_in_area_under_air(p1,p2,{"mcl_core:stonebrickmossy"}) - if #mc == 2 then - table.shuffle(mc) - minetest.add_entity(vector.offset(mc[1],0,1,0),"mobs_mc:villager") - minetest.add_entity(vector.offset(mc[2],0,1,0),"mobs_mc:villager_zombie") - end + mcl_structures.construct_nodes(p1,p2,{"mcl_brewing:stand_000","mcl_books:bookshelf"}) + spawn_mobs(p1,p2) end, pr) end @@ -58,19 +74,19 @@ function mcl_structures.generate_igloo(pos, def, pr) if rotation == "0" then dir = {x=-1, y=0, z=0} tdir = {x=1, y=0, z=0} - tpos = {x=pos.x+7, y=pos.y-1, z=pos.z+3} + tpos = {x=pos.x+7, y=pos.y-2, z=pos.z+3} elseif rotation == "90" then dir = {x=0, y=0, z=-1} tdir = {x=0, y=0, z=-1} - tpos = {x=pos.x+3, y=pos.y-1, z=pos.z+1} + tpos = {x=pos.x+3, y=pos.y-2, z=pos.z+1} elseif rotation == "180" then dir = {x=1, y=0, z=0} tdir = {x=-1, y=0, z=0} - tpos = {x=pos.x+1, y=pos.y-1, z=pos.z+3} + tpos = {x=pos.x+1, y=pos.y-2, z=pos.z+3} elseif rotation == "270" then dir = {x=0, y=0, z=1} tdir = {x=0, y=0, z=1} - tpos = {x=pos.x+3, y=pos.y-1, z=pos.z+7} + tpos = {x=pos.x+3, y=pos.y-2, z=pos.z+7} else return success end @@ -139,7 +155,7 @@ mcl_structures.register_structure("igloo",{ biomes = { "ColdTaiga", "IcePlainsSpikes", "IcePlains" }, place_func = mcl_structures.generate_igloo, loot = { - ["mcl_chests:chest"] = {{ + ["mcl_chests:chest_small"] = {{ stacks_min = 1, stacks_max = 1, items = { @@ -157,6 +173,7 @@ mcl_structures.register_structure("igloo",{ { itemstring = "mcl_mobitems:rotten_flesh", weight = 10 }, { itemstring = "mcl_tools:axe_stone", weight = 2 }, { itemstring = "mcl_core:emerald", weight = 1 }, + { itemstring = "mcl_core:apple_gold", weight = 1 }, } }}, } diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index f57fa34f4..cd5691fca 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -4,216 +4,6 @@ local modpath = minetest.get_modpath(modname) mcl_structures = {} -local rotations = { - "0", - "90", - "180", - "270" -} - -local replacement = { - ["mcl_farming:pumpkintige_linked_t"] = "mcl_farming:pumpkintige_unconnect", - ["mcl_farming:melontige_linked_t"] = "mcl_farming:melontige_unconnect" -} - -local function ecb_place(blockpos, action, calls_remaining, param) - if calls_remaining >= 1 then return end - minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags) - if param.after_placement_callback and param.p1 and param.p2 then - param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param) - end -end - -function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param) - local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")() - if s and s.size then - local x, z = s.size.x, s.size.z - if rotation then - if rotation == "random" and pr then - rotation = rotations[pr:next(1,#rotations)] - end - if rotation == "random" then - x = math.max(x, z) - z = x - elseif rotation == "90" or rotation == "270" then - x, z = z, x - end - end - local p1 = {x=pos.x , y=pos.y , z=pos.z } - local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1} - minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) - local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacement, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param} - minetest.emerge_area(p1, p2, ecb_place, param) - return true - end -end - -function mcl_structures.get_struct(file) - local localfile = modpath.."/schematics/"..file - local file, errorload = io.open(localfile, "rb") - if errorload then - minetest.log("error", "[mcl_structures] Could not open this struct: "..localfile) - return nil - end - - local allnode = file:read("*a") - file:close() - - return allnode -end - --- Call on_construct on pos. --- Useful to init chests from formspec. -local function init_node_construct(pos) - local node = minetest.get_node(pos) - local def = minetest.registered_nodes[node.name] - if def and def.on_construct then - def.on_construct(pos) - return true - end - return false -end -mcl_structures.init_node_construct = init_node_construct - --- The call of Struct -function mcl_structures.call_struct(pos, struct_style, rotation, pr) - minetest.log("action","[mcl_structures] call_struct " .. struct_style.." at "..minetest.pos_to_string(pos)) - if not rotation then - rotation = "random" - end - if struct_style == "end_portal_shrine" then - return mcl_structures.generate_end_portal_shrine(pos, rotation, pr) - end -end - -local function shrine_placement_callback(p1, p2, size, rotation, pr) - -- Find and setup spawner with silverfish - local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") - for s=1, #spawners do - --local meta = minetest.get_meta(spawners[s]) - mcl_mobspawners.setup_spawner(spawners[s], "mobs_mc:silverfish") - end - - -- Shuffle stone brick types - local bricks = minetest.find_nodes_in_area(p1, p2, "mcl_core:stonebrick") - for b=1, #bricks do - local r_bricktype = pr:next(1, 100) - local r_infested = pr:next(1, 100) - local bricktype - if r_infested <= 5 then - if r_bricktype <= 30 then -- 30% - bricktype = "mcl_monster_eggs:monster_egg_stonebrickmossy" - elseif r_bricktype <= 50 then -- 20% - bricktype = "mcl_monster_eggs:monster_egg_stonebrickcracked" - else -- 50% - bricktype = "mcl_monster_eggs:monster_egg_stonebrick" - end - else - if r_bricktype <= 30 then -- 30% - bricktype = "mcl_core:stonebrickmossy" - elseif r_bricktype <= 50 then -- 20% - bricktype = "mcl_core:stonebrickcracked" - end - -- 50% stonebrick (no change necessary) - end - if bricktype then - minetest.set_node(bricks[b], { name = bricktype }) - end - end - - -- Also replace stairs - local stairs = minetest.find_nodes_in_area(p1, p2, {"mcl_stairs:stair_stonebrick", "mcl_stairs:stair_stonebrick_outer", "mcl_stairs:stair_stonebrick_inner"}) - for s=1, #stairs do - local stair = minetest.get_node(stairs[s]) - local r_type = pr:next(1, 100) - if r_type <= 30 then -- 30% mossy - if stair.name == "mcl_stairs:stair_stonebrick" then - stair.name = "mcl_stairs:stair_stonebrickmossy" - elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then - stair.name = "mcl_stairs:stair_stonebrickmossy_outer" - elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then - stair.name = "mcl_stairs:stair_stonebrickmossy_inner" - end - minetest.set_node(stairs[s], stair) - elseif r_type <= 50 then -- 20% cracky - if stair.name == "mcl_stairs:stair_stonebrick" then - stair.name = "mcl_stairs:stair_stonebrickcracked" - elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then - stair.name = "mcl_stairs:stair_stonebrickcracked_outer" - elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then - stair.name = "mcl_stairs:stair_stonebrickcracked_inner" - end - minetest.set_node(stairs[s], stair) - end - -- 50% no change - end - - -- Randomly add ender eyes into end portal frames, but never fill the entire frame - local frames = minetest.find_nodes_in_area(p1, p2, "mcl_portals:end_portal_frame") - local eyes = 0 - for f=1, #frames do - local r_eye = pr:next(1, 10) - if r_eye == 1 then - eyes = eyes + 1 - if eyes < #frames then - local frame_node = minetest.get_node(frames[f]) - frame_node.name = "mcl_portals:end_portal_frame_eye" - minetest.set_node(frames[f], frame_node) - end - end - end -end - -function mcl_structures.generate_end_portal_shrine(pos, rotation, pr) - local offset = {x=6, y=4, z=6} - --local size = {x=13, y=8, z=13} - local newpos = { x = pos.x - offset.x, y = pos.y, z = pos.z - offset.z } - - local path = modpath.."/schematics/mcl_structures_end_portal_room_simple.mts" - mcl_structures.place_schematic(newpos, path, rotation or "0", nil, true, nil, shrine_placement_callback, pr) -end - -local structure_data = {} - ---[[ Returns a table of structure of the specified type. -Currently the only valid parameter is "stronghold". -Format of return value: -{ - { pos = , generated= }, -- first structure - { pos = , generated= }, -- second structure - -- and so on -} - -TODO: Implement this function for all other structure types as well. -]] -function mcl_structures.get_structure_data(structure_type) - if structure_data[structure_type] then - return table.copy(structure_data[structure_type]) - else - return {} - end -end - --- Register a structures table for the given type. The table format is the same as for --- mcl_structures.get_structure_data. -function mcl_structures.register_structure_data(structure_type, structures) - structure_data[structure_type] = structures -end - -local function dir_to_rotation(dir) - local ax, az = math.abs(dir.x), math.abs(dir.z) - if ax > az then - if dir.x < 0 then - return "270" - end - return "90" - end - if dir.z < 0 then - return "180" - end - return "0" -end - dofile(modpath.."/api.lua") dofile(modpath.."/shipwrecks.lua") dofile(modpath.."/desert_temple.lua") @@ -276,21 +66,32 @@ mcl_structures.register_structure("boulder",{ -- small boulder 3x as likely }, },true) --is spawned as a normal decoration. this is just for /spawnstruct + mcl_structures.register_structure("ice_spike_small",{ - filenames = { - modpath.."/schematics/mcl_structures_ice_spike_small.mts" - }, + filenames = { modpath.."/schematics/mcl_structures_ice_spike_small.mts" }, },true) --is spawned as a normal decoration. this is just for /spawnstruct mcl_structures.register_structure("ice_spike_large",{ sidelen = 6, - filenames = { - modpath.."/schematics/mcl_structures_ice_spike_large.mts" - }, + filenames = { modpath.."/schematics/mcl_structures_ice_spike_large.mts" }, },true) --is spawned as a normal decoration. this is just for /spawnstruct -- Debug command +local function dir_to_rotation(dir) + local ax, az = math.abs(dir.x), math.abs(dir.z) + if ax > az then + if dir.x < 0 then + return "270" + end + return "90" + end + if dir.z < 0 then + return "180" + end + return "0" +end + minetest.register_chatcommand("spawnstruct", { - params = "end_portal_shrine | dungeon", + params = "dungeon", description = S("Generate a pre-defined structure near your position."), privs = {debug = true}, func = function(name, param) @@ -304,9 +105,7 @@ minetest.register_chatcommand("spawnstruct", { local pr = PseudoRandom(pos.x+pos.y+pos.z) local errord = false local message = S("Structure placed.") - if param == "end_portal_shrine" then - mcl_structures.generate_end_portal_shrine(pos, rot, pr) - elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then + if param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then mcl_dungeons.spawn_dungeon(pos, rot, pr) elseif param == "" then message = S("Error: No structure type given. Please use “/spawnstruct ”.") @@ -314,7 +113,7 @@ minetest.register_chatcommand("spawnstruct", { else for n,d in pairs(mcl_structures.registered_structures) do if n == param then - mcl_structures.place_structure(pos,d,pr,math.random()) + mcl_structures.place_structure(pos,d,pr,math.random(),rot) return true,message end end diff --git a/mods/MAPGEN/mcl_structures/pillager_outpost.lua b/mods/MAPGEN/mcl_structures/pillager_outpost.lua index fe1db5ce3..719672044 100644 --- a/mods/MAPGEN/mcl_structures/pillager_outpost.lua +++ b/mods/MAPGEN/mcl_structures/pillager_outpost.lua @@ -3,19 +3,24 @@ local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false) +local spawnon = {"mcl_core:stripped_oak","mcl_stairs:slab_birchwood_top"} + mcl_structures.register_structure("pillager_outpost",{ place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass","group:sand"}, fill_ratio = 0.01, flags = "place_center_x, place_center_z", solid_ground = true, make_foundation = true, - sidelen = 23, + sidelen = 32, y_offset = 0, chunk_probability = 600, y_max = mcl_vars.mg_overworld_max, y_min = 1, biomes = { "Desert", "Plains", "Savanna", "IcePlains", "Taiga" }, - filenames = { modpath.."/schematics/mcl_structures_pillager_outpost.mts" }, + filenames = { + modpath.."/schematics/mcl_structures_pillager_outpost.mts", + modpath.."/schematics/mcl_structures_pillager_outpost_2.mts" + }, loot = { ["mcl_chests:chest_small" ] ={ { @@ -56,29 +61,32 @@ mcl_structures.register_structure("pillager_outpost",{ }} }, after_place = function(p,def,pr) - local p1 = vector.offset(p,-7,0,-7) - local p2 = vector.offset(p,7,14,7) - local spawnon = {"mcl_core:stripped_oak"} - local sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon) - for _,n in pairs(minetest.find_nodes_in_area(p1,p2,{"group:wall"})) do - local def = minetest.registered_nodes[minetest.get_node(n).name:gsub("_%d+$","")] - if def and def.on_construct then - def.on_construct(n) - end - end - if not peaceful then - if sp and #sp > 0 then - for i=1,5 do - local pos = sp[pr:next(1,#sp)] - if pos then - minetest.add_entity(pos,"mobs_mc:pillager") - end - end - local pos = sp[pr:next(1,#sp)] - if pos then - minetest.add_entity(pos,"mobs_mc:evoker") - end - end - end + local p1 = vector.offset(p,-9,0,-9) + local p2 = vector.offset(p,9,32,9) + mcl_structures.spawn_mobs("mobs_mc:evoker",spawnon,p1,p2,pr,1) + mcl_structures.spawn_mobs("mobs_mc:pillager",spawnon,p1,p2,pr,5) + mcl_structures.spawn_mobs("mobs_mc:parrot",{"mesecons_pressureplates:pressure_plate_stone_off"},p1,p2,pr,3) + mcl_structures.spawn_mobs("mobs_mc:iron_golem",{"mesecons_button:button_stone_off"},p1,p2,pr,1) + mcl_structures.construct_nodes(p1,p2,{"group:wall"}) end }) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:pillager", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 10, + interval = 60, + limit = 9, + spawnon = spawnon, +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:evoker", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 100, + interval = 60, + limit = 4, + spawnon = spawnon, +}) diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_basement.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_basement.mts index c2a774e78..2bc92ae5d 100644 Binary files a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_basement.mts and b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_basement.mts differ diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_top.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_top.mts index e3705236e..5a2a96dea 100644 Binary files a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_top.mts and b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_igloo_top.mts differ diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple.mts new file mode 100644 index 000000000..0a16fa9b2 Binary files /dev/null and b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple.mts differ diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple_2.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple_2.mts new file mode 100644 index 000000000..8a5a6a313 Binary files /dev/null and b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_ocean_temple_2.mts differ diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_pillager_outpost_2.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_pillager_outpost_2.mts new file mode 100644 index 000000000..4a7727acf Binary files /dev/null and b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_pillager_outpost_2.mts differ diff --git a/mods/MAPGEN/mcl_structures/shipwrecks.lua b/mods/MAPGEN/mcl_structures/shipwrecks.lua index a6dbb4981..38f790cb6 100644 --- a/mods/MAPGEN/mcl_structures/shipwrecks.lua +++ b/mods/MAPGEN/mcl_structures/shipwrecks.lua @@ -172,3 +172,92 @@ mcl_structures.register_structure("shipwreck",{ } } }) + +local spawnon = { "mcl_stairs:slab_prismarine_dark"} + +mcl_structures.register_structure("ocean_temple",{ + place_on = {"group:sand","mcl_core:gravel"}, + spawn_by = {"group:water"}, + num_spawn_by = 4, + noise_params = { + offset = 0, + scale = 0.0000122, + spread = {x = 250, y = 250, z = 250}, + seed = 32345, + octaves = 3, + persist = 0.001, + flags = "absvalue", + }, + sidelen = 32, + flags = "force_placement", + biomes = ocean_biomes, + y_max = water_level-4, + y_min = mcl_vars.mg_overworld_min, + filenames = { + modpath .. "/schematics/mcl_structures_ocean_temple.mts", + modpath .. "/schematics/mcl_structures_ocean_temple_2.mts", + }, + y_offset = function(pr) return pr:next(-2,0) end, + after_place = function(p,def,pr) + local p1 = vector.offset(p,-9,0,-9) + local p2 = vector.offset(p,9,32,9) + mcl_structures.spawn_mobs("mobs_mc:guardian",spawnon,p1,p2,pr,5,true) + mcl_structures.spawn_mobs("mobs_mc:guardian_elder",spawnon,p1,p2,pr,1,true) + mcl_structures.construct_nodes(p1,p2,{"group:wall"}) + end, + loot = { + ["mcl_chests:chest_small"] = { + stacks_min = 3, + stacks_max = 10, + items = { + { itemstring = "mcl_sus_stew:stew", weight = 10, amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_core:paper", weight = 8, amount_min = 1, amount_max = 12 }, + { itemstring = "mcl_fishing:fish_raw", weight = 5, amount_min = 8, amount_max = 21 }, + { itemstring = "mcl_fishing:salmon_raw", weight = 7, amount_min = 4, amount_max = 8 }, + { itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 }, + }, + { + stacks_min = 2, + stacks_max = 6, + items = { + { itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2 }, + { itemstring = "mcl_experience:bottle", weight = 5, amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_fishing:fishing_rod", weight = 1, amount_min = 1, amount_max = 1 }, + } + }, + { + stacks_min = 4, + stacks_max = 4, + items = { + --{ itemstring = "FIXME TREASURE MAP", weight = 8, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_books:book", weight = 1, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_clock:clock", weight = 1, amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_compass:compass", weight = 1, amount_min = 1, amount_max = 1 }, + { itemstring = "mcl_maps:empty_map", weight = 1, amount_min = 1, amount_max = 1 }, + } + }, + } + } +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:guardian", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 10, + interval = 60, + limit = 9, + spawnon = spawnon, +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:guardian_elder", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 100, + interval = 60, + limit = 4, + spawnon = spawnon, +}) diff --git a/mods/MAPGEN/mcl_structures/woodland_mansion.lua b/mods/MAPGEN/mcl_structures/woodland_mansion.lua index ca1464fef..c4d494871 100644 --- a/mods/MAPGEN/mcl_structures/woodland_mansion.lua +++ b/mods/MAPGEN/mcl_structures/woodland_mansion.lua @@ -3,6 +3,8 @@ local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false) +local spawnon = {"mcl_deepslate:deepslate","mcl_core:birchwood","mcl_wool:red_carpet","mcl_wool:brown_carpet"} + mcl_structures.register_structure("woodland_cabin",{ place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass"}, fill_ratio = 0.01, @@ -20,28 +22,11 @@ mcl_structures.register_structure("woodland_cabin",{ }, construct_nodes = {"mcl_barrels:barrel_closed"}, after_place = function(p,def,pr) - local spawnon = {"mcl_deepslate:deepslate","mcl_core:birchwood","mcl_wool:red_carpet","mcl_wool:brown_carpet"} local p1=vector.offset(p,-def.sidelen,-1,-def.sidelen) local p2=vector.offset(p,def.sidelen,def.sidelen,def.sidelen) - local sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon) - if not peaceful then - if sp and #sp > 0 then - for i=1,5 do - local pos = sp[pr:next(1,#sp)] - if pos then - minetest.add_entity(pos,"mobs_mc:vindicator") - end - end - local pos = sp[pr:next(1,#sp)] - if pos then - minetest.add_entity(pos,"mobs_mc:evoker") - end - end - end - local parrot = minetest.find_node_near(p,25,{"mcl_heads:wither_skeleton"}) - if parrot then - minetest.add_entity(parrot,"mobs_mc:parrot") - end + mcl_structures.spawn_mobs("mobs_mc:vindicator",spawnon,p1,p2,pr,5) + mcl_structures.spawn_mobs("mobs_mc:evoker",spawnon,p1,p2,pr,1) + mcl_structures.spawn_mobs("mobs_mc:parrot",{"mcl_heads:wither_skeleton"},p1,p2,pr,1) end, loot = { ["mcl_chests:chest_small" ] ={{ @@ -82,3 +67,23 @@ mcl_structures.register_structure("woodland_cabin",{ }} } }) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:vindicator", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 10, + interval = 60, + limit = 6, + spawnon = spawnon, +}) + +mcl_structures.register_structure_spawn({ + name = "mobs_mc:evoker", + y_min = mcl_vars.mg_overworld_min, + y_max = mcl_vars.mg_overworld_max, + chance = 50, + interval = 60, + limit = 6, + spawnon = spawnon, +}) diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index 9f25c5eda..321139c5f 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -11,10 +11,9 @@ Hunger is enabled when damage is enabled. If the damage setting is changed within the game, this does NOT update the hunger mechanic, so the game must be restarted for this to take effect. ]] -if minetest.settings:get_bool("enable_damage") == true then +mcl_hunger.active = false +if minetest.settings:get_bool("enable_damage") == true and minetest.settings:get_bool("mcl_enable_hunger") ~= false then mcl_hunger.active = true -else - mcl_hunger.active = false end mcl_hunger.HUD_TICK = 0.1 diff --git a/mods/PLAYER/mcl_meshhand/init.lua b/mods/PLAYER/mcl_meshhand/init.lua index 96086e4f2..904ffa533 100644 --- a/mods/PLAYER/mcl_meshhand/init.lua +++ b/mods/PLAYER/mcl_meshhand/init.lua @@ -10,7 +10,7 @@ local node_def = { drawtype = "mesh", node_placement_prediction = "", on_construct = function(pos) - local name = get_node(pos).name + local name = minetest.get_node(pos).name local message = "[mcl_meshhand] Trying to construct " .. name .. " at " .. minetest.pos_to_string(pos) minetest.log("error", message) minetest.remove_node(pos) @@ -48,7 +48,7 @@ end if mcl_skins_enabled then -- Change the player's hand to their skin - mcl_skins.register_on_set_skin(function(player) + 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) diff --git a/mods/PLAYER/mcl_meshhand/mod.conf b/mods/PLAYER/mcl_meshhand/mod.conf index 6a988417f..a95edb858 100644 --- a/mods/PLAYER/mcl_meshhand/mod.conf +++ b/mods/PLAYER/mcl_meshhand/mod.conf @@ -1,6 +1,5 @@ name = mcl_meshhand author = jordan4ibanez description = Applies the player skin texture to the hand. -depends = mcl_tools +depends = mcl_tools, mcl_player optional_depends = mcl_skins - diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index ccd5d5e0e..6c521be72 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -1,3 +1,5 @@ +local sf = string.format + -- Minetest 0.4 mod: player -- See README.txt for licensing and other information. mcl_player = {} @@ -53,17 +55,55 @@ local player_model = {} local player_textures = {} local player_anim = {} local player_sneak = {} +local player_visible = {} mcl_player.player_attached = {} function mcl_player.player_get_animation(player) local name = player:get_player_name() + local textures = player_textures[name] + + if not player_visible[name] then + textures = table.copy(textures) + textures[1] = "blank.png" + end + return { model = player_model[name], - textures = player_textures[name], + textures = textures, animation = player_anim[name], + visibility = player_visibility[name] } end +local registered_on_visual_change = {} + +function mcl_player.register_on_visual_change(func) + table.insert(registered_on_visual_change, func) +end + +local function update_player_textures(player) + local name = player:get_player_name() + local textures = player_textures[name] + + if not player_visible[name] then + textures = table.copy(textures) + textures[1] = "blank.png" + end + + player:set_properties({ textures = textures }) + + -- Delay calling the callbacks because mods (including mcl_player) + -- need to fully initialize player data from minetest.register_on_joinplayer + -- before callbacks run + minetest.after(0.1, function() + if player:is_player() then + for i, func in ipairs(registered_on_visual_change) do + func(player) + end + end + end) +end + -- Called when a player's appearance needs to be updated function mcl_player.player_set_model(player, model_name) local name = player:get_player_name() @@ -74,11 +114,11 @@ function mcl_player.player_set_model(player, model_name) end player:set_properties({ mesh = model_name, - textures = player_textures[name] or model.textures, visual = "mesh", visual_size = model.visual_size or {x=1, y=1}, damage_texture_modifier = "^[colorize:red:130", }) + update_player_textures(player) mcl_player.player_set_animation(player, "stand") else player:set_properties({ @@ -89,25 +129,36 @@ function mcl_player.player_set_model(player, model_name) player_model[name] = model_name end -local function set_texture(player, index, texture) - local textures = player_textures[player:get_player_name()] - textures[index] = texture - player:set_properties({textures = textures}) +function mcl_player.player_set_visibility(player, visible) + local name = player:get_player_name() + if player_visible[name] == visible then return end + player_visible[name] = visible + update_player_textures(player) end function mcl_player.player_set_skin(player, texture) - set_texture(player, 1, texture) + local name = player:get_player_name() + player_textures[name][1] = texture + update_player_textures(player) end function mcl_player.player_set_armor(player, texture) - set_texture(player, 2, texture) + local name = player:get_player_name() + player_textures[name][2] = texture + update_player_textures(player) end function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname) local name = player:get_player_name() local model = player_model[name] local anim = models[model].animations[player_anim[name]] - return "model["..x..","..y..";"..w..","..h..";"..fsname..";"..model..";"..table.concat(player_textures[name], ",")..";0,".. 180 ..";false;false;"..anim.x..","..anim.y.."]" + local textures = player_textures[name] + if not player_visible[name] then + textures = table.copy(textures) + textures[1] = "blank.png" + end + return sf("model[%s,%s;%s,%s;%s;%s;%s;0,180;false;false;%s,%s]", x, y, w, h, fsname, model, + table.concat(textures, ","), anim.x, anim.y) end function mcl_player.player_set_animation(player, anim_name, speed) @@ -128,6 +179,7 @@ end minetest.register_on_joinplayer(function(player) local name = player:get_player_name() mcl_player.player_attached[name] = false + player_visible[name] = true mcl_player.player_set_model(player, "character.b3d") player_textures[name] = {"character.png", "blank.png", "blank.png"} --player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30) @@ -139,6 +191,8 @@ minetest.register_on_leaveplayer(function(player) player_model[name] = nil player_anim[name] = nil player_textures[name] = nil + player_sneak[name] = nil + player_visible[name] = nil end) -- Localize for better performance. @@ -180,6 +234,8 @@ minetest.register_globalstep(function(dtime) -- Apply animations based on what the player is doing if player:get_hp() == 0 then player_set_animation(player, "die") + elseif mcl_playerplus.elytra[player] and mcl_playerplus.elytra[player].active then + player_set_animation(player, "stand") elseif walking and velocity.x > 0.35 or walking and velocity.x < -0.35 or walking and velocity.z > 0.35 diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index be95455c9..0faa9c53f 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -3,6 +3,8 @@ mcl_playerplus = { is_pressing_jump = {}, } +local hud_water = {} + local get_connected_players = minetest.get_connected_players local dir_to_yaw = minetest.dir_to_yaw local get_item_group = minetest.get_item_group @@ -25,6 +27,26 @@ local mcl_playerplus_internal = {} local time = 0 local look_pitch = 0 + +local function calculate_water_depth(pos) + for i=1, 50 do + if get_item_group(minetest.get_node(vector.new(pos.x,pos.y+i,pos.z)).name, "water") == 0 then + return i + end + end + return 50 +end + +local function remove_water_hud(player) + if hud_water[player] then + mcl_weather.skycolor.update_sky_color() + for i=1, #hud_water[player] do + player:hud_remove(hud_water[player][i]) + end + hud_water[player] = nil + end +end + local function player_collision(player) local pos = player:get_pos() @@ -121,98 +143,8 @@ end local node_stand, node_stand_below, node_head, node_feet, node_head_top local is_swimming --- This following part is 2 wrapper functions for player:set_bones --- and player:set_properties preventing them from being resent on --- every globalstep when they have not changed. - -local function roundN(n, d) - if type(n) ~= "number" then return n end - local m = 10^d - return math.floor(n * m + 0.5) / m -end - -local function close_enough(a,b) - local rt=true - if type(a) == "table" and type(b) == "table" then - for k,v in pairs(a) do - if roundN(v,2) ~= roundN(b[k],2) then - rt=false - break - end - end - else - rt = roundN(a,2) == roundN(b,2) - end - return rt -end - - - -local function props_changed(props,oldprops) - local changed=false - local p={} - for k,v in pairs(props) do - if not close_enough(v,oldprops[k]) then - p[k]=v - changed=true - end - end - return changed,p -end - ---tests for roundN -local test_round1=15 -local test_round2=15.00199999999 -local test_round3=15.00111111 -local test_round4=15.00999999 - -assert(roundN(test_round1,2)==roundN(test_round1,2)) -assert(roundN(test_round1,2)==roundN(test_round2,2)) -assert(roundN(test_round1,2)==roundN(test_round3,2)) -assert(roundN(test_round1,2)~=roundN(test_round4,2)) - --- tests for close_enough -local test_cb = {-0.35,0,-0.35,0.35,0.8,0.35} --collisionboxes -local test_cb_close = {-0.351213,0,-0.35,0.35,0.8,0.351212} -local test_cb_diff = {-0.35,0,-1.35,0.35,0.8,0.35} - -local test_eh = 1.65 --eye height -local test_eh_close = 1.65123123 -local test_eh_diff = 1.35 - -local test_nt = { r = 225, b = 225, a = 225, g = 225 } --nametag -local test_nt_diff = { r = 225, b = 225, a = 0, g = 225 } - -assert(close_enough(test_cb,test_cb_close)) -assert(not close_enough(test_cb,test_cb_diff)) -assert(close_enough(test_eh,test_eh_close)) -assert(not close_enough(test_eh,test_eh_diff)) -assert(not close_enough(test_nt,test_nt_diff)) --no floats involved here - ---tests for properties_changed -local test_properties_set1={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }} -local test_properties_set2={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 225, g = 225 }} - -local test_p1,_=props_changed(test_properties_set1,test_properties_set1) -local test_p2,_=props_changed(test_properties_set1,test_properties_set2) - -assert(not test_p1) -assert(test_p2) - -local function set_properties_conditional(player,props) - local changed,p=props_changed(props,player:get_properties()) - if changed then - player:set_properties(p) - end -end - -local function set_bone_position_conditional(player,b,p,r) --bone,position,rotation - local oldp,oldr=player:get_bone_position(b) - if vector.equals(vector.round(oldp),vector.round(p)) and vector.equals(vector.round(oldr),vector.round(r)) then - return - end - player:set_bone_position(b,p,r) -end +local set_bone_pos = mcl_util.set_bone_position +local set_properties = mcl_util.set_properties local function get_overall_velocity(vector) local v = math.sqrt(vector.x^2 + vector.y^2 + vector.z^2) @@ -235,6 +167,31 @@ local elytra_vars = { rocket_speed = 5.5, } +local player_props_elytra = { + collisionbox = { -0.35, 0, -0.35, 0.35, 0.8, 0.35 }, + eye_height = 0.5, + nametag_color = { r = 225, b = 225, a = 225, g = 225 } +} +local player_props_riding = { + collisionbox = { -0.312, 0, -0.312, 0.312, 1.8, 0.312 }, + eye_height = 1.5, + nametag_color = { r = 225, b = 225, a = 225, g = 225 } +} +local player_props_sneaking = { + collisionbox = { -0.312, 0, -0.312, 0.312, 1.8, 0.312 }, + eye_height = 1.35, + nametag_color = { r = 225, b = 225, a = 0, g = 225 } +} +local player_props_swimming = { + collisionbox = { -0.312, 0, -0.312, 0.312, 0.8, 0.312 }, + eye_height = 0.5, + nametag_color = { r = 225, b = 225, a = 225, g = 225 } +} +local player_props_normal = { + collisionbox = { -0.312, 0, -0.312, 0.312, 1.8, 0.312 }, + eye_height = 1.5, + nametag_color = { r = 225, b = 225, a = 225, g = 225 } +} minetest.register_globalstep(function(dtime) @@ -286,6 +243,10 @@ minetest.register_globalstep(function(dtime) elytra.speed = 0 end + if not elytra.last_yaw then + elytra.last_yaw = player:get_look_horizontal() + end + local is_just_jumped = control.jump and not mcl_playerplus.is_pressing_jump[name] and not elytra.active mcl_playerplus.is_pressing_jump[name] = control.jump if is_just_jumped and not elytra.active then @@ -294,7 +255,7 @@ minetest.register_globalstep(function(dtime) end elytra.active = player:get_inventory():get_stack("armor", 3):get_name() == "mcl_armor:elytra" - and not player:get_attach() + and not parent and (elytra.active or (is_just_jumped and player_velocity.y < -0)) and ((not minetest.registered_nodes[fly_node].walkable) or fly_node == "ignore") @@ -359,86 +320,123 @@ minetest.register_globalstep(function(dtime) end if wielded_def and wielded_def._mcl_toollike_wield then - set_bone_position_conditional(player,"Wield_Item", vector.new(0,4.7,3.1), vector.new(-90,225,90)) + set_bone_pos(player, "Wield_Item", vector.new(0, 4.7, 3.1), vector.new(-90, 225, 90)) elseif string.find(wielded:get_name(), "mcl_bows:bow") then - set_bone_position_conditional(player,"Wield_Item", vector.new(1,4,0), vector.new(90,130,115)) + set_bone_pos(player, "Wield_Item", vector.new(1, 4, 0), vector.new(90, 130, 115)) elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then - set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.2,1.2), vector.new(0,180,73)) + set_bone_pos(player, "Wield_Item", vector.new(0, 5.2, 1.2), vector.new(0, 180, 73)) elseif string.find(wielded:get_name(), "mcl_bows:crossbow") then - set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.2,1.2), vector.new(0,180,45)) + set_bone_pos(player, "Wield_Item", vector.new(0, 5.2, 1.2), vector.new(0, 180, 45)) elseif wielded_def.inventory_image == "" then - set_bone_position_conditional(player,"Wield_Item", vector.new(0,6,2), vector.new(180,-45,0)) + set_bone_pos(player,"Wield_Item", vector.new(0, 6, 2), vector.new(180, -45, 0)) else - set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.3,2), vector.new(90,0,0)) + set_bone_pos(player, "Wield_Item", vector.new(0, 5.3, 2), vector.new(90, 0, 0)) end -- controls right and left arms pitch when shooting a bow or blocking if mcl_shields.is_blocking(player) == 2 then - set_bone_position_conditional(player, "Arm_Right_Pitch_Control", vector.new(-3, 5.785, 0), vector.new(20, -20, 0)) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, vector.new(20, -20, 0)) elseif mcl_shields.is_blocking(player) == 1 then - set_bone_position_conditional(player, "Arm_Left_Pitch_Control", vector.new(3, 5.785, 0), vector.new(20, 20, 0)) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, vector.new(20, 20, 0)) elseif string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB then - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35)) - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35)) + local right_arm_rot = vector.new(pitch + 90, -30, pitch * -1 * .35) + local left_arm_rot = vector.new(pitch + 90, 43, pitch * .35) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, right_arm_rot) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, left_arm_rot) -- controls right and left arms pitch when holing a loaded crossbow elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35)) - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35)) + local right_arm_rot = vector.new(pitch + 90, -30, pitch * -1 * .35) + local left_arm_rot = vector.new(pitch + 90, 43, pitch * .35) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, right_arm_rot) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, left_arm_rot) -- controls right and left arms pitch when loading a crossbow elseif string.find(wielded:get_name(), "mcl_bows:crossbow_") then - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(45,-20,25)) - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(55,20,-45)) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, vector.new(45, -20, 25)) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, vector.new(55, 20, -45)) -- when punching elseif control.LMB and not parent then - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0)) - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0)) + set_bone_pos(player,"Arm_Right_Pitch_Control", nil, vector.new(pitch, 0, 0)) + set_bone_pos(player,"Arm_Left_Pitch_Control", nil, vector.zero()) -- when holding an item. elseif wielded:get_name() ~= "" then - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(20,0,0)) - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0)) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, vector.new(20, 0, 0)) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, vector.zero()) -- resets arms pitch else - set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0)) - set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0)) + set_bone_pos(player, "Arm_Left_Pitch_Control", nil, vector.zero()) + set_bone_pos(player, "Arm_Right_Pitch_Control", nil, vector.zero()) end if elytra.active then -- set head pitch and yaw when flying - set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity)),player_vel_yaw - yaw,0)) + local head_rot = vector.new(pitch - degrees(dir_to_pitch(player_velocity)) + 50, player_vel_yaw - yaw, 0) + set_bone_pos(player,"Head_Control", nil, head_rot) + -- sets eye height, and nametag color accordingly - set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}) + set_properties(player, player_props_elytra) + -- control body bone when flying - set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new((75-degrees(dir_to_pitch(player_velocity))) , -player_vel_yaw + yaw, 0)) + local body_rot = vector.new((75 - degrees(dir_to_pitch(player_velocity))), -player_vel_yaw + yaw, 0) + set_bone_pos(player, "Body_Control", nil, body_rot) elseif parent then + set_properties(player, player_props_riding) + local parent_yaw = degrees(parent:get_yaw()) - set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}) - set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, -limit_vel_yaw(yaw, parent_yaw) + parent_yaw, 0)) - set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,0,0)) + local head_rot = vector.new(pitch, -limit_vel_yaw(yaw, parent_yaw) + parent_yaw, 0) + set_bone_pos(player, "Head_Control", nil, head_rot) + set_bone_pos(player,"Body_Control", nil, vector.zero()) elseif control.sneak then -- controls head pitch when sneaking - set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, player_vel_yaw - yaw)) + local head_rot = vector.new(pitch, player_vel_yaw - yaw, player_vel_yaw - yaw) + set_bone_pos(player, "Head_Control", nil, head_rot) + -- sets eye height, and nametag color accordingly - set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 0, g = 225 }}) + set_properties(player, player_props_sneaking) + -- sneaking body conrols - set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0)) + set_bone_pos(player, "Body_Control", nil, vector.new(0, -player_vel_yaw + yaw, 0)) elseif get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and is_sprinting(name) == true then -- set head pitch and yaw when swimming is_swimming = true - set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity))+20,player_vel_yaw - yaw,0)) + local head_rot = vector.new(pitch - degrees(dir_to_pitch(player_velocity)) + 20, player_vel_yaw - yaw, 0) + set_bone_pos(player, "Head_Control", nil, head_rot) + -- sets eye height, and nametag color accordingly - set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,0.8,0.312}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}) + set_properties(player, player_props_swimming) + -- control body bone when swimming - set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new((75-degrees(dir_to_pitch(player_velocity))) , -player_vel_yaw + yaw, 0)) + local body_rot = vector.new((75 + degrees(dir_to_pitch(player_velocity))), player_vel_yaw - yaw, 180) + set_bone_pos(player,"Body_Control", nil, body_rot) elseif get_item_group(mcl_playerinfo[name].node_head, "solid") == 0 and get_item_group(mcl_playerinfo[name].node_head_top, "solid") == 0 then -- sets eye height, and nametag color accordingly is_swimming = false - set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}) + set_properties(player, player_props_normal) - set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, 0)) - set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0)) + set_bone_pos(player,"Head_Control", nil, vector.new(pitch, player_vel_yaw - yaw, 0)) + set_bone_pos(player,"Body_Control", nil, vector.new(0, -player_vel_yaw + yaw, 0)) end + if get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 then + if not hud_water[player] or hud_water[player] and calculate_water_depth(player:get_pos()) ~= #hud_water[player] then + remove_water_hud(player) + hud_water[player] = {} + for i=1, calculate_water_depth(player:get_pos()) do + table.insert(hud_water[player], player:hud_add({ + hud_elem_type = "image", + text = "mcl_playerplus_water.png", + position = {x = 0.5, y = 0.5}, + scale = {x = 32, y = 16}, + offset = {x = 0, y = 0}, + z_index = -1002, + })) + end + end + else + remove_water_hud(player) + end + + elytra.last_yaw = player:get_look_horizontal() -- Update jump status immediately since we need this info in real time. -- WARNING: This section is HACKY as hell since it is all just based on heuristics. @@ -682,6 +680,13 @@ minetest.register_on_joinplayer(function(player) jump_cooldown = -1, -- Cooldown timer for jumping, we need this to prevent the jump exhaustion to increase rapidly } mcl_playerplus.elytra[player] = {active = false, rocketing = 0, speed = 0} + + -- Minetest bug: get_bone_position() returns all zeros vectors. + -- Workaround: call set_bone_position() one time first. + player:set_bone_position("Head_Control", vector.new(0, 6.75, 0)) + player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3, 5.785, 0)) + player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3, 5.785, 0)) + player:set_bone_position("Body_Control", vector.new(0, 6.75, 0)) end) -- clear when player leaves @@ -695,9 +700,6 @@ end) -- Don't change HP if the player falls in the water or through End Portal: mcl_damage.register_modifier(function(obj, damage, reason) if reason.type == "fall" then - if minetest.is_creative_enabled(obj:get_player_name()) then - return 0 - end local pos = obj:get_pos() local node = minetest.get_node(pos) local velocity = obj:get_velocity() or obj:get_player_velocity() or {x=0,y=-10,z=0} diff --git a/mods/PLAYER/mcl_playerplus/textures/mcl_playerplus_water.png b/mods/PLAYER/mcl_playerplus/textures/mcl_playerplus_water.png new file mode 100644 index 000000000..0524ce8d6 Binary files /dev/null and b/mods/PLAYER/mcl_playerplus/textures/mcl_playerplus_water.png differ diff --git a/mods/PLAYER/mcl_skins/README.md b/mods/PLAYER/mcl_skins/README.md index a6ad02f30..d05bf9a2e 100644 --- a/mods/PLAYER/mcl_skins/README.md +++ b/mods/PLAYER/mcl_skins/README.md @@ -44,10 +44,6 @@ Can be one of: "arm", "base", "footwear", "eye", "mouth", "bottom", "top", "hair `page_num` The page number to display of there are multiple pages of items. This parameter is optional. Must be a number. If it is not a valid page number the closest page number will be shown. -### `mcl_skins.register_on_set_skin(func)` -Register a function to be called whenever a player skin changes. -The function will be given a player ObjectRef as a parameter. - ### `mcl_skins.get_skin_list()` This function is used by mods that want a list of skins to register nodes that use the player skin as a texture. Returns an array of tables containing information about each skin. diff --git a/mods/PLAYER/mcl_skins/edit_skin.lua b/mods/PLAYER/mcl_skins/edit_skin.lua index eea6e5e87..3ced41d6d 100644 --- a/mods/PLAYER/mcl_skins/edit_skin.lua +++ b/mods/PLAYER/mcl_skins/edit_skin.lua @@ -25,21 +25,21 @@ mcl_skins = { -- Base color is separate to keep the number of junk nodes registered in check base_color = {0xffeeb592, 0xffb47a57, 0xff8d471d}, color = { - 0xff613915, -- 1 Dark brown Steve hair, Alex bottom + 0xff613915, -- 1 Dark brown 0xff97491b, -- 2 Medium brown 0xffb17050, -- 3 Light brown 0xffe2bc7b, -- 4 Beige 0xff706662, -- 5 Gray 0xff151515, -- 6 Black 0xffc21c1c, -- 7 Red - 0xff178c32, -- 8 Green Alex top + 0xff178c32, -- 8 Green 0xffae2ad3, -- 9 Plum 0xffebe8e4, -- 10 White 0xffe3dd26, -- 11 Yellow - 0xff449acc, -- 12 Light blue Steve top - 0xff124d87, -- 13 Dark blue Steve bottom + 0xff449acc, -- 12 Light blue + 0xff124d87, -- 13 Dark blue 0xfffc0eb3, -- 14 Pink - 0xffd0672a, -- 15 Orange Alex hair + 0xffd0672a, -- 15 Orange }, footwear = {}, mouth = {}, @@ -127,12 +127,6 @@ function mcl_skins.update_player_skin(player) end local model = slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d" mcl_player.player_set_model(player, model) - - mcl_inventory.update_inventory_formspec(player) - - for i=1, #mcl_skins.registered_on_set_skins do - mcl_skins.registered_on_set_skins[i](player) - end end -- Load player skin on join @@ -170,12 +164,6 @@ minetest.register_on_leaveplayer(function(player) mcl_skins.players[player] = nil end) -mcl_skins.registered_on_set_skins = {} - -function mcl_skins.register_on_set_skin(func) - table.insert(mcl_skins.registered_on_set_skins, func) -end - function mcl_skins.show_formspec(player, active_tab, page_num) local skin = mcl_skins.players[player] local default = #mcl_skins.simple_skins > 0 and "skin" or "template" @@ -225,7 +213,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "model[10,0.3;3,7;player_mesh;" .. mesh .. ";" .. mcl_skins.compile_skin(skin) .. - ",blank.png,blank.png;0,180;false;true;0,0;0]" + ",blank.png,blank.png;0,180;false;true;0,0]" if active_tab == "skin" then local page_start = (page_num - 1) * 8 - 1 @@ -234,7 +222,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "style_type[button;bgcolor=#00000000]" local skin = table.copy(skin) - skin_id = skin.simple_skins_id or -1 + local skin_id = skin.simple_skins_id or -1 skin.simple_skins_id = nil local skins = table.copy(mcl_skins.simple_skins) @@ -254,7 +242,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "model[" .. x .. "," .. y .. ";1.5,3;player_mesh;" .. mesh .. ";" .. skin.texture .. - ",blank.png,blank.png;0,180;false;true;0,0;0]" + ",blank.png,blank.png;0,180;false;true;0,0]" if skin_id == i then formspec = formspec .. @@ -273,13 +261,13 @@ function mcl_skins.show_formspec(player, active_tab, page_num) formspec = formspec .. "model[4,2;2,3;player_mesh;mcl_armor_character.b3d;" .. mcl_skins.compile_skin(mcl_skins.steve) .. - ",blank.png,blank.png;0,180;false;true;0,0;0]" .. + ",blank.png,blank.png;0,180;false;true;0,0]" .. "button[4,5.2;2,0.8;steve;" .. S("Select") .. "]" .. "model[6.5,2;2,3;player_mesh;mcl_armor_character_female.b3d;" .. mcl_skins.compile_skin(mcl_skins.alex) .. - ",blank.png,blank.png;0,180;false;true;0,0;0]" .. + ",blank.png,blank.png;0,180;false;true;0,0]" .. "button[6.5,5.2;2,0.8;alex;" .. S("Select") .. "]" @@ -322,7 +310,7 @@ function mcl_skins.show_formspec(player, active_tab, page_num) "model[" .. x .. "," .. y .. ";1.5,1.5;" .. mesh .. ";" .. mesh .. ";" .. preview .. - ";" .. rot_x .. "," .. rot_y .. ";false;false;0,0;0]" + ";" .. rot_x .. "," .. rot_y .. ";false;false;0,0]" if skin[active_tab] == texture then formspec = formspec .. @@ -586,16 +574,16 @@ local function init() for _, item in pairs(json) do mcl_skins.register_item(item) end - mcl_skins.steve.base_color = mcl_skins.base_color[1] - mcl_skins.steve.hair_color = mcl_skins.color[1] - mcl_skins.steve.top_color = mcl_skins.color[12] - mcl_skins.steve.bottom_color = mcl_skins.color[13] + mcl_skins.steve.base_color = mcl_skins.base_color[2] + mcl_skins.steve.hair_color = 0xff5d473b + mcl_skins.steve.top_color = 0xff993535 + mcl_skins.steve.bottom_color = 0xff644939 mcl_skins.steve.slim_arms = false mcl_skins.alex.base_color = mcl_skins.base_color[1] - mcl_skins.alex.hair_color = mcl_skins.color[15] - mcl_skins.alex.top_color = mcl_skins.color[8] - mcl_skins.alex.bottom_color = mcl_skins.color[1] + mcl_skins.alex.hair_color = 0xff715d57 + mcl_skins.alex.top_color = 0xff346840 + mcl_skins.alex.bottom_color = 0xff383532 mcl_skins.alex.slim_arms = true end diff --git a/mods/PLAYER/mcl_skins/list.json b/mods/PLAYER/mcl_skins/list.json index 163111a4c..01bb622e5 100644 --- a/mods/PLAYER/mcl_skins/list.json +++ b/mods/PLAYER/mcl_skins/list.json @@ -18,11 +18,13 @@ }, { "type": "eye", - "texture": "mcl_skins_eye_1.png" + "texture": "mcl_skins_eye_1.png", + "alex": true }, { "type": "eye", - "texture": "mcl_skins_eye_2.png" + "texture": "mcl_skins_eye_2.png", + "steve": true }, { "type": "eye", @@ -34,9 +36,7 @@ }, { "type": "eye", - "texture": "mcl_skins_eye_5.png", - "steve": true, - "alex": true + "texture": "mcl_skins_eye_5.png" }, { "type": "eye", @@ -73,21 +73,23 @@ }, { "type": "mouth", - "texture": "mcl_skins_mouth_7.png", - "alex": true + "texture": "mcl_skins_mouth_7.png" }, { - "type": "mouth" + "type": "mouth", + "alex": true }, { "type": "hair", "texture": "mcl_skins_hair_1.png", - "mask": "mcl_skins_hair_1_mask.png" + "mask": "mcl_skins_hair_1_mask.png", + "alex": true }, { "type": "hair", "texture": "mcl_skins_hair_2.png", - "mask": "mcl_skins_hair_2_mask.png" + "mask": "mcl_skins_hair_2_mask.png", + "steve": true }, { "type": "hair", @@ -127,14 +129,12 @@ { "type": "hair", "texture": "mcl_skins_hair_10.png", - "mask": "mcl_skins_hair_10_mask.png", - "steve": true + "mask": "mcl_skins_hair_10_mask.png" }, { "type": "hair", "texture": "mcl_skins_hair_11.png", - "mask": "mcl_skins_hair_11_mask.png", - "alex": true + "mask": "mcl_skins_hair_11_mask.png" }, { "type": "hair" @@ -145,7 +145,8 @@ }, { "type": "headwear", - "texture": "mcl_skins_headwear_2.png" + "texture": "mcl_skins_headwear_2.png", + "alex": true }, { "type": "headwear", @@ -173,13 +174,14 @@ }, { "type": "headwear", - "steve": true, - "alex": true + "steve": true }, { "type": "bottom", "texture": "mcl_skins_bottom_1.png", - "mask": "mcl_skins_bottom_1_mask.png" + "mask": "mcl_skins_bottom_1_mask.png", + "steve": true, + "alex": true }, { "type": "bottom", @@ -194,14 +196,14 @@ { "type": "bottom", "texture": "mcl_skins_bottom_4.png", - "mask": "mcl_skins_bottom_4_mask.png", - "steve": true, - "alex": true + "mask": "mcl_skins_bottom_4_mask.png" }, { "type": "top", "texture": "mcl_skins_top_1.png", - "mask": "mcl_skins_top_1_mask.png" + "mask": "mcl_skins_top_1_mask.png", + "steve": true, + "alex": true }, { "type": "top", @@ -241,14 +243,12 @@ { "type": "top", "texture": "mcl_skins_top_9.png", - "mask": "mcl_skins_top_9_mask.png", - "alex": true + "mask": "mcl_skins_top_9_mask.png" }, { "type": "top", "texture": "mcl_skins_top_10.png", - "mask": "mcl_skins_top_10_mask.png", - "steve": true + "mask": "mcl_skins_top_10_mask.png" }, { "type": "base", diff --git a/mods/PLAYER/mcl_skins/media_credits.txt b/mods/PLAYER/mcl_skins/media_credits.txt index b81058356..cda321d60 100644 --- a/mods/PLAYER/mcl_skins/media_credits.txt +++ b/mods/PLAYER/mcl_skins/media_credits.txt @@ -20,6 +20,7 @@ mcl_skins_top_6.png mcl_skins_bottom_3.png mcl_skins_eye_7.png mcl_skins_mouth_7.png +mcl_skins_hair_10.png Original work by MrRar License: CC BY-SA 4.0 @@ -99,7 +100,6 @@ Source: http://minetest.fensta.bplaced.net/#id=1258 mcl_skins_bottom_4.png mcl_skins_top_9.png mcl_skins_top_10.png -mcl_skins_hair_10.png mcl_skins_hair_11.png Name: Pixel Perfection Legacy 1.19 Author: Nova_Wostra. Adapted for mcl_skins by MrRar. diff --git a/mods/PLAYER/mcl_skins/mod.conf b/mods/PLAYER/mcl_skins/mod.conf index f631b76dc..bd2191097 100644 --- a/mods/PLAYER/mcl_skins/mod.conf +++ b/mods/PLAYER/mcl_skins/mod.conf @@ -1,4 +1,4 @@ name = mcl_skins author = MrRar description = Advanced player skin customization. -depends = mcl_player,mcl_inventory +depends = mcl_player diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1.png index df2397d32..789468518 100644 Binary files a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1.png and b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_1.png differ diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10.png index 72a50f722..962d1aa70 100644 Binary files a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10.png and b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10.png differ diff --git a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10_mask.png b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10_mask.png index 7c8822cf6..775d8cd96 100644 Binary files a/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10_mask.png and b/mods/PLAYER/mcl_skins/textures/mcl_skins_hair_10_mask.png differ diff --git a/mods/PLAYER/mcl_spawn/init.lua b/mods/PLAYER/mcl_spawn/init.lua index 9022dfc25..eb0208dcb 100644 --- a/mods/PLAYER/mcl_spawn/init.lua +++ b/mods/PLAYER/mcl_spawn/init.lua @@ -4,6 +4,10 @@ local S = minetest.get_translator(minetest.get_current_modname()) local mg_name = minetest.get_mapgen_setting("mg_name") local storage = minetest.get_mod_storage() +local function mcl_log (message) + mcl_util.mcl_log (message, "[Spawn]") +end + -- Parameters ------------- @@ -429,6 +433,43 @@ function mcl_spawn.set_spawn_pos(player, pos, message) else local oldpos = minetest.string_to_pos(meta:get_string("mcl_beds:spawn")) meta:set_string("mcl_beds:spawn", minetest.pos_to_string(pos)) + + -- Set player ownership on bed + local bed_node = minetest.get_node(pos) + local bed_meta = minetest.get_meta(pos) + + local bed_bottom = mcl_beds.get_bed_bottom (pos) + local bed_bottom_meta = minetest.get_meta(bed_bottom) + + if bed_meta then + if bed_node then + mcl_log("Bed name: " .. bed_node.name) + end + + mcl_log("Setting bed meta: " .. player:get_player_name()) + bed_meta:set_string("player", player:get_player_name()) + + -- Pass in villager as arg. Shouldn't know about villagers + if bed_bottom_meta then + mcl_log("Removing villager from bed bottom meta") + bed_bottom_meta:set_string("villager", nil) + else + mcl_log("Cannot remove villager from bed bottom meta") + end + + + + if oldpos and oldpos ~= pos then + local old_bed_meta = minetest.get_meta(oldpos) + if old_bed_meta then + mcl_log("Removing old bed meta") + old_bed_meta:set_string("player", "") + end + else + mcl_log("No old bed meta to remove or same as current") + end + end + if oldpos then -- We don't bother sending a message if the new spawn pos is basically the same spawn_changed = vector.distance(pos, oldpos) > 0.1 diff --git a/settingtypes.txt b/settingtypes.txt index 7ab47e36d..25ac943ea 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -42,6 +42,9 @@ mcl_tnt_griefing (TNT destroys blocks) bool true # Comma separated list of disabled structure names mcl_disabled_structures (Disabled structures) string +# Comma separated list of disabled event names +mcl_disabled_events (Disabled events) string + [Players] # If enabled, players respawn at the bed they last lay on instead of normal # spawn. @@ -69,6 +72,16 @@ mcl_craftguide_progressive_mode (Learn crafting recipes progressively) bool true # If disabled, the skin of all players will be character.png mcl_enable_skin_customization (Enable player skin customization) bool true +# How far the player hand can reach +# Default:4.5 +mcl_hand_range (Hand range) float 4.5 1 128 + +# How far the player hand can reach in creative mode (not gamemode-creative) +# Default:10 +mcl_hand_range_creative (Creative mode hand range) float 10 1 128 + +# If enabled the hunger mechanic will be active +mcl_enable_hunger (Hunger mechanic) bool true [Mobs] # If enabled, mobs will spawn naturally. This does not affect @@ -99,6 +112,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 @@ -108,6 +127,14 @@ mcl_mob_cap_animal (Mob cap animals) int 10 0 1024 #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 +#Display mob icons in inventory instead of mc-like spawn eggs +mcl_old_spawn_icons (Old spawn icons instead of eggs) bool false + +# How far from players should mobs stop moving +# Larger values will have a larger performance impact (default:48) +mcl_mob_active_range (Active mob range) int 48 0 256 + + [Audio] # Enable flame sound. flame_sound (Flame sound) bool true @@ -127,6 +154,10 @@ max_bossbars (Maximum Boss bars) int 5 # Default intensity of shadows (default: 0.33) mcl_default_shadow_intensity (Default shadow intensity) float 0.33 0.0 1.0 +# When enabled, when a player holds a bucket, a select box will be shown around liquid nodes. +# Selecting liquid nodes on clients without a cross hair will not work correctly if this setting is disabled. +mcl_buckets_use_select_box (Buckets use select box) bool false + [Experimental] # Whether ice is translucent. If disabled, ice is fully opaque. # @@ -191,6 +222,12 @@ mcl_bookshelf_inventories (Enable bookshelf inventories) bool true # Enable swiftness on enchanted golden apples mcl_enable_fapples (Enable swiftness on enchanted golden apples) bool true +# All tameable mobs listen to the "sit" righclick like dogs +mcl_extended_pet_control (Extended pet control) bool true + +# Enable hamburgers for villagers to follow +mcl_enable_hamburger (Enable Hamburger) bool true + [Debugging] # If enabled, this will show the itemstring of an item in the description. mcl_item_id_debug (Item ID Debug) bool false @@ -203,3 +240,9 @@ mcl_logging_mapgen (Chunk generation logging) bool false # If enabled generated structures will be logged mcl_logging_structures (Structure generation logging) bool true + +#Complete debug logging for mcl_signs events. Use this if you have issues with signs. +mcl_logging_mcl_signs (Complete debug logging for mcl_signs) bool false + +#Debug logging for mcl_events. +mcl_logging_event_api (Debug logging for mcl_events) bool false diff --git a/tools/colors.txt b/tools/colors.txt new file mode 100644 index 000000000..de20aa49a --- /dev/null +++ b/tools/colors.txt @@ -0,0 +1,2240 @@ +## Mcl2 colors.txt file for minetestmapper +## by Ranko Saotome using the tools provided by minetestmapper + +# mcl_amethyst +mcl_amethyst:amethyst_block 143 94 174 +mcl_amethyst:amethyst_cluster 165 121 193 +mcl_amethyst:budding_amethyst_block 138 88 170 +mcl_amethyst:calcite 189 193 207 +mcl_amethyst:large_amethyst_bud 177 136 203 +mcl_amethyst:medium_amethyst_bud 187 148 212 +mcl_amethyst:small_amethyst_bud 181 140 206 +mcl_amethyst:tinted_glass 126 74 160 + +# mcl_anvils +mcl_anvils:anvil 53 53 53 +mcl_anvils:anvil_damage_1 52 52 52 +mcl_anvils:anvil_damage_2 50 50 50 + +# mcl_armor_stand +mcl_armor_stand:armor_stand 115 89 68 + +# mcl_banners +mcl_banners:hanging_banner 102 88 74 +mcl_banners:standing_banner 102 88 74 + +# mcl_barrels +mcl_barrels:barrel_closed 81 63 49 +mcl_barrels:barrel_open 60 46 36 + +# mcl_beacons +mcl_beacons:beacon 116 168 197 + +# mcl_beds +mcl_beds:bed_black_bottom 109 90 78 +mcl_beds:bed_black_top 109 90 78 +mcl_beds:bed_blue_bottom 108 98 107 +mcl_beds:bed_blue_top 108 98 107 +mcl_beds:bed_brown_bottom 121 94 79 +mcl_beds:bed_brown_top 121 94 79 +mcl_beds:bed_cyan_bottom 109 106 102 +mcl_beds:bed_cyan_top 109 106 102 +mcl_beds:bed_green_bottom 109 103 79 +mcl_beds:bed_green_top 109 103 79 +mcl_beds:bed_grey_bottom 119 100 89 +mcl_beds:bed_grey_top 119 100 89 +mcl_beds:bed_light_blue_bottom 118 118 134 +mcl_beds:bed_light_blue_top 118 118 134 +mcl_beds:bed_lime_bottom 122 123 87 +mcl_beds:bed_lime_top 122 123 87 +mcl_beds:bed_magenta_bottom 136 101 112 +mcl_beds:bed_magenta_top 136 101 112 +mcl_beds:bed_orange_bottom 152 107 81 +mcl_beds:bed_orange_top 152 107 81 +mcl_beds:bed_pink_bottom 152 111 106 +mcl_beds:bed_pink_top 152 111 106 +mcl_beds:bed_purple_bottom 119 94 102 +mcl_beds:bed_purple_top 119 94 102 +mcl_beds:bed_red_bottom 136 90 79 +mcl_beds:bed_red_top 136 90 79 +mcl_beds:bed_silver_bottom 137 118 109 +mcl_beds:bed_silver_top 137 118 109 +mcl_beds:bed_white_bottom 170 152 135 +mcl_beds:bed_white_top 170 152 135 +mcl_beds:bed_yellow_bottom 161 134 86 +mcl_beds:bed_yellow_top 161 134 86 +mcl_beds:respawn_anchor 93 75 91 +mcl_beds:respawn_anchor_charged_1 105 75 136 +mcl_beds:respawn_anchor_charged_2 105 75 136 +mcl_beds:respawn_anchor_charged_3 105 75 136 +mcl_beds:respawn_anchor_charged_4 105 75 136 + +# mcl_bells +mcl_bells:bell 207 203 82 + +# mcl_blackstone +mcl_blackstone:basalt 71 71 71 +mcl_blackstone:basalt_polished 80 79 79 +mcl_blackstone:basalt_smooth 88 87 88 +mcl_blackstone:blackstone 33 31 35 +mcl_blackstone:blackstone_brick_polished 42 39 44 +mcl_blackstone:blackstone_chiseled_polished 42 39 44 +mcl_blackstone:blackstone_gilded 33 31 35 +mcl_blackstone:blackstone_polished 44 42 47 +mcl_blackstone:nether_gold 133 52 40 +mcl_blackstone:quartz_brick 190 185 182 +mcl_blackstone:soul_fire 89 169 169 +mcl_blackstone:soul_soil 94 72 54 +mcl_blackstone:soul_torch 98 108 100 +mcl_blackstone:soul_torch_wall 98 108 100 +mcl_blackstone:wall 33 31 35 +mcl_blackstone:wall_0 33 31 35 +mcl_blackstone:wall_1 33 31 35 +mcl_blackstone:wall_10 33 31 35 +mcl_blackstone:wall_11 33 31 35 +mcl_blackstone:wall_12 33 31 35 +mcl_blackstone:wall_13 33 31 35 +mcl_blackstone:wall_14 33 31 35 +mcl_blackstone:wall_15 33 31 35 +mcl_blackstone:wall_16 33 31 35 +mcl_blackstone:wall_2 33 31 35 +mcl_blackstone:wall_21 33 31 35 +mcl_blackstone:wall_3 33 31 35 +mcl_blackstone:wall_4 33 31 35 +mcl_blackstone:wall_5 33 31 35 +mcl_blackstone:wall_6 33 31 35 +mcl_blackstone:wall_7 33 31 35 +mcl_blackstone:wall_8 33 31 35 +mcl_blackstone:wall_9 33 31 35 + +# mcl_blast_furnace +mcl_blast_furnace:blast_furnace 130 120 115 +mcl_blast_furnace:blast_furnace_active 130 120 115 + +# mcl_books +mcl_books:bookshelf 111 86 66 + +# mcl_brewing +mcl_brewing:stand_000 141 134 134 +mcl_brewing:stand_001 141 134 134 +mcl_brewing:stand_010 141 134 134 +mcl_brewing:stand_011 141 134 134 +mcl_brewing:stand_100 141 134 134 +mcl_brewing:stand_101 141 134 134 +mcl_brewing:stand_110 141 134 134 +mcl_brewing:stand_111 141 134 134 + +# mcl_cake +mcl_cake:cake 241 233 231 +mcl_cake:cake_1 241 233 231 +mcl_cake:cake_2 241 233 231 +mcl_cake:cake_3 241 233 231 +mcl_cake:cake_4 241 233 231 +mcl_cake:cake_5 241 233 231 +mcl_cake:cake_6 241 233 231 + +# mcl_campfires +mcl_campfires:campfire 83 69 65 +mcl_campfires:campfire_lit 210 114 39 +mcl_campfires:soul_campfire 83 69 65 +mcl_campfires:soul_campfire_lit 39 189 195 + +# mcl_cartography_table +mcl_cartography_table:cartography_table 127 110 96 + +# mcl_cauldrons +mcl_cauldrons:cauldron 25 25 25 +mcl_cauldrons:cauldron_1 38 98 129 +mcl_cauldrons:cauldron_1_lava 183 54 21 +mcl_cauldrons:cauldron_1r 32 121 138 +mcl_cauldrons:cauldron_2 38 98 129 +mcl_cauldrons:cauldron_2_lava 183 54 21 +mcl_cauldrons:cauldron_2r 32 121 138 +mcl_cauldrons:cauldron_3 38 98 129 +mcl_cauldrons:cauldron_3_lava 183 54 21 +mcl_cauldrons:cauldron_3r 32 121 138 + +# mcl_chests +mcl_chests:black_shulker_box 101 92 87 +mcl_chests:blue_shulker_box 107 109 128 +mcl_chests:brown_shulker_box 110 95 82 +mcl_chests:chest 100 79 62 +mcl_chests:cyan_shulker_box 107 121 130 +mcl_chests:dark_green_shulker_box 107 128 92 +mcl_chests:dark_grey_shulker_box 119 112 113 +mcl_chests:dark_grey_shulker_box_small 0 0 0 +mcl_chests:ender_chest 75 68 62 +mcl_chests:green_shulker_box 120 136 95 +mcl_chests:grey_shulker_box 147 142 145 +mcl_chests:lightblue_shulker_box 124 143 159 +mcl_chests:magenta_shulker_box 148 106 132 +mcl_chests:orange_shulker_box 160 102 80 +mcl_chests:pink_shulker_box 176 131 161 +mcl_chests:red_shulker_box 151 92 83 +mcl_chests:trapped_chest 100 79 62 +mcl_chests:trapped_chest_on 100 79 62 +mcl_chests:violet_shulker_box 142 99 104 +mcl_chests:white_shulker_box 186 183 187 +mcl_chests:yellow_shulker_box 178 132 81 + +# mcl_cocoas +mcl_cocoas:cocoa_3 140 74 54 + +# mcl_colorblocks +mcl_colorblocks:concrete_black 8 10 15 +mcl_colorblocks:concrete_blue 46 48 147 +mcl_colorblocks:concrete_brown 98 60 32 +mcl_colorblocks:concrete_cyan 21 123 140 +mcl_colorblocks:concrete_green 75 94 37 +mcl_colorblocks:concrete_grey 56 59 64 +mcl_colorblocks:concrete_light_blue 37 140 200 +mcl_colorblocks:concrete_lime 96 171 25 +mcl_colorblocks:concrete_magenta 171 49 162 +mcl_colorblocks:concrete_orange 226 101 1 +mcl_colorblocks:concrete_pink 213 103 144 +mcl_colorblocks:concrete_powder_black 23 26 30 +mcl_colorblocks:concrete_powder_blue 72 76 169 +mcl_colorblocks:concrete_powder_brown 128 87 54 +mcl_colorblocks:concrete_powder_cyan 38 150 160 +mcl_colorblocks:concrete_powder_green 104 127 45 +mcl_colorblocks:concrete_powder_grey 91 98 103 +mcl_colorblocks:concrete_powder_light_blue 76 181 212 +mcl_colorblocks:concrete_powder_lime 126 186 42 +mcl_colorblocks:concrete_powder_magenta 196 94 189 +mcl_colorblocks:concrete_powder_orange 227 141 38 +mcl_colorblocks:concrete_powder_pink 224 149 176 +mcl_colorblocks:concrete_powder_purple 138 58 180 +mcl_colorblocks:concrete_powder_red 172 57 52 +mcl_colorblocks:concrete_powder_silver 160 160 155 +mcl_colorblocks:concrete_powder_white 224 225 225 +mcl_colorblocks:concrete_powder_yellow 230 198 54 +mcl_colorblocks:concrete_purple 103 32 159 +mcl_colorblocks:concrete_red 146 34 34 +mcl_colorblocks:concrete_silver 128 129 118 +mcl_colorblocks:concrete_white 208 214 215 +mcl_colorblocks:concrete_yellow 241 177 21 +mcl_colorblocks:glazed_terracotta_black 61 28 28 +mcl_colorblocks:glazed_terracotta_blue 35 83 135 +mcl_colorblocks:glazed_terracotta_brown 116 93 73 +mcl_colorblocks:glazed_terracotta_cyan 117 144 148 +mcl_colorblocks:glazed_terracotta_green 122 141 83 +mcl_colorblocks:glazed_terracotta_grey 96 96 96 +mcl_colorblocks:glazed_terracotta_light_blue 123 174 208 +mcl_colorblocks:glazed_terracotta_lime 160 213 86 +mcl_colorblocks:glazed_terracotta_magenta 210 112 216 +mcl_colorblocks:glazed_terracotta_orange 196 150 102 +mcl_colorblocks:glazed_terracotta_pink 251 145 173 +mcl_colorblocks:glazed_terracotta_purple 118 55 159 +mcl_colorblocks:glazed_terracotta_red 189 72 63 +mcl_colorblocks:glazed_terracotta_silver 150 160 160 +mcl_colorblocks:glazed_terracotta_white 205 217 219 +mcl_colorblocks:glazed_terracotta_yellow 236 205 111 +mcl_colorblocks:hardened_clay 143 104 88 +mcl_colorblocks:hardened_clay_black 70 53 46 +mcl_colorblocks:hardened_clay_blue 68 91 143 +mcl_colorblocks:hardened_clay_brown 96 69 61 +mcl_colorblocks:hardened_clay_cyan 71 108 124 +mcl_colorblocks:hardened_clay_green 75 102 63 +mcl_colorblocks:hardened_clay_grey 110 92 85 +mcl_colorblocks:hardened_clay_light_blue 91 128 171 +mcl_colorblocks:hardened_clay_lime 106 135 73 +mcl_colorblocks:hardened_clay_magenta 150 80 85 +mcl_colorblocks:hardened_clay_orange 157 95 70 +mcl_colorblocks:hardened_clay_pink 164 80 76 +mcl_colorblocks:hardened_clay_purple 82 71 124 +mcl_colorblocks:hardened_clay_red 159 82 67 +mcl_colorblocks:hardened_clay_silver 149 129 117 +mcl_colorblocks:hardened_clay_white 213 197 184 +mcl_colorblocks:hardened_clay_yellow 177 128 51 + +# mcl_comparators +mcl_comparators:comparator_off_comp 116 106 102 +mcl_comparators:comparator_off_sub 116 106 102 +mcl_comparators:comparator_on_comp 118 106 102 +mcl_comparators:comparator_on_sub 118 106 102 + +# mcl_compass +mcl_compass:lodestone 86 76 72 + +# mcl_composters +mcl_composters:composter 143 112 88 +mcl_composters:composter_1 76 76 41 +mcl_composters:composter_2 76 76 41 +mcl_composters:composter_3 76 76 41 +mcl_composters:composter_4 76 76 41 +mcl_composters:composter_5 76 76 41 +mcl_composters:composter_6 76 76 41 +mcl_composters:composter_7 76 76 41 +mcl_composters:composter_ready 124 120 95 + +# mcl_copper +mcl_copper:block 150 78 57 +mcl_copper:block_cut 150 78 58 +mcl_copper:block_exposed 130 94 84 +mcl_copper:block_exposed_cut 132 94 84 +mcl_copper:block_oxidized 90 110 111 +mcl_copper:block_oxidized_cut 91 112 112 +mcl_copper:block_raw 171 91 69 +mcl_copper:block_weathered 104 104 102 +mcl_copper:block_weathered_cut 109 105 102 +mcl_copper:stone_with_copper 131 123 118 + +# mcl_core +mcl_core:acacialeaves 110 88 44 +mcl_core:acaciasapling 111 94 65 +mcl_core:acaciatree 137 89 58 +mcl_core:acaciatree_bark 107 94 77 +mcl_core:acaciawood 153 103 71 +mcl_core:andesite 105 111 107 +mcl_core:andesite_smooth 107 114 110 +mcl_core:bedrock 92 79 68 +mcl_core:birchleaves 27 56 27 +mcl_core:birchsapling 93 114 84 +mcl_core:birchtree 160 137 119 +mcl_core:birchtree_bark 199 190 180 +mcl_core:birchwood 147 116 90 +mcl_core:bone_block 222 203 171 +mcl_core:brick_block 140 92 81 +mcl_core:cactus 90 106 66 +mcl_core:clay 124 124 124 +mcl_core:coalblock 54 51 54 +mcl_core:coarse_dirt 119 94 78 +mcl_core:cobble 114 108 105 +mcl_core:cobweb 203 190 168 +mcl_core:crying_obsidian 26 19 41 +mcl_core:darkleaves 20 69 28 +mcl_core:darksapling 70 98 85 +mcl_core:darktree 87 74 66 +mcl_core:darktree_bark 77 65 58 +mcl_core:darkwood 89 76 63 +mcl_core:deadbush 121 91 70 +mcl_core:diamondblock 98 164 203 +mcl_core:diorite 154 150 148 +mcl_core:diorite_smooth 158 155 153 +mcl_core:dirt 109 84 70 +mcl_core:dirt_with_grass 64 111 26 +mcl_core:dirt_with_grass_snow 221 229 234 +mcl_core:emeraldblock 56 146 49 +mcl_core:frosted_ice_0 141 194 224 +mcl_core:frosted_ice_1 149 199 227 +mcl_core:frosted_ice_2 155 203 229 +mcl_core:frosted_ice_3 168 210 233 +mcl_core:glass 215 224 235 +mcl_core:glass_black 25 25 25 +mcl_core:glass_blue 51 76 178 +mcl_core:glass_brown 102 76 51 +mcl_core:glass_cyan 76 127 153 +mcl_core:glass_gray 76 76 76 +mcl_core:glass_green 102 127 51 +mcl_core:glass_light_blue 102 153 216 +mcl_core:glass_lime 127 204 25 +mcl_core:glass_magenta 178 76 216 +mcl_core:glass_orange 216 127 51 +mcl_core:glass_pink 242 127 165 +mcl_core:glass_purple 127 63 178 +mcl_core:glass_red 153 51 51 +mcl_core:glass_silver 153 153 153 +mcl_core:glass_white 255 255 255 +mcl_core:glass_yellow 229 229 51 +mcl_core:goldblock 196 153 69 +mcl_core:granite 155 122 111 +mcl_core:granite_smooth 151 122 111 +mcl_core:grass_path 148 122 65 +mcl_core:gravel 137 142 140 +mcl_core:ice 146 198 227 +mcl_core:ironblock 164 157 157 +mcl_core:jungleleaves 29 84 30 +mcl_core:junglesapling 66 91 40 +mcl_core:jungletree 132 92 70 +mcl_core:jungletree_bark 90 62 46 +mcl_core:junglewood 114 80 60 +mcl_core:ladder 85 66 51 +mcl_core:lapisblock 58 97 165 +mcl_core:lava_source 255 100 0 +mcl_core:lava_flowing 255 100 0 +mcl_core:leaves 40 80 39 +mcl_core:mossycobble 105 106 97 +mcl_core:mycelium 109 89 118 +mcl_core:mycelium_snow 221 229 234 +mcl_core:obsidian 26 19 41 +mcl_core:packed_ice 166 212 231 +mcl_core:podzol 86 64 43 +mcl_core:podzol_snow 221 229 234 +mcl_core:redsand 225 137 111 +mcl_core:redsandstone 212 126 108 +mcl_core:redsandstonecarved 212 126 108 +mcl_core:redsandstonesmooth 212 126 108 +mcl_core:redsandstonesmooth2 212 126 108 +mcl_core:reeds 107 107 107 +mcl_core:sand 221 171 127 +mcl_core:sandstone 202 155 121 +mcl_core:sandstonecarved 202 155 121 +mcl_core:sandstonesmooth 202 155 121 +mcl_core:sandstonesmooth2 202 155 121 +mcl_core:sapling 66 93 47 +mcl_core:slimeblock 93 157 87 +mcl_core:snow 221 229 234 +mcl_core:snow_2 221 229 234 +mcl_core:snow_3 221 229 234 +mcl_core:snow_4 221 229 234 +mcl_core:snow_5 221 229 234 +mcl_core:snow_6 221 229 234 +mcl_core:snow_7 221 229 234 +mcl_core:snow_8 221 229 234 +mcl_core:snowblock 221 229 234 +mcl_core:spruceleaves 38 75 47 +mcl_core:sprucesapling 59 76 56 +mcl_core:sprucetree 104 75 59 +mcl_core:sprucetree_bark 69 53 45 +mcl_core:sprucewood 82 66 54 +mcl_core:stone 131 123 118 +mcl_core:stone_smooth 128 119 115 +mcl_core:stone_with_coal 114 106 103 +mcl_core:stone_with_diamond 124 128 133 +mcl_core:stone_with_emerald 120 124 108 +mcl_core:stone_with_gold 136 121 107 +mcl_core:stone_with_iron 137 125 119 +mcl_core:stone_with_lapis 116 115 128 +mcl_core:stone_with_redstone 131 101 98 +mcl_core:stone_with_redstone_lit 131 101 98 +mcl_core:stonebrick 122 122 122 +mcl_core:stonebrickcarved 100 92 88 +mcl_core:stonebrickcracked 96 89 85 +mcl_core:stonebrickmossy 86 104 79 +mcl_core:stripped_acacia 157 99 63 +mcl_core:stripped_acacia_bark 151 90 57 +mcl_core:stripped_birch 170 136 108 +mcl_core:stripped_birch_bark 179 144 115 +mcl_core:stripped_dark_oak 92 79 70 +mcl_core:stripped_dark_oak_bark 91 79 70 +mcl_core:stripped_jungle 170 114 84 +mcl_core:stripped_jungle_bark 176 117 86 +mcl_core:stripped_oak 155 117 81 +mcl_core:stripped_oak_bark 162 122 84 +mcl_core:stripped_spruce 109 80 65 +mcl_core:stripped_spruce_bark 109 82 67 +mcl_core:tree 142 108 77 +mcl_core:tree_bark 99 78 59 +mcl_core:vine 21 62 22 +mcl_core:water_source 0 94 184 224 +mcl_core:wood 115 89 68 + +# mcl_crafting_table +mcl_crafting_table:crafting_table 154 123 95 + +# mcl_crimson +mcl_crimson:crimson_door_t_1 119 46 40 +mcl_crimson:crimson_door_t_2 119 46 40 +mcl_crimson:crimson_fence 107 40 48 +mcl_crimson:crimson_fence_gate 107 40 48 +mcl_crimson:crimson_fence_gate_open 107 40 48 +mcl_crimson:crimson_fungus 153 60 41 +mcl_crimson:crimson_hyphae 176 81 69 +mcl_crimson:crimson_hyphae_bark 100 74 62 +mcl_crimson:crimson_hyphae_wood 119 46 40 +mcl_crimson:crimson_nylium 133 31 35 +mcl_crimson:crimson_roots 129 39 39 +mcl_crimson:crimson_trapdoor 91 40 47 +mcl_crimson:crimson_trapdoor_open 119 46 40 +mcl_crimson:nether_sprouts 115 90 156 +mcl_crimson:shroomlight 253 187 125 +mcl_crimson:stripped_crimson_hyphae 177 74 67 +mcl_crimson:stripped_crimson_hyphae_bark 117 40 48 +mcl_crimson:stripped_warped_hyphae 20 94 82 +mcl_crimson:stripped_warped_hyphae_bark 117 40 48 +mcl_crimson:twisting_vines 101 82 133 +mcl_crimson:warped_fungus 128 139 114 +mcl_crimson:warped_hyphae 90 71 121 +mcl_crimson:warped_hyphae_bark 51 44 61 +mcl_crimson:warped_hyphae_wood 78 64 108 +mcl_crimson:warped_nylium 86 72 116 +mcl_crimson:warped_roots 97 79 128 +mcl_crimson:warped_trapdoor 37 60 54 +mcl_crimson:warped_trapdoor_open 78 64 108 +mcl_crimson:warped_wart_block 70 56 97 +mcl_crimson:weeping_vines 145 47 38 + +# mcl_deepslate +mcl_deepslate:deepslate 75 73 73 +mcl_deepslate:deepslate_bricks 64 62 62 +mcl_deepslate:deepslate_bricks_cracked 62 60 60 +mcl_deepslate:deepslate_chiseled 46 45 45 +mcl_deepslate:deepslate_cobbled 80 78 76 +mcl_deepslate:deepslate_polished 69 68 67 +mcl_deepslate:deepslate_tiles 51 50 49 +mcl_deepslate:deepslate_tiles_cracked 49 48 48 +mcl_deepslate:deepslate_with_coal 65 62 61 +mcl_deepslate:deepslate_with_copper 88 72 68 +mcl_deepslate:deepslate_with_diamond 76 105 118 +mcl_deepslate:deepslate_with_emerald 66 88 73 +mcl_deepslate:deepslate_with_gold 98 84 66 +mcl_deepslate:deepslate_with_iron 98 91 86 +mcl_deepslate:deepslate_with_lapis 67 77 100 +mcl_deepslate:deepslate_with_redstone 97 63 62 +mcl_deepslate:deepslate_with_redstone_lit 97 63 62 +mcl_deepslate:deepslatebrickswall 64 62 62 +mcl_deepslate:deepslatebrickswall_0 64 62 62 +mcl_deepslate:deepslatebrickswall_1 64 62 62 +mcl_deepslate:deepslatebrickswall_10 64 62 62 +mcl_deepslate:deepslatebrickswall_11 64 62 62 +mcl_deepslate:deepslatebrickswall_12 64 62 62 +mcl_deepslate:deepslatebrickswall_13 64 62 62 +mcl_deepslate:deepslatebrickswall_14 64 62 62 +mcl_deepslate:deepslatebrickswall_15 64 62 62 +mcl_deepslate:deepslatebrickswall_16 64 62 62 +mcl_deepslate:deepslatebrickswall_2 64 62 62 +mcl_deepslate:deepslatebrickswall_21 64 62 62 +mcl_deepslate:deepslatebrickswall_3 64 62 62 +mcl_deepslate:deepslatebrickswall_4 64 62 62 +mcl_deepslate:deepslatebrickswall_5 64 62 62 +mcl_deepslate:deepslatebrickswall_6 64 62 62 +mcl_deepslate:deepslatebrickswall_7 64 62 62 +mcl_deepslate:deepslatebrickswall_8 64 62 62 +mcl_deepslate:deepslatebrickswall_9 64 62 62 +mcl_deepslate:deepslatecobbledwall 80 78 76 +mcl_deepslate:deepslatecobbledwall_0 80 78 76 +mcl_deepslate:deepslatecobbledwall_1 80 78 76 +mcl_deepslate:deepslatecobbledwall_10 80 78 76 +mcl_deepslate:deepslatecobbledwall_11 80 78 76 +mcl_deepslate:deepslatecobbledwall_12 80 78 76 +mcl_deepslate:deepslatecobbledwall_13 80 78 76 +mcl_deepslate:deepslatecobbledwall_14 80 78 76 +mcl_deepslate:deepslatecobbledwall_15 80 78 76 +mcl_deepslate:deepslatecobbledwall_16 80 78 76 +mcl_deepslate:deepslatecobbledwall_2 80 78 76 +mcl_deepslate:deepslatecobbledwall_21 80 78 76 +mcl_deepslate:deepslatecobbledwall_3 80 78 76 +mcl_deepslate:deepslatecobbledwall_4 80 78 76 +mcl_deepslate:deepslatecobbledwall_5 80 78 76 +mcl_deepslate:deepslatecobbledwall_6 80 78 76 +mcl_deepslate:deepslatecobbledwall_7 80 78 76 +mcl_deepslate:deepslatecobbledwall_8 80 78 76 +mcl_deepslate:deepslatecobbledwall_9 80 78 76 +mcl_deepslate:deepslatepolishedwall 69 68 67 +mcl_deepslate:deepslatepolishedwall_0 69 68 67 +mcl_deepslate:deepslatepolishedwall_1 69 68 67 +mcl_deepslate:deepslatepolishedwall_10 69 68 67 +mcl_deepslate:deepslatepolishedwall_11 69 68 67 +mcl_deepslate:deepslatepolishedwall_12 69 68 67 +mcl_deepslate:deepslatepolishedwall_13 69 68 67 +mcl_deepslate:deepslatepolishedwall_14 69 68 67 +mcl_deepslate:deepslatepolishedwall_15 69 68 67 +mcl_deepslate:deepslatepolishedwall_16 69 68 67 +mcl_deepslate:deepslatepolishedwall_2 69 68 67 +mcl_deepslate:deepslatepolishedwall_21 69 68 67 +mcl_deepslate:deepslatepolishedwall_3 69 68 67 +mcl_deepslate:deepslatepolishedwall_4 69 68 67 +mcl_deepslate:deepslatepolishedwall_5 69 68 67 +mcl_deepslate:deepslatepolishedwall_6 69 68 67 +mcl_deepslate:deepslatepolishedwall_7 69 68 67 +mcl_deepslate:deepslatepolishedwall_8 69 68 67 +mcl_deepslate:deepslatepolishedwall_9 69 68 67 +mcl_deepslate:deepslatetileswall 51 50 49 +mcl_deepslate:deepslatetileswall_0 51 50 49 +mcl_deepslate:deepslatetileswall_1 51 50 49 +mcl_deepslate:deepslatetileswall_10 51 50 49 +mcl_deepslate:deepslatetileswall_11 51 50 49 +mcl_deepslate:deepslatetileswall_12 51 50 49 +mcl_deepslate:deepslatetileswall_13 51 50 49 +mcl_deepslate:deepslatetileswall_14 51 50 49 +mcl_deepslate:deepslatetileswall_15 51 50 49 +mcl_deepslate:deepslatetileswall_16 51 50 49 +mcl_deepslate:deepslatetileswall_2 51 50 49 +mcl_deepslate:deepslatetileswall_21 51 50 49 +mcl_deepslate:deepslatetileswall_3 51 50 49 +mcl_deepslate:deepslatetileswall_4 51 50 49 +mcl_deepslate:deepslatetileswall_5 51 50 49 +mcl_deepslate:deepslatetileswall_6 51 50 49 +mcl_deepslate:deepslatetileswall_7 51 50 49 +mcl_deepslate:deepslatetileswall_8 51 50 49 +mcl_deepslate:deepslatetileswall_9 51 50 49 +mcl_deepslate:infested_deepslate 75 73 73 +mcl_deepslate:tuff 99 82 70 + +# mcl_dispensers +mcl_dispensers:dispenser 149 139 133 +mcl_dispensers:dispenser_down 149 139 133 +mcl_dispensers:dispenser_up 123 113 108 + +# mcl_doors +mcl_doors:acacia_door_t_1 134 81 53 +mcl_doors:acacia_door_t_2 134 81 53 +mcl_doors:acacia_trapdoor 150 100 69 +mcl_doors:acacia_trapdoor_open 156 105 73 +mcl_doors:birch_door_t_1 154 121 94 +mcl_doors:birch_door_t_2 154 121 94 +mcl_doors:birch_trapdoor 180 163 146 +mcl_doors:birch_trapdoor_open 147 116 90 +mcl_doors:dark_oak_door_t_1 103 90 76 +mcl_doors:dark_oak_door_t_2 103 90 76 +mcl_doors:dark_oak_trapdoor 82 70 58 +mcl_doors:dark_oak_trapdoor_open 86 73 61 +mcl_doors:iron_door_t_1 157 151 150 +mcl_doors:iron_door_t_2 157 151 150 +mcl_doors:iron_trapdoor 151 143 143 +mcl_doors:iron_trapdoor_open 151 142 142 +mcl_doors:jungle_door_t_1 110 76 57 +mcl_doors:jungle_door_t_2 110 76 57 +mcl_doors:jungle_trapdoor 106 73 53 +mcl_doors:jungle_trapdoor_open 122 88 63 +mcl_doors:spruce_door_t_1 93 80 69 +mcl_doors:spruce_door_t_2 93 80 69 +mcl_doors:spruce_trapdoor 73 59 48 +mcl_doors:spruce_trapdoor_open 76 60 49 +mcl_doors:trapdoor 100 76 60 +mcl_doors:trapdoor_open 114 86 67 +mcl_doors:wooden_door_t_1 85 65 52 +mcl_doors:wooden_door_t_2 85 65 52 + +# mcl_droppers +mcl_droppers:dropper 149 139 133 +mcl_droppers:dropper_down 149 139 133 +mcl_droppers:dropper_up 126 115 111 + +# mcl_enchanting +mcl_enchanting:table 97 97 96 + +# mcl_end +mcl_end:chorus_flower 96 100 127 +mcl_end:chorus_flower_dead 83 82 119 +mcl_end:chorus_plant 79 74 115 +mcl_end:dragon_egg 56 36 34 +mcl_end:end_bricks 195 189 123 +mcl_end:end_rod 124 77 97 +mcl_end:end_stone 221 214 131 +mcl_end:purpur_block 161 112 175 +mcl_end:purpur_pillar 160 111 173 + +# mcl_farming +mcl_farming:beetroot 84 109 72 +mcl_farming:beetroot_0 56 122 76 +mcl_farming:beetroot_1 55 119 73 +mcl_farming:beetroot_2 56 120 74 +mcl_farming:carrot 105 106 59 +mcl_farming:carrot_1 76 113 62 +mcl_farming:carrot_2 76 113 62 +mcl_farming:carrot_3 74 109 59 +mcl_farming:carrot_4 74 109 59 +mcl_farming:carrot_5 72 108 58 +mcl_farming:carrot_6 72 108 58 +mcl_farming:carrot_7 72 108 58 +mcl_farming:hay_block 156 119 83 +mcl_farming:melon 59 82 34 +mcl_farming:melontige_unconnect 100 100 100 +mcl_farming:potato 86 111 59 +mcl_farming:potato_1 75 120 65 +mcl_farming:potato_2 75 120 65 +mcl_farming:potato_3 71 115 62 +mcl_farming:potato_4 71 115 62 +mcl_farming:potato_5 74 119 64 +mcl_farming:potato_6 74 119 64 +mcl_farming:potato_7 74 119 64 +mcl_farming:pumpkin 174 90 40 +mcl_farming:pumpkin_face 174 90 40 +mcl_farming:pumpkin_face_light 174 90 40 +mcl_farming:pumpkintige_unconnect 100 100 100 +mcl_farming:soil 103 81 69 +mcl_farming:soil_wet 70 56 47 +mcl_farming:sweet_berry_bush_0 0 111 29 +mcl_farming:sweet_berry_bush_1 0 101 25 +mcl_farming:sweet_berry_bush_2 76 95 24 +mcl_farming:sweet_berry_bush_3 107 87 39 +mcl_farming:wheat 167 120 78 +mcl_farming:wheat_1 55 103 48 +mcl_farming:wheat_2 51 99 46 +mcl_farming:wheat_3 51 98 46 +mcl_farming:wheat_4 67 115 53 +mcl_farming:wheat_5 87 130 66 +mcl_farming:wheat_6 104 144 68 +mcl_farming:wheat_7 148 147 71 + +# mcl_fences +mcl_fences:acacia_fence 153 101 70 +mcl_fences:acacia_fence_gate 153 101 70 +mcl_fences:acacia_fence_gate_open 153 101 70 +mcl_fences:birch_fence 152 120 93 +mcl_fences:birch_fence_gate 152 120 93 +mcl_fences:birch_fence_gate_open 152 120 93 +mcl_fences:dark_oak_fence 85 73 60 +mcl_fences:dark_oak_fence_gate 85 73 60 +mcl_fences:dark_oak_fence_gate_open 85 73 60 +mcl_fences:fence 110 84 65 +mcl_fences:fence_gate 110 84 65 +mcl_fences:fence_gate_open 110 84 65 +mcl_fences:jungle_fence 116 82 61 +mcl_fences:jungle_fence_gate 116 82 61 +mcl_fences:jungle_fence_gate_open 116 82 61 +mcl_fences:nether_brick_fence 50 25 26 +mcl_fences:spruce_fence 85 68 55 +mcl_fences:spruce_fence_gate 85 68 55 +mcl_fences:spruce_fence_gate_open 85 68 55 + +# mcl_fire +mcl_fire:eternal_fire 209 112 39 +mcl_fire:fire 209 112 39 + +# mcl_fletching_table +mcl_fletching_table:fletching_table 174 116 83 + +# mcl_flowerpots +mcl_flowerpots:flower_pot 121 57 48 +mcl_flowerpots:flower_pot_cactus 114 92 57 + +# mcl_flowers +mcl_flowers:allium 130 121 159 +mcl_flowers:azure_bluet 118 124 125 +mcl_flowers:blue_orchid 0 118 191 +mcl_flowers:dandelion 136 120 59 +mcl_flowers:double_fern 142 132 114 +mcl_flowers:double_fern_top 150 139 120 +mcl_flowers:double_grass 0 255 0 +mcl_flowers:double_grass_top 0 255 0 +mcl_flowers:fern 144 134 116 +mcl_flowers:lilac 198 161 207 +mcl_flowers:lilac_top 198 161 207 +mcl_flowers:oxeye_daisy 162 158 139 +mcl_flowers:peony 242 172 185 +mcl_flowers:peony_top 242 172 185 +mcl_flowers:poppy 161 0 14 +mcl_flowers:rose_bush 161 0 14 +mcl_flowers:rose_bush_top 161 0 14 +mcl_flowers:sunflower 247 247 73 +mcl_flowers:sunflower_top 247 247 73 +mcl_flowers:tulip_orange 132 87 55 +mcl_flowers:tulip_pink 242 172 185 +mcl_flowers:tulip_red 161 0 14 +mcl_flowers:tulip_white 255 255 255 +mcl_flowers:waterlily 29 83 29 +mcl_flowers:tallgrass 21 71 52 + +# mcl_furnaces +mcl_furnaces:furnace 149 139 133 +mcl_furnaces:furnace_active 149 139 133 + +# mcl_grindstone +mcl_grindstone:grindstone 216 216 216 + +# mcl_heads +mcl_heads:creeper22_5 94 115 69 +mcl_heads:creeper45 94 115 69 +mcl_heads:creeper67_5 94 115 69 +mcl_heads:skeleton22_5 126 126 126 +mcl_heads:skeleton45 126 126 126 +mcl_heads:skeleton67_5 126 126 126 +mcl_heads:steve22_5 123 87 69 +mcl_heads:steve45 123 87 69 +mcl_heads:steve67_5 123 87 69 +mcl_heads:wither_skeleton22_5 50 50 50 +mcl_heads:wither_skeleton45 50 50 50 +mcl_heads:wither_skeleton67_5 50 50 50 +mcl_heads:zombie22_5 67 105 70 +mcl_heads:zombie45 67 105 70 +mcl_heads:zombie67_5 67 105 70 + +# mcl_hoppers +mcl_hoppers:hopper 50 50 50 +mcl_hoppers:hopper_disabled 50 50 50 +mcl_hoppers:hopper_side 50 50 50 +mcl_hoppers:hopper_side_disabled 50 50 50 + +# mcl_itemframes +mcl_itemframes:glow_item_frame 182 132 79 +mcl_itemframes:item_frame 127 94 66 + +# mcl_jukebox +mcl_jukebox:jukebox 77 60 46 + +# mcl_lanterns +mcl_lanterns:chain 41 41 41 +mcl_lanterns:lantern_ceiling 102 73 51 +mcl_lanterns:lantern_floor 102 73 51 +mcl_lanterns:soul_lantern_ceiling 62 91 92 +mcl_lanterns:soul_lantern_floor 62 91 92 + +# mcl_lightning_rods + +# mcl_loom +mcl_loom:loom 130 121 119 + +# mcl_mangrove +mcl_mangrove:hanging_propagule_1 80 100 48 +mcl_mangrove:mangrove_door_t_1 125 61 55 +mcl_mangrove:mangrove_door_t_2 125 61 55 +mcl_mangrove:mangrove_mud_roots 66 61 58 +mcl_mangrove:mangrove_roots 97 75 49 +mcl_mangrove:mangrove_stripped_bark 141 68 57 +mcl_mangrove:mangrove_stripped_trunk 127 62 56 +mcl_mangrove:mangrove_trapdoor 123 60 55 +mcl_mangrove:mangrove_trapdoor_open 125 61 55 +mcl_mangrove:mangrove_tree 125 66 54 +mcl_mangrove:mangrove_tree_bark 88 68 46 +mcl_mangrove:mangrove_wood 125 61 55 +mcl_mangrove:mangrove_wood_fence 125 61 55 +mcl_mangrove:mangrove_wood_fence_gate 125 61 55 +mcl_mangrove:mangrove_wood_fence_gate_open 125 61 55 +mcl_mangrove:mangroveleaves 34 50 14 +mcl_mangrove:propagule 71 114 46 +mcl_mangrove:propagule_clay 124 124 124 +mcl_mangrove:propagule_coarse_dirt 119 94 78 +mcl_mangrove:propagule_dirt 109 84 70 +mcl_mangrove:propagule_mud 66 61 58 +mcl_mangrove:river_water_logged_roots 32 121 138 +mcl_mangrove:water_logged_roots 38 98 129 + +# mcl_maps +mcl_maps:filled_map_character_male 123 77 64 +mcl_maps:filled_map_mcl_skins_base_18D471DFF_female 0 0 0 +mcl_maps:filled_map_mcl_skins_base_18D471DFF_male 0 0 0 +mcl_maps:filled_map_mcl_skins_base_1B47A57FF_female 0 0 0 +mcl_maps:filled_map_mcl_skins_base_1B47A57FF_male 0 0 0 +mcl_maps:filled_map_mcl_skins_base_1EEB592FF_female 0 0 0 +mcl_maps:filled_map_mcl_skins_base_1EEB592FF_male 0 0 0 +mcl_maps:filled_map_mcl_skins_character_1_female 106 100 86 + +# mcl_meshhand +mcl_meshhand:character_male 123 77 64 +mcl_meshhand:mcl_skins_base_18D471DFF_female 0 0 0 +mcl_meshhand:mcl_skins_base_18D471DFF_male 0 0 0 +mcl_meshhand:mcl_skins_base_1B47A57FF_female 0 0 0 +mcl_meshhand:mcl_skins_base_1B47A57FF_male 0 0 0 +mcl_meshhand:mcl_skins_base_1EEB592FF_female 0 0 0 +mcl_meshhand:mcl_skins_base_1EEB592FF_male 0 0 0 +mcl_meshhand:mcl_skins_character_1_female 106 100 86 + +# mcl_minecarts +mcl_minecarts:activator_rail 87 70 59 +mcl_minecarts:activator_rail_on 95 69 59 +mcl_minecarts:detector_rail 94 81 73 +mcl_minecarts:detector_rail_on 96 81 73 +mcl_minecarts:golden_rail 107 88 63 +mcl_minecarts:golden_rail_on 110 88 63 +mcl_minecarts:rail 92 75 63 + +# mcl_mobspawners +mcl_mobspawners:spawner 42 42 42 + +# mcl_monster_eggs +mcl_monster_eggs:monster_egg_cobble 114 108 105 +mcl_monster_eggs:monster_egg_stone 131 123 118 +mcl_monster_eggs:monster_egg_stonebrick 99 91 88 +mcl_monster_eggs:monster_egg_stonebrickcarved 100 92 88 +mcl_monster_eggs:monster_egg_stonebrickcracked 96 89 85 +mcl_monster_eggs:monster_egg_stonebrickmossy 86 104 79 + +# mcl_mud +mcl_mud:mud 66 61 58 +mcl_mud:mud_bricks 109 96 87 +mcl_mud:packed_mud 102 90 83 + +# mcl_mushrooms +mcl_mushrooms:brown_mushroom_block_cap_000000 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000001 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000010 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000011 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000100 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000101 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000110 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_000111 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001000 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001001 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001010 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001011 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001100 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001101 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001110 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_001111 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010000 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010001 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010010 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010011 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010100 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010101 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010110 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_010111 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011000 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011001 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011010 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011011 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011100 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011101 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011110 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_011111 218 176 137 +mcl_mushrooms:brown_mushroom_block_cap_100000 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100001 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100010 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100011 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100100 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100101 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100110 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_100111 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101000 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101001 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101010 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101011 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101100 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101101 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101110 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_101111 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110000 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110001 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110010 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110011 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110100 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110101 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110110 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_110111 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111000 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111001 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111010 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111011 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111100 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111101 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111110 132 87 69 +mcl_mushrooms:brown_mushroom_block_cap_111111 132 87 69 +mcl_mushrooms:brown_mushroom_block_stem 218 176 137 +mcl_mushrooms:brown_mushroom_block_stem_full 205 184 151 +mcl_mushrooms:mushroom_brown 123 84 61 +mcl_mushrooms:mushroom_red 173 71 66 +mcl_mushrooms:red_mushroom_block_cap_000000 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000001 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000010 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000011 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000100 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000101 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000110 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_000111 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001000 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001001 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001010 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001011 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001100 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001101 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001110 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_001111 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010000 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010001 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010010 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010011 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010100 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010101 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010110 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_010111 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011000 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011001 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011010 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011011 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011100 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011101 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011110 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_011111 218 176 137 +mcl_mushrooms:red_mushroom_block_cap_100000 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100001 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100010 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100011 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100100 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100101 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100110 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_100111 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101000 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101001 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101010 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101011 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101100 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101101 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101110 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_101111 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110000 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110001 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110010 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110011 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110100 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110101 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110110 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_110111 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111000 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111001 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111010 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111011 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111100 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111101 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111110 138 40 26 +mcl_mushrooms:red_mushroom_block_cap_111111 138 40 26 +mcl_mushrooms:red_mushroom_block_stem 218 176 137 +mcl_mushrooms:red_mushroom_block_stem_full 205 184 151 + +# mcl_nether +mcl_nether:ancient_debris 63 57 50 +mcl_nether:glowstone 206 160 102 +mcl_nether:magma 99 35 28 +mcl_nether:nether_brick 49 25 26 +mcl_nether:nether_lava_flowing 180 50 19 +mcl_nether:nether_lava_source 183 54 21 +mcl_nether:nether_wart 129 61 57 +mcl_nether:nether_wart_0 59 42 39 +mcl_nether:nether_wart_1 103 59 56 +mcl_nether:nether_wart_2 103 59 56 +mcl_nether:nether_wart_block 179 79 74 +mcl_nether:netheriteblock 36 34 33 +mcl_nether:netherrack 133 52 40 +mcl_nether:quartz_block 198 191 187 +mcl_nether:quartz_chiseled 198 190 187 +mcl_nether:quartz_ore 137 75 67 +mcl_nether:quartz_pillar 196 188 186 +mcl_nether:quartz_smooth 198 191 187 +mcl_nether:red_nether_brick 72 17 6 +mcl_nether:soul_sand 92 71 52 + +# mcl_observers +mcl_observers:observer_down_off 89 82 79 +mcl_observers:observer_down_on 92 82 79 +mcl_observers:observer_off 142 131 126 +mcl_observers:observer_on 142 131 126 +mcl_observers:observer_up_off 111 91 91 +mcl_observers:observer_up_on 111 91 91 + +# mcl_ocean +mcl_ocean:brain_coral 202 85 149 +mcl_ocean:brain_coral_block 202 85 149 +mcl_ocean:brain_coral_fan 202 85 149 +mcl_ocean:bubble_coral 145 76 196 +mcl_ocean:bubble_coral_block 145 76 196 +mcl_ocean:bubble_coral_fan 145 76 196 +mcl_ocean:dead_brain_coral 131 114 124 +mcl_ocean:dead_brain_coral_block 131 114 124 +mcl_ocean:dead_brain_coral_fan 131 114 124 +mcl_ocean:dead_bubble_coral 115 106 123 +mcl_ocean:dead_bubble_coral_block 115 106 123 +mcl_ocean:dead_bubble_coral_fan 115 106 123 +mcl_ocean:dead_fire_coral 129 103 101 +mcl_ocean:dead_fire_coral_block 129 103 101 +mcl_ocean:dead_fire_coral_fan 129 103 101 +mcl_ocean:dead_horn_coral 154 147 127 +mcl_ocean:dead_horn_coral_block 154 147 127 +mcl_ocean:dead_horn_coral_fan 154 147 127 +mcl_ocean:dead_tube_coral 100 106 129 +mcl_ocean:dead_tube_coral_block 100 106 129 +mcl_ocean:dead_tube_coral_fan 100 106 129 +mcl_ocean:dried_kelp_block 56 71 57 +mcl_ocean:fire_coral 201 75 62 +mcl_ocean:fire_coral_block 201 75 62 +mcl_ocean:fire_coral_fan 201 75 62 +mcl_ocean:horn_coral 232 195 70 +mcl_ocean:horn_coral_block 232 195 70 +mcl_ocean:horn_coral_fan 232 195 70 +mcl_ocean:kelp_dirt 109 84 70 +mcl_ocean:kelp_gravel 115 109 103 +mcl_ocean:kelp_redsand 225 137 111 +mcl_ocean:kelp_sand 221 171 127 +mcl_ocean:prismarine 106 127 123 +mcl_ocean:prismarine_brick 107 116 117 +mcl_ocean:prismarine_dark 77 90 97 +mcl_ocean:sea_lantern 141 152 152 +mcl_ocean:sea_pickle_1_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_1_off_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_2_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_2_off_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_3_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_3_off_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_4_dead_brain_coral_block 131 114 124 +mcl_ocean:sea_pickle_4_off_dead_brain_coral_block 131 114 124 +mcl_ocean:seagrass_dirt 109 84 70 +mcl_ocean:seagrass_gravel 115 109 103 +mcl_ocean:seagrass_redsand 225 137 111 +mcl_ocean:seagrass_sand 221 171 127 +mcl_ocean:tube_coral 58 91 211 +mcl_ocean:tube_coral_block 58 91 211 +mcl_ocean:tube_coral_fan 58 91 211 + +# mcl_portals +mcl_portals:end_portal_frame 101 92 80 +mcl_portals:end_portal_frame_eye 101 92 80 +mcl_portals:portal_end 15 15 15 +mcl_portals:portal_gateway 15 15 15 + +# mcl_potions +mcl_potions:fire_resistance_arrow_box 148 132 127 +mcl_potions:fire_resistance_plus_arrow_box 148 132 127 +mcl_potions:harming_2_arrow_box 148 132 127 +mcl_potions:harming_arrow_box 148 132 127 +mcl_potions:healing_2_arrow_box 148 132 127 +mcl_potions:healing_arrow_box 148 132 127 +mcl_potions:invisibility_arrow_box 148 132 127 +mcl_potions:invisibility_plus_arrow_box 148 132 127 +mcl_potions:leaping_2_arrow_box 148 132 127 +mcl_potions:leaping_arrow_box 148 132 127 +mcl_potions:leaping_plus_arrow_box 148 132 127 +mcl_potions:night_vision_arrow_box 148 132 127 +mcl_potions:night_vision_plus_arrow_box 148 132 127 +mcl_potions:poison_2_arrow_box 148 132 127 +mcl_potions:poison_arrow_box 148 132 127 +mcl_potions:poison_plus_arrow_box 148 132 127 +mcl_potions:regeneration_2_arrow_box 148 132 127 +mcl_potions:regeneration_arrow_box 148 132 127 +mcl_potions:regeneration_plus_arrow_box 148 132 127 +mcl_potions:slowness_2_arrow_box 148 132 127 +mcl_potions:slowness_arrow_box 148 132 127 +mcl_potions:slowness_plus_arrow_box 148 132 127 +mcl_potions:swiftness_2_arrow_box 148 132 127 +mcl_potions:swiftness_arrow_box 148 132 127 +mcl_potions:swiftness_plus_arrow_box 148 132 127 +mcl_potions:water_breathing_arrow_box 148 132 127 +mcl_potions:water_breathing_plus_arrow_box 148 132 127 + +# mcl_raw_ores +mcl_raw_ores:raw_gold_block 210 169 85 +mcl_raw_ores:raw_iron_block 195 175 159 + +# mcl_sculk +mcl_sculk:catalyst 5 19 24 +mcl_sculk:sculk 5 19 24 +mcl_sculk:vein 6 17 24 + +# mcl_signs +mcl_signs:standing_sign 119 93 72 +mcl_signs:standing_sign22_5 119 93 72 +mcl_signs:standing_sign22_5_acaciawood 234 116 121 +mcl_signs:standing_sign22_5_birchwood 255 219 167 +mcl_signs:standing_sign22_5_crimson_hyphae_wood 195 95 81 +mcl_signs:standing_sign22_5_darkwood 133 100 67 +mcl_signs:standing_sign22_5_junglewood 134 98 73 +mcl_signs:standing_sign22_5_mangrove_wood 184 105 61 +mcl_signs:standing_sign22_5_sprucewood 85 62 36 +mcl_signs:standing_sign22_5_warped_hyphae_wood 159 125 207 +mcl_signs:standing_sign45 119 93 72 +mcl_signs:standing_sign45_acaciawood 234 116 121 +mcl_signs:standing_sign45_birchwood 255 219 167 +mcl_signs:standing_sign45_crimson_hyphae_wood 195 95 81 +mcl_signs:standing_sign45_darkwood 133 100 67 +mcl_signs:standing_sign45_junglewood 134 98 73 +mcl_signs:standing_sign45_mangrove_wood 134 105 61 +mcl_signs:standing_sign45_sprucewood 85 62 36 +mcl_signs:standing_sign45_warped_hyphae_wood 159 125 207 +mcl_signs:standing_sign67_5 119 93 72 +mcl_signs:standing_sign67_5_acaciawood 234 116 121 +mcl_signs:standing_sign67_5_birchwood 255 219 167 +mcl_signs:standing_sign67_5_crimson_hyphae_wood 195 95 81 +mcl_signs:standing_sign67_5_darkwood 133 100 67 +mcl_signs:standing_sign67_5_junglewood 134 98 73 +mcl_signs:standing_sign67_5_mangrove_wood 184 105 61 +mcl_signs:standing_sign67_5_sprucewood 85 62 36 +mcl_signs:standing_sign67_5_warped_hyphae_wood 159 125 207 +mcl_signs:standing_sign_acaciawood 234 116 121 +mcl_signs:standing_sign_birchwood 255 219 167 +mcl_signs:standing_sign_crimson_hyphae_wood 195 95 81 +mcl_signs:standing_sign_darkwood 133 100 67 +mcl_signs:standing_sign_junglewood 134 98 73 +mcl_signs:standing_sign_mangrove_wood 119 93 72 +mcl_signs:standing_sign_sprucewood 85 62 36 +mcl_signs:standing_sign_warped_hyphae_wood 159 125 207 +mcl_signs:wall_sign 119 93 72 +mcl_signs:wall_sign_acaciawood 234 116 121 +mcl_signs:wall_sign_birchwood 255 219 255 +mcl_signs:wall_sign_crimson_hyphae_wood 195 95 81 +mcl_signs:wall_sign_darkwood 133 100 67 +mcl_signs:wall_sign_junglewood 134 98 73 +mcl_signs:wall_sign_mangrove_wood 184 105 61 +mcl_signs:wall_sign_sprucewood 85 62 36 +mcl_signs:wall_sign_warped_hyphae_wood 159 125 207 + +# mcl_smithing_table +mcl_smithing_table:table 51 48 45 + +# mcl_smoker +mcl_smoker:smoker 121 110 106 +mcl_smoker:smoker_active 121 110 106 + +# mcl_sponges +mcl_sponges:sponge 211 179 120 +mcl_sponges:sponge_wet 157 136 94 +mcl_sponges:sponge_wet_river_water 158 142 105 + +# mcl_stairs +mcl_stairs:slab_acaciatree_bark 107 94 77 +mcl_stairs:slab_acaciatree_bark_double 107 94 77 +mcl_stairs:slab_acaciatree_bark_top 107 94 77 +mcl_stairs:slab_acaciawood 153 103 71 +mcl_stairs:slab_acaciawood_double 153 103 71 +mcl_stairs:slab_acaciawood_top 153 103 71 +mcl_stairs:slab_andesite 105 111 107 +mcl_stairs:slab_andesite_double 105 111 107 +mcl_stairs:slab_andesite_smooth 107 114 110 +mcl_stairs:slab_andesite_smooth_double 107 114 110 +mcl_stairs:slab_andesite_smooth_top 107 114 110 +mcl_stairs:slab_andesite_top 105 111 107 +mcl_stairs:slab_birchtree_bark 199 190 180 +mcl_stairs:slab_birchtree_bark_double 199 190 180 +mcl_stairs:slab_birchtree_bark_top 199 190 180 +mcl_stairs:slab_birchwood 147 116 90 +mcl_stairs:slab_birchwood_double 147 116 90 +mcl_stairs:slab_birchwood_top 147 116 90 +mcl_stairs:slab_blackstone 33 31 35 +mcl_stairs:slab_blackstone_brick_polished 42 39 44 +mcl_stairs:slab_blackstone_brick_polished_double 42 39 44 +mcl_stairs:slab_blackstone_brick_polished_top 42 39 44 +mcl_stairs:slab_blackstone_chiseled_polished 42 39 44 +mcl_stairs:slab_blackstone_chiseled_polished_double 42 39 44 +mcl_stairs:slab_blackstone_chiseled_polished_top 42 39 44 +mcl_stairs:slab_blackstone_double 33 31 35 +mcl_stairs:slab_blackstone_polished 44 42 47 +mcl_stairs:slab_blackstone_polished_double 44 42 47 +mcl_stairs:slab_blackstone_polished_top 44 42 47 +mcl_stairs:slab_blackstone_top 33 31 35 +mcl_stairs:slab_brick_block 140 92 81 +mcl_stairs:slab_brick_block_double 140 92 81 +mcl_stairs:slab_brick_block_top 140 92 81 +mcl_stairs:slab_cobble 114 108 105 +mcl_stairs:slab_cobble_double 114 108 105 +mcl_stairs:slab_cobble_top 114 108 105 +mcl_stairs:slab_concrete_black 8 10 15 +mcl_stairs:slab_concrete_black_double 8 10 15 +mcl_stairs:slab_concrete_black_top 8 10 15 +mcl_stairs:slab_concrete_blue 46 48 147 +mcl_stairs:slab_concrete_blue_double 46 48 147 +mcl_stairs:slab_concrete_blue_top 46 48 147 +mcl_stairs:slab_concrete_brown 98 60 32 +mcl_stairs:slab_concrete_brown_double 98 60 32 +mcl_stairs:slab_concrete_brown_top 98 60 32 +mcl_stairs:slab_concrete_cyan 21 123 140 +mcl_stairs:slab_concrete_cyan_double 21 123 140 +mcl_stairs:slab_concrete_cyan_top 21 123 140 +mcl_stairs:slab_concrete_green 75 94 37 +mcl_stairs:slab_concrete_green_double 75 94 37 +mcl_stairs:slab_concrete_green_top 75 94 37 +mcl_stairs:slab_concrete_grey 56 59 64 +mcl_stairs:slab_concrete_grey_double 56 59 64 +mcl_stairs:slab_concrete_grey_top 56 59 64 +mcl_stairs:slab_concrete_light_blue 37 140 200 +mcl_stairs:slab_concrete_light_blue_double 37 140 200 +mcl_stairs:slab_concrete_light_blue_top 37 140 200 +mcl_stairs:slab_concrete_lime 96 171 25 +mcl_stairs:slab_concrete_lime_double 96 171 25 +mcl_stairs:slab_concrete_lime_top 96 171 25 +mcl_stairs:slab_concrete_magenta 171 49 162 +mcl_stairs:slab_concrete_magenta_double 171 49 162 +mcl_stairs:slab_concrete_magenta_top 171 49 162 +mcl_stairs:slab_concrete_orange 226 101 1 +mcl_stairs:slab_concrete_orange_double 226 101 1 +mcl_stairs:slab_concrete_orange_top 226 101 1 +mcl_stairs:slab_concrete_pink 213 103 144 +mcl_stairs:slab_concrete_pink_double 213 103 144 +mcl_stairs:slab_concrete_pink_top 213 103 144 +mcl_stairs:slab_concrete_purple 103 32 159 +mcl_stairs:slab_concrete_purple_double 103 32 159 +mcl_stairs:slab_concrete_purple_top 103 32 159 +mcl_stairs:slab_concrete_red 146 34 34 +mcl_stairs:slab_concrete_red_double 146 34 34 +mcl_stairs:slab_concrete_red_top 146 34 34 +mcl_stairs:slab_concrete_silver 128 129 118 +mcl_stairs:slab_concrete_silver_double 128 129 118 +mcl_stairs:slab_concrete_silver_top 128 129 118 +mcl_stairs:slab_concrete_white 208 214 215 +mcl_stairs:slab_concrete_white_double 208 214 215 +mcl_stairs:slab_concrete_white_top 208 214 215 +mcl_stairs:slab_concrete_yellow 241 177 21 +mcl_stairs:slab_concrete_yellow_double 241 177 21 +mcl_stairs:slab_concrete_yellow_top 241 177 21 +mcl_stairs:slab_copper_cut 150 78 58 +mcl_stairs:slab_copper_cut_double 150 78 58 +mcl_stairs:slab_copper_cut_top 150 78 58 +mcl_stairs:slab_copper_exposed_cut 132 94 84 +mcl_stairs:slab_copper_exposed_cut_double 132 94 84 +mcl_stairs:slab_copper_exposed_cut_top 132 94 84 +mcl_stairs:slab_copper_oxidized_cut 91 112 112 +mcl_stairs:slab_copper_oxidized_cut_double 91 112 112 +mcl_stairs:slab_copper_oxidized_cut_top 91 112 112 +mcl_stairs:slab_copper_weathered_cut 109 105 102 +mcl_stairs:slab_copper_weathered_cut_double 109 105 102 +mcl_stairs:slab_copper_weathered_cut_top 109 105 102 +mcl_stairs:slab_crimson_hyphae_wood 119 46 40 +mcl_stairs:slab_crimson_hyphae_wood_double 119 46 40 +mcl_stairs:slab_crimson_hyphae_wood_top 119 46 40 +mcl_stairs:slab_darktree_bark 77 65 58 +mcl_stairs:slab_darktree_bark_double 77 65 58 +mcl_stairs:slab_darktree_bark_top 77 65 58 +mcl_stairs:slab_darkwood 89 76 63 +mcl_stairs:slab_darkwood_double 89 76 63 +mcl_stairs:slab_darkwood_top 89 76 63 +mcl_stairs:slab_deepslate_bricks 64 62 62 +mcl_stairs:slab_deepslate_bricks_double 64 62 62 +mcl_stairs:slab_deepslate_bricks_top 64 62 62 +mcl_stairs:slab_deepslate_cobbled 80 78 76 +mcl_stairs:slab_deepslate_cobbled_double 80 78 76 +mcl_stairs:slab_deepslate_cobbled_top 80 78 76 +mcl_stairs:slab_deepslate_polished 69 68 67 +mcl_stairs:slab_deepslate_polished_double 69 68 67 +mcl_stairs:slab_deepslate_polished_top 69 68 67 +mcl_stairs:slab_deepslate_tiles 51 50 49 +mcl_stairs:slab_deepslate_tiles_double 51 50 49 +mcl_stairs:slab_deepslate_tiles_top 51 50 49 +mcl_stairs:slab_diorite 154 150 148 +mcl_stairs:slab_diorite_double 154 150 148 +mcl_stairs:slab_diorite_smooth 158 155 153 +mcl_stairs:slab_diorite_smooth_double 158 155 153 +mcl_stairs:slab_diorite_smooth_top 158 155 153 +mcl_stairs:slab_diorite_top 154 150 148 +mcl_stairs:slab_end_bricks 195 189 123 +mcl_stairs:slab_end_bricks_double 195 189 123 +mcl_stairs:slab_end_bricks_top 195 189 123 +mcl_stairs:slab_goldblock 196 153 69 +mcl_stairs:slab_goldblock_double 196 153 69 +mcl_stairs:slab_goldblock_top 196 153 69 +mcl_stairs:slab_granite 155 122 111 +mcl_stairs:slab_granite_double 155 122 111 +mcl_stairs:slab_granite_smooth 151 122 111 +mcl_stairs:slab_granite_smooth_double 151 122 111 +mcl_stairs:slab_granite_smooth_top 151 122 111 +mcl_stairs:slab_granite_top 155 122 111 +mcl_stairs:slab_ironblock 164 157 157 +mcl_stairs:slab_ironblock_double 164 157 157 +mcl_stairs:slab_ironblock_top 164 157 157 +mcl_stairs:slab_jungletree_bark 90 62 46 +mcl_stairs:slab_jungletree_bark_double 90 62 46 +mcl_stairs:slab_jungletree_bark_top 90 62 46 +mcl_stairs:slab_junglewood 114 80 60 +mcl_stairs:slab_junglewood_double 114 80 60 +mcl_stairs:slab_junglewood_top 114 80 60 +mcl_stairs:slab_lapisblock 58 97 165 +mcl_stairs:slab_lapisblock_double 58 97 165 +mcl_stairs:slab_lapisblock_top 58 97 165 +mcl_stairs:slab_mangrove_wood 125 61 55 +mcl_stairs:slab_mangrove_wood_double 125 61 55 +mcl_stairs:slab_mangrove_wood_top 125 61 55 +mcl_stairs:slab_mossycobble 105 106 97 +mcl_stairs:slab_mossycobble_double 105 106 97 +mcl_stairs:slab_mossycobble_top 105 106 97 +mcl_stairs:slab_mud_brick 109 96 87 +mcl_stairs:slab_mud_brick_double 109 96 87 +mcl_stairs:slab_mud_brick_top 109 96 87 +mcl_stairs:slab_nether_brick 49 25 26 +mcl_stairs:slab_nether_brick_double 49 25 26 +mcl_stairs:slab_nether_brick_top 49 25 26 +mcl_stairs:slab_prismarine 106 127 123 +mcl_stairs:slab_prismarine_brick 107 116 117 +mcl_stairs:slab_prismarine_brick_double 107 116 117 +mcl_stairs:slab_prismarine_brick_top 107 116 117 +mcl_stairs:slab_prismarine_dark 77 90 97 +mcl_stairs:slab_prismarine_dark_double 77 90 97 +mcl_stairs:slab_prismarine_dark_top 77 90 97 +mcl_stairs:slab_prismarine_double 106 127 123 +mcl_stairs:slab_prismarine_top 106 127 123 +mcl_stairs:slab_purpur_block 161 112 175 +mcl_stairs:slab_purpur_block_double 161 112 175 +mcl_stairs:slab_purpur_block_top 161 112 175 +mcl_stairs:slab_quartz_smooth 198 191 187 +mcl_stairs:slab_quartz_smooth_double 198 191 187 +mcl_stairs:slab_quartz_smooth_top 198 191 187 +mcl_stairs:slab_quartzblock 198 191 187 +mcl_stairs:slab_quartzblock_double 198 191 187 +mcl_stairs:slab_quartzblock_top 198 191 187 +mcl_stairs:slab_red_nether_brick 72 17 6 +mcl_stairs:slab_red_nether_brick_double 72 17 6 +mcl_stairs:slab_red_nether_brick_top 72 17 6 +mcl_stairs:slab_redsandstone 212 126 108 +mcl_stairs:slab_redsandstone_double 212 126 108 +mcl_stairs:slab_redsandstone_top 212 126 108 +mcl_stairs:slab_redsandstonesmooth2 212 126 108 +mcl_stairs:slab_redsandstonesmooth2_double 212 126 108 +mcl_stairs:slab_redsandstonesmooth2_top 212 126 108 +mcl_stairs:slab_sandstone 202 155 121 +mcl_stairs:slab_sandstone_double 202 155 121 +mcl_stairs:slab_sandstone_top 202 155 121 +mcl_stairs:slab_sandstonesmooth2 202 155 121 +mcl_stairs:slab_sandstonesmooth2_double 202 155 121 +mcl_stairs:slab_sandstonesmooth2_top 202 155 121 +mcl_stairs:slab_sprucetree_bark 69 53 45 +mcl_stairs:slab_sprucetree_bark_double 69 53 45 +mcl_stairs:slab_sprucetree_bark_top 69 53 45 +mcl_stairs:slab_sprucewood 82 66 54 +mcl_stairs:slab_sprucewood_double 82 66 54 +mcl_stairs:slab_sprucewood_top 82 66 54 +mcl_stairs:slab_stone 128 119 115 +mcl_stairs:slab_stone_double 128 119 115 +mcl_stairs:slab_stone_rough 131 123 118 +mcl_stairs:slab_stone_rough_double 131 123 118 +mcl_stairs:slab_stone_rough_top 131 123 118 +mcl_stairs:slab_stone_top 128 119 115 +mcl_stairs:slab_stonebrick 99 91 88 +mcl_stairs:slab_stonebrick_double 99 91 88 +mcl_stairs:slab_stonebrick_top 99 91 88 +mcl_stairs:slab_stonebrickcracked 96 89 85 +mcl_stairs:slab_stonebrickcracked_double 96 89 85 +mcl_stairs:slab_stonebrickcracked_top 96 89 85 +mcl_stairs:slab_stonebrickmossy 86 104 79 +mcl_stairs:slab_stonebrickmossy_double 86 104 79 +mcl_stairs:slab_stonebrickmossy_top 86 104 79 +mcl_stairs:slab_tree_bark 99 78 59 +mcl_stairs:slab_tree_bark_double 99 78 59 +mcl_stairs:slab_tree_bark_top 99 78 59 +mcl_stairs:slab_warped_hyphae_wood 78 64 108 +mcl_stairs:slab_warped_hyphae_wood_double 78 64 108 +mcl_stairs:slab_warped_hyphae_wood_top 78 64 108 +mcl_stairs:slab_wood 115 89 68 +mcl_stairs:slab_wood_double 115 89 68 +mcl_stairs:slab_wood_top 115 89 68 +mcl_stairs:stair_acaciatree_bark 107 94 77 +mcl_stairs:stair_acaciatree_bark_inner 107 94 77 +mcl_stairs:stair_acaciatree_bark_outer 107 94 77 +mcl_stairs:stair_acaciawood 153 103 71 +mcl_stairs:stair_acaciawood_inner 153 103 71 +mcl_stairs:stair_acaciawood_outer 153 103 71 +mcl_stairs:stair_andesite 105 111 107 +mcl_stairs:stair_andesite_inner 105 111 107 +mcl_stairs:stair_andesite_outer 105 111 107 +mcl_stairs:stair_andesite_smooth 107 114 109 +mcl_stairs:stair_andesite_smooth_inner 107 114 109 +mcl_stairs:stair_andesite_smooth_outer 107 114 109 +mcl_stairs:stair_birchtree_bark 199 190 180 +mcl_stairs:stair_birchtree_bark_inner 199 190 180 +mcl_stairs:stair_birchtree_bark_outer 199 190 180 +mcl_stairs:stair_birchwood 147 116 90 +mcl_stairs:stair_birchwood_inner 147 116 90 +mcl_stairs:stair_birchwood_outer 147 116 90 +mcl_stairs:stair_blackstone 33 31 35 +mcl_stairs:stair_blackstone_brick_polished 42 39 44 +mcl_stairs:stair_blackstone_brick_polished_inner 42 39 44 +mcl_stairs:stair_blackstone_brick_polished_outer 42 39 44 +mcl_stairs:stair_blackstone_chiseled_polished 42 39 44 +mcl_stairs:stair_blackstone_chiseled_polished_inner 42 39 44 +mcl_stairs:stair_blackstone_chiseled_polished_outer 42 39 44 +mcl_stairs:stair_blackstone_inner 33 31 35 +mcl_stairs:stair_blackstone_outer 33 31 35 +mcl_stairs:stair_blackstone_polished 44 42 47 +mcl_stairs:stair_blackstone_polished_inner 44 42 47 +mcl_stairs:stair_blackstone_polished_outer 44 42 47 +mcl_stairs:stair_brick_block 140 92 81 +mcl_stairs:stair_brick_block_inner 140 92 81 +mcl_stairs:stair_brick_block_outer 140 92 81 +mcl_stairs:stair_cobble 114 108 105 +mcl_stairs:stair_cobble_inner 114 108 105 +mcl_stairs:stair_cobble_outer 114 108 105 +mcl_stairs:stair_concrete_black 8 10 15 +mcl_stairs:stair_concrete_black_inner 8 10 15 +mcl_stairs:stair_concrete_black_outer 8 10 15 +mcl_stairs:stair_concrete_blue 46 48 147 +mcl_stairs:stair_concrete_blue_inner 46 48 147 +mcl_stairs:stair_concrete_blue_outer 46 48 147 +mcl_stairs:stair_concrete_brown 98 60 32 +mcl_stairs:stair_concrete_brown_inner 98 60 32 +mcl_stairs:stair_concrete_brown_outer 98 60 32 +mcl_stairs:stair_concrete_cyan 21 123 140 +mcl_stairs:stair_concrete_cyan_inner 21 123 140 +mcl_stairs:stair_concrete_cyan_outer 21 123 140 +mcl_stairs:stair_concrete_green 75 94 37 +mcl_stairs:stair_concrete_green_inner 75 94 37 +mcl_stairs:stair_concrete_green_outer 75 94 37 +mcl_stairs:stair_concrete_grey 56 59 64 +mcl_stairs:stair_concrete_grey_inner 56 59 64 +mcl_stairs:stair_concrete_grey_outer 56 59 64 +mcl_stairs:stair_concrete_light_blue 37 140 200 +mcl_stairs:stair_concrete_light_blue_inner 37 140 200 +mcl_stairs:stair_concrete_light_blue_outer 37 140 200 +mcl_stairs:stair_concrete_lime 96 171 25 +mcl_stairs:stair_concrete_lime_inner 96 171 25 +mcl_stairs:stair_concrete_lime_outer 96 171 25 +mcl_stairs:stair_concrete_magenta 171 49 162 +mcl_stairs:stair_concrete_magenta_inner 171 49 162 +mcl_stairs:stair_concrete_magenta_outer 171 49 162 +mcl_stairs:stair_concrete_orange 226 101 1 +mcl_stairs:stair_concrete_orange_inner 226 101 1 +mcl_stairs:stair_concrete_orange_outer 226 101 1 +mcl_stairs:stair_concrete_pink 213 103 144 +mcl_stairs:stair_concrete_pink_inner 213 103 144 +mcl_stairs:stair_concrete_pink_outer 213 103 144 +mcl_stairs:stair_concrete_purple 103 32 159 +mcl_stairs:stair_concrete_purple_inner 103 32 159 +mcl_stairs:stair_concrete_purple_outer 103 32 159 +mcl_stairs:stair_concrete_red 146 34 34 +mcl_stairs:stair_concrete_red_inner 146 34 34 +mcl_stairs:stair_concrete_red_outer 146 34 34 +mcl_stairs:stair_concrete_silver 128 129 118 +mcl_stairs:stair_concrete_silver_inner 128 129 118 +mcl_stairs:stair_concrete_silver_outer 128 129 118 +mcl_stairs:stair_concrete_white 208 214 215 +mcl_stairs:stair_concrete_white_inner 208 214 215 +mcl_stairs:stair_concrete_white_outer 208 214 215 +mcl_stairs:stair_concrete_yellow 241 177 21 +mcl_stairs:stair_concrete_yellow_inner 241 177 21 +mcl_stairs:stair_concrete_yellow_outer 241 177 21 +mcl_stairs:stair_copper_cut 150 78 58 +mcl_stairs:stair_copper_cut_inner 150 78 58 +mcl_stairs:stair_copper_cut_outer 150 78 58 +mcl_stairs:stair_copper_exposed_cut 132 94 84 +mcl_stairs:stair_copper_exposed_cut_inner 132 94 84 +mcl_stairs:stair_copper_exposed_cut_outer 132 94 84 +mcl_stairs:stair_copper_oxidized_cut 91 112 112 +mcl_stairs:stair_copper_oxidized_cut_inner 91 112 112 +mcl_stairs:stair_copper_oxidized_cut_outer 91 112 112 +mcl_stairs:stair_copper_weathered_cut 109 105 102 +mcl_stairs:stair_copper_weathered_cut_inner 109 105 102 +mcl_stairs:stair_copper_weathered_cut_outer 109 105 102 +mcl_stairs:stair_crimson_hyphae_wood 119 46 40 +mcl_stairs:stair_crimson_hyphae_wood_inner 119 46 40 +mcl_stairs:stair_crimson_hyphae_wood_outer 119 46 40 +mcl_stairs:stair_darktree_bark 77 65 58 +mcl_stairs:stair_darktree_bark_inner 77 65 58 +mcl_stairs:stair_darktree_bark_outer 77 65 58 +mcl_stairs:stair_darkwood 89 76 63 +mcl_stairs:stair_darkwood_inner 89 76 63 +mcl_stairs:stair_darkwood_outer 89 76 63 +mcl_stairs:stair_deepslate_bricks 64 62 62 +mcl_stairs:stair_deepslate_bricks_inner 64 62 62 +mcl_stairs:stair_deepslate_bricks_outer 64 62 62 +mcl_stairs:stair_deepslate_cobbled 80 78 76 +mcl_stairs:stair_deepslate_cobbled_inner 80 78 76 +mcl_stairs:stair_deepslate_cobbled_outer 80 78 76 +mcl_stairs:stair_deepslate_polished 69 68 67 +mcl_stairs:stair_deepslate_polished_inner 69 68 67 +mcl_stairs:stair_deepslate_polished_outer 69 68 67 +mcl_stairs:stair_deepslate_tiles 51 50 49 +mcl_stairs:stair_deepslate_tiles_inner 51 50 49 +mcl_stairs:stair_deepslate_tiles_outer 51 50 49 +mcl_stairs:stair_diorite 154 150 148 +mcl_stairs:stair_diorite_inner 154 150 148 +mcl_stairs:stair_diorite_outer 154 150 148 +mcl_stairs:stair_diorite_smooth 158 155 152 +mcl_stairs:stair_diorite_smooth_inner 158 155 152 +mcl_stairs:stair_diorite_smooth_outer 158 155 152 +mcl_stairs:stair_end_bricks 195 189 123 +mcl_stairs:stair_end_bricks_inner 195 189 123 +mcl_stairs:stair_end_bricks_outer 195 189 123 +mcl_stairs:stair_goldblock 195 152 65 +mcl_stairs:stair_goldblock_inner 195 152 65 +mcl_stairs:stair_goldblock_outer 195 152 65 +mcl_stairs:stair_granite 155 122 111 +mcl_stairs:stair_granite_inner 155 122 111 +mcl_stairs:stair_granite_outer 155 122 111 +mcl_stairs:stair_granite_smooth 152 122 110 +mcl_stairs:stair_granite_smooth_inner 152 122 110 +mcl_stairs:stair_granite_smooth_outer 152 122 110 +mcl_stairs:stair_ironblock 173 167 167 +mcl_stairs:stair_ironblock_inner 173 167 167 +mcl_stairs:stair_ironblock_outer 173 167 167 +mcl_stairs:stair_jungletree_bark 90 62 46 +mcl_stairs:stair_jungletree_bark_inner 90 62 46 +mcl_stairs:stair_jungletree_bark_outer 90 62 46 +mcl_stairs:stair_junglewood 114 80 60 +mcl_stairs:stair_junglewood_inner 114 80 60 +mcl_stairs:stair_junglewood_outer 114 80 60 +mcl_stairs:stair_lapisblock 57 95 161 +mcl_stairs:stair_lapisblock_inner 57 95 161 +mcl_stairs:stair_lapisblock_outer 57 95 161 +mcl_stairs:stair_mangrove_wood 125 61 55 +mcl_stairs:stair_mangrove_wood_inner 125 61 55 +mcl_stairs:stair_mangrove_wood_outer 125 61 55 +mcl_stairs:stair_mossycobble 105 106 97 +mcl_stairs:stair_mossycobble_inner 105 106 97 +mcl_stairs:stair_mossycobble_outer 105 106 97 +mcl_stairs:stair_mud_brick 109 96 87 +mcl_stairs:stair_mud_brick_inner 109 96 87 +mcl_stairs:stair_mud_brick_outer 109 96 87 +mcl_stairs:stair_nether_brick 49 25 26 +mcl_stairs:stair_nether_brick_inner 49 25 26 +mcl_stairs:stair_nether_brick_outer 49 25 26 +mcl_stairs:stair_prismarine 106 127 123 +mcl_stairs:stair_prismarine_brick 107 116 117 +mcl_stairs:stair_prismarine_brick_inner 107 116 117 +mcl_stairs:stair_prismarine_brick_outer 107 116 117 +mcl_stairs:stair_prismarine_dark 77 90 97 +mcl_stairs:stair_prismarine_dark_inner 77 90 97 +mcl_stairs:stair_prismarine_dark_outer 77 90 97 +mcl_stairs:stair_prismarine_inner 106 127 123 +mcl_stairs:stair_prismarine_outer 106 127 123 +mcl_stairs:stair_purpur_block 161 112 175 +mcl_stairs:stair_purpur_block_inner 161 112 175 +mcl_stairs:stair_purpur_block_outer 161 112 175 +mcl_stairs:stair_quartz_smooth 198 191 187 +mcl_stairs:stair_quartz_smooth_inner 198 191 187 +mcl_stairs:stair_quartz_smooth_outer 198 191 187 +mcl_stairs:stair_quartzblock 198 191 187 +mcl_stairs:stair_quartzblock_inner 198 191 187 +mcl_stairs:stair_quartzblock_outer 198 191 187 +mcl_stairs:stair_red_nether_brick 72 17 6 +mcl_stairs:stair_red_nether_brick_inner 72 17 6 +mcl_stairs:stair_red_nether_brick_outer 72 17 6 +mcl_stairs:stair_redsandstone 212 126 108 +mcl_stairs:stair_redsandstone_inner 212 126 108 +mcl_stairs:stair_redsandstone_outer 212 126 108 +mcl_stairs:stair_redsandstonesmooth2 212 126 108 +mcl_stairs:stair_redsandstonesmooth2_inner 212 126 108 +mcl_stairs:stair_redsandstonesmooth2_outer 212 126 108 +mcl_stairs:stair_sandstone 202 155 121 +mcl_stairs:stair_sandstone_inner 202 155 121 +mcl_stairs:stair_sandstone_outer 202 155 121 +mcl_stairs:stair_sandstonesmooth2 202 155 121 +mcl_stairs:stair_sandstonesmooth2_inner 202 155 121 +mcl_stairs:stair_sandstonesmooth2_outer 202 155 121 +mcl_stairs:stair_sprucetree_bark 69 53 45 +mcl_stairs:stair_sprucetree_bark_inner 69 53 45 +mcl_stairs:stair_sprucetree_bark_outer 69 53 45 +mcl_stairs:stair_sprucewood 82 66 54 +mcl_stairs:stair_sprucewood_inner 82 66 54 +mcl_stairs:stair_sprucewood_outer 82 66 54 +mcl_stairs:stair_stone_rough 131 123 118 +mcl_stairs:stair_stone_rough_inner 131 123 118 +mcl_stairs:stair_stone_rough_outer 131 123 118 +mcl_stairs:stair_stonebrick 99 91 88 +mcl_stairs:stair_stonebrick_inner 99 91 88 +mcl_stairs:stair_stonebrick_outer 99 91 88 +mcl_stairs:stair_stonebrickcracked 96 89 85 +mcl_stairs:stair_stonebrickcracked_inner 96 89 85 +mcl_stairs:stair_stonebrickcracked_outer 96 89 85 +mcl_stairs:stair_stonebrickmossy 86 104 79 +mcl_stairs:stair_stonebrickmossy_inner 86 104 79 +mcl_stairs:stair_stonebrickmossy_outer 86 104 79 +mcl_stairs:stair_tree_bark 99 78 59 +mcl_stairs:stair_tree_bark_inner 99 78 59 +mcl_stairs:stair_tree_bark_outer 99 78 59 +mcl_stairs:stair_warped_hyphae_wood 78 64 108 +mcl_stairs:stair_warped_hyphae_wood_inner 78 64 108 +mcl_stairs:stair_warped_hyphae_wood_outer 78 64 108 +mcl_stairs:stair_wood 115 89 68 +mcl_stairs:stair_wood_inner 115 89 68 +mcl_stairs:stair_wood_outer 115 89 68 + +# mcl_stonecutter +mcl_stonecutter:stonecutter 88 82 80 + +# mcl_structures + +# mcl_target +mcl_target:target_off 182 137 112 +mcl_target:target_on 182 137 112 + +# mcl_tnt +mcl_tnt:tnt 134 55 57 + +# mcl_torches +mcl_torches:torch 94 72 58 +mcl_torches:torch_wall 94 72 58 + +# mcl_villages +mcl_villages:stonebrickcarved 100 92 88 + +# mcl_walls +mcl_walls:andesite 105 111 107 +mcl_walls:andesite_0 105 111 107 +mcl_walls:andesite_1 105 111 107 +mcl_walls:andesite_10 105 111 107 +mcl_walls:andesite_11 105 111 107 +mcl_walls:andesite_12 105 111 107 +mcl_walls:andesite_13 105 111 107 +mcl_walls:andesite_14 105 111 107 +mcl_walls:andesite_15 105 111 107 +mcl_walls:andesite_16 105 111 107 +mcl_walls:andesite_2 105 111 107 +mcl_walls:andesite_21 105 111 107 +mcl_walls:andesite_3 105 111 107 +mcl_walls:andesite_4 105 111 107 +mcl_walls:andesite_5 105 111 107 +mcl_walls:andesite_6 105 111 107 +mcl_walls:andesite_7 105 111 107 +mcl_walls:andesite_8 105 111 107 +mcl_walls:andesite_9 105 111 107 +mcl_walls:brick 140 92 81 +mcl_walls:brick_0 140 92 81 +mcl_walls:brick_1 140 92 81 +mcl_walls:brick_10 140 92 81 +mcl_walls:brick_11 140 92 81 +mcl_walls:brick_12 140 92 81 +mcl_walls:brick_13 140 92 81 +mcl_walls:brick_14 140 92 81 +mcl_walls:brick_15 140 92 81 +mcl_walls:brick_16 140 92 81 +mcl_walls:brick_2 140 92 81 +mcl_walls:brick_21 140 92 81 +mcl_walls:brick_3 140 92 81 +mcl_walls:brick_4 140 92 81 +mcl_walls:brick_5 140 92 81 +mcl_walls:brick_6 140 92 81 +mcl_walls:brick_7 140 92 81 +mcl_walls:brick_8 140 92 81 +mcl_walls:brick_9 140 92 81 +mcl_walls:cobble 122 116 113 +mcl_walls:cobble_0 122 116 113 +mcl_walls:cobble_1 122 116 113 +mcl_walls:cobble_10 122 116 113 +mcl_walls:cobble_11 122 116 113 +mcl_walls:cobble_12 122 116 113 +mcl_walls:cobble_13 122 116 113 +mcl_walls:cobble_14 122 116 113 +mcl_walls:cobble_15 122 116 113 +mcl_walls:cobble_16 122 116 113 +mcl_walls:cobble_2 122 116 113 +mcl_walls:cobble_21 122 116 113 +mcl_walls:cobble_3 122 116 113 +mcl_walls:cobble_4 122 116 113 +mcl_walls:cobble_5 122 116 113 +mcl_walls:cobble_6 122 116 113 +mcl_walls:cobble_7 122 116 113 +mcl_walls:cobble_8 122 116 113 +mcl_walls:cobble_9 122 116 113 +mcl_walls:diorite 154 150 148 +mcl_walls:diorite_0 154 150 148 +mcl_walls:diorite_1 154 150 148 +mcl_walls:diorite_10 154 150 148 +mcl_walls:diorite_11 154 150 148 +mcl_walls:diorite_12 154 150 148 +mcl_walls:diorite_13 154 150 148 +mcl_walls:diorite_14 154 150 148 +mcl_walls:diorite_15 154 150 148 +mcl_walls:diorite_16 154 150 148 +mcl_walls:diorite_2 154 150 148 +mcl_walls:diorite_21 154 150 148 +mcl_walls:diorite_3 154 150 148 +mcl_walls:diorite_4 154 150 148 +mcl_walls:diorite_5 154 150 148 +mcl_walls:diorite_6 154 150 148 +mcl_walls:diorite_7 154 150 148 +mcl_walls:diorite_8 154 150 148 +mcl_walls:diorite_9 154 150 148 +mcl_walls:endbricks 195 189 123 +mcl_walls:endbricks_0 195 189 123 +mcl_walls:endbricks_1 195 189 123 +mcl_walls:endbricks_10 195 189 123 +mcl_walls:endbricks_11 195 189 123 +mcl_walls:endbricks_12 195 189 123 +mcl_walls:endbricks_13 195 189 123 +mcl_walls:endbricks_14 195 189 123 +mcl_walls:endbricks_15 195 189 123 +mcl_walls:endbricks_16 195 189 123 +mcl_walls:endbricks_2 195 189 123 +mcl_walls:endbricks_21 195 189 123 +mcl_walls:endbricks_3 195 189 123 +mcl_walls:endbricks_4 195 189 123 +mcl_walls:endbricks_5 195 189 123 +mcl_walls:endbricks_6 195 189 123 +mcl_walls:endbricks_7 195 189 123 +mcl_walls:endbricks_8 195 189 123 +mcl_walls:endbricks_9 195 189 123 +mcl_walls:granite 155 122 111 +mcl_walls:granite_0 155 122 111 +mcl_walls:granite_1 155 122 111 +mcl_walls:granite_10 155 122 111 +mcl_walls:granite_11 155 122 111 +mcl_walls:granite_12 155 122 111 +mcl_walls:granite_13 155 122 111 +mcl_walls:granite_14 155 122 111 +mcl_walls:granite_15 155 122 111 +mcl_walls:granite_16 155 122 111 +mcl_walls:granite_2 155 122 111 +mcl_walls:granite_21 155 122 111 +mcl_walls:granite_3 155 122 111 +mcl_walls:granite_4 155 122 111 +mcl_walls:granite_5 155 122 111 +mcl_walls:granite_6 155 122 111 +mcl_walls:granite_7 155 122 111 +mcl_walls:granite_8 155 122 111 +mcl_walls:granite_9 155 122 111 +mcl_walls:mossycobble 59 98 63 +mcl_walls:mossycobble_0 59 98 63 +mcl_walls:mossycobble_1 59 98 63 +mcl_walls:mossycobble_10 59 98 63 +mcl_walls:mossycobble_11 59 98 63 +mcl_walls:mossycobble_12 59 98 63 +mcl_walls:mossycobble_13 59 98 63 +mcl_walls:mossycobble_14 59 98 63 +mcl_walls:mossycobble_15 59 98 63 +mcl_walls:mossycobble_16 59 98 63 +mcl_walls:mossycobble_2 59 98 63 +mcl_walls:mossycobble_21 59 98 63 +mcl_walls:mossycobble_3 59 98 63 +mcl_walls:mossycobble_4 59 98 63 +mcl_walls:mossycobble_5 59 98 63 +mcl_walls:mossycobble_6 59 98 63 +mcl_walls:mossycobble_7 59 98 63 +mcl_walls:mossycobble_8 59 98 63 +mcl_walls:mossycobble_9 59 98 63 +mcl_walls:mudbrick 109 96 87 +mcl_walls:mudbrick_0 109 96 87 +mcl_walls:mudbrick_1 109 96 87 +mcl_walls:mudbrick_10 109 96 87 +mcl_walls:mudbrick_11 109 96 87 +mcl_walls:mudbrick_12 109 96 87 +mcl_walls:mudbrick_13 109 96 87 +mcl_walls:mudbrick_14 109 96 87 +mcl_walls:mudbrick_15 109 96 87 +mcl_walls:mudbrick_16 109 96 87 +mcl_walls:mudbrick_2 109 96 87 +mcl_walls:mudbrick_21 109 96 87 +mcl_walls:mudbrick_3 109 96 87 +mcl_walls:mudbrick_4 109 96 87 +mcl_walls:mudbrick_5 109 96 87 +mcl_walls:mudbrick_6 109 96 87 +mcl_walls:mudbrick_7 109 96 87 +mcl_walls:mudbrick_8 109 96 87 +mcl_walls:mudbrick_9 109 96 87 +mcl_walls:netherbrick 49 25 26 +mcl_walls:netherbrick_0 49 25 26 +mcl_walls:netherbrick_1 49 25 26 +mcl_walls:netherbrick_10 49 25 26 +mcl_walls:netherbrick_11 49 25 26 +mcl_walls:netherbrick_12 49 25 26 +mcl_walls:netherbrick_13 49 25 26 +mcl_walls:netherbrick_14 49 25 26 +mcl_walls:netherbrick_15 49 25 26 +mcl_walls:netherbrick_16 49 25 26 +mcl_walls:netherbrick_2 49 25 26 +mcl_walls:netherbrick_21 49 25 26 +mcl_walls:netherbrick_3 49 25 26 +mcl_walls:netherbrick_4 49 25 26 +mcl_walls:netherbrick_5 49 25 26 +mcl_walls:netherbrick_6 49 25 26 +mcl_walls:netherbrick_7 49 25 26 +mcl_walls:netherbrick_8 49 25 26 +mcl_walls:netherbrick_9 49 25 26 +mcl_walls:prismarine 106 127 123 +mcl_walls:prismarine_0 106 127 123 +mcl_walls:prismarine_1 106 127 123 +mcl_walls:prismarine_10 106 127 123 +mcl_walls:prismarine_11 106 127 123 +mcl_walls:prismarine_12 106 127 123 +mcl_walls:prismarine_13 106 127 123 +mcl_walls:prismarine_14 106 127 123 +mcl_walls:prismarine_15 106 127 123 +mcl_walls:prismarine_16 106 127 123 +mcl_walls:prismarine_2 106 127 123 +mcl_walls:prismarine_21 106 127 123 +mcl_walls:prismarine_3 106 127 123 +mcl_walls:prismarine_4 106 127 123 +mcl_walls:prismarine_5 106 127 123 +mcl_walls:prismarine_6 106 127 123 +mcl_walls:prismarine_7 106 127 123 +mcl_walls:prismarine_8 106 127 123 +mcl_walls:prismarine_9 106 127 123 +mcl_walls:rednetherbrick 72 17 6 +mcl_walls:rednetherbrick_0 72 17 6 +mcl_walls:rednetherbrick_1 72 17 6 +mcl_walls:rednetherbrick_10 72 17 6 +mcl_walls:rednetherbrick_11 72 17 6 +mcl_walls:rednetherbrick_12 72 17 6 +mcl_walls:rednetherbrick_13 72 17 6 +mcl_walls:rednetherbrick_14 72 17 6 +mcl_walls:rednetherbrick_15 72 17 6 +mcl_walls:rednetherbrick_16 72 17 6 +mcl_walls:rednetherbrick_2 72 17 6 +mcl_walls:rednetherbrick_21 72 17 6 +mcl_walls:rednetherbrick_3 72 17 6 +mcl_walls:rednetherbrick_4 72 17 6 +mcl_walls:rednetherbrick_5 72 17 6 +mcl_walls:rednetherbrick_6 72 17 6 +mcl_walls:rednetherbrick_7 72 17 6 +mcl_walls:rednetherbrick_8 72 17 6 +mcl_walls:rednetherbrick_9 72 17 6 +mcl_walls:redsandstone 212 126 108 +mcl_walls:redsandstone_0 212 126 108 +mcl_walls:redsandstone_1 212 126 108 +mcl_walls:redsandstone_10 212 126 108 +mcl_walls:redsandstone_11 212 126 108 +mcl_walls:redsandstone_12 212 126 108 +mcl_walls:redsandstone_13 212 126 108 +mcl_walls:redsandstone_14 212 126 108 +mcl_walls:redsandstone_15 212 126 108 +mcl_walls:redsandstone_16 212 126 108 +mcl_walls:redsandstone_2 212 126 108 +mcl_walls:redsandstone_21 212 126 108 +mcl_walls:redsandstone_3 212 126 108 +mcl_walls:redsandstone_4 212 126 108 +mcl_walls:redsandstone_5 212 126 108 +mcl_walls:redsandstone_6 212 126 108 +mcl_walls:redsandstone_7 212 126 108 +mcl_walls:redsandstone_8 212 126 108 +mcl_walls:redsandstone_9 212 126 108 +mcl_walls:sandstone 202 155 121 +mcl_walls:sandstone_0 202 155 121 +mcl_walls:sandstone_1 202 155 121 +mcl_walls:sandstone_10 202 155 121 +mcl_walls:sandstone_11 202 155 121 +mcl_walls:sandstone_12 202 155 121 +mcl_walls:sandstone_13 202 155 121 +mcl_walls:sandstone_14 202 155 121 +mcl_walls:sandstone_15 202 155 121 +mcl_walls:sandstone_16 202 155 121 +mcl_walls:sandstone_2 202 155 121 +mcl_walls:sandstone_21 202 155 121 +mcl_walls:sandstone_3 202 155 121 +mcl_walls:sandstone_4 202 155 121 +mcl_walls:sandstone_5 202 155 121 +mcl_walls:sandstone_6 202 155 121 +mcl_walls:sandstone_7 202 155 121 +mcl_walls:sandstone_8 202 155 121 +mcl_walls:sandstone_9 202 155 121 +mcl_walls:stonebrick 99 91 88 +mcl_walls:stonebrick_0 99 91 88 +mcl_walls:stonebrick_1 99 91 88 +mcl_walls:stonebrick_10 99 91 88 +mcl_walls:stonebrick_11 99 91 88 +mcl_walls:stonebrick_12 99 91 88 +mcl_walls:stonebrick_13 99 91 88 +mcl_walls:stonebrick_14 99 91 88 +mcl_walls:stonebrick_15 99 91 88 +mcl_walls:stonebrick_16 99 91 88 +mcl_walls:stonebrick_2 99 91 88 +mcl_walls:stonebrick_21 99 91 88 +mcl_walls:stonebrick_3 99 91 88 +mcl_walls:stonebrick_4 99 91 88 +mcl_walls:stonebrick_5 99 91 88 +mcl_walls:stonebrick_6 99 91 88 +mcl_walls:stonebrick_7 99 91 88 +mcl_walls:stonebrick_8 99 91 88 +mcl_walls:stonebrick_9 99 91 88 +mcl_walls:stonebrickmossy 86 104 79 +mcl_walls:stonebrickmossy_0 86 104 79 +mcl_walls:stonebrickmossy_1 86 104 79 +mcl_walls:stonebrickmossy_10 86 104 79 +mcl_walls:stonebrickmossy_11 86 104 79 +mcl_walls:stonebrickmossy_12 86 104 79 +mcl_walls:stonebrickmossy_13 86 104 79 +mcl_walls:stonebrickmossy_14 86 104 79 +mcl_walls:stonebrickmossy_15 86 104 79 +mcl_walls:stonebrickmossy_16 86 104 79 +mcl_walls:stonebrickmossy_2 86 104 79 +mcl_walls:stonebrickmossy_21 86 104 79 +mcl_walls:stonebrickmossy_3 86 104 79 +mcl_walls:stonebrickmossy_4 86 104 79 +mcl_walls:stonebrickmossy_5 86 104 79 +mcl_walls:stonebrickmossy_6 86 104 79 +mcl_walls:stonebrickmossy_7 86 104 79 +mcl_walls:stonebrickmossy_8 86 104 79 +mcl_walls:stonebrickmossy_9 86 104 79 + +# mcl_wool +mcl_wool:black 46 43 43 +mcl_wool:black_carpet 46 43 43 +mcl_wool:blue 43 75 126 +mcl_wool:blue_carpet 43 75 126 +mcl_wool:brown 87 57 43 +mcl_wool:brown_carpet 87 57 43 +mcl_wool:cyan 30 95 113 +mcl_wool:cyan_carpet 30 95 113 +mcl_wool:green 54 92 51 +mcl_wool:green_carpet 54 92 51 +mcl_wool:grey 97 88 88 +mcl_wool:grey_carpet 97 88 88 +mcl_wool:light_blue 92 132 180 +mcl_wool:light_blue_carpet 92 132 180 +mcl_wool:lime 110 152 77 +mcl_wool:lime_carpet 110 152 77 +mcl_wool:magenta 142 86 126 +mcl_wool:magenta_carpet 142 86 126 +mcl_wool:orange 188 107 46 +mcl_wool:orange_carpet 188 107 46 +mcl_wool:pink 171 92 108 +mcl_wool:pink_carpet 171 92 108 +mcl_wool:purple 79 57 103 +mcl_wool:purple_carpet 79 57 103 +mcl_wool:red 133 42 45 +mcl_wool:red_carpet 133 42 45 +mcl_wool:silver 143 135 135 +mcl_wool:silver_carpet 143 135 135 +mcl_wool:white 212 199 183 +mcl_wool:white_carpet 212 199 183 +mcl_wool:yellow 201 164 70 +mcl_wool:yellow_carpet 201 164 70 + +# mclx_core +mclx_core:river_water_flowing 0 122 139 +mclx_core:river_water_source 32 121 138 + +# mclx_fences +mclx_fences:nether_brick_fence_gate 51 27 27 +mclx_fences:nether_brick_fence_gate_open 51 27 27 +mclx_fences:red_nether_brick_fence 72 18 0 +mclx_fences:red_nether_brick_fence_gate 68 16 0 +mclx_fences:red_nether_brick_fence_gate_open 68 16 0 + +# mesecons +mesecons:wire_00000000_off 171 171 171 +mesecons:wire_00000000_on 171 171 171 +mesecons:wire_00010000_off 171 171 171 +mesecons:wire_00010000_on 171 171 171 +mesecons:wire_00010001_off 171 171 171 +mesecons:wire_00010001_on 171 171 171 +mesecons:wire_00100000_off 171 171 171 +mesecons:wire_00100000_on 171 171 171 +mesecons:wire_00100010_off 171 171 171 +mesecons:wire_00100010_on 171 171 171 +mesecons:wire_00110000_off 171 171 171 +mesecons:wire_00110000_on 171 171 171 +mesecons:wire_00110001_off 171 171 171 +mesecons:wire_00110001_on 171 171 171 +mesecons:wire_00110010_off 171 171 171 +mesecons:wire_00110010_on 171 171 171 +mesecons:wire_00110011_off 171 171 171 +mesecons:wire_00110011_on 171 171 171 +mesecons:wire_01000000_off 171 171 171 +mesecons:wire_01000000_on 171 171 171 +mesecons:wire_01000100_off 171 171 171 +mesecons:wire_01000100_on 171 171 171 +mesecons:wire_01010000_off 171 171 171 +mesecons:wire_01010000_on 171 171 171 +mesecons:wire_01010001_off 171 171 171 +mesecons:wire_01010001_on 171 171 171 +mesecons:wire_01010100_off 171 171 171 +mesecons:wire_01010100_on 171 171 171 +mesecons:wire_01010101_off 171 171 171 +mesecons:wire_01010101_on 171 171 171 +mesecons:wire_01100000_off 171 171 171 +mesecons:wire_01100000_on 171 171 171 +mesecons:wire_01100010_off 171 171 171 +mesecons:wire_01100010_on 171 171 171 +mesecons:wire_01100100_off 171 171 171 +mesecons:wire_01100100_on 171 171 171 +mesecons:wire_01100110_off 171 171 171 +mesecons:wire_01100110_on 171 171 171 +mesecons:wire_01110000_off 171 171 171 +mesecons:wire_01110000_on 171 171 171 +mesecons:wire_01110001_off 171 171 171 +mesecons:wire_01110001_on 171 171 171 +mesecons:wire_01110010_off 171 171 171 +mesecons:wire_01110010_on 171 171 171 +mesecons:wire_01110011_off 171 171 171 +mesecons:wire_01110011_on 171 171 171 +mesecons:wire_01110100_off 171 171 171 +mesecons:wire_01110100_on 171 171 171 +mesecons:wire_01110101_off 171 171 171 +mesecons:wire_01110101_on 171 171 171 +mesecons:wire_01110110_off 171 171 171 +mesecons:wire_01110110_on 171 171 171 +mesecons:wire_01110111_off 171 171 171 +mesecons:wire_01110111_on 171 171 171 +mesecons:wire_10000000_off 171 171 171 +mesecons:wire_10000000_on 171 171 171 +mesecons:wire_10001000_off 171 171 171 +mesecons:wire_10001000_on 171 171 171 +mesecons:wire_10010000_off 171 171 171 +mesecons:wire_10010000_on 171 171 171 +mesecons:wire_10010001_off 171 171 171 +mesecons:wire_10010001_on 171 171 171 +mesecons:wire_10011000_off 171 171 171 +mesecons:wire_10011000_on 171 171 171 +mesecons:wire_10011001_off 171 171 171 +mesecons:wire_10011001_on 171 171 171 +mesecons:wire_10100000_off 171 171 171 +mesecons:wire_10100000_on 171 171 171 +mesecons:wire_10100010_off 171 171 171 +mesecons:wire_10100010_on 171 171 171 +mesecons:wire_10101000_off 171 171 171 +mesecons:wire_10101000_on 171 171 171 +mesecons:wire_10101010_off 171 171 171 +mesecons:wire_10101010_on 171 171 171 +mesecons:wire_10110000_off 171 171 171 +mesecons:wire_10110000_on 171 171 171 +mesecons:wire_10110001_off 171 171 171 +mesecons:wire_10110001_on 171 171 171 +mesecons:wire_10110010_off 171 171 171 +mesecons:wire_10110010_on 171 171 171 +mesecons:wire_10110011_off 171 171 171 +mesecons:wire_10110011_on 171 171 171 +mesecons:wire_10111000_off 171 171 171 +mesecons:wire_10111000_on 171 171 171 +mesecons:wire_10111001_off 171 171 171 +mesecons:wire_10111001_on 171 171 171 +mesecons:wire_10111010_off 171 171 171 +mesecons:wire_10111010_on 171 171 171 +mesecons:wire_10111011_off 171 171 171 +mesecons:wire_10111011_on 171 171 171 +mesecons:wire_11000000_off 171 171 171 +mesecons:wire_11000000_on 171 171 171 +mesecons:wire_11000100_off 171 171 171 +mesecons:wire_11000100_on 171 171 171 +mesecons:wire_11001000_off 171 171 171 +mesecons:wire_11001000_on 171 171 171 +mesecons:wire_11001100_off 171 171 171 +mesecons:wire_11001100_on 171 171 171 +mesecons:wire_11010000_off 171 171 171 +mesecons:wire_11010000_on 171 171 171 +mesecons:wire_11010001_off 171 171 171 +mesecons:wire_11010001_on 171 171 171 +mesecons:wire_11010100_off 171 171 171 +mesecons:wire_11010100_on 171 171 171 +mesecons:wire_11010101_off 171 171 171 +mesecons:wire_11010101_on 171 171 171 +mesecons:wire_11011000_off 171 171 171 +mesecons:wire_11011000_on 171 171 171 +mesecons:wire_11011001_off 171 171 171 +mesecons:wire_11011001_on 171 171 171 +mesecons:wire_11011100_off 171 171 171 +mesecons:wire_11011100_on 171 171 171 +mesecons:wire_11011101_off 171 171 171 +mesecons:wire_11011101_on 171 171 171 +mesecons:wire_11100000_off 171 171 171 +mesecons:wire_11100000_on 171 171 171 +mesecons:wire_11100010_off 171 171 171 +mesecons:wire_11100010_on 171 171 171 +mesecons:wire_11100100_off 171 171 171 +mesecons:wire_11100100_on 171 171 171 +mesecons:wire_11100110_off 171 171 171 +mesecons:wire_11100110_on 171 171 171 +mesecons:wire_11101000_off 171 171 171 +mesecons:wire_11101000_on 171 171 171 +mesecons:wire_11101010_off 171 171 171 +mesecons:wire_11101010_on 171 171 171 +mesecons:wire_11101100_off 171 171 171 +mesecons:wire_11101100_on 171 171 171 +mesecons:wire_11101110_off 171 171 171 +mesecons:wire_11101110_on 171 171 171 +mesecons:wire_11110000_off 171 171 171 +mesecons:wire_11110000_on 171 171 171 +mesecons:wire_11110001_off 171 171 171 +mesecons:wire_11110001_on 171 171 171 +mesecons:wire_11110010_off 171 171 171 +mesecons:wire_11110010_on 171 171 171 +mesecons:wire_11110011_off 171 171 171 +mesecons:wire_11110011_on 171 171 171 +mesecons:wire_11110100_off 171 171 171 +mesecons:wire_11110100_on 171 171 171 +mesecons:wire_11110101_off 171 171 171 +mesecons:wire_11110101_on 171 171 171 +mesecons:wire_11110110_off 171 171 171 +mesecons:wire_11110110_on 171 171 171 +mesecons:wire_11110111_off 171 171 171 +mesecons:wire_11110111_on 171 171 171 +mesecons:wire_11111000_off 171 171 171 +mesecons:wire_11111000_on 171 171 171 +mesecons:wire_11111001_off 171 171 171 +mesecons:wire_11111001_on 171 171 171 +mesecons:wire_11111010_off 171 171 171 +mesecons:wire_11111010_on 171 171 171 +mesecons:wire_11111011_off 171 171 171 +mesecons:wire_11111011_on 171 171 171 +mesecons:wire_11111100_off 171 171 171 +mesecons:wire_11111100_on 171 171 171 +mesecons:wire_11111101_off 171 171 171 +mesecons:wire_11111101_on 171 171 171 +mesecons:wire_11111110_off 171 171 171 +mesecons:wire_11111110_on 171 171 171 +mesecons:wire_11111111_off 171 171 171 +mesecons:wire_11111111_on 171 171 171 + +# mesecons_button +mesecons_button:button_acaciawood_off 153 103 71 +mesecons_button:button_acaciawood_on 153 103 71 +mesecons_button:button_birchwood_off 147 116 90 +mesecons_button:button_birchwood_on 147 116 90 +mesecons_button:button_darkwood_off 89 76 63 +mesecons_button:button_darkwood_on 89 76 63 +mesecons_button:button_junglewood_off 114 80 60 +mesecons_button:button_junglewood_on 114 80 60 +mesecons_button:button_sprucewood_off 82 66 54 +mesecons_button:button_sprucewood_on 82 66 54 +mesecons_button:button_stone_off 131 123 118 +mesecons_button:button_stone_on 131 123 118 +mesecons_button:button_wood_off 115 89 68 +mesecons_button:button_wood_on 115 89 68 + +# mesecons_commandblock +mesecons_commandblock:commandblock_off 128 113 105 +mesecons_commandblock:commandblock_on 128 113 105 + +# mesecons_delayer +mesecons_delayer:delayer_off_1 115 105 101 +mesecons_delayer:delayer_off_2 115 105 101 +mesecons_delayer:delayer_off_3 115 105 101 +mesecons_delayer:delayer_off_4 115 105 101 +mesecons_delayer:delayer_off_locked 113 104 99 +mesecons_delayer:delayer_on_1 118 105 101 +mesecons_delayer:delayer_on_2 118 105 101 +mesecons_delayer:delayer_on_3 118 105 101 +mesecons_delayer:delayer_on_4 118 105 101 +mesecons_delayer:delayer_on_locked 116 104 99 + +# mesecons_lightstone +mesecons_lightstone:lightstone_off 73 52 44 +mesecons_lightstone:lightstone_on 122 65 41 + +# mesecons_noteblock +mesecons_noteblock:noteblock 114 89 69 + +# mesecons_pistons +mesecons_pistons:piston_down_normal_off 117 108 104 +mesecons_pistons:piston_down_normal_on 117 108 104 +mesecons_pistons:piston_down_pusher_normal 110 85 67 +mesecons_pistons:piston_down_pusher_sticky 110 85 67 +mesecons_pistons:piston_down_sticky_off 117 108 104 +mesecons_pistons:piston_down_sticky_on 117 108 104 +mesecons_pistons:piston_normal_off 123 111 103 +mesecons_pistons:piston_normal_on 123 111 103 +mesecons_pistons:piston_pusher_normal 110 85 67 +mesecons_pistons:piston_pusher_sticky 110 85 67 +mesecons_pistons:piston_sticky_off 123 111 103 +mesecons_pistons:piston_sticky_on 123 111 103 +mesecons_pistons:piston_up_normal_off 110 85 67 +mesecons_pistons:piston_up_normal_on 116 107 104 +mesecons_pistons:piston_up_pusher_normal 110 85 67 +mesecons_pistons:piston_up_pusher_sticky 103 84 65 +mesecons_pistons:piston_up_sticky_off 103 84 65 +mesecons_pistons:piston_up_sticky_on 116 107 104 + +# mesecons_pressureplates +mesecons_pressureplates:pressure_plate_acaciawood_off 153 103 71 +mesecons_pressureplates:pressure_plate_acaciawood_on 153 103 71 +mesecons_pressureplates:pressure_plate_birchwood_off 147 116 90 +mesecons_pressureplates:pressure_plate_birchwood_on 147 116 90 +mesecons_pressureplates:pressure_plate_darkwood_off 89 76 63 +mesecons_pressureplates:pressure_plate_darkwood_on 89 76 63 +mesecons_pressureplates:pressure_plate_junglewood_off 114 80 60 +mesecons_pressureplates:pressure_plate_junglewood_on 114 80 60 +mesecons_pressureplates:pressure_plate_sprucewood_off 82 66 54 +mesecons_pressureplates:pressure_plate_sprucewood_on 82 66 54 +mesecons_pressureplates:pressure_plate_stone_off 131 123 118 +mesecons_pressureplates:pressure_plate_stone_on 131 123 118 +mesecons_pressureplates:pressure_plate_wood_off 115 89 68 +mesecons_pressureplates:pressure_plate_wood_on 115 89 68 + +# mesecons_solarpanel +mesecons_solarpanel:solar_panel_inverted_off 118 132 149 +mesecons_solarpanel:solar_panel_inverted_on 118 132 149 +mesecons_solarpanel:solar_panel_off 150 141 130 +mesecons_solarpanel:solar_panel_on 150 141 130 + +# mesecons_torch +mesecons_torch:mesecon_torch_off 93 71 57 +mesecons_torch:mesecon_torch_off_wall 93 71 57 +mesecons_torch:mesecon_torch_on 104 72 58 +mesecons_torch:mesecon_torch_on_wall 104 72 58 +mesecons_torch:mesecon_torch_overheated 93 71 57 +mesecons_torch:mesecon_torch_overheated_wall 93 71 57 +mesecons_torch:redstoneblock 131 12 14 + +# mesecons_walllever +mesecons_walllever:wall_lever_off 110 100 95 +mesecons_walllever:wall_lever_on 110 100 95 + +# xpanes +xpanes:bar 157 148 148 64 16 +xpanes:bar_flat 157 148 148 64 16 +xpanes:pane_black 25 25 25 64 16 +xpanes:pane_black_flat 25 25 25 64 16 +xpanes:pane_blue 51 76 178 64 16 +xpanes:pane_blue_flat 51 76 178 64 16 +xpanes:pane_brown 102 76 51 64 16 +xpanes:pane_brown_flat 102 76 51 64 16 +xpanes:pane_cyan 76 127 153 64 16 +xpanes:pane_cyan_flat 76 127 153 64 16 +xpanes:pane_gray 76 76 76 64 16 +xpanes:pane_gray_flat 76 76 76 64 16 +xpanes:pane_green 102 127 51 64 16 +xpanes:pane_green_flat 102 127 51 64 16 +xpanes:pane_light_blue 102 153 216 64 16 +xpanes:pane_light_blue_flat 102 153 216 64 16 +xpanes:pane_lime 127 204 25 64 16 +xpanes:pane_lime_flat 127 204 25 64 16 +xpanes:pane_magenta 0 0 0 64 16 +xpanes:pane_magenta_flat 0 0 0 64 16 +xpanes:pane_natural 222 222 239 64 16 +xpanes:pane_natural_flat 222 222 239 64 16 +xpanes:pane_orange 216 127 51 64 16 +xpanes:pane_orange_flat 216 127 51 64 16 +xpanes:pane_pink 0 0 0 64 16 +xpanes:pane_pink_flat 0 0 0 64 16 +xpanes:pane_purple 127 63 178 64 16 +xpanes:pane_purple_flat 127 63 178 64 16 +xpanes:pane_red 153 51 51 64 16 +xpanes:pane_red_flat 153 51 51 64 16 +xpanes:pane_silver 153 153 153 64 16 +xpanes:pane_silver_flat 153 153 153 64 16 +xpanes:pane_white 255 255 255 64 16 +xpanes:pane_white_flat 255 255 255 64 16 +xpanes:pane_yellow 229 229 51 64 16 +xpanes:pane_yellow_flat 229 229 51 64 16 + diff --git a/tools/remove_end.py b/tools/remove_end.py deleted file mode 100644 index 3b73e5575..000000000 --- a/tools/remove_end.py +++ /dev/null @@ -1,46 +0,0 @@ -world_name = "world" -path_to_map_sqlite = "../../../worlds/" + world_name + "/map.sqlite" - -import sqlite3, sys - -try: - conn = sqlite3.connect(path_to_map_sqlite) -except Error as e: - print(e) - sys.exit() - -def unsignedToSigned(i, max_positive): - if i < max_positive: - return i - else: - return i - 2*max_positive - -cursor = conn.cursor() -cursor.execute("SELECT pos FROM blocks") -poses = cursor.fetchall() -end_blocks = [] -for i0 in (poses): - i = int(i0[0]) - blockpos = i - x = unsignedToSigned(i % 4096, 2048) - i = int((i - x) / 4096) - y = unsignedToSigned(i % 4096, 2048) - i = int((i - y) / 4096) - z = unsignedToSigned(i % 4096, 2048) - - node_pos_y = y * 16 - if node_pos_y > -28811 and node_pos_y + 15 < -67: - end_blocks.append(blockpos) - -if len(end_blocks) < 1: - print ("End blocks not found") - sys.exit() - -counter = 0 -for blockpos in end_blocks: - print("Deleting ", blockpos) - cursor.execute("DELETE FROM blocks WHERE pos=" + str(blockpos)) - counter += 1 -conn.commit() - -print(counter, " block(s) deleted")