Merge branch 'master' into chat-command-builder

This commit is contained in:
AFCMS 2021-03-30 20:33:32 +02:00
commit 3137c86f67
287 changed files with 2709 additions and 2147 deletions

4
API.md
View File

@ -17,6 +17,10 @@ Items can have these fields:
anvil. anvil.
See `mcl_banners` for an example. See `mcl_banners` for an example.
Tools can have these fields:
* `_mcl_diggroups`: Specifies the digging groups that a tool can dig and how
efficiently. See `_mcl_autogroup` for more information.
All nodes can have these fields: All nodes can have these fields:
* `_mcl_hardness`: Hardness of the block, ranges from 0 to infinity (represented by -1). Determines digging times. Default: 0 * `_mcl_hardness`: Hardness of the block, ranges from 0 to infinity (represented by -1). Determines digging times. Default: 0

View File

@ -33,10 +33,10 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de
keepInventory = false keepInventory = false
# Performance settings # Performance settings
dedicated_server_step = 0.001 # dedicated_server_step = 0.001
abm_interval = 0.25 # abm_interval = 0.25
max_objects_per_block = 4096 # max_objects_per_block = 4096
max_packets_per_iteration = 10096 # max_packets_per_iteration = 10096
# Clientmodding to support official client # Clientmodding to support official client
enable_client_modding = true enable_client_modding = true

View File

@ -4,6 +4,11 @@ Specifically, this mod has 2 purposes:
1) Automatically adding the group “solid” for blocks considered “solid” in Minecraft. 1) Automatically adding the group “solid” for blocks considered “solid” in Minecraft.
2) Generating digging time group for all nodes based on node metadata (it's complicated) 2) Generating digging time group for all nodes based on node metadata (it's complicated)
This mod also requires another mod called “mcl_autogroup” to function properly.
“mcl_autogroup” exposes the API used to register digging groups, while this mod
uses those digging groups to set the digging time groups for all the nodes and
tools.
See init.lua for more infos. See init.lua for more infos.
The leading underscore in the name “_mcl_autogroup” was added to force Minetest to load this mod as late as possible. The leading underscore in the name “_mcl_autogroup” was added to force Minetest to load this mod as late as possible.

View File

