Compare commits

...

174 Commits

Author SHA1 Message Date
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 20e44e4033 Merge pull request 'Add mod.confs to silence Minetest 5.5 warnings' (#298) from rudzik8/Mineclonia:add-mod-confs into master
Reviewed-on: Mineclonia/Mineclonia#298
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-05-11 23:33:15 +00:00
Mikita Wiśniewski ac3031c679 Add mod.confs to silence Minetest 5.5 warnings 2022-05-11 07:09:15 +07:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 54f72a1457 Merge pull request 'ITEMS/mcl_farming: Move farming plant nodes 1/16 downwards' (#293) from move-farming-plants-lower into master
Reviewed-on: Mineclonia/Mineclonia#293
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-04-30 22:01:30 +00:00
Nils Dagsson Moskopp 0808b54192
Render mcl_farming plant stems 1/16 node lower
This patch shifts mcl_farming nodes that represent a stem 1/16 nodes
downwards. It also replaces the plantlike drawtype of mcl_farming nodes
that represent an unconnected stem (x) with a nodebox drawtype that
looks like a plus (+), as Minetest has no option to rotate nodeboxes.
The goal is to remove the gap between plants and farming soil with a
node height of 15/16.

This patch affects melon stem and pumpkin stem nodes.
2022-04-21 02:45:36 +02:00
Nils Dagsson Moskopp 14cbc63b5f
Render mcl_farming plant grids 1/16 node lower
This patch replaces the plantlike drawtype of mcl_farming plant nodes
that are rendered like a grid (#) with a nodebox drawtype. The nodebox
looks like a plantlike grid shifted 1/16 nodes downwards. The goal is to
remove gaps between plants and farming soil with a node height of 15/16.

This patch affects beetroot, carrots, potatoes, and wheat nodes.
2022-04-21 02:44:45 +02:00
Nils Dagsson Moskopp de8ea11b39
Add debug command to spawn mcl_farming plant nodes
This patch adds the debug command “/generate_farming_plant_rows”. The
command generates rows of plants and stems per plant type near a player.
A farming soil or glass node is placed below each node, so players can
find and examine possible gaps between a plant node and a node below.
2022-04-18 21:43:21 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 1ce88e7528 Merge pull request 'ITEMS/mcl_tnt: Add setting for TNT drop rate (default 100%)' (#291) from add-tnt-drop-rate-setting into master
Reviewed-on: Mineclonia/Mineclonia#291
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-04-18 19:36:10 +00:00
Nils Dagsson Moskopp 6e11819b79
Increase TNT drop rate to 100%
This makes the TNT drop rate match Minecraft 1.14.
2022-04-17 18:44:09 +02:00
Nils Dagsson Moskopp 5acc9191fa
Add setting for TNT drop rate 2022-04-17 18:42:46 +02:00
Nils Dagsson Moskopp 32d89d6d5f
Add TNT test structure
This patch adds a new test structure to the “/spawnstruct” command which
can be spawned with this command: /spawnstruct test_structure_tnt

The structure was added to reduce manual work when examining or
verifying TNT explosion results after changes to TNT drop rate.
2022-04-17 17:24:54 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. d2c335d8fb Merge pull request 'ITEMS/mcl_farming: Use uncarved pumpkin in survival' (#285) from uncarved-pumpkin-4 into master
Reviewed-on: Mineclonia/Mineclonia#285
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-04-15 22:51:58 +00:00
Nils Dagsson Moskopp 7d2ef66175
Trigger node callbacks when pumpkin is sheared
The code for shearing a pumpkin used minetest.swap_node() to replace a
faceless pumpkin with a carved pumpkin. This did not trigger the node
callbacks of the carved pumpkin, which meant that shearing a pumpkin
would not check for the snow golem or iron golem spawn conditions.

This patch replaces minetest.swap_node() in the code for shearing a
pumpkin with minetest.set_node(), which does trigger the callbacks;
therefore snow and iron golems can now spawn as a pumpkin is carved.
2022-04-14 18:52:31 +02:00
Nils Dagsson Moskopp fdd3c5db86
Drop carved pumpkin when shearing snow golem 2022-04-14 00:23:01 +02:00
Nils Dagsson Moskopp c4912effaf
Disconnect gourd stems after destruct
While testing the previous commit, it became clear that gourd stems do
not disconnect properly if the gourd disappears while not being dug. A
simple method to create illegal curved stems was to explode the gourd.

This patch changes gourds so that the stem curves back after a gourd is
destroyed, regardless of reason. This hopefully makes curved stems that
are not connected to matching gourds a relict of the past.
2022-04-14 00:23:01 +02:00
Nils Dagsson Moskopp 1967e10a52
Disconnect stems from carved pumpkins after dig
Carved pumpkins can end up being connected to a stem – either if they
were grown in a previous version of MineClone2 or Mineclonia, or if a
player carves them before harvesting them. This patch makes sure that
stems turn into unconnected stems after such a carved pumpkin is dug.
2022-04-14 00:23:00 +02:00
Nils Dagsson Moskopp f8d55ee61b
Make villagers accept uncarved pumpkin in trades
As map generation and growing mechanics have been changed to generate
uncarved pumpkins instead of carved, requiring players to shear every
pumpkin before trading it with villagers seems like useless busywork.
2022-04-14 00:23:00 +02:00
Nils Dagsson Moskopp 3948a0e7af
Remove pumpkin pie recipe with carved pumpkin
Shearing an uncarved pumpkin turns it into a carved pumpkin and drops
four pumpkin seeds. As map generation and growing mechanics have been
changed to generate uncarved pumpkins instead of carved, preserving a
recipe to get pumpkin pie from carved pumpkins enabled players to get
both seeds and pumpkin pie from grown pumpkins, which was unintended.
2022-04-14 00:22:59 +02:00
Nils Dagsson Moskopp a44fd9c88b
Remove pumpkin seeds recipe with carved pumpkin
Shearing an uncarved pumpkin turns it into a carved pumpkin and drops
four pumpkin seeds. As map generation and growing mechanics have been
changed to generate uncarved pumpkins instead of carved, preserving a
recipe to get seeds from carved pumpkins enables players to get twice
the amount of seeds as intended. Because of this, the recipe must go.
2022-04-14 00:22:59 +02:00
Alexander Minges 6381d65dbb
Use correct location for pumpkin shearing sound
The code for turning an uncarved pumpkin into a carved pumpkin using
the shears was using “above” instead of “pointed_thing.above” as the
location for its sound. This resulted in a warning being logged when
shears were being used on a pumpkin. This patch rectifies the issue.
2022-04-14 00:22:59 +02:00
Alexander Minges 59b013f766
Grow uncarved pumpkin from seeds instead of carved
Carved pumpkin has to be explicitly registered as a separate node, as
registering a carved pumpkin node happened as a side effect of invoking
mcl_farming:add_gourd() for the carved pumpkin.

The iron / snow golem spawning checks that trigger whenever a carved
pumpkin is placed had to be moved out of the mcl_farming:add_gourd()
invocation to preserve the existing behaviour.

Note that uncarved pumpkin must not be registered as a separate node,
as invoking mcl_farming:add_gourd() for a registered node name leads to
stems not updating when an adjacent node is manually placed or mined.
2022-04-14 00:22:58 +02:00
Alexander Minges d59888c4df
Use uncarved pumpkin instead of carved in mapgen 2022-04-14 00:22:58 +02:00
cora 8810a24ce0 Merge pull request 'ITEMS/REDSTONE/mcl_comparators: Fix redstone comparator flooding crash' (#284) from fix-comparator-cauldron-water-crash into master
Reviewed-on: Mineclonia/Mineclonia#284
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-23 22:30:44 +00:00
Nils Dagsson Moskopp be915478af
Fix redstone comparator flooding crash
Redstone comparators have two modes, comparison mode & subtraction mode.
Before this patch, the functions to turn comparators on or off attempted
to swap nodes with comparators in the same mode, but failed to determine
the correct replacement node, if the existing node was not a comparator.

When a comparator in an on state (e.g. powered by a filled cauldron) was
flooded, the flooding dropped the comparator and replaced the comparator
node that was to be swapped out with air, which lead to a server crash.

This patch changes the functions that turn comparators on or off so they
only swap existing nodes with comparators in the same mode if the name
of the replacement node can be determined – i.e. if it is not nil.
2022-02-23 00:27:56 +01:00
Nils Dagsson Moskopp d9764fdac6
Add comparator test structure
This patch adds a new test structure to the “/spawnstruct” command which
can be spawned with this command: /spawnstruct test_structure_comparator

The structure was added to reduce manual work when examining or
verifying comparator behaviour after changes to comparator code.
2022-02-22 23:48:10 +01:00
cora de9f2479eb Merge pull request 'HUD/mcl_tmp_message: Add setting for temporary message display duration (default: 10s)' (#266) from tmp-message-timeout-increase into master
Reviewed-on: Mineclonia/Mineclonia#266
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-02-18 10:59:47 +00:00
Nils Dagsson Moskopp c128d43321
Increase temporary message display duration to 10s 2022-02-12 17:25:09 +01:00
Nils Dagsson Moskopp e7070c034c
Add setting for temporary message display duration 2022-02-12 17:25:03 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 18e299d923 Merge pull request 'ITEMS/mcl_fire: Fix fire spread to not freeze the game' (#234) from fix-fire into master
Reviewed-on: Mineclonia/Mineclonia#234
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2022-02-12 03:39:40 +00:00
cora f5ba6f5649
Fix memory leak & C stack overflow
Before this patch, when placing a fire above a node that would turn it
into eternal fire (e.g. Netherrack or Magma) the spawn_fire() function
would call itself infinitely via the on_construct() handler of eternal
fire – because the latter called spawn_fire() itself.

On an x86 machine, this caused a memory leak, hanging Minetest. On an
x86_64 machine though, Minetest crashed immediately, showing an error
message about a stack overflow.
2022-02-11 17:44:11 +01:00
cora 4647710945
Extinguish fire without nearby “fuel” faster
This patch adjusts how often the ABM runs that removes fire nodes with
no adjacent nodes that can burn up. This makes fire linger less in air.
2022-02-11 17:44:10 +01:00
cora 5d09ec311c
Extinguish fire using an ABM instead of timers
Even the mitigated timers seem to have lead to slow
memory leaks. Once Minetest has used up all the RAM,
it will free some, then quickly use memory up again,
then repeat it ad nauseum, requiring 100% CPU. On a
PC with 2GB of RAM this could be reliably triggered
by having a fire burn a forest for 20 to 30 minutes.

This patch removes fire node timers completely and
instead extinguishes fire using an ABM.
2022-02-11 17:44:09 +01:00
cora ef7370550f
Make fire spread direction truly random
This patch initializes the random number generator used in mcl_fire with
the current Unix timestamp. It also corrects two biases in fire spread
that were caused by nodes being iterated over in a predictable way.
2022-02-11 17:41:42 +01:00
cora 6c2fb98160
Fix nodes with “flammable = -1” not catching fire 2022-02-07 04:51:27 +01:00
cora 052c9fcbcf
Fix diagonal fire-spread
In Minecraft fire spread logic, “adjacent” does not mean “diagonal”.
2022-02-07 04:51:06 +01:00
cora db8fbdc5dd
Fix beds burning away and dropping 2022-02-07 03:39:52 +01:00
cora 1b89c15193
Fix double nodes not being properly removed 2022-02-07 03:39:51 +01:00
cora 02fa2c9e07
Fix nodes that should not burn up burning up
Nodes with the group “flammable = -1” (e.g. crafting tables) must be
able to catch fire, but must not burn up. This patch adds checks for
this group.
2022-02-07 03:39:51 +01:00
cora c12076e74d
Reimplement basic Minecraft-like fire spread 2022-02-07 03:39:45 +01:00
cora 4deca628dc
Make fire actually remove nodes 2022-02-07 03:22:15 +01:00
cora df4ea94dbc
Add node timer back in so fires burn out 2022-02-07 03:22:02 +01:00
cora 8e8ccddb68
Replace MineClone2 fire with Minetest Game ABMs
ABMs have better performance than the laggy timer-based implementation.
2022-02-07 03:18:54 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 11469886e0 Merge pull request 'MAPGEN/mcl_structures: Add (theoretically) fireproof test structure' (#258) from add-fireproof-structure into master
Reviewed-on: Mineclonia/Mineclonia#258
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-02-07 01:24:58 +00:00
Nils Dagsson Moskopp 96822be63d
Add (theoretically) fireproof test structure
This patch adds a new test structure to the “/spawnstruct” command which
can be spawned with this command: /spawnstruct test_structure_fireproof

The structure can be used to verify that eternal fire can be spawned by
the structure placement code. It can also be used to debug fire spread,
as according to Minecraft fire spread rules, it should be fireproof.

See <https://minecraft.fandom.com/wiki/Fire#Spread> for those rules.
2022-02-06 01:19:23 +01:00
cora 6abdbbbd13 Merge pull request 'ENTITIES/mcl_boats: Fix mob-in-boat crash in Minetest 5.5-dev' (#249) from fix-boat-crash-in-minetest-5.5-dev into master
Reviewed-on: Mineclonia/Mineclonia#249
Reviewed-by: cora <cora@noreply.git.minetest.land>
2022-01-27 00:50:08 +00:00
Nils Dagsson Moskopp f89c52dff6
Fix mob-in-boat crash in Minetest 5.5-dev
In Minetest 5.4.1, calling get_player_control() on a mob returned the
empty string. Minetest commit 5eb45e1ea03c6104f007efec6dd9c351f310193d
changed this, so now calling get_player_control() on a mob returns nil.

As mcl_boats defines boats that can have a player or a mob as a driver,
code like the following crashes with a changed get_player_control() API:

local ctrl = driver:get_player_control()
if ctrl.sneak then
    detach_object(driver, true)
end

Furthermore, once a world has crashed, joining it near a mob that is the
driver of a boat with such control code immediately crashes again.

When I reported this bug to Minetest, several Minetest core developers
stated that they disliked the old API and proposed other return values
for calling a mob's get_player_control() function – all different from
the empty string. Since I have some doubts that this bug will be fixed
in Minetest 5.5.0, boat code must take into account a nil return value.

Minetest issue: https://github.com/minetest/minetest/issues/11989
2022-01-26 18:25:08 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. b1b96e3fac Merge pull request 'ITEMS/mcl_armor: Fix armor rendering when wearing pumpkin' (#244) from fix-pumpkin-armor-rendering-2 into master
Reviewed-on: Mineclonia/Mineclonia#244
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-23 19:59:13 +00:00
epCode 6bfb97842f
Fix armor rendering when wearing pumpkin
Before this patch, wearing a pumpkin would make body armor render as a
corrupted item held in the player's left hand instead of on their body.
Some parts of their armor would also get rendered on the player's feet.

(cherry picked from commit 12192d1a8d)
2022-01-23 20:11:55 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 3b92d060f4 Merge pull request 'HUD/mcl_inventory: Fix creative mode inventory search crash' (#237) from fix-creative-inventory-crash into master
Reviewed-on: Mineclonia/Mineclonia#237
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-22 16:49:19 +00:00
Nils Dagsson Moskopp f975055464
Fix creative mode inventory search crash
Before this patch it was possible for any user to to crash Minetest in
creative mode. This was possible because queries in the search field
were interpreted as search patterns for string.find().

A search for a single square bracket would reliably crash the server.
Also, a search for 6000 times the string “a?” would hang the server.

The solution to both bugs is to not interpret the query as a pattern.
2022-01-21 23:31:25 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 23f1c51912 Merge pull request 'ITEMS/mcl_farming: Convert correct floor node to dirt as gourd grows' (#231) from fix-gourd-farmland-dirtification into master
Reviewed-on: Mineclonia/Mineclonia#231
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-15 22:07:24 +00:00
Nils Dagsson Moskopp 4d02af8c94
Convert correct floor node to dirt as gourd grows
Before this patch, growing a gourd (e.g. melon, pumpkin) would always
convert a node west of the node below the stem to dirt if belonged to
the group “dirtifies_below_solid”. This happened because of a loop in
which the variables floorpos and floor were re-used without setting a
new value … therefore, both floorpos and floor were always containing
the last values set in a previous loop instead of the correct values.

This patch fixes the problem by setting both variables in both loops.
2022-01-13 07:29:57 +01:00
Li0n_2 7ede0ca79a Merge pull request 'Fix shearsy wool typo in GROUPS.md' (#229) from JosiahWI/Mineclonia:fix-groups-typo into master
Reviewed-on: Mineclonia/Mineclonia#229
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-12 21:19:10 +00:00
JosiahWI e2e7e15b39
fix one character typo in GROUPS.md 2022-01-12 11:09:07 -06:00
cora 93a0879b40 Merge pull request 'MISC/mcl_selftests: Do not crash if minetest.find_nodes_in_area() lies' (#214) from fix-selftest-crash into master
Reviewed-on: Mineclonia/Mineclonia#214
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-20 22:42:59 +00:00
Nils Dagsson Moskopp 0b5fa14041 Do not crash if minetest.find_nodes_in_area() lies 2021-12-20 21:38:24 +01:00
cora 4f33f626f5 Merge pull request 'ITEMS/mcl_chests: Reskin chests as presents on December 24th to 26th' (#212) from add-christmas-chests into master
Reviewed-on: Mineclonia/Mineclonia#212
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-20 16:34:54 +00:00
Nils Dagsson Moskopp df7bd78af5
Add noise to christmas chest textures 2021-12-12 15:40:29 +01:00
Nils Dagsson Moskopp fe3e837e1b
Reskin chests as presents on December 24th to 26th 2021-12-11 18:17:53 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 6f811b3cee Merge pull request 'ITEMS/mcl_chests: Spawn small chest entities only if animated chests are enabled' (#207) from fix-animchest-setting into master
Reviewed-on: Mineclonia/Mineclonia#207
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-12-11 14:27:24 +00:00
Lizzy Fleckenstein dfa56f229f
Spawn small chest entities only if animated chests are enabled 2021-12-10 22:15:53 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. ee77f33ea8 Merge pull request 'PLAYER/mcl_playerplus: send player object props only if changed' (#147) from fix-active-object-message-spam into master
Reviewed-on: Mineclonia/Mineclonia#147
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-12-09 09:31:09 +00:00
cora 5deaabdb47
Fix player bone positions and properties setting
The comparison and setting logic in the previous patch that set player
bone positions and properties conditionally incorrectly did not update
some values (like player eye level position) when they changed. This
patch fixes it and adds asserts to ensure the code works as intended.
2021-12-09 04:53:45 +01:00
cora d77f31eab8
Only set/send player properties if necessary
Before this patch, Mineclonia set (and therefore sent) player bone
positions and player properties in every globalstep. This results in
about 30 TOCLIENT_ACTIVE_OBJECT_MESSAGE per second per player. This
patch adds conditional functions to set bone positions and properties.
The functions set values only when they have changed, reducing traffic.
2021-12-09 04:26:22 +01:00
cora 10670d5c10 Merge pull request 'HUD/mcl_death_messages: Fix crash when skeleton kills player using bow' (#202) from fix-skelly-crash-2 into master
Reviewed-on: Mineclonia/Mineclonia#202
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-06 18:42:20 +00:00
Nils Dagsson Moskopp 609105e091
Add test cases for get_tool_name() 2021-12-06 04:11:55 +01:00
cora f9e3c4fd6d
Fix crash when skeleton kills player using bow
Commit 5252952555 used string.gsub() to
strip newlines from tools in death messages. The second return value of
string.gsub() (the number of substitutions) was erroneously returned too
by get_tool_name(). This bug caused a crash whenever a skeleton killed a
player using its bow.
2021-12-06 03:48:39 +01:00
cora d70c05e92c Merge pull request 'ITEMS/mcl_chests: Fix access to ender chest inventory without an ender chest' (#193) from EliasFleckenstein03/Mineclonia:enderchest-fix into master
Reviewed-on: Mineclonia/Mineclonia#193
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-04 13:25:26 +00:00
Lizzy Fleckenstein cacddd3fb4
Fix access to ender inventory without an ender chest 2021-12-03 21:23:10 +01:00
cora dd347c50c5 Merge pull request 'ITEMS/mcl_chests: Add debug command to show ender chest inventory formspec.' (#194) from add-enderchest-command into master
Reviewed-on: Mineclonia/Mineclonia#194
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-03 10:53:51 +00:00
Nils Dagsson Moskopp 54b36c42a9
Add debug command to show ender chest inventory formspec. 2021-12-02 19:44:22 +01:00
cora 5252952555 strip newlines from tools in death messages
Players naming their tools with newlines can mess up chat with death
messages. This commit strips out newlines (\r and \n ) in the tool
name for death messages.
2021-12-01 13:25:57 +00:00
Li0n_2 c08f9850f6 Merge pull request 'Add packed ice crafting recipe' (#180) from add-packed-ice-crafting-recipe into master
Reviewed-on: Mineclonia/Mineclonia#180
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2021-11-27 23:43:28 +00:00
Nils Dagsson Moskopp f8b5066c61
Add packed ice crafting recipe 2021-11-24 06:06:26 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 4b9094ddc2 Merge pull request 'ITEMS/mcl_core: remove swiftness from egapps' (#177) from fix-egapp-speed into master
Reviewed-on: Mineclonia/Mineclonia#177
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-11-20 01:21:11 +00:00
cora 5087e8194a remove swiftness from egapps
The minetest world is already so small that you can reach world
border from spawn in about 2 hours. I think the regen and fire
resistance are  good enough to make them special.
2021-11-20 02:14:16 +01:00
cora 71befcff10 Merge pull request 'ENTITIES/mcl_mobs: Give mobs sunburn at correct light level' (#175) from fix-mobs-burning-in-sunlight into master
Reviewed-on: Mineclonia/Mineclonia#175
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-11-19 20:27:55 +00:00
Nils Dagsson Moskopp 66dd87af25
Give mobs sunburn at correct light level
Before this patch, the light level that makes mobs that burn in sunlight
catch fire had been mistakenly specified as minetest.LIGHT_MAX or more.

The correct light level for sunlight is LIGHT_SUN, which is one higher
than minetest.LIGHT_MAX. Since minetest.LIGHT_MAX is the maximum light
value that a node can have and torches emit light at that light level,
mobs that burn in sunlight caught fire inside torch nodes.
2021-11-19 03:14:36 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. fc47f0a87e Merge pull request 'CORE/mcl_colors: Add mod providing global color values' (#172) from add-mcl-colors into master
Reviewed-on: Mineclonia/Mineclonia#172
Reviewed-by: Li0n <li0nsdichachu@outlook.com>
2021-11-18 20:57:08 +00:00
Nils Dagsson Moskopp 6bd4b0e62c
Fix typo in mcl_colors API documentation 2021-11-18 19:23:57 +01:00
AFCMS 3473f55136
Add API documentation to mcl_colors 2021-11-18 19:14:21 +01:00
Lizzy Fleckenstein af7f7c3574
Add mcl_colors 2021-11-18 19:13:08 +01:00
cora 434e545745 Merge pull request 'MISC/mcl_engine_workarounds: Add crash fix and tests for minetest.find_nodes_in_area()' (#169) from fix-find-nodes-in-area-3 into master
Reviewed-on: Mineclonia/Mineclonia#169
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-11-18 11:43:57 +00:00
Nils Dagsson Moskopp 76d2846c59
Improve test for minetest.find_nodes_in_area()
• By emerging test areas, the test gets real map data and does not block.
• The test now also ensures that any return values are compared exactly.
• minetest.find_nodes_in_area() is tested with the “grouped” parameter.
2021-11-18 04:47:03 +01:00
Nils Dagsson Moskopp 526c25aa57
Add crash fix and tests for minetest.find_nodes_in_area()
For some specific out of bounds values, the volume calculation in
minetest.find_nodes_in_area() is off by about four million nodes.
Unfortunately that behaviour made it trivial to crash Mineclonia,
as Minetest immediately crashes upon encountering large numbers.

This commit introduces a wrapper around minetest.find_nodes_in_area()
which should avoid a crash. Additionally, three self tests are executed
when a server starts; they crash Mineclonia in case the workaround fails.
2021-11-18 00:55:59 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 249cfb8118 Merge pull request 'ENTITIES/mcl_burning: Fix burning animation packetspam' (#149) from fix-burning-animation-packetspam into master
Reviewed-on: Mineclonia/Mineclonia#149
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-11-13 01:34:17 +00:00
cora 84194b71e6 burning: prevent adding multiple entities+huds 2021-11-12 01:16:16 +01:00
cora 0b7097cb28 add a burning animation fps setting 2021-11-12 01:16:16 +01:00
cora bfbc953b92 Merge pull request 'ENTITIES/mcl_burning: Add debug command to burn a player' (#164) from add-burn-command-2 into master
Reviewed-on: Mineclonia/Mineclonia#164
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-11-11 22:25:14 +00:00
Nils Dagsson Moskopp 253100380c
Add debug command to burn a player 2021-11-11 21:37:26 +01:00
cora df98db1d8c Merge pull request 'ITEMS/mcl_banners: Render preview banners with transparent patterns correctly' (#158) from banner-mask-fix-4 into master
Reviewed-on: Mineclonia/Mineclonia#158
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-11-08 12:21:50 +00:00
Nils Dagsson Moskopp f410de485a
Render preview banners with transparent patterns correctly
Without this fix, the banner pattern preview generation does not mask
the banner pattern, so the alpha channel of the banner pattern is not
taken into account. This lead to preview banners with color gradients
showing up as a solid color banner and opaque pixel artifacts for the
bottom triangle pattern.
2021-10-31 20:53:18 +01:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 3a78211be4 Merge pull request 'ITEMS/mcl_maps: send hud_flags only if actually changed' (#146) from fix-minimap-spam into master
Reviewed-on: Mineclonia/Mineclonia#146
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-09-15 17:20:34 +00:00
cora eee94658e7 mcl_maps: send hud_flags only if actually changed 2021-09-13 14:15:32 +02:00
cora 07a59ef120 Merge pull request 'Add dirt node group documentation' (#142) from add-dirt-group-documentation into master
Reviewed-on: Mineclonia/Mineclonia#142
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-09-08 01:39:32 +00:00
Nils Dagsson Moskopp e1462d9534
Add dirt node group documentation 2021-09-08 03:16:19 +02:00
cora 42a076cc0b Merge pull request 'ITEMS/mcl_core: Add debarking and stripped trunk / wood' (#135) from stripped-wood-3 into master
Reviewed-on: Mineclonia/Mineclonia#135
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-09-07 01:41:01 +00:00
NO11 3759d50344
Add german translation for stripped wood 2021-09-07 00:48:40 +02:00
NO11 50e913b370
Add template for stripped wood translation 2021-09-07 00:48:39 +02:00
NO11 508b08dfd3
Add specific help text for stripped wood 2021-09-07 00:48:38 +02:00
NO11 68646b62b3
Add some spaces 2021-09-07 00:48:38 +02:00
NO11 d3348ef8b7
Add stripped trunk / wood textures
Stripped trunk / wood nodes exist for acacia, birch, dark oak, jungle
tree, oak, and spruce. This patch adds the textures for all of these.
2021-09-07 00:48:37 +02:00
NO11 eadb96dd40
Refactor wooden plank crafting
This patch makes it possible to craft planks out of stripped wood.
2021-09-07 00:48:36 +02:00
NO11 616b009452
Add stripped trunk and stripped wood nodes 2021-09-07 00:48:35 +02:00
NO11 a92e1c05a3
Add debarking by right clicking wood using an axe 2021-09-07 00:48:10 +02:00
cora b26fb44aeb Merge pull request 'New Mineclonia logo' (#140) from add-mineclonia-menu-header into master
Reviewed-on: Mineclonia/Mineclonia#140
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-08-27 02:53:11 +00:00
Li0n 19112bfbec
New Mineclonia logo 2021-08-27 04:09:35 +02:00
cora 6f046b199d Merge pull request 'Add Mineclonia menu icon' (#139) from add-mineclonia-menu-icon into master
Reviewed-on: Mineclonia/Mineclonia#139
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-08-27 01:31:19 +00:00
Nils Dagsson Moskopp 7f4f5c5c89
Make menu icon export compatible with Inkscape 1.0
Though usually one would export directly to "${3}", Inkscape 1.0 had
its command line options changed by people who apparently think that
backwards compatibility is some kind of swear word: Whereas earlier
Inkscape versions would export to a file called foo.png.tmp, newer
behaviour is to ignore the user's wishes & write to foo.png.png –
unless one asks it to write to a filename with a .png extension,
Inkscape 1.0 changes the filename extension to .png each time.

As we do not know the extension of "${3}", we have to use the
extension, then rename the resulting file to the proper name;
only that way the export works with Inkscape 1.0 & earlier …
2021-08-27 03:08:04 +02:00
Nils Dagsson Moskopp a2b8489c80
Add Mineclonia menu icon PNG 2021-08-24 03:32:10 +02:00
Nils Dagsson Moskopp c83278d3ff
Add dofile for Mineclonia menu icon PNG 2021-08-24 03:31:58 +02:00
Nils Dagsson Moskopp cef3669ee2
Add Mineclonia menu icon SVG 2021-08-24 01:52:55 +02:00
cora 78634d4c90 Merge pull request 'PLAYER/wieldview: Fix server crash by client leaving after joining' (#138) from fix-server-crash-by-client-leaving-after-joining into master
Reviewed-on: Mineclonia/Mineclonia#138
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-08-22 17:26:32 +00:00
Nils Dagsson Moskopp 10ce37d887
Fix server crash by client leaving after joining
When a player joins and immediately leaves the game before a function is
called by minetest.after() in mods/PLAYER/wieldview/init.lua, it gets an
invalidated player object. This results in the player methods returning
nil (since Minetest 5.2); perhaps surprisingly, the player is not nil.

Not checking that the result of player:get_pos() is not nil could lead
to a server crash if a client crashed when joining. It has been reported
that a syntax error in a client side mod was enough to trigger that.
2021-08-22 04:21:35 +02:00
cora 3cd4ad5591 Merge pull request 'ENTITIES/mcl_item_entity: Fix non-serializable item entity unload crash' (#132) from fix-overlong-meta-item-crash-2 into master
Reviewed-on: Mineclonia/Mineclonia#132
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-08-01 01:23:43 +00:00
Nils Dagsson Moskopp ce6d6c26cc
Add debug command to acquire a written book
The “getwrittenbook” command gives a player that has the “debug” privilege a book
with a configurable amount of characters. This was added as a debug aid, to help
reproducing situations in which items with lots of metadata trigger issues like
heavy lag or server crashes.
2021-07-30 17:22:33 +02:00
Nils Dagsson Moskopp a0c9f11af6
Log warning for non-serializable item entity fix 2021-07-30 17:15:13 +02:00
sfan5 62d5b547a0
Fix non-serializable item entity unload crash
Some items, like shulkers or books, can have so much metadata that the
corresponding item entity can not be serialized by the Minetest engine.

Without this patch, dropping such an item and then moving away crashes
Minetest, as it can not serialize the entity with serializeString16()
when unloading a map block.

The patch resets the overlong metadata of non-serializable item entities.
This avoids a crash and makes it possible to retrieve a “sanitized” item
without metadata when the mapblock containing the item entity is reloaded.

Originally sfan5 guessed the maximum possible item entity serialization size
that would not lead to a crash as 65530 bytes, but anon5 calculated it to be
actually 65487 bytes. This has been experimentally verified by erlehmann.
2021-07-30 17:13:26 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 45cdad7283 Merge pull request 'MAPGEN/tsm_railcorridors: Generate pig spawners in mineshafts' (#127) from mineshaft-pig-spawners into master
Reviewed-on: Mineclonia/Mineclonia#127
Reviewed-by: E <e@noreply.git.minetest.land>
2021-07-23 02:24:17 +00:00
Nils Dagsson Moskopp 71cff7051f
Generate pig spawners in mineshafts
In Minecraft Java Edition, when the map generator generates a spawner,
it can generates a pig spawner instead of the spawner it should create.
That behaviour is very rare, but has never been removed from Minecraft.

This patch changes 1 in 1000 spawners in a mineshaft to be a pig spawner
instead of a cave spider spawner.
2021-07-23 04:11:33 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. eddbfb4b5c Merge pull request 'HUD/hudbars: Do not send useless HUDCHANGE packets' (#122) from fix-hudchange-spam into master
Reviewed-on: Mineclonia/Mineclonia#122
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-07-22 01:21:22 +00:00
Wuzzy 280aed484c
Do not send useless HUDCHANGE packets
Several mods set or unset the visibility of a HUD bar way too often (e.g.
in a globalstep handler), causing the server to send a lot of superfluous
HUDCHANGE packets to each client. Returning from hb.hide_hudbar() early
if HUD bar visibility would not change prevents sending these packets.
2021-07-21 10:28:04 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. c1cf50ae15 Merge pull request 'Add script to show packets count from client logs' (#123) from analyze-packet-spam into master
Reviewed-on: Mineclonia/Mineclonia#123
Reviewed-by: E <e@noreply.git.minetest.land>
2021-07-21 07:16:34 +00:00
Nils Dagsson Moskopp 01c8339f40
Add script to show packets count from debug logs
Mineclonia has inherited mods from MineClone 2 that send a lot of network
packets. This behaviour wastes bandwith and is most likely a major reason
for the unusually high amount of lag that MineClone2 and Mineclonia have.

Many network packets that are sent by Mineclonia are entirely useless.
Analyzing minetest log files to figure out what kind of packets are
sent and how often is a first step in getting rid of useless traffic.
2021-07-19 22:29:07 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 6219e8ae12 Merge pull request 'ITEMS/mcl_end: Make dragon egg teleport on punching' (#119) from dragon-egg-teleport into master
Reviewed-on: Mineclonia/Mineclonia#119
Reviewed-by: E <e@noreply.git.minetest.land>
2021-07-13 08:02:12 +00:00
Lizzy Fleckenstein 920ca96764
Make dragon egg teleport on punching 2021-07-13 09:11:48 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. e2e08f28dd Merge pull request 'items/mcl_bows: Let players shoot themselves with arrows' (#117) from fix-arrow-selfshoot-3 into master
Reviewed-on: Mineclonia/Mineclonia#117
Reviewed-by: E <e@noreply.git.minetest.land>
2021-07-13 06:55:57 +00:00
Nils Dagsson Moskopp 76e3a00e18
Make potion arrows able to hit end crystals 2021-07-12 22:21:15 +02:00
Nils Dagsson Moskopp 2033a9bf1d
Refactor potion arrow flight time calculation 2021-07-12 16:07:20 +02:00
Nils Dagsson Moskopp 99ebf08873
Refactor regular arrow flight time calculation 2021-07-12 16:06:44 +02:00
Nils Dagsson Moskopp c45c0df118
Play no hit sound when potion arrow hits shooter 2021-07-12 04:59:53 +02:00
Nils Dagsson Moskopp 39023f1adf
Play no hit sound when regular arrow hits shooter 2021-07-12 04:59:39 +02:00
Nils Dagsson Moskopp 689054f904
Fix sound_play invocation when player hit by potion arrow 2021-07-12 03:49:05 +02:00
cora 8ed5fd4740
Let players shoot themselves with potion arrows 2021-07-12 02:44:17 +02:00
epCode 6951ecdfc9
Let players shoot themselves with regular arrows 2021-07-12 02:09:47 +02:00
cora 9f086a9242 Merge pull request 'PLAYER/mcl_sprint: Send FOV packets only when necessary' (#106) from reduce-fov-packet-spam into master
Reviewed-on: Mineclonia/Mineclonia#106
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-07-06 20:35:12 +00:00
Nils Dagsson Moskopp 275f0826ed
Send FOV packets only when necessary
Before this change, about 10 to 30 FOV packets were sent from the server
to each connected client each second. This patch only sends FOV packets
when the FOV actually needs to be changed, i.e. when the player starts
or stops sprinting.
2021-07-04 03:25:05 +02:00
cora 00ee2d5013 Merge pull request 'ITEMS/mcl_chests: Fix Ender chests from MineClone2' (#103) from fix-ender-chests-from-mineclone2 into master
Reviewed-on: Mineclonia/Mineclonia#103
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-29 21:25:37 +00:00
Nils Dagsson Moskopp f8c58262bc
Fix Ender chests from MineClone2
Commit 819dbc6224c3b96ad4094cccf3d9150f3ef61d45 of MineClone2 introduced
an LBM that removed Ender chest formspecs stored in the node meta. That
change makes Ender chests that were loaded in MineClone2 versions past
that commit not show the Ender chest inventory form on right-click.

This patch makes those broken Ender chests work by introducing an LBM
that writes the formspec to the node meta for Ender chest nodes once.

Since the LBM name is suffixed with a hash of the Ender chest formspec,
changes to the Ender chest formspec (even removing it entirely) should
not require manual adjustment of the LBM code.
2021-06-28 22:54:00 +02:00
cora 926d5e2c37 Merge pull request 'mcl_inventory: Remove _mcl_autogroup dependency from mcl_inventory' (#76) from fix_inventory_depends into master
Reviewed-on: Mineclonia/Mineclonia#76
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-25 15:25:45 +00:00
cora f1ac39eaad Merge branch 'master' into fix_inventory_depends 2021-06-25 15:12:05 +00:00
cora 58fe08332f Merge pull request 'ITEMS/mcl_core: Fix snow dupe' (#102) from fix-snow-dupe into master
Reviewed-on: Mineclonia/Mineclonia#102
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-24 21:46:04 +00:00
Nils Dagsson Moskopp 1e42c37895
Reduce snow layer silk touch drop amount
It was possible to duplicate snow layers by placing them and then mining
them using a tool enchanted with silk touch. This commit fixes the “snow
dupe” by reducing the amount of snow layers dropped in this case by one.
2021-06-23 03:06:24 +02:00
cora 0816ee38b4 Merge pull request 'ITEMS/screwdriver: Show screwdriver in creative inventory' (#99) from show-screwdriver-in-creative-inventory into master
Reviewed-on: Mineclonia/Mineclonia#99
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-21 22:43:59 +00:00
Nils Dagsson Moskopp 0b92dc1f26
Show screwdriver in creative inventory 2021-06-22 00:16:57 +02:00
cora 87761bf454 Merge pull request 'Make fully grown beetroot drop 1 to 4 seeds when harvested' (#96) from fix-beetroot-seed-drops into master
Reviewed-on: Mineclonia/Mineclonia#96
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-20 22:13:45 +00:00
Elias Åström 725bf517ca Merge remote-tracking branch 'n_to/bow_increase_critical_chance_to_25'
Reviewed-on: #34
Reviewed-by: Elias Åström <ryvnf@riseup.net>
Reviewed-by: E <e@noreply.git.minetest.land>
2021-06-20 23:55:44 +02:00
Elias Åström fc61c71df5 Merge remote-tracking branch 'n_to/nametag_death_german'
Reviewed-on: #32
Reviewed-by: Li0n <li0nsdichachu@outlook.com>
Reviewed-by: Elias Åström <ryvnf@riseup.net>
2021-06-20 23:54:18 +02:00
Elias Åström 7bfd28cd75 Merge remote-tracking branch 'n_to/update_template.txt'
Reviewed-on: #17
Reviewed-by: Lion <li0nsdichachu@outlook.com>
2021-06-20 23:52:15 +02:00
Nils Dagsson Moskopp eb7b99d59e
Make fully grown beetroot drop 1 to 4 seeds when harvested
As beetroot often did not drop seeds, players could end up with no seeds when
trying to farm beetroot. This patch guarantees that at least one beetroot seed
is dropped when harvesting beetroot.
2021-06-20 19:02:35 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. b96dad7852 Merge pull request 'ITEMS/mcl_banners: Allow more layers for banners with gradients' (#74) from e/Mineclonia:banner-gradient-limits into master
Reviewed-on: Mineclonia/Mineclonia#74
Reviewed-by: Elias Åström <ryvnf@riseup.net>
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-06-19 13:01:11 +00:00
E 2feab24dd3 Allow more layers for banners with gradients
At some point in the past, Minetest had a bug that caused rendering
issues with transparent textures, like those used for banner gradients.
As a workaround, the number of allowed layers was reduced for banners
containing gradients. The engine bug has since been fixed, but the limit
was never removed.

This commit removes the limit.

See also: Mineclonia/Mineclonia#72 (comment)
and https://github.com/minetest/minetest/issues/6210
2021-06-19 01:43:36 -04:00
cora c9a8ef0ac2 Merge pull request 'ITEMS/REDSTONE/mcl_dispensers: Fix server crash when dispensing an unknown item' (#93) from fix-dispenser-unknown-item-crash into master
Reviewed-on: Mineclonia/Mineclonia#93
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-19 01:32:26 +00:00
Nils Dagsson Moskopp 2aafb2f2d0
Fix server crash when dispensing an unknown item 2021-06-19 02:04:59 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 86c1f37296 Merge pull request 'ENTITIES/mcl_boats: Fix server crash when boat passenger sneaks' (#91) from fix-boat-passenger-sneaking-crash into master
Reviewed-on: Mineclonia/Mineclonia#91
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-18 22:01:35 +00:00
Lizzy Fleckenstein 764ff5512a
Fix server crash when boat passenger sneaks
The crash occured when a player who is not a driver of a boat sneaked.
2021-06-18 19:08:19 +02:00
cora 6c311d5528 Merge pull request 'CORE/_mcl_autogroup: Prevent server crash on digging unknown' (#85) from fix-dig-unknown-crash into master
Reviewed-on: Mineclonia/Mineclonia#85
Reviewed-by: erlehmann <nils+git.minetest.land@dieweltistgarnichtso.net>
2021-06-17 21:51:55 +00:00
cora 79766bff23
Fix server crash when players dig unknown nodes
Digging unknown nodes crashes the Clamity Minetest server, which
runs modified Minetest: https://github.com/ClamityAnarchy/minetest
Crashes did occur with commit d5434bf008 of that Minetest version.

This commit makes unknown nodes explicitly not harvestable.
2021-06-17 23:39:13 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 031ae5fcb5 Merge pull request 'ITEMS/mcl_jukebox: backport mcl_jukebox API' (#83) from backport_mcl_jukebox_api into master
Reviewed-on: Mineclonia/Mineclonia#83
Reviewed-by: Elias Åström <ryvnf@riseup.net>
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-06-16 07:10:18 +00:00
Nils Dagsson Moskopp 7ccdbc5905
Document that music_record group, if it exists, is always 1 2021-06-15 23:22:45 +02:00
Nils Dagsson Moskopp 5f0710a486
Make jukebox accept and play old music records
With the introduction of the mcl_jukebox API, all music record items
were given new names. Old music record items were aliased, but never
worked with the jukebox. Apparently no one tested existing records.

By explicitly looking up the item name in minetest.registered_aliases,
the jukebox accepts old records, plays them, and gives out new records.
2021-06-15 17:46:03 +02:00
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 811b6d7058 Merge branch 'master' into backport_mcl_jukebox_api 2021-06-14 22:03:28 +00:00
AFCMS e858ea6233
Add backward compatibility for mcl_jukeboxes 2021-06-14 23:42:25 +02:00
AFCMS 20b7b6ff99
Add API documentation for mcl_jukeboxe 2021-06-14 23:40:24 +02:00
AFCMS b6fc888559
Add API for mcl_jukebox 2021-06-14 23:35:30 +02:00
Elias Åström ab389e9995 Merge pull request 'tools: set up luacheck' (#57) from e/Mineclonia:luacheck-setup into master
Reviewed-on: Mineclonia/Mineclonia#57
Reviewed-by: Elias Åström <ryvnf@riseup.net>
2021-06-14 21:31:23 +00:00
E e14265ff8e luacheck: remove luacheck generator, generate rules in .luacheckrc 2021-05-29 18:45:22 -04:00
E b1fbbfdd35 tools: remove inline scripting from make-luacheck-files
- the awk script was moved to its own file (deps-to-luacheck.awk) with
  minor changes, including added commentary, slightly more rigorous error
  checking, and using a different separator model to avoid a second
  stage to remove trailing commas
- SED_MODCONF2DEPS was moved to a containing function, and commented
- the awk command itself is now easier on the eyes
2021-05-29 18:45:22 -04:00
E 02a8496b5f luacheck: include a generated luacheck config 2021-05-29 18:45:22 -04:00
E 0c13293f43 tools: add a luacheckrc generator
tools/make-luacheck-files.sh will generate a .luacheckrc with the
following rules:
 - any rules set in the project header (.luacheck.head)
 - each mod is allowed to use a single global sharing its mod name
 - mod dependency information is parsed, and those mods' globals are
   permitted for read access
2021-05-29 18:45:22 -04:00
Elias Åström 4b4d40f158 Use register_on_mods_loaded in mcl_inventory
This removes the need to include _mcl_autogroup as a dependency for
mcl_inventory (which should be avoided) and decreases the likelihood
that the code used for populating item tables is executed before all
other mods are loaded.
2021-05-23 20:35:10 +02:00
Benjamin Schötz 9f61cfffaa mcl_bows: Cleanup translation files with script
Reordered translation-strings
Duplicates were removed
Gaps were detected for spanish and filled with machine-translation
2021-04-26 12:09:19 +02:00
Benjamin Schötz 7d44596c6d mcl_bows: Increase chance for critical from 20% to 25%
bow.lua Increase chance from 20% to 25%
bow.lua Adjust helptexts
arrow.lua Adjust helptexts
mcl_bows.(de,es,fr,ru).tr template.txt: Adjust helptexts
2021-04-26 11:11:18 +02:00
Benjamin Schötz 48091cecab mcl_enchanting: Add missing translation strings for enchantment table to template.txt and german, french, russian translations. 2021-04-24 09:06:56 +02:00
Benjamin Schötz adbb2f037a Adds string for '@1 was slain by @2' (deathmessage for mob with nametag) to template.txt and mcl_death_messages.de.tr 2021-04-20 22:19:35 +02:00
107 changed files with 10822 additions and 596 deletions

102
.luacheckrc Normal file
View File

@ -0,0 +1,102 @@
std = "min"
read_globals = {
"ItemStack",
"dump", "dump2",
"vector",
"VoxelArea",
"minetest",
"PseudoRandom",
"PerlinNoise",
"PcgRandom",
string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}},
math = {fields = {"hypot", "round"}},
}
-- A config option to allow r/w access to mods which contain
-- this one. It only avoids a couple warnings, and may not be
-- the behavior we want, so it's disabled by default.
local allow_parents=false
local lfs = require "lfs"
-- Seed the queue with the mods/ directory
local queue={ {"mods"} }
local function check(dir)
-- Get the string of the directory path
local sdir=table.concat(dir, "/")
-- Save the top-level directory name as a
-- fallback in case there's no mod.conf,
-- or no name= directive.
local name=dir[#dir]
-- Is there a mod.conf?
if lfs.attributes(sdir.."/mod.conf", "mode") == "file" then
local deps={}
for line in io.lines(sdir.."/mod.conf") do
-- Use name= if it's there
name=string.match(line, "name *= *([a-zA-Z0-9_]+)") or name
-- Get the dependency entries (if they're there)
local ents=string.match(line, "depends *=(.*)$")
if ents then
-- Split them in to the comma-separated names
for m in string.gmatch(ents, "([a-zA-Z0-9_]+),?") do
table.insert(deps, m)
end
end
end
local glb={ name }
if allow_parents then
for _, v in pairs(dir) do
-- Skip ALL-CAPS names since those tend
-- to be collections of mods instead of
-- mods themselves.
if not string.match(v, "^[A-Z]+$") then
table.insert(glb, v)
end
end
end
-- Tell Luacheck what the directory is allowed to do
files[sdir]={
globals = glb,
read_globals = deps,
}
elseif lfs.attributes(sdir.."/init.lua", "mode") == "file" then
-- No mod.conf, but there's an init.lua here.
local glb={ name }
if allow_parents then
for _, v in pairs(dir) do
-- Again, skip ALL-CAPS.
if not string.match(v, "^[A-Z]+$") then
table.insert(glb, v)
end
end
end
files[sdir]={ globals=glb }
end
-- Queue any child directories
for d in lfs.dir(sdir) do
-- Skip hidden directories and parent/current directories.
if lfs.attributes(sdir.."/"..d, "mode") == "directory" and not string.match(d, "^%.") then
-- Copy dir in to nd (New Dir)
local nd={}
for k, v in pairs(dir) do
nd[k]=v
end
nd[#nd+1]=d
table.insert(queue, nd)
end
end
end
while #queue > 0 do
-- Pop an entry and process it.
check(table.remove(queue, 1))
end

View File

@ -21,7 +21,7 @@ The basic digging time groups determine by which tools a node can be dug.
* `swordy=1`: Diggable by sword (any material), and this node is *not* a cobweb
* `swordy_cobweb=1`: Diggable by sword (any material), and this node is a cobweb
* `shearsy=1`: Diggable by shears, and this node is *not* wool
* `shearsy=wool=1`: Diggable by shears, and this node is wool
* `shearsy_wool=1`: Diggable by shears, and this node is wool
* `handy=1`: Breakable by hand and this node gives it useful drop when dug by hand. All nodes which are breakable by pickaxe, axe, shovel, sword or shears are also automatically breakable by hand, but not neccess
* `creative_breakable=1`: Block is breakable by hand in creative mode. This group is implied if the node belongs to any other digging group
@ -149,7 +149,7 @@ These groups are used mostly for informational purposes
* `trapdoor=2`: Open trapdoor
* `glass=1`: Glass (full cubes only)
* `rail=1`: Rail
* `music_record`: Music Disc (rating is track ID)
* `music_record=1`: Music Disc
* `tnt=1`: Block is TNT
* `boat=1`: Boat
* `minecart=1`: Minecart
@ -182,6 +182,10 @@ These groups are used mostly for informational purposes
* `redstone_torch=1`: Redstone Torch (lit)
* `redstone_torch=2`: Redstone Torch (unlit)
* `dirt=1`: Uncovered dirt
* `dirt=2`: Covered dirt (grass or mycelium or podzol on top)
* `dirt=3`: Coarse dirt
* `plant=1`: Plant or part of a plant
* `double_plant`: Part of a double-sized plant. 1 = lower part, 2 = upper part

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

29
menu/icon.png.do Normal file
View File

@ -0,0 +1,29 @@
#!/bin/sh
set -eu
SVG_FILE=${2%.png}.svg
# How crisp a Minetest menu icon appears is influenced by image height
# and width. Low resolutions lead to blurry edges, as Minetest scales
# menu icons up. High resolutions lead to jagged edges, as Minetest
# scales menu icons down. Height & width of 72 pixes seem to work.
#
# Though usually one would export directly to "${3}", Inkscape 1.0 had
# its command line options changed by people who apparently think that
# backwards compatibility is some kind of swear word: Whereas earlier
# Inkscape versions would export to a file called foo.png.tmp, newer
# behaviour is to ignore the user's wishes & write to foo.png.png
# unless one asks it to write to a filename with a .png extension,
# Inkscape 1.0 changes the filename extension to .png each time.
#
# As we do not know the extension of "${3}", we have to use the
# extension, then rename the resulting file to the proper name;
# only that way the export works with Inkscape 1.0 & earlier …
>&2 inkscape \
--file="${SVG_FILE}" \
--export-png="${3}".png \
--export-area-page \
--export-height 72 \
--export-width 72 \
mv "${3}".png "${3}"

8838
menu/icon.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 509 KiB

View File

@ -207,6 +207,10 @@ end
function mcl_autogroup.can_harvest(nodename, toolname)
local ndef = minetest.registered_nodes[nodename]
if not ndef then
return false
end
if minetest.get_item_group(nodename, "dig_immediate") >= 2 then
return true
end

View File

@ -0,0 +1,8 @@
# mcl_colors
Mod providing global table containing legacy minecraft colors to be used in mods.
## mcl_colors.*
Colors by upper name, in hex value.
## mcl_colors.background.*
Background colors by upper name, in hex value.

View File

@ -0,0 +1,36 @@
mcl_colors = {
BLACK = "#000000",
DARK_BLUE = "#0000AA",
DARK_GREEN = "#00AA00",
DARK_AQUA = "#00AAAA",
DARK_RED = "#AA0000",
DARK_PURPLE = "#AA00AA",
GOLD = "#FFAA00",
GRAY = "#AAAAAA",
DARK_GRAY = "#555555",
BLUE = "#5555FF",
GREEN = "#55FF55",
AQUA = "#55FFFF",
RED = "#FF5555",
LIGHT_PURPLE = "#FF55FF",
YELLOW = "#FFFF55",
WHITE = "#FFFFFF",
background = {
BLACK = "#000000",
DARK_BLUE = "#00002A",
DARK_GREEN = "#002A00",
DARK_AQUA = "#002A2A",
DARK_RED = "#2A0000",
DARK_PURPLE = "#2A002A",
GOLD = "#2A2A00",
GRAY = "#2A2A2A",
DARK_GRAY = "#151515",
BLUE = "#15153F",
GREEN = "#153F15",
AQUA = "#153F3F",
RED = "#3F1515",
LIGHT_PURPLE = "#3F153F",
YELLOW = "#3F3F15",
WHITE = "#373501",
}
}

View File

@ -0,0 +1,3 @@
name = mcl_colors
author = Fleckenstein
description = The HTML sequences for the minecraft colors

View File

@ -0,0 +1 @@
name = walkover

View File

@ -243,7 +243,7 @@ function boat.on_step(self, dtime, moveresult)
else
local ctrl = self._passenger:get_player_control()
if ctrl and ctrl.sneak then
detach_player(self._passenger, true)
detach_object(self._passenger, true)
self._passenger = nil
end
end
@ -260,7 +260,7 @@ function boat.on_step(self, dtime, moveresult)
return
end
local yaw = self.object:get_yaw()
if ctrl.up then
if ctrl and ctrl.up then
-- Forwards
self._v = self._v + 0.1 * v_factor
@ -269,7 +269,7 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, paddling_speed, 0, true)
self._animation = 1
end
elseif ctrl.down then
elseif ctrl and ctrl.down then
-- Backwards
self._v = self._v - 0.1 * v_factor

View File

@ -155,6 +155,16 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
}) + 1
end
local already_burning = mcl_burning.is_burning(obj)
mcl_burning.set(obj, "float", "burn_time", burn_time)
mcl_burning.set(obj, "string", "reason", reason)
if already_burning then
return
end
local hud_id
if obj:is_player() then
hud_id = mcl_burning.get(obj, "int", "hud_id")
@ -168,8 +178,7 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
}) + 1
end
end
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)
@ -285,7 +294,7 @@ function mcl_burning.fire_entity_step(self, dtime)
end
local animation_timer = self.animation_timer + dtime
if animation_timer >= 0.015 then
if animation_timer >= ( 1 / mcl_burning.animation_fps ) then
animation_timer = 0
local animation_frame = self.animation_frame + 1
if animation_frame > mcl_burning.animation_frames - 1 then
@ -296,3 +305,48 @@ function mcl_burning.fire_entity_step(self, dtime)
end
self.animation_timer = animation_timer
end
minetest.register_chatcommand("burn", {
params = S("<playername> <duration> <reason>"),
description = S("Sets a player on fire for the given amount of seconds with the given reason."),
privs = { debug = true },
func = function(name, params)
local playername, duration, reason = params:match("^(.+) (.+) (.+)$")
if not (playername and duration and reason) then
return false, S("Error: Parameter missing.")
end
local player = minetest.get_player_by_name(playername)
if not player then
return false, S(
"Error: Player “@1” not found.",
playername
)
end
local duration_number = tonumber(duration)
-- Lua numbers are truthy
-- NaN is not equal to NaN
if not duration_number or (duration_number ~= duration_number) then
return false, S(
"Error: Duration “@1” is not a number.",
duration
)
end
if duration_number < 0 then
return false, S(
"Error: Duration “@1” is negative.",
duration
)
end
mcl_burning.set_on_fire(
player,
duration_number,
reason
)
return true, S(
"Set @1 on fire for @2s for the following reason: @3",
playername,
duration,
reason
)
end,
})

View File

@ -2,7 +2,8 @@ local S = minetest.get_translator("mcl_burning")
local modpath = minetest.get_modpath("mcl_burning")
mcl_burning = {
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8,
animation_fps = tonumber(minetest.settings:get("fire_animation_fps")) or 30
}
dofile(modpath .. "/api.lua")

View File

@ -1,3 +1,4 @@
local S = minetest.get_translator("mcl_item_entity")
--basic settings
local item_drop_settings = {} --settings table
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
@ -448,7 +449,7 @@ minetest.register_entity(":__builtin:item", {
end,
get_staticdata = function(self)
return minetest.serialize({
local data = minetest.serialize({
itemstring = self.itemstring,
always_collect = self.always_collect,
age = self.age,
@ -456,6 +457,39 @@ minetest.register_entity(":__builtin:item", {
_flowing = self._flowing,
_removed = self._removed,
})
-- sfan5 guessed that the biggest serializable item
-- entity would have a size of 65530 bytes. This has
-- been experimentally verified to be still too large.
--
-- anon5 has calculated that the biggest serializable
-- item entity has a size of exactly 65487 bytes:
--
-- 1. serializeString16 can handle max. 65535 bytes.
-- 2. The following engine metadata is always saved:
-- • 1 byte (version)
-- • 2 byte (length prefix)
-- • 14 byte “__builtin:item”
-- • 4 byte (length prefix)
-- • 2 byte (health)
-- • 3 × 4 byte = 12 byte (position)
-- • 4 byte (yaw)
-- • 1 byte (version 2)
-- • 2 × 4 byte = 8 byte (pitch and roll)
-- 3. This leaves 65487 bytes for the serialization.
if #data > 65487 then -- would crash the engine
local stack = ItemStack(self.itemstring)
stack:get_meta():from_table(nil)
self.itemstring = stack:to_string()
minetest.log(
"warning",
"Overlong item entity metadata removed: “" ..
self.itemstring ..
"” had serialized length of " ..
#data
)
return self:get_staticdata()
end
return data
end,
on_activate = function(self, staticdata, dtime_s)
@ -748,3 +782,29 @@ minetest.register_entity(":__builtin:item", {
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
})
-- The “getwrittenbook” command was added as a debug aid. It can help
-- reproducing situations in which items with lots of metadata trigger
-- issues like heavy lag or server crashes. Do not remove this command
-- unless another easy way of getting items with overlong meta exists!
--
-- “/getwrittenbook 65323” creates an item that creates the largest
-- possible serializable written book item entity when dropped.
--
-- “/getwrittenbook 65324” creates an item that creates the smallest
-- possible non-serializable written book item entity when dropped.
minetest.register_chatcommand("getwrittenbook", {
params = S("<Count>"),
description = S("Get a written book with a configurable amount of characters."),
privs = {debug=true},
func = function(name, param)
local count = tonumber(param)
local itemstack = ItemStack("mcl_books:written_book")
local meta = itemstack:get_meta()
meta:set_string("description", "")
meta:set_string("text", string.rep("x", count))
local player = minetest.get_player_by_name(name)
local inv = player:get_inventory()
inv:add_item("main", itemstack)
end
})

View File

@ -14,6 +14,8 @@ local DEFAULT_FALL_SPEED = -10
local FLOP_HEIGHT = 5.0
local FLOP_HOR_SPEED = 1.5
local LIGHT_SUN = minetest.LIGHT_MAX + 1
local MOB_CAP = {}
MOB_CAP.hostile = 70
MOB_CAP.passive = 10
@ -1057,7 +1059,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 (minetest.get_node_light(pos) or 0) >= minetest.LIGHT_MAX and dim == "overworld" then
if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (minetest.get_node_light(pos) or 0) == LIGHT_SUN and dim == "overworld" then
if self.ignited_by_sunlight then
mcl_burning.set_on_fire(self.object, 10)
else

View File

@ -123,6 +123,10 @@ mobs:register_mob("mobs_mc:snowman", {
local pos = self.object:get_pos()
minetest.sound_play("mcl_tools_shears_cut", {pos = pos}, true)
if minetest.registered_items["mcl_farming:pumpkin_face"] then
minetest.add_item({x=pos.x, y=pos.y+1.4, z=pos.z}, "mcl_farming:pumpkin_face")
end
-- Wear out
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:add_wear(mobs_mc.misc.shears_wear)

View File

@ -74,7 +74,7 @@ local professions = {
},
{
{ { "mcl_farming:pumpkin_face", 8, 13 }, E1 },
{ { "mcl_farming:pumpkin", 8, 13 }, E1 },
{ E1, { "mcl_farming:pumpkin_pie", 2, 3} },
},

View File

@ -413,6 +413,7 @@ function hb.hide_hudbar(player, identifier)
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == true then return true end
if hb.settings.bar_type == "progress_bar" then
if hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
@ -431,6 +432,7 @@ function hb.unhide_hudbar(player, identifier)
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == false then return true end
local value = hudtable.hudstate[name].value
local max = hudtable.hudstate[name].max
if hb.settings.bar_type == "progress_bar" then

View File

@ -3,12 +3,105 @@ local N = function(s) return s end
local function get_tool_name(item)
local name = item:get_meta():get_string("name")
if name ~= "" then
return name
end
if name == "" then
local def = item:get_definition()
return def._tt_original_description or def.description
name=def._tt_original_description or def.description
end
local sanitized_name, substitution_count = name:gsub("[\r\n]"," ")
return sanitized_name
end
local test_tool_1a = {
get_meta = function()
return {
get_string = function()
return "foo 1a"
end
}
end
}
assert( get_tool_name(test_tool_1a) == "foo 1a" )
local test_tool_1b = {
get_meta = function()
return {
get_string = function()
return "bar\rbaz\n1b"
end
}
end
}
assert( get_tool_name(test_tool_1b) == "bar baz 1b" )
local test_tool_2a = {
get_definition = function()
return {
_tt_original_description = "foo 2a"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_2a) == "foo 2a" )
local test_tool_2b = {
get_definition = function()
return {
_tt_original_description = "bar\rbaz\n2b"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_2b) == "bar baz 2b" )
local test_tool_3a = {
get_definition = function()
return {
description = "foo 3a"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_3a) == "foo 3a" )
local test_tool_3b = {
get_definition = function()
return {
description = "bar\rbaz\n3b"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_3b) == "bar baz 3b" )
mcl_death_messages = {}

View File

@ -10,6 +10,7 @@
@1 drowned.=@1 ertrank.
@1 ran out of oxygen.=@1 ging die Luft aus.
@1 was killed by @2.=@1 wurde von @2 getötet.
@1 was slain by @2.=@1 wurde von @2 getötet.
@1 was killed.=@1 wurde getötet.
@1 was killed by a mob.=@1 wurde von einem Mob getötet.
@1 was burned to death by a blaze's fireball.=@1 wurde von einem Feuerball einer Lohe zu Tode verbrannt.

View File

@ -10,6 +10,7 @@
@1 drowned.=
@1 ran out of oxygen.=
@1 was killed by @2.=
@1 was slain by @2.=
@1 was killed.=
@1 was killed by a mob.=
@1 was burned to death by a blaze's fireball.=

View File

@ -0,0 +1 @@
name = mcl_experience

View File

@ -1 +1,2 @@
name = mcl_formspec
description = Helper mod to simplify creation of formspecs a little bit

View File

@ -28,10 +28,9 @@ local function replace_enchanted_books(tbl)
end
end
--[[ Populate all the item tables. We only do this once. Note this mod must be
loaded after _mcl_autogroup for this to work, because it required certain
groups to be set. ]]
do
--[[ Populate all the item tables. We only do this once. Note this code must be
executed after loading all the other mods in order to work. ]]
minetest.register_on_mods_loaded(function()
for name,def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then
local is_redstone = function(def)
@ -109,7 +108,7 @@ do
table.sort(to_sort)
replace_enchanted_books(to_sort)
end
end
end)
local function filter_item(name, description, lang, filter)
local desc
@ -118,7 +117,7 @@ local function filter_item(name, description, lang, filter)
else
desc = string.lower(minetest.get_translated_string(lang, description))
end
return string.find(name, filter) or string.find(desc, filter)
return string.find(name, filter, nil, true) or string.find(desc, filter, nil, true)
end
local function set_inv_search(filter, player)

View File

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

View File

@ -1,4 +1,8 @@
mcl_tmp_message = {}
mcl_tmp_message = {
hud_hide_timeout = tonumber(
minetest.settings:get("mcl_tmp_message_hud_hide_timeout")
) or 10
}
local huds = {}
local hud_hide_timeouts = {}
@ -6,7 +10,7 @@ local hud_hide_timeouts = {}
function mcl_tmp_message.message(player, message)
local name = player:get_player_name()
player:hud_change(huds[name], "text", message)
hud_hide_timeouts[name] = 3
hud_hide_timeouts[name] = mcl_tmp_message.hud_hide_timeout
end
minetest.register_on_joinplayer(function(player)

View File

@ -0,0 +1 @@
name = mcl_tmp_message

View File

@ -43,14 +43,20 @@ end
local comparator_activate = function(pos, node)
local def = minetest.registered_nodes[node.name]
minetest.swap_node(pos, { name = def.comparator_onstate, param2 = node.param2 })
local onstate = def.comparator_onstate
if onstate then
minetest.swap_node(pos, { name = onstate, param2 = node.param2 })
end
minetest.after(0.1, comparator_turnon , {pos = pos, node = node})
end
local comparator_deactivate = function(pos, node)
local def = minetest.registered_nodes[node.name]
minetest.swap_node(pos, { name = def.comparator_offstate, param2 = node.param2 })
local offstate = def.comparator_offstate
if offstate then
minetest.swap_node(pos, { name = offstate, param2 = node.param2 })
end
minetest.after(0.1, comparator_turnoff, {pos = pos, node = node})
end

View File

@ -129,6 +129,19 @@ local dispenserdef = {
local stack_id = stacks[r].stackpos
local stackdef = stack:get_definition()
local iname = stack:get_name()
if not minetest.registered_items[iname] then
minetest.log(
"warning",
"Trying to dispense unknown item " ..
"" .. iname .. "" ..
"near (" ..
pos.x .. ", " ..
pos.y .. ", " ..
pos.z ..
")"
)
return
end
local igroups = minetest.registered_items[iname].groups
--[===[ Dispense item ]===]

View File

@ -149,8 +149,8 @@ armor.set_player_armor = function(self, player)
if level then
local texture = def.texture or item:gsub("%:", "_")
local enchanted_addition = (mcl_enchanting.is_enchanted(item) and mcl_enchanting.overlay or "")
table.insert(textures, "("..texture..".png"..enchanted_addition..")")
preview = "(player.png^[opacity:0^"..texture.."_preview.png"..enchanted_addition..")"..(preview and "^"..preview or "")
table.insert(textures, texture..".png"..enchanted_addition)
preview = "player.png^[opacity:0^"..texture.."_preview.png"..enchanted_addition..""..(preview and "^"..preview or "")
armor_level = armor_level + level
items = items + 1
mcl_armor_points = mcl_armor_points + (def.groups["mcl_armor_points"] or 0)

View File

@ -387,13 +387,15 @@ for colorid, colortab in pairs(mcl_banners.colors) do
-- redraw the pattern textures as low-resolution pixel
-- art and use that instead.
local layer = "(([combine:20x40:-2,-2="..pattern.."^[resize:16x24^[colorize:"..color..":"..layer_ratio.."))"
local layer = "([combine:20x40:-2,-2=" .. pattern .. "^[resize:16x24^[colorize:" .. color .. ":" .. layer_ratio .. ")"
local mask = "([combine:20x40:-2,-2=" .. pattern .. "^[resize:16x24" .. ")"
function escape(text)
return text:gsub("%^", "\\%^"):gsub(":", "\\:") -- :gsub("%(", "\\%("):gsub("%)", "\\%)")
end
finished_banner = "[combine:32x32:0,0=" .. escape(base) .. ":8,4=" .. escape(layer)
local layer_masked = layer .. "^[mask:" .. escape(mask)
finished_banner = "[combine:32x32:0,0=" .. escape(base) .. ":8,4=" .. escape(layer_masked)
end
inv = finished_banner

View File

@ -8,9 +8,6 @@ local N = function(s) return s end
-- Maximum number of layers which can be put on a banner by crafting.
local max_layers_crafting = 12
-- Maximum number of layers when banner includes a gradient (workaround, see below).
local max_layers_gradient = 3
-- Max. number lines in the descriptions for the banner layers.
-- This is done to avoid huge tooltips.
local max_layer_lines = 6
@ -398,16 +395,6 @@ local banner_pattern_craft = function(itemstack, player, old_craft_grid, craft_i
if #layers >= max_layers_crafting then
return ItemStack("")
end
-- Lower layer limit when banner includes any gradient.
-- Workaround to circumvent Minetest bug (https://github.com/minetest/minetest/issues/6210)
-- TODO: Remove this restriction when bug #6210 is fixed.
if #layers >= max_layers_gradient then
for l=1, #layers do
if layers[l].pattern == "gradient" or layers[l].pattern == "gradient_up" then
return ItemStack("")
end
end
end
local matching_pattern
local max_i = player:get_inventory():get_size("craft")

View File

@ -81,7 +81,7 @@ function mcl_beds.register_bed(name, def)
paramtype2 = "facedir",
is_ground_content = false,
stack_max = 1,
groups = {handy=1, flammable = 3, bed = 1, dig_by_piston=1, bouncy=66, fall_damage_add_percent=-50, deco_block = 1, flammable=-1},
groups = {handy=1, bed = 1, dig_by_piston=1, bouncy=66, fall_damage_add_percent=-50, deco_block = 1, flammable=-1},
_mcl_hardness = 0.2,
_mcl_blast_resistance = 1,
sounds = def.sounds or default_sounds,
@ -204,7 +204,7 @@ function mcl_beds.register_bed(name, def)
paramtype2 = "facedir",
is_ground_content = false,
-- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks!
groups = {handy = 1, flammable = 3, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1},
groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1},
_mcl_hardness = 0.2,
_mcl_blast_resistance = 1,
sounds = def.sounds or default_sounds,

View File

@ -22,7 +22,7 @@ minetest.register_craftitem("mcl_bows:arrow", {
description = S("Arrow"),
_tt_help = S("Ammunition").."\n"..S("Damage from bow: 1-10").."\n"..S("Damage from dispenser: 3"),
_doc_items_longdesc = S("Arrows are ammunition for bows and dispensers.").."\n"..
S("An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.").."\n"..
S("An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.").."\n"..
S("Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons."),
_doc_items_usagehelp = S("To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it."),
inventory_image = "mcl_bows_arrow_inv.png",
@ -136,6 +136,8 @@ end
ARROW_ENTITY.on_step = function(self, dtime)
mcl_burning.tick(self.object, dtime)
self._time_in_air = self._time_in_air + dtime
local pos = self.object:get_pos()
local dpos = table.copy(pos) -- digital pos
dpos = vector.round(dpos)
@ -201,10 +203,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 ~= self._shooter and obj:is_player() then
if obj:is_player() then
ok = true
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
end
end
@ -226,7 +228,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
local obj = closest_object
local is_player = obj:is_player()
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 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
-- Check if there is no solid node between arrow and object
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)
@ -263,7 +265,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
if is_player then
if self._shooter and self._shooter:is_player() then
if self._shooter and self._shooter:is_player() and obj ~= self._shooter 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
@ -411,6 +413,7 @@ end
ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s)
local data = minetest.deserialize(staticdata)
self._time_in_air = dtime_s
if data then
self._stuck = data.stuck
if data.stuck then

View File

@ -129,7 +129,7 @@ minetest.register_tool("mcl_bows:bow", {
description = S("Bow"),
_tt_help = S("Launches arrows"),
_doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes.").."\n"..
S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."),
S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead."),
_doc_items_usagehelp = S("To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot."),
_doc_items_durability = BOW_DURABILITY,
inventory_image = "mcl_bows_bow.png",
@ -256,9 +256,9 @@ controls.register_on_release(function(player, key, time)
local is_critical = false
if charge >= BOW_CHARGE_TIME_FULL then
speed = BOW_MAX_SPEED
local r = math.random(1,5)
local r = math.random(1,4)
if r == 1 then
-- 20% chance for critical hit
-- 25% chance for critical hit
damage = 10
is_critical = true
else

View File

@ -1,15 +1,14 @@
# textdomain: mcl_bows
Arrow=Pfeil
Arrows are ammunition for bows and dispensers.=Pfeile sind Munition für Bögen und Werfer.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Ein Bogen von einem Pfeil richtet regulär 1-9 Schaden an. Mit voller Zugkraft gibt es eine 20%-ige Chance auf einen kritischen Treffer mit 10 Schaden. Ein Pfeil aus einem Werfer richtet immer 3 Schaden an.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Pfeile können in festen Blöcken stecken bleiben und wieder aufgesammelt werden. Sie können auf Holzknöpfe drücken.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Um Pfeile als Munition für dne Bogen zu benutzen, platzieren Sie sie einfach irgendwo im Inventar, sie werden automatisch benutzt. Um Pfeile als Munition für Werfer zu benutzen, platzieren Sie sie ins Inventar eines Werferr. Um einen steckengebliebenen Pfeil aufzusammeln, gehen Sie einfach zu ihm hin.
Bow=Bogen
Bows are ranged weapons to shoot arrows at your foes.=Bogen sind Fernwaffen, um Pfeile auf Ihre Feinde zu schießen.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=Die Geschwindigkeit und der Schaden des Bogens erhöht sich, je länger sie den Bogen spannen. Der reguläre Schaden des Pfeiles ist zwischen 1 und 9. Ist der Bogen voll gespannt, gibt es eine 20%-ig Change für einen kritischen Treffer, der 10 Schaden anrichtet.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Um den Bogen zu benutzen, muss sich im Inventar mindestens ein Pfeil befinden (außer im Kreativmodus). Halten sie die rechte Maustaste gedrückt zum Spannen, lassen Sie sie los zum Schießen.
Bow=Bogen
Ammunition=Munition
Damage from bow: 1-10=Schaden vom Bogen: 1-10
Damage from dispenser: 3=Schaden vom Werfer: 3
Arrows are ammunition for bows and dispensers.=Pfeile sind Munition für Bögen und Werfer.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Ein Bogen von einem Pfeil richtet regulär 1-9 Schaden an. Mit voller Zugkraft gibt es eine 25%-ige Chance auf einen kritischen Treffer mit 10 Schaden. Ein Pfeil aus einem Werfer richtet immer 3 Schaden an.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Pfeile können in festen Blöcken stecken bleiben und wieder aufgesammelt werden. Sie können auf Holzknöpfe drücken.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Um Pfeile als Munition für dne Bogen zu benutzen, platzieren Sie sie einfach irgendwo im Inventar, sie werden automatisch benutzt. Um Pfeile als Munition für Werfer zu benutzen, platzieren Sie sie ins Inventar eines Werferr. Um einen steckengebliebenen Pfeil aufzusammeln, gehen Sie einfach zu ihm hin.
Bow=Bogen
Launches arrows=Verschießt Pfeile
Bows are ranged weapons to shoot arrows at your foes.=Bogen sind Fernwaffen, um Pfeile auf Ihre Feinde zu schießen.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead.=Die Geschwindigkeit und der Schaden des Bogens erhöht sich, je länger sie den Bogen spannen. Der reguläre Schaden des Pfeiles ist zwischen 1 und 9. Ist der Bogen voll gespannt, gibt es eine 25%-ig Change für einen kritischen Treffer, der 10 Schaden anrichtet.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Um den Bogen zu benutzen, muss sich im Inventar mindestens ein Pfeil befinden (außer im Kreativmodus). Halten sie die rechte Maustaste gedrückt zum Spannen, lassen Sie sie los zum Schießen.

View File

@ -1,11 +1,14 @@
# textdomain: mcl_bows
Arrow=Flecha
Ammunition=Munición
Damage from bow: 1-10=Daño del arco: 1-10
Damage from dispenser: 3=Daño del dispensador: 3
Arrows are ammunition for bows and dispensers.=Las flechas son municiones para arcos y dispensadores.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Una flecha disparada desde un arco tiene un daño regular de 1-9. A plena carga, hay un 20% de posibilidades de que un golpe crítico inflija 10 daños en su lugar. Una flecha disparada desde un dispensador siempre causa 3 de daño.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Una flecha disparada desde un arco tiene un daño regular de 1-9. A plena carga, hay un 25% de posibilidades de que un golpe crítico inflija 10 daños en su lugar. Una flecha disparada desde un dispensador siempre causa 3 de daño.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Las flechas pueden atascarse en bloques sólidos y pueden recuperarse nuevamente. También son capaces de presionar botones de madera.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Para usar flechas como municiones para un arco, simplemente colóquelas en cualquier parte de su inventario, se usarán automáticamente. Para usar flechas como municiones para un dispensador, colóquelas en el inventario del dispensador. Para recuperar una flecha que se pega en un bloque, simplemente camine cerca de ella.
Bow=Arco
Launches arrows=Dispara flechas
Bows are ranged weapons to shoot arrows at your foes.=Los arcos son armas a distancia para disparar flechas a tus enemigos.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=La velocidad y el daño de la flecha aumentan cuanto más tiempo tenses. El daño regular de la flecha está entre 1 y 9. A plena carga, también hay un 20% de un golpe crítico, que en vez de eso causa 10 de daño.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead.=La velocidad y el daño de la flecha aumentan cuanto más tiempo tenses. El daño regular de la flecha está entre 1 y 9. A plena carga, también hay un 25% de un golpe crítico, que en vez de eso causa 10 de daño.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Para usar el arco, primero debes de tener al menos una flecha en cualquier parte de su inventario (a menos que esté en modo creativo). Mantenga presionado el botón derecho del mouse para tensar, suelte para disparar.
Bow=Arco

View File

@ -1,15 +1,14 @@
# textdomain: mcl_bows
Arrow=Flèche
Arrows are ammunition for bows and dispensers.=Les flèches sont des munitions pour les arcs et les distributeurs.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Une flèche tirée d'un arc a des dégâts réguliers de 1 à 9. À pleine charge, il y a 20% de chances qu'un coup critique inflige 10 dégâts à la place. Une flèche tirée depuis un distributeur inflige toujours 3 dégâts.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Les flèches peuvent se coincer sur des blocs solides et peuvent être récupérées à nouveau. Ils sont également capables de pousser des boutons en bois.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Pour utiliser des flèches comme munitions pour un arc, il suffit de les placer n'importe où dans votre inventaire, elles seront utilisées automatiquement. Pour utiliser des flèches comme munitions pour un distributeur, placez-les dans l'inventaire du distributeur. Pour récupérer une flèche qui colle dans un bloc, il vous suffit de vous en approcher.
Bow=Arc
Bows are ranged weapons to shoot arrows at your foes.=Les arcs sont des armes à distance pour tirer des flèches sur vos ennemis.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=La vitesse et les dégâts de la flèche augmentent plus vous chargez. Les dégâts réguliers de la flèche sont compris entre 1 et 9. À pleine charge, il y a également 20% d'un coup critique, infligeant 10 dégâts à la place.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Pour utiliser l'arc, vous devez d'abord avoir au moins une flèche n'importe où dans votre inventaire (sauf en mode créatif). Maintenez enfoncé le bouton droit de la souris pour charger, relâchez pour tirer.
Bow=Arc
Ammunition=Munition
Damage from bow: 1-10=Dégâts de l'arc: 1-10
Damage from dispenser: 3=Dégâts du distributeur: 3
Arrows are ammunition for bows and dispensers.=Les flèches sont des munitions pour les arcs et les distributeurs.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Une flèche tirée d'un arc a des dégâts réguliers de 1 à 9. À pleine charge, il y a 25% de chances qu'un coup critique inflige 10 dégâts à la place. Une flèche tirée depuis un distributeur inflige toujours 3 dégâts.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Les flèches peuvent se coincer sur des blocs solides et peuvent être récupérées à nouveau. Ils sont également capables de pousser des boutons en bois.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Pour utiliser des flèches comme munitions pour un arc, il suffit de les placer n'importe où dans votre inventaire, elles seront utilisées automatiquement. Pour utiliser des flèches comme munitions pour un distributeur, placez-les dans l'inventaire du distributeur. Pour récupérer une flèche qui colle dans un bloc, il vous suffit de vous en approcher.
Bow=Arc
Launches arrows=Lance des flèches
Bows are ranged weapons to shoot arrows at your foes.=Les arcs sont des armes à distance pour tirer des flèches sur vos ennemis.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead.=La vitesse et les dégâts de la flèche augmentent plus vous chargez. Les dégâts réguliers de la flèche sont compris entre 1 et 9. À pleine charge, il y a également 25% d'un coup critique, infligeant 10 dégâts à la place.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Pour utiliser l'arc, vous devez d'abord avoir au moins une flèche n'importe où dans votre inventaire (sauf en mode créatif). Maintenez enfoncé le bouton droit de la souris pour charger, relâchez pour tirer.

View File

@ -1,15 +1,14 @@
# textdomain: mcl_bows
Arrow=Стрела
Arrows are ammunition for bows and dispensers.=Стрелы - это боеприпасы для луков и диспенсеров.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Стрела, выпущенная из лука, обычно наносит урон 1-9. При полном натяжении есть 20-процентный шанс критического удара с уроном 10. Стрела из диспенсера всегда наносит урон уровня 3.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Стрелы могут застревать в твёрдых блоках, их можно подбирать для повторного использования. Они также способны нажимать деревянные кнопки.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Чтобы использовать стрелы в качестве боеприпасов для лука, просто положите их в любую ячейку вашего инвентаря, и они будут использоваться автоматически. Чтобы использовать стрелы в качестве боеприпасов для диспенсера, поместите их в инвентарь диспенсера. Чтобы взять стрелу, застрявшую в блоке, просто пройдите рядом с ней.
Bow=Лук
Bows are ranged weapons to shoot arrows at your foes.=Лук - это оружие дальнего боя, чтобы стрелять стрелами по вашим врагам.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=Скорость и урон стрелы увеличиваются, пока вы её натягиваете. Обычный урон стрелы находится между 1 и 9. При полном натяжении есть 20-процентный шанс критического удара с уроном 10.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Чтобы использовать лук, нужно иметь хотя бы одну стрелу в вашем инвентаре (за исключением творческого режима). Удерживайте правую клавишу мыши, чтобы натягивать тетиву, затем отпустите, чтобы выстрелить.
Bow=Лук
Ammunition=Боеприпасы
Damage from bow: 1-10=Урон от лука: 1-10
Damage from dispenser: 3=Урон от диспенсера: 3
Arrows are ammunition for bows and dispensers.=Стрелы - это боеприпасы для луков и диспенсеров.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=Стрела, выпущенная из лука, обычно наносит урон 1-9. При полном натяжении есть 25-процентный шанс критического удара с уроном 10. Стрела из диспенсера всегда наносит урон уровня 3.
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=Стрелы могут застревать в твёрдых блоках, их можно подбирать для повторного использования. Они также способны нажимать деревянные кнопки.
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=Чтобы использовать стрелы в качестве боеприпасов для лука, просто положите их в любую ячейку вашего инвентаря, и они будут использоваться автоматически. Чтобы использовать стрелы в качестве боеприпасов для диспенсера, поместите их в инвентарь диспенсера. Чтобы взять стрелу, застрявшую в блоке, просто пройдите рядом с ней.
Bow=Лук
Launches arrows=Пускает стрелы
Bows are ranged weapons to shoot arrows at your foes.=Лук - это оружие дальнего боя, чтобы стрелять стрелами по вашим врагам.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead.=Скорость и урон стрелы увеличиваются, пока вы её натягиваете. Обычный урон стрелы находится между 1 и 9. При полном натяжении есть 25-процентный шанс критического удара с уроном 10.
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=Чтобы использовать лук, нужно иметь хотя бы одну стрелу в вашем инвентаре (за исключением творческого режима). Удерживайте правую клавишу мыши, чтобы натягивать тетиву, затем отпустите, чтобы выстрелить.

View File

@ -1,15 +1,14 @@
# textdomain: mcl_bows
Arrow=
Arrows are ammunition for bows and dispensers.=
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=
Bow=
Bows are ranged weapons to shoot arrows at your foes.=
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.=
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=
Bow=
Ammunition=
Damage from bow: 1-10=
Damage from dispenser: 3=
Arrows are ammunition for bows and dispensers.=
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 25% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.=
Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons.=
To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory. To retrieve an arrow that sticks in a block, simply walk close to it.=
Bow=
Launches arrows=
Bows are ranged weapons to shoot arrows at your foes.=
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 25% of a critical hit, dealing 10 damage instead.=
To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.=

View File

@ -1,6 +1,41 @@
local S = minetest.get_translator("mcl_chests")
local mod_doc = minetest.get_modpath("doc")
-- Christmas chest setup
local it_is_christmas = false
local date = os.date("*t")
if (
date.month == 12 and (
date.day == 24 or
date.day == 25 or
date.day == 26
)
) then
it_is_christmas = true
end
local tiles_chest_normal_small = {"mcl_chests_normal.png"}
local tiles_chest_normal_double = {"mcl_chests_normal_double.png"}
if it_is_christmas then
tiles_chest_normal_small = {"mcl_chests_normal_present.png^mcl_chests_noise.png"}
tiles_chest_normal_double = {"mcl_chests_normal_double_present.png^mcl_chests_noise_double.png"}
end
local tiles_chest_trapped_small = {"mcl_chests_trapped.png"}
local tiles_chest_trapped_double = {"mcl_chests_trapped_double.png"}
if it_is_christmas then
tiles_chest_trapped_small = {"mcl_chests_trapped_present.png^mcl_chests_noise.png"}
tiles_chest_trapped_double = {"mcl_chests_trapped_double_present.png^mcl_chests_noise_double.png"}
end
local tiles_chest_ender_small = {"mcl_chests_ender.png"}
if it_is_christmas then
tiles_chest_ender_small = {"mcl_chests_ender_present.png^mcl_chests_noise.png"}
end
-- Chest Entity
local animate_chests = (minetest.settings:get_bool("animated_chests") ~= false)
local entity_animations = {
@ -152,7 +187,10 @@ if minetest.get_modpath("screwdriver") then
local nodename = node.name
local nodedef = minetest.registered_nodes[nodename]
local dir = minetest.facedir_to_dir(new_param2)
if animate_chests then
find_or_create_entity(pos, nodename, nodedef._chest_entity_textures, new_param2, false, nodedef._chest_entity_sound, nodedef._chest_entity_mesh, nodedef._chest_entity_animation_type, dir):set_yaw(dir)
end
else
return false
end
@ -181,6 +219,10 @@ local player_chest_open = function(player, pos, node_name, textures, param2, dou
local dir = minetest.facedir_to_dir(param2)
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)
else
minetest.sound_play(sound .. "_open", {
pos = pos,
})
end
end
@ -212,11 +254,14 @@ local chest_update_after_close = function(pos)
if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
end
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
elseif node.name == "mcl_chests:trapped_chest_on_left" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -228,7 +273,7 @@ local chest_update_after_close = function(pos)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
end
end
@ -242,6 +287,10 @@ local player_chest_close = function(player)
end
if animate_chests then
find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2, open_chest.double, open_chest.sound, open_chest.mesh, open_chest.shulker and "shulker" or "chest"):close(name)
else
minetest.sound_play(open_chest.sound .. "_close", {
pos = open_chest.pos,
})
end
chest_update_after_close(open_chest.pos)
@ -380,12 +429,21 @@ minetest.register_node(small_name, {
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
_doc_items_hidden = hidden,
drawtype = "nodebox",
node_box = {
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_chest.obj" or nil,
node_box = animate_chests and {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
} or nil,
collision_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
tiles = {"mcl_chests_blank.png"},
selection_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
tiles = animate_chests and {"mcl_chests_blank.png"} or small_textures,
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
_chest_entity_textures = small_textures,
_chest_entity_sound = "default_chest",
@ -435,8 +493,11 @@ minetest.register_node(small_name, {
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 })
else
minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 })
if animate_chests then
create_entity(pos, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
end
end
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
@ -823,8 +884,8 @@ register_chest("chest",
chestusage,
S("27 inventory slots") .. "\n" .. S("Can be combined to a large chest"),
{
small = {"mcl_chests_normal.png"},
double = {"mcl_chests_normal_double.png"},
small = tiles_chest_normal_small,
double = tiles_chest_normal_double,
inv = {"default_chest_top.png", "mcl_chests_chest_bottom.png",
"mcl_chests_chest_right.png", "mcl_chests_chest_left.png",
"mcl_chests_chest_back.png", "default_chest_front.png"},
@ -839,8 +900,8 @@ register_chest("chest",
)
local traptiles = {
small = {"mcl_chests_trapped.png"},
double = {"mcl_chests_trapped_double.png"},
small = tiles_chest_trapped_small,
double = tiles_chest_trapped_double,
inv = {"mcl_chests_chest_trapped_top.png", "mcl_chests_chest_trapped_bottom.png",
"mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png",
"mcl_chests_chest_trapped_back.png", "mcl_chests_chest_trapped_front.png"},
@ -865,7 +926,9 @@ register_chest("trapped_chest",
}},
function(pos, node, clicker)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_small")
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_small")
end
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
end,
function(pos, node, clicker)
@ -873,7 +936,7 @@ register_chest("trapped_chest",
meta:set_int("players", 1)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -887,7 +950,7 @@ register_chest("trapped_chest",
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
end
)
@ -908,13 +971,15 @@ local function close_if_trapped_chest(pos, player)
if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
end
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
player_chest_close(player)
elseif node.name == "mcl_chests:trapped_chest_on_left" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -928,7 +993,7 @@ local function close_if_trapped_chest(pos, player)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
player_chest_close(player)
@ -976,7 +1041,7 @@ minetest.register_node("mcl_chests:ender_chest", {
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
drawtype = "mesh",
mesh = "mcl_chests_chest.obj",
tiles = {"mcl_chests_ender.png"},
tiles = tiles_chest_ender_small,
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
@ -1002,22 +1067,38 @@ local formspec_ender_chest = "size[9,8.75]"..
"listring[current_player;enderchest]"..
"listring[current_player;main]"
minetest.register_chatcommand("enderchest", {
description = S("Show ender chest inventory formspec."),
privs = { debug = true },
func = function(name, params)
minetest.show_formspec(name, "enderchest:enderchest", formspec_ender_chest)
end
})
minetest.register_node("mcl_chests:ender_chest_small", {
description = S("Ender Chest"),
_tt_help = S("27 interdimensional inventory slots") .. "\n" .. S("Put items inside, retrieve them from any ender chest"),
_doc_items_longdesc = S("Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This inventory is the same no matter from which ender chest you access it from. If you put one item into one ender chest, you will find it in all other ender chests. Each player will only see their own items, but not the items of other players."),
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
drawtype = "nodebox",
node_box = {
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_chest.obj" or nil,
node_box = animate_chests and {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.5, 0.375, 0.4375},
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
} or nil,
collision_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
_chest_entity_textures = {"mcl_chests_ender.png"},
selection_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
tiles = animate_chests and {"mcl_chests_blank.png"} or tiles_chest_ender_small,
_chest_entity_textures = tiles_chest_ender_small,
_chest_entity_sound = "mcl_chests_enderchest",
_chest_entity_mesh = "mcl_chests_chest",
_chest_entity_animation_type = "chest",
tiles = {"mcl_chests_blank.png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
--[[{"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png",
"mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png",
@ -1034,10 +1115,13 @@ minetest.register_node("mcl_chests:ender_chest_small", {
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec_ender_chest)
create_entity(pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
if animate_chests then
create_entity(pos, "mcl_chests:ender_chest_small", tiles_chest_ender_small, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
end
end,
on_rightclick = function(pos, node, clicker)
player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, node.param2, false, "mcl_chests_enderchest", "mcl_chests_chest")
player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", tiles_chest_ender_small, node.param2, false, "mcl_chests_enderchest", "mcl_chests_chest")
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then
@ -1055,6 +1139,20 @@ minetest.register_on_joinplayer(function(player)
inv:set_size("enderchest", 9*3)
end)
minetest.register_allow_player_inventory_action(function(player, action, inv, info)
if inv:get_location().type == "player" and (
action == "move" and (info.from_list == "enderchest" or info.to_list == "enderchest")
or action == "put" and info.listname == "enderchest"
or action == "take" and info.listname == "enderchest"
) then
local def = player:get_wielded_item():get_definition()
if not minetest.find_node_near(player:get_pos(), def and def.range or ItemStack():get_definition().range, "mcl_chests:ender_chest_small", true) then
return 0
end
end
end)
minetest.register_craft({
output = 'mcl_chests:ender_chest',
recipe = {
@ -1215,8 +1313,9 @@ for color, desc in pairs(boxtypes) do
_doc_items_entry_name = entry_name,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
drawtype = "nodebox",
tiles = {"mcl_chests_blank.png"},
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_shulker.obj" or nil,
tiles = animate_chests and {"mcl_chests_blank.png"} or {mob_texture},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
_chest_entity_textures = {mob_texture},
_chest_entity_sound = "mcl_chests_shulker",
@ -1237,7 +1336,10 @@ for color, desc in pairs(boxtypes) do
meta:set_string("formspec", formspec_shulker_box(nil))
local inv = meta:get_inventory()
inv:set_size("main", 9*3)
if animate_chests then
create_entity(pos, small_name, {mob_texture}, minetest.get_node(pos).param2, false, "mcl_chests_shulker", "mcl_chests_shulker", "shulker")
end
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local nmeta = minetest.get_meta(pos)
@ -1356,6 +1458,11 @@ local function select_and_spawn_entity(pos, node)
local node_name = node.name
local node_def = minetest.registered_nodes[node_name]
local double_chest = minetest.get_item_group(node_name, "double_chest") > 0
if not animate_chests and not double_chest then
return
end
find_or_create_entity(pos, node_name, node_def._chest_entity_textures, node.param2, double_chest, node_def._chest_entity_sound, node_def._chest_entity_mesh, node_def._chest_entity_animation_type)
end
@ -1401,6 +1508,22 @@ minetest.register_lbm({
end,
})
-- The following LBM allows the Ender chests from MineClone2 post-0.71
-- (after commit 819dbc6224c3b96ad4094cccf3d9150f3ef61d45) to work in
-- Mineclonia. It also ensures that any Ender chest formspec changes
-- (even a removal of the formspec) get applied in future versions.
minetest.register_lbm({
label = "Update ender chest formspecs (MineClone2 compatibility)",
name = "mcl_chests:update_ender_chest_formspecs_" ..
minetest.sha1(formspec_ender_chest),
nodenames = { "mcl_chests:ender_chest_small" },
run_at_every_load = false,
action = function(pos, node)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec_ender_chest)
end,
})
minetest.register_lbm({
label = "Update shulker box formspecs (0.60.0)",
name = "mcl_chests:update_shulker_box_formspecs_0_60_0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

View File

@ -4,47 +4,30 @@
-- Crafting definition
--
local function craft_planks(output, input)
minetest.register_craft({
output = 'mcl_core:wood 4',
output = "mcl_core:"..output.."wood 4",
recipe = {
{'mcl_core:tree'},
{"mcl_core:"..input},
}
})
end
minetest.register_craft({
output = 'mcl_core:darkwood 4',
recipe = {
{'mcl_core:darktree'},
local planks = {
{"", "oak"},
{"dark", "dark_oak"},
{"jungle", "jungle"},
{"acacia", "acacia"},
{"spruce", "spruce"},
{"birch", "birch"}
}
})
minetest.register_craft({
output = 'mcl_core:junglewood 4',
recipe = {
{'mcl_core:jungletree'},
}
})
minetest.register_craft({
output = 'mcl_core:acaciawood 4',
recipe = {
{'mcl_core:acaciatree'},
}
})
minetest.register_craft({
output = 'mcl_core:sprucewood 4',
recipe = {
{'mcl_core:sprucetree'},
}
})
minetest.register_craft({
output = 'mcl_core:birchwood 4',
recipe = {
{'mcl_core:birchtree'},
}
})
for _, p in pairs(planks) do
craft_planks(p[1], p[1].."tree")
craft_planks(p[1], p[1].."tree_bark")
craft_planks(p[1], "stripped_"..p[2])
craft_planks(p[1], "stripped_"..p[2].."_bark")
end
minetest.register_craft({
type = 'shapeless',
@ -399,8 +382,14 @@ minetest.register_craft({
}
})
-- TODO: Add crafting recipe: 9 ice → 1 packed ice
-- Add it when silk touch tools work.
minetest.register_craft({
output = 'mcl_core:packed_ice 1',
recipe = {
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
}
})
--
-- Crafting (tool repair)

View File

@ -165,7 +165,7 @@ local function eat_gapple(itemstack, placer, pointed_thing)
mcl_potions.fire_resistance_func(placer, 1, 300)
mcl_potions.leaping_func(placer, 1, 300)
end
mcl_potions.swiftness_func(placer, absorbtion_factor, 120) -- TODO: Absorbtion
-- TODO: Absorbtion
mcl_potions.regeneration_func(placer, 2, regen_duration)
return gapple_hunger_restore(itemstack, placer, pointed_thing)
end

View File

@ -202,18 +202,42 @@ Stained glass is a decorative and mostly transparent block which comes in variou
Stick=Stock
Sticks are a very versatile crafting material; used in countless crafting recipes.=Stöcke sind ein vielseitiges Material, sie werden in zahllosen Fertigungsrezepten gebraucht.
Stone=Stein
Stripped Acacia Log=Entrindeter Akazienstamm
Stripped Acacia Wood=Entrindetes Akazienholz
Stripped Birch Log=Entrindeter Birkenstamm
Stripped Birch Wood=Entrindetes Birkenholz
Stripped Dark Oak Log=Entrindeter Schwarzeichenstamm
Stripped Dark Oak Wood=Entrindetes Schwarzeichenholz
Stripped Jungle Log=Entrindeter Dschungelbaumstamm
Stripped Jungle Wood=Entrindetes Dschungelholz
Stripped Oak Log=Entrindeter Eichenstamm
Stripped Oak Wood=Entrindetes Eichenholz
Stripped Spruce Log=Entrindeter Fichtenstamm
Stripped Spruce Wood=Entrindetes Fichtenholz
Stone Bricks=Steinziegel
Sugar=Zucker
Sugar Canes=Zuckerrohr
Sugar canes are a plant which has some uses in crafting. Sugar canes will slowly grow up to 3 blocks when they are next to water and are placed on a grass block, dirt, sand, red sand, podzol or coarse dirt. When a sugar cane is broken, all sugar canes connected above will break as well.=Zuckerrohr ist eine Pflanze, die in der Herstellung gebraucht wird. Zuckerrohr wird in der Nähe von Wasser bis zu 3 zusätzliche Blöcke wachsen lassen, wenn sie sich neben Wasser befinden und auf einem Grasblock, auf Erde, Sand, roten Sand, Podsol oder grobe Erde platziert wurden. Wird ein Zuckerrohr abgebrochen, werden alle verbundenen Zuckerrohrblöcke ebenfalls abbrechen.
Sugar canes can only be placed top of other sugar canes and on top of blocks on which they would grow.=Zuckerrohr kann nur auf Zuckerrohr platziert werden und auf Blöcken, auf denen Zuckerrohr wachsen würde.
Sugar comes from sugar canes and is used to make sweet foods.=Zucker kommt von Zuckerrohr und wird benutzt, um süße Lebensmittel zu machen.
The stripped trunk of an acacia tree.=Der entrindete Stamm einer Akazie.
The stripped trunk of a birch tree.=Der entrindete Stamm einer Birke.
The stripped trunk of a dark oak tree.=Der entrindete Stamm einer Schwarzeiche.
The stripped trunk of a jungle tree.=Der entrindete Stamm eines Dschungelbaums.
The stripped trunk of an oak tree.=Der entrindete Stamm einer Eiche.
The stripped trunk of a spruce tree.=Der entrindete Stamm einer Fichte.
The trunk of a birch tree.=Der Baumstamm einer Birke.
The trunk of a dark oak tree.=Der Baumstamm einer Schwarzeiche.
The trunk of a jungle tree.=Der Baumstamm eines Dschungelbaums.
The trunk of a spruce tree.=Der Baumstamm einer Fichte.
The trunk of an acacia.=Der Baumstamm einer Akazie.
The trunk of an oak tree.=Der Baumstamm einer Eiche.
The stripped wood of an acacia tree.=Das entrindete Holz einer Akazie.
The stripped wood of a birch tree.=Das entrindete Holz einer Birke.
The stripped wood of a dark oak tree.=Das entrindete Holz einer Schwarzeiche.
The stripped wood of a jungle tree.=Das entrindete Holz eines Dschungelbaums.
The stripped wood of an oak tree.=Das entrindete Holz einer Eiche.
The stripped wood of a spruce tree.=Das entrindete Holz einer Fichte.
This block consists of a couple of loose stones and can't support itself.=Diser Block besteht aus ein paar losen Steinchen und kann sich nicht selbst tragen.
This is a decorative block surrounded by the bark of a tree trunk.=Dies ist ein dekorativer Block, der von der Rinde eines Baumstamms umgeben ist.
This is a full block of snow. Snow of this thickness is usually found in areas of extreme cold.=Ein ganzer Block aus Schnee. Schnee von dieser Dicke wird üblicherweise in Gebieten extremer Kälte gefunden.

View File

@ -202,18 +202,42 @@ Stained glass is a decorative and mostly transparent block which comes in variou
Stick=
Sticks are a very versatile crafting material; used in countless crafting recipes.=
Stone=
Stripped Acacia Log=
Stripped Acacia Wood=
Stripped Birch Log=
Stripped Birch Wood=
Stripped Dark Oak Log=
Stripped Dark Oak Wood=
Stripped Jungle Log=
Stripped Jungle Wood=
Stripped Oak Log=
Stripped Oak Wood=
Stripped Spruce Log=
Stripped Spruce Wood=
Stone Bricks=
Sugar=
Sugar Canes=
Sugar canes are a plant which has some uses in crafting. Sugar canes will slowly grow up to 3 blocks when they are next to water and are placed on a grass block, dirt, sand, red sand, podzol or coarse dirt. When a sugar cane is broken, all sugar canes connected above will break as well.=
Sugar canes can only be placed top of other sugar canes and on top of blocks on which they would grow.=
Sugar comes from sugar canes and is used to make sweet foods.=
The stripped trunk of an acacia tree.=
The stripped trunk of a birch tree.=
The stripped trunk of a dark oak tree.=
The stripped trunk of a jungle tree.=
The stripped trunk of an oak tree.=
The stripped trunk of a spruce tree.=
The trunk of a birch tree.=
The trunk of a dark oak tree.=
The trunk of a jungle tree.=
The trunk of a spruce tree.=
The trunk of an acacia.=
The trunk of an oak tree.=
The stripped wood of an acacia tree.=
The stripped wood of a birch tree.=
The stripped wood of a dark oak tree.=
The stripped wood of a jungle tree.=
The stripped wood of an oak tree.=
The stripped wood of a spruce tree.=
This block consists of a couple of loose stones and can't support itself.=
This is a decorative block surrounded by the bark of a tree trunk.=
This is a full block of snow. Snow of this thickness is usually found in areas of extreme cold.=

View File

@ -1032,7 +1032,7 @@ for i=1,8 do
drop = "mcl_throwing:snowball "..(i+1),
_mcl_blast_resistance = 0.1,
_mcl_hardness = 0.1,
_mcl_silk_touch_drop = {"mcl_core:snow " .. (i+1)},
_mcl_silk_touch_drop = {"mcl_core:snow " .. i},
})
end

View File

@ -8,7 +8,7 @@ if mod_screwdriver then
end
-- Register tree trunk (wood) and bark
local register_tree_trunk = function(subname, description_trunk, description_bark, longdesc, tile_inner, tile_bark)
local function register_tree_trunk(subname, description_trunk, description_bark, longdesc, tile_inner, tile_bark, stripped_variant)
minetest.register_node("mcl_core:"..subname, {
description = description_trunk,
_doc_items_longdesc = longdesc,
@ -22,6 +22,7 @@ local register_tree_trunk = function(subname, description_trunk, description_bar
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = stripped_variant,
})
minetest.register_node("mcl_core:"..subname.."_bark", {
@ -37,6 +38,48 @@ local register_tree_trunk = function(subname, description_trunk, description_bar
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = stripped_variant.."_bark",
})
minetest.register_craft({
output = "mcl_core:"..subname.."_bark 3",
recipe = {
{ "mcl_core:"..subname, "mcl_core:"..subname },
{ "mcl_core:"..subname, "mcl_core:"..subname },
}
})
end
-- Register stripped trunk and stripped wood
local function register_stripped_trunk(subname, description_stripped_trunk, description_stripped_bark, longdesc, longdesc_wood, tile_stripped_inner, tile_stripped_bark)
minetest.register_node("mcl_core:"..subname, {
description = description_stripped_trunk,
_doc_items_longdesc = longdesc,
_doc_items_hidden = false,
tiles = {tile_stripped_inner, tile_stripped_inner, tile_stripped_bark},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
})
minetest.register_node("mcl_core:"..subname.."_bark", {
description = description_stripped_bark,
_doc_items_longdesc = longdesc_wood,
tiles = {tile_stripped_bark},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
is_ground_content = false,
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
})
minetest.register_craft({
@ -48,7 +91,7 @@ local register_tree_trunk = function(subname, description_trunk, description_bar
})
end
local register_wooden_planks = function(subname, description, tiles)
local function register_wooden_planks(subname, description, tiles)
minetest.register_node("mcl_core:"..subname, {
description = description,
_doc_items_longdesc = doc.sub.items.temp.build,
@ -119,7 +162,7 @@ local register_leaves = function(subname, description, longdesc, tiles, sapling,
})
end
local register_sapling = function(subname, description, longdesc, tt_help, texture, selbox)
local function register_sapling(subname, description, longdesc, tt_help, texture, selbox)
minetest.register_node("mcl_core:"..subname, {
description = description,
_tt_help = tt_help,
@ -161,12 +204,19 @@ end
---------------------
register_tree_trunk("tree", S("Oak Wood"), S("Oak Bark"), S("The trunk of an oak tree."), "default_tree_top.png", "default_tree.png")
register_tree_trunk("darktree", S("Dark Oak Wood"), S("Dark Oak Bark"), S("The trunk of a dark oak tree."), "mcl_core_log_big_oak_top.png", "mcl_core_log_big_oak.png")
register_tree_trunk("acaciatree", S("Acacia Wood"), S("Acacia Bark"), S("The trunk of an acacia."), "default_acacia_tree_top.png", "default_acacia_tree.png")
register_tree_trunk("sprucetree", S("Spruce Wood"), S("Spruce Bark"), S("The trunk of a spruce tree."), "mcl_core_log_spruce_top.png", "mcl_core_log_spruce.png")
register_tree_trunk("birchtree", S("Birch Wood"), S("Birch Bark"), S("The trunk of a birch tree."), "mcl_core_log_birch_top.png", "mcl_core_log_birch.png")
register_tree_trunk("jungletree", S("Jungle Wood"), S("Jungle Bark"), S("The trunk of a jungle tree."), "default_jungletree_top.png", "default_jungletree.png")
register_tree_trunk("tree", S("Oak Wood"), S("Oak Bark"), S("The trunk of an oak tree."), "default_tree_top.png", "default_tree.png", "mcl_core:stripped_oak")
register_tree_trunk("darktree", S("Dark Oak Wood"), S("Dark Oak Bark"), S("The trunk of a dark oak tree."), "mcl_core_log_big_oak_top.png", "mcl_core_log_big_oak.png", "mcl_core:stripped_dark_oak")
register_tree_trunk("acaciatree", S("Acacia Wood"), S("Acacia Bark"), S("The trunk of an acacia."), "default_acacia_tree_top.png", "default_acacia_tree.png", "mcl_core:stripped_acacia")
register_tree_trunk("sprucetree", S("Spruce Wood"), S("Spruce Bark"), S("The trunk of a spruce tree."), "mcl_core_log_spruce_top.png", "mcl_core_log_spruce.png", "mcl_core:stripped_spruce")
register_tree_trunk("birchtree", S("Birch Wood"), S("Birch Bark"), S("The trunk of a birch tree."), "mcl_core_log_birch_top.png", "mcl_core_log_birch.png", "mcl_core:stripped_birch")
register_tree_trunk("jungletree", S("Jungle Wood"), S("Jungle Bark"), S("The trunk of a jungle tree."), "default_jungletree_top.png", "default_jungletree.png", "mcl_core:stripped_jungle")
register_stripped_trunk("stripped_oak", S("Stripped Oak Log"), S("Stripped Oak Wood"), S("The stripped trunk of an oak tree."), S("The stripped wood of an oak tree."), "mcl_core_stripped_oak_top.png", "mcl_core_stripped_oak_side.png")
register_stripped_trunk("stripped_acacia", S("Stripped Acacia Log"), S("Stripped Acacia Wood"), S("The stripped trunk of an acacia tree."), S("The stripped wood of an acacia tree."), "mcl_core_stripped_acacia_top.png", "mcl_core_stripped_acacia_side.png")
register_stripped_trunk("stripped_dark_oak", S("Stripped Dark Oak Log"), S("Stripped Dark Oak Wood"), S("The stripped trunk of a dark oak tree."), S("The stripped wood of a dark oak tree."), "mcl_core_stripped_dark_oak_top.png", "mcl_core_stripped_dark_oak_side.png")
register_stripped_trunk("stripped_birch", S("Stripped Birch Log"), S("Stripped Birch Wood"), S("The stripped trunk of a birch tree."), S("The stripped wood of a birch tree."), "mcl_core_stripped_birch_top.png", "mcl_core_stripped_birch_side.png")
register_stripped_trunk("stripped_spruce", S("Stripped Spruce Log"), S("Stripped Spruce Wood"), S("The stripped trunk of a spruce tree."), S("The stripped wood of a spruce tree."), "mcl_core_stripped_spruce_top.png", "mcl_core_stripped_spruce_side.png")
register_stripped_trunk("stripped_jungle", S("Stripped Jungle Log"), S("Stripped Jungle Wood"), S("The stripped trunk of a jungle tree."), S("The stripped wood of a jungle tree."),"mcl_core_stripped_jungle_top.png", "mcl_core_stripped_jungle_side.png")
register_wooden_planks("wood", S("Oak Wood Planks"), {"default_wood.png"})
register_wooden_planks("darkwood", S("Dark Oak Wood Planks"), {"mcl_core_planks_big_oak.png"})

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

View File

@ -97,4 +97,12 @@ The target item is not enchantable.=Der Zielgegenstand ist nicht verzauberbar.
'@1' is not a valid number.='@1' ist keine gültige Zahl.
Enchanted Book=Verzaubertes Buch
Enchanting Table=Zaubertisch
Spend experience, and lapis to enchant various items.=Verbrauche Erfahrung und Lapislazuli, um verschiedene Gegenstände zu verzaubern.
Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=Mit Zaubertischen kannst Du Rüstungen, Werkzeuge, Waffen und Bücher mit verschiedenen Fähigkeiten verzaubern. Das kostet aber Erfahrung und Lapislazuli.
Rightclick the Enchanting Table to open the enchanting menu.=Rechtsklick auf den Zaubertisch öffnet das Verzaubern-Menü
Place a tool, armor, weapon or book into the top left slot, and then place 1-3 Lapis Lazuli in the slot to the right.=Platziere ein Werkzeug, eine Waffe oder ein Buch im oberen linken Slot und platziere dann 1-3 Lapislazuli im rechten Slot.
After placing your items in the slots, the enchanting options will be shown. Hover over the options to read what is available to you.=Nachdem Du Deine Gegenstände in den Slots platziert hast, werden die Verzauberungs-Optionen angezeigt. Fahre mit der Maus über die Optionen, um die angebotenen Verzauberungen zu sehen.
These options are randomized, and dependent on experience level; but the enchantment strength can be increased.=Die Auswahl wird zufällig generiert und hängt von Deinem Erfahrungslevel ab; Du kannst die Stärker der Verzauberung aber erhöhen.
To increase the enchantment strength, place bookshelves around the enchanting table. However, you will need to keep 1 air node between the table, & the bookshelves to empower the enchanting table.=Um die Stärker der Verzauberung zu erhöhen, platziere Bücherregale um den Zaubertisch. Damit die Verstärkung funktioniert, muss zwischen Tisch und Bücherregalen aber ein Block Freiraum sein.
After finally selecting your enchantment; left-click on the selection, and you will see both the lapis lazuli and your experience levels consumed. And, an enchanted item left in its place.=Nachdem Du Deine Verzauberung ausgewählt hast, klicke links auf die Auswahl. Nun werden Lapislazuli und Erfahrung verbraucht und durch einen verzauberten Gegenstand ersetzt.
Enchant=Verzaubern

View File

@ -1,4 +1,5 @@
# textdomain: mcl_enchanting
# Disclaimer: Some of these texts were machine-translated and should be reviewed by someone competent
Aqua Affinity=Affinité aquatique
Increases underwater mining speed.=Augmente la vitesse de minage sous-marine.
Bane of Arthropods=Fléau des arthropodes
@ -76,8 +77,8 @@ Reflects some of the damage taken when hit, at the cost of reducing durability w
Unbreaking=Solidité
Increases item durability.=Augmente la durabilité des objets.
Inventory=Inventaire
@1 × Lapis Lazuli=@1 × Lapis Lazuli
Enchantment levels: @1=Niveaux d'enchantement: @1
@1 Lapis Lazuli=@1 Lapis Lazuli
@1 Enchantment Levels=Niveaux d'enchantement: @1
Level requirement: @1=Niveau requis: @1
Enchant an item=Enchanter un objet
<player> <enchantment> [<level>]=<joueur> <enchantement> [<niveau>]
@ -97,4 +98,12 @@ The target item is not enchantable.=L'objet cible n'est pas enchantable.
'@1' is not a valid number.='@1' n'est pas un nombre valide.
Enchanted Book=Livre enchanté
Enchanting Table=Table d'enchantement
Spend experience, and lapis to enchant various items.=Dépensez de l'expérience et du lapis pour enchanter divers objets.
Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=Les tables d'enchantement vous permettront d'enchanter des armures, des outils, des armes et des livres avec diverses capacités. Mais, au prix d'un peu d'expérience, et de lapis-lazuli.
Rightclick the Enchanting Table to open the enchanting menu.=Faites un clic droit sur la table d'enchantement pour ouvrir le menu d'enchantement.
Place a tool, armor, weapon or book into the top left slot, and then place 1-3 Lapis Lazuli in the slot to the right.=Placez un outil, une armure, une arme ou un livre dans la fente supérieure gauche, puis placez 1-3 Lapis Lazuli dans la fente de droite.
After placing your items in the slots, the enchanting options will be shown. Hover over the options to read what is available to you.=Après avoir placé vos objets dans les emplacements, les options d'enchantement s'afficheront. Passez la souris sur les options pour lire ce qui est disponible pour vous.
These options are randomized, and dependent on experience level; but the enchantment strength can be increased.=Ces options sont aléatoires et dépendent du niveau d'expérience, mais la force de l'enchantement peut être augmentée.
To increase the enchantment strength, place bookshelves around the enchanting table. However, you will need to keep 1 air node between the table, & the bookshelves to empower the enchanting table.=Pour augmenter la puissance de l'enchantement, placez des étagères autour de la table d'enchantement. Cependant, vous devrez garder un nœud aérien entre la table et les étagères pour renforcer la table d'enchantement.
After finally selecting your enchantment; left-click on the selection, and you will see both the lapis lazuli and your experience levels consumed. And, an enchanted item left in its place.=Après avoir finalement sélectionné votre enchantement, cliquez avec le bouton gauche de la souris sur la sélection, et vous verrez le lapis-lazuli et vos niveaux d'expérience consommés. Et, un objet enchanté laissé à sa place.
Enchant=Enchantement

View File

@ -1,4 +1,5 @@
# textdomain: mcl_enchanting
# Disclaimer: Some of these texts were machine-translated and should be reviewed by someone competent
Aqua Affinity=Родство с водой
Increases underwater mining speed.=Увеличивает скорость добычи под водой.
Bane of Arthropods=Бич членистоногих
@ -76,8 +77,8 @@ Reflects some of the damage taken when hit, at the cost of reducing durability w
Unbreaking=Нерушимость
Increases item durability.=Увеличивает прочность предмета.
Inventory=Инвентарь
@1 × Lapis Lazuli=@1 × Ляпис-лазурь
Enchantment levels: @1=Уровень зачаровывания: @1
@1 Lapis Lazuli=@1 Ляпис-лазурь
@1 Enchantment Levels=@1 Уровень зачаровывания
Level requirement: @1=Требуемый уровень: @1
Enchant an item=Зачаровать предмет
<player> <enchantment> [<level>]=<игрок> <зачарование> [<уровень>]
@ -97,4 +98,18 @@ The target item is not enchantable.=Указана незачаровываем
'@1' is not a valid number.='@1' не является допустимым числом.
Enchanted Book=Зачарованная книга
Enchanting Table=Стол зачаровывания
Spend experience, and lapis to enchant various items.=Проведите время, и ляпис, чтобы очаровать различные предметы.
Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=Волшебные столы позволят вам очаровать доспехами, инструментами, оружием и книгами с различными способностями. Но, ценой некоторого опыта, и ляпис-лазурь.
Rightclick the Enchanting Table to open the enchanting menu.=Щелкните правой кнопкой мыши Зачаровывающий стол, чтобы открыть зачаровывающее меню.
Place a tool, armor, weapon or book into the top left slot, and then place 1-3 Lapis Lazuli in the slot to the right.=Поместите инструмент, броню, оружие или книгу в верхний левый паз, а затем поместите 1-3 лазурита в паз справа.
After placing your items in the slots, the enchanting options will be shown. Hover over the options to read what is available to you.=После размещения Ваших элементов в слотах, будут показаны волшебные опции. Наведите курсор на опции, чтобы прочитать, что доступно для вас.
These options are randomized, and dependent on experience level; but the enchantment strength can be increased.=Эти варианты рандомизированы и зависят от уровня опыта; но сила очарования может быть увеличена.
To increase the enchantment strength, place bookshelves around the enchanting table. However, you will need to keep 1 air node between the table, & the bookshelves to empower the enchanting table.=Чтобы увеличить силу очарования, разместите книжные полки вокруг очаровательного стола. Однако, вам нужно будет держать 1 воздушный узел между столом и книжными полками, чтобы придать силу очаровательному столу.
After finally selecting your enchantment; left-click on the selection, and you will see both the lapis lazuli and your experience levels consumed. And, an enchanted item left in its place.=После того, как вы, наконец, выбрали свое очарование; щелкните левой кнопкой мыши по выбору, и вы увидите, как лазурь ляпис и ваш уровень опыта потребляется. И очарованная вещь, оставленная на своем месте.
Enchant=Зачарование
##### not used anymore #####
@1 × Lapis Lazuli=@1 × Ляпис-лазурь
Enchantment levels: @1=Уровень зачаровывания: @1

View File

@ -76,8 +76,8 @@ Reflects some of the damage taken when hit, at the cost of reducing durability w
Unbreaking=
Increases item durability.=
Inventory=
@1 × Lapis Lazuli=
Enchantment levels: @1=
@1 Lapis Lazuli=
@1 Enchantment Levels=
Level requirement: @1=
Enchant an item=
<player> <enchantment> [<level>]=
@ -97,4 +97,12 @@ The target item is not enchantable.=
'@1' is not a valid number.=
Enchanted Book=
Enchanting Table=
Spend experience, and lapis to enchant various items.=
Enchanting Tables will let you enchant armors, tools, weapons, and books with various abilities. But, at the cost of some experience, and lapis lazuli.=
Rightclick the Enchanting Table to open the enchanting menu.=
Place a tool, armor, weapon or book into the top left slot, and then place 1-3 Lapis Lazuli in the slot to the right.=
After placing your items in the slots, the enchanting options will be shown. Hover over the options to read what is available to you.=
These options are randomized, and dependent on experience level; but the enchantment strength can be increased.=
To increase the enchantment strength, place bookshelves around the enchanting table. However, you will need to keep 1 air node between the table, & the bookshelves to empower the enchanting table.=
After finally selecting your enchantment; left-click on the selection, and you will see both the lapis lazuli and your experience levels consumed. And, an enchanted item left in its place.=
Enchant=

View File

@ -169,7 +169,16 @@ minetest.register_node("mcl_end:dragon_egg", {
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 9,
_mcl_hardness = 3,
-- TODO: Make dragon egg teleport on punching
on_punch = function(pos, node)
local max_dist = vector.new(15, 7, 15)
local positions = minetest.find_nodes_in_area(vector.subtract(pos, max_dist), vector.add(pos, max_dist), "air", false)
if #positions > 0 then
local tpos = positions[math.random(#positions)]
minetest.remove_node(pos)
minetest.set_node(tpos, node)
minetest.check_for_falling(tpos)
end
end,
})

View File

@ -18,19 +18,21 @@ minetest.register_node("mcl_farming:beetroot_0", {
_doc_items_longdesc = S("Beetroot plants are plants which grow on farmland under sunlight in 4 stages. On hydrated farmland, they grow a bit faster. They can be harvested at any time but will only yield a profit when mature."),
_doc_items_entry_name = S("Premature Beetroot Plant"),
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:beetroot_seeds",
tiles = {"mcl_farming_beetroot_0.png"},
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_beetroot_0.png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_beetroot_0.png",
wield_image = "mcl_farming_beetroot_0.png",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}
{-0.5, -9/16, -0.5, 0.5, -6/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},
@ -42,19 +44,21 @@ minetest.register_node("mcl_farming:beetroot_1", {
description = S("Premature Beetroot Plant (Stage 2)"),
_doc_items_create_entry = false,
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:beetroot_seeds",
tiles = {"mcl_farming_beetroot_1.png"},
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_beetroot_1.png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_beetroot_1.png",
wield_image = "mcl_farming_beetroot_1.png",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -3/16, 0.5}
{-0.5, -9/16, -0.5, 0.5, -4/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},
@ -66,19 +70,21 @@ minetest.register_node("mcl_farming:beetroot_2", {
description = S("Premature Beetroot Plant (Stage 3)"),
_doc_items_create_entry = false,
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:beetroot_seeds",
tiles = {"mcl_farming_beetroot_2.png"},
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_beetroot_2.png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_beetroot_2.png",
wield_image = "mcl_farming_beetroot_2.png",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 2/16, 0.5}
{-0.5, -9/16, -0.5, 0.5, 1/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},
@ -91,33 +97,36 @@ minetest.register_node("mcl_farming:beetroot", {
_doc_items_longdesc = S("A mature beetroot plant is a farming plant which is ready to be harvested for a beetroot and some beetroot seeds. It won't grow any further."),
_doc_items_create_entry = true,
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = {
--[[ drops 1 beetroot guaranteed.
drops 0-3 beetroot seeds:
0 seeds: 42.18%
1 seed: 14.06%
2 seeds: 18.75%
3 seeds: 25% ]]
max_items = 2,
drops 1-4 beetroot seeds:
1 seed: 42.18%
2 seeds: 14.06%
3 seeds: 18.75%
4 seeds: 25% ]]
max_items = 3,
items = {
{ items = {"mcl_farming:beetroot_item"}, rarity = 1 },
{ items = {"mcl_farming:beetroot_seeds 1"}, rarity = 1 },
{ items = {"mcl_farming:beetroot_seeds 3"}, rarity = 4 },
{ items = {"mcl_farming:beetroot_seeds 2"}, rarity = 4 },
{ items = {"mcl_farming:beetroot_seeds 1"}, rarity = 4 },
},
},
tiles = {"mcl_farming_beetroot_3.png"},
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_beetroot_3.png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_beetroot_3.png",
wield_image = "mcl_farming_beetroot_3.png",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 3/16, 0.5}
{-0.5, -9/16, -0.5, 0.5, 2/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,beetroot=4},

View File

@ -28,18 +28,20 @@ for i=1, 7 do
_doc_items_longdesc = longdesc,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "meshoptions",
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:carrot_item",
tiles = {texture},
tiles = { mcl_farming:align_plantlike_nodebox_texture(texture) },
use_texture_alpha = "clip",
inventory_image = texture,
wield_image = texture,
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, sel_height, 0.5}
{-0.5, -9/16, -0.5, 0.5, sel_height - 1/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},
@ -53,11 +55,13 @@ minetest.register_node("mcl_farming:carrot", {
_doc_items_longdesc = S("Mature carrot plants are ready to be harvested for carrots. They won't grow any further."),
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "meshoptions",
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
tiles = {"farming_carrot_4.png"},
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
tiles = { mcl_farming:align_plantlike_nodebox_texture("farming_carrot_4.png") },
use_texture_alpha = "clip",
inventory_image = "farming_carrot_4.png",
wield_image = "farming_carrot_4.png",
drop = {
@ -72,7 +76,7 @@ minetest.register_node("mcl_farming:carrot", {
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 4/16, 0.5}
{-0.5, -9/16, -0.5, 0.5, 3/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},

View File

@ -27,3 +27,73 @@ dofile(minetest.get_modpath("mcl_farming").."/potatoes.lua")
-- ========= BEETROOT =========
dofile(minetest.get_modpath("mcl_farming").."/beetroot.lua")
-- This function generates a row of plantlike and nodebox nodes whose
-- name starts with a given string, starting at a given position. It
-- places a given node below so that the rendering can be examined.
local function generate_plant_row(prefix, pos, below_node)
local i = 1
for node_name, node in pairs(minetest.registered_nodes) do
if (
1 == node_name:find(prefix) and
(
"plantlike" == node.drawtype or
"nodebox" == node.drawtype
)
) then
local node_pos = {
x = pos.x + i,
y = pos.y,
z = pos.z,
}
minetest.set_node(
node_pos,
{
name = node_name,
param2 = node.place_param2 or 0
}
)
local below_pos = {
x = node_pos.x,
y = node_pos.y - 1,
z = node_pos.z
}
minetest.set_node(
below_pos,
below_node
)
i = i + 1
end
end
end
minetest.register_chatcommand("generate_farming_plant_rows",{
description = "Generates rows of mcl_farming plant nodes on farming soil and glass",
privs = { debug = true },
func = function(name, param)
local player = minetest.get_player_by_name(name)
local pos = player:get_pos()
local node_prefixes = {
"mcl_farming:beetroot",
"mcl_farming:carrot",
"mcl_farming:melon",
"mcl_farming:potato",
"mcl_farming:pumpkin",
"mcl_farming:wheat",
}
for i,node_prefix in ipairs(node_prefixes) do
generate_plant_row(
node_prefix,
pos,
{ name = "mcl_farming:soil" }
)
pos.z = pos.z + 2
generate_plant_row(
node_prefix,
pos,
{ name = "mcl_core:glass" }
)
pos.z = pos.z + 2
end
end
})

View File

@ -91,16 +91,18 @@ for s=1,7 do
_doc_items_longdesc = longdesc,
paramtype = "light",
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_plus_nodebox(),
sunlight_propagates = true,
drop = stem_drop,
tiles = {texture},
tiles = { mcl_farming:align_plantlike_nodebox_texture(texture) },
use_texture_alpha = "clip",
wield_image = texture,
inventory_image = texture,
selection_box = {
type = "fixed",
fixed = {
{-0.15, -0.5, -0.15, 0.15, -0.5+h, 0.15}
{-0.15, -9/16, -0.15, 0.15, -9/16+h, 0.15}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1, plant_melon_stem=s},

View File

@ -6,13 +6,13 @@ for i=1, 7 do
local texture, selbox
if i < 3 then
texture = "mcl_farming_potatoes_stage_0.png"
selbox = { -0.5, -0.5, -0.5, 0.5, -5/16, 0.5 }
selbox = { -0.5, -9/16, -0.5, 0.5, -6/16, 0.5 }
elseif i < 5 then
texture = "mcl_farming_potatoes_stage_1.png"
selbox = { -0.5, -0.5, -0.5, 0.5, -2/16, 0.5 }
selbox = { -0.5, -9/16, -0.5, 0.5, -3/16, 0.5 }
else
texture = "mcl_farming_potatoes_stage_2.png"
selbox = { -0.5, -0.5, -0.5, 0.5, 2/16, 0.5 }
selbox = { -0.5, -9/16, -0.5, 0.5, 1/16, 0.5 }
end
local create, name, longdesc
@ -33,13 +33,15 @@ for i=1, 7 do
_doc_items_entry_name = name,
_doc_items_longdesc = longdesc,
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:potato_item",
tiles = { texture },
tiles = { mcl_farming:align_plantlike_nodebox_texture(texture) },
use_texture_alpha = "clip",
inventory_image = texture,
wield_image = texture,
selection_box = {
@ -57,12 +59,14 @@ minetest.register_node("mcl_farming:potato", {
description = S("Mature Potato Plant"),
_doc_items_longdesc = S("Mature potato plants are ready to be harvested for potatoes. They won't grow any further."),
paramtype = "light",
paramtype2 = "meshoptions",
sunlight_propagates = true,
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
tiles = {"mcl_farming_potatoes_stage_3.png"},
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_potatoes_stage_3.png") },
use_texture_alpha = "clip",
wield_image = "mcl_farming_potatoes_stage_3.png",
inventory_image = "mcl_farming_potatoes_stage_3.png",
drop = {
@ -77,7 +81,7 @@ minetest.register_node("mcl_farming:potato", {
selection_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 1/16, 0.5 }
{ -0.5, -9/16, -0.5, 0.5, 0, 0.5 }
}
},
groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1},

View File

@ -63,16 +63,18 @@ for s=1,7 do
_doc_items_longdesc = longdesc,
paramtype = "light",
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_plus_nodebox(),
sunlight_propagates = true,
drop = stem_drop,
tiles = {texture},
tiles = { mcl_farming:align_plantlike_nodebox_texture(texture) },
use_texture_alpha = "clip",
inventory_image = texture,
wield_image = texture,
selection_box = {
type = "fixed",
fixed = {
{-0.15, -0.5, -0.15, 0.15, -0.5+h, 0.15}
{-0.15, -9/16, -0.15, 0.15, -9/16+h, 0.15}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1,},
@ -104,7 +106,6 @@ local pumpkin_base_def = {
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
}
minetest.register_node("mcl_farming:pumpkin", pumpkin_base_def)
local pumpkin_face_base_def = table.copy(pumpkin_base_def)
pumpkin_face_base_def.description = S("Pumpkin")
@ -115,6 +116,11 @@ pumpkin_face_base_def.groups.armor_head=1
pumpkin_face_base_def._mcl_armor_mob_range_factor = 0
pumpkin_face_base_def._mcl_armor_mob_range_mob = "mobs_mc:enderman"
pumpkin_face_base_def.groups.non_combat_armor=1
pumpkin_face_base_def.on_construct = function(pos)
-- Attempt to spawn iron golem or snow golem
mobs_mc.tools.check_iron_golem_summon(pos)
mobs_mc.tools.check_snow_golem_summon(pos)
end
if minetest.get_modpath("mcl_armor") then
pumpkin_face_base_def.on_secondary_use = armor.on_armor_use
end
@ -123,12 +129,11 @@ end
mcl_farming:add_plant("plant_pumpkin_stem", "mcl_farming:pumpkintige_unconnect", {"mcl_farming:pumpkin_1", "mcl_farming:pumpkin_2", "mcl_farming:pumpkin_3", "mcl_farming:pumpkin_4", "mcl_farming:pumpkin_5", "mcl_farming:pumpkin_6", "mcl_farming:pumpkin_7"}, 30, 5)
-- Register actual pumpkin, connected stems and stem-to-pumpkin growth
mcl_farming:add_gourd("mcl_farming:pumpkintige_unconnect", "mcl_farming:pumpkintige_linked", "mcl_farming:pumpkintige_unconnect", stem_def, stem_drop, "mcl_farming:pumpkin_face", pumpkin_face_base_def, 30, 15, "mcl_farming_pumpkin_stem_connected.png^[colorize:#FFA800:127",
function(pos)
-- Attempt to spawn iron golem or snow golem
mobs_mc.tools.check_iron_golem_summon(pos)
mobs_mc.tools.check_snow_golem_summon(pos)
end)
mcl_farming:add_gourd("mcl_farming:pumpkintige_unconnect", "mcl_farming:pumpkintige_linked", "mcl_farming:pumpkintige_unconnect", stem_def, stem_drop, "mcl_farming:pumpkin", pumpkin_base_def, 30, 15, "mcl_farming_pumpkin_stem_connected.png^[colorize:#FFA800:127")
-- Steal function to properly disconnect a carved pumpkin
pumpkin_face_base_def.after_destruct = minetest.registered_nodes["mcl_farming:pumpkin"].after_destruct
minetest.register_node("mcl_farming:pumpkin_face", pumpkin_face_base_def)
-- Jack o'Lantern
minetest.register_node("mcl_farming:pumpkin_face_light", {
@ -165,11 +170,6 @@ minetest.register_craft({
recipe = {{"mcl_farming:pumpkin"}}
})
minetest.register_craft({
output = "mcl_farming:pumpkin_seeds 4",
recipe = {{"mcl_farming:pumpkin_face"}}
})
minetest.register_craftitem("mcl_farming:pumpkin_pie", {
description = S("Pumpkin Pie"),
_doc_items_longdesc = S("A pumpkin pie is a tasty food item which can be eaten."),
@ -187,11 +187,6 @@ minetest.register_craft({
output = "mcl_farming:pumpkin_pie",
recipe = {"mcl_farming:pumpkin", "mcl_core:sugar", "mcl_throwing:egg"},
})
minetest.register_craft({
type = "shapeless",
output = "mcl_farming:pumpkin_pie",
recipe = {"mcl_farming:pumpkin_face", "mcl_core:sugar", "mcl_throwing:egg"},
})
if minetest.get_modpath("doc") then

View File

@ -178,7 +178,7 @@ end
- stem_def: Partial node definition of the fully-grown unconnected stem node. Many fields are already defined. You need to add `tiles` and `description` at minimum. Don't define on_construct without good reason
- stem_drop: Drop probability table for all stem
- gourd_itemstring: Desired itemstring of the full gourd node
- gourd_def: (almost) full definition of the gourd node. This function will add on_construct and after_dig_node to the definition for unconnecting any connected stems
- gourd_def: (almost) full definition of the gourd node. This function will add on_construct and after_destruct to the definition for unconnecting any connected stems
- grow_interval: Will attempt to grow a gourd periodically at this interval in seconds
- grow_chance: Chance of 1/grow_chance to grow a gourd next to the full unconnected stem after grow_interval has passed. Must be a natural number
- connected_stem_texture: Texture of the connected stem
@ -228,8 +228,8 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
end
-- Register gourd
if not gourd_def.after_dig_node then
gourd_def.after_dig_node = function(blockpos, oldnode, oldmetadata, user)
if not gourd_def.after_destruct then
gourd_def.after_destruct = function(blockpos, oldnode)
-- Disconnect any connected stems, turning them back to normal stems
for n=1, #neighbors do
local offset = neighbors[n]
@ -265,7 +265,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
stem_def.selection_box = {
type = "fixed",
fixed = {
{-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}
{-0.15, -9/16, -0.15, 0.15, 7/16, 0.15}
},
}
end
@ -273,7 +273,20 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
stem_def.paramtype = "light"
end
if not stem_def.drawtype then
stem_def.drawtype = "plantlike"
stem_def.drawtype = "nodebox"
end
if not stem_def.node_box then
stem_def.node_box = mcl_farming:get_plantlike_plus_nodebox()
end
if stem_def.tiles then
for i=1,#stem_def.tiles do
stem_def.tiles[i] = mcl_farming:align_plantlike_nodebox_texture(
stem_def.tiles[i]
)
end
end
if not stem_def.use_texture_alpha then
stem_def.use_texture_alpha = "clip"
end
if stem_def.walkable == nil then
stem_def.walkable = false
@ -300,7 +313,9 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
minetest.register_node(stem_itemstring, stem_def)
-- Register connected stems
local connected_stem_texture = mcl_farming:align_plantlike_nodebox_texture(
connected_stem_texture
)
local connected_stem_tiles = {
{ "blank.png", --top
"blank.png", -- bottom
@ -332,16 +347,16 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
}
}
local connected_stem_nodebox = {
{-0.5, -0.5, 0, 0.5, 0.5, 0},
{-0.5, -0.5, 0, 0.5, 0.5, 0},
{0, -0.5, -0.5, 0, 0.5, 0.5},
{0, -0.5, -0.5, 0, 0.5, 0.5},
{-0.5, -9/16, 0, 0.5, 7/16, 0},
{-0.5, -9/16, 0, 0.5, 7/16, 0},
{0, -9/16, -0.5, 0, 7/16, 0.5},
{0, -9/16, -0.5, 0, 7/16, 0.5},
}
local connected_stem_selectionbox = {
{-0.1, -0.5, -0.1, 0.5, 0.2, 0.1},
{-0.5, -0.5, -0.1, 0.1, 0.2, 0.1},
{-0.1, -0.5, -0.1, 0.1, 0.2, 0.5},
{-0.1, -0.5, -0.5, 0.1, 0.2, 0.1},
{-0.1, -9/16, -0.1, 0.5, 0.2 - 1/16, 0.1},
{-0.5, -9/16, -0.1, 0.1, 0.2 - 1/16, 0.1},
{-0.1, -9/16, -0.1, 0.1, 0.2 - 1/16, 0.5},
{-0.1, -9/16, -0.5, 0.1, 0.2 - 1/16, 0.1},
}
for i=1, 4 do
@ -388,12 +403,11 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
{ x=0, y=0, z=-1 },
{ x=0, y=0, z=1 },
}
local floorpos, floor
for n=#neighbors, 1, -1 do
local offset = neighbors[n]
local blockpos = vector.add(stempos, offset)
floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
floor = minetest.get_node(floorpos)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local block = minetest.get_node(blockpos)
local soilgroup = minetest.get_item_group(floor.name, "soil")
if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name=="mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then
@ -407,6 +421,8 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
local r = math.random(1, #neighbors)
local offset = neighbors[r]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local p2
if offset.x == 1 then
minetest.set_node(stempos, {name=connected_stem_names[1]})
@ -468,3 +484,40 @@ minetest.register_lbm({
mcl_farming:grow_plant(identifier, pos, node, false, false, low_speed)
end,
})
-- This function returns a nodebox that imitates a plantlike plus (+)
-- drawtype, but is shifted 1/16 lower, into the empty space above
-- farming soil. The regular plantlike drawtype can not do this.
function mcl_farming:get_plantlike_plus_nodebox()
return {
type = "fixed",
fixed = {
{ 0, -9/16, -0.15, 0, 7/16, 0.15 },
{ -0.15, -9/16, 0, 0.15, 7/16, 0 }
}
}
end
-- This function returns a nodebox that imitates a plantlike grid (#)
-- drawtype, but is shifted 1/16 lower, into the empty space above
-- farming soil. The regular plantlike drawtype can not do this.
function mcl_farming:get_plantlike_grid_nodebox()
return {
type = "fixed",
fixed = {
{ 4/16, -9/16, -8/16, 4/16, 7/16, 8/16},
{-4/16, -9/16, -8/16, -4/16, 7/16, 8/16},
{-8/16, -9/16, -4/16, 8/16, 7/16, -4/16},
{-8/16, -9/16, 4/16, 8/16, 7/16, 4/16},
}
}
end
-- This function takes a texture and returns a modified texture where
-- the bottom row is at the top, assuming 16px × 16px textures. This
-- is used to align textures to a “plantlike” nodebox shifted 1/16
-- below its own node into the empty space above farming soil.
function mcl_farming:align_plantlike_nodebox_texture(texture)
local texture = texture:gsub("%^", "\\%^"):gsub(":", "\\:")
return "[combine:16x16:0,-15=" .. texture .. ":0,1=" .. texture
end

View File

@ -39,19 +39,21 @@ for i=1,7 do
_doc_items_entry_name = name,
_doc_items_longdesc = longdesc,
paramtype = "light",
paramtype2 = "meshoptions",
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
sunlight_propagates = true,
walkable = false,
drawtype = "plantlike",
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
drop = "mcl_farming:wheat_seeds",
tiles = {"mcl_farming_wheat_stage_"..(i-1)..".png"},
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_wheat_stage_"..(i-1)..".png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_wheat_stage_"..(i-1)..".png",
wield_image = "mcl_farming_wheat_stage_"..(i-1)..".png",
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, sel_heights[i], 0.5}
{-0.5, -9/16, -0.5, 0.5, sel_heights[i] - 1/16, 0.5}
},
},
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1},
@ -65,13 +67,21 @@ minetest.register_node("mcl_farming:wheat", {
_doc_items_longdesc = S("Mature wheat plants are ready to be harvested for wheat and wheat seeds. They won't grow any further."),
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "meshoptions",
-- keep place_param2 for plantlike drawtype compatiblity
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
tiles = {"mcl_farming_wheat_stage_7.png"},
drawtype = "nodebox",
node_box = mcl_farming:get_plantlike_grid_nodebox(),
tiles = { mcl_farming:align_plantlike_nodebox_texture("mcl_farming_wheat_stage_7.png") },
use_texture_alpha = "clip",
inventory_image = "mcl_farming_wheat_stage_7.png",
wield_image = "mcl_farming_wheat_stage_7.png",
selection_box = {
type = "fixed",
fixed = {
{ -0.5, -9/16, -0.5, 0.5, 7/16, 0.5 }
}
},
drop = {
max_items = 4,
items = {

View File

@ -5,29 +5,6 @@ mcl_fire = {}
local S = minetest.get_translator("mcl_fire")
local N = function(s) return s end
-- inverse pyramid pattern above lava source, floor 1 of 2:
local lava_fire=
{
{ x =-1, y = 1, z =-1},
{ x =-1, y = 1, z = 0},
{ x =-1, y = 1, z = 1},
{ x = 0, y = 1, z =-1},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 1, z = 1},
{ x = 1, y = 1, z =-1},
{ x = 1, y = 1, z = 0},
{ x = 1, y = 1, z = 1}
}
local alldirs=
{
{ x =-1, y = 0, z = 0},
{ x = 1, y = 0, z = 0},
{ x = 0, y =-1, z = 0},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 0, z =-1},
{ x = 0, y = 0, z = 1}
}
local spawn_smoke = function(pos)
mcl_particles.add_node_particlespawner(pos, {
amount = 0.1,
@ -50,6 +27,34 @@ local spawn_smoke = function(pos)
}, "high")
end
local adjacents = {
{ x =-1, y = 0, z = 0 },
{ x = 1, y = 0, z = 0 },
{ x = 0, y = 1, z = 0 },
{ x = 0, y =-1, z = 0 },
{ x = 0, y = 0, z =-1 },
{ x = 0, y = 0, z = 1 },
}
math.randomseed(os.time())
local function shuffle_table(t)
for i = #t, 1, -1 do
local r = math.random(i)
t[i], t[r] = t[r], t[i]
end
end
shuffle_table(adjacents)
local function has_flammable(pos)
for k,v in pairs(adjacents) do
local p=vector.add(pos,v)
local n=minetest.get_node_or_nil(p)
if n and minetest.get_item_group(n.name, "flammable") ~= 0 then
return p
end
end
end
--
-- Items
--
@ -85,10 +90,6 @@ local fire_death_messages = {
N("@1 died in a fire."),
}
local fire_timer = function(pos)
minetest.get_node_timer(pos):start(math.random(3, 7))
end
local spawn_fire = function(pos, age)
minetest.set_node(pos, {name="mcl_fire:fire", param2 = age})
minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
@ -124,82 +125,6 @@ minetest.register_node("mcl_fire:fire", {
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
end
end,
on_timer = function(pos)
local node = minetest.get_node(pos)
-- Age is a number from 0 to 15 and is increased every timer step.
-- "old" fire is more likely to be extinguished
local age = node.param2
local flammables = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"})
local below = minetest.get_node({x=pos.x, y=pos.z-1, z=pos.z})
local below_is_flammable = minetest.get_item_group(below.name, "flammable") > 0
-- Extinguish fire
if (not fire_enabled) and (math.random(1,3) == 1) then
minetest.remove_node(pos)
return
end
if age == 15 and not below_is_flammable then
minetest.remove_node(pos)
return
elseif age > 3 and #flammables == 0 and not below_is_flammable and math.random(1,4) == 1 then
minetest.remove_node(pos)
return
end
local age_add = 1
-- If fire spread is disabled, we have to skip the "destructive" code
if (not fire_enabled) then
if age + age_add <= 15 then
node.param2 = age + age_add
minetest.set_node(pos, node)
end
-- Restart timer
fire_timer(pos)
return
end
-- Spawn fire to nearby flammable nodes
local is_next_to_flammable = minetest.find_node_near(pos, 2, {"group:flammable"}) ~= nil
if is_next_to_flammable and math.random(1,2) == 1 then
-- The fire we spawn copies the age of this fire.
-- This prevents fire from spreading infinitely far as the fire fire dies off
-- quicker the further it has spreaded.
local age_next = math.min(15, age + math.random(0, 1))
-- Select random type of fire spread
local burntype = math.random(1,2)
if burntype == 1 then
-- Spawn fire in air
local nodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"})
while #nodes > 0 do
local r = math.random(1, #nodes)
if minetest.find_node_near(nodes[r], 1, {"group:flammable"}) then
spawn_fire(nodes[r], age_next)
break
else
table.remove(nodes, r)
end
end
else
-- Burn flammable block
local nodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"})
if #nodes > 0 then
local r = math.random(1, #nodes)
local nn = minetest.get_node(nodes[r]).name
local ndef = minetest.registered_nodes[nn]
local fgroup = minetest.get_item_group(nn, "flammable")
if ndef and ndef._on_burn then
ndef._on_burn(nodes[r])
elseif fgroup ~= -1 then
spawn_fire(nodes[r], age_next)
end
end
end
end
-- Regular age increase
if age + age_add <= 15 then
node.param2 = age + age_add
minetest.set_node(pos, node)
end
-- Restart timer
fire_timer(pos)
end,
drop = "",
sounds = {},
-- Turn into eternal fire on special blocks, light Nether portal (if possible), start burning timer
@ -209,14 +134,12 @@ minetest.register_node("mcl_fire:fire", {
local dim = mcl_worlds.pos_to_dimension(bpos)
if under == "mcl_nether:magma" or under == "mcl_nether:netherrack" or (under == "mcl_core:bedrock" and dim == "end") then
minetest.swap_node(pos, {name = "mcl_fire:eternal_fire"})
minetest.set_node(pos, {name="mcl_fire:eternal_fire"})
end
if minetest.get_modpath("mcl_portals") then
mcl_portals.light_nether_portal(pos)
end
fire_timer(pos)
spawn_smoke(pos)
end,
on_destruct = function(pos)
@ -255,29 +178,7 @@ minetest.register_node("mcl_fire:eternal_fire", {
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
end
end,
on_timer = function(pos)
if fire_enabled then
local airs = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"})
while #airs > 0 do
local r = math.random(1, #airs)
if minetest.find_node_near(airs[r], 1, {"group:flammable"}) then
local node = minetest.get_node(airs[r])
local age = node.param2
local age_next = math.min(15, age + math.random(0, 1))
spawn_fire(airs[r], age_next)
break
else
table.remove(airs, r)
end
end
end
-- Restart timer
fire_timer(pos)
end,
-- Start burning timer and light Nether portal (if possible)
on_construct = function(pos)
fire_timer(pos)
if minetest.get_modpath("mcl_portals") then
mcl_portals.light_nether_portal(pos)
end
@ -402,114 +303,6 @@ if flame_sound then
end
--
-- ABMs
--
-- Extinguish all flames quickly with water and such
minetest.register_abm({
label = "Extinguish fire",
nodenames = {"mcl_fire:fire", "mcl_fire:eternal_fire"},
neighbors = {"group:puts_out_fire"},
interval = 3,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.remove_node(pos)
minetest.sound_play("fire_extinguish_flame",
{pos = pos, max_hear_distance = 16, gain = 0.15}, true)
end,
})
-- Enable the following ABMs according to 'enable fire' setting
local function has_flammable(pos)
local npos, node
for n, v in ipairs(alldirs) do
npos = vector.add(pos, v)
node = minetest.get_node_or_nil(npos)
if node and node.name and minetest.get_item_group(node.name, "flammable") ~= 0 then
return npos
end
end
return false
end
if not fire_enabled then
-- Occasionally remove fire if fire disabled
-- NOTE: Fire is normally extinguished in timer function
minetest.register_abm({
label = "Remove disabled fire",
nodenames = {"mcl_fire:fire"},
interval = 10,
chance = 10,
catch_up = false,
action = minetest.remove_node,
})
else -- Fire enabled
-- Set fire to air nodes
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"group:lava"},
neighbors = {"air"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local i, dir, target, node, i2, f
i = math.random(1,9)
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
i = ((i + math.random(0,7)) % 9) + 1
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
return
end
end
i2 = math.random(1,15)
if i2 < 10 then
local dir2, target2, node2
dir2 = lava_fire[i2]
target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z}
node2 = minetest.get_node(target2)
if node2 and node2.name == "air" then
f = has_flammable(target2)
if f then
minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z},
expirationtime=1, size=1.5, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
return
end
end
end
f = has_flammable(target)
if f then
minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z},
expirationtime=1, size=1, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
end
end,
})
end
-- Set pointed_thing on (normal) fire.
-- * pointed_thing: Pointed thing to ignite
-- * player: Player who sets fire or nil if nobody
@ -535,6 +328,144 @@ mcl_fire.set_fire = function(pointed_thing, player, allow_on_fire)
end
end
--
-- ABMs
--
-- Extinguish all flames quickly with water and such
minetest.register_abm({
label = "Extinguish fire",
nodenames = {"mcl_fire:fire", "mcl_fire:eternal_fire"},
neighbors = {"group:puts_out_fire"},
interval = 3,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.remove_node(pos)
minetest.sound_play("fire_extinguish_flame",
{pos = pos, max_hear_distance = 16, gain = 0.15}, true)
end,
})
-- Enable the following ABMs according to 'enable fire' setting
-- [...]a fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range.
-- https://minecraft.fandom.com/wiki/Fire#Spread
local function check_aircube(p1,p2)
local nds=minetest.find_nodes_in_area(p1,p2,{"air"})
shuffle_table(nds)
for k,v in pairs(nds) do
if has_flammable(v) then return v end
end
end
-- [...] a fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to).
local function get_ignitable(pos)
return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1)))
end
-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block.
local function get_ignitable_by_lava(pos)
return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil
end
if not fire_enabled then
-- Occasionally remove fire if fire disabled
-- NOTE: Fire is normally extinguished in timer function
minetest.register_abm({
label = "Remove disabled fire",
nodenames = {"mcl_fire:fire"},
interval = 10,
chance = 10,
catch_up = false,
action = minetest.remove_node,
})
else -- Fire enabled
-- Fire Spread
minetest.register_abm({
label = "Ignite flame",
nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"},
interval = 7,
chance = 12,
catch_up = false,
action = function(pos)
local p = get_ignitable(pos)
if p then
spawn_fire(p)
shuffle_table(adjacents)
end
end
})
--lava fire spread
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"},
neighbors = {"air","group:flammable"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local p=get_ignitable_by_lava(pos)
if p then
spawn_fire(p)
end
end,
})
minetest.register_abm({
label = "Remove fires",
nodenames = {"mcl_fire:fire"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local p=has_flammable(pos)
if p then
local n=minetest.get_node_or_nil(p)
if n and minetest.get_item_group(n.name, "flammable") < 1 then
minetest.remove_node(pos)
end
else
minetest.remove_node(pos)
end
end,
})
-- Remove flammable nodes around basic flame
minetest.register_abm({
label = "Remove flammable nodes",
nodenames = {"mcl_fire:fire","mcl_fire:eternal_fire"},
neighbors = {"group:flammable"},
interval = 5,
chance = 18,
catch_up = false,
action = function(pos)
local p = has_flammable(pos)
if not p then
return
end
local nn = minetest.get_node(p).name
local def = minetest.registered_nodes[nn]
local fgroup = minetest.get_item_group(nn, "flammable")
if def and def._on_burn then
def._on_burn(p)
elseif fgroup ~= -1 then
spawn_fire(p)
minetest.check_for_falling(p)
end
end
})
end
minetest.register_lbm({
label = "Smoke particles from fire",
name = "mcl_fire:smoke",

View File

@ -0,0 +1,18 @@
# mcl_jukebox
## mcl_jukebox.register_record(title, author, identifier, image, sound)
* title: title of the track
* author: author of the track
* identifier: short string used in the item registration
* image: the texture of the track
* sound: sound file of the track
## mcl_jukebox.registered_records
Table indexed by item name containing:
* title: title of the track
* author: author of the track
* identifier: short string used in the item registration
* image: the texture of the track
* sound: sound file of the track

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator("mcl_jukebox")
mcl_jukebox = {}
mcl_jukebox.registered_records = {}
-- Player name-indexed table containing the currently heard track
local active_tracks = {}
@ -10,47 +13,30 @@ local active_huds = {}
-- Used to make sure that minetest.after only applies to the latest HUD change event
local hud_sequence_numbers = {}
-- List of music
local recorddata = {
-- { title, author, identifier }
{ "The Evil Sister (Jordach's Mix)", "SoundHelix", "13" } ,
{ "The Energetic Rat (Jordach's Mix)", "SoundHelix", "wait" },
{ "Eastern Feeling", "Jordach", "blocks"},
{ "Minetest", "Jordach", "far" },
{ "Credit Roll (Jordach's HD Mix)", "Junichi Masuda", "chirp" },
{ "Winter Feeling", "Tom Peter", "strad" },
{ "Synthgroove (Jordach's Mix)", "HeroOfTheWinds", "mellohi" },
{ "The Clueless Frog (Jordach's Mix)", "SoundHelix", "mall" },
}
local records = #recorddata
for r=1, records do
local doc = false
local entryname, longdesc, usagehelp
if r == 1 then
doc = true
entryname = S("Music Disc")
longdesc = S("A music disc holds a single music track which can be used in a jukebox to play music.")
usagehelp = S("Place a music disc into an empty jukebox to play the music. Use the jukebox again to retrieve the music disc. The music can only be heard by you, not by other players.")
end
minetest.register_craftitem("mcl_jukebox:record_"..r, {
function mcl_jukebox.register_record(title, author, identifier, image, sound)
mcl_jukebox.registered_records["mcl_jukebox:record_"..identifier] = {title, author, identifier, image, sound}
local entryname = S("Music Disc")
local longdesc = S("A music disc holds a single music track which can be used in a jukebox to play music.")
local usagehelp = S("Place a music disc into an empty jukebox to play the music. Use the jukebox again to retrieve the music disc. The music can only be heard by you, not by other players.")
minetest.register_craftitem(":mcl_jukebox:record_"..identifier, {
description =
core.colorize("#55FFFF", S("Music Disc")) .. "\n" ..
core.colorize("#989898", S("@1—@2", recorddata[r][2], recorddata[r][1])),
_doc_items_create_entry = doc,
core.colorize("#989898", S("@1—@2", author, title)),
_doc_items_create_entry = true,
_doc_items_entry_name = entryname,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
inventory_image = "mcl_jukebox_record_"..recorddata[r][3]..".png",
--inventory_image = "mcl_jukebox_record_"..recorddata[r][3]..".png",
inventory_image = image,
stack_max = 1,
groups = { music_record = r },
groups = { music_record = 1 },
})
end
local function now_playing(player, track_id)
local function now_playing(player, name)
local playername = player:get_player_name()
local hud = active_huds[playername]
local text = S("Now playing: @1—@2", recorddata[track_id][2], recorddata[track_id][1])
local text = S("Now playing: @1—@2", mcl_jukebox.registered_records[name][2], mcl_jukebox.registered_records[name][1])
if not hud_sequence_numbers[playername] then
hud_sequence_numbers[playername] = 1
@ -106,18 +92,20 @@ minetest.register_craft({
})
local play_record = function(pos, itemstack, player)
local record_id = minetest.get_item_group(itemstack:get_name(), "music_record")
if record_id ~= 0 then
local item_name = itemstack:get_name()
-- ensure the jukebox uses the new record names for old records
local name = minetest.registered_aliases[item_name] or item_name
if mcl_jukebox.registered_records[name] then
local cname = player:get_player_name()
if active_tracks[cname] ~= nil then
minetest.sound_stop(active_tracks[cname])
active_tracks[cname] = nil
end
active_tracks[cname] = minetest.sound_play("mcl_jukebox_track_"..record_id, {
active_tracks[cname] = minetest.sound_play(mcl_jukebox.registered_records[name][5], {
to_player = cname,
gain = 1,
})
now_playing(player, record_id)
now_playing(player, name)
return true
end
return false
@ -239,3 +227,22 @@ minetest.register_craft({
recipe = "mcl_jukebox:jukebox",
burntime = 15,
})
mcl_jukebox.register_record("The Evil Sister (Jordach's Mix)", "SoundHelix", "13", "mcl_jukebox_record_13.png", "mcl_jukebox_track_1")
mcl_jukebox.register_record("The Energetic Rat (Jordach's Mix)", "SoundHelix", "wait", "mcl_jukebox_record_wait.png", "mcl_jukebox_track_2")
mcl_jukebox.register_record("Eastern Feeling", "Jordach", "blocks", "mcl_jukebox_record_blocks.png", "mcl_jukebox_track_3")
mcl_jukebox.register_record("Minetest", "Jordach", "far", "mcl_jukebox_record_far.png", "mcl_jukebox_track_4")
mcl_jukebox.register_record("Credit Roll (Jordach's HD Mix)", "Junichi Masuda", "chirp", "mcl_jukebox_record_chirp.png", "mcl_jukebox_track_5")
mcl_jukebox.register_record("Winter Feeling", "Tom Peter", "strad", "mcl_jukebox_record_strad.png", "mcl_jukebox_track_6")
mcl_jukebox.register_record("Synthgroove (Jordach's Mix)", "HeroOfTheWinds", "mellohi", "mcl_jukebox_record_mellohi.png", "mcl_jukebox_track_7")
mcl_jukebox.register_record("The Clueless Frog (Jordach's Mix)", "SoundHelix", "mall", "mcl_jukebox_record_mall.png", "mcl_jukebox_track_8")
--add backward compatibility
minetest.register_alias("mcl_jukebox:record_1", "mcl_jukebox:record_13")
minetest.register_alias("mcl_jukebox:record_2", "mcl_jukebox:record_wait")
minetest.register_alias("mcl_jukebox:record_3", "mcl_jukebox:record_blocks")
minetest.register_alias("mcl_jukebox:record_4", "mcl_jukebox:record_far")
minetest.register_alias("mcl_jukebox:record_5", "mcl_jukebox:record_chirp")
minetest.register_alias("mcl_jukebox:record_6", "mcl_jukebox:record_strad")
minetest.register_alias("mcl_jukebox:record_7", "mcl_jukebox:record_mellohi")
minetest.register_alias("mcl_jukebox:record_8", "mcl_jukebox:record_mall")

View File

@ -43,13 +43,19 @@ end
-- Checks if player is still allowed to display the minimap
local function update_minimap(player)
local creative = minetest.is_creative_enabled(player:get_player_name())
local newstate=false
local oldstate=player:hud_get_flags().minimap
if creative or has_item_in_hotbar(player, "mcl_maps:filled_map") then
newstate=true
end
if oldstate ~= newstate then
if creative then
player:hud_set_flags({minimap = true, minimap_radar = true})
else
if has_item_in_hotbar(player, "mcl_maps:filled_map") then
player:hud_set_flags({minimap = true, minimap_radar = false})
else
player:hud_set_flags({minimap = false, minimap_radar = false})
player:hud_set_flags({minimap = newstate, minimap_radar = false})
end
end
end

View File

@ -130,6 +130,8 @@ function mcl_potions.register_arrow(name, desc, color, def)
end
ARROW_ENTITY.on_step = function(self, dtime)
self._time_in_air = self._time_in_air + dtime
local pos = self.object:get_pos()
local dpos = table.copy(pos) -- digital pos
dpos = vector.round(dpos)
@ -193,10 +195,10 @@ function mcl_potions.register_arrow(name, desc, color, def)
for k, obj in pairs(objs) do
local ok = false
-- Arrows can only damage players and mobs
if obj ~= self._shooter and obj:is_player() then
if obj:is_player() then
ok = true
elseif obj:get_luaentity() ~= nil then
if obj ~= self._shooter and obj:get_luaentity()._cmi_is_mob then
if obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile then
ok = true
end
end
@ -218,7 +220,7 @@ function mcl_potions.register_arrow(name, desc, color, def)
local obj = closest_object
local is_player = obj:is_player()
local lua = obj:get_luaentity()
if obj ~= self._shooter and (is_player or (lua and lua._cmi_is_mob)) then
if obj == self._shooter and self._time_in_air > 1 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
-- Check if there is no solid node between arrow and object
@ -256,9 +258,9 @@ function mcl_potions.register_arrow(name, desc, color, def)
end
if is_player then
if self._shooter and self._shooter:is_player() then
if self._shooter and self._shooter:is_player() and obj ~= self._shooter then
-- “Ding” sound for hitting another player
minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter}, true)
minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true)
end
end
@ -395,6 +397,7 @@ function mcl_potions.register_arrow(name, desc, color, def)
ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s)
local data = minetest.deserialize(staticdata)
self._time_in_air = dtime_s
if data then
self._stuck = data.stuck
if data.stuck then

View File

@ -1,4 +1,5 @@
local S = minetest.get_translator("mcl_tnt")
local tnt_drop_rate = tonumber(minetest.settings:get("mcl_tnt_drop_rate") or 1.0)
local tnt_griefing = minetest.settings:get_bool("mcl_tnt_griefing", true)
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
@ -180,7 +181,7 @@ function TNT:on_step(dtime)
self.blinkstatus = not self.blinkstatus
end
if self.timer > tnt.BOOMTIMER then
mcl_explosions.explode(self.object:get_pos(), 4, {}, self.object)
mcl_explosions.explode(self.object:get_pos(), 4, { drop_chance = tnt_drop_rate }, self.object)
self.object:remove()
end
end

View File

@ -232,10 +232,10 @@ if minetest.get_modpath("mcl_farming") then
local wear = mcl_autogroup.get_wear(toolname, "shearsy")
itemstack:add_wear(wear)
end
minetest.sound_play({name="default_grass_footstep", gain=1}, {pos = above}, true)
minetest.sound_play({name="default_grass_footstep", gain=1}, {pos = pointed_thing.above}, true)
local dir = vector.subtract(pointed_thing.under, pointed_thing.above)
local param2 = minetest.dir_to_facedir(dir)
minetest.swap_node(pointed_thing.under, {name="mcl_farming:pumpkin_face", param2 = param2})
minetest.set_node(pointed_thing.under, {name="mcl_farming:pumpkin_face", param2 = param2})
minetest.add_item(pointed_thing.above, "mcl_farming:pumpkin_seeds 4")
end
return itemstack
@ -351,6 +351,34 @@ minetest.register_tool("mcl_tools:shovel_diamond", {
})
-- Axes
local function make_stripped_trunk(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then return end
local node = minetest.get_node(pointed_thing.under)
local nodedef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
if not placer:get_player_control().sneak and nodedef.on_rightclick then
return minetest.item_place(itemstack, placer, pointed_thing)
end
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
minetest.record_protection_violation(pointed_thing.under, placer:get_player_name())
return itemstack
end
if nodedef._mcl_stripped_variant == nil then
return itemstack
else
minetest.swap_node(pointed_thing.under, {name=nodedef._mcl_stripped_variant, param2=node.param2})
if not minetest.is_creative_enabled(placer:get_player_name()) then
-- Add wear (as if digging a axey node)
local toolname = itemstack:get_name()
local wear = mcl_autogroup.get_wear(toolname, "axey")
itemstack:add_wear(wear)
end
end
return itemstack
end
minetest.register_tool("mcl_tools:axe_wood", {
description = S("Wooden Axe"),
_doc_items_longdesc = axe_longdesc,
@ -364,6 +392,7 @@ minetest.register_tool("mcl_tools:axe_wood", {
damage_groups = {fleshy=7},
punch_attack_uses = 30,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:wood",
_mcl_toollike_wield = true,
@ -383,6 +412,7 @@ minetest.register_tool("mcl_tools:axe_stone", {
damage_groups = {fleshy=9},
punch_attack_uses = 66,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
@ -403,6 +433,7 @@ minetest.register_tool("mcl_tools:axe_iron", {
damage_groups = {fleshy=9},
punch_attack_uses = 126,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
@ -422,6 +453,7 @@ minetest.register_tool("mcl_tools:axe_gold", {
damage_groups = {fleshy=7},
punch_attack_uses = 17,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
@ -441,6 +473,7 @@ minetest.register_tool("mcl_tools:axe_diamond", {
damage_groups = {fleshy=9},
punch_attack_uses = 781,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,

View File

@ -176,7 +176,7 @@ minetest.register_tool("screwdriver:screwdriver", {
description = S("Screwdriver"),
inventory_image = "screwdriver.png",
wield_image = "screwdriver.png^[transformFX",
groups = { tool = 1, not_in_creative_inventory = 1 },
groups = { tool = 1 },
on_use = function(itemstack, user, pointed_thing)
screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200)
return itemstack

View File

@ -0,0 +1 @@
name = screwdriver

View File

@ -3532,7 +3532,7 @@ local function register_decorations()
-- Pumpkin
minetest.register_decoration({
deco_type = "simple",
decoration = "mcl_farming:pumpkin_face",
decoration = "mcl_farming:pumpkin",
param2 = 0,
param2_max = 3,
place_on = {"group:grass_block_no_snow"},

View File

@ -868,7 +868,7 @@ local function register_mgv6_decorations()
-- Pumpkin
minetest.register_decoration({
deco_type = "simple",
decoration = "mcl_farming:pumpkin_face",
decoration = "mcl_farming:pumpkin",
param2 = 0,
param2_max = 3,
place_on = {"group:grass_block_no_snow"},

View File

@ -532,9 +532,24 @@ local function dir_to_rotation(dir)
return "0"
end
mcl_structures.generate_test_structure_comparator = function(pos, rotation, pr)
local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_test_structure_comparator.mts"
mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, nil, pr)
end
mcl_structures.generate_test_structure_fireproof = function(pos, rotation, pr)
local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_test_structure_fireproof.mts"
mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, nil, pr)
end
mcl_structures.generate_test_structure_tnt = function(pos, rotation, pr)
local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_test_structure_tnt.mts"
mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, nil, pr)
end
-- Debug command
minetest.register_chatcommand("spawnstruct", {
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine",
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | test_structure_comparator | test_structure_fireproof | test_structure_tnt",
description = S("Generate a pre-defined structure near your position."),
privs = {debug = true},
func = function(name, param)
@ -568,6 +583,12 @@ minetest.register_chatcommand("spawnstruct", {
mcl_structures.generate_end_exit_portal(pos, rot, pr)
elseif param == "end_portal_shrine" then
mcl_structures.generate_end_portal_shrine(pos, rot, pr)
elseif param == "test_structure_comparator" then
mcl_structures.generate_test_structure_comparator(pos, rot, pr)
elseif param == "test_structure_fireproof" then
mcl_structures.generate_test_structure_fireproof(pos, rot, pr)
elseif param == "test_structure_tnt" then
mcl_structures.generate_test_structure_tnt(pos, rot, pr)
elseif param == "" then
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
errord = true

View File

@ -51,10 +51,23 @@ function tsm_railcorridors.get_default_treasure(pr)
-- UNUSED IN MINECLONE 2!
end
-- All spawners spawn cave spiders
function tsm_railcorridors.on_construct_spawner(pos)
-- Almost all spawners spawn cave spiders, but there is a 1 in 1000
-- chance to spawn a pig spawner instead, inspired by multiple bugs
-- in Minecraft that turn spawners in Mineshafts into pig spawners.
-- (Basically any spawner bug in Minecraft generates pig spawners.)
--
-- The Minecraft chance to get a pig spawner here is way lower than
-- 1 in 1000, but because of the small size of Minetest worlds, the
-- Minecraft chance would risk not having a pig spawner in a world.
--
-- The world with the seed “pigs” generates a pig spawner at 3,-8,7
function tsm_railcorridors.on_construct_spawner(pos, pr)
if pr:next(1,1000) == 900 then
mcl_mobspawners.setup_spawner(pos, "mobs_mc:pig", 0, 7)
else
mcl_mobspawners.setup_spawner(pos, "mobs_mc:cave_spider", 0, 7)
end
end
-- MineClone 2's treasure function. Gets all treasures for a single chest.
-- Based on information from Minecraft Wiki.

View File

@ -114,7 +114,7 @@ if not tsm_railcorridors.nodes.corridor_woods_function then
end
-- Random Perlin noise generators
local pr, pr_carts, pr_treasures, pr_deco, webperlin_major, webperlin_minor
local pr, pr_carts, pr_spawner, pr_treasures, pr_deco, webperlin_major, webperlin_minor
local function InitRandomizer(seed)
-- Mostly used for corridor gen.
@ -123,6 +123,8 @@ local function InitRandomizer(seed)
pr_deco = PseudoRandom(seed+25)
-- Separate randomizer for carts because spawning carts is very timing-dependent
pr_carts = PseudoRandom(seed-654)
-- Spawner type randomiser
pr_spawner = PseudoRandom(seed+345)
-- Chest contents randomizer
pr_treasures = PseudoRandom(seed+777)
-- Used for cobweb generation, both noises have to reach a high value for cobwebs to appear
@ -751,7 +753,7 @@ local function create_corridor_section(waypoint, axis, sign, up_or_down, up_or_d
if place_cobwebs then
Cube(p, size, {name=tsm_railcorridors.nodes.cobweb}, true)
end
tsm_railcorridors.on_construct_spawner(p)
tsm_railcorridors.on_construct_spawner(p, pr_spawner)
no_spawner = true
end
end

View File

@ -0,0 +1,206 @@
local clamp = function(value, min, max)
assert( min < max )
if value < min then
return min
end
if value > max then
return max
end
return value
end
assert( clamp(000, -100, 100) == 000 )
assert( clamp(999, -100, 100) == 100 )
assert( clamp(999, -999, 999) == 999 )
assert( clamp(998, 999, 1999) == 999 )
assert( clamp(999, 999, 1999) == 999 )
local clamp_s16 = function(value)
-- seems minetest hangs on -32768 and 32767
return clamp(value, -32767, 32766)
end
assert( clamp_s16(000000) == 000000 )
assert( clamp_s16(000001) == 000001 )
assert( clamp_s16(000010) == 000010 )
assert( clamp_s16(000100) == 000100 )
assert( clamp_s16(001000) == 001000 )
assert( clamp_s16(010000) == 010000 )
assert( clamp_s16(100000) == 032766 )
assert( clamp_s16(-00000) == -00000 )
assert( clamp_s16(-00009) == -00009 )
assert( clamp_s16(-00099) == -00099 )
assert( clamp_s16(-00999) == -00999 )
assert( clamp_s16(-09999) == -09999 )
assert( clamp_s16(-99999) == -32767 )
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
minetest.find_nodes_in_area = function(minp, maxp, ...)
if
minp.x >= 32767 or minp.x <= -32768 or
minp.y >= 32767 or minp.y <= -32768 or
minp.z >= 32767 or minp.z <= -32768 or
maxp.x >= 32767 or maxp.x <= -32768 or
maxp.y >= 32767 or maxp.y <= -32768 or
maxp.z >= 32767 or maxp.z <= -32768
then
minetest.log(
"warning",
"find_nodes_in_area() called with coords outside interval (-32768, 32767), clamping arguments: " ..
"minp { x=" .. minp.x .. ", y=" .. minp.y .. " z=" .. minp.z .. " } " ..
"maxp { x=" .. maxp.x .. ", y=" .. maxp.y .. " z=" .. maxp.z .. " } "
)
return minetest_find_nodes_in_area(
{ x=clamp_s16(minp.x), y=clamp_s16(minp.y), z=clamp_s16(minp.z) },
{ x=clamp_s16(maxp.x), y=clamp_s16(maxp.y), z=clamp_s16(maxp.z) },
...
)
else
return minetest_find_nodes_in_area(
minp,
maxp,
...
)
end
end
deep_compare = function(a, b)
local type_a = type(a)
local type_b = type(b)
if type_a ~= type_b then
return false
end
if type_a ~= "table" and type_b ~= "table" then
return a == b
end
for key_a, value_a in pairs(a) do
local value_b = b[key_a]
if not deep_compare(value_a, value_b) then
return false
end
end
for key_b, value_b in pairs(b) do
local value_a = a[key_b]
if not deep_compare(value_b, value_a) then
return false
end
end
return true
end
assert(
deep_compare(
1,
1.0
) == true
)
assert(
deep_compare(
true,
"true"
) == false
)
assert(
deep_compare(
{ a=1, b=-2, c=3.4 },
{ a=1, b=-2, c=3.4 }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b="foo", c=false },
{ a={ 1, 2, 3 }, b="foo", c=false }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b="foo", c=false },
{ a={ 4, 5, 6 }, b="foo", c=false }
) == false
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b={ c=false } },
{ a={ 1, 2, 3 }, b={ c=false } }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b={ } },
{ a={ 1, 2, 3 }, b={ c=false } }
) == false
)
local test_minetest_find_nodes_in_area_implementation_equivalence = function()
-- If any assertion in this test function fails, the wrapper
-- for minetest.find_nodes_in_area() does not behave like the
-- original function. If you are reading the code because your
-- server crashed, please inform the Mineclonia developers.
local fun_1 = minetest_find_nodes_in_area
local fun_2 = minetest.find_nodes_in_area
for x = -31000, 31000, 15500 do
for y = -31000, 31000, 15500 do
for z = -31000, 31000, 15500 do
for d = 1, 9, 3 do
local minp = { x=x, y=y, z=z }
local maxp = { x=x+d, y=y+d, z=z+d }
minetest.emerge_area(
minp,
maxp,
function(blockpos, action, calls_remaining)
local npos_1, nnum_1 = fun_1(
minp,
maxp,
{ "air", "ignore" }
)
local npos_2, nnum_2 = fun_2(
minp,
maxp,
{ "air", "ignore" }
)
assert(
deep_compare(
npos_1,
npos_2
) == true
)
assert(
deep_compare(
nnum_1,
nnum_2
) == true
)
local ntab_1 = fun_1(
minp,
maxp,
{ "air", "ignore" },
true
)
local ntab_2 = fun_2(
minp,
maxp,
{ "air", "ignore" },
true
)
assert(
deep_compare(
ntab_1,
ntab_2
) == true
)
end
)
end
end
end
end
end
minetest.after( 0, test_minetest_find_nodes_in_area_implementation_equivalence )

View File

@ -0,0 +1 @@
name = mcl_engine_workarounds

View File

@ -0,0 +1,121 @@
local test_minetest_find_nodes_in_area_can_count = function(dtime)
-- This function tests that minetest.find_nodes_in_area() can
-- count nodes correctly. If it fails, the engine can not be
-- trusted to actually count how many nodes of a given type
-- are in a given volume. Yes, *it* is bad if that happens.
--
-- If you are looking at this function because it executes at
-- startup and crashes the game, by far the most stupid thing
-- you could do is disabling it. Only an absolute moron would
-- disable tests that ensure basic functionality still works.
--
-- Experience has taught me that such warnings are mostly not
-- taken seriously by both Minetest mod & core developers. As
-- there are very few situations in which someone would read
-- the code of the function without a crash, you are probably
-- asking yourself how bad it can be. Surely you will want an
-- example of what will break if this test breaks. The answer
-- to this simple question is equally simple and consists of a
-- heartfelt “What the fuck did you say, you stupid fuckwad?”.
--
-- Alrighty then, let's get it on …
local pos = { x=30999, y=30999, z=30999 }
-- You think there is nothing there? Well, here is the thing:
-- With standard settings you can only see map until x=30927,
-- although the renderer can actually render up to x=31007 if
-- you configure it to. Any statements given by minetest core
-- devs that contradict the above assertion are probably lies.
--
-- In any way, this area should be so far out that no one has
-- built here … yet. Now that you know it is possible, I know
-- you want to. How though? I suggest to figure the technique
-- out yourself, then go on and build invisible lag machines.
local radius = 3
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local nodename = "air"
local c_nodename = minetest.get_content_id(nodename)
-- Why not use minetest.set_node() here? Well, some mods do
-- trigger on every placement of a node in the entire map …
-- and we do not want to crash those mods in this test case.
-- (Voxelmanip does not trigger callbacks so all is well.)
--
-- And now for a funny story: I initially copied the following
-- code from the Minetest developer wiki. Can you spot a typo?
-- <https://dev.minetest.net/index.php?title=minetest.get_content_id&action=edit>
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(
minp,
maxp
)
local area = VoxelArea:new({
MinEdge=emin,
MaxEdge=emax
})
local data = vm:get_data()
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
local vi = area:index(minp.x, y, z)
for x = minp.x, maxp.y do
data[vi] = c_nodename
vi = vi + 1
end
end
end
vm:set_data(data)
vm:write_to_map()
local npos, nnum = minetest.find_nodes_in_area(
minp,
maxp,
{ nodename }
)
local nodes_expected = math.pow( 1 + (2 * radius), 3 )
local nodes_counted = nnum[nodename]
local nodes_difference = nodes_expected - nodes_counted
-- Originally, there was an assertion here that made the game
-- crash at startup if Minetest forgot how to count. This was
-- originally intended to avoid buggy engine releases, but it
-- mostly made people upset and hindered debugging. Also, the
-- assertion contained no error message hinting at the reason
-- for the crash, making it exceptionally user-unfriendly. It
-- follows that a game or mod should only assert on behaviour
-- of the Lua code, not the underlying implementation, unless
-- engine bugs are bad enough to permanently corrupt a world.
if ( 0 ~= nodes_difference ) then
minetest.debug(
"minetest.find_nodes_in_area() failed to find " ..
nodes_difference .. " nodes that were placed. " ..
"Downgrading to Minetest 5.4.1 might fix this."
)
end
end
minetest.after( 0, test_minetest_find_nodes_in_area_can_count )
local test_minetest_find_nodes_in_area_crash = function(dtime)
-- And now for our feature presentation, where we call the
-- function “minetest.find_nodes_in_area()” with a position
-- out of bounds! Will it crash? Who knows‽ If it does, the
-- workaround is not working though, so it should be patched.
local pos = { x=32767, y=32767, z=32767 }
-- Note that not all out of bounds values actually crash the
-- function minetest.find_nodes_in_area()“. In fact, the vast
-- majority of out of bounds values do not crash the function.
local radius = 3
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local nodename = "air"
local npos, nnum = minetest.find_nodes_in_area(
minp,
maxp,
{ nodename }
)
-- That's all, folks!
end
minetest.after( 0, test_minetest_find_nodes_in_area_crash )

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