Merge branch 'master' into master

This commit is contained in:
3raven 2022-08-31 17:04:43 +00:00
commit 5329e70df9
29 changed files with 413 additions and 286 deletions

@ -853,9 +853,10 @@ minetest.register_entity(":__builtin:item", {
-- If node is not registered or node is walkably solid and resting on nodebox
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local def = minetest.registered_nodes[nn]
local v = self.object:get_velocity()
local is_on_floor = (minetest.registered_nodes[nn].walkable
and not minetest.registered_nodes[nn].groups.slippery and v.y == 0)
local is_on_floor = def and (def.walkable
and not def.groups.slippery and v.y == 0)
if not minetest.registered_nodes[nn]
or is_floating or is_on_floor then

@ -213,11 +213,11 @@ end
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()
@ -254,12 +254,14 @@ local set_velocity = function(self, v)
end
local yaw = (self.object:get_yaw() or 0) + self.rotate
self.object:set_velocity({
x = (sin(yaw) * -v) + c_x,
y = self.object:get_velocity().y,
z = (cos(yaw) * v) + c_y,
})
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
@ -3002,6 +3004,7 @@ 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
@ -3467,7 +3470,10 @@ local mob_activate = function(self, staticdata, def, dtime)
def.textures = {def.textures}
end
self.base_texture = def.textures[random(1, #def.textures)]
local c = 1
if #def.textures > c then c = #def.textures end
self.base_texture = def.textures[math.random(c)]
self.base_mesh = def.mesh
self.base_size = self.visual_size
self.base_colbox = self.collisionbox

@ -23,7 +23,8 @@ local table_copy = table.copy
local table_remove = table.remove
local pairs = pairs
local dbg_spawn_attempts = 0
local dbg_spawn_succ = 0
-- range for mob count
local aoc_range = 136
@ -416,47 +417,87 @@ local function get_water_spawn(p)
end
end
local dbg_spawn_attempts = 0
local dbg_spawn_succ = 0
local function spawn_check(pos,spawn_def)
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 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
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
local is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
if not is_ground then
pos.y = pos.y - 1
gotten_node = get_node(pos).name
is_ground = minetest.get_item_group(gotten_node,"solid") ~= 0
end
pos.y = pos.y + 1
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)
if pos and spawn_def
and mob_count_wide < (mob_cap[mob_type] or 15)
and mob_count < 5
and pos.y >= spawn_def.min_height
and pos.y <= spawn_def.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.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 is_bedrock then
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(pos)
if gotten_light >= spawn_def.min_light and gotten_light <= spawn_def.max_light then
return true
end
end
return false
end
local function spawn_group(p,mob,spawn_on,group_max,group_min)
if not group_min then group_min = 1 end
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
local o
table.shuffle(nn)
if not nn or #nn < 1 then
nn = {}
table.insert(nn,p)
end
for i = 1, math.random(group_min,group_max) do
local sp = vector.offset(nn[math.random(#nn)],0,1,0)
if mob.type_of_spawning == "water" then
sp = get_water_spawn(sp)
if spawn_check(nn[math.random(#nn)],mob) then
if mob.type_of_spawning == "water" then
sp = get_water_spawn(sp)
end
o = minetest.add_entity(sp,mob.name)
if o then dbg_spawn_succ = dbg_spawn_succ + 1 end
end
o = minetest.add_entity(sp,mob.name)
if o then dbg_spawn_succ = dbg_spawn_succ + 1 end
end
return o
end
minetest.register_chatcommand("mobstats",{
privs = { debug = true },
func = function(n,param)
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())
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
end
})
if mobs_spawn then
local perlin_noise
local function spawn_a_mob(pos, dimension, y_min, y_max)
dbg_spawn_attempts = dbg_spawn_attempts + 1
local dimension = dimension or mcl_worlds.pos_to_dimension(pos)
--create a disconnected clone of the spawn dictionary
--prevents memory leak
local mob_library_worker_table = table_copy(spawn_dictionary)
local goal_pos = get_next_mob_spawn_pos(pos)
--grab mob that fits into the spawning location
--randomly grab a mob, don't exclude any possibilities
local spawning_position_list = find_nodes_in_area_under_air(
{x = goal_pos.x, y = y_min, z = goal_pos.z},
{x = goal_pos.x, y = y_max, z = goal_pos.z},
@ -465,37 +506,6 @@ if mobs_spawn then
if #spawning_position_list <= 0 then return end
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
local gotten_node = get_node(spawning_position).name
local gotten_biome = minetest.get_biome_data(spawning_position)
if not gotten_node or not gotten_biome then return end
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
--add this so mobs don't spawn inside nodes
spawning_position.y = spawning_position.y + 1
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(spawning_position)
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_ground = not (is_water or is_lava)
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
local has_bed = minetest.find_node_near(pos,25,{"group:bed"})
if not is_ground then
spawning_position.y = spawning_position.y - 1
end
local mob_def
--create a disconnected clone of the spawn dictionary
--prevents memory leak
local mob_library_worker_table = table_copy(spawn_dictionary)
--grab mob that fits into the spawning location
--randomly grab a mob, don't exclude any possibilities
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
local noise = perlin_noise:get_3d(spawning_position)
local current_summary_chance = summary_chance
@ -511,28 +521,10 @@ if mobs_spawn then
step_chance = step_chance + mob_chance
end
local mob_def = mob_library_worker_table[mob_index]
local mob_type = minetest.registered_entities[mob_def.name].type
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_count_wide = count_mobs(pos,aoc_range,mob_type)
local mob_count = count_mobs(spawning_position,32,mob_type)
if mob_def
and mob_count_wide < (mob_cap[mob_type] or 15)
and mob_count < 5
and spawning_position.y >= mob_def.min_height
and spawning_position.y <= mob_def.max_height
and mob_def.dimension == dimension
and biome_check(mob_def.biomes, gotten_biome)
and gotten_light >= mob_def.min_light
and gotten_light <= mob_def.max_light
and (is_ground or mob_def.type_of_spawning ~= "ground")
and (mob_def.type_of_spawning ~= "ground" or not is_leaf)
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
and (not is_farm_animal(mob_def.name) or is_grass)
and (mob_type ~= "npc" or has_bed)
and (mob_def.type_of_spawning ~= "water" or is_water)
and not is_bedrock
then
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
@ -544,9 +536,10 @@ if mobs_spawn then
end
--everything is correct, spawn mob
local object
if spawn_in_group then
object = spawn_group(spawning_position,mob_def,{gotten_node},spawn_in_group,spawn_in_group_min)
else object = minetest.add_entity(spawning_position, mob_def.name)
if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then
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
object = minetest.add_entity(spawning_position, mob_def.name)
end
@ -580,3 +573,14 @@ if mobs_spawn then
end
end)
end
minetest.register_chatcommand("mobstats",{
privs = { debug = true },
func = function(n,param)
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())
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
end
})

@ -12,6 +12,7 @@ local S = minetest.get_translator("mobs_mc")
mcl_mobs:register_mob("mobs_mc:creeper", {
type = "monster",
spawn_class = "hostile",
spawn_in_group = 1,
hp_min = 20,
hp_max = 20,
xp_min = 5,

@ -219,6 +219,7 @@ local select_enderman_animation = function(animation_type)
end
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local spawners = {}
mcl_mobs:register_mob("mobs_mc:enderman", {
description = S("Enderman"),
@ -263,20 +264,42 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
do_custom = function(self, dtime)
-- PARTICLE BEHAVIOUR HERE.
local enderpos = self.object:get_pos()
local chanceOfParticle = math.random(0, 1)
if chanceOfParticle == 1 then
minetest.add_particle({
pos = {x=enderpos.x+math.random(-1,1)*math.random()/2,y=enderpos.y+math.random(0,3),z=enderpos.z+math.random(-1,1)*math.random()/2},
velocity = {x=math.random(-.25,.25), y=math.random(-.25,.25), z=math.random(-.25,.25)},
acceleration = {x=math.random(-.5,.5), y=math.random(-.5,.5), z=math.random(-.5,.5)},
expirationtime = math.random(),
size = math.random(),
collisiondetection = true,
vertical = false,
texture = "mcl_portals_particle"..math.random(1, 5)..".png",
})
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 dim = mcl_worlds.pos_to_dimension(enderpos)
if dim == "overworld" then
if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then
@ -593,6 +616,13 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
attack_type = "dogfight",
})
minetest.register_on_leaveplayer(function(player)
for _,s in pairs(spawners[player]) do
minetest.delete_particlespawner(s)
end
spawners[player] = nil
end)
-- End spawn
mcl_mobs:spawn_specific(

@ -72,7 +72,7 @@ local tropical_fish = {
collisionbox = {-0.2, 0.0, -0.2, 0.2, 0.1, 0.2},
visual = "mesh",
mesh = "extra_mobs_tropical_fish_a.b3d",
textures = {}, -- to be populated on_spawn
textures = { "extra_mobs_tropical_fish_a.png" }, -- to be populated on_spawn
sounds = {},
animation = {
stand_start = 0,

@ -591,6 +591,51 @@ local function go_home(entity)
end)
end
local function has_golem(pos)
local r = false
for _,o in pairs(minetest.get_objects_inside_radius(pos,16)) do
local l = o:get_luaentity()
if l and l.name == "mobs_mc:iron_golem" 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
if l and l.name == "mobs_mc:villager" then r = r + 1 end
end
return r > 2
end
local function summon_golem(self)
vector.offset(self.object:get_pos(),-10,-10,-10)
local nn = minetest.find_nodes_in_area_under_air(vector.offset(self.object:get_pos(),-10,-10,-10),vector.offset(self.object:get_pos(),10,10,10),{"group:solid","group:water"})
table.shuffle(nn)
for _,n in pairs(nn) do
local up = minetest.find_nodes_in_area(vector.offset(n,0,1,0),vector.offset(n,0,3,0),{"air"})
if up and #up >= 3 then
minetest.sound_play("mcl_portals_open_end_portal", {pos=n, gain=0.5, max_hear_distance = 16}, true)
return minetest.add_entity(vector.offset(n,0,1,0),"mobs_mc:iron_golem")
end
end
end
local function check_summon(self,dtime)
-- TODO has selpt in last 20?
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 not has_summon_participants(self) then return end
summon_golem(self)
elseif self._summon_timer == nil then
self._summon_timer = 0
end
self._summon_timer = self._summon_timer + dtime
end
----- JOBSITE LOGIC
local function get_profession_by_jobsite(js)
for k,v in pairs(professions) do
@ -1337,6 +1382,7 @@ mcl_mobs:register_mob("mobs_mc:villager", {
_player_scan_timer = 0,
_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

@ -55,7 +55,7 @@ local zombie = {
xp_max = 5,
breath_max = -1,
armor = {undead = 90, fleshy = 90},
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3},
collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.8, 0.3},
visual = "mesh",
mesh = "mobs_mc_zombie.b3d",
textures = {
@ -65,7 +65,6 @@ local zombie = {
"mobs_mc_empty.png", -- wielded_item
}
},
visual_size = {x=3, y=3},
makes_footstep_sound = true,
sounds = {
random = "mobs_mc_zombie_growl",
@ -85,16 +84,23 @@ local zombie = {
group_attack = { "mobs_mc:zombie", "mobs_mc:baby_zombie", "mobs_mc:husk", "mobs_mc:baby_husk" },
drops = drops_zombie,
animation = {
speed_normal = 25, speed_run = 50,
stand_start = 40, stand_end = 80,
walk_start = 0, walk_end = 40,
run_start = 0, run_end = 40,
stand_start = 40, stand_end = 49, stand_speed = 2,
walk_start = 0, walk_end = 39, speed_normal = 25,
run_start = 0, run_end = 39, speed_run = 50,
punch_start = 50, punch_end = 59, punch_speed = 20,
},
ignited_by_sunlight = true,
sunlight_damage = 2,
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,
}
mcl_mobs:register_mob("mobs_mc:zombie", zombie)
@ -104,13 +110,20 @@ mcl_mobs:register_mob("mobs_mc:zombie", zombie)
local baby_zombie = table.copy(zombie)
baby_zombie.description = S("Baby Zombie")
baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
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=zombie.visual_size.x/2, y=zombie.visual_size.y/2}
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
baby_zombie.reach = 1
baby_zombie.animation = {
stand_start = 100, stand_end = 109, stand_speed = 2,
walk_start = 60, walk_end = 99, speed_normal = 40,
run_start = 60, run_end = 99, speed_run = 80,
punch_start = 109, punch_end = 119
}
mcl_mobs:register_mob("mobs_mc:baby_zombie", baby_zombie)
@ -134,15 +147,16 @@ mcl_mobs:register_mob("mobs_mc:husk", husk)
-- Baby husk.
-- A smaller and more dangerous variant of the husk
local baby_husk = table.copy(husk)
local baby_husk = table.copy(baby_zombie)
baby_husk.description = S("Baby Husk")
baby_husk.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.94, 0.25}
baby_husk.xp_min = 12
baby_husk.xp_max = 12
baby_husk.visual_size = {x=zombie.visual_size.x/2, y=zombie.visual_size.y/2}
baby_husk.walk_velocity = 1.2
baby_husk.run_velocity = 2.4
baby_husk.child = 1
baby_husk.textures = {{
"mobs_mc_empty.png", -- armor
"mobs_mc_husk.png", -- texture
"mobs_mc_empty.png", -- wielded_item
}}
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)

@ -1,4 +1,6 @@
local S = minetest.get_translator(minetest.get_current_modname())
local F = minetest.formspec_escape
local C = minetest.colorize
local max_text_length = 4500 -- TODO: Increase to 12800 when scroll bar was added to written book
local max_title_length = 64
@ -331,6 +333,75 @@ if minetest.get_modpath("mcl_sounds") then
wood_sound = mcl_sounds.node_sound_wood_defaults()
end
-- Bookshelf GUI
local drop_content = mcl_util.drop_items_from_meta_container("main")
local function on_blast(pos)
local node = minetest.get_node(pos)
drop_content(pos, node)
minetest.remove_node(pos)
end
-- Simple protection checking functions
local function protection_check_move(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
local function protection_check_put_take(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
elseif minetest.get_item_group(stack:get_name(), "book") ~= 0 or stack:get_name() == "mcl_enchanting:book_enchanted" then
return stack:get_count()
else
return 0
end
end
local function bookshelf_gui(pos, node, clicker)
local name = minetest.get_meta(pos):get_string("name")
if name == "" then
name = S("Bookshelf")
end
local playername = clicker:get_player_name()
minetest.show_formspec(playername,
"mcl_books:bookshelf_"..pos.x.."_"..pos.y.."_"..pos.z,
table.concat({
"size[9,8.75]",
"label[0,0;"..F(C("#313131", name)).."]",
"list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]",
mcl_formspec.get_itemslot_bg(0, 0.5, 9, 3),
"label[0,4.0;"..F(C("#313131", S("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[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]",
"listring[current_player;main]",
})
)
end
local function close_forms(pos)
local players = minetest.get_connected_players()
local formname = "mcl_books:bookshelf_"..pos.x.."_"..pos.y.."_"..pos.z
for p = 1, #players do
if vector.distance(players[p]:get_pos(), pos) <= 30 then
minetest.close_formspec(players[p]:get_player_name(), formname)
end
end
end
-- Bookshelf
minetest.register_node("mcl_books:bookshelf", {
description = S("Bookshelf"),
@ -340,13 +411,40 @@ minetest.register_node("mcl_books:bookshelf", {
is_ground_content = false,
groups = {
handy=1, axey=1, deco_block=1, material_wood=1,
flammable=3, fire_encouragement=30, fire_flammability=20
flammable=3, fire_encouragement=30, fire_flammability=20, container=1
},
drop = "mcl_books:book 3",
sounds = wood_sound,
_mcl_blast_resistance = 1.5,
_mcl_hardness = 1.5,
_mcl_silk_touch_drop = true,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("main", 9*3)
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
end,
allow_metadata_inventory_move = protection_check_move,
allow_metadata_inventory_take = protection_check_put_take,
allow_metadata_inventory_put = protection_check_put_take,
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
minetest.log("action", player:get_player_name()..
" moves stuff in bookshelf at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" moves stuff to bookshelf at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" takes stuff from bookshelf at "..minetest.pos_to_string(pos))
end,
after_dig_node = drop_content,
on_blast = on_blast,
on_rightclick = bookshelf_gui,
on_destruct = close_gui,
})
minetest.register_craft({

@ -1,4 +1,5 @@
name = mcl_books
author = celeron55
description = Books mod for MCL2
depends = mcl_util, mcl_formspec
optional_depends = mcl_init, mcl_core, mcl_sounds, mcl_mobitems, mcl_dye, mcl_colors

@ -390,7 +390,7 @@ minetest.register_tool("mcl_fishing:fishing_rod", {
_doc_items_usagehelp = S("Rightclick to launch the bobber. When it sinks right-click again to reel in an item. Who knows what you're going to catch?"),
groups = { tool=1, fishing_rod=1, enchantability=1 },
inventory_image = "mcl_fishing_fishing_rod.png",
wield_image = "mcl_fishing_fishing_rod.png^[transformR270",
wield_image = "mcl_fishing_fishing_rod.png^[transformFY^[transformR90",
wield_scale = { x = 1.5, y = 1.5, z = 1 },
stack_max = 1,
on_place = fish,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 359 B

@ -177,15 +177,27 @@ local function drop_grindstone_items(pos, meta)
end
end
local node_box = {
type = "fixed",
-- created with nodebox editor
fixed = {
{-0.25, -0.25, -0.375, 0.25, 0.5, 0.375},
{-0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875},
{0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875},
{0.25, -0.5, -0.125, 0.375, -0.0625, 0.125},
{-0.375, -0.5, -0.125, -0.25, -0.0625, 0.125},
}
}
minetest.register_node("mcl_grindstone:grindstone", {
description = S("Grindstone"),
_tt_help = S("Used to disenchant/fix tools"),
_doc_items_longdesc = S("Grindstone disenchants tools and armour except for curses, and repairs two items of the same type it is also the weapon smith's work station."),
_doc_items_usagehelp = S("To use the grindstone, rightclick it, Two input slots (on the left) and a single output slot.").."\n"..
S("To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.").."\n"..
S("To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.").."\n"..
S("If both items have enchantments the player will get xp from both items from the disenchant.").."\n"..
S("Curses cannot be removed and will be transfered to the new repaired item, if both items have a different curse the curses will be combined."),
S("To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.").."\n"..
S("To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.").."\n"..
S("If both items have enchantments the player will get xp from both items from the disenchant.").."\n"..
S("Curses cannot be removed and will be transfered to the new repaired item, if both items have a different curse the curses will be combined."),
tiles = {
"grindstone_top.png",
"grindstone_top.png",
@ -196,17 +208,7 @@ minetest.register_node("mcl_grindstone:grindstone", {
},
drawtype = "nodebox",
paramtype2 = "facedir",
node_box = {
type = "fixed",
-- created with nodebox editor
fixed = {
{-0.25, -0.25, -0.375, 0.25, 0.5, 0.375},
{-0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875},
{0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875},
{0.25, -0.5, -0.125, 0.375, -0.0625, 0.125},
{-0.375, -0.5, -0.125, -0.25, -0.0625, 0.125},
}
},
node_box = node_box,
selection_box = node_box,
collision_box = node_box,
sounds = mcl_sounds.node_sound_stone_defaults(),

@ -227,6 +227,7 @@ filled_wield_def.drawtype = "mesh"
filled_wield_def.node_placement_prediction = ""
filled_wield_def.range = minetest.registered_items[""].range
filled_wield_def.on_place = mcl_util.call_on_rightclick
filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map"
for _, texture in pairs(mcl_skins.list) do
local def = table.copy(filled_wield_def)

@ -321,7 +321,7 @@ minetest.register_tool("mcl_mobitems:carrot_on_a_stick", {
_tt_help = S("Lets you ride a saddled pig"),
_doc_items_longdesc = S("A carrot on a stick can be used on saddled pigs to ride them."),
_doc_items_usagehelp = S("Place it on a saddled pig to mount it. You can now ride the pig like a horse. Pigs will also walk towards you when you just wield the carrot on a stick."),
wield_image = "mcl_mobitems_carrot_on_a_stick.png",
wield_image = "mcl_mobitems_carrot_on_a_stick.png^[transformFY^[transformR90",
inventory_image = "mcl_mobitems_carrot_on_a_stick.png",
groups = { transport = 1 },
_mcl_toollike_wield = true,

@ -31,12 +31,12 @@ minetest.register_tool("mcl_shields:shield", {
shield = 1,
weapon = 1,
enchantability = -1,
no_wieldview = 1,
offhand_item = 1,
},
sound = {breaks = "default_tool_breaks"},
_repair_material = "group:wood",
wield_scale = vector.new(2, 2, 2),
_mcl_wieldview_item = "",
})
local function wielded_item(obj, i)
@ -438,7 +438,6 @@ for _, colortab in pairs(mcl_banners.colors) do
shield = 1,
weapon = 1,
enchantability = -1,
no_wieldview = 1,
not_in_creative_inventory = 1,
offhand_item = 1,
},
@ -446,6 +445,7 @@ for _, colortab in pairs(mcl_banners.colors) do
_repair_material = "group:wood",
wield_scale = vector.new(2, 2, 2),
_shield_color = colortab[4],
_mcl_wieldview_item = "",
})
local banner = "mcl_banners:banner_item_" .. color

@ -7,19 +7,15 @@ mcl_smithing_table = {}
-- Function to upgrade diamond tool/armor to netherite tool/armor
function mcl_smithing_table.upgrade_item(itemstack)
itemstack = ItemStack(itemstack) -- Copy the stack
local def = itemstack:get_definition()
if not def or not def._mcl_upgradable then
return
end
local itemname = itemstack:get_name()
local upgrade_item = itemname:gsub("diamond", "netherite")
local upgrade_item = def._mcl_upgrade_item or itemname:gsub("diamond", "netherite")
if upgrade_item == itemname then
if def._mcl_upgrade_item and upgrade_item == itemname then
return
end

@ -8,7 +8,7 @@ mcl_structures.register_structure("pillager_outpost",{
flags = "place_center_x, place_center_z",
solid_ground = true,
make_foundation = true,
sidelen = 18,
sidelen = 23,
y_offset = 0,
chunk_probability = 600,
y_max = mcl_vars.mg_overworld_max,

@ -33,21 +33,20 @@ minetest.register_on_dieplayer(function(player)
end
local listname = mcl_death_drop.registered_dropped_lists[l].listname
local drop = mcl_death_drop.registered_dropped_lists[l].drop
local dropspots = minetest.find_nodes_in_area(vector.offset(pos,-3,0,-3),vector.offset(pos,3,0,3),{"air"})
if #dropspots == 0 then
table.insert(dropspots,pos)
end
if inv then
for i, stack in ipairs(inv:get_list(listname)) do
local x = random(0, 9)/3
local z = random(0, 9)/3
pos.x = pos.x + x
pos.z = pos.z + z
local p = vector.offset(dropspots[math.random(#dropspots)],math.random()-0.5,math.random()-0.5,math.random()-0.5)
if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then
local def = minetest.registered_items[stack:get_name()]
if def and def.on_drop then
stack = def.on_drop(stack, player, pos)
stack = def.on_drop(stack, player, p)
end
minetest.add_item(pos, stack)
minetest.add_item(p, stack)
end
pos.x = pos.x - x
pos.z = pos.z - z
end
inv:set_list(listname, {})
end

@ -103,10 +103,6 @@ function mcl_player.player_set_armor(player, texture)
set_texture(player, 2, texture)
end
function mcl_player.player_set_wielditem(player, texture)
set_texture(player, 3, texture)
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]

@ -359,15 +359,17 @@ 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,3.9,1.3), vector.new(90,0,0))
set_bone_position_conditional(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(.5,4.5,-1.6), vector.new(90,0,20))
set_bone_position_conditional(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(-1.5,5.7,1.8), vector.new(64,90,0))
set_bone_position_conditional(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(-1.5,5.7,1.8), vector.new(90,90,0))
set_bone_position_conditional(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))
else
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
set_bone_position_conditional(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

@ -1,21 +1,13 @@
[mod] visible wielded items [wieldview]
[mod] visible wielded items [mcl_wieldview]
=======================================
Makes hand wielded items visible to other players.
default settings: [minetest.conf]
# Set number of seconds between visible wielded item updates.
wieldview_update_time = 2
# Show nodes as tiles, disabled by default
wieldview_node_tiles = false
Info for modders
################
Wield image transformation: To apply a simple transformation to the item in
hand, add the group “wieldview_transform” to the item definition. The group
rating equals one of the numbers used for the [transform texture modifier
of the Lua API.
Register an item with the property "_mcl_wieldview_item" to change the third person wield view appearance of the item.
"_mcl_wieldview_item" should be set to an item name that will be shown by the wield view instead of the item.
If you use an empty string, nothing will be shown.

@ -1,126 +1,64 @@
local get_connected_players = minetest.get_connected_players
local get_item_group = minetest.get_item_group
mcl_wieldview = {
players = {}
}
function mcl_wieldview.get_item_texture(itemname)
if itemname == "" or minetest.get_item_group(itemname, "no_wieldview") ~= 0 then
return
end
local def = minetest.registered_items[itemname]
if not def then
return
end
local inv_image = def.inventory_image
if inv_image == "" then
return
end
local texture = inv_image
local transform = get_item_group(itemname, "wieldview_transform")
if transform then
-- This actually works with groups ratings because transform1, transform2, etc.
-- have meaning and transform0 is used for identidy, so it can be ignored
texture = texture .. "^[transform" .. transform
end
return texture
end
function mcl_wieldview.update_wielded_item(player)
if not player then
return
end
local itemstack = player:get_wielded_item()
local itemname = itemstack:get_name()
local def = mcl_wieldview.players[player]
if def.item == itemname then
return
end
def.item = itemname
def.texture = mcl_wieldview.get_item_texture(itemname) or "blank.png"
mcl_player.player_set_wielditem(player, def.texture)
end
minetest.register_on_joinplayer(function(player)
mcl_wieldview.players[player] = {item = "", texture = "blank.png"}
minetest.after(0, function()
if not player:is_player() then
return
end
mcl_wieldview.update_wielded_item(player)
local itementity = minetest.add_entity(player:get_pos(), "mcl_wieldview:wieldnode")
itementity:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 0, 45))
itementity:get_luaentity().wielder = player
end)
end)
minetest.register_on_leaveplayer(function(player)
mcl_wieldview.players[player] = nil
end)
minetest.register_globalstep(function()
local players = get_connected_players()
for i = 1, #players do
mcl_wieldview.update_wielded_item(players[i])
end
end)
minetest.register_entity("mcl_wieldview:wieldnode", {
minetest.register_entity("mcl_wieldview:wieldview", {
initial_properties = {
hp_max = 1,
visual = "wielditem",
physical = false,
textures = {""},
automatic_rotate = 1.5,
is_visible = true,
is_visible = false,
pointable = false,
collide_with_objects = false,
static_save = false,
collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
visual_size = {x = 0.21, y = 0.21},
},
itemstring = "",
on_step = function(self)
if self.wielder:is_player() then
local def = mcl_wieldview.players[self.wielder]
local itemstring = def.item
if self.itemstring ~= itemstring then
local itemdef = minetest.registered_items[itemstring]
self.object:set_properties({glow = itemdef and itemdef.light_source or 0})
-- wield item as cubic
if def.texture == "blank.png" then
self.object:set_properties({textures = {itemstring}})
-- wield item as flat
else
self.object:set_properties({textures = {""}})
end
if minetest.get_item_group(itemstring, "no_wieldview") ~= 0 then
self.object:set_properties({textures = {""}})
end
self.itemstring = itemstring
end
else
self.object:remove()
end
end,
}
})
local wieldview_luaentites = {}
local function update_wieldview_entity(player)
local luaentity = wieldview_luaentites[player]
if luaentity and luaentity.object:get_yaw() then
local item = player:get_wielded_item():get_name()
if item == luaentity._item then return end
luaentity._item = item
local def = player:get_wielded_item():get_definition()
if def and def._mcl_wieldview_item then
item = def._mcl_wieldview_item
end
local item_def = minetest.registered_items[item]
luaentity.object:set_properties({
glow = item_def and item_def.light_source or 0,
wield_item = item,
is_visible = item ~= ""
})
else
-- If the player is running through an unloaded area,
-- the wieldview entity will sometimes get unloaded.
-- This code path is also used to initalize the wieldview.
-- Creating entites from minetest.register_on_joinplayer
-- is unreliable as of Minetest 5.6
local obj_ref = minetest.add_entity(player:get_pos(), "mcl_wieldview:wieldview")
if not obj_ref then return end
obj_ref:set_attach(player, "Wield_Item")
--obj_ref:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 45, 90))
wieldview_luaentites[player] = obj_ref:get_luaentity()
end
end
minetest.register_on_leaveplayer(function(player)
if wieldview_luaentites[player] then
wieldview_luaentites[player].object:remove()
end
wieldview_luaentites[player] = nil
end)
minetest.register_globalstep(function(dtime)
local players = minetest.get_connected_players()
for i, player in pairs(players) do
update_wieldview_entity(player)
end
end)

@ -1,4 +1,4 @@
name = mcl_wieldview
author = stujones11
description = Makes hand wielded items visible to other players.
depends = mcl_player
depends = mcl_armor, mcl_playerplus