@ -1,170 +1,362 @@
--[[ Mining times. Yeah, mining times … Alright, this is going to be FUN! --[[
This mod implements a HACK to make 100% sure the digging times of all tools
match Minecraft's perfectly. The digging times system of Minetest is very
different, so this weird group trickery has to be used. In Minecraft, each
block has a hardness and the actual Minecraft digging time is determined by
this:
This mod does include a HACK to make 100% sure the digging times of all tools match Minecraft's perfectly.
The digging times system of Minetest is very different, so this weird group trickery has to be used.
In Minecraft, each block has a hardness and the actual Minecraft digging time is determined by this:
1) The block's hardness 1) The block's hardness
2) The tool being used 2) The tool being used (the tool speed and its efficiency level)
3) Whether the tool is considered as eligible for the block 3) Whether the tool is considered as "eligible" for the block
(e.g. only diamond pick eligible for obsidian) (e.g. only diamond pick eligible for obsidian)
See Minecraft Wiki <http://minecraft.gamepedia.com/Minecraft_Wiki> for more information.
In MineClone 2, all diggable node have the hardness set in the custom field _mcl_hardness (0 by default). See Minecraft Wiki <http://minecraft.gamepedia.com/Minecraft_Wiki> for more
The nodes are also required to specify the eligible tools in groups like pickaxey, shovely, etc. information.
This mod then calculates the real digging time based on the node meta data. The real digging times
are then added into mcl_autogroup.digtimes where the table indices are group rating and the values are the
digging times in seconds. These digging times can be then added verbatim into the tool definitions.
Example: How the mod is used
mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2 ===================
This means that when a node has been assigned the group pickaxey_dig_diamond=1, it can be dug by the In MineClone 2, all diggable nodes have the hardness set in the custom field
diamond pickaxe in 0.2 seconds. "_mcl_hardness" (0 by default). These values are used together with digging
groups by this mod to create the correct digging times for nodes. Digging
groups are registered using the following code:
mcl_autogroup.register_diggroup("shovely")
mcl_autogroup.register_diggroup("pickaxey", {
levels = { "wood", "gold", "stone", "iron", "diamond" }
})
The first line registers a simple digging group. The second line registers a
digging group with 5 different levels (in this case one for each material of a
pickaxes).
This strange setup with mcl_autogroup has been done to minimize the amount of required digging times Nodes indicate that they belong to a particular digging group by being member of
a single tool needs to use. If this is not being done, the loading time will increase considerably the digging group in their node definition. "mcl_core:dirt" for example has
(>10s). shovely=1 in its groups. If the digging group has multiple levels the value of
the group indicates which digging level the node requires.
"mcl_core:stone_with_gold" for example has pickaxey=4 because it requires a
pickaxe of level 4 be mined.
]] For tools to be able to dig nodes of digging groups they need to use the have
the custom field "_mcl_diggroups" function to get the groupcaps. The value of
this field is a table which defines which groups the tool can dig and how
efficiently.
local materials = { "wood", "gold", "stone", "iron", "diamond" } _mcl_diggroups = {
local basegroups = { "pickaxey", "axey", "shovely" } handy = { speed = 1, level = 1, uses = 0 },
local minigroups = { "handy", "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" } pickaxey = { speed = 1, level = 0, uses = 0 },
local divisors = { }
["wood"] = 2,
["gold"] = 12,
["stone"] = 4,
["iron"] = 6,
["diamond"] = 8,
["handy"] = 1,
["shearsy"] = 15,
["swordy"] = 1.5,
["shearsy_wool"] = 5,
["swordy_cobweb"] = 15,
}
local max_efficiency_level = 5
mcl_autogroup = {} The "uses" field indicate how many uses (0 for infinite) a tool has when used on
mcl_autogroup.digtimes = {} the specified digging group. The "speed" field is a multiplier to the dig speed
mcl_autogroup.creativetimes = {} -- Copy of digtimes, except that all values are 0. Used for creative mode on that digging group.
for m=1, #materials do The "level" field indicates which levels of the group the tool can harvest. A
for g=1, #basegroups do level of 0 means that the tool cannot harvest blocks of that node. A level of 1
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {} or above means that the tool can harvest nodes with that level or below. See
mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {} "mcl_tools/init.lua" for examples on how "_mcl_diggroups" is used in practice.
for e=1, max_efficiency_level do
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {} Information about the mod
=========================
The mod is split up into two parts, mcl_autogroup and _mcl_autogroup.
mcl_autogroup contains the API functions used to register custom digging groups.
_mcl_autogroup contains most of the code. The leading underscore in the name
"_mcl_autogroup" is used to force Minetest to load that part of the mod as late
as possible. Minetest loads mods in reverse alphabetical order.
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()
local maps = {}
local values = {}
for g, _ in pairs(mcl_autogroup.registered_diggroups) do
maps[g] = {}
values[g] = {}
end
for _, ndef in pairs(minetest.registered_nodes) do
for g, _ in pairs(mcl_autogroup.registered_diggroups) do
if ndef.groups[g] ~= nil then
maps[g][ndef._mcl_hardness or 0] = true
end
end
end
for g, map in pairs(maps) do
for k, _ in pairs(map) do
table.insert(values[g], k)
end
end
for g, _ in pairs(mcl_autogroup.registered_diggroups) do
table.sort(values[g])
end
return values
end
-- Returns a table containing a table indexed by "_mcl_hardness_value" to get
-- its index in the list of unique hardnesses for each diggroup.
local function get_hardness_lookup_for_groups(hardness_values)
local map = {}
for g, values in pairs(hardness_values) do
map[g] = {}
for k, v in pairs(values) do
map[g][v] = k
end
end
return map
end
-- Array of unique hardness values for each group which affects dig time.
local hardness_values = get_hardness_values_for_groups()
-- Map indexed by hardness values which return the index of that value in
-- hardness_value. Used for quick lookup.
local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
local function compute_creativetimes(group)
local creativetimes = {}
for index, hardness in pairs(hardness_values[group]) do
table.insert(creativetimes, 0)
end
return creativetimes
end
-- Get the list of digging times for using a specific tool on a specific
-- diggroup.
--
-- Parameters:
-- group - the group which it is digging
-- can_harvest - if the tool can harvest the block
-- speed - dig speed multiplier for tool (default 1)
-- efficiency - efficiency level for the tool if applicable
local function get_digtimes(group, can_harvest, speed, efficiency)
local speed = speed or 1
if efficiency then
speed = speed + efficiency * efficiency + 1
end
local digtimes = {}
for index, hardness in pairs(hardness_values[group]) do
local digtime = (hardness or 0) / speed
if can_harvest then
digtime = digtime * 1.5
else
digtime = digtime * 5
end
if digtime <= 0.05 then
digtime = 0
else
digtime = math.ceil(digtime * 20) / 20
end
table.insert(digtimes, digtime)
end
return digtimes
end
-- Get one groupcap field for using a specific tool on a specific group.
local function get_groupcap(group, can_harvest, multiplier, efficiency, uses)
return {
times = get_digtimes(group, can_harvest, multiplier, efficiency),
uses = uses,
maxlevel = 0,
}
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.speed or 1
local uses = capsdef.uses
local def = mcl_autogroup.registered_diggroups[g]
local max_level = def.levels and #def.levels or 1
assert(capsdef.level, toolname .. ' is missing level for ' .. g)
local level = math.min(capsdef.level, max_level)
if def.levels then
groupcaps[g .. "_dig_default"] = get_groupcap(g, false, mult, efficiency, uses)
if level > 0 then
groupcaps[g .. "_dig_" .. def.levels[level]] = get_groupcap(g, true, mult, efficiency, uses)
end
else
groupcaps[g .. "_dig"] = get_groupcap(g, level > 0, mult, efficiency, uses)
end end
end end
end end
for g=1, #minigroups do
mcl_autogroup.digtimes[minigroups[g].."_dig"] = {} -- Checks if the given node would drop its useful drop if dug by a given tool.
mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {} -- Returns true if it will yield its useful drop, false otherwise.
for e=1, max_efficiency_level do function mcl_autogroup.can_harvest(nodename, toolname)
mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {} local ndef = minetest.registered_nodes[nodename]
mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {}
if minetest.get_item_group(nodename, "dig_immediate") >= 2 then
return true
end end
-- Check if it can be dug by tool
local tdef = minetest.registered_tools[toolname]
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
return true
end
end
end
end
-- Check if it can be dug by hand
local tdef = minetest.registered_tools[""]
if tdef then
for g, gdef in pairs(tdef._mcl_diggroups) do
if ndef.groups[g] then
if ndef.groups[g] <= gdef.level then
return true
end
end
end
end
return false
end
-- Get one groupcap field for using a specific tool on a specific group.
local function get_groupcap(group, can_harvest, multiplier, efficiency, uses)
return {
times = get_digtimes(group, can_harvest, multiplier, efficiency),
uses = uses,
maxlevel = 0,
}
end
-- Returns the tool_capabilities from a tool definition or a default set of
-- tool_capabilities
local function get_tool_capabilities(tdef)
if tdef.tool_capabilities then
return tdef.tool_capabilities
end
-- If the damage group and punch interval from hand is not included,
-- then the user will not be able to attack with the tool.
local hand_toolcaps = minetest.registered_tools[""].tool_capabilities
return {
full_punch_interval = hand_toolcaps.full_punch_interval,
damage_groups = hand_toolcaps.damage_groups
}
end
-- Get the groupcaps for a tool. This function returns "groupcaps" table of
-- digging which should be put in the "tool_capabilities" of the tool definition
-- or in the metadata of an enchanted tool.
--
-- Parameters:
-- toolname - Name of the tool being enchanted (like "mcl_tools:diamond_pickaxe")
-- efficiency - The efficiency level the tool is enchanted with (default 0)
--
-- NOTE:
-- This function can only be called after mod initialization. Otherwise a mod
-- would have to add _mcl_autogroup as a dependency which would break the mod
-- loading order.
function mcl_autogroup.get_groupcaps(toolname, efficiency)
local tdef = minetest.registered_tools[toolname]
local groupcaps = table.copy(get_tool_capabilities(tdef).groupcaps or {})
add_groupcaps(toolname, groupcaps, tdef._mcl_diggroups, efficiency)
return groupcaps
end
-- Get the wear from using a tool on a digging group.
--
-- Parameters
-- toolname - Name of the tool used
-- diggroup - The name of the diggroup the tool is used on
--
-- NOTE:
-- This function can only be called after mod initialization. Otherwise a mod
-- would have to add _mcl_autogroup as a dependency which would break the mod
-- loading order.
function mcl_autogroup.get_wear(toolname, diggroup)
local tdef = minetest.registered_tools[toolname]
local uses = tdef._mcl_diggroups[diggroup].uses
return math.ceil(65535 / uses)
end end
local overwrite = function() local overwrite = function()
for nname, ndef in pairs(minetest.registered_nodes) do for nname, ndef in pairs(minetest.registered_nodes) do
local groups_changed = false
local newgroups = table.copy(ndef.groups) local newgroups = table.copy(ndef.groups)
if (nname ~= "ignore" and ndef.diggable) then if (nname ~= "ignore" and ndef.diggable) then
-- Automatically assign the “solid” group for solid nodes -- Automatically assign the "solid" group for solid nodes
if (ndef.walkable == nil or ndef.walkable == true) if (ndef.walkable == nil or ndef.walkable == true)
and (ndef.collision_box == nil or ndef.collision_box.type == "regular") and (ndef.collision_box == nil or ndef.collision_box.type == "regular")
and (ndef.node_box == nil or ndef.node_box.type == "regular") and (ndef.node_box == nil or ndef.node_box.type == "regular")
and (ndef.groups.not_solid == 0 or ndef.groups.not_solid == nil) then and (ndef.groups.not_solid == 0 or ndef.groups.not_solid == nil) then
newgroups.solid = 1 newgroups.solid = 1
groups_changed = true
end end
-- Automatically assign the “opaque” group for opaque nodes -- Automatically assign the "opaque" group for opaque nodes
if (not (ndef.paramtype == "light" or ndef.sunlight_propagates)) and if (not (ndef.paramtype == "light" or ndef.sunlight_propagates)) and
(ndef.groups.not_opaque == 0 or ndef.groups.not_opaque == nil) then (ndef.groups.not_opaque == 0 or ndef.groups.not_opaque == nil) then
newgroups.opaque = 1 newgroups.opaque = 1
groups_changed = true
end end
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency) local creative_breakable = false
local time, validity_factor
if actual_rating >= expected_rating then -- Assign groups used for digging this node depending on
-- Valid tool -- the registered digging groups
validity_factor = 1.5 for g, gdef in pairs(mcl_autogroup.registered_diggroups) do
creative_breakable = true
local index = hardness_lookup[g][ndef._mcl_hardness or 0]
if ndef.groups[g] then
if gdef.levels then
newgroups[g .. "_dig_default"] = index
for i = ndef.groups[g], #gdef.levels do
newgroups[g .. "_dig_" .. gdef.levels[i]] = index
end
else else
-- Wrong tool (higher digging time) newgroups[g .. "_dig"] = index
validity_factor = 5
end
local speed_multiplier = divisors[material]
if efficiency then
speed_multiplier = speed_multiplier + efficiency * efficiency + 1
end
time = (hardness * validity_factor) / speed_multiplier
if time <= 0.05 then
time = 0
else
time = math.ceil(time * 20) / 20
end
table.insert(mcl_autogroup.digtimes[diggroup], time)
if not efficiency then
table.insert(mcl_autogroup.creativetimes[diggroup], 0)
end
newgroups[diggroup] = #mcl_autogroup.digtimes[diggroup]
return newgroups
end
-- Hack in digging times
local hardness = ndef._mcl_hardness
if not hardness then
hardness = 0
end
-- Handle pickaxey, axey and shovely
for _, basegroup in pairs(basegroups) do
if (hardness ~= -1 and ndef.groups[basegroup]) then
for g=1,#materials do
local diggroup = basegroup.."_dig_"..materials[g]
newgroups = calculate_group(hardness, materials[g], diggroup, newgroups, g, ndef.groups[basegroup])
for e=1,max_efficiency_level do
newgroups = calculate_group(hardness, materials[g], diggroup .. "_efficiency_" .. e, newgroups, g, ndef.groups[basegroup], e)
end
groups_changed = true
end
end
end
for m=1, #minigroups do
local minigroup = minigroups[m]
if hardness ~= -1 then
local diggroup = minigroup.."_dig"
-- actual rating
local ar = ndef.groups[minigroup]
if ar == nil then
ar = 0
end
if (minigroup == "handy")
or
(ndef.groups.shearsy_wool and minigroup == "shearsy_wool" and ndef.groups.wool)
or
(ndef.groups.swordy_cobweb and minigroup == "swordy_cobweb" and nname == "mcl_core:cobweb")
or
(ndef.groups[minigroup] and minigroup ~= "swordy_cobweb" and minigroup ~= "shearsy_wool") then
newgroups = calculate_group(hardness, minigroup, diggroup, newgroups, ar, 1)
for e=1,max_efficiency_level do
newgroups = calculate_group(hardness, minigroup, diggroup .. "_efficiency_" .. e, newgroups, ar, 1, e)
end
groups_changed = true
end end
end end
end end
if groups_changed then -- Automatically assign the node to the
-- creative_breakable group if it belongs to any digging
-- group.
newgroups["creative_breakable"] = 1
minetest.override_item(nname, { minetest.override_item(nname, {
groups = newgroups groups = newgroups
}) })
end end
end end
for tname, tdef in pairs(minetest.registered_tools) do
-- Assign groupcaps for digging the registered digging groups
-- depending on the _mcl_diggroups in the tool definition
if tdef._mcl_diggroups then
local toolcaps = table.copy(get_tool_capabilities(tdef))
toolcaps.groupcaps = mcl_autogroup.get_groupcaps(tname)
minetest.override_item(tname, {
tool_capabilities = toolcaps
})
end
end end
end end

View File

@ -1,3 +1,3 @@
name = _mcl_autogroup name = _mcl_autogroup
author = Wuzzy author = ryvnf
description = MineClone 2 core mod which automatically adds groups to all items. Very important for digging times. description = MineClone 2 core mod which automatically adds groups to all items. Very important for digging times.

View File

@ -0,0 +1,28 @@
--[[
This is one part of a mod to replicate the digging times from Minecraft. This
part only exposes a function to register digging groups. The rest of the mod is
implemented and documented in the _mcl_autogroup.
The mod is split up into two parts, mcl_autogroup and _mcl_autogroup.
mcl_autogroup contains the API functions used to register custom digging groups.
_mcl_autogroup contains most of the code. The leading underscore in the name
"_mcl_autogroup" is used to force Minetest to load that part of the mod as late
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:
-- group - Name of the group to register as a digging group
-- def - Table with information about the diggroup (defaults to {} if unspecified)
--
-- Values in def:
-- level - If specified it is an array containing the names of the different
-- digging levels the digging group supports.
function mcl_autogroup.register_diggroup(group, def)
mcl_autogroup.registered_diggroups[group] = def or {}
end

View File

@ -0,0 +1,3 @@
name = mcl_autogroup
author = ryvnf
description = MineClone 2 core mod which automatically adds groups to all items. Very important for digging times.

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.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) 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 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_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 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 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_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_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1 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 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) / chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits. 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 * chunk_size_in_nodes 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 * 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) local function coordinate_to_block(x)
return math.floor(x / mcl_vars.MAP_BLOCKSIZE) return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
end end
local function coordinate_to_chunk(x) 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 end
function mcl_vars.pos_to_block(pos) function mcl_vars.pos_to_block(pos)
@ -70,7 +71,7 @@ function mcl_vars.pos_to_chunk(pos)
} }
end 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_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z local k_positive_y = k_positive_z * k_positive_z
@ -174,3 +175,86 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function) -- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time()) math.randomseed(os.time())
local chunks = {} -- intervals of chunks generated
function mcl_vars.add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_vars.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_vars.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_vars.is_generated(pos) then
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

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

