Merge branch 'master' into api-cauldrons

This commit is contained in:
AFCMS 2021-03-19 10:16:27 +01:00
commit aa0c7bd2cf
142 changed files with 726 additions and 600 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

@ -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,358 @@
--[[ 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_multiplier 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 = { tool_multiplier = 1, level = 1, uses = 0 },
local minigroups = { "handy", "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" } pickaxey = { tool_multiplier = 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 "tool_multiplier" field is a multiplier to the
mcl_autogroup.creativetimes = {} -- Copy of digtimes, except that all values are 0. Used for creative mode dig speed 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.
--]]
-- 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 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 end
for g=1, #minigroups do
mcl_autogroup.digtimes[minigroups[g].."_dig"] = {} -- Returns a table containing a table indexed by "_mcl_hardness_value" to get
mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {} -- its index in the list of unique hardnesses for each diggroup.
for e=1, max_efficiency_level do local function get_hardness_lookup_for_groups(hardness_values)
mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {} local map = {}
mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {} for g, values in pairs(hardness_values) do
map[g] = {}
for k, v in pairs(values) do
map[g][v] = k
end 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
-- tool_multiplier - dig speed multiplier for tool (default 1)
-- efficiency - efficiency level for the tool if applicable
local function get_digtimes(group, can_harvest, tool_multiplier, efficiency)
tool_multiplier = tool_multiplier or 1
local speed_multiplier = tool_multiplier
if efficiency then
speed_multiplier = speed_multiplier + efficiency * efficiency + 1
end
local digtimes = {}
for index, hardness in pairs(hardness_values[group]) do
local digtime = (hardness or 0) / speed_multiplier
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)
for g, capsdef in pairs(groupcaps_def) do
local mult = capsdef.tool_multiplier 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
return groupcaps
end
-- Checks if the given node would drop its useful drop if dug by a given tool.
-- Returns true if it will yield its useful drop, false otherwise.
function mcl_autogroup.can_harvest(nodename, toolname)
local ndef = minetest.registered_nodes[nodename]
if minetest.get_item_group(nodename, "dig_immediate") >= 2 then
return true
end
-- Check if it can be dug by tool
local tdef = minetest.registered_tools[toolname]
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
-- 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,26 @@
--[[
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 = {}
-- 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

@ -163,6 +163,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 +190,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

View File

@ -169,62 +169,6 @@ local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
local basegroups = { "pickaxey", "axey", "shovely" } local basegroups = { "pickaxey", "axey", "shovely" }
local materials = { "wood", "gold", "stone", "iron", "diamond" } 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 +225,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 +250,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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

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

@ -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
optional_depends = doc, screwdriver

View File

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

View File

@ -0,0 +1,3 @@
name = mcl_droppers
depends = mcl_init, mcl_formspec, mesecons, mcl_util
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

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

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

@ -0,0 +1,3 @@
name = mesecons_commandblock
depends = mesecons
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

View File

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

View File

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

View File

@ -1 +0,0 @@
mesecons

View File

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

View File

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

View File

@ -0,0 +1,2 @@
name = mesecons_noteblock
depends = mesecons, mcl_particles

View File

@ -1,5 +0,0 @@
mesecons
mesecons_mvps
mcl_mobitems
doc?
screwdriver?

View File

@ -0,0 +1,3 @@
name = mesecons_pistons
depends = mesecons, mesecons_mvps, mcl_mobitems
optional_depends = doc, screwdriver

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -116,6 +116,8 @@ end
ARROW_ENTITY.on_step = function(self, dtime) ARROW_ENTITY.on_step = function(self, dtime)
mcl_burning.tick(self.object, dtime) mcl_burning.tick(self.object, dtime)
self._time_in_air = self._time_in_air + .001
local pos = self.object:get_pos() local pos = self.object:get_pos()
local dpos = table.copy(pos) -- digital pos local dpos = table.copy(pos) -- digital pos
dpos = vector.round(dpos) dpos = vector.round(dpos)
@ -125,9 +127,11 @@ ARROW_ENTITY.on_step = function(self, dtime)
self.object:remove() self.object:remove()
end end
if self.object:get_attach() and not self.object:get_attach(parent) then minetest.register_on_leaveplayer(function(player)
if self.object:get_attach(parent) == player then
self.object:remove() self.object:remove()
end end
end)
if self._stuck then if self._stuck then
self._stucktimer = self._stucktimer + dtime self._stucktimer = self._stucktimer + dtime
@ -208,10 +212,10 @@ ARROW_ENTITY.on_step = function(self, dtime)
for k, obj in pairs(objs) do for k, obj in pairs(objs) do
local ok = false local ok = false
-- Arrows can only damage players and mobs -- Arrows can only damage players and mobs
if obj ~= self._shooter and obj:is_player() then if obj:is_player() then
ok = true ok = true
elseif obj:get_luaentity() ~= nil then elseif obj:get_luaentity() ~= nil then
if obj ~= self._shooter and (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then if (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then
ok = true ok = true
end end
end end
@ -229,11 +233,12 @@ ARROW_ENTITY.on_step = function(self, dtime)
end end
-- If an attackable object was found, we will damage the closest one only -- If an attackable object was found, we will damage the closest one only
if closest_object ~= nil then if closest_object ~= nil then
local obj = closest_object local obj = closest_object
local is_player = obj:is_player() local is_player = obj:is_player()
local lua = obj:get_luaentity() local lua = obj:get_luaentity()
if obj ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then if obj == self._shooter and self._time_in_air > 1.02 or obj ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then
if obj:get_hp() > 0 then if obj:get_hp() > 0 then
-- Check if there is no solid node between arrow and object -- Check if there is no solid node between arrow and object
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true) local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)
@ -462,6 +467,7 @@ ARROW_ENTITY.get_staticdata = function(self)
end end
ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s) ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s)
self._time_in_air = 1.0
self._in_player = false self._in_player = false
local data = minetest.deserialize(staticdata) local data = minetest.deserialize(staticdata)
if data then if data then

