Merge branch 'master' into shields2

NO11 2022-03-28 12:27:57 +00:00
commit 5974b6f609
16 changed files with 344 additions and 125 deletions

@ -56,6 +56,7 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
* `no_eat_delay=1`: Only for foodstuffs. When eating this, all eating delays are ignored. * `no_eat_delay=1`: Only for foodstuffs. When eating this, all eating delays are ignored.
* `can_eat_when_full=1`: Only for foodstuffs. This item can be eaten when the user has a full hunger bar * `can_eat_when_full=1`: Only for foodstuffs. This item can be eaten when the user has a full hunger bar
* `attached_node_facedir=1`: Like `attached_node`, but for facedir nodes * `attached_node_facedir=1`: Like `attached_node`, but for facedir nodes
* `supported_node=1`: Like `attached_node`, but can be placed on any nodes that do not have the `drawtype="airlike"` attribute.
* `cauldron`: Cauldron. 1: Empty. 2-4: Water height * `cauldron`: Cauldron. 1: Empty. 2-4: Water height
* `anvil`: Anvil. 1: No damage. 2-3: Higher damage levels * `anvil`: Anvil. 1: No damage. 2-3: Higher damage levels
* `no_rename=1`: Item cannot be renamed by anvil * `no_rename=1`: Item cannot be renamed by anvil

@ -2,7 +2,7 @@
An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils. An unofficial Minecraft-like game for Minetest. Forked from MineClone by davedevils.
Developed by many people. Not developed or endorsed by Mojang AB. Developed by many people. Not developed or endorsed by Mojang AB.
Version: 0.72.0 Version: 0.73.0 (in development)
### Gameplay ### Gameplay
You start in a randomly-generated world made entirely of cubes. You can explore You start in a randomly-generated world made entirely of cubes. You can explore
@ -66,7 +66,7 @@ Use the `/giveme` chat command to obtain them. See the in-game help for
an explanation. an explanation.
## Installation ## Installation
This game requires [Minetest](http://minetest.net) to run (version 5.3.0 or This game requires [Minetest](http://minetest.net) to run (version 5.4.1 or
later). So you need to install Minetest first. Only stable versions of Minetest later). So you need to install Minetest first. Only stable versions of Minetest
are officially supported. are officially supported.
There is no support for running MineClone2 in development versions of Minetest. There is no support for running MineClone2 in development versions of Minetest.

@ -1,29 +1,93 @@
-- Overrides the builtin minetest.check_single_for_falling.
-- We need to do this in order to handle nodes in mineclone specific groups
-- "supported_node" and "attached_node_facedir".
--
-- 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 vector = vector local vector = vector
local facedir_to_dir = minetest.facedir_to_dir local facedir_to_dir = minetest.facedir_to_dir
local get_item_group = minetest.get_item_group local get_item_group = minetest.get_item_group
local remove_node = minetest.remove_node local remove_node = minetest.remove_node
local get_node = minetest.get_node local get_node = minetest.get_node
local get_meta = minetest.get_meta
local registered_nodes = minetest.registered_nodes
local get_node_drops = minetest.get_node_drops
local add_item = minetest.add_item
-- drop_attached_node(p)
--
-- This function is copied verbatim from minetest/builtin/game/falling.lua
-- 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.
--
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 drop_stacks = {}
for k, v in pairs(drops) do
drop_stacks[k] = ItemStack(v)
end
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)
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,
}
add_item(pos, item)
end
end
-- minetest.check_single_for_falling(pos)
--
-- * causes an unsupported `group:falling_node` node to fall and causes an
-- unattached `group:attached_node` or `group:attached_node_facedir` node
-- or unsupported `group:supported_node` node to drop.
-- * does not spread these updates to neighbours.
--
-- Returns true if the node at <pos> has spawned a falling node or has been
-- dropped as item(s).
--
local original_function = minetest.check_single_for_falling local original_function = minetest.check_single_for_falling
function minetest.check_single_for_falling(pos) function minetest.check_single_for_falling(pos)
local ret_o = original_function(pos) if original_function(pos) then
local ret = false return true
local node = minetest.get_node(pos) end
local node = get_node(pos)
if get_item_group(node.name, "attached_node_facedir") ~= 0 then if get_item_group(node.name, "attached_node_facedir") ~= 0 then
local dir = facedir_to_dir(node.param2) local dir = facedir_to_dir(node.param2)
if dir then if dir then
if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then
remove_node(pos) drop_attached_node(pos)
local drops = minetest.get_node_drops(node.name, "") return true
for dr=1, #drops do
minetest.add_item(pos, drops[dr])
end
ret = true
end end
end end
end end
return ret_o or ret
if get_item_group(node.name, "supported_node") ~= 0 then
local def = registered_nodes[get_node(vector.offset(pos, 0, -1, 0)).name]
if def and def.drawtype == "airlike" then
drop_attached_node(pos)
return true
end
end
return false
end end