View File

@ -22,7 +22,7 @@ minetest.register_on_mods_loaded(function()
end end
end end
for _,func in ipairs(walkover.registered_globals) do --cache registered globals for _,func in ipairs(walkover.registered_globals) do --cache registered globals
table.insert(registered_globals, value) table.insert(registered_globals, func)
end end
end) end)
@ -30,7 +30,7 @@ local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime; timer = timer + dtime;
if timer >= 0.3 then if timer >= 0.3 then
for _,player in ipairs(get_connected_players()) do for _,player in pairs(get_connected_players()) do
local pp = player:get_pos() local pp = player:get_pos()
pp.y = ceil(pp.y) pp.y = ceil(pp.y)
local loc = vector_add(pp, {x=0,y=-1,z=0}) local loc = vector_add(pp, {x=0,y=-1,z=0})

View File

@ -1,6 +1,6 @@
local S = minetest.get_translator("mcl_boats") local S = minetest.get_translator("mcl_boats")
local boat_visual_size = {x = 3, y = 3, z = 3} local boat_visual_size = {x = 1, y = 1, z = 1}
local paddling_speed = 22 local paddling_speed = 22
local boat_y_offset = 0.35 local boat_y_offset = 0.35
local boat_y_offset_ground = boat_y_offset + 0.6 local boat_y_offset_ground = boat_y_offset + 0.6
@ -12,9 +12,7 @@ local function is_group(pos, group)
return minetest.get_item_group(nn, group) ~= 0 return minetest.get_item_group(nn, group) ~= 0
end end
local function is_water(pos) local is_water = flowlib.is_water
return is_group(pos, "water")
end
local function is_ice(pos) local function is_ice(pos)
return is_group(pos, "ice") return is_group(pos, "ice")
@ -163,6 +161,8 @@ function boat.get_staticdata(self)
end end
function boat.on_death(self, killer) function boat.on_death(self, killer)
mcl_burning.extinguish(self.object)
if killer and killer:is_player() and minetest.is_creative_enabled(killer:get_player_name()) then if killer and killer:is_player() and minetest.is_creative_enabled(killer:get_player_name()) then
local inv = killer:get_inventory() local inv = killer:get_inventory()
if not inv:contains_item("main", self._itemstring) then if not inv:contains_item("main", self._itemstring) then
@ -188,6 +188,8 @@ function boat.on_punch(self, puncher, time_from_last_punch, tool_capabilities, d
end end
function boat.on_step(self, dtime, moveresult) function boat.on_step(self, dtime, moveresult)
mcl_burning.tick(self.object, dtime)
self._v = get_v(self.object:get_velocity()) * get_sign(self._v) self._v = get_v(self.object:get_velocity()) * get_sign(self._v)
local v_factor = 1 local v_factor = 1
local v_slowdown = 0.02 local v_slowdown = 0.02
@ -223,7 +225,7 @@ function boat.on_step(self, dtime, moveresult)
self._regen_timer = regen_timer self._regen_timer = regen_timer
if moveresult and moveresult.collides then if moveresult and moveresult.collides then
for _, collision in ipairs(moveresult.collisions) do for _, collision in pairs(moveresult.collisions) do
local pos = collision.node_pos local pos = collision.node_pos
if collision.type == "node" and minetest.get_item_group(minetest.get_node(pos).name, "dig_by_boat") > 0 then if collision.type == "node" and minetest.get_item_group(minetest.get_node(pos).name, "dig_by_boat") > 0 then
minetest.dig_node(pos) minetest.dig_node(pos)
@ -243,7 +245,7 @@ function boat.on_step(self, dtime, moveresult)
else else
local ctrl = self._passenger:get_player_control() local ctrl = self._passenger:get_player_control()
if ctrl and ctrl.sneak then if ctrl and ctrl.sneak then
detach_player(self._passenger, true) detach_object(self._passenger, true)
self._passenger = nil self._passenger = nil
end end
end end
@ -305,7 +307,7 @@ function boat.on_step(self, dtime, moveresult)
self._animation = 0 self._animation = 0
end end
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
if entity and entity._cmi_is_mob then if entity and entity._cmi_is_mob then
attach_object(self, obj) attach_object(self, obj)

View File

@ -1,7 +1,7 @@
name = mcl_boats name = mcl_boats
author = PilzAdam author = PilzAdam
description = Adds drivable boats. description = Adds drivable boats.
depends = mcl_player depends = mcl_player, flowlib
optional_depends = mcl_core, doc_identifier optional_depends = mcl_core, doc_identifier

View File

@ -117,6 +117,10 @@ function mcl_burning.damage(obj)
end end
function mcl_burning.set_on_fire(obj, burn_time, reason) function mcl_burning.set_on_fire(obj, burn_time, reason)
if obj:get_hp() < 0 then
return
end
local luaentity = obj:get_luaentity() local luaentity = obj:get_luaentity()
if luaentity and luaentity.fire_resistant then if luaentity and luaentity.fire_resistant then
return return
@ -145,7 +149,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
end end
if old_burn_time <= burn_time then if old_burn_time <= burn_time then
local sound_id = mcl_burning.get(obj, "int", "sound_id") --[[local sound_id = mcl_burning.get(obj, "int", "sound_id")
if sound_id == 0 then if sound_id == 0 then
sound_id = minetest.sound_play("fire_fire", { sound_id = minetest.sound_play("fire_fire", {
object = obj, object = obj,
@ -153,7 +157,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
max_hear_distance = 16, max_hear_distance = 16,
loop = true, loop = true,
}) + 1 }) + 1
end end]]--
local hud_id local hud_id
if obj:is_player() then if obj:is_player() then
@ -163,7 +167,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 0.5, y = 0.5}, position = {x = 0.5, y = 0.5},
scale = {x = -100, y = -100}, scale = {x = -100, y = -100},
text = "fire_basic_flame.png", text = "mcl_burning_entity_flame_animated.png^[opacity:180^[verticalframe:" .. mcl_burning.animation_frames .. ":" .. 1,
z_index = 1000, z_index = 1000,
}) + 1 }) + 1
end end
@ -171,7 +175,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
mcl_burning.set(obj, "float", "burn_time", burn_time) mcl_burning.set(obj, "float", "burn_time", burn_time)
mcl_burning.set(obj, "string", "reason", reason) mcl_burning.set(obj, "string", "reason", reason)
mcl_burning.set(obj, "int", "hud_id", hud_id) mcl_burning.set(obj, "int", "hud_id", hud_id)
mcl_burning.set(obj, "int", "sound_id", sound_id) --mcl_burning.set(obj, "int", "sound_id", sound_id)
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire") local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
local minp, maxp = mcl_burning.get_collisionbox(obj) local minp, maxp = mcl_burning.get_collisionbox(obj)
@ -194,8 +198,8 @@ end
function mcl_burning.extinguish(obj) function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then if mcl_burning.is_burning(obj) then
local sound_id = mcl_burning.get(obj, "int", "sound_id") - 1 --local sound_id = mcl_burning.get(obj, "int", "sound_id") - 1
minetest.sound_stop(sound_id) --minetest.sound_stop(sound_id)
if obj:is_player() then if obj:is_player() then
local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1 local hud_id = mcl_burning.get(obj, "int", "hud_id") - 1
@ -206,7 +210,7 @@ function mcl_burning.extinguish(obj)
mcl_burning.set(obj, "float", "burn_time") mcl_burning.set(obj, "float", "burn_time")
mcl_burning.set(obj, "float", "damage_timer") mcl_burning.set(obj, "float", "damage_timer")
mcl_burning.set(obj, "int", "hud_id") mcl_burning.set(obj, "int", "hud_id")
mcl_burning.set(obj, "int", "sound_id") --mcl_burning.set(obj, "int", "sound_id")
end end
end end
@ -267,7 +271,7 @@ function mcl_burning.fire_entity_step(self, dtime)
if not parent or not mcl_burning.is_burning(parent) then if not parent or not mcl_burning.is_burning(parent) then
do_remove = true do_remove = true
else else
for _, other in ipairs(minetest.get_objects_inside_radius(obj:get_pos(), 0)) do for _, other in pairs(minetest.get_objects_inside_radius(obj:get_pos(), 0)) do
local luaentity = obj:get_luaentity() local luaentity = obj:get_luaentity()
if luaentity and luaentity.name == "mcl_burning:fire" and not luaentity.doing_step and not luaentity.removed then if luaentity and luaentity.name == "mcl_burning:fire" and not luaentity.doing_step and not luaentity.removed then
do_remove = true do_remove = true

View File

@ -22,7 +22,7 @@ minetest.register_entity("mcl_burning:fire", {
}) })
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(minetest.get_connected_players()) do
mcl_burning.tick(player, dtime) mcl_burning.tick(player, dtime)
end end
end) end)

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator("mcl_falling_nodes") local S = minetest.get_translator("mcl_falling_nodes")
local dmes = minetest.get_modpath("mcl_death_messages") ~= nil local dmes = minetest.get_modpath("mcl_death_messages") ~= nil
local has_mcl_armor = minetest.get_modpath("mcl_armor")
local is_creative_enabled = minetest.is_creative_enabled
local get_falling_depth = function(self) local get_falling_depth = function(self)
if not self._startpos then 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 if minetest.get_item_group(self.node.name, "falling_node_damage") == 0 then
return return
end end
-- Cause damage to any player it hits. -- Cause damage to any entity it hits.
-- Algorithm based on MC anvils. -- Algorithm based on MC anvils.
-- TODO: Support smashing other objects, too.
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not self._startpos then if not self._startpos then
-- Fallback -- Fallback
@ -23,12 +25,13 @@ local deal_falling_damage = function(self, dtime)
end end
local objs = minetest.get_objects_inside_radius(pos, 1) local objs = minetest.get_objects_inside_radius(pos, 1)
for _,v in ipairs(objs) do for _,v in ipairs(objs) do
if v:is_player() then
local hp = v:get_hp() 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 if not self._hit_players then
self._hit_players = {} self._hit_players = {}
end end
local name = v:get_player_name()
local hit = false local hit = false
for _,v in ipairs(self._hit_players) do for _,v in ipairs(self._hit_players) do
if name == v then if name == v then
@ -45,8 +48,16 @@ local deal_falling_damage = function(self, dtime)
if hp < 0 then if hp < 0 then
hp = 0 hp = 0
end end
if v:is_player() then -- Reduce damage if wearing a helmet
-- TODO: 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 is_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 local msg
if minetest.get_item_group(self.node.name, "anvil") ~= 0 then if minetest.get_item_group(self.node.name, "anvil") ~= 0 then
msg = S("@1 was smashed by a falling anvil.", v:get_player_name()) 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 if dmes then
mcl_death_messages.player_damage(v, msg) mcl_death_messages.player_damage(v, msg)
end end
end
v:set_hp(hp, { type = "punch", from = "mod" }) v:set_hp(hp, { type = "punch", from = "mod" })
end end
end 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
end end