View File

@ -1,8 +0,0 @@
mcl_init
mcl_formspec
mcl_core
mcl_sounds
mcl_end
mesecons
doc?
screwdriver?

View File

@ -0,0 +1,3 @@
name = mcl_chests
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_end, mesecons
optional_depends = doc, screwdriver

View File

@ -1,4 +0,0 @@
mcl_init
mcl_worlds
mesecons
doc?

View File

@ -1 +0,0 @@
A fantasy clock item roughly shows the time of day.

View File

@ -1 +1,4 @@
name = mcl_clock name = mcl_clock
description = A fantasy clock item roughly shows the time of day.
depends = mcl_init, mcl_worlds, mesecons
optional_depends = doc

View File

@ -1,5 +0,0 @@
mcl_core
mcl_sounds
mcl_dye
doc?
screwdriver?

View File

@ -1 +0,0 @@
Adds blocks which can be colored, namely hardened clay.

View File

@ -1 +1,4 @@
name = mcl_colorblocks name = mcl_colorblocks
description = Adds blocks which can be colored, namely hardened clay.
depends = mcl_core, mcl_sounds, mcl_dye
optional_depends = doc, screwdriver

View File

@ -1,4 +0,0 @@
mcl_core
mcl_worlds
mesecons
doc?

View File

@ -1 +0,0 @@
A compass item which points towards the world origin.

View File

@ -1 +1,4 @@
name = mcl_compass name = mcl_compass
description = A compass item which points towards the world origin.
depends = mcl_core, mcl_worlds, mesecons
optional_depends = doc

View File

@ -1,8 +0,0 @@
mcl_init
mcl_sounds
mcl_particles
mcl_util
mcl_worlds
doc_items
doc?
mcl_enchanting

View File

@ -1 +0,0 @@
Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else.

View File

