Compare commits

..

28 Commits

Author SHA1 Message Date
AFCMS 2a28bf215d Merge branch 'master' into chat-command-builder 2021-03-16 10:28:03 +00:00
AFCMS 86f01eed75 try to fix a bug 2021-03-11 19:12:28 +01:00
AFCMS a51bbb6974 fix nodename pattern 2021-03-10 20:41:41 +01:00
AFCMS 11384bd73c fix nodename pattern and add debug command (do not work) 2021-03-10 19:35:23 +01:00
AFCMS 669a9ff0a4 remove (for now) unused params
temporary removed params need an engine change
https://github.com/minetest/minetest/pull/11022
2021-03-09 19:04:37 +01:00
AFCMS 783146f32e FIX THE STUPIDIEST BUG EVER 2021-03-09 18:42:53 +01:00
AFCMS 31e256e1e2 cleanup and fixes 2021-03-09 12:47:57 +01:00
AFCMS 5f00d47ec2 cleanup and fixes (WIP) 2021-03-09 10:15:27 +01:00
AFCMS 0d3147b13d add 2 more patterns types (WIP) 2021-03-09 00:57:13 +01:00
AFCMS a22188ccf4 refine some commands to match last changes 2021-03-09 00:47:01 +01:00
AFCMS f90243f6e5 add public API to properly (take care of mcl_builtin_commands_overide) rename and alias chat command 2021-03-09 00:34:33 +01:00
AFCMS 884097a8e5 add API documentation for mcl_commands 2021-03-09 00:00:21 +01:00
AFCMS 72ddaf33f6 move mcl_commands to core and add mcl_basic_commands 2021-03-08 23:35:34 +01:00
AFCMS 19e83fc2fb fixes 2021-03-08 23:27:39 +01:00
AFCMS 43c641f84f improve chat command definition 2021-03-08 22:48:44 +01:00
AFCMS 155548f384 refactor chat message then you haven't the required privs 2021-03-08 20:34:36 +01:00
AFCMS f7b832508f cleanup 2021-03-08 18:53:01 +01:00
AFCMS 9e7ec24c0e add log 2021-03-08 17:45:25 +01:00
AFCMS 5b5b525d32 fix title command 2021-03-08 17:05:17 +01:00
AFCMS e334665365 fix somethings 2021-03-08 17:01:11 +01:00
AFCMS 88a971fe6f fix stupid code duplication 2021-03-08 16:54:57 +01:00
AFCMS 5425a01097 fix message 2021-03-08 16:53:21 +01:00
AFCMS 1f5076cfd0 Add ability for sub commands to have special privs 2021-03-08 16:48:59 +01:00
AFCMS 7139ca1395 fix 2021-03-08 16:19:43 +01:00
AFCMS 84de4ea728 cleanup 2021-03-08 16:18:37 +01:00
AFCMS 59ab7e6ae6 add /title command 2021-03-08 16:15:52 +01:00
AFCMS d5874b4062 add credits 2021-03-08 16:05:26 +01:00
AFCMS d72fa76757 add basic API (basicaly chat command builder) 2021-03-08 14:47:49 +01:00
230 changed files with 2241 additions and 1776 deletions

4
API.md
View File