View File

@ -1,3 +1,7 @@
local has_awards = minetest.get_modpath("awards")
mcl_item_entity = {}
--basic settings --basic settings
local item_drop_settings = {} --settings table local item_drop_settings = {} --settings table
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
@ -16,16 +20,33 @@ local get_gravity = function()
return tonumber(minetest.settings:get("movement_gravity")) or 9.81 return tonumber(minetest.settings:get("movement_gravity")) or 9.81
end end
local registered_pickup_achievement = {}
--TODO: remove limitation of 1 award per itemname
function mcl_item_entity.register_pickup_achievement(itemname, award)
if not has_awards then
minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing")
elseif registered_pickup_achievement[itemname] then
minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]")
else
registered_pickup_achievement[itemname] = award
end
end
mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
local check_pickup_achievements = function(object, player) local check_pickup_achievements = function(object, player)
if has_awards then
local itemname = ItemStack(object:get_luaentity().itemstring):get_name() local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
if minetest.get_item_group(itemname, "tree") ~= 0 then local playername = player:get_player_name()
awards.unlock(player:get_player_name(), "mcl:mineWood") for name,award in pairs(registered_pickup_achievement) do
elseif itemname == "mcl_mobitems:blaze_rod" then if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
awards.unlock(player:get_player_name(), "mcl:blazeRod") awards.unlock(playername, award)
elseif itemname == "mcl_mobitems:leather" then end
awards.unlock(player:get_player_name(), "mcl:killCow") end
elseif itemname == "mcl_core:diamond" then
awards.unlock(player:get_player_name(), "mcl:diamonds")
end end
end end
@ -54,14 +75,14 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement
end end
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
for _,player in ipairs(minetest.get_connected_players()) do for _,player in pairs(minetest.get_connected_players()) do
if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
local pos = player:get_pos() local pos = player:get_pos()
local inv = player:get_inventory() local inv = player:get_inventory()
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z} local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
--magnet and collection --magnet and collection
for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
local collected = false local collected = false
@ -165,66 +186,6 @@ minetest.register_globalstep(function(dtime)
end end
end) end)
local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
local basegroups = { "pickaxey", "axey", "shovely" }
local materials = { "wood", "gold", "stone", "iron", "diamond" }
-- Checks if the given node would drop its useful drop if dug by a tool
-- with the given tool capabilities. Returns true if it will yield its useful
-- drop, false otherwise.
local check_can_drop = function(node_name, tool_capabilities)
local handy = minetest.get_item_group(node_name, "handy")
local dig_immediate = minetest.get_item_group(node_name, "dig_immediate")
if handy == 1 or dig_immediate == 2 or dig_immediate == 3 then
return true
else
local toolgroupcaps
if tool_capabilities then
toolgroupcaps = tool_capabilities.groupcaps
else
return false
end
-- Compare node groups with tool capabilities
for m=1, #minigroups do
local minigroup = minigroups[m]
local g = minetest.get_item_group(node_name, minigroup)
if g ~= 0 then
local plus = minigroup .. "_dig"
if toolgroupcaps[plus] then
return true
end
for e=1,5 do
local effplus = plus .. "_efficiency_" .. e
if toolgroupcaps[effplus] then
return true
end
end
end
end
for b=1, #basegroups do
local basegroup = basegroups[b]
local g = minetest.get_item_group(node_name, basegroup)
if g ~= 0 then
for m=g, #materials do
local plus = basegroup .. "_dig_"..materials[m]
if toolgroupcaps[plus] then
return true
end
for e=1,5 do
local effplus = plus .. "_efficiency_" .. e
if toolgroupcaps[effplus] then
return true
end
end
end
end
end
return false
end
end
-- Stupid workaround to get drops from a drop table: -- Stupid workaround to get drops from a drop table:
-- Create a temporary table in minetest.registered_nodes that contains the proper drops, -- 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 -- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition
@ -281,17 +242,20 @@ function minetest.handle_node_drops(pos, drops, digger)
-- Check if node will yield its useful drop by the digger's tool -- Check if node will yield its useful drop by the digger's tool
local dug_node = minetest.get_node(pos) local dug_node = minetest.get_node(pos)
local toolcaps local tooldef
local tool local tool
if digger ~= nil then if digger ~= nil then
tool = digger:get_wielded_item() tool = digger:get_wielded_item()
toolcaps = tool:get_tool_capabilities() tooldef = minetest.registered_tools[tool:get_name()]
if not check_can_drop(dug_node.name, toolcaps) then if not mcl_autogroup.can_harvest(dug_node.name, tool:get_name()) then
return return
end end
end end
local diggroups = tooldef and tooldef._mcl_diggroups
local shearsy_level = diggroups and diggroups.shearsy and diggroups.shearsy.level
--[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop --[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop
from the node definition. from the node definition.
Definition of _mcl_shears_drop / _mcl_silk_touch_drop: Definition of _mcl_shears_drop / _mcl_silk_touch_drop:
@ -303,7 +267,7 @@ function minetest.handle_node_drops(pos, drops, digger)
local silk_touch_drop = false local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name] local nodedef = minetest.registered_nodes[dug_node.name]
if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then if shearsy_level and shearsy_level > 0 and nodedef._mcl_shears_drop then
if nodedef._mcl_shears_drop == true then if nodedef._mcl_shears_drop == true then
drops = { dug_node.name } drops = { dug_node.name }
else else
@ -785,7 +749,7 @@ minetest.register_entity(":__builtin:item", {
if self.physical_state then if self.physical_state then
local own_stack = ItemStack(self.object:get_luaentity().itemstring) local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-- Merge with close entities of the same item -- Merge with close entities of the same item
for _, object in ipairs(minetest.get_objects_inside_radius(p, 0.8)) do for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
local obj = object:get_luaentity() local obj = object:get_luaentity()
if obj and obj.name == "__builtin:item" if obj and obj.name == "__builtin:item"
and obj.physical_state == false then and obj.physical_state == false then

View File

@ -1,5 +1,7 @@
local S = minetest.get_translator("mcl_minecarts") local S = minetest.get_translator("mcl_minecarts")
local has_mcl_wip = minetest.get_modpath("mcl_wip")
mcl_minecarts = {} mcl_minecarts = {}
mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts") mcl_minecarts.modpath = minetest.get_modpath("mcl_minecarts")
mcl_minecarts.speed_max = 10 mcl_minecarts.speed_max = 10
@ -663,8 +665,6 @@ register_minecart(
{"mcl_minecarts:minecart", "mcl_chests:chest"}, {"mcl_minecarts:minecart", "mcl_chests:chest"},
nil, nil, false) nil, nil, false)
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
-- Minecart with Furnace -- Minecart with Furnace
register_minecart( register_minecart(
"mcl_minecarts:furnace_minecart", "mcl_minecarts:furnace_minecart",
@ -719,8 +719,6 @@ register_minecart(
end, nil, false end, nil, false
) )
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
-- Minecart with Command Block -- Minecart with Command Block
register_minecart( register_minecart(
"mcl_minecarts:command_block_minecart", "mcl_minecarts:command_block_minecart",
@ -742,8 +740,6 @@ register_minecart(
nil, nil, false nil, nil, false
) )
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
-- Minecart with Hopper -- Minecart with Hopper
register_minecart( register_minecart(
"mcl_minecarts:hopper_minecart", "mcl_minecarts:hopper_minecart",
@ -762,8 +758,6 @@ register_minecart(
nil, nil, false nil, nil, false
) )
mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart")
-- Minecart with TNT -- Minecart with TNT
register_minecart( register_minecart(
"mcl_minecarts:tnt_minecart", "mcl_minecarts:tnt_minecart",
@ -824,29 +818,34 @@ minetest.register_craft({
-- TODO: Re-enable crafting of special minecarts when they have been implemented -- TODO: Re-enable crafting of special minecarts when they have been implemented
if false then if false then
minetest.register_craft({
minetest.register_craft({
output = "mcl_minecarts:furnace_minecart", output = "mcl_minecarts:furnace_minecart",
recipe = { recipe = {
{"mcl_furnaces:furnace"}, {"mcl_furnaces:furnace"},
{"mcl_minecarts:minecart"}, {"mcl_minecarts:minecart"},
}, },
}) })
minetest.register_craft({ minetest.register_craft({
output = "mcl_minecarts:hopper_minecart", output = "mcl_minecarts:hopper_minecart",
recipe = { recipe = {
{"mcl_hoppers:hopper"}, {"mcl_hoppers:hopper"},
{"mcl_minecarts:minecart"}, {"mcl_minecarts:minecart"},
}, },
}) })
minetest.register_craft({ minetest.register_craft({
output = "mcl_minecarts:chest_minecart", output = "mcl_minecarts:chest_minecart",
recipe = { recipe = {
{"mcl_chests:chest"}, {"mcl_chests:chest"},
{"mcl_minecarts:minecart"}, {"mcl_minecarts:minecart"},
}, },
}) })
end
if has_mcl_wip then
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
mcl_wip.register_wip_item("mcl_minecarts:hopper_minecart")
end end

View File

@ -1,6 +1,6 @@
name = mcl_minecarts name = mcl_minecarts
author = Krock author = Krock
description = Minecarts are vehicles to move players quickly on rails. description = Minecarts are vehicles to move players quickly on rails.
depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_wip depends = mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons
optional_depends = doc_identifier optional_depends = doc_identifier, mcl_wip

View File

@ -226,7 +226,7 @@ local collision = function(self)
local z = 0 local z = 0
local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5
for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
if object:is_player() if object:is_player()
or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then
@ -283,6 +283,33 @@ local get_velocity = function(self)
return 0 return 0
end 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 -- set and return valid yaw
local set_yaw = function(self, yaw, delay, dtime) 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 yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
end end
self.object:set_yaw(yaw) self.object:set_yaw(yaw)
update_roll(self)
return yaw return yaw
end end
@ -645,9 +673,9 @@ local update_tag = function(self)
nametag = tag, nametag = tag,
}) })
update_roll(self)
end end
-- drop items -- drop items
local item_drop = function(self, cooked, looting_level) local item_drop = function(self, cooked, looting_level)
@ -1047,8 +1075,13 @@ local do_env_damage = function(self)
end end
end end
-- Use get_node_light for Minetest version 5.3 where get_natural_light
-- does not exist yet.
local get_light = minetest.get_natural_light or minetest.get_node_light
local sunlight = get_light(pos, self.time_of_day)
-- bright light harms mob -- bright light harms mob
if self.light_damage ~= 0 and (minetest.get_node_light(pos) or 0) > 12 then if self.light_damage ~= 0 and (sunlight or 0) > 12 then
if deal_light_damage(self, pos, self.light_damage) then if deal_light_damage(self, pos, self.light_damage) then
return true return true
end end
@ -1057,7 +1090,7 @@ local do_env_damage = function(self)
if mod_worlds then if mod_worlds then
_, dim = mcl_worlds.y_to_layer(pos.y) _, dim = mcl_worlds.y_to_layer(pos.y)
end end
if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (minetest.get_node_light(pos) or 0) >= minetest.LIGHT_MAX and dim == "overworld" then if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then
if self.ignited_by_sunlight then if self.ignited_by_sunlight then
mcl_burning.set_on_fire(self.object, 10) mcl_burning.set_on_fire(self.object, 10)
else else
@ -2821,7 +2854,7 @@ local falling = function(self, pos)
end end
if mcl_portals ~= nil then 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 return false -- mob has teleported through Nether portal - it's 99% not falling
end end
end end
@ -2851,6 +2884,18 @@ local falling = function(self, pos)
self.object:set_acceleration({x = 0, y = 0, z = 0}) self.object:set_acceleration({x = 0, y = 0, z = 0})
end 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 -- in water then float up
if minetest.registered_nodes[node_ok(pos).name].groups.water then if minetest.registered_nodes[node_ok(pos).name].groups.water then
@ -3470,6 +3515,7 @@ local mob_step = function(self, dtime)
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
end end
self.object:set_yaw(yaw) self.object:set_yaw(yaw)
update_roll(self)
end end
-- end rotation -- end rotation
@ -3768,6 +3814,7 @@ minetest.register_entity(name, {
knock_back = def.knock_back ~= false, knock_back = def.knock_back ~= false,
shoot_offset = def.shoot_offset or 0, shoot_offset = def.shoot_offset or 0,
floats = def.floats or 1, -- floats in water by default 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_rate = def.replace_rate,
replace_what = def.replace_what, replace_what = def.replace_what,
replace_with = def.replace_with, replace_with = def.replace_with,
@ -4576,9 +4623,9 @@ local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime timer = timer + dtime
if timer < 1 then return end if timer < 1 then return end
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(minetest.get_connected_players()) do
local pos = player:get_pos() local pos = player:get_pos()
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 47)) do for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do
local lua = obj:get_luaentity() local lua = obj:get_luaentity()
if lua and lua._cmi_is_mob then if lua and lua._cmi_is_mob then
lua.lifetimer = math.max(20, lua.lifetimer) lua.lifetimer = math.max(20, lua.lifetimer)

View File

@ -191,6 +191,14 @@ minetest.register_craftitem("mcl_paintings:painting", {
if pointed_thing.type ~= "node" then if pointed_thing.type ~= "node" then
return itemstack return itemstack
end end
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
local dir = vector.subtract(pointed_thing.above, pointed_thing.under) local dir = vector.subtract(pointed_thing.above, pointed_thing.under)
dir = vector.normalize(dir) dir = vector.normalize(dir)
if dir.y ~= 0 then if dir.y ~= 0 then

View File

@ -521,7 +521,7 @@ if c("totem") then
-- Totem of Undying -- Totem of Undying
minetest.register_craftitem("mobs_mc:totem", { minetest.register_craftitem("mobs_mc:totem", {
description = S("Totem of Undying"), description = S("Totem of Undying"),
_tt_help = minetest.colorize("#00FF00", S("Protects you from death while wielding it")), _tt_help = minetest.colorize(mcl_colors.GREEN, S("Protects you from death while wielding it")),
_doc_items_longdesc = S("A totem of undying is a rare artifact which may safe you from certain death."), _doc_items_longdesc = S("A totem of undying is a rare artifact which may safe you from certain death."),
_doc_items_usagehelp = S("The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however."), _doc_items_usagehelp = S("The totem only works while you hold it in your hand. If you receive fatal damage, you are saved from death and you get a second chance with 1 HP. The totem is destroyed in the process, however."),
inventory_image = "mcl_totems_totem.png", inventory_image = "mcl_totems_totem.png",

View File

@ -122,7 +122,7 @@ local arrows = {
} }
local throwing_shoot_arrow = function(itemstack, player) local throwing_shoot_arrow = function(itemstack, player)
for _,arrow in ipairs(arrows) do for _,arrow in pairs(arrows) do
if player:get_inventory():get_stack("main", player:get_wield_index()+1):get_name() == arrow[1] then if player:get_inventory():get_stack("main", player:get_wield_index()+1):get_name() == arrow[1] then
if not minetest.is_creative_enabled(player:get_player_name()) then if not minetest.is_creative_enabled(player:get_player_name()) then
player:get_inventory():remove_item("main", arrow[1]) player:get_inventory():remove_item("main", arrow[1])

View File

@ -1,6 +1,6 @@
name = mobs_mc name = mobs_mc
author = maikerumine author = maikerumine
description = Adds Minecraft-like monsters and animals. description = Adds Minecraft-like monsters and animals.
depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip depends = mcl_init, mcl_particles, mcl_mobs, mcl_wip, mcl_colors
optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, mobs_mc_gameconfig, doc_items optional_depends = default, mcl_tnt, mcl_bows, mcl_throwing, mcl_fishing, bones, mesecons_materials, mobs_mc_gameconfig, doc_items

View File

@ -25,6 +25,19 @@ local colors = {
unicolor_black = { mobs_mc.items.wool_black, "#000000D0" }, 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 if minetest.get_modpath("mcl_wool") ~= nil then
colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" } colors["unicolor_light_blue"] = { mobs_mc.items.wool_light_blue, "#5050FFD0" }
end end
@ -112,7 +125,7 @@ mobs:register_mob("mobs_mc:sheep", {
end, end,
-- Set random color on spawn -- Set random color on spawn
do_custom = function(self) do_custom = function(self, dtime)
if not self.initial_color_set then if not self.initial_color_set then
local r = math.random(0,100000) local r = math.random(0,100000)
local textures local textures
@ -149,6 +162,33 @@ mobs:register_mob("mobs_mc:sheep", {
} }
self.initial_color_set = true self.initial_color_set = true
end 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, end,
on_rightclick = function(self, clicker) on_rightclick = function(self, clicker)

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -516,7 +516,7 @@ local function show_trade_formspec(playername, trader, tradenum)
"size[9,8.75]" "size[9,8.75]"
.."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]" .."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]"
..disabled_img ..disabled_img
.."label[4,0;"..F(minetest.colorize("#313131", S(profession))).."]" .."label[4,0;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S(profession))).."]"
.."list[current_player;main;0,4.5;9,3;9]" .."list[current_player;main;0,4.5;9,3;9]"
.."list[current_player;main;0,7.74;9,1;]" .."list[current_player;main;0,7.74;9,1;]"
..b_prev..b_next ..b_prev..b_next
@ -960,13 +960,17 @@ mobs:register_mob("mobs_mc:villager", {
"mobs_mc_villager_smith.png", --hat "mobs_mc_villager_smith.png", --hat
}, },
}, },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
makes_footstep_sound = true, makes_footstep_sound = true,
walk_velocity = 1.2, walk_velocity = 1.2,
run_velocity = 2.4, run_velocity = 2.4,
drops = {}, drops = {},
can_despawn = false, can_despawn = false,
-- TODO: sounds -- TODO: sounds
sounds = {
random = "mobs_mc_villager",
distance = 10,
},
animation = { animation = {
stand_speed = 25, stand_speed = 25,
stand_start = 40, stand_start = 40,

View File

@ -28,7 +28,7 @@ mobs:register_mob("mobs_mc:evoker", {
"blank.png", --no hat "blank.png", --no hat
-- TODO: Attack glow -- TODO: Attack glow
} }, } },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
makes_footstep_sound = true, makes_footstep_sound = true,
damage = 6, damage = 6,
walk_velocity = 0.2, walk_velocity = 0.2,

View File

@ -36,7 +36,7 @@ mobs:register_mob("mobs_mc:illusioner", {
-- TODO: more sounds -- TODO: more sounds
distance = 16, distance = 16,
}, },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
walk_velocity = 0.6, walk_velocity = 0.6,
run_velocity = 2, run_velocity = 2,
jump = true, jump = true,

View File

@ -30,7 +30,7 @@ mobs:register_mob("mobs_mc:vindicator", {
-- TODO: Glow when attacking (mobs_mc_vindicator.png) -- TODO: Glow when attacking (mobs_mc_vindicator.png)
}, },
}, },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
makes_footstep_sound = true, makes_footstep_sound = true,
damage = 13, damage = 13,
reach = 2, reach = 2,

View File

@ -45,7 +45,7 @@ mobs:register_mob("mobs_mc:villager_zombie", {
{"mobs_mc_zombie_smith.png"}, {"mobs_mc_zombie_smith.png"},
{"mobs_mc_zombie_villager.png"} {"mobs_mc_zombie_villager.png"}
}, },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
makes_footstep_sound = true, makes_footstep_sound = true,
damage = 3, damage = 3,
reach = 2, reach = 2,

View File

@ -25,7 +25,7 @@ mobs:register_mob("mobs_mc:witch", {
textures = { textures = {
{"mobs_mc_witch.png"}, {"mobs_mc_witch.png"},
}, },
visual_size = {x=3, y=3}, visual_size = {x=2.75, y=2.75},
makes_footstep_sound = true, makes_footstep_sound = true,
damage = 2, damage = 2,
reach = 2, reach = 2,

View File

@ -16,7 +16,7 @@ mobs:register_mob("mobs_mc:wither", {
hp_min = 300, hp_min = 300,
xp_min = 50, xp_min = 50,
xp_max = 50, xp_max = 50,
armor = {undead = 80, fleshy = 80}, armor = {undead = 80, fleshy = 100},
-- This deviates from MC Wiki's size, which makes no sense -- This deviates from MC Wiki's size, which makes no sense
collisionbox = {-0.9, 0.4, -0.9, 0.9, 2.45, 0.9}, collisionbox = {-0.9, 0.4, -0.9, 0.9, 2.45, 0.9},
visual = "mesh", visual = "mesh",
@ -66,6 +66,14 @@ mobs:register_mob("mobs_mc:wither", {
run_start = 0, run_end = 20, run_start = 0, run_end = 20,
}, },
harmed_by_heal = true, harmed_by_heal = true,
do_custom = function(self)
if self.health < (self.hp_max / 2) then
self.base_texture = "mobs_mc_wither_half_health.png"
self.fly = false
self.object:set_properties({textures={self.base_texture}})
self.armor = {undead = 80, fleshy = 80}
end
end,
on_spawn = function(self) on_spawn = function(self)
minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64})
end, end,

View File

@ -27,7 +27,7 @@ minetest.register_globalstep(function(dtime)
if timer < 0.7 then return end if timer < 0.7 then return end
timer = 0 timer = 0
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(minetest.get_connected_players()) do
if not mcl_worlds.has_dust(player:get_pos()) then if not mcl_worlds.has_dust(player:get_pos()) then
return false return false
end end

View File

@ -1,6 +1,8 @@
local PARTICLES_COUNT_RAIN = 30 local PARTICLES_COUNT_RAIN = 30
local PARTICLES_COUNT_THUNDER = 45 local PARTICLES_COUNT_THUNDER = 45
local get_connected_players = minetest.get_connected_players
mcl_weather.rain = { mcl_weather.rain = {
-- max rain particles created at time -- max rain particles created at time
particles_count = PARTICLES_COUNT_RAIN, particles_count = PARTICLES_COUNT_RAIN,
@ -36,7 +38,7 @@ mcl_weather.rain.set_sky_box = function()
{r=85, g=86, b=98}, {r=85, g=86, b=98},
{r=0, g=0, b=0}}) {r=0, g=0, b=0}})
mcl_weather.skycolor.active = true mcl_weather.skycolor.active = true
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
player:set_clouds({color="#5D5D5FE8"}) player:set_clouds({color="#5D5D5FE8"})
end end
end end
@ -154,7 +156,7 @@ mcl_weather.rain.clear = function()
mcl_weather.rain.init_done = false mcl_weather.rain.init_done = false
mcl_weather.rain.set_particles_mode("rain") mcl_weather.rain.set_particles_mode("rain")
mcl_weather.skycolor.remove_layer("weather-pack-rain-sky") mcl_weather.skycolor.remove_layer("weather-pack-rain-sky")
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
mcl_weather.rain.remove_sound(player) mcl_weather.rain.remove_sound(player)
mcl_weather.rain.remove_player(player) mcl_weather.rain.remove_player(player)
end end
@ -176,7 +178,7 @@ mcl_weather.rain.make_weather = function()
mcl_weather.rain.init_done = true mcl_weather.rain.init_done = true
end end
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then
mcl_weather.rain.remove_sound(player) mcl_weather.rain.remove_sound(player)
return false return false

View File

@ -43,7 +43,7 @@ mcl_weather.skycolor = {
-- Remove layer from colors table -- Remove layer from colors table
remove_layer = function(layer_name) remove_layer = function(layer_name)
for k, name in ipairs(mcl_weather.skycolor.layer_names) do for k, name in pairs(mcl_weather.skycolor.layer_names) do
if name == layer_name then if name == layer_name then
table.remove(mcl_weather.skycolor.layer_names, k) table.remove(mcl_weather.skycolor.layer_names, k)
mcl_weather.skycolor.force_update = true mcl_weather.skycolor.force_update = true

View File

@ -1,3 +1,5 @@
local get_connected_players = minetest.get_connected_players
mcl_weather.snow = {} mcl_weather.snow = {}
mcl_weather.snow.particles_count = 15 mcl_weather.snow.particles_count = 15
@ -37,7 +39,7 @@ mcl_weather.snow.set_sky_box = function()
{r=85, g=86, b=86}, {r=85, g=86, b=86},
{r=0, g=0, b=0}}) {r=0, g=0, b=0}})
mcl_weather.skycolor.active = true mcl_weather.skycolor.active = true
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
player:set_clouds({color="#ADADADE8"}) player:set_clouds({color="#ADADADE8"})
end end
mcl_weather.skycolor.active = true mcl_weather.skycolor.active = true
@ -71,7 +73,7 @@ minetest.register_globalstep(function(dtime)
mcl_weather.snow.init_done = true mcl_weather.snow.init_done = true
end end
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then
return false return false
end end

View File

@ -1,3 +1,5 @@
local get_connected_players = minetest.get_connected_players
-- turn off lightning mod 'auto mode' -- turn off lightning mod 'auto mode'
lightning.auto = false lightning.auto = false
@ -25,7 +27,7 @@ minetest.register_globalstep(function(dtime)
{r=40, g=40, b=40}, {r=40, g=40, b=40},
{r=0, g=0, b=0}}) {r=0, g=0, b=0}})
mcl_weather.skycolor.active = true mcl_weather.skycolor.active = true
for _, player in ipairs(minetest.get_connected_players()) do for _, player in pairs(get_connected_players()) do
player:set_clouds({color="#3D3D3FE8"}) player:set_clouds({color="#3D3D3FE8"})
end end
mcl_weather.thunder.init_done = true mcl_weather.thunder.init_done = true

View File

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

View File

@ -1,13 +1,7 @@
local S = minetest.get_translator("doc") local S = minetest.get_translator("doc")
local F = function(f) return minetest.formspec_escape(S(f)) end local F = function(f) return minetest.formspec_escape(S(f)) end
-- Compability for 0.4.14 or earlier local colorize = minetest.colorize
local colorize
if minetest.colorize then
colorize = minetest.colorize
else
colorize = function(color, text) return text end
end
doc = {} doc = {}
@ -41,10 +35,10 @@ doc.FORMSPEC.ENTRY_HEIGHT = doc.FORMSPEC.ENTRY_END_Y - doc.FORMSPEC.ENTRY_START_
-- Internal helper variables -- Internal helper variables
local DOC_INTRO = S("This is the help.") local DOC_INTRO = S("This is the help.")
local COLOR_NOT_VIEWED = "#00FFFF" -- cyan local COLOR_NOT_VIEWED = mcl_colors.AQUA
local COLOR_VIEWED = "#FFFFFF" -- white local COLOR_VIEWED = mcl_colors.WHITE
local COLOR_HIDDEN = "#999999" -- gray local COLOR_HIDDEN = mcl_colors.GRAY
local COLOR_ERROR = "#FF0000" -- red local COLOR_ERROR = mcl_colors.RED
local CATEGORYFIELDSIZE = { local CATEGORYFIELDSIZE = {
WIDTH = math.ceil(doc.FORMSPEC.WIDTH / 4), WIDTH = math.ceil(doc.FORMSPEC.WIDTH / 4),
@ -776,7 +770,7 @@ function doc.generate_entry_list(cid, playername)
if name == nil or name == "" then if name == nil or name == "" then
name = S("Nameless entry (@1)", eid) name = S("Nameless entry (@1)", eid)
if doc.entry_viewed(playername, cid, eid) then if doc.entry_viewed(playername, cid, eid) then
viewedprefix = "#FF4444" viewedprefix = mcl_colors.RED
else else
viewedprefix = COLOR_ERROR viewedprefix = COLOR_ERROR
end end

View File

@ -2,3 +2,4 @@ name = doc
author = Wuzzy author = Wuzzy
description = A simple in-game documentation system which enables mods to add help entries based on templates. description = A simple in-game documentation system which enables mods to add help entries based on templates.
optional_depends = unified_inventory, sfinv_buttons, central_message, inventory_plus optional_depends = unified_inventory, sfinv_buttons, central_message, inventory_plus
depends = mcl_colors

View File

@ -410,7 +410,7 @@ local function get_tooltip(item, groups, cooktime, burntime)
local tooltip local tooltip
if groups then if groups then
local gcol = "#FFAAFF" local gcol = mcl_colors.LIGHT_PURPLE
if #groups == 1 then if #groups == 1 then
local g = group_names[groups[1]] local g = group_names[groups[1]]
local groupstr local groupstr
@ -446,12 +446,12 @@ local function get_tooltip(item, groups, cooktime, burntime)
if not groups and cooktime then if not groups and cooktime then
tooltip = tooltip .. "\n" .. tooltip = tooltip .. "\n" ..
S("Cooking time: @1", colorize("yellow", cooktime)) S("Cooking time: @1", colorize(mcl_colors.YELLOW, cooktime))
end end
if not groups and burntime then if not groups and burntime then
tooltip = tooltip .. "\n" .. tooltip = tooltip .. "\n" ..
S("Burning time: @1", colorize("yellow", burntime)) S("Burning time: @1", colorize(mcl_colors.YELLOW, burntime))
end end
return fmt(FMT.tooltip, item, ESC(tooltip)) return fmt(FMT.tooltip, item, ESC(tooltip))
@ -668,7 +668,7 @@ local function make_formspec(name)
fs[#fs + 1] = fmt("label[%f,%f;%s]", fs[#fs + 1] = fmt("label[%f,%f;%s]",
sfinv_only and 6.3 or data.iX - 2.2, sfinv_only and 6.3 or data.iX - 2.2,
0.22, 0.22,
ESC(colorize("#383838", fmt("%s / %u", data.pagenum, data.pagemax)))) ESC(colorize(mcl_colors.DARK_GRAY, fmt("%s / %u", data.pagenum, data.pagemax))))
fs[#fs + 1] = fmt([[ fs[#fs + 1] = fmt([[
image_button[%f,0.12;0.8,0.8;craftguide_prev_icon.png;prev;] image_button[%f,0.12;0.8,0.8;craftguide_prev_icon.png;prev;]

View File

@ -1,5 +1,5 @@
name = mcl_craftguide name = mcl_craftguide
author = kilbith author = kilbith
description = The most comprehensive Crafting Guide on Minetest. description = The most comprehensive Crafting Guide on Minetest.
depends = mcl_core, mcl_compass, mcl_clock, doc depends = mcl_core, mcl_compass, mcl_clock, doc, mcl_colors
optional_depends = sfinv, sfinv_buttons optional_depends = sfinv, sfinv_buttons

View File

@ -1,4 +1,4 @@
name = mcl_tt name = mcl_tt
author = Wuzzy author = Wuzzy
description = Add MCL2 tooltips description = Add MCL2 tooltips
depends = tt, mcl_enchanting depends = tt, mcl_enchanting, mcl_colors

View File

@ -77,7 +77,7 @@ end)
tt.register_snippet(function(itemstring) tt.register_snippet(function(itemstring)
local def = minetest.registered_items[itemstring] local def = minetest.registered_items[itemstring]
if minetest.get_item_group(itemstring, "crush_after_fall") == 1 then if minetest.get_item_group(itemstring, "crush_after_fall") == 1 then
return S("Deals damage when falling"), "#FFFF00" return S("Deals damage when falling"), mcl_colors.YELLOW
end end
end) end)

View File

@ -1,7 +1,8 @@
tt = {} tt = {}
tt.COLOR_DEFAULT = "#d0ffd0" tt.COLOR_DEFAULT = mcl_colors.GREEN
tt.COLOR_DANGER = "#ffff00" tt.COLOR_DANGER = mcl_colors.YELLOW
tt.COLOR_GOOD = "#00ff00" tt.COLOR_GOOD = mcl_colors.GREEN
tt.NAME_COLOR = mcl_colors.YELLOW
-- API -- API
tt.registered_snippets = {} tt.registered_snippets = {}
@ -63,12 +64,15 @@ tt.reload_itemstack_description = function(itemstack)
local meta = itemstack:get_meta() local meta = itemstack:get_meta()
if def and def._mcl_generate_description then if def and def._mcl_generate_description then
def._mcl_generate_description(itemstack) def._mcl_generate_description(itemstack)
elseif should_change(itemstring, def) and meta:get_string("name") == "" then elseif should_change(itemstring, def) then
local toolcaps local toolcaps
if def.tool_capabilities then if def.tool_capabilities then
toolcaps = itemstack:get_tool_capabilities() toolcaps = itemstack:get_tool_capabilities()
end end
local orig_desc = def._tt_original_description or def.description 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) local desc = apply_snippets(orig_desc, itemstring, toolcaps or def.tool_capabilities, itemstack)
if desc ~= orig_desc then if desc ~= orig_desc then
meta:set_string("description", desc) meta:set_string("description", desc)

View File

@ -1,3 +1,4 @@
name = tt name = tt
author = Wuzzy author = Wuzzy
description = Support for custom tooltip extensions for items description = Support for custom tooltip extensions for items
depends = mcl_colors

View File

@ -214,7 +214,7 @@ function awards.unlock(name, award)
-- Get award -- Get award
minetest.log("action", name.." has gotten award "..award) minetest.log("action", name.." has gotten award "..award)
minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize("#51EF4E", "[" .. (awdef.title or award) .. "]"))) minetest.chat_send_all(S("@1 has made the achievement @2", name, minetest.colorize(mcl_colors.GREEN, "[" .. (awdef.title or award) .. "]")))
data.unlocked[award] = award data.unlocked[award] = award
awards.save() awards.save()
@ -447,7 +447,7 @@ function awards.getFormspec(name, to, sid)
first = false first = false
if def.secret and not award.got then if def.secret and not award.got then
formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)")) formspec = formspec .. mcl_colors.DARK_GRAY..minetest.formspec_escape(S("(Secret Award)"))
else else
local title = award.name local title = award.name
if def and def.title then if def and def.title then
@ -456,7 +456,7 @@ function awards.getFormspec(name, to, sid)
if award.got then if award.got then
formspec = formspec .. minetest.formspec_escape(title) formspec = formspec .. minetest.formspec_escape(title)
else else
formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title) formspec = formspec .. mcl_colors.GRAY.. minetest.formspec_escape(title)
end end
end end
end end