@ -131,17 +131,6 @@ function mcl_burning.set_on_fire(obj, burn_time)
if obj:is_player() then if obj:is_player() then
mcl_burning.update_hud(obj) mcl_burning.update_hud(obj)
end end
-- FIXME: does this code make sense? It removes attached fire luaentities from
-- another object that happen to be at the same position.
local fire_luaentity = fire_entity:get_luaentity()
for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do
local other_luaentity = other:get_luaentity()
if other_luaentity and other_luaentity.name == "mcl_burning:fire" and other_luaentity ~= fire_luaentity then
other:remove()
break
end
end
end end
function mcl_burning.extinguish(obj) function mcl_burning.extinguish(obj)

@ -57,7 +57,7 @@ minetest.register_on_joinplayer(function(player)
local storage = {} local storage = {}
local burn_data = player:get_meta():get_string("mcl_burning:data") local burn_data = player:get_meta():get_string("mcl_burning:data")
if burn_data ~= "" then if burn_data ~= "" then
storage = minetest.deserialize(burn_data) storage = minetest.deserialize(burn_data) or storage
end end
mcl_burning.storage[player] = storage mcl_burning.storage[player] = storage
if storage.burn_time and storage.burn_time > 0 then if storage.burn_time and storage.burn_time > 0 then
@ -98,8 +98,7 @@ minetest.register_entity("mcl_burning:fire", {
glow = -1, glow = -1,
backface_culling = false, backface_culling = false,
}, },
animation_frame = 0, _mcl_animation_timer = 0,
animation_timer = 0,
on_activate = function(self) on_activate = function(self)
self.object:set_sprite({x = 0, y = 0}, animation_frames, 1.0 / animation_frames) self.object:set_sprite({x = 0, y = 0}, animation_frames, 1.0 / animation_frames)
end, end,
@ -115,9 +114,9 @@ minetest.register_entity("mcl_burning:fire", {
return return
end end
if parent:is_player() then if parent:is_player() then
self.animation_timer = self.animation_timer + dtime self._mcl_animation_timer = self._mcl_animation_timer + dtime
if self.animation_timer >= 0.1 then if self._mcl_animation_timer >= 0.1 then
self.animation_timer = 0 self._mcl_animation_timer = 0
mcl_burning.update_hud(parent) mcl_burning.update_hud(parent)
end end
end end

@ -222,8 +222,8 @@ local collision = function(self)
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
if object:is_player() local ent = object:get_luaentity()
or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then if object:is_player() or (ent and ent._cmi_is_mob and object ~= self.object) then
local pos2 = object:get_pos() local pos2 = object:get_pos()
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}

@ -570,12 +570,22 @@ if mobs_spawn then
break break
end end
local gotten_node = get_node(spawning_position).name local gotten_node = get_node(spawning_position)
local gotten_node_name = gotten_node.name
local gotten_node_def = minetest.registered_nodes[gotten_node_name]
if not gotten_node or gotten_node == "air" then --skip air nodes if not gotten_node_name or not gotten_node_def or gotten_node_name == "air" then --skip air nodes
break break
end end
if gotten_node_def.use_texture_alpha and gotten_node_def.use_texture_alpha ~= "opaque" then
break
end --don't spawn on nonopaque nodes
local leaf = minetest.get_item_group(gotten_node_name,"leaves")
if leaf ~= 0 then
break end --don't spawn on treetops
local gotten_biome = minetest.get_biome_data(spawning_position) local gotten_biome = minetest.get_biome_data(spawning_position)
if not gotten_biome then if not gotten_biome then
@ -616,8 +626,8 @@ if mobs_spawn then
break break
end end
local is_water = get_item_group(gotten_node, "water") ~= 0 local is_water = get_item_group(gotten_node_name, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 0 local is_lava = get_item_group(gotten_node_name, "lava") ~= 0
if mob_def.type_of_spawning == "ground" and is_water then if mob_def.type_of_spawning == "ground" and is_water then
break break

@ -106,22 +106,42 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "flat",
"Swampland", "IcePlainsSpikes",
"Taiga", "ColdTaiga",
"ExtremeHills", "ColdTaiga_beach",
"BirchForest", "ColdTaiga_beach_water",
"MegaSpruceTaiga", "MegaTaiga",
"MegaTaiga", "MegaSpruceTaiga",
"ExtremeHills+", "ExtremeHills",
"Forest", "ExtremeHills_beach",
"Plains", "ExtremeHillsM",
"ColdTaiga", "ExtremeHills+",
"SunflowerPlains", "ExtremeHills+_snowtop",
"RoofedForest", "StoneBeach",
"MesaPlateauFM_grasstop", "Plains",
"ExtremeHillsM", "Plains_beach",
"BirchForestM", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
9, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -151,22 +151,42 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "flat",
"Swampland", "IcePlainsSpikes",
"Taiga", "ColdTaiga",
"ExtremeHills", "ColdTaiga_beach",
"BirchForest", "ColdTaiga_beach_water",
"MegaSpruceTaiga", "MegaTaiga",
"MegaTaiga", "MegaSpruceTaiga",
"ExtremeHills+", "ExtremeHills",
"Forest", "ExtremeHills_beach",
"Plains", "ExtremeHillsM",
"ColdTaiga", "ExtremeHills+",
"SunflowerPlains", "ExtremeHills+_snowtop",
"RoofedForest", "StoneBeach",
"MesaPlateauFM_grasstop", "Plains",
"ExtremeHillsM", "Plains_beach",
"BirchForestM", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
9, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -520,22 +520,42 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "flat",
"Swampland", "IcePlainsSpikes",
"Taiga", "ColdTaiga",
"ExtremeHills", "ColdTaiga_beach",
"BirchForest", "ColdTaiga_beach_water",
"MegaSpruceTaiga", "MegaTaiga",
"MegaTaiga", "MegaSpruceTaiga",
"ExtremeHills+", "ExtremeHills",
"Forest", "ExtremeHills_beach",
"Plains", "ExtremeHillsM",
"ColdTaiga", "ExtremeHills+",
"SunflowerPlains", "ExtremeHills+_snowtop",
"RoofedForest", "StoneBeach",
"MesaPlateauFM_grasstop", "Plains",
"ExtremeHillsM", "Plains_beach",
"BirchForestM", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -223,12 +223,18 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"Mesa", "Mesa",
"MesaPlateauFM_grasstop", "MesaPlateauFM_grasstop",
"MesaPlateauF", "MesaPlateauF",
"MesaPlateauFM", "MesaPlateauFM",
"MesaPlateauF_grasstop", "MesaPlateauF_grasstop",
"MesaBryce", "MesaBryce",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -188,22 +188,42 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "flat",
"Swampland", "IcePlainsSpikes",
"Taiga", "ColdTaiga",
"ExtremeHills", "ColdTaiga_beach",
"BirchForest", "ColdTaiga_beach_water",
"MegaSpruceTaiga", "MegaTaiga",
"MegaTaiga", "MegaSpruceTaiga",
"ExtremeHills+", "ExtremeHills",
"Forest", "ExtremeHills_beach",
"Plains", "ExtremeHillsM",
"ColdTaiga", "ExtremeHills+",
"SunflowerPlains", "ExtremeHills+_snowtop",
"RoofedForest", "StoneBeach",
"MesaPlateauFM_grasstop", "Plains",
"ExtremeHillsM", "Plains_beach",
"BirchForestM", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
9, 9,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -309,22 +309,42 @@ mobs:spawn_specific(
"overworld", "overworld",
"ground", "ground",
{ {
"FlowerForest", "flat",
"Swampland", "IcePlainsSpikes",
"Taiga", "ColdTaiga",
"ExtremeHills", "ColdTaiga_beach",
"BirchForest", "ColdTaiga_beach_water",
"MegaSpruceTaiga", "MegaTaiga",
"MegaTaiga", "MegaSpruceTaiga",
"ExtremeHills+", "ExtremeHills",
"Forest", "ExtremeHills_beach",
"Plains", "ExtremeHillsM",
"ColdTaiga", "ExtremeHills+",
"SunflowerPlains", "ExtremeHills+_snowtop",
"RoofedForest", "StoneBeach",
"MesaPlateauFM_grasstop", "Plains",
"ExtremeHillsM", "Plains_beach",
"BirchForestM", "SunflowerPlains",
"Taiga",
"Taiga_beach",
"Forest",
"Forest_beach",
"FlowerForest",
"FlowerForest_beach",
"BirchForest",
"BirchForestM",
"RoofedForest",
"Savanna",
"Savanna_beach",
"SavannaM",
"Jungle",
"Jungle_shore",
"JungleM",
"JungleM_shore",
"JungleEdge",
"JungleEdgeM",
"Swampland",
"Swampland_shore"
}, },
0, 0,
minetest.LIGHT_MAX+1, minetest.LIGHT_MAX+1,

@ -14,6 +14,27 @@ local function on_blast(pos)
minetest.remove_node(pos) minetest.remove_node(pos)
end 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
else
return stack:get_count()
end
end
local function barrel_open(pos, node, clicker) local function barrel_open(pos, node, clicker)
local name = minetest.get_meta(pos):get_string("name") local name = minetest.get_meta(pos):get_string("name")
@ -82,7 +103,6 @@ minetest.register_node("mcl_barrels:barrel_closed", {
tiles = {"mcl_barrels_barrel_top.png^[transformR270", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"}, tiles = {"mcl_barrels_barrel_top.png^[transformR270", "mcl_barrels_barrel_bottom.png", "mcl_barrels_barrel_side.png"},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
--on_place = mcl_util.rotate_axis,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
minetest.rotate_and_place(itemstack, placer, pointed_thing, minetest.is_creative_enabled(placer:get_player_name()), {}, false) minetest.rotate_and_place(itemstack, placer, pointed_thing, minetest.is_creative_enabled(placer:get_player_name()), {}, false)
return itemstack return itemstack
@ -98,6 +118,21 @@ minetest.register_node("mcl_barrels:barrel_closed", {
after_place_node = function(pos, placer, itemstack, pointed_thing) after_place_node = function(pos, placer, itemstack, pointed_thing)
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name")) minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
end, 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 barrel 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 barrel 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 barrel at "..minetest.pos_to_string(pos))
end,
after_dig_node = drop_content, after_dig_node = drop_content,
on_blast = on_blast, on_blast = on_blast,
on_rightclick = barrel_open, on_rightclick = barrel_open,
@ -119,6 +154,21 @@ minetest.register_node("mcl_barrels:barrel_open", {
stack_max = 64, stack_max = 64,
sounds = mcl_sounds.node_sound_wood_defaults(), sounds = mcl_sounds.node_sound_wood_defaults(),
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1}, groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1},
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 barrel 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 barrel 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 barrel at "..minetest.pos_to_string(pos))
end,
after_dig_node = drop_content, after_dig_node = drop_content,
on_blast = on_blast, on_blast = on_blast,
on_rightclick = barrel_open, on_rightclick = barrel_open,

@ -75,7 +75,7 @@ for _, row in ipairs(wool.dyes) do
tiles = {texture..".png"}, tiles = {texture..".png"},
wield_image = texture..".png", wield_image = texture..".png",
wield_scale = { x=1, y=1, z=0.5 }, wield_scale = { x=1, y=1, z=0.5 },
groups = {handy=1, carpet=1,attached_node=1,flammable=1,fire_encouragement=60, fire_flammability=20, dig_by_water=1,deco_block=1,[color_group]=1}, groups = {handy=1, carpet=1,supported_node=1,flammable=1,fire_encouragement=60, fire_flammability=20, dig_by_water=1,deco_block=1,[color_group]=1},
sounds = mcl_sounds.node_sound_wool_defaults(), sounds = mcl_sounds.node_sound_wool_defaults(),
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,

@ -35,8 +35,8 @@ local function player_collision(player)
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
if object and (object:is_player() local ent = object:get_luaentity()
or (object:get_luaentity()._cmi_is_mob == true and object ~= player)) then if (object:is_player() or (ent and ent._cmi_is_mob and object ~= player)) then
local pos2 = object:get_pos() local pos2 = object:get_pos()
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}