@ -17,10 +17,6 @@ Items can have these fields:
anvil.
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:
* `_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
# Performance settings
# dedicated_server_step = 0.001
# abm_interval = 0.25
# max_objects_per_block = 4096
# max_packets_per_iteration = 10096
dedicated_server_step = 0.001
abm_interval = 0.25
max_objects_per_block = 4096
max_packets_per_iteration = 10096
# Clientmodding to support official client
enable_client_modding = true

View File

@ -4,11 +4,6 @@ Specifically, this mod has 2 purposes:
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)
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.
The leading underscore in the name “_mcl_autogroup” was added to force Minetest to load this mod as late as possible.

View File

@ -1,358 +1,169 @@
--[[
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:
--[[ Mining times. Yeah, mining times … Alright, this is going to be FUN!
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
2) The tool being used (the tool speed and its efficiency level)
3) Whether the tool is considered as "eligible" for the block
2) The tool being used
3) Whether the tool is considered as eligible for the block
(e.g. only diamond pick eligible for obsidian)
See Minecraft Wiki <http://minecraft.gamepedia.com/Minecraft_Wiki> for more information.
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).
The nodes are also required to specify the eligible tools in groups like pickaxey, shovely, etc.
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.
How the mod is used
===================
Example:
mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2
In MineClone 2, all diggable nodes have the hardness set in the custom field
"_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:
This means that when a node has been assigned the group pickaxey_dig_diamond=1, it can be dug by the
diamond pickaxe in 0.2 seconds.
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).
Nodes indicate that they belong to a particular digging group by being member of
the digging group in their node definition. "mcl_core:dirt" for example has
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.
This strange setup with mcl_autogroup has been done to minimize the amount of required digging times
a single tool needs to use. If this is not being done, the loading time will increase considerably
(>10s).
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.
]]
_mcl_diggroups = {
handy = { speed = 1, level = 1, uses = 0 },
pickaxey = { speed = 1, level = 0, uses = 0 },
}
local materials = { "wood", "gold", "stone", "iron", "diamond" }
local basegroups = { "pickaxey", "axey", "shovely" }
local minigroups = { "handy", "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
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
The "uses" field indicate how many uses (0 for infinite) a tool has when used on
the specified digging group. The "speed" field is a multiplier to the dig speed
on that digging group.
mcl_autogroup = {}
mcl_autogroup.digtimes = {}
mcl_autogroup.creativetimes = {} -- Copy of digtimes, except that all values are 0. Used for creative mode
The "level" field indicates which levels of the group the tool can harvest. A
level of 0 means that the tool cannot harvest blocks of that node. A level of 1
or above means that the tool can harvest nodes with that level or below. See
"mcl_tools/init.lua" for examples on how "_mcl_diggroups" is used in practice.
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
for m=1, #materials do
for g=1, #basegroups do
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {}
mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {}
for e=1, max_efficiency_level do
mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {}
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
for g=1, #minigroups do
mcl_autogroup.digtimes[minigroups[g].."_dig"] = {}
mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {}
for e=1, max_efficiency_level do
mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {}
mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {}
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)
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
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 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
local overwrite = function()
for nname, ndef in pairs(minetest.registered_nodes) do
local groups_changed = false
local newgroups = table.copy(ndef.groups)
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)
and (ndef.collision_box == nil or ndef.collision_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
newgroups.solid = 1
groups_changed = true
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
(ndef.groups.not_opaque == 0 or ndef.groups.not_opaque == nil) then
newgroups.opaque = 1
groups_changed = true
end
local creative_breakable = false
local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency)
local time, validity_factor
if actual_rating >= expected_rating then
-- Valid tool
validity_factor = 1.5
else
-- Wrong tool (higher digging time)
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
-- Assign groups used for digging this node depending on
-- the registered digging groups
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
-- Hack in digging times
local hardness = ndef._mcl_hardness
if not hardness then
hardness = 0
end
for i = ndef.groups[g], #gdef.levels do
newgroups[g .. "_dig_" .. gdef.levels[i]] = index
-- 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
else
newgroups[g .. "_dig"] = index
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
-- Automatically assign the node to the
-- creative_breakable group if it belongs to any digging
-- group.
newgroups["creative_breakable"] = 1
minetest.override_item(nname, {
groups = newgroups
})
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
})
if groups_changed then
minetest.override_item(nname, {
groups = newgroups
})
end
end
end
end

View File

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

View File

@ -1,28 +0,0 @@
--[[
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

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

View File

@ -0,0 +1,74 @@
# API documentation of mcl_commands
The mcl_commands API allows you to register and overide complex commands.
This mod is derivated from ChatCommandBuilder by rubenwardy
Some public functions are not documented here but they are for internal use only.
## Technical differences from ChatCommandBuilder
* subcommand aditional specific privs
* new types: `json`, `color`, `nodename` an maybe more in the future
## Public Functions
### `mcl_commands.register_command("exemple", def)`
This is a function which is called when an item is dispensed by the dispenser.
These are the parameters:
```
mcl_commands.register_command("exemple", {
func = function(cmd) --function executed on registration
cmd:sub(":name:username title :params:json", { --create a new subcommand called "title" with defined patterns
func = function(name, target, json)
return a_cool_function(target, json) --function executed if the params match the patterns
end,
privs = {settime = true}, --subcommand aditional specific privs
})
end,
description = "Controls text displayed on the screen.", --the description of the command
params = "<target> command <params>", --very basic explaination of the syntax of the command (will be semi-automatic in the future)
privs = {server = true}, --global privs
})
```
Register a complex chatcommand. If a chat command with the same name is already registered, the program will fail.
### `mcl_commands.overide_command("exemple", def)`
Same as above but will overide existing command.
### `mcl_commands.register_chatcommand_alias(alias, cmd, [bypass])`
Register an alias called `alias` of the `cmd` command.
If the setting `mcl_builtin_commands_overide` is set to `false`, the function will silently fail.
If `bypass` is set to `true` the function will not take care of the above setting.
Will warn if trying to alias to already existing command.
### `mcl_commands.rename_chatcommand(newname, cmd, [bypass])`
Rename `cmd` command to `newname`.
If the setting `mcl_builtin_commands_overide` is set to `false`, the function will silently fail.
If `bypass` is set to `true` the function will not take care of the above setting.
Will warn if trying to rename to already existing command.
### paterns
mcl_commands adds many types for patterns
If not specified, a value will be by default with the word pattern.
* pos value must be pos
* text value must be text WARNING: this pattern must be the last pattern of the subcommand!!
* number value must be number
* int value must be integer
* word value must be word
* alpha value must be alphanumeric
* modname value must be a valid modname
* alphascore
* alphanumeric
* username: value must be a valid username
* json: value must be a json string (will be parsed automaticaly)
* color value must be a color string or a valid named color
* nodename value must be a valid (existing) node or item name

View File

@ -0,0 +1,379 @@
--mcl_commands
--derivated from ChatCommandBuilder by @rubenwardy
local S = minetest.get_translator("mcl_commands")
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
local modpath = minetest.get_modpath(minetest.get_current_modname())
local parse_json = minetest.parse_json
local get_modpath = minetest.get_modpath
mcl_commands = {}
-- mcl_commands.types = {
-- pos = "%(? *(%-?[%d.]+) *, *(%-?[%d.]+) *, *(%-?[%d.]+) *%)?",
-- text = "(.+)",
-- number = "(%-?[%d.]+)",
-- int = "(%-?[%d]+)",
-- word = "([^ ]+)",
-- alpha = "([A-Za-z]+)",
-- modname = "([a-z0-9_]+)",
-- alphascore = "([A-Za-z_]+)",
-- alphanumeric = "([A-Za-z0-9]+)",
-- username = "([A-Za-z0-9-_]+)",
-- json = "(.+)", --FIXME
-- color = "([^ ]+)", --FIXME
-- nodename = "([A-Za-z_]+)",
-- }
mcl_commands.types = {
pos = {"%(? *(%-?[%d.]+) *,? *(%-?[%d.]+) *,? *(%-?[%d.]+) *%)?",
function(res, pointer)
local pos = {
x = tonumber(res[pointer]),
y = tonumber(res[pointer + 1]),
z = tonumber(res[pointer + 2])
}
if pos.x and pos.y and pos.z then
return nil, pos, pointer+3
else
return S("Pos is invalid!")
end
end},
text = {"(.+)",
function(res, pointer)
if res[pointer] == tostring(res[pointer]) then
return nil, res[pointer], pointer+1
else
return S("Text is invalid!")
end
end},
number = {"(%-?[%d.]+)}",
function(res, pointer)
if res[pointer] == tonumber(res[pointer]) then
return nil, tonumber(res[pointer]), pointer+1
else
return S("Number is invalid!")
end
end},
int = {"(%-?[%d]+)}",
function(res, pointer)
if res[pointer] == math.floor(tonumber(res[pointer])) then
return nil, tonumber(res[pointer]), pointer+1
else
return S("Int is invalid!")
end
end},
word = {"([^ ]+)",
function(res, pointer)
if res[pointer] == tostring(res[pointer]) then
return nil, tostring(res[pointer]), pointer+1
else
return S("Word is invalid!")
end
end},
alpha = {"([A-Za-z]+)}",
function(res, pointer)
if res[pointer] then
return nil, res[pointer], pointer+1
else
return S("Alpha is invalid!")
end
end},
modname = {"([a-z0-9_]+)}",
function(res, pointer)
if get_modpath(res[pointer]) then
return nil, res[pointer], pointer+1
else
return S("Modname is invalid!")
end
end},
alphascore = {"([A-Za-z_]+)",
function(res, pointer)
if res[pointer] then --What is alphascore?
return nil, res[pointer], pointer+1
else
return S("Alphascore is invalid!")
end
end},
alphanumeric = {"([A-Za-z0-9]+)}",
function(res, pointer)
if res[pointer] then --What is alphanumerical?
return nil, res[pointer], pointer+1
else
return S("Alphanumerical is invalid!")
end
end},
username = {"([A-Za-z0-9-_]+)",
function(res, pointer)
--if minetest.player_exists(res[pointer]) then
if res[pointer] then
return nil, res[pointer], pointer+1
else
return S("Player doesn't exist.")
end
end},
json = {"(.+)", --FIXME
function(res, pointer)
local parsed = parse_json(res[pointer])
if parsed then
return nil, parsed, pointer+1
else
return S("Json failed to parse!")
end
end},
color = {"([^ ]+)", --FIXME
function(res, pointer)
local color = mcl_util.get_color(res[pointer])
if color then
return nil, color, pointer+1
else
return S("Color is not a valid color name or hexadecimal!")
end
end},
nodename = {"(%l+[%w_]+%:?[_%l]+[%w_]*)",
function(res, pointer)
if minetest.registered_items[res[pointer]] then
return nil, res[pointer], pointer+1
else
return S("Nodename is invalid")
end
end},
}
function mcl_commands.register_command(name, def)
def = def or {}
local cmd = mcl_commands.build(name, def)
if minetest.registered_chatcommands[name] then
error("[mcl_commands] Failed to register command: ["..name.."] command already existing! Use mcl_commands.overide_command() if you want to overide existing command")
end
minetest.register_chatcommand(name, cmd)
minetest.log("action", "[mcl_commands] ["..name.."] command registered successfully")
return cmd
end
function mcl_commands.override_command(name, def)
def = def or {}
local cmd = mcl_commands.build(name, def)
if minetest.registered_chatcommands[name] then
minetest.unregister_chatcommand(name)
end
minetest.register_chatcommand(name, cmd)
minetest.log("action", "[mcl_commands] ["..name.."] command overridden successfully")
return cmd
end
local STATE_READY = 1
local STATE_PARAM = 2
local STATE_PARAM_TYPE = 3
local bad_chars = {"(", ")", ".", "%", "+", "-", "*", "?", "[", "^", "$"}
local function escape(char)
if bad_chars[char] then
return "%" .. char
else
return char
end
end
local dprint = function() end
function mcl_commands.build(name, chat_def)
local cmd = {
_subs = {}
}
function cmd:sub(route, def)
dprint("Parsing " .. route)
if string.trim then
route = string.trim(route)
end
local sub = {
pattern = "^",
params = {},
func = def.func,
privs = def.privs or {},
desc = def.desc,
params_desc = def.params or "",
}
-- End of param reached: add it to the pattern
local param = ""
local param_type = ""
local should_be_eos = false
local function finishParam()
if param ~= "" and param_type ~= "" then
dprint(" - Found param " .. param .. " type " .. param_type)
local pattern = mcl_commands.types[param_type][1]
if not pattern then
error("Unrecognised param_type=" .. param_type)
end
sub.pattern = sub.pattern .. pattern
table.insert(sub.params, param_type)
param = ""
param_type = ""
end
end
-- Iterate through the route to find params
local state = STATE_READY
local catching_space = false
local match_space = " " -- change to "%s" to also catch tabs and newlines
local catch_space = match_space.."+"
for i = 1, #route do
local c = route:sub(i, i)
if should_be_eos then
error("Should be end of string. Nothing is allowed after a param of type text.")
end
if state == STATE_READY then
if c == ":" then
dprint(" - Found :, entering param")
state = STATE_PARAM
param_type = "word"
catching_space = false
elseif c:match(match_space) then
print(" - Found space")
if not catching_space then
catching_space = true
sub.pattern = sub.pattern .. catch_space
end
else
catching_space = false
sub.pattern = sub.pattern .. escape(c)
end
elseif state == STATE_PARAM then
if c == ":" then
dprint(" - Found :, entering param type")
state = STATE_PARAM_TYPE
param_type = ""
elseif c:match(match_space) then
print(" - Found whitespace, leaving param")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param = param .. c
end
elseif state == STATE_PARAM_TYPE then
if c:match(match_space) then
print(" - Found space, leaving param type")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param type")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param_type = param_type .. c
end
end
end
dprint(" - End of route")
finishParam()
sub.pattern = sub.pattern .. "$"
dprint("Pattern: " .. sub.pattern)
table.insert(self._subs, sub)
end
if chat_def.func then
chat_def.func(cmd)
end
cmd.func = function(name, param)
local msg
for i = 1, #cmd._subs do
local sub = cmd._subs[i]
local res = { string.match(param, sub.pattern) }
if #res > 0 then
local pointer = 1
local params = { name }
for j = 1, #sub.params do
local param = sub.params[j]
local value
if mcl_commands.types[param] then
msg, value, pointer = mcl_commands.check_type(param, res, pointer)
table.insert(params, value)
else
table.insert(params, res[pointer])
pointer = pointer + 1
end
end
local can_execute, missing_privs = minetest.check_player_privs(name, sub.privs)
if can_execute then
if table.unpack then
-- lua 5.2 or later
return sub.func(table.unpack(params))
else
-- lua 5.1 or earlier
return sub.func(unpack(params))
end
else
local missing_privs_str = ""
for i = 1, #missing_privs do
if not i == #missing_privs then
missing_privs_str = missing_privs_str..missing_privs[i].." "
else
missing_privs_str = missing_privs_str..missing_privs[i]
end
end
return false, "You don't have permission to run this command (missing privilege: "..missing_privs_str..")"
end
end
end
return false, msg
end
if chat_def.params then
cmd.params = chat_def.params
else
cmd.params = ""
end
cmd.privs = chat_def.privs
cmd.description = chat_def.description
return cmd
end
function mcl_commands.check_type(type, res, pointer)
return mcl_commands.types[type][2](res, pointer)
end
function mcl_commands.register_chatcommand_alias(alias, cmd, bypass)
if not bypass then bypass = false end
if minetest.registered_chatcommands[alias] then
minetest.log("warning", "[mcl_commands] trying to alias ["..cmd.."] to already existing ["..alias.."] command")
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
minetest.register_chatcommand(alias, minetest.chatcommands[cmd])
minetest.log("action", "[mcl_commands] ["..cmd.."] command aliased successfully to ["..alias.."]")
else
minetest.log("action", "[mcl_commands] ["..cmd.."] command not aliased to ["..alias.."]")
end
end
function mcl_commands.rename_chatcommand(newname, cmd, bypass)
if not bypass then bypass = false end
if minetest.registered_chatcommands[newname] then
minetest.log("warning", "[mcl_commands] trying to rename ["..cmd.."] to already existing ["..alias.."] command")
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
minetest.register_chatcommand(newname, minetest.chatcommands[cmd])
minetest.unregister_chatcommand(cmd)
minetest.log("action", "[mcl_commands] ["..cmd.."] command renamed successfully to ["..newname.."]")
else
minetest.log("action", "[mcl_commands] ["..cmd.."] command not renamed to ["..newname.."]")
end
end

View File

@ -0,0 +1,6 @@
name = mcl_commands
author = AFCMS
description = MCL2 commands API
depends = mcl_colors, mcl_util
optional_depends =

View File

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

View File

@ -6,7 +6,7 @@ mcl_worlds = {}
function mcl_worlds.is_in_void(pos)
local void =
not ((pos.y < mcl_vars.mg_overworld_max and pos.y > mcl_vars.mg_overworld_min) or
(pos.y < mcl_vars.mg_nether_max+128 and pos.y > mcl_vars.mg_nether_min) or
(pos.y < mcl_vars.mg_nether_max and pos.y > mcl_vars.mg_nether_min) or
(pos.y < mcl_vars.mg_end_max and pos.y > mcl_vars.mg_end_min))
local void_deadly = false
@ -15,11 +15,11 @@ function mcl_worlds.is_in_void(pos)
-- Overworld → Void → End → Void → Nether → Void
if pos.y < mcl_vars.mg_overworld_min and pos.y > mcl_vars.mg_end_max then
void_deadly = pos.y < mcl_vars.mg_overworld_min - deadly_tolerance
elseif pos.y < mcl_vars.mg_end_min and pos.y > mcl_vars.mg_nether_max+128 then
elseif pos.y < mcl_vars.mg_end_min and pos.y > mcl_vars.mg_nether_max then
-- The void between End and Nether. Like usual, but here, the void
-- *above* the Nether also has a small tolerance area, so player
-- can fly above the Nether without getting hurt instantly.
void_deadly = (pos.y < mcl_vars.mg_end_min - deadly_tolerance) and (pos.y > mcl_vars.mg_nether_max+128 + deadly_tolerance)
void_deadly = (pos.y < mcl_vars.mg_end_min - deadly_tolerance) and (pos.y > mcl_vars.mg_nether_max + deadly_tolerance)
elseif pos.y < mcl_vars.mg_nether_min then
void_deadly = pos.y < mcl_vars.mg_nether_min - deadly_tolerance
end
@ -35,7 +35,7 @@ end
function mcl_worlds.y_to_layer(y)
if y >= mcl_vars.mg_overworld_min then
return y - mcl_vars.mg_overworld_min, "overworld"
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max+128 then
elseif y >= mcl_vars.mg_nether_min and y <= mcl_vars.mg_nether_max then
return y - mcl_vars.mg_nether_min, "nether"
elseif y >= mcl_vars.mg_end_min and y <= mcl_vars.mg_end_max then
return y - mcl_vars.mg_end_min, "end"
@ -73,7 +73,7 @@ end
-- Takes a position and returns true if this position can have Nether dust
function mcl_worlds.has_dust(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_nether_max + 138 and pos.y >= mcl_vars.mg_nether_min - 10
return pos.y <= mcl_vars.mg_nether_max + 64 and pos.y >= mcl_vars.mg_nether_min - 64
end
-- 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
for _,func in ipairs(walkover.registered_globals) do --cache registered globals
table.insert(registered_globals, func)
table.insert(registered_globals, value)
end
end)
@ -30,7 +30,7 @@ local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
if timer >= 0.3 then
for _,player in pairs(get_connected_players()) do
for _,player in ipairs(get_connected_players()) do
local pp = player:get_pos()
pp.y = ceil(pp.y)
local loc = vector_add(pp, {x=0,y=-1,z=0})

View File

@ -163,8 +163,6 @@ function boat.get_staticdata(self)
end
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
local inv = killer:get_inventory()
if not inv:contains_item("main", self._itemstring) then
@ -190,8 +188,6 @@ function boat.on_punch(self, puncher, time_from_last_punch, tool_capabilities, d
end
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)
local v_factor = 1
local v_slowdown = 0.02
@ -227,7 +223,7 @@ function boat.on_step(self, dtime, moveresult)
self._regen_timer = regen_timer
if moveresult and moveresult.collides then
for _, collision in pairs(moveresult.collisions) do
for _, collision in ipairs(moveresult.collisions) do
local pos = collision.node_pos
if collision.type == "node" and minetest.get_item_group(minetest.get_node(pos).name, "dig_by_boat") > 0 then
minetest.dig_node(pos)
@ -309,7 +305,7 @@ function boat.on_step(self, dtime, moveresult)
self._animation = 0
end
for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
local entity = obj:get_luaentity()
if entity and entity._cmi_is_mob then
attach_object(self, obj)

View File

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

View File

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

View File

@ -54,14 +54,14 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement
end
minetest.register_globalstep(function(dtime)
for _,player in pairs(minetest.get_connected_players()) do
for _,player in ipairs(minetest.get_connected_players()) do
if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
local pos = player:get_pos()
local inv = player:get_inventory()
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
--magnet and collection
for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
for _,object in ipairs(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
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
local collected = false
@ -165,6 +165,66 @@ minetest.register_globalstep(function(dtime)
end
end)
local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
local basegroups = { "pickaxey", "axey", "shovely" }
local materials = { "wood", "gold", "stone", "iron", "diamond" }
-- 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:
-- 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
@ -221,20 +281,17 @@ function minetest.handle_node_drops(pos, drops, digger)
-- Check if node will yield its useful drop by the digger's tool
local dug_node = minetest.get_node(pos)
local tooldef
local toolcaps
local tool
if digger ~= nil then
tool = digger:get_wielded_item()
tooldef = minetest.registered_tools[tool:get_name()]
toolcaps = tool:get_tool_capabilities()
if not mcl_autogroup.can_harvest(dug_node.name, tool:get_name()) then
if not check_can_drop(dug_node.name, toolcaps) then
return
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
from the node definition.
Definition of _mcl_shears_drop / _mcl_silk_touch_drop:
@ -246,7 +303,7 @@ function minetest.handle_node_drops(pos, drops, digger)
local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name]
if shearsy_level and shearsy_level > 0 and nodedef._mcl_shears_drop then
if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then
if nodedef._mcl_shears_drop == true then
drops = { dug_node.name }
else
@ -728,7 +785,7 @@ minetest.register_entity(":__builtin:item", {
if self.physical_state then
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-- Merge with close entities of the same item
for _, object in pairs(minetest.get_objects_inside_radius(p, 0.8)) do
for _, object in ipairs(minetest.get_objects_inside_radius(p, 0.8)) do
local obj = object:get_luaentity()
if obj and obj.name == "__builtin:item"
and obj.physical_state == false then

View File

@ -226,7 +226,7 @@ local collision = function(self)
local z = 0
local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do
if object:is_player()
or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then
@ -1047,13 +1047,8 @@ local do_env_damage = function(self)
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
if self.light_damage ~= 0 and (sunlight or 0) > 12 then
if self.light_damage ~= 0 and (minetest.get_node_light(pos) or 0) > 12 then
if deal_light_damage(self, pos, self.light_damage) then
return true
end
@ -1062,7 +1057,7 @@ local do_env_damage = function(self)
if mod_worlds then
_, dim = mcl_worlds.y_to_layer(pos.y)
end
if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then
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.ignited_by_sunlight then
mcl_burning.set_on_fire(self.object, 10)
else
@ -2826,7 +2821,7 @@ local falling = function(self, pos)
end
if mcl_portals ~= nil then
if mcl_portals.nether_portal_cooloff(self.object) then
if mcl_portals.nether_portal_cooloff[self.object] then
return false -- mob has teleported through Nether portal - it's 99% not falling
end
end
@ -2856,18 +2851,6 @@ local falling = function(self, pos)
self.object:set_acceleration({x = 0, y = 0, z = 0})
end
if minetest.registered_nodes[node_ok(pos).name].groups.lava then
if self.floats_on_lava == 1 then
self.object:set_acceleration({
x = 0,
y = -self.fall_speed / (max(1, v.y) ^ 2),
z = 0
})
end
end
-- in water then float up
if minetest.registered_nodes[node_ok(pos).name].groups.water then
@ -3785,7 +3768,6 @@ minetest.register_entity(name, {
knock_back = def.knock_back ~= false,
shoot_offset = def.shoot_offset or 0,
floats = def.floats or 1, -- floats in water by default
floats_on_lava = def.floats_on_lava or 0,
replace_rate = def.replace_rate,
replace_what = def.replace_what,
replace_with = def.replace_with,
@ -4594,9 +4576,9 @@ local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer < 1 then return end
for _, player in pairs(minetest.get_connected_players()) do
for _, player in ipairs(minetest.get_connected_players()) do
local pos = player:get_pos()
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 47)) do
local lua = obj:get_luaentity()
if lua and lua._cmi_is_mob then
lua.lifetimer = math.max(20, lua.lifetimer)

View File

@ -191,14 +191,6 @@ minetest.register_craftitem("mcl_paintings:painting", {
if pointed_thing.type ~= "node" then
return itemstack
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)
dir = vector.normalize(dir)
if dir.y ~= 0 then

View File

@ -122,7 +122,7 @@ local arrows = {
}
local throwing_shoot_arrow = function(itemstack, player)
for _,arrow in pairs(arrows) do
for _,arrow in ipairs(arrows) do
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
player:get_inventory():remove_item("main", arrow[1])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -960,7 +960,7 @@ mobs:register_mob("mobs_mc:villager", {
"mobs_mc_villager_smith.png", --hat
},
},
visual_size = {x=2.75, y=2.75},
visual_size = {x=3, y=3},
makes_footstep_sound = true,
walk_velocity = 1.2,
run_velocity = 2.4,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +0,0 @@
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

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

View File

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

View File

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

View File

@ -1,2 +0,0 @@
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
-- Otherwise, add the action to the queue
if overwritecheck then -- check if old action has to be overwritten / removed:
for i, ac in pairs(mesecon.queue.actions) do
for i, ac in ipairs(mesecon.queue.actions) do
if(vector.equals(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
toremove = i

View File

@ -0,0 +1,3 @@
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
-- Call turnon on all linking positions
for _, rule in pairs(mesecon.flattenrules(rules)) do
for _, rule in ipairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in pairs(rulenames) do
for _, rulename in ipairs(rulenames) do
mesecon.turnon(np, rulename)
end
end

View File

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

View File

@ -0,0 +1 @@
mesecons

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
mesecons

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,7 @@ local function check_in_beds(players)
players = minetest.get_connected_players()
end
for n, player in pairs(players) do
for n, player in ipairs(players) do
local name = player:get_player_name()
if not in_bed[name] then
return false
@ -102,7 +102,8 @@ local function lay_down(player, pos, bed_pos, state, skip)
-- No sleeping if monsters nearby.
-- The exceptions above apply.
-- Zombie pigmen only prevent sleep while they are hostle.
for _, obj in pairs(minetest.get_objects_inside_radius(bed_pos, 8)) do
local objs = minetest.get_objects_inside_radius(bed_pos, 8)
for _, obj in ipairs(objs) do
if obj ~= nil and not obj:is_player() then
local ent = obj:get_luaentity()
local mobname = ent.name

View File

@ -15,20 +15,6 @@ local dir_to_pitch = function(dir)
return -math.atan2(-dir.y, xz)
end
local random_arrow_positions = function(positions, placement)
if positions == 'x' then
return math.random(-4, 4)
elseif positions == 'y' then
return math.random(0, 10)
end
if placement == 'front' and positions == 'z' then
return 3
elseif placement == 'back' and positions == 'z' then
return -3
end
return 0
end
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
local mod_button = minetest.get_modpath("mesecons_button")
@ -110,23 +96,11 @@ end
ARROW_ENTITY.on_step = function(self, dtime)
mcl_burning.tick(self.object, dtime)
self._time_in_air = self._time_in_air + .001
local pos = self.object:get_pos()
local dpos = table.copy(pos) -- digital pos
dpos = vector.round(dpos)
local node = minetest.get_node(dpos)
if self.object:get_attach() ~= nil and self.object:get_attach(parent):get_hp() < 1 then
self.object:remove()
end
minetest.register_on_leaveplayer(function(player)
if self.object:get_attach(parent) == player then
self.object:remove()
end
end)
if self._stuck then
self._stucktimer = self._stucktimer + dtime
self._stuckrechecktimer = self._stuckrechecktimer + dtime
@ -172,7 +146,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
-- Check for object "collision". Done every tick (hopefully this is not too stressing)
else
if self._damage >= 9 and self._in_player == false then
if self._damage >= 9 then
minetest.add_particlespawner({
amount = 1,
time = .001,
@ -206,10 +180,10 @@ ARROW_ENTITY.on_step = function(self, dtime)
for k, obj in pairs(objs) do
local ok = false
-- Arrows can only damage players and mobs
if obj:is_player() then
if obj ~= self._shooter and obj:is_player() then
ok = true
elseif obj:get_luaentity() ~= nil then
if (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then
if obj ~= self._shooter and (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then
ok = true
end
end
@ -227,12 +201,11 @@ ARROW_ENTITY.on_step = function(self, dtime)
end
-- If an attackable object was found, we will damage the closest one only
if closest_object ~= nil then
local obj = closest_object
local is_player = obj:is_player()
local lua = obj:get_luaentity()
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 ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then
if obj:get_hp() > 0 then
-- Check if there is no solid node between arrow and object
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)
@ -257,60 +230,19 @@ ARROW_ENTITY.on_step = function(self, dtime)
if obj:is_player() and rawget(_G, "armor") and armor.last_damage_types then
armor.last_damage_types[obj:get_player_name()] = "projectile"
end
if self._in_player == false then
damage_particles(self.object:get_pos(), self._is_critical)
end
damage_particles(self.object:get_pos(), self._is_critical)
if mcl_burning.is_burning(self.object) then
mcl_burning.set_on_fire(obj, 5)
end
if self._in_player == false then
obj:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, self.object:get_velocity())
if obj:is_player() then
local placement = ''
self._placement = math.random(1, 2)
if self._placement == 1 then
placement = 'front'
else
placement = 'back'
end
self._in_player = true
if self._placement == 2 then
self._rotation_station = 90
else
self._rotation_station = -90
end
self._y_position = random_arrow_positions('y', placement)
self._x_position = random_arrow_positions('x', placement)
if self._y_position > 6 and self._x_position < 2 and self._x_position > -2 then
self._attach_parent = 'Head'
self._y_position = self._y_position - 6
elseif self._x_position > 2 then
self._attach_parent = 'Arm_Right'
self._y_position = self._y_position - 3
self._x_position = self._x_position - 2
elseif self._x_position < -2 then
self._attach_parent = 'Arm_Left'
self._y_position = self._y_position - 3
self._x_position = self._x_position + 2
else
self._attach_parent = 'Body'
end
self._z_rotation = math.random(-30, 30)
self._y_rotation = math.random( -30, 30)
self.object:set_attach(obj, self._attach_parent, {x=self._x_position,y=self._y_position,z=random_arrow_positions('z', placement)}, {x=0,y=self._rotation_station + self._y_rotation,z=self._z_rotation})
minetest.after(150, function()
self.object:remove()
end)
end
end
obj:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, self.object:get_velocity())
end
if is_player then
if self._shooter and self._shooter:is_player() and self._in_player == false then
if self._shooter and self._shooter:is_player() then
-- “Ding” sound for hitting another player
minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true)
end
@ -327,14 +259,10 @@ ARROW_ENTITY.on_step = function(self, dtime)
end
end
end
if self._in_player == false then
minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true)
end
end
if not obj:is_player() then
mcl_burning.extinguish(self.object)
self.object:remove()
minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true)
end
mcl_burning.extinguish(self.object)
self.object:remove()
return
end
end
@ -461,8 +389,6 @@ ARROW_ENTITY.get_staticdata = function(self)
end
ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s)
self._time_in_air = 1.0
self._in_player = false
local data = minetest.deserialize(staticdata)
if data then
self._stuck = data.stuck

View File

@ -341,7 +341,7 @@ controls.register_on_hold(function(player, key, time)
end)
minetest.register_globalstep(function(dtime)
for _, player in pairs(minetest.get_connected_players()) do
for _, player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local wielditem = player:get_wielded_item()
local wieldindex = player:get_wield_index()

View File

@ -65,7 +65,7 @@ function mcl_buckets.register_liquid(def)
_doc_items_usagehelp = def.usagehelp,
_tt_help = def.tt_help,
inventory_image = def.inventory_image,
stack_max = 1,
stack_max = 16,
groups = def.groups,
on_place = function(itemstack, user, pointed_thing)
-- Must be pointing to node
@ -92,7 +92,7 @@ function mcl_buckets.register_liquid(def)
-- Check if pointing to a buildable node
local item = itemstack:get_name()
if def.extra_check and def.extra_check(place_pos, user) == false then
if extra_check and extra_check(place_pos, user) == false then
-- Fail placement of liquid
elseif minetest.registered_nodes[nn] and minetest.registered_nodes[nn].buildable_to then
-- buildable; replace the node

View File

@ -2,20 +2,6 @@ local S = minetest.get_translator(minetest.get_current_modname())
local mod_mcl_core = minetest.get_modpath("mcl_core")
local mod_mclx_core = minetest.get_modpath("mclx_core")
local sound_place = function(itemname, pos)
local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.place then
minetest.sound_play(def.sounds.place, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end
end
local sound_take = function(itemname, pos)
local def = minetest.registered_nodes[itemname]
if def and def.sounds and def.sounds.dug then
minetest.sound_play(def.sounds.dug, {gain=1.0, pos = pos, pitch = 1 + math.random(-10, 10)*0.005}, true)
end
end
if mod_mcl_core then
-- Lava bucket
mcl_buckets.register_liquid({

View File

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

View File

@ -131,7 +131,7 @@ minetest.register_abm({
interval = 0.5,
chance = 1,
action = function(pos, node)
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.4)) do
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 0.4)) do
if mcl_burning.is_burning(obj) then
mcl_burning.extinguish(obj)
local new_group = minetest.get_item_group(node.name, "cauldron_filled") - 1

View File

@ -1,3 +1 @@
name = mcl_cauldrons
depends = mcl_core, mcl_sounds
optional_depends = mclx_core, doc

View File

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

View File

@ -11,8 +11,10 @@ local entity_animations = {
},
chest = {
speed = 25,
open = {x = 0, y = 7},
close = {x = 13, y = 20},
open = {x = 0, y = 10},
open_partly = {x = 0, y = 7},
close = {x = 10, y = 20},
close_partly = {x = 13, y = 20},
}
}
@ -32,14 +34,15 @@ minetest.register_entity("mcl_chests:chest", {
self.object:set_animation(anim, anim_table.speed, 0, false)
end,
open = function(self, playername)
open = function(self, playername, partly)
self.players[playername] = true
if not self.is_open then
self:set_animation("open")
self:set_animation(partly and "open_partly" or "open")
minetest.sound_play(self.sound_prefix .. "_open", {
pos = self.node_pos,
})
self.is_open = true
self.opened_partly = partly
end
end,
@ -50,11 +53,12 @@ minetest.register_entity("mcl_chests:chest", {
for _ in pairs(playerlist) do
return
end
self:set_animation("close")
self:set_animation(self.opened_partly and "close_partly" or "close")
minetest.sound_play(self.sound_prefix .. "_close", {
pos = self.node_pos,
})
self.is_open = false
self.opened_partly = false
end
end,
@ -114,7 +118,7 @@ local function get_entity_pos(pos, dir, double)
end
local function find_entity(pos)
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0)) do
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 0)) do
local luaentity = obj:get_luaentity()
if luaentity and luaentity.name == "mcl_chests:chest" then
return luaentity
@ -175,7 +179,8 @@ local player_chest_open = function(player, pos, node_name, textures, param2, dou
open_chests[name] = {pos = pos, node_name = node_name, textures = textures, param2 = param2, double = double, sound = sound, mesh = mesh, shulker = shulker}
if animate_chests then
local dir = minetest.facedir_to_dir(param2)
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name)
local blocked = not shulker and (back_is_blocked(pos, dir) or double and back_is_blocked(mcl_util.get_double_container_neighbor_pos(pos, param2, node_name:sub(-4)), dir))
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name, blocked)
end
end

View File

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

View File

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

View File

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

View File

@ -94,8 +94,9 @@ minetest.register_globalstep(function(dtime)
watch.old_time = now
for p, player in pairs(minetest.get_connected_players()) do
for s, stack in pairs(player:get_inventory():get_list("main")) do
local players = minetest.get_connected_players()
for p, player in ipairs(players) do
for s, stack in ipairs(player:get_inventory():get_list("main")) do
local dim = mcl_worlds.pos_to_dimension(player:get_pos())
local frame
-- Clocks do not work in certain zones

View File

@ -1,4 +1 @@
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

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

View File

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

View File

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

View File

@ -1,4 +1 @@
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

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

View File

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

View File

@ -14,14 +14,15 @@ local random_frame = math.random(0, compass_frames-1)
minetest.register_globalstep(function(dtime)
random_timer = random_timer + dtime
local players = minetest.get_connected_players()
if random_timer >= random_timer_trigger then
random_frame = (random_frame + math.random(-1, 1)) % compass_frames
random_timer = 0
end
for i,player in pairs(minetest.get_connected_players()) do
for i,player in ipairs(players) do
local function has_compass(player)
for _,stack in pairs(player:get_inventory():get_list("main")) do
for _,stack in ipairs(player:get_inventory():get_list("main")) do
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 then
return true
end
@ -52,7 +53,7 @@ minetest.register_globalstep(function(dtime)
compass_image = math.floor((angle_relative/11.25) + 0.5) % compass_frames
end
for j,stack in pairs(player:get_inventory():get_list("main")) do
for j,stack in ipairs(player:get_inventory():get_list("main")) do
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 and
minetest.get_item_group(stack:get_name(), "compass")-1 ~= compass_image then
local itemname = "mcl_compass:"..compass_image

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