View File

@ -6,3 +6,4 @@ license = LGPL 2.1 or later
forum = https://forum.minetest.net/viewtopic.php?t=4870 forum = https://forum.minetest.net/viewtopic.php?t=4870
version = 2.3.0 version = 2.3.0
optional_depends = sfinv, unified_inventory optional_depends = sfinv, unified_inventory
depends = mcl_colors

View File

@ -238,3 +238,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
awards.show_to(name, name, nil, false) awards.show_to(name, name, nil, false)
end end
end) end)
awards.register_achievement("mcl:stoneAge", {
title = S("Stone Age"),
description = S("Mine a stone with new pickaxe."),
icon = "default_cobble.png",
})
awards.register_achievement("mcl:hotStuff", {
title = S("Hot Stuff"),
description = S("Put lava in a bucket."),
icon = "bucket_lava.png",
})
awards.register_achievement("mcl:obsidian", {
title = S("Ice Bucket Challenge"),
description = S("Obtain an obsidian block."),
icon = "default_obsidian.png",
})

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator("mcl_death_messages") local S = minetest.get_translator("mcl_death_messages")
local N = function(s) return s end local N = function(s) return s end
local C = minetest.colorize
local color_skyblue = mcl_colors.AQUA
local function get_tool_name(item) local function get_tool_name(item)
local name = item:get_meta():get_string("name") local name = item:get_meta():get_string("name")
@ -41,6 +44,9 @@ local msgs = {
["murder"] = { ["murder"] = {
N("@1 was slain by @2 using [@3]"), N("@1 was slain by @2 using [@3]"),
}, },
["murder_hand"] = {
N("@1 was slain by @2"),
},
["murder_any"] = { ["murder_any"] = {
N("@1 was killed."), N("@1 was killed."),
}, },
@ -131,7 +137,7 @@ local last_damages = { }
minetest.register_on_dieplayer(function(player, reason) minetest.register_on_dieplayer(function(player, reason)
-- Death message -- 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 if message == nil then
message = true message = true
end end
@ -201,7 +207,11 @@ minetest.register_on_dieplayer(function(player, reason)
elseif hitter:is_player() then elseif hitter:is_player() then
hittername = hitter:get_player_name() hittername = hitter:get_player_name()
if hittername ~= nil then 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 else
msg = dmsg("murder_any", name) msg = dmsg("murder_any", name)
end end
@ -229,7 +239,7 @@ minetest.register_on_dieplayer(function(player, reason)
if shooter == nil then if shooter == nil then
msg = dmsg("arrow", name) msg = dmsg("arrow", name)
elseif shooter:is_player() then 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 elseif s_ent and s_ent._cmi_is_mob then
if s_ent.nametag ~= "" then if s_ent.nametag ~= "" then
msg = dmsg("arrow_name", name, shooter:get_player_name(), get_tool_name(shooter:get_wielded_item())) 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 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 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 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 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 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 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 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 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 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 baby husk.=@1 был(а) убит(а) машылом-кадавром.
@1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком. @1 was killed by a zombie pigman.=@1 был(а) убит(а) зомби-свиночеловеком.
@1 was killed by a baby 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 baby husk.=
@1 was killed by a zombie pigman.= @1 was killed by a zombie pigman.=
@1 was killed by a baby 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 name = mcl_death_messages
author = 4Evergreen4 author = 4Evergreen4
description = Shows messages in chat when a player dies. description = Shows messages in chat when a player dies.
depends = mcl_colors

View File

@ -118,7 +118,7 @@ minetest.register_globalstep(function(dtime)
if main_timer > mcl_hbarmor.tick or timer > 4 then if main_timer > mcl_hbarmor.tick or timer > 4 then
if minetest.settings:get_bool("enable_damage") then if minetest.settings:get_bool("enable_damage") then
if main_timer > mcl_hbarmor.tick then main_timer = 0 end if main_timer > mcl_hbarmor.tick then main_timer = 0 end
for _,player in ipairs(minetest.get_connected_players()) do for _,player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name() local name = player:get_player_name()
if mcl_hbarmor.player_active[name] == true then if mcl_hbarmor.player_active[name] == true then
local ret = mcl_hbarmor.get_armor(player) local ret = mcl_hbarmor.get_armor(player)

View File

@ -442,7 +442,7 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
end end
local caption = "" local caption = ""
if name ~= "inv" and filtername[name] then if name ~= "inv" and filtername[name] then
caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]" caption = "label[0,1.2;"..F(minetest.colorize(mcl_colors.DARK_GRAY, filtername[name])).."]"
end end
formspec = "size[10,9.3]".. formspec = "size[10,9.3]"..
@ -489,8 +489,8 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
if filter == nil then if filter == nil then
filter = "" filter = ""
end end
formspec = formspec .. "field[5.3,1.34;4,0.75;suche;;"..minetest.formspec_escape(filter).."]" formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]"
formspec = formspec .. "field_close_on_enter[suche;false]" formspec = formspec .. "field_close_on_enter[search;false]"
end end
if pagenum ~= nil then formspec = formspec .. "p"..tostring(pagenum) 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 elseif fields.inv then
if players[name].page == "inv" then return end if players[name].page == "inv" then return end
page = "inv" 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) set_inv_page("all", player)
page = "nix" page = "nix"
elseif fields.suche ~= nil and not fields.creative_next and not fields.creative_prev then elseif fields.search ~= nil and not fields.creative_next and not fields.creative_prev then
set_inv_search(string.lower(fields.suche),player) set_inv_search(string.lower(fields.search),player)
page = "nix" page = "nix"
end end
@ -612,8 +612,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
players[name].start_i = start_i players[name].start_i = start_i
local filter = "" local filter = ""
if not fields.nix and fields.suche ~= nil and fields.suche ~= "" then if not fields.nix and fields.search ~= nil and fields.search ~= "" then
filter = fields.suche filter = fields.search
players[name].filter = filter players[name].filter = filter
end end

View File

@ -109,10 +109,10 @@ local function set_inventory(player, armor_change_only)
mcl_formspec.get_itemslot_bg(0,3,1,1).. mcl_formspec.get_itemslot_bg(0,3,1,1)..
armor_slot_imgs.. armor_slot_imgs..
-- craft and inventory -- craft and inventory
"label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]".. "label[0,4;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,4.5;9,3;9]"..
"list[current_player;main;0,7.74;9,1;]".. "list[current_player;main;0,7.74;9,1;]"..
"label[4,0.5;"..F(minetest.colorize("#313131", S("Crafting"))).."]".. "label[4,0.5;"..F(minetest.colorize(mcl_colors.DARK_GRAY, S("Crafting"))).."]"..
"list[current_player;craft;4,1;2,2]".. "list[current_player;craft;4,1;2,2]"..
"list[current_player;craftpreview;7,1.5;1,1;]".. "list[current_player;craftpreview;7,1.5;1,1;]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3).. mcl_formspec.get_itemslot_bg(0,4.5,9,3)..

View File

@ -1,6 +1,6 @@
name = mcl_inventory name = mcl_inventory
author = BlockMen author = BlockMen
description = Adds the player inventory and creative inventory. description = Adds the player inventory and creative inventory.
depends = mcl_init, mcl_formspec depends = mcl_init, mcl_formspec, mcl_colors
optional_depends = mcl_player, _mcl_autogroup, mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting optional_depends = mcl_player, _mcl_autogroup, mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting

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,4 +0,0 @@
mesecons
mcl_sounds
doc?
screwdriver?

View File

@ -1,2 +1,3 @@
name = mcl_comparators name = mcl_comparators
depends = mcl_wip depends = mcl_wip, mesecons, mcl_sounds
optional_depends = doc, screwdriver

View File

@ -1,12 +0,0 @@
mcl_init
mcl_formspec
mesecons
mcl_sounds
mcl_tnt
mcl_worlds
mcl_core
mcl_nether
mcl_armor_stand
mcl_armor
doc?
screwdriver?

View File

@ -13,12 +13,12 @@ local S = minetest.get_translator("mcl_dispensers")
local setup_dispenser = function(pos) local setup_dispenser = function(pos)
-- Set formspec and inventory -- Set formspec and inventory
local form = "size[9,8.75]".. local form = "size[9,8.75]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3).. mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]".. "list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1).. mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dispenser"))).."]".. "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dispenser"))).."]"..
"list[current_name;main;3,0.5;3,3;]".. "list[current_name;main;3,0.5;3,3;]"..
mcl_formspec.get_itemslot_bg(3,0.5,3,3).. mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
"listring[current_name;main]".. "listring[current_name;main]"..

