Merge branch 'master' into api-cauldrons

This commit is contained in:
AFCMS 2021-03-27 11:35:24 +01:00
commit b4033ddfc9
68 changed files with 1365 additions and 1166 deletions

View File

@ -6,7 +6,7 @@ block has a hardness and the actual Minecraft digging time is determined by
this:
1) The block's hardness
2) The tool being used (the tool_multiplier and its efficiency level)
2) The tool being used (the tool speed and its efficiency level)
3) Whether the tool is considered as "eligible" for the block
(e.g. only diamond pick eligible for obsidian)
@ -43,13 +43,13 @@ this field is a table which defines which groups the tool can dig and how
efficiently.
_mcl_diggroups = {
handy = { tool_multiplier = 1, level = 1, uses = 0 },
pickaxey = { tool_multiplier = 1, level = 0, uses = 0 },
handy = { speed = 1, level = 1, uses = 0 },
pickaxey = { speed = 1, level = 0, uses = 0 },
}
The "uses" field indicate how many uses (0 for infinite) a tool has when used on
the specified digging group. The "tool_multiplier" field is a multiplier to the
dig speed on that digging group.
the specified digging group. The "speed" field is a multiplier to the dig speed
on that digging group.
The "level" field indicates which levels of the group the tool can harvest. A
level of 0 means that the tool cannot harvest blocks of that node. A level of 1
@ -69,6 +69,8 @@ This also means that it is very important that no mod adds _mcl_autogroup as a
dependency.
--]]
assert(minetest.get_modpath("mcl_autogroup"), "This mod requires the mod mcl_autogroup to function")
-- Returns a table containing the unique "_mcl_hardness" for nodes belonging to
-- each diggroup.
local function get_hardness_values_for_groups()
@ -135,19 +137,18 @@ end
-- Parameters:
-- group - the group which it is digging
-- can_harvest - if the tool can harvest the block
-- tool_multiplier - dig speed multiplier for tool (default 1)
-- speed - dig speed multiplier for tool (default 1)
-- efficiency - efficiency level for the tool if applicable
local function get_digtimes(group, can_harvest, tool_multiplier, efficiency)
tool_multiplier = tool_multiplier or 1
local speed_multiplier = tool_multiplier
local function get_digtimes(group, can_harvest, speed, efficiency)
local speed = speed or 1
if efficiency then
speed_multiplier = speed_multiplier + efficiency * efficiency + 1
speed = speed + efficiency * efficiency + 1
end
local digtimes = {}
for index, hardness in pairs(hardness_values[group]) do
local digtime = (hardness or 0) / speed_multiplier
local digtime = (hardness or 0) / speed
if can_harvest then
digtime = digtime * 1.5
else
@ -177,8 +178,12 @@ end
-- Add the groupcaps from a field in "_mcl_diggroups" to the groupcaps of a
-- tool.
local function add_groupcaps(toolname, groupcaps, groupcaps_def, efficiency)
if not groupcaps_def then
return
end
for g, capsdef in pairs(groupcaps_def) do
local mult = capsdef.tool_multiplier or 1
local mult = capsdef.speed or 1
local uses = capsdef.uses
local def = mcl_autogroup.registered_diggroups[g]
local max_level = def.levels and #def.levels or 1
@ -195,7 +200,6 @@ local function add_groupcaps(toolname, groupcaps, groupcaps_def, efficiency)
groupcaps[g .. "_dig"] = get_groupcap(g, level > 0, mult, efficiency, uses)
end
end
return groupcaps
end
-- Checks if the given node would drop its useful drop if dug by a given tool.
@ -209,7 +213,7 @@ function mcl_autogroup.can_harvest(nodename, toolname)
-- Check if it can be dug by tool
local tdef = minetest.registered_tools[toolname]
if tdef then
if tdef and tdef._mcl_diggroups then
for g, gdef in pairs(tdef._mcl_diggroups) do
if ndef.groups[g] then
if ndef.groups[g] <= gdef.level then

View File

@ -12,6 +12,8 @@ as possible. Minetest loads mods in reverse alphabetical order.
mcl_autogroup = {}
mcl_autogroup.registered_diggroups = {}
assert(minetest.get_modpath("_mcl_autogroup"), "This mod requires the mod _mcl_autogroup to function")
-- Register a group as a digging group.
--
-- Parameters:

View File

@ -33,25 +33,26 @@ mcl_vars.MAP_BLOCKSIZE = math.max(1, core.MAP_BLOCKSIZE or 16)
mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, core.MAX_MAP_GENERATION_LIMIT or 31000)
local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2)
local chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
mcl_vars.central_chunk_offset_in_nodes = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
mcl_vars.chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
local central_chunk_max_pos = central_chunk_min_pos + chunk_size_in_nodes - 1
local central_chunk_max_pos = central_chunk_min_pos + mcl_vars.chunk_size_in_nodes - 1
local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes
local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE)
local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * chunk_size_in_nodes
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * chunk_size_in_nodes
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / mcl_vars.chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / mcl_vars.chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * mcl_vars.chunk_size_in_nodes
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * mcl_vars.chunk_size_in_nodes
local function coordinate_to_block(x)
return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
end
local function coordinate_to_chunk(x)
return math.floor((coordinate_to_block(x) + central_chunk_offset) / mcl_vars.chunksize)
return math.floor((coordinate_to_block(x) - central_chunk_offset) / mcl_vars.chunksize)
end
function mcl_vars.pos_to_block(pos)
@ -70,7 +71,7 @@ function mcl_vars.pos_to_chunk(pos)
}
end
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / chunk_size_in_nodes)
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / mcl_vars.chunk_size_in_nodes)
local k_positive_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z

View File

@ -6,7 +6,7 @@ mcl_worlds = {}
function mcl_worlds.is_in_void(pos)
local void =
not ((pos.y < mcl_vars.mg_overworld_max and pos.y > mcl_vars.mg_overworld_min) or
(pos.y < mcl_vars.mg_nether_max and pos.y > mcl_vars.mg_nether_min) or
(pos.y < mcl_vars.mg_nether_max+128 and pos.y > mcl_vars.mg_nether_min) or
(pos.y < mcl_vars.mg_end_max and pos.y > mcl_vars.mg_end_min))
local void_deadly = false
@ -15,11 +15,11 @@ function mcl_worlds.is_in_void(pos)
-- Overworld → Void → End → Void → Nether → Void
if pos.y < mcl_vars.mg_overworld_min and pos.y > mcl_vars.mg_end_max then
void_deadly = pos.y < mcl_vars.mg_overworld_min - deadly_tolerance
elseif pos.y < mcl_vars.mg_end_min and pos.y > mcl_vars.mg_nether_max then
elseif pos.y < mcl_vars.mg_end_min and pos.y > mcl_vars.mg_nether_max+128 then
-- The void between End and Nether. Like usual, but here, the void
-- *above* the Nether also has a small tolerance area, so player
-- can fly above the Nether without getting hurt instantly.
void_deadly = (pos.y < mcl_vars.mg_end_min - deadly_tolerance) and (pos.y > mcl_vars.mg_nether_max + deadly_tolerance)
void_deadly = (pos.y < mcl_vars.mg_end_min - deadly_tolerance) and (pos.y > mcl_vars.mg_nether_max+128 + deadly_tolerance)
elseif pos.y < mcl_vars.mg_nether_min then
void_deadly = pos.y < mcl_vars.mg_nether_min - deadly_tolerance
end
@ -35,7 +35,7 @@ end
function mcl_worlds.y_to_layer(y)
if y >= mcl_vars.mg_overworld_min then
return y - mcl_vars.mg_overworld_min, "overworld"
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max then
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max+128 then
return y - mcl_vars.mg_nether_min, "nether"
elseif y >= mcl_vars.mg_end_min and y <= mcl_vars.mg_end_max then
return y - mcl_vars.mg_end_min, "end"
@ -73,7 +73,7 @@ end
-- Takes a position and returns true if this position can have Nether dust
function mcl_worlds.has_dust(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_nether_max + 64 and pos.y >= mcl_vars.mg_nether_min - 64
return pos.y <= mcl_vars.mg_nether_max + 138 and pos.y >= mcl_vars.mg_nether_min - 10
end
-- Takes a position (pos) and returns true if compasses are working here

View File

@ -247,7 +247,7 @@ function boat.on_step(self, dtime, moveresult)
else
local ctrl = self._passenger:get_player_control()
if ctrl and ctrl.sneak then
detach_player(self._passenger, true)
detach_object(self._passenger, true)
self._passenger = nil
end
end

View File

@ -167,7 +167,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
hud_elem_type = "image",
position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100},
text = "mcl_burning_hud_flame_animated.png",
text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1,
z_index = 1000,
}) + 1
end

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator("mcl_falling_nodes")
local dmes = minetest.get_modpath("mcl_death_messages") ~= nil
local has_mcl_armor = minetest.get_modpath("mcl_armor")
local his_creative_enabled = minetest.is_creative_enabled
local get_falling_depth = function(self)
if not self._startpos then
@ -13,9 +16,8 @@ local deal_falling_damage = function(self, dtime)
if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then
return
end
-- Cause damage to any player it hits.
-- Cause damage to any entity it hits.
-- Algorithm based on MC anvils.
-- TODO: Support smashing other objects, too.
local pos = self.object:get_pos()
if not self._startpos then
-- Fallback
@ -23,12 +25,13 @@ local deal_falling_damage = function(self, dtime)
end
local objs = minetest.get_objects_inside_radius(pos, 1)
for _,v in ipairs(objs) do
if v:is_player() then
local hp = v:get_hp()
if v:is_player() and hp ~= 0 then
local name = v:get_player_name()
if hp ~= 0 then
if not self._hit_players then
self._hit_players = {}
end
local name = v:get_player_name()
local hit = false
for _,v in ipairs(self._hit_players) do
if name == v then
@ -45,8 +48,16 @@ local deal_falling_damage = function(self, dtime)
if hp < 0 then
hp = 0
end
if v:is_player() then
-- TODO: Reduce damage if wearing a helmet
-- Reduce damage if wearing a helmet
local inv = v:get_inventory()
local helmet = inv:get_stack("armor", 2)
if has_mcl_armor and not helmet:is_empty() then
hp = hp/4*3
if not his_creative_enabled(name) then
helmet:add_wear(65535/helmet:get_definition().groups.mcl_armor_uses) --TODO: be sure damage is exactly like mc (informations are missing in the mc wiki)
inv:set_stack("armor", 2, helmet)
end
end
local msg
if minetest.get_item_group(self.node.name, "anvil") ~= 0 then
msg = S("@1 was smashed by a falling anvil.", v:get_player_name())
@ -56,11 +67,38 @@ local deal_falling_damage = function(self, dtime)
if dmes then
mcl_death_messages.player_damage(v, msg)
end
end
v:set_hp(hp, { type = "punch", from = "mod" })
end
end
end
else
local hp = v:get_luaentity().health
if hp and hp ~= 0 then
if not self._hit_mobs then
self._hit_mobs = {}
end
local hit = false
for _,mob in ipairs(self._hit_mobs) do
if v == mob then
hit = true
end
end
--TODO: reduce damage for mobs then they will be able to wear armor
if not hit then
table.insert(self._hit_mobs, v)
local way = self._startpos.y - pos.y
local damage = (way - 1) * 2
damage = math.min(40, math.max(0, damage))
if damage >= 1 then
hp = hp - damage
if hp < 0 then
hp = 0
end
v:get_luaentity().health = hp
end
end
end
end
end
end