@ -3,6 +3,19 @@ mcl_core = {}
-- Repair percentage for toolrepair -- Repair percentage for toolrepair
mcl_core.repair = 0.05 mcl_core.repair = 0.05
mcl_autogroup.register_diggroup("handy")
mcl_autogroup.register_diggroup("pickaxey", {
levels = { "wood", "gold", "stone", "iron", "diamond" }
})
mcl_autogroup.register_diggroup("axey")
mcl_autogroup.register_diggroup("shovely")
mcl_autogroup.register_diggroup("shearsy")
mcl_autogroup.register_diggroup("shearsy_wool")
mcl_autogroup.register_diggroup("shearsy_cobweb")
mcl_autogroup.register_diggroup("swordy")
mcl_autogroup.register_diggroup("swordy_cobweb")
mcl_autogroup.register_diggroup("creative_breakable")
-- Load files -- Load files
local modpath = minetest.get_modpath("mcl_core") local modpath = minetest.get_modpath("mcl_core")
dofile(modpath.."/functions.lua") dofile(modpath.."/functions.lua")

View File

@ -1 +1,4 @@
name = mcl_core name = mcl_core
description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else.
depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting
optional_depends = doc

View File

@ -108,7 +108,7 @@ minetest.register_node("mcl_core:cobweb", {
liquid_renewable = false, liquid_renewable = false,
liquid_range = 0, liquid_range = 0,
walkable = false, walkable = false,
groups = {swordy_cobweb=1,shearsy=1, fake_liquid=1, disable_jump=1, deco_block=1, dig_by_piston=1, dig_by_water=1,destroy_by_lava_flow=1,}, groups = {swordy_cobweb=1, shearsy_cobweb=1, fake_liquid=1, disable_jump=1, deco_block=1, dig_by_piston=1, dig_by_water=1,destroy_by_lava_flow=1,},
drop = "mcl_mobitems:string", drop = "mcl_mobitems:string",
_mcl_shears_drop = true, _mcl_shears_drop = true,
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),

View File

@ -1,5 +0,0 @@
mcl_core
mcl_sounds
doc?
screwdriver?
mesecons

View File

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

View File

@ -1,4 +0,0 @@
mcl_core
mcl_flowers
mcl_mobitems
mcl_cocoas

View File

@ -1 +1,2 @@
name = mcl_dye name = mcl_dye
depends = mcl_core, mcl_flowers, mcl_mobitems, mcl_cocoas

View File

@ -155,15 +155,7 @@ mcl_enchanting.enchantments.efficiency = {
description = S("Increases mining speed."), description = S("Increases mining speed."),
curse = false, curse = false,
on_enchant = function(itemstack, level) on_enchant = function(itemstack, level)
local tool_capabilities = itemstack:get_tool_capabilities() mcl_enchanting.update_groupcaps(itemstack)
local groupcaps = {}
for group, capability in pairs(tool_capabilities.groupcaps) do
local groupname = group .. "_efficiency_" .. level
capability.times = mcl_autogroup.digtimes[groupname]
groupcaps[groupname] = capability
end
tool_capabilities.groupcaps = groupcaps
itemstack:get_meta():set_tool_capabilities(tool_capabilities)
end, end,
requires_tool = false, requires_tool = false,
treasure = false, treasure = false,

View File

@ -219,6 +219,38 @@ function mcl_enchanting.enchantments_snippet(_, _, itemstack)
end end
end end
-- Returns the after_use callback function to use when registering an enchanted
-- item. The after_use callback is used to update the tool_capabilities of
-- efficiency enchanted tools with outdated digging times.
--
-- It does this by calling apply_efficiency to reapply the efficiency
-- enchantment. That function is written to use hash values to only update the
-- tool if neccessary.
--
-- This is neccessary for digging times of tools to be in sync when MineClone2
-- or mods add new hardness values.
local function get_after_use_callback(itemdef)
if itemdef.after_use then
-- If the tool already has an after_use, make sure to call that
-- one too.
return function(itemstack, user, node, digparams)
itemdef.after_use(itemstack, user, node, digparams)
mcl_enchanting.update_groupcaps(itemstack)
end
end
-- If the tool does not have after_use, add wear to the tool as if no
-- after_use was registered.
return function(itemstack, user, node, digparams)
if not minetest.is_creative_enabled(user) then
itemstack:add_wear(digparams.wear)
end
local enchantments = mcl_enchanting.get_enchantments(itemstack)
mcl_enchanting.update_groupcaps(itemstack)
end
end
function mcl_enchanting.initialize() function mcl_enchanting.initialize()
local register_tool_list = {} local register_tool_list = {}
local register_item_list = {} local register_item_list = {}
@ -236,6 +268,7 @@ function mcl_enchanting.initialize()
new_def.groups.enchanted = 1 new_def.groups.enchanted = 1
new_def.texture = itemdef.texture or itemname:gsub("%:", "_") new_def.texture = itemdef.texture or itemname:gsub("%:", "_")
new_def._mcl_enchanting_enchanted_tool = new_name new_def._mcl_enchanting_enchanted_tool = new_name
new_def.after_use = get_after_use_callback(itemdef)
local register_list = register_item_list local register_list = register_item_list
if itemdef.type == "tool" then if itemdef.type == "tool" then
register_list = register_tool_list register_list = register_tool_list

View File

@ -0,0 +1,59 @@
local groupcaps_cache = {}
-- Compute a hash value.
function compute_hash(value)
-- minetest.get_password_hash is quite fast, even if it uses a
-- cryptographic hashing function (SHA-1). It is written in C++ and it
-- is probably hard to write a faster hashing function in Lua.
return string.sub(minetest.get_password_hash("ryvnf", minetest.serialize(value)), 1, 8)
end
-- Get the groupcaps and hash for an enchanted tool. If this function is called
-- repeatedly with the same values it will return data from a cache.
--
-- Parameters:
-- toolname - Name of the tool
-- level - The efficiency level of the tool
--
-- Returns a table with the following two fields:
-- values - The groupcaps table
-- hash - The hash of the groupcaps table
local function get_efficiency_groupcaps(toolname, level)
local toolcache = groupcaps_cache[toolname]
local level = level
if not toolcache then
toolcache = {}
groupcaps_cache[toolname] = toolcache
end
local levelcache = toolcache[level]
if not levelcache then
levelcache = {}
levelcache.values = mcl_autogroup.get_groupcaps(toolname, level)
levelcache.hash = compute_hash(levelcache.values)
toolcache[level] = levelcache
end
return levelcache
end
-- Update groupcaps of an enchanted tool. This function will be called
-- repeatedly to make sure the digging times stored in groupcaps stays in sync
-- when the digging times of nodes can change.
--
-- To make it more efficient it will first check a hash value to determine if
-- the tool needs to be updated.
function mcl_enchanting.update_groupcaps(itemstack)
local name = itemstack:get_name()
local level = mcl_enchanting.get_enchantment(itemstack, "efficiency")
local groupcaps = get_efficiency_groupcaps(name, level)
local hash = itemstack:get_meta():get_string("groupcaps_hash")
if not hash or hash ~= groupcaps.hash then
local tool_capabilities = itemstack:get_tool_capabilities()
tool_capabilities.groupcaps = groupcaps.values
itemstack:get_meta():set_tool_capabilities(tool_capabilities)
itemstack:get_meta():set_string("groupcaps_hash", groupcaps.hash)
end
end

View File

@ -59,6 +59,7 @@ mcl_enchanting = {
} }
dofile(modpath .. "/engine.lua") dofile(modpath .. "/engine.lua")
dofile(modpath .. "/groupcaps.lua")
dofile(modpath .. "/enchantments.lua") dofile(modpath .. "/enchantments.lua")
minetest.register_chatcommand("enchant", { minetest.register_chatcommand("enchant", {

View File

@ -86,6 +86,11 @@ minetest.register_craftitem("mcl_end:crystal", {
if pointed_thing.type == "node" then if pointed_thing.type == "node" then
local pos = minetest.get_pointed_thing_position(pointed_thing) local pos = minetest.get_pointed_thing_position(pointed_thing)
local node = minetest.get_node(pos).name local node = minetest.get_node(pos).name
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
if find_crystal(pos) then return itemstack end if find_crystal(pos) then return itemstack end
if node == "mcl_core:obsidian" or node == "mcl_core:bedrock" then if node == "mcl_core:obsidian" or node == "mcl_core:bedrock" then
if not minetest.is_creative_enabled(placer:get_player_name()) then if not minetest.is_creative_enabled(placer:get_player_name()) then

View File

@ -1,8 +0,0 @@
mcl_core
mcl_sounds
mcl_wool
mcl_torches
mcl_weather
mcl_armor?
mobs_mc
doc?

View File

@ -1 +1,3 @@
name = mcl_farming name = mcl_farming
depends = mcl_core, mcl_sounds, mcl_wool, mcl_torches, mcl_weather, mobs_mc
optional_depends = mcl_armor, doc

View File

@ -1,4 +0,0 @@
mcl_core
mcl_sounds
doc?
screwdriver?

View File

@ -1 +1,3 @@
name = mcl_fences name = mcl_fences
depends = mcl_core, mcl_sounds
optional_depends = doc, screwdriver

View File

@ -1,5 +0,0 @@
mcl_core
mcl_sounds
mcl_loot
mcl_mobs
mcl_enchanting

View File

@ -1 +0,0 @@
Adds fish and fishing poles to go fishing.

View File

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

View File

@ -1,9 +0,0 @@
mcl_init
mcl_formspec
mcl_core
mcl_sounds
mcl_craftguide
mcl_achievements
mcl_particles
doc?
screwdriver?

View File

@ -1 +1,3 @@
name = mcl_furnaces name = mcl_furnaces
depends = mcl_init, mcl_formspec, mcl_core, mcl_sounds, mcl_craftguide, mcl_achievements, mcl_particles
optional_depends = doc, screwdriver

View File

@ -1,4 +0,0 @@
mcl_sounds
mcl_armor?
screwdriver?
doc?

View File

@ -1 +0,0 @@
Small decorative head blocks.

View File

@ -1 +1,4 @@
name = mcl_heads name = mcl_heads
description = Small decorative head blocks.
depends = mcl_sounds
optional_depends = mcl_armor, screwdriver, doc

View File

@ -1,6 +0,0 @@
mcl_core
mcl_formspec
mcl_sounds
mcl_util
doc?
screwdriver?

View File

@ -1 +0,0 @@
It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed.

View File

@ -0,0 +1,4 @@
name = mcl_hoppers
description = It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed.
depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util
optional_depends = doc, screwdriver

View File

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

View File

@ -0,0 +1,3 @@
name = mcl_itemframes
depends = mcl_core, mcl_sounds
optional_depends = screwdriver

View File

@ -1,2 +0,0 @@
mcl_core
mcl_hunger

View File

@ -1 +1,2 @@
name = mcl_mobitems name = mcl_mobitems
depends = mcl_core, mcl_hunger

View File

@ -1,2 +0,0 @@
mcl_sounds
mcl_mobs

View File

@ -1 +1,2 @@
name = mcl_mobspawners name = mcl_mobspawners
depends = mcl_sounds, mcl_mobs

View File

@ -1,2 +0,0 @@
mcl_sounds
mobs_mc

View File

@ -1 +0,0 @@
Adds infested blocks: Blocks which which disguise themselves as stone blocks and spawn a silverfish when broken.

View File

@ -0,0 +1,3 @@
name = mcl_monster_eggs
description = Adds infested blocks: Blocks which which disguise themselves as stone blocks and spawn a silverfish when broken.
depends = mcl_sounds, mobs_mc

View File

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

View File

@ -1 +1,3 @@
name = mcl_mushrooms name = mcl_mushrooms
depends = mcl_sounds, mcl_util
optional_depends = doc

View File

@ -1,8 +0,0 @@
mcl_core
mcl_sounds
mcl_util
walkover
mcl_death_messages?
doc_items
doc?
screwdriver?

View File

@ -106,7 +106,7 @@ minetest.register_node("mcl_nether:magma", {
sounds = mcl_sounds.node_sound_stone_defaults(), sounds = mcl_sounds.node_sound_stone_defaults(),
-- From walkover mod -- From walkover mod
on_walk_over = function(loc, nodeiamon, player) on_walk_over = function(loc, nodeiamon, player)
if minetest.global_exists("mcl_potions") and mcl_potions.player_has_effect(player, "fire_proof") then if player and player:get_player_control().sneak or minetest.global_exists("mcl_potions") and mcl_potions.player_has_effect(player, "fire_proof") then
return return
end end
-- Hurt players standing on top of this block -- Hurt players standing on top of this block

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