View File

@ -0,0 +1,3 @@
name = mcl_dispensers
depends = mcl_init, mcl_formspec, mesecons, mcl_sounds, mcl_tnt, mcl_worlds, mcl_core, mcl_nether, mcl_armor_stand, mcl_armor, mcl_colors
optional_depends = doc, screwdriver

View File

@ -1,6 +0,0 @@
mcl_init
mcl_formspec
mesecons
mcl_util
doc?
screwdriver?

View File

@ -14,12 +14,12 @@ local S = minetest.get_translator("mcl_droppers")
local setup_dropper = function(pos) local setup_dropper = function(pos)
-- Set formspec and inventory -- Set formspec and inventory
local form = "size[9,8.75]".. local form = "size[9,8.75]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3).. mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]".. "list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1).. mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]".. "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dropper"))).."]"..
"list[current_name;main;3,0.5;3,3;]".. "list[current_name;main;3,0.5;3,3;]"..
mcl_formspec.get_itemslot_bg(3,0.5,3,3).. mcl_formspec.get_itemslot_bg(3,0.5,3,3)..
"listring[current_name;main]".. "listring[current_name;main]"..

View File

@ -15,10 +15,10 @@ local setup_dropper = function(pos)
-- Set formspec and inventory -- Set formspec and inventory
local form = "size[9,8.75]".. local form = "size[9,8.75]"..
"background[-0.19,-0.25;9.41,9.49;crafting_inventory_9_slots.png]".. "background[-0.19,-0.25;9.41,9.49;crafting_inventory_9_slots.png]"..
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. "label[0,4.0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Inventory"))).."]"..
"list[current_player;main;0,4.5;9,3;9]".. "list[current_player;main;0,4.5;9,3;9]"..
"list[current_player;main;0,7.74;9,1;]".. "list[current_player;main;0,7.74;9,1;]"..
"label[3,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Dropper"))).."]".. "label[3,0;"..minetest.formspec_escape(minetest.colorize(mcl_colors.DARK_GRAY, S("Dropper"))).."]"..
"list[current_name;main;3,0.5;3,3;]".. "list[current_name;main;3,0.5;3,3;]"..
"listring[current_name;main]".. "listring[current_name;main]"..
"listring[current_player;main]" "listring[current_player;main]"