View File

@ -165,10 +165,6 @@ minetest.register_globalstep(function(dtime)
end
end)
local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
local basegroups = { "pickaxey", "axey", "shovely" }
local materials = { "wood", "gold", "stone", "iron", "diamond" }
-- Stupid workaround to get drops from a drop table:
-- Create a temporary table in minetest.registered_nodes that contains the proper drops,
-- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition

View File

@ -283,6 +283,33 @@ local get_velocity = function(self)
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 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]
end
self.object:set_properties({collisionbox = cbox})
end
-- set and return valid yaw
local set_yaw = function(self, yaw, delay, dtime)
@ -298,6 +325,7 @@ local set_yaw = function(self, yaw, delay, dtime)
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
end
self.object:set_yaw(yaw)
update_roll(self)
return yaw
end
@ -645,9 +673,9 @@ local update_tag = function(self)
nametag = tag,
})
update_roll(self)
end
-- drop items
local item_drop = function(self, cooked, looting_level)
@ -2826,7 +2854,7 @@ local falling = function(self, pos)
end
if mcl_portals ~= nil then
if mcl_portals.nether_portal_cooloff[self.object] 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
@ -2856,6 +2884,18 @@ local falling = function(self, pos)
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
@ -3475,6 +3515,7 @@ local mob_step = function(self, dtime)
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
end
self.object:set_yaw(yaw)
update_roll(self)
end
-- end rotation
@ -3773,6 +3814,7 @@ minetest.register_entity(name, {
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,

View File

@ -25,6 +25,19 @@ local colors = {
unicolor_black = { mobs_mc.items.wool_black, "#000000D0" },
}
local rainbow_colors = {
"unicolor_light_red",
"unicolor_red",
"unicolor_orange",
"unicolor_yellow",
"unicolor_green",
"unicolor_dark_green",
"unicolor_light_blue",
"unicolor_blue",
"unicolor_violet",
"unicolor_red_violet"
}
if minetest.get_modpath("mcl_wool") ~= nil then
colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" }
end
@ -112,7 +125,7 @@ mobs:register_mob("mobs_mc:sheep", {
end,
-- Set random color on spawn
do_custom = function(self)
do_custom = function(self, dtime)
if not self.initial_color_set then
local r = math.random(0,100000)
local textures
@ -149,6 +162,33 @@ mobs:register_mob("mobs_mc:sheep", {
}
self.initial_color_set = true
end
local is_kay27 = self.nametag == "kay27"
if self.color_change_timer then
local old_color = self.color
if is_kay27 then
self.color_change_timer = self.color_change_timer - dtime
if self.color_change_timer < 0 then
self.color_change_timer = 0.5
self.color_index = (self.color_index + 1) % #rainbow_colors
self.color = rainbow_colors[self.color_index + 1]
end
else
self.color_change_timer = nil
self.color_index = nil
self.color = self.initial_color
end
if old_color ~= self.color then
self.base_texture = sheep_texture(self.color)
self.object:set_properties({textures = self.base_texture})
end
elseif is_kay27 then
self.initial_color = self.color
self.color_change_timer = 0
self.color_index = -1
end
end,
on_rightclick = function(self, clicker)

View File

@ -109,7 +109,6 @@ local slime_big = {
fear_height = 0,
spawn_small_alternative = "mobs_mc:slime_small",
on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5),
fire_resistant = true,
use_texture_alpha = true,
}
mobs:register_mob("mobs_mc:slime_big", slime_big)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -967,6 +967,10 @@ mobs:register_mob("mobs_mc:villager", {
drops = {},
can_despawn = false,
-- TODO: sounds
sounds = {
random = "mobs_mc_villager",
distance = 10,
},
animation = {
stand_speed = 25,
stand_start = 40,

View File

@ -38,6 +38,7 @@ mcl_weather.reg_weathers["none"] = {
local storage = minetest.get_mod_storage()
-- Save weather into mod storage, so it can be loaded after restarting the server
local save_weather = function()
if not mcl_weather.end_time then return end
storage:set_string("mcl_weather_state", mcl_weather.state)
storage:set_int("mcl_weather_end_time", mcl_weather.end_time)
minetest.log("verbose", "[mcl_weather] Weather data saved: state="..mcl_weather.state.." end_time="..mcl_weather.end_time)

View File

@ -2,6 +2,7 @@ tt = {}
tt.COLOR_DEFAULT = "#d0ffd0"
tt.COLOR_DANGER = "#ffff00"
tt.COLOR_GOOD = "#00ff00"
tt.NAME_COLOR = "#FFFF4C"
-- API
tt.registered_snippets = {}
@ -63,12 +64,15 @@ tt.reload_itemstack_description = function(itemstack)
local meta = itemstack:get_meta()
if def and def._mcl_generate_description then
def._mcl_generate_description(itemstack)
elseif should_change(itemstring, def) and meta:get_string("name") == "" then
elseif should_change(itemstring, def) then
local toolcaps
if def.tool_capabilities then
toolcaps = itemstack:get_tool_capabilities()
end
local orig_desc = def._tt_original_description or def.description
if meta:get_string("name") ~= "" then
orig_desc = minetest.colorize(tt.NAME_COLOR, meta:get_string("name"))
end
local desc = apply_snippets(orig_desc, itemstring, toolcaps or def.tool_capabilities, itemstack)
if desc ~= orig_desc then
meta:set_string("description", desc)

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator("mcl_death_messages")
local N = function(s) return s end
local C = minetest.colorize
local color_skyblue = mcl_colors.AQUA
local function get_tool_name(item)
local name = item:get_meta():get_string("name")
@ -41,6 +44,9 @@ local msgs = {
["murder"] = {
N("@1 was slain by @2 using [@3]"),
},
["murder_hand"] = {
N("@1 was slain by @2"),
},
["murder_any"] = {
N("@1 was killed."),
},
@ -131,7 +137,7 @@ local last_damages = { }
minetest.register_on_dieplayer(function(player, reason)
-- Death message
local message = minetest.settings:get_bool("mcl_showDeathMessages")
local message = minetest.settings:get_bool("mcl_showDeathMessages") --Maybe cache the setting?
if message == nil then
message = true
end
@ -201,7 +207,11 @@ minetest.register_on_dieplayer(function(player, reason)
elseif hitter:is_player() then
hittername = hitter:get_player_name()
if hittername ~= nil then
msg = dmsg("murder", name, hittername, minetest.colorize("#00FFFF", hitter_toolname))
if hitter_toolname == "" then
msg = dmsg("murder_hand", name, hittername)
else
msg = dmsg("murder", name, hittername, C(color_skyblue, hitter_toolname))
end
else
msg = dmsg("murder_any", name)
end
@ -229,7 +239,7 @@ minetest.register_on_dieplayer(function(player, reason)
if shooter == nil then
msg = dmsg("arrow", name)
elseif shooter:is_player() then
msg = dmsg("arrow_name", name, shooter:get_player_name(), minetest.colorize("#00FFFF", get_tool_name(shooter:get_wielded_item())))
msg = dmsg("arrow_name", name, shooter:get_player_name(), C(color_skyblue, get_tool_name(shooter:get_wielded_item())))
elseif s_ent and s_ent._cmi_is_mob then
if s_ent.nametag ~= "" then
msg = dmsg("arrow_name", name, shooter:get_player_name(), get_tool_name(shooter:get_wielded_item()))

View File

@ -56,3 +56,4 @@ A ghast scared @1 to death.=Ein Ghast hat @1 zu Tode erschrocken.
@1 was killed by a baby husk.=@1 wurde von einem Wüstenzombiebaby getötet.
@1 was killed by a zombie pigman.=@1 wurde von einem Schweinezombie getötet.
@1 was killed by a baby zombie pigman.=@1 wurde von einem Schweinezombiebaby getötet.
@1 was slain by @2.=

View File

@ -55,3 +55,4 @@ A ghast scared @1 to death.=Se ha asustado @1 hasta morir.
@1 was killed by a baby husk.=@1 fue asesinado por un bebé husk.
@1 was killed by a zombie pigman.=@1 fue asesinado por un cerdo zombie.
@1 was killed by a baby zombie pigman.=@1 fue asesinado por un bebé cerdo zombie.
@1 was slain by @2.=

View File

@ -56,3 +56,4 @@ A ghast scared @1 to death.=Un ghast a éffrayé @1 à mort.
@1 was killed by a baby husk.=@1 a été tué par un bébé zombie momie.
@1 was killed by a zombie pigman.=@1 a été tué par un zombie-couchon.
@1 was killed by a baby zombie pigman.=@1 a été tué par un bébé zombie-couchon
@1 was slain by @2.=

View File

@ -56,3 +56,4 @@ A ghast scared @1 to death.=Гаст напугал @1 до смерти.
@1 was killed by a baby husk.=@1 был(а) убит(а) машылом-кадавром.
@1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком.
@1 was killed by a baby zombie pigman.=@1 был(а) убит(а) малышом-зомби-свиночеловеком.
@1 was slain by @2.=

View File

@ -56,3 +56,4 @@ A ghast scared @1 to death.=
@1 was killed by a baby husk.=
@1 was killed by a zombie pigman.=
@1 was killed by a baby zombie pigman.=
@1 was slain by @2.=

View File

@ -1,3 +1,4 @@
name = mcl_death_messages
author = 4Evergreen4
description = Shows messages in chat when a player dies.
depends = mcl_colors

View File

@ -489,8 +489,8 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
if filter == nil then
filter = ""
end
formspec = formspec .. "field[5.3,1.34;4,0.75;suche;;"..minetest.formspec_escape(filter).."]"
formspec = formspec .. "field_close_on_enter[suche;false]"
formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]"
formspec = formspec .. "field_close_on_enter[search;false]"
end
if pagenum ~= nil then formspec = formspec .. "p"..tostring(pagenum) end
@ -561,11 +561,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
elseif fields.inv then
if players[name].page == "inv" then return end
page = "inv"
elseif fields.suche == "" and not fields.creative_next and not fields.creative_prev then
elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then
set_inv_page("all", player)
page = "nix"
elseif fields.suche ~= nil and not fields.creative_next and not fields.creative_prev then
set_inv_search(string.lower(fields.suche),player)
elseif fields.search ~= nil and not fields.creative_next and not fields.creative_prev then
set_inv_search(string.lower(fields.search),player)
page = "nix"
end
@ -612,8 +612,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
players[name].start_i = start_i
local filter = ""
if not fields.nix and fields.suche ~= nil and fields.suche ~= "" then
filter = fields.suche
if not fields.nix and fields.search ~= nil and fields.search ~= "" then
filter = fields.search
players[name].filter = filter
end

View File

@ -0,0 +1,7 @@
# mcl_temp_message
Allow mods to show short messages in the hud of players.
## mcl_tmp_message.message(player, message)
Show above the hotbar a hud message <message> to player <player>.

View File

@ -1,6 +1,11 @@
local S = minetest.get_translator("mesecons_commandblock")
local F = minetest.formspec_escape
local color_red = mcl_colors.RED
local command_blocks_activated = minetest.settings:get_bool("mcl_enable_commandblocks", true)
local msg_not_activated = S("Command blocks are not enabled on this server")
local function construct(pos)
local meta = minetest.get_meta(pos)
@ -78,7 +83,7 @@ local function check_commands(commands, player_name)
if string.sub(cmd, 1, 1) == "/" then
msg = S("Error: The command “@1” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands. Hint: Try to remove the leading slash.", cmd)
end
return false, minetest.colorize("#FF0000", msg)
return false, minetest.colorize(color_red, msg)
end
if player_name then
local player_privs = minetest.get_player_privs(player_name)
@ -86,7 +91,7 @@ local function check_commands(commands, player_name)
for cmd_priv, _ in pairs(cmddef.privs) do
if player_privs[cmd_priv] ~= true then
local msg = S("Error: You have insufficient privileges to use the command “@1” (missing privilege: @2)! The command block has not been changed.", cmd, cmd_priv)
return false, minetest.colorize("#FF0000", msg)
return false, minetest.colorize(color_red, msg)
end
end
end
@ -99,9 +104,14 @@ local function commandblock_action_on(pos, node)
return
end
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
local meta = minetest.get_meta(pos)
local commander = meta:get_string("commander")
if not command_blocks_activated then
--minetest.chat_send_player(commander, msg_not_activated)
return
end
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
local commands = resolve_commands(meta:get_string("commands"), pos)
for _, command in pairs(commands:split("\n")) do
@ -117,7 +127,6 @@ local function commandblock_action_on(pos, node)
return
end
-- Execute command in the name of commander
local commander = meta:get_string("commander")
cmddef.func(commander, param)
end
end
@ -129,6 +138,10 @@ local function commandblock_action_off(pos, node)
end
local on_rightclick = function(pos, node, player, itemstack, pointed_thing)
if not command_blocks_activated then
minetest.chat_send_player(player:get_player_name(), msg_not_activated)
return
end
local can_edit = true
-- Only allow write access in Creative Mode
if not minetest.is_creative_enabled(player:get_player_name()) then

View File

@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=Zugr
Editing the command block has failed! You can only change the command block in Creative Mode!=Bearbeitung des Befehlsblocks fehlgeschlagen! Sie können den Befehlsblock nur im Kreativmodus ändern!
Editing the command block has failed! The command block is gone.=Bearbeiten des Befehlsblocks fehlgeschlagen! Der Befehlsblock ist verschwunden.
Executes server commands when powered by redstone power=Führt Serverbefehle aus, wenn mit Redstoneenergie versorgt
Command blocks are not enabled on this server=

View File

@ -28,3 +28,4 @@ Example 2:@n give @@n mcl_core:apple 5@nGives the nearest player 5 apples=2.
Access denied. You need the “maphack” privilege to edit command blocks.=Acceso denegado. Necesita el privilegio "maphack" para editar bloques de comandos.
Editing the command block has failed! You can only change the command block in Creative Mode!=¡La edición del bloque de comando ha fallado! ¡Solo puede cambiar el bloque de comandos en modo creativo!
Editing the command block has failed! The command block is gone.=¡La edición del bloque de comando ha fallado! El bloque de comando se ha ido.
Command blocks are not enabled on this server=

View File

@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=Acc
Editing the command block has failed! You can only change the command block in Creative Mode!=La modification du bloc de commandes a échoué! Vous ne pouvez modifier le bloc de commandes qu'en mode créatif!
Editing the command block has failed! The command block is gone.=La modification du bloc de commandes a échoué! Le bloc de commande a disparu.
Executes server commands when powered by redstone power=Exécute les commandes du serveur lorsqu'il est alimenté par l'alimentation Redstone
Command blocks are not enabled on this server=Les blocks de commandes ne sont pas activés sur ce serveur

View File

@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=До
Editing the command block has failed! You can only change the command block in Creative Mode!=Попытка редактирования командного блока потерпела неудачу. Вы можете изменять командные блоки только в творческом режиме!
Editing the command block has failed! The command block is gone.=Попытка редактирования командного блока потерпела неудачу. Командный блок исчез.
Executes server commands when powered by redstone power=При подаче энергии редстоуна выполняет серверные команды
Command blocks are not enabled on this server=

View File

@ -27,3 +27,4 @@ Access denied. You need the “maphack” privilege to edit command blocks.=
Editing the command block has failed! You can only change the command block in Creative Mode!=
Editing the command block has failed! The command block is gone.=
Executes server commands when powered by redstone power=
Command blocks are not enabled on this server=

View File

@ -1,3 +1,3 @@
name = mesecons_commandblock
depends = mesecons
depends = mesecons, mcl_colors
optional_depends = doc, doc_items

View File

@ -9,7 +9,6 @@ local MATERIAL_TOOL_REPAIR_BOOST = {
math.ceil(MAX_WEAR * 0.75), -- 75%
MAX_WEAR, -- 100%
}
local NAME_COLOR = "#FFFF4C"
local function get_anvil_formspec(set_name)
if not set_name then
@ -172,14 +171,8 @@ local function update_anvil_slots(meta)
if new_name ~= old_name then
-- Save the raw name internally
meta:set_string("name", new_name)
-- Rename item
if new_name == "" then
-- Rename item handled by tt
tt.reload_itemstack_description(name_item)
else
-- Custom name set. Colorize it!
-- This makes the name visually different from unnamed items
meta:set_string("description", minetest.colorize(NAME_COLOR, new_name))
end
new_output = name_item
elseif just_rename then
new_output = ""
@ -495,7 +488,6 @@ S("The anvil has limited durability and 3 damage levels: undamaged, slightly dam
local anvildef1 = table.copy(anvildef)
anvildef1.description = S("Slightly Damaged Anvil")
anvildef1._doc_items_create_entry = false
anvildef1.groups.not_in_creative_inventory = 1
anvildef1.groups.anvil = 2
anvildef1._doc_items_create_entry = false
anvildef1.tiles = {"mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}
@ -503,7 +495,6 @@ anvildef1.tiles = {"mcl_anvils_anvil_top_damaged_1.png^[transformR90", "mcl_anvi
local anvildef2 = table.copy(anvildef)
anvildef2.description = S("Very Damaged Anvil")
anvildef2._doc_items_create_entry = false
anvildef2.groups.not_in_creative_inventory = 1
anvildef2.groups.anvil = 3
anvildef2._doc_items_create_entry = false
anvildef2.tiles = {"mcl_anvils_anvil_top_damaged_2.png^[transformR90", "mcl_anvils_anvil_base.png", "mcl_anvils_anvil_side.png"}

View File

@ -16,23 +16,17 @@ local dir_to_pitch = function(dir)
end
local random_arrow_positions = function(positions, placement)
local min = 0
local max = 0
if positions == 'x' then
min = -4
max = 4
return math.random(-4, 4)
elseif positions == 'y' then
min = 0
max = 10
return math.random(0, 10)
end
if placement == 'front' and positions == 'z' then
min = 3
max = 3
return 3
elseif placement == 'back' and positions == 'z' then
min = -3
max = -3
return -3
end
return math.random(max, min)
return 0
end
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
@ -304,8 +298,8 @@ ARROW_ENTITY.on_step = function(self, dtime)
else
self._attach_parent = 'Body'
end
self._z_rotation = math.random(30, -30)
self._y_rotation = math.random(30, -30)
self._z_rotation = math.random(-30, 30)
self._y_rotation = math.random( -30, 30)
self.object:set_attach(obj, self._attach_parent, {x=self._x_position,y=self._y_position,z=random_arrow_positions('z', placement)}, {x=0,y=self._rotation_station + self._y_rotation,z=self._z_rotation})
minetest.after(150, function()
self.object:remove()

View File

@ -19,7 +19,7 @@ function mcl_cocoas.place(itemstack, placer, pt, plantname)
-- Am I right-clicking on something that has a custom on_rightclick set?
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[under.name] and minetest.registered_nodes[under.name].on_rightclick then
return minetest.registered_nodes[under.name].on_rightclick(pointed_thing.under, under, placer, itemstack) or itemstack
return minetest.registered_nodes[under.name].on_rightclick(pt.under, under, placer, itemstack) or itemstack
end
end

View File

@ -14,7 +14,7 @@ mcl_autogroup.register_diggroup("shearsy_wool")
mcl_autogroup.register_diggroup("shearsy_cobweb")
mcl_autogroup.register_diggroup("swordy")
mcl_autogroup.register_diggroup("swordy_cobweb")
mcl_autogroup.register_diggroup("creative_breakable")
mcl_autogroup.register_diggroup("hoey")
-- Load files
local modpath = minetest.get_modpath("mcl_core")

View File

@ -808,7 +808,7 @@ minetest.register_node("mcl_core:obsidian", {
description = S("Obsidian"),
_doc_items_longdesc = S("Obsidian is an extremely hard mineral with an enourmous blast-resistance. Obsidian is formed when water meets lava."),
tiles = {"default_obsidian.png"},
is_ground_content = true,
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
stack_max = 64,
groups = {pickaxey=5, building_block=1, material_stone=1},

View File

@ -108,7 +108,19 @@ local register_leaves = function(subname, description, longdesc, tiles, sapling,
tiles = tiles,
paramtype = "light",
stack_max = 64,
groups = {handy=1,shearsy=1,swordy=1, leafdecay=leafdecay_distance, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60},
groups = {
handy=1,
hoey=1,
shearsy=1,
swordy=1,
leafdecay=leafdecay_distance,
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(),

View File

@ -582,7 +582,12 @@ function mcl_enchanting.allow_inventory_action(player, action, inventory, invent
local listname = inventory_info.to_list
local stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index)
if stack:get_name() == "mcl_dye:blue" and listname ~= "enchanting_item" then
return math.min(inventory:get_stack("enchanting_lapis", 1):get_free_space(), stack:get_count())
local count = stack:get_count()
local old_stack = inventory:get_stack("enchanting_lapis", 1)
if old_stack:get_name() ~= "" then
count = math.min(count, old_stack:get_free_space())
end
return count
elseif inventory:get_stack("enchanting_item", 1):get_count() == 0 and listname ~= "enchanting_lapis" then
return 1
else

View File

@ -45,6 +45,10 @@ end
-- To make it more efficient it will first check a hash value to determine if
-- the tool needs to be updated.
function mcl_enchanting.update_groupcaps(itemstack)
if not itemstack:get_meta():get("tool_capabilities") then
return
end
local name = itemstack:get_name()
local level = mcl_enchanting.get_enchantment(itemstack, "efficiency")
local groupcaps = get_efficiency_groupcaps(name, level)

View File

@ -29,7 +29,7 @@ minetest.register_entity("mcl_end:ender_eye", {
if self._age >= 3 then
-- End of life
local r = math.random(1,5)
if r == 1 or minetest.is_creative_enabled("") then
if r == 1 then
-- 20% chance to get destroyed completely.
-- 100% if in Creative Mode
self.object:remove()

View File

@ -78,6 +78,9 @@ minetest.register_tool("mcl_farming:hoe_wood", {
},
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
hoey = { speed = 2, level = 1, uses = 60 }
},
})
minetest.register_craft({
@ -118,6 +121,9 @@ minetest.register_tool("mcl_farming:hoe_stone", {
},
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
hoey = { speed = 4, level = 3, uses = 132 }
},
})
minetest.register_craft({
@ -154,6 +160,9 @@ minetest.register_tool("mcl_farming:hoe_iron", {
},
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
hoey = { speed = 6, level = 4, uses = 251 }
},
})
minetest.register_craft({
@ -196,6 +205,9 @@ minetest.register_tool("mcl_farming:hoe_gold", {
},
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
hoey = { speed = 12, level = 2, uses = 33 }
},
})
minetest.register_craft({
@ -240,6 +252,9 @@ minetest.register_tool("mcl_farming:hoe_diamond", {
},
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
hoey = { speed = 8, level = 5, uses = 1562 }
},
})
minetest.register_craft({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 303 B

View File

@ -146,7 +146,7 @@ minetest.register_node("mcl_farming:hay_block", {
paramtype2 = "facedir",
is_ground_content = false,
on_place = mcl_util.rotate_axis,
groups = {handy=1, flammable=2, fire_encouragement=60, fire_flammability=20, building_block=1, fall_damage_add_percent=-80},
groups = {handy=1, hoey=1, flammable=2, fire_encouragement=60, fire_flammability=20, building_block=1, fall_damage_add_percent=-80},
sounds = mcl_sounds.node_sound_leaves_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 0.5,

View File

@ -173,7 +173,7 @@ local fish = function(itemstack, player, pointed_thing)
if noent == true then
local playerpos = player:get_pos()
local dir = player:get_look_dir()
local obj = mcl_throwing.throw("mcl_throwing:flying_bobber", {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, 15, player:get_player_name())
local obj = mcl_throwing.throw("mcl_fishing:flying_bobber", {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, 15, player:get_player_name())
end
end
@ -295,6 +295,52 @@ bobber_ENTITY.on_step = bobber_on_step
minetest.register_entity("mcl_fishing:bobber_entity", bobber_ENTITY)
local flying_bobber_ENTITY={
physical = false,
timer=0,
textures = {"mcl_fishing_bobber.png"}, --FIXME: Replace with correct texture.
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil,
objtype="fishing",
}
-- Movement function of flying bobber
local flying_bobber_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
--local player = minetest.get_player_by_name(self._thrower)
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and (def.walkable or def.liquidtype == "flowing" or def.liquidtype == "source")) or not def then
local make_child= function(object)
local ent = object:get_luaentity()
ent.player = self._thrower
ent.child = true
end
make_child(minetest.add_entity(self._lastpos, "mcl_fishing:bobber_entity"))
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
flying_bobber_ENTITY.on_step = flying_bobber_on_step
minetest.register_entity("mcl_fishing:flying_bobber_entity", flying_bobber_ENTITY)
mcl_throwing.register_throwable_object("mcl_fishing:flying_bobber", "mcl_fishing:flying_bobber_entity", 5)
-- If player leaves area, remove bobber.
minetest.register_on_leaveplayer(function(player)
local objs = minetest.get_objects_inside_radius(player:get_pos(), 250)
@ -449,7 +495,7 @@ minetest.register_craftitem("mcl_fishing:clownfish_raw", {
minetest.register_craftitem("mcl_fishing:pufferfish_raw", {
description = S("Pufferfish"),
_tt_help = minetest.colorize("#FFFF00", S("Very poisonous")),
_tt_help = minetest.colorize(mcl_colors.YELLOW, S("Very poisonous")),
_doc_items_longdesc = S("Pufferfish are a common species of fish and can be obtained by fishing. They can technically be eaten, but they are very bad for humans. Eating a pufferfish only restores 1 hunger point and will poison you very badly (which drains your health non-fatally) and causes serious food poisoning (which increases your hunger)."),
inventory_image = "mcl_fishing_pufferfish_raw.png",
on_place = minetest.item_eat(1),

View File

@ -1,3 +1,3 @@
name = mcl_fishing
description = Adds fish and fishing poles to go fishing.
depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting
depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing, mcl_colors

View File

@ -161,6 +161,12 @@ local function on_metadata_inventory_take(pos, listname, index, stack, player)
end
end
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
if from_list == "dst" then
give_xp(pos, player)
end
end
local function spawn_flames(pos, param2)
local minrelpos, maxrelpos
local dir = minetest.facedir_to_dir(param2)
@ -477,10 +483,12 @@ minetest.register_node("mcl_furnaces:furnace", {
give_xp(pos)
end,
on_metadata_inventory_move = function(pos)
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
-- Reset accumulated game time when player works with furnace:
furnace_reset_delta_time(pos)
minetest.get_node_timer(pos):start(1.0)
on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
end,
on_metadata_inventory_put = function(pos)
-- Reset accumulated game time when player works with furnace:
@ -494,9 +502,7 @@ minetest.register_node("mcl_furnaces:furnace", {
-- start timer function, it will helpful if player clears dst slot
minetest.get_node_timer(pos):start(1.0)
if listname == "dst" then
give_xp(pos, player)
end
on_metadata_inventory_take(pos, listname, index, stack, player)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
@ -552,6 +558,7 @@ minetest.register_node("mcl_furnaces:furnace_active", {
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
on_metadata_inventory_move = on_metadata_inventory_move,
on_metadata_inventory_take = on_metadata_inventory_take,
on_receive_fields = receive_fields,
_mcl_blast_resistance = 3.5,

View File

@ -176,7 +176,7 @@ minetest.register_node("mcl_nether:nether_wart_block", {
stack_max = 64,
tiles = {"mcl_nether_nether_wart_block.png"},
is_ground_content = false,
groups = {handy=1, building_block=1},
groups = {handy=1, hoey=1, building_block=1},
sounds = mcl_sounds.node_sound_leaves_defaults(
{
footstep={name="default_dirt_footstep", gain=0.7},

View File

@ -275,7 +275,7 @@ minetest.register_node("mcl_ocean:dried_kelp_block", {
description = S("Dried Kelp Block"),
_doc_items_longdesc = S("A decorative block that serves as a great furnace fuel."),
tiles = { "mcl_ocean_dried_kelp_top.png", "mcl_ocean_dried_kelp_bottom.png", "mcl_ocean_dried_kelp_side.png" },
groups = { handy = 1, building_block = 1, flammable = 2, fire_encouragement = 30, fire_flammability = 60 },
groups = { handy = 1, hoey = 1, building_block = 1, flammable = 2, fire_encouragement = 30, fire_flammability = 60 },
sounds = mcl_sounds.node_sound_leaves_defaults(),
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,

View File

@ -1,4 +1,4 @@
name = mcl_portals
description = Adds buildable portals to the Nether and End dimensions.
depends = mcl_init, mcl_worlds, mcl_core, mcl_nether, mcl_end, mcl_particles, mcl_spawn
depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn
optional_depends = awards, doc

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ minetest.register_node("mcl_sponges:sponge", {
buildable_to = false,
stack_max = 64,
sounds = mcl_sounds.node_sound_dirt_defaults(),
groups = {handy=1, building_block=1},
groups = {handy=1, hoey=1, building_block=1},
on_place = function(itemstack, placer, pointed_thing)
local pn = placer:get_player_name()
if pointed_thing.type ~= "node" then
@ -107,7 +107,7 @@ minetest.register_node("mcl_sponges:sponge_wet", {
buildable_to = false,
stack_max = 64,
sounds = mcl_sounds.node_sound_dirt_defaults(),
groups = {handy=1, building_block=1},
groups = {handy=1, hoey=1, building_block=1},
_mcl_blast_resistance = 0.6,
_mcl_hardness = 0.6,
})

View File

@ -0,0 +1,35 @@
# mcl_throwing
## mcl_throwing.throw(throw_item, pos, dir, velocity, thrower)
Throw a throwable item.
* throw_item: itemstring of the throwable item
* pos: initial position of the entity
* dir: direction where the throwable item will be thrown
* velocity: (optional) will overide the default velocity value (can be nil)
* thrower: (optional) player/entity who throw the object (can be nil)
## mcl_throwing.register_throwable_object(name, entity, velocity)
Register a throwable item.
* name: itemname of the throwable object
* entity: entity thrown
* velocity: initial velocity of the entity
## mcl_throwing.dispense_function(stack, dispenserpos, droppos, dropnode, dropdir)
Throw throwable item from dispencer.
Shouldn't be called directly.
Must be used in item definition:
`_on_dispense = mcl_throwing.dispense_function,`
## mcl_throwing.get_player_throw_function(entity_name, velocity)
Return a function who handle item throwing (to be used in item definition)
Handle creative mode, and throw params.
* entity_name: the name of the entity to throw
* velocity: (optional) velocity overide (can be nil)

View File

@ -2,7 +2,7 @@ mcl_throwing = {}
local S = minetest.get_translator("mcl_throwing")
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
local mod_fishing = minetest.get_modpath("mcl_fishing")
local modpath = minetest.get_modpath(minetest.get_current_modname())
--
-- Snowballs and other throwable items
@ -10,21 +10,15 @@ local mod_fishing = minetest.get_modpath("mcl_fishing")
local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
local entity_mapping = {
["mcl_throwing:flying_bobber"] = "mcl_throwing:flying_bobber_entity",
["mcl_throwing:snowball"] = "mcl_throwing:snowball_entity",
["mcl_throwing:egg"] = "mcl_throwing:egg_entity",
["mcl_throwing:ender_pearl"] = "mcl_throwing:ender_pearl_entity",
}
local entity_mapping = {}
local velocities = {}
local velocities = {
["mcl_throwing:flying_bobber_entity"] = 5,
["mcl_throwing:snowball_entity"] = 22,
["mcl_throwing:egg_entity"] = 22,
["mcl_throwing:ender_pearl_entity"] = 22,
}
function mcl_throwing.register_throwable_object(name, entity, velocity)
entity_mapping[name] = entity
velocities[name] = velocity
end
mcl_throwing.throw = function(throw_item, pos, dir, velocity, thrower)
function mcl_throwing.throw(throw_item, pos, dir, velocity, thrower)
if velocity == nil then
velocity = velocities[throw_item]
end
@ -44,7 +38,7 @@ mcl_throwing.throw = function(throw_item, pos, dir, velocity, thrower)
end
-- Throw item
local player_throw_function = function(entity_name, velocity)
function mcl_throwing.get_player_throw_function(entity_name, velocity)
local func = function(item, player, pointed_thing)
local playerpos = player:get_pos()
local dir = player:get_look_dir()
@ -57,7 +51,7 @@ local player_throw_function = function(entity_name, velocity)
return func
end
local dispense_function = function(stack, dispenserpos, droppos, dropnode, dropdir)
function mcl_throwing.dispense_function(stack, dispenserpos, droppos, dropnode, dropdir)
-- Launch throwable item
local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51))
mcl_throwing.throw(stack:get_name(), shootpos, dropdir)
@ -85,374 +79,4 @@ local on_activate = function(self, staticdata, dtime_s)
end
end
-- The snowball entity
local snowball_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_snowball.png"},
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_thrower = nil,
_lastpos={},
}
local egg_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_egg.png"},
visual_size = {x=0.45, y=0.45},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_thrower = nil,
_lastpos={},
}
-- Ender pearl entity
local pearl_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_ender_pearl.png"},
visual_size = {x=0.9, y=0.9},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil, -- Player ObjectRef of the player who threw the ender pearl
}
local flying_bobber_ENTITY={
physical = false,
timer=0,
textures = {"mcl_fishing_bobber.png"}, --FIXME: Replace with correct texture.
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil,
objtype="fishing",
}
local check_object_hit = function(self, pos, dmg)
for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do
local entity = object:get_luaentity()
if entity
and entity.name ~= self.object:get_luaentity().name then
if object:is_player() and self._thrower ~= object:get_player_name() then
-- TODO: Deal knockback
self.object:remove()
return true
elseif (entity._cmi_is_mob == true or entity._hittable_by_projectile) and (self._thrower ~= object) then
-- FIXME: Knockback is broken
object:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = dmg,
}, nil)
return true
end
end
end
return false
end
local snowball_particles = function(pos, vel)
local vel = vector.normalize(vector.multiply(vel, -1))
minetest.add_particlespawner({
amount = 20,
time = 0.001,
minpos = pos,
maxpos = pos,
minvel = vector.add({x=-2, y=3, z=-2}, vel),
maxvel = vector.add({x=2, y=5, z=2}, vel),
minacc = {x=0, y=-9.81, z=0},
maxacc = {x=0, y=-9.81, z=0},
minexptime = 1,
maxexptime = 3,
minsize = 0.7,
maxsize = 0.7,
collisiondetection = true,
collision_removal = true,
object_collision = false,
texture = "weather_pack_snow_snowflake"..math.random(1,2)..".png",
})
end
-- Snowball on_step()--> called when snowball is moving.
local snowball_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local vel = self.object:get_velocity()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(self._lastpos, vel)
self.object:remove()
return
end
end
if check_object_hit(self, pos, {snowball_vulnerable = 3}) then
minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(pos, vel)
self.object:remove()
return
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node
end
-- Movement function of egg
local egg_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node with chance to spawn chicks
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
-- 1/8 chance to spawn a chick
-- FIXME: Chicks have a quite good chance to spawn in walls
local r = math.random(1,8)
-- Turn given object into a child
local make_child= function(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"))
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
local r = math.random(1,32)
if r == 1 then
local offsets = {
{ x=0.7, y=0, z=0 },
{ x=-0.7, y=0, z=-0.7 },
{ x=-0.7, y=0, z=0.7 },
}
for o=1, 3 do
local pos = vector.add(self._lastpos, offsets[o])
make_child(minetest.add_entity(pos, "mobs_mc:chicken"))
end
end
end
minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true)
self.object:remove()
return
end
end
-- Destroy when hitting a mob or player (no chick spawning)
if check_object_hit(self, pos) then
minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true)
self.object:remove()
return
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
-- Movement function of ender pearl
local pearl_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
pos.y = math.floor(pos.y)
local node = minetest.get_node(pos)
local nn = node.name
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
local walkable = (def and def.walkable)
-- No teleport for hitting ignore for now. Otherwise the player could get stuck.
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas
if node.name == "ignore" then
self.object:remove()
-- Activate when hitting a solid node or a plant
elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then
local player = minetest.get_player_by_name(self._thrower)
if player then
-- Teleport and hurt player
-- First determine good teleport position
local dir = {x=0, y=0, z=0}
local v = self.object:get_velocity()
if walkable then
local vc = table.copy(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
vc = vector.normalize(vc)
-- Zero-out the two axes with a lower absolute value than
-- the axis with the strongest force
local lv, ld
lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
lv, ld = math.abs(vc.z), "z"
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:get_pos()
-- Teleport and hurt player
player:set_pos(telepos)
player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" })
-- 5% chance to spawn endermite at the player's origin
local r = math.random(1,20)
if r == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
-- Movement function of flying bobber
local flying_bobber_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
--local player = minetest.get_player_by_name(self._thrower)
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and (def.walkable or def.liquidtype == "flowing" or def.liquidtype == "source")) or not def then
local make_child= function(object)
local ent = object:get_luaentity()
ent.player = self._thrower
ent.child = true
end
make_child(minetest.add_entity(self._lastpos, "mcl_fishing:bobber_entity"))
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
snowball_ENTITY.on_step = snowball_on_step
egg_ENTITY.on_step = egg_on_step
pearl_ENTITY.on_step = pearl_on_step
flying_bobber_ENTITY.on_step = flying_bobber_on_step
minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY)
minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY)
minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY)
minetest.register_entity("mcl_throwing:flying_bobber_entity", flying_bobber_ENTITY)
local how_to_throw = S("Use the punch key to throw.")
-- Snowball
minetest.register_craftitem("mcl_throwing:snowball", {
description = S("Snowball"),
_tt_help = S("Throwable"),
_doc_items_longdesc = S("Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing."),
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_snowball.png",
stack_max = 16,
groups = { weapon_ranged = 1 },
on_use = player_throw_function("mcl_throwing:snowball_entity"),
_on_dispense = dispense_function,
})
-- Egg
minetest.register_craftitem("mcl_throwing:egg", {
description = S("Egg"),
_tt_help = S("Throwable").."\n"..S("Chance to hatch chicks when broken"),
_doc_items_longdesc = S("Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chicks will pop out of the egg."),
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_egg.png",
stack_max = 16,
on_use = player_throw_function("mcl_throwing:egg_entity"),
_on_dispense = dispense_function,
groups = { craftitem = 1 },
})
-- Ender Pearl
minetest.register_craftitem("mcl_throwing:ender_pearl", {
description = S("Ender Pearl"),
_tt_help = S("Throwable").."\n"..minetest.colorize("#FFFF00", S("Teleports you on impact for cost of 5 HP")),
_doc_items_longdesc = S("An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block or a plant. Each teleportation hurts the user by 5 hit points."),
_doc_items_usagehelp = how_to_throw,
wield_image = "mcl_throwing_ender_pearl.png",
inventory_image = "mcl_throwing_ender_pearl.png",
stack_max = 16,
on_use = player_throw_function("mcl_throwing:ender_pearl_entity"),
groups = { transport = 1 },
})
dofile(modpath.."/register.lua")

View File

@ -1,3 +1,3 @@
name = mcl_throwing
depends = mcl_fishing
depends = mcl_colors
optional_depends = mcl_core, mcl_mobitems, doc

View File

@ -0,0 +1,335 @@
local S = minetest.get_translator(minetest.get_current_modname())
-- The snowball entity
local snowball_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_snowball.png"},
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_thrower = nil,
_lastpos={},
}
local egg_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_egg.png"},
visual_size = {x=0.45, y=0.45},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_thrower = nil,
_lastpos={},
}
-- Ender pearl entity
local pearl_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_ender_pearl.png"},
visual_size = {x=0.9, y=0.9},
collisionbox = {0,0,0,0,0,0},
pointable = false,
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil, -- Player ObjectRef of the player who threw the ender pearl
}
local check_object_hit = function(self, pos, dmg)
for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do
local entity = object:get_luaentity()
if entity
and entity.name ~= self.object:get_luaentity().name then
if object:is_player() and self._thrower ~= object:get_player_name() then
-- TODO: Deal knockback
self.object:remove()
return true
elseif (entity._cmi_is_mob == true or entity._hittable_by_projectile) and (self._thrower ~= object) then
-- FIXME: Knockback is broken
object:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = dmg,
}, nil)
return true
end
end
end
return false
end
local snowball_particles = function(pos, vel)
local vel = vector.normalize(vector.multiply(vel, -1))
minetest.add_particlespawner({
amount = 20,
time = 0.001,
minpos = pos,
maxpos = pos,
minvel = vector.add({x=-2, y=3, z=-2}, vel),
maxvel = vector.add({x=2, y=5, z=2}, vel),
minacc = {x=0, y=-9.81, z=0},
maxacc = {x=0, y=-9.81, z=0},
minexptime = 1,
maxexptime = 3,
minsize = 0.7,
maxsize = 0.7,
collisiondetection = true,
collision_removal = true,
object_collision = false,
texture = "weather_pack_snow_snowflake"..math.random(1,2)..".png",
})
end
-- Snowball on_step()--> called when snowball is moving.
local snowball_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local vel = self.object:get_velocity()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(self._lastpos, vel)
self.object:remove()
return
end
end
if check_object_hit(self, pos, {snowball_vulnerable = 3}) then
minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(pos, vel)
self.object:remove()
return
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node
end
-- Movement function of egg
local egg_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node with chance to spawn chicks
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
-- 1/8 chance to spawn a chick
-- FIXME: Chicks have a quite good chance to spawn in walls
local r = math.random(1,8)
-- Turn given object into a child
local make_child= function(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"))
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
local r = math.random(1,32)
if r == 1 then
local offsets = {
{ x=0.7, y=0, z=0 },
{ x=-0.7, y=0, z=-0.7 },
{ x=-0.7, y=0, z=0.7 },
}
for o=1, 3 do
local pos = vector.add(self._lastpos, offsets[o])
make_child(minetest.add_entity(pos, "mobs_mc:chicken"))
end
end
end
minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true)
self.object:remove()
return
end
end
-- Destroy when hitting a mob or player (no chick spawning)
if check_object_hit(self, pos) then
minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true)
self.object:remove()
return
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
-- Movement function of ender pearl
local pearl_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:get_pos()
pos.y = math.floor(pos.y)
local node = minetest.get_node(pos)
local nn = node.name
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
local walkable = (def and def.walkable)
-- No teleport for hitting ignore for now. Otherwise the player could get stuck.
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas
if node.name == "ignore" then
self.object:remove()
-- Activate when hitting a solid node or a plant
elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then
local player = minetest.get_player_by_name(self._thrower)
if player then
-- Teleport and hurt player
-- First determine good teleport position
local dir = {x=0, y=0, z=0}
local v = self.object:get_velocity()
if walkable then
local vc = table.copy(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
vc = vector.normalize(vc)
-- Zero-out the two axes with a lower absolute value than
-- the axis with the strongest force
local lv, ld
lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
lv, ld = math.abs(vc.z), "z"
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:get_pos()
-- Teleport and hurt player
player:set_pos(telepos)
player:set_hp(player:get_hp() - 5, { type = "fall", from = "mod" })
-- 5% chance to spawn endermite at the player's origin
local r = math.random(1,20)
if r == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
snowball_ENTITY.on_step = snowball_on_step
egg_ENTITY.on_step = egg_on_step
pearl_ENTITY.on_step = pearl_on_step
minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY)
minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY)
minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY)
local how_to_throw = S("Use the punch key to throw.")
-- Snowball
minetest.register_craftitem("mcl_throwing:snowball", {
description = S("Snowball"),
_tt_help = S("Throwable"),
_doc_items_longdesc = S("Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing."),
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_snowball.png",
stack_max = 16,
groups = { weapon_ranged = 1 },
on_use = mcl_throwing.get_player_throw_function("mcl_throwing:snowball_entity"),
_on_dispense = mcl_throwing.dispense_function,
})
-- Egg
minetest.register_craftitem("mcl_throwing:egg", {
description = S("Egg"),
_tt_help = S("Throwable").."\n"..S("Chance to hatch chicks when broken"),
_doc_items_longdesc = S("Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chicks will pop out of the egg."),
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_egg.png",
stack_max = 16,
on_use = mcl_throwing.get_player_throw_function("mcl_throwing:egg_entity"),
_on_dispense = mcl_throwing.dispense_function,
groups = { craftitem = 1 },
})
-- Ender Pearl
minetest.register_craftitem("mcl_throwing:ender_pearl", {
description = S("Ender Pearl"),
_tt_help = S("Throwable").."\n"..minetest.colorize(mcl_colors.YELLOW, S("Teleports you on impact for cost of 5 HP")),
_doc_items_longdesc = S("An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block or a plant. Each teleportation hurts the user by 5 hit points."),
_doc_items_usagehelp = how_to_throw,
wield_image = "mcl_throwing_ender_pearl.png",
inventory_image = "mcl_throwing_ender_pearl.png",
stack_max = 16,
on_use = mcl_throwing.get_player_throw_function("mcl_throwing:ender_pearl_entity"),
groups = { transport = 1 },
})
mcl_throwing.register_throwable_object("mcl_throwing:snowball", "mcl_throwing:snowball_entity", 22)
mcl_throwing.register_throwable_object("mcl_throwing:egg", "mcl_throwing:egg_entity", 22)
mcl_throwing.register_throwable_object("mcl_throwing:ender_pearl", "mcl_throwing:ender_pearl_entity", 22)

View File

@ -48,15 +48,16 @@ minetest.register_tool(":", {
},
groups = hand_groups,
_mcl_diggroups = {
handy = { tool_multiplier = 1, level = 1, uses = 0 },
axey = { tool_multiplier = 1, level = 1, uses = 0 },
shovely = { tool_multiplier = 1, level = 1, uses = 0 },
pickaxey = { tool_multiplier = 1, level = 0, uses = 0 },
swordy = { tool_multiplier = 1, level = 0, uses = 0 },
swordy_cobweb = { tool_multiplier = 1, level = 0, uses = 0 },
shearsy = { tool_multiplier = 1, level = 0, uses = 0 },
shearsy_wool = { tool_multiplier = 1, level = 0, uses = 0 },
shearsy_cobweb = { tool_multiplier = 1, level = 0, uses = 0 },
handy = { speed = 1, level = 1, uses = 0 },
axey = { speed = 1, level = 1, uses = 0 },
shovely = { speed = 1, level = 1, uses = 0 },
hoey = { speed = 1, level = 1, uses = 0 },
pickaxey = { speed = 1, level = 0, uses = 0 },
swordy = { speed = 1, level = 0, uses = 0 },
swordy_cobweb = { speed = 1, level = 0, uses = 0 },
shearsy = { speed = 1, level = 0, uses = 0 },
shearsy_wool = { speed = 1, level = 0, uses = 0 },
shearsy_cobweb = { speed = 1, level = 0, uses = 0 },
}
})
@ -90,7 +91,7 @@ minetest.register_tool("mcl_tools:pick_wood", {
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { tool_multiplier = 2, level = 1, uses = 60 }
pickaxey = { speed = 2, level = 1, uses = 60 }
},
})
minetest.register_tool("mcl_tools:pick_stone", {
@ -110,7 +111,7 @@ minetest.register_tool("mcl_tools:pick_stone", {
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { tool_multiplier = 4, level = 3, uses = 132 }
pickaxey = { speed = 4, level = 3, uses = 132 }
},
})
minetest.register_tool("mcl_tools:pick_iron", {
@ -130,7 +131,7 @@ minetest.register_tool("mcl_tools:pick_iron", {
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { tool_multiplier = 6, level = 4, uses = 251 }
pickaxey = { speed = 6, level = 4, uses = 251 }
},
})
minetest.register_tool("mcl_tools:pick_gold", {
@ -150,7 +151,7 @@ minetest.register_tool("mcl_tools:pick_gold", {
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { tool_multiplier = 12, level = 2, uses = 33 }
pickaxey = { speed = 12, level = 2, uses = 33 }
},
})
minetest.register_tool("mcl_tools:pick_diamond", {
@ -170,7 +171,7 @@ minetest.register_tool("mcl_tools:pick_diamond", {
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { tool_multiplier = 8, level = 5, uses = 1562 }
pickaxey = { speed = 8, level = 5, uses = 1562 }
},
})
@ -262,7 +263,7 @@ minetest.register_tool("mcl_tools:shovel_wood", {
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
shovely = { tool_multiplier = 2, level = 1, uses = 60 }
shovely = { speed = 2, level = 1, uses = 60 }
},
})
minetest.register_tool("mcl_tools:shovel_stone", {
@ -283,7 +284,7 @@ minetest.register_tool("mcl_tools:shovel_stone", {
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
shovely = { tool_multiplier = 4, level = 3, uses = 132 }
shovely = { speed = 4, level = 3, uses = 132 }
},
})
minetest.register_tool("mcl_tools:shovel_iron", {
@ -304,7 +305,7 @@ minetest.register_tool("mcl_tools:shovel_iron", {
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
shovely = { tool_multiplier = 6, level = 4, uses = 251 }
shovely = { speed = 6, level = 4, uses = 251 }
},
})
minetest.register_tool("mcl_tools:shovel_gold", {
@ -325,7 +326,7 @@ minetest.register_tool("mcl_tools:shovel_gold", {
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
shovely = { tool_multiplier = 12, level = 2, uses = 33 }
shovely = { speed = 12, level = 2, uses = 33 }
},
})
minetest.register_tool("mcl_tools:shovel_diamond", {
@ -346,7 +347,7 @@ minetest.register_tool("mcl_tools:shovel_diamond", {
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
shovely = { tool_multiplier = 8, level = 5, uses = 1562 }
shovely = { speed = 8, level = 5, uses = 1562 }
},
})
@ -368,7 +369,7 @@ minetest.register_tool("mcl_tools:axe_wood", {
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
axey = { tool_multiplier = 2, level = 1, uses = 60 }
axey = { speed = 2, level = 1, uses = 60 }
},
})
minetest.register_tool("mcl_tools:axe_stone", {
@ -387,7 +388,7 @@ minetest.register_tool("mcl_tools:axe_stone", {
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
axey = { tool_multiplier = 4, level = 3, uses = 132 }
axey = { speed = 4, level = 3, uses = 132 }
},
})
minetest.register_tool("mcl_tools:axe_iron", {
@ -407,7 +408,7 @@ minetest.register_tool("mcl_tools:axe_iron", {
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
axey = { tool_multiplier = 6, level = 4, uses = 251 }
axey = { speed = 6, level = 4, uses = 251 }
},
})
minetest.register_tool("mcl_tools:axe_gold", {
@ -426,7 +427,7 @@ minetest.register_tool("mcl_tools:axe_gold", {
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
axey = { tool_multiplier = 12, level = 2, uses = 33 }
axey = { speed = 12, level = 2, uses = 33 }
},
})
minetest.register_tool("mcl_tools:axe_diamond", {
@ -445,7 +446,7 @@ minetest.register_tool("mcl_tools:axe_diamond", {
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
axey = { tool_multiplier = 8, level = 5, uses = 1562 }
axey = { speed = 8, level = 5, uses = 1562 }
},
})
@ -467,8 +468,8 @@ minetest.register_tool("mcl_tools:sword_wood", {
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { tool_multiplier = 2, level = 1, uses = 60 },
swordy_cobweb = { tool_multiplier = 2, level = 1, uses = 60 }
swordy = { speed = 2, level = 1, uses = 60 },
swordy_cobweb = { speed = 2, level = 1, uses = 60 }
},
})
minetest.register_tool("mcl_tools:sword_stone", {
@ -487,8 +488,8 @@ minetest.register_tool("mcl_tools:sword_stone", {
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { tool_multiplier = 4, level = 3, uses = 132 },
swordy_cobweb = { tool_multiplier = 4, level = 3, uses = 132 }
swordy = { speed = 4, level = 3, uses = 132 },
swordy_cobweb = { speed = 4, level = 3, uses = 132 }
},
})
minetest.register_tool("mcl_tools:sword_iron", {
@ -507,8 +508,8 @@ minetest.register_tool("mcl_tools:sword_iron", {
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { tool_multiplier = 6, level = 4, uses = 251 },
swordy_cobweb = { tool_multiplier = 6, level = 4, uses = 251 }
swordy = { speed = 6, level = 4, uses = 251 },
swordy_cobweb = { speed = 6, level = 4, uses = 251 }
},
})
minetest.register_tool("mcl_tools:sword_gold", {
@ -527,8 +528,8 @@ minetest.register_tool("mcl_tools:sword_gold", {
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { tool_multiplier = 12, level = 2, uses = 33 },
swordy_cobweb = { tool_multiplier = 12, level = 2, uses = 33 }
swordy = { speed = 12, level = 2, uses = 33 },
swordy_cobweb = { speed = 12, level = 2, uses = 33 }
},
})
minetest.register_tool("mcl_tools:sword_diamond", {
@ -547,8 +548,8 @@ minetest.register_tool("mcl_tools:sword_diamond", {
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { tool_multiplier = 8, level = 5, uses = 1562 },
swordy_cobweb = { tool_multiplier = 8, level = 5, uses = 1562 }
swordy = { speed = 8, level = 5, uses = 1562 },
swordy_cobweb = { speed = 8, level = 5, uses = 1562 }
},
})
@ -569,9 +570,9 @@ minetest.register_tool("mcl_tools:shears", {
sound = { breaks = "default_tool_breaks" },
_mcl_toollike_wield = true,
_mcl_diggroups = {
shearsy = { tool_multiplier = 1.5, level = 1, uses = 238 },
shearsy_wool = { tool_multiplier = 5, level = 1, uses = 238 },
shearsy_cobweb = { tool_multiplier = 15, level = 1, uses = 238 }
shearsy = { speed = 1.5, level = 1, uses = 238 },
shearsy_wool = { speed = 5, level = 1, uses = 238 },
shearsy_cobweb = { speed = 15, level = 1, uses = 238 }
},
})

View File

@ -29,7 +29,7 @@ local function add_chunk(pos)
end
prev = d
end
chunks[#chunks] = {n, n}
chunks[#chunks+1] = {n, n}
end
function mcl_mapgen_core.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
@ -1790,6 +1790,8 @@ local generate_nether_decorations = function(minp, maxp, seed)
return
end
minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
-- TODO: Generate everything based on Perlin noise instead of PseudoRandom
local bpos
@ -1847,6 +1849,7 @@ local generate_nether_decorations = function(minp, maxp, seed)
end
minetest.register_on_generated(function(minp, maxp, blockseed)
minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
add_chunk(minp)
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
@ -2132,12 +2135,8 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- * Replace water with Nether lava.
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then
local nodes
if mg_name == "v6" then
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
else
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
end
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
for n=1, #nodes do
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
if data[p_pos] == c_water then
@ -2151,6 +2150,18 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
lvm_used = true
end
end
else
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining, param)
if calls_remaining > 0 then return end
-- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"})
local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"})
local sn=(mcl_observers and mcl_observers.swap_node) or minetest.swap_node
local l = {name="mcl_nether:nether_lava_source"}
for _, n in pairs(nodes) do
sn(n, l)
end
end, {minp=vector.new(minp), maxp=vector.new(maxp)})
end
-- End block fixes:
-- * Replace water with end stone or air (depending on height).

View File

@ -534,7 +534,7 @@ end
-- Debug command
minetest.register_chatcommand("spawnstruct", {
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | dungeon",
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | nether_portal | dungeon",
description = S("Generate a pre-defined structure near your position."),
privs = {debug = true},
func = function(name, param)
@ -570,6 +570,8 @@ minetest.register_chatcommand("spawnstruct", {
mcl_structures.generate_end_portal_shrine(pos, rot, pr)
elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then
mcl_dungeons.spawn_dungeon(pos, rot, pr)
elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then
mcl_portals.spawn_nether_portal(pos, rot, pr, name)
elseif param == "" then
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
errord = true

View File

@ -96,6 +96,8 @@ minetest.register_globalstep(function(dtime)
local player_velocity = player:get_velocity() or player:get_player_velocity()
local wielded = player:get_wielded_item()
-- controls head bone
local pitch = - degrees(player:get_look_vertical())
local yaw = degrees(player:get_look_horizontal())
@ -107,13 +109,19 @@ minetest.register_globalstep(function(dtime)
player_vel_yaw = limit_vel_yaw(player_vel_yaw, yaw)
player_vel_yaws[name] = player_vel_yaw
-- controls right and left arms pitch when shooting a bow or punching
if string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB and not controls.LMB and not controls.up and not controls.down and not controls.left and not controls.right then
-- controls right and left arms pitch when shooting a bow
if string.find(wielded:get_name(), "mcl_bows:bow") and controls.RMB and not controls.LMB and not controls.up and not controls.down and not controls.left and not controls.right then
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35))
-- when punching
elseif controls.LMB and player:get_attach() == nil then
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
-- when holding an item.
elseif wielded:get_name() ~= "" then
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(20,0,0))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
-- resets arms pitch
else
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0))
@ -244,13 +252,7 @@ minetest.register_globalstep(function(dtime)
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.4)
end
end
else
-- Reset speed decrease
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:surface")
end
-- Swimming? Check if boots are enchanted with depth strider
if get_item_group(node_feet, "liquid") ~= 0 and mcl_enchanting.get_enchantment(player:get_inventory():get_stack("armor", 5), "depth_strider") then
elseif get_item_group(node_feet, "liquid") ~= 0 and mcl_enchanting.get_enchantment(player:get_inventory():get_stack("armor", 5), "depth_strider") then
local boots = player:get_inventory():get_stack("armor", 5)
local depth_strider = mcl_enchanting.get_enchantment(boots, "depth_strider")

View File

@ -106,14 +106,18 @@ minetest.register_entity("wieldview:wieldnode", {
if player then
local wielded = player:get_wielded_item()
local itemstring = wielded:get_name()
if self.itemstring ~= itemstring then
local def = minetest.registered_items[itemstring]
self.object:set_properties({glow = def and def.light_source or 0})
-- wield item as cubic
if armor.textures[self.wielder].wielditem == "blank.png" then
self.object:set_properties({textures = {itemstring}})
else
else -- wield item as flat
self.object:set_properties({textures = {""}})
end
self.itemstring = itemstring
end
else

View File

@ -129,6 +129,9 @@ mcl_superflat_classic (Classic superflat map generation) bool false
# If disabled, no ores will be generated.
mcl_generate_ores (Generate Ores) bool true
# If disabled, command blocks will be unusuable (but still present).
mcl_enable_commandblocks (Enable Command Blocks) bool true
# Make some blocks emit decorative particles like flames. This setting
# specifies the detail level of particles, with higher levels being
# more CPU demanding.