View File

@ -0,0 +1,3 @@
name = mcl_droppers
depends = mcl_init, mcl_formspec, mesecons, mcl_util, mcl_colors
optional_depends = doc, screwdriver

View File

@ -1,2 +0,0 @@
mesecons
mcl_util

View File

@ -0,0 +1,2 @@
name = mcl_observers
depends = mesecons, mcl_util

View File

@ -22,7 +22,7 @@ function mesecon.queue:add_action(pos, func, params, time, overwritecheck, prior
local toremove = nil local toremove = nil
-- Otherwise, add the action to the queue -- Otherwise, add the action to the queue
if overwritecheck then -- check if old action has to be overwritten / removed: if overwritecheck then -- check if old action has to be overwritten / removed:
for i, ac in ipairs(mesecon.queue.actions) do for i, ac in pairs(mesecon.queue.actions) do
if(vector.equals(pos, ac.pos) if(vector.equals(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck)) then and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
toremove = i toremove = i

View File

@ -1,3 +0,0 @@
mcl_sounds
mcl_core
doc?

View File

@ -75,10 +75,10 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
rules = rules or mesecon.rules.default rules = rules or mesecon.rules.default
-- Call turnon on all linking positions -- Call turnon on all linking positions
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in pairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule) local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule) local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do for _, rulename in pairs(rulenames) do
mesecon.turnon(np, rulename) mesecon.turnon(np, rulename)
end end
end end

View File

@ -0,0 +1,3 @@
name = mesecons
depends = mcl_sounds, mcl_core
optional_depends = doc

View File

@ -1 +0,0 @@
mesecons

View File

@ -0,0 +1,2 @@
name = mesecons_alias
depends = mesecons

View File

@ -1,2 +0,0 @@
mesecons
doc?

View File

@ -0,0 +1,3 @@
name = mesecons_button
depends = mesecons
optional_depends = doc

View File

@ -1,3 +0,0 @@
mesecons
doc?
doc_items?

View File

@ -1,6 +1,11 @@
local S = minetest.get_translator("mesecons_commandblock") local S = minetest.get_translator("mesecons_commandblock")
local F = minetest.formspec_escape 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 function construct(pos)
local meta = minetest.get_meta(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 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) 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 end
return false, minetest.colorize("#FF0000", msg) return false, minetest.colorize(color_red, msg)
end end
if player_name then if player_name then
local player_privs = minetest.get_player_privs(player_name) 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 for cmd_priv, _ in pairs(cmddef.privs) do
if player_privs[cmd_priv] ~= true then 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) 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 end
end end
@ -99,9 +104,14 @@ local function commandblock_action_on(pos, node)
return return
end end
minetest.swap_node(pos, {name = "mesecons_commandblock:commandblock_on"})
local meta = minetest.get_meta(pos) 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) local commands = resolve_commands(meta:get_string("commands"), pos)
for _, command in pairs(commands:split("\n")) do for _, command in pairs(commands:split("\n")) do
@ -117,7 +127,6 @@ local function commandblock_action_on(pos, node)
return return
end end
-- Execute command in the name of commander -- Execute command in the name of commander
local commander = meta:get_string("commander")
cmddef.func(commander, param) cmddef.func(commander, param)
end end
end end
@ -129,6 +138,10 @@ local function commandblock_action_off(pos, node)
end end
local on_rightclick = function(pos, node, player, itemstack, pointed_thing) 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 local can_edit = true
-- Only allow write access in Creative Mode -- Only allow write access in Creative Mode
if not minetest.is_creative_enabled(player:get_player_name()) then 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! 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. 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 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. 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! 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. 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! 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. 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 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! You can only change the command block in Creative Mode!=Попытка редактирования командного блока потерпела неудачу. Вы можете изменять командные блоки только в творческом режиме!
Editing the command block has failed! The command block is gone.=Попытка редактирования командного блока потерпела неудачу. Командный блок исчез. Editing the command block has failed! The command block is gone.=Попытка редактирования командного блока потерпела неудачу. Командный блок исчез.
Executes server commands when powered by redstone power=При подаче энергии редстоуна выполняет серверные команды 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! You can only change the command block in Creative Mode!=
Editing the command block has failed! The command block is gone.= Editing the command block has failed! The command block is gone.=
Executes server commands when powered by redstone power= Executes server commands when powered by redstone power=
Command blocks are not enabled on this server=

View File

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

View File

@ -1,3 +0,0 @@
mesecons
doc?
screwdriver?

View File

@ -0,0 +1,3 @@
name = mesecons_delayer
depends = mesecons
optional_depends = doc, screwdriver

Some files were not shown because too many files have changed in this diff Show More