Compare commits

...

108 Commits

Author SHA1 Message Date
the-real-herowl d79c6b5694 Reworked hammer crushing
- crushing is now done by digging with a hammer
- cobble is now crushable
2024-11-15 13:47:24 +01:00
the-real-herowl bfa2d4d11f Added spears 2024-11-15 13:47:24 +01:00
teknomunk e072a6c172 Resolve merge conflict 2024-11-15 13:47:24 +01:00
the-real-herowl b33f7974ad Added hammers 2024-11-15 13:47:24 +01:00
marro 4dc5d0939c Whitespace fix in translation (#4701)
Reviewed-on: VoxeLibre/VoxeLibre#4701
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: marro <marronclement0403@gmail.com>
Co-committed-by: marro <marronclement0403@gmail.com>
2024-11-11 03:49:43 +01:00
the-real-herowl 32b334322b Merge pull request 'Mobile fixes & improvements (cherry-pick from Mineclonia)' (#4685) from grorp/MineClone2:vl-mobile-fixes-and-improvements into master
Reviewed-on: VoxeLibre/VoxeLibre#4685
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
2024-11-11 01:44:27 +01:00
grorp 88c3c4558b Fix for VoxeLibre 2024-11-10 15:14:56 +01:00
grorp 3954acdfb7 Creative inventory: padding[-0.015,-0.015] on mobile
- less wasted screen space
- matches old layout
2024-11-10 15:14:56 +01:00
grorp 02b354f54a Avoid tab buttons going off-screen with high scaling values 2024-11-10 15:14:56 +01:00
grorp cb624fe1d9 Creative inventory: Make the whole tab button clickable
Previously, only the tab icon was clickable. Clicking next to the icon would
just close the inventory.
The icon is still kept clickable too since that gives a nicer press animation.
I didn't end up using image_button because that resulted in a different image
size and position, even with the exact same coordinates.
2024-11-10 15:14:56 +01:00
grorp bd9ab16762 Add touch_interaction to (cross)bow and spyglass 2024-11-10 15:14:56 +01:00
kno10 fb3c85e289 Improve stalker textures (#4674)
- don't change back to default texture when falling, but rather keep the previous texture
- use a colorized default texture for gaps in the texture

Reviewed-on: VoxeLibre/VoxeLibre#4674
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <erich.schubert@gmail.com>
Co-committed-by: kno10 <erich.schubert@gmail.com>
2024-11-10 12:02:20 +01:00
kno10 f6f5481f30 Attempt to fix chest minecarts, at least for 5.9 (#4684)
Not using the `RecheckCartHack` on >5.9 seems to help with #4670 - not tested on older minetest; chest minecarts might still be empty there when the block is unloaded in the meantime. For <5.9, maybe it helps to decrease the time interval, 3 seconds seems to fairly long.

This also makes the minecarts random: 40% minecart, 40% chest minecart, 20% tnt minecart.

Reviewed-on: VoxeLibre/VoxeLibre#4684
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <erich.schubert@gmail.com>
Co-committed-by: kno10 <erich.schubert@gmail.com>
2024-11-10 11:41:19 +01:00
the-real-herowl c428fa576b Merge pull request 'bonemeal API update' (#4221) from teknomunk/MineClone2:bonemeal-2 into master
Reviewed-on: VoxeLibre/VoxeLibre#4221
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
2024-11-10 11:38:08 +01:00
teknomunk a46833eaa4 Fix alias 2024-11-09 20:30:35 -06:00
teknomunk 3514fe211f Implement more bonemeal mod shim, update bonemeal dependencies 2024-11-09 20:30:35 -06:00
teknomunk 94d9e4c881 Address review comments 2024-11-09 20:30:35 -06:00
teknomunk 6b1aa43238 Only show particles if bone meal is consumed, don't continue testing positions if bonemeal was used on the first check position 2024-11-09 20:30:35 -06:00
teknomunk cfdef2435a Show particles regardless of success 2024-11-09 20:30:35 -06:00
teknomunk 49c8ae2fa0 Quick patch to get cherry saplings growing pending inclusing of a proper tree API 2024-11-09 20:30:33 -06:00
teknomunk 6ada1a3477 Remove check with mcl_core.check_vines_supported for twisted and crimson vines 2024-11-09 20:24:02 -06:00
teknomunk 189a2c62ad Address review comments on mcl_util.trace_nodes 2024-11-09 20:24:02 -06:00
teknomunk 981cddddd4 Add growth limits to crimson/twisting vines 2024-11-09 20:24:02 -06:00
teknomunk 66b5a369f1 Add mcl_util.trace_node(), rewrite bamboo growth code to fix bone meal growth 2024-11-09 20:24:02 -06:00
teknomunk 4eda77acd1 Prevent bonemealing grass from making flowers and also bonemealing the block above the grass 2024-11-09 20:24:02 -06:00
teknomunk afc270195a Fix crash when bonemealing weaping and twisting vines, fix weaping vine growth 2024-11-09 20:24:02 -06:00
teknomunk 8f53074b58 Reorder functions to prevent crash 2024-11-09 20:24:02 -06:00
teknomunk 70e8ba9a89 Remove TODO pending future discussions, revert timer change in composter code 2024-11-09 20:24:02 -06:00
teknomunk 6741c5a809 Make composter_progress_chance local, as it is not used anywhere except in mcl_composters 2024-11-09 20:24:02 -06:00
teknomunk d09791db7b Fix typo that prevented bone mealing pumpkin plants 2024-11-09 20:24:02 -06:00
teknomunk 354160e9e6 Check both above and below in pointed_thing for bonemealing (and pass thru the position as .under), make crimson vines and twisting vines compostable by rightclicking on the composter 2024-11-09 20:24:02 -06:00
teknomunk cf1325d466 Fix crash at one more spot 2024-11-09 20:24:02 -06:00
teknomunk 7112369917 Fix crashes when using bonemeal on nether nodes 2024-11-09 20:24:02 -06:00
teknomunk e6e13bdc67 Change _mcl_on_bonemealing to _on_bone_meal, update API.md to reflect this 2024-11-09 20:24:02 -06:00
teknomunk 42d37210c5 Fix mods/ITEMS/mcl_composters/locale/mcl_composters.ru.tr 2024-11-09 20:24:02 -06:00
teknomunk c3a33ea2c2 Update mod authors, remove a TODO 2024-11-09 20:24:02 -06:00
teknomunk 7f6d456a32 Remove bone to bone meal recipe from mcl_dye as it now resides in mcl_bone_meal 2024-11-09 20:24:02 -06:00
teknomunk 44d154f594 Modify backtrace listing to use minetest.log 2024-11-09 20:24:02 -06:00
teknomunk eb6131b037 Fix localization errors 2024-11-09 20:24:02 -06:00
teknomunk 3c2f2593db Only consume bone meal if a _mcl_on_bonemealing callback is defined or the legacy API returns true, convert vines to use new bonemeal API 2024-11-09 20:24:02 -06:00
teknomunk 9e6d49dd38 Fix localization except mcl_composters.ru.tr 2024-11-09 20:24:02 -06:00
teknomunk 4a865fa2df Enable bamboo bonemealing despite rightclick handling strangeness 2024-11-09 20:24:02 -06:00
teknomunk 55b4d3d5ee Rename localization files 2024-11-09 20:24:02 -06:00
teknomunk 09bcf3d22b Add untested bonemeal mod compatibility shim 2024-11-09 20:24:02 -06:00
teknomunk 57678e31bc Move commented out bamboo bone meal code into mods/ITEMS/mcl_bamboo/bamboo_base.lua 2024-11-09 20:24:02 -06:00
teknomunk d5684ca305 Add new API call mcl_bone_meal.use_bone_meal and use this to remove duplicate code, update mcl_farming:sweet_berries to use bonemeal API, add stub for bonemeal mod compatibility 2024-11-09 20:24:02 -06:00
teknomunk a4f1ccd0ee Update mcl_crimson to use bonemealing API 2024-11-09 20:24:02 -06:00
teknomunk 1e0f7618ba Remove bone meal definition in mcl_dye, make textures in mcl_cocoas match master branch 2024-11-09 20:24:02 -06:00
teknomunk f44102c238 Display call stack to assist in removing deprecated function calls 2024-11-09 20:24:02 -06:00
teknomunk 5b1fcf76f6 Fix mod dependencies 2024-11-09 20:24:02 -06:00
kabou f61a7ab4cb Remove color specifications from bone meal.
* The bone meal craftitem definition still had color specifications
  from its past as a dye substitute.  These can be removed now.
* Also remove default stack_max setting.
2024-11-09 20:24:02 -06:00
kabou 4449f74742 Remove color specifications from cocoa beans.
* The cocoa beans craftitem definition still had color specifications
  from its past as a dye substitute.  These can be removed now.
2024-11-09 20:24:02 -06:00
kabou ba1e0e4301 Also generate double grass when bonemealing grass blocks. 2024-11-09 20:24:02 -06:00
kabou 7938fba4a5 Remove expired bone meal API.md from mcl_dye. 2024-11-09 20:24:02 -06:00
kabou 8acddab74f Bonemealing mechanics bugfix.
When applying bonemeal to eg. farm crops, these have a chance to grow in
response to the application of bone meal. When a node can be bonemealed, the
applied bone meal item should always be spent after using it, regardless of
the results.  Currently this does not work correctly, if the result of
bonemealing has no effect on the node, the used bone meal item is not spent.

This commit fixes the behavior of the bone meal item to always be taken when
used on a node that defines a `_mcl_on_bonemealing()` callback.

The nodes that implement the callback imay use the handler's return value
only to signal if the bonemealing was succesful, not to signal if it was at
all possible.  For this reason, some nodes need to be made more strictly
conforming to the API.

* Always take the used bone meal item (if user is not in creative mode),
  regardless of whether the bonemealed node's handler returned `true`.
* Make dispensers spawn particles after succesful bonemealing.
* Trivial comment fix.
* Ripe cocoa pod cannot be bonemealed.
* Update API.md to describe the stricter API semantics.
2024-11-09 20:24:02 -06:00
kabou c2c7df820f Improve mcl_bone_meal fr translations.
* Changed the wording after suggestions by AFCMS.
2024-11-09 20:24:02 -06:00
kabou e5cf4bd225 Add missing es translation to mcl_bone_meal. 2024-11-09 20:24:02 -06:00
kabou 810051c591 Move cocoa beans item to mcl_cocoas.
* Add `mcl_cocoas:coca_beans` craftitem to mcl_cocoas.
* Remove `mcl_dye:brown` craftitem from mcl_dye.
* Move cocoa beans translations from mcl_dye to mcl_cocoas.
* Add `mcl_dye:brown` alias for `mcl_cocoas:cocoa_beans` to
  mcl_dye.
* Abstract cocoa pod node registration into a loop.
* Update chocolate cookies crafting recipe in mcl_farming.
2024-11-09 20:24:02 -06:00
kabou ae56a864d0 Remove stray line from locale template.
* Removed a line from the mcl_bone_meal locale template that had by
  accident put there during the bone meal <-> white dye changes.
2024-11-09 20:24:02 -06:00
kabou 7ddcf3f93f Use better override mechanism.
* Use `minetest.override_item()` instead of re-registering the node with
  ":" prefixed to its name.  Thanks again to wsor for mentioning this.
2024-11-09 20:24:02 -06:00
kabou e8d965e21a Add more particles when bonemealing grass.
* Bonemealing dirt_with_grass spawns new growth over a wide area, so it
  looks better if we spawn a few more extra bone meal particles.
* Update mod.conf depends to mcl_bone_meal.
2024-11-09 20:24:02 -06:00
kabou 8855246dd4 Update to new bone meal API.
* Update to use new mcl_bone_meal API:
* Use new bone meal item and remove related comment.
* Update mod depends in mod.conf
* Spelling fixes: s/bonemeal/bone meal/g
2024-11-09 20:24:02 -06:00
kabou 3889abbaf4 Add mcl_bone_meal.
* New mod mcl_bone_meal, replacing bone meal functionality previously
  held in mcl_dye.
* Improve bonemealing API using callbacks in the nodes that support
  bonemealing.
* Rename bone meal item to `"mcl_bone_meal:bone_meal"` and updated its
  crafting recipe.
* Implement legacy compatibility for older bone meal API.
* Remove all non dye-related bone meal code, texture and translations from
  mcl_dye.
* Add legacy compatibility shims to mcl_dye that refer to mcl_bone_meal.
* Add an alias for "mcl_dye:white" to keep mcl_dye and its API working
  uniterrupted.
* Update mod depends in mcl_dye mod.conf.
2024-11-09 20:24:02 -06:00
kabou f6235e8e92 Add bonemealing callback for fern.
* Adds a _mcl_on_bonemealing callback to fern.
2024-11-09 20:24:02 -06:00
kabou 2190080832 Add bonemealing callback for tall grass.
* Adds a _mcl_on_bonemealing callback to tall grass.
2024-11-09 20:24:02 -06:00
kabou ea1d52baab Add bonemealing callback for double flowers.
* Adds a _mcl_on_bonemealing callback to the double flowers.
2024-11-09 20:24:02 -06:00
kabou fdc7f4634d Add bonemealing callback for dirt with grass.
* Add new file mcl_flowers/bonemeal.lua, containing the bonemealing
  callback for "mcl_core:dirt_with_grass".
* Override "mcl_core:dirt_with_grass" with a _mcl_on_bonemealing handler
  calling a function defined in mcl_flowers. This sidesteps the problem
  that bonemealing a node from mcl_core needs knowledge of mcl_flowers,
  which would create a circular dependency.  H/t to cora for suggesting
  this solution. H/t to wsor for suggesting a solution that also works.
2024-11-09 20:24:02 -06:00
kabou bde0d9b238 Add bonemealing callback to cocoa.
* Adds a _mcl_on_bonemealing callback to the unripe cocoa pods.
2024-11-09 20:24:02 -06:00
teknomunk f644d37332 Keep same selection box size 2024-11-09 20:24:02 -06:00
kabou 17f2d85de9 Refactor beetroots and add bonemealing callback.
* Abstract unripe beetroot plant node registrations into a single
  indexed definition and do the registration in a loop.
* Adds a _mcl_on_bonemealing callback to the unripe melon plants.
2024-11-09 20:24:02 -06:00
kabou d07e8d9536 Add bonemealing callback to melons.
* Adds a _mcl_on_bonemealing callback to the unripe melon plants.
2024-11-09 20:24:02 -06:00
kabou 5d2fa8072a Add bonemealing callback to pumpkins.
* Adds a _mcl_on_bonemealing callback to the unripe pumpkin plants.
2024-11-09 20:24:02 -06:00
kabou 2d8bb12fad Add bonemealing callback to carrots.
* Adds a _mcl_on_bonemealing callback to the unripe carrot plants.
2024-11-09 20:24:02 -06:00
kabou 69032c3222 Add bonemealing callback to potatoes.
* Adds a _mcl_on_bonemealing callback to the unripe potato plants.
2024-11-09 20:24:02 -06:00
kabou 71e6fa9646 Add bonemealing callback to wheat.
* Adds a _mcl_on_bonemealing callback to the unripe wheat node definitions.
2024-11-09 20:24:02 -06:00
kabou 9ea52ce9b3 Add bonemealing callback to small mushrooms.
* Adds a _mcl_on_bonemealing callback to the mushroom node definitions.
2024-11-09 20:24:02 -06:00
kabou 0422635047 Add bonemealing callback to saplings.
* Adds a _mcl_on_bonemealing callback to the sapling node definitions.
2024-11-09 20:24:02 -06:00
kno10 b540e6c77b Improve head swivel code (#4622)
* Utilize the minetest 5.9.0 API that uses radians not degree.
* Simplify computations to make this more efficient, in particular by querying and updating the bone position less frequently.
* Resolves minetest warning `Deprecated call to set_bone_position, use set_bone_override instead` in this location, but other uses remain.
* `mcl_util.set_bone_position` not modified, because it redundantly compares to the previous rotation once more.

Reviewed-on: VoxeLibre/VoxeLibre#4622
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <erich.schubert@gmail.com>
Co-committed-by: kno10 <erich.schubert@gmail.com>
2024-11-10 02:41:55 +01:00
kno10 d49426d453 Cleanup of mcl_core/functions (#4592)
Cleanup of mods/ITEMS/mcl_core/functions.lua

This improves several further ABMs such as vine growing, and uses the `vector` API instead of tables.

Reviewed-on: VoxeLibre/VoxeLibre#4592
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <erich.schubert@gmail.com>
Co-committed-by: kno10 <erich.schubert@gmail.com>
2024-11-10 02:32:51 +01:00
the-real-herowl 2b7b7f1872 Merge pull request 'Improve plant growth system, add moisture level' (#4681) from kno10/VoxeLibre:pumpkin-melon-growth-1 into master
Reviewed-on: VoxeLibre/VoxeLibre#4681
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
2024-11-10 02:11:37 +01:00
kno10 b5afa34469 Remove "wet" metadata altogether 2024-11-10 02:11:37 +01:00
kno10 ebf6cf32e8 meta:set_private("wet"), require only walkable nodes 2024-11-10 02:11:37 +01:00
kno10 a8318f6600 simplify catch-up LBM logic 2024-11-10 02:11:37 +01:00
kno10 fa7a7f4e81 more fixes to plant growth 2024-11-10 02:11:37 +01:00
kno10 c097c65262 adjust growth rates again 2024-11-10 02:11:37 +01:00
kno10 220a7b06e6 code review feedback 2024-11-10 02:11:37 +01:00
kno10 540a070c59 always use day light level, more fixes 2024-11-10 02:11:37 +01:00
kno10 78a958db4e Double the odds, to halve the ABM frequencies. 2024-11-10 02:11:37 +01:00
kno10 e9453d6210 Add plant growth speed option, drop average light level
Closes: #4683 by removal
2024-11-10 02:11:37 +01:00
kno10 9376cf92b1 Adjust growth speeds 2024-11-10 02:11:37 +01:00
kno10 c4030115c4 improve moisture logic 2024-11-10 02:11:37 +01:00
kno10 e1ace4ad01 pumpkin/melon growth only tests one neighbor every time 2024-11-10 02:11:37 +01:00
the-real-herowl e3b7847df1 Merge pull request 'Shield improvements and bugfixes (fixes #2756)' (#4582) from shieldy_shields into master
Reviewed-on: VoxeLibre/VoxeLibre#4582
Reviewed-by: kno10 <kno10@noreply.git.minetest.land>
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
2024-11-10 01:34:50 +01:00
Mikita Wiśniewski f86a641dfa Improve shield block code and unhardcode offhand group 2024-11-10 01:34:50 +01:00
Mikita Wiśniewski 084741b733 Fix using shield on unknown nodes and cleanup 2024-11-10 01:34:50 +01:00
Mikita Wiśniewski d5bc0613d8 Make node itemstack check in mcl_shields less hacky 2024-11-10 01:34:50 +01:00
Loveaabb f26c34e65f Bugfix: Shield fails to block arrows 2024-11-10 01:34:50 +01:00
Loveaabb 04e29c5796 Several improvements to the Shield 2024-11-10 01:34:50 +01:00
Elias Åström 45ae170447 Deduplicate shield slowdown removal code 2024-11-10 01:34:50 +01:00
Elias Åström d0d1217dec Remove unused code in mcl_privs 2024-11-10 01:34:50 +01:00
Elias Åström cffc8e0145 Fix loosing interact bug in mcl_shields 2024-11-10 01:34:50 +01:00
the-real-herowl b136cbf9bb Changed bamboo cap drawtype (#4658)
Reviewed-on: VoxeLibre/VoxeLibre#4658
Co-authored-by: the-real-herowl <wiktor_t-i@proton.me>
Co-committed-by: the-real-herowl <wiktor_t-i@proton.me>
2024-11-02 21:04:00 +01:00
the-real-herowl e6d8d840db Merge pull request 'Fix missing protection checks in smithing tables' (#4659) from smithing_table_patch into master
Reviewed-on: VoxeLibre/VoxeLibre#4659
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
2024-11-02 21:00:19 +01:00
Mikita Wiśniewski 78125f425a Fix taking items out of protected smithing tables 2024-11-02 21:00:19 +01:00
cora cb1999414b Fix putting items in protected smithing tables 2024-11-02 21:00:19 +01:00
Mikita Wiśniewski 41b188caea Remove "double drop" mechanics for bamboo (fixes #4514) (#4642)
Reviewed-on: VoxeLibre/VoxeLibre#4642
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: Mikita Wiśniewski <rudzik8@protonmail.com>
Co-committed-by: Mikita Wiśniewski <rudzik8@protonmail.com>
2024-10-27 14:16:06 +01:00
kno10 ae7995d195 Fix axolotl attacking water mobs (#4675)
Also avoid jumping out of the water closes #4644

Reviewed-on: VoxeLibre/VoxeLibre#4675
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <kno10@noreply.git.minetest.land>
Co-committed-by: kno10 <kno10@noreply.git.minetest.land>
2024-10-27 14:10:11 +01:00
kno10 e293cbe631 Better handling of touching_ground for bouncing on beds (#4689)
Reviewed-on: VoxeLibre/VoxeLibre#4689
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
Co-authored-by: kno10 <erich.schubert@gmail.com>
Co-committed-by: kno10 <erich.schubert@gmail.com>
2024-10-27 14:03:50 +01:00
101 changed files with 2633 additions and 1821 deletions

View File

@ -1131,3 +1131,25 @@ if not vector.in_area then
(pos.z >= min.z) and (pos.z <= max.z) (pos.z >= min.z) and (pos.z <= max.z)
end end
end end
-- Traces along a line of nodes vertically to find the next possition that isn't an allowed node
---@param pos The position to start tracing from
---@param dir The direction to trace in. 1 is up, -1 is down, all other values are not allowed.
---@param allowed_nodes A set of node names to trace along.
---@param limit The maximum number of steps to make. Defaults to 16 if nil or missing
---@return Three return values:
--- the position of the next node that isn't allowed or nil if no such node was found,
--- the distance from the start where that node was found,
--- the node table if a node was found
function mcl_util.trace_nodes(pos, dir, allowed_nodes, limit)
if (dir ~= -1) and (dir ~= 1) then return nil, 0, nil end
limit = limit or 16
for i = 1,limit do
pos = vector.offset(pos, 0, dir, 0)
local node = minetest.get_node(pos)
if not allowed_nodes[node.name] then return pos, i, node end
end
return nil, limit, nil
end

View File

@ -318,6 +318,12 @@ function minetest.handle_node_drops(pos, drops, digger)
end end
end end
-- Special node drops (crushing) when digging with a hammer
local hammer = tooldef.groups.hammer
if hammer and hammer > 0 and nodedef._vl_crushing_drop then
drops = nodedef._vl_crushing_drop
end
if tool and nodedef._mcl_fortune_drop and enchantments.fortune then if tool and nodedef._mcl_fortune_drop and enchantments.fortune then
local fortune_level = enchantments.fortune local fortune_level = enchantments.fortune
local fortune_drop = nodedef._mcl_fortune_drop local fortune_drop = nodedef._mcl_fortune_drop

View File

@ -522,10 +522,11 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir)
local is_player = hitter:is_player() local is_player = hitter:is_player()
local mob_pos = self.object:get_pos() local mob_pos = self.object:get_pos()
local player_pos = hitter:get_pos() local player_pos = hitter:get_pos()
local weapon = hitter:get_wielded_item()
if is_player then if is_player then
-- is mob out of reach? -- is mob out of reach?
if vector.distance(mob_pos, player_pos) > 3 then if vector.distance(mob_pos, player_pos) > (weapon:get_definition().range or 3) then
return return
end end
-- is mob protected? -- is mob protected?
@ -572,7 +573,6 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir)
-- punch interval -- punch interval
local weapon = hitter:get_wielded_item()
local punch_interval = 1.4 local punch_interval = 1.4
-- exhaust attacker -- exhaust attacker
@ -733,6 +733,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir)
if hitter and is_player then if hitter and is_player then
local wielditem = hitter:get_wielded_item() local wielditem = hitter:get_wielded_item()
kb = kb + 9 * mcl_enchanting.get_enchantment(wielditem, "knockback") kb = kb + 9 * mcl_enchanting.get_enchantment(wielditem, "knockback")
kb = kb + 9 * minetest.get_item_group(wielditem:get_name(), "hammer")
-- add player velocity to mob knockback -- add player velocity to mob knockback
local hv = hitter:get_velocity() local hv = hitter:get_velocity()
local dir_dot = (hv.x * dir.x) + (hv.z * dir.z) local dir_dot = (hv.x * dir.x) + (hv.z * dir.z)

View File

@ -5,6 +5,7 @@ local validate_vector = mcl_util.validate_vector
local active_particlespawners = {} local active_particlespawners = {}
local disable_blood = minetest.settings:get_bool("mobs_disable_blood") local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
local DEFAULT_FALL_SPEED = -9.81*1.5 local DEFAULT_FALL_SPEED = -9.81*1.5
local PI_THIRD = math.pi / 3 -- 60 degrees
local PATHFINDING = "gowp" local PATHFINDING = "gowp"
@ -294,86 +295,66 @@ function mcl_mobs:set_animation(self, anim)
self:set_animation(anim) self:set_animation(anim)
end end
local function dir_to_pitch(dir)
--local dir2 = vector.normalize(dir)
local xz = math.abs(dir.x) + math.abs(dir.z)
return -math.atan2(-dir.y, xz)
end
local function who_are_you_looking_at (self, dtime) local function who_are_you_looking_at (self, dtime)
local pos = self.object:get_pos() if self.order == "sleep" then
self._locked_object = nil
return
end
local stop_look_at_player_chance = math.random(833/self.curiosity)
-- was 10000 - div by 12 for avg entities as outside loop -- was 10000 - div by 12 for avg entities as outside loop
local stop_look_at_player = math.random() * 833 <= self.curiosity
local stop_look_at_player = stop_look_at_player_chance == 1
if self.attack then if self.attack then
if not self.target_time_lost then self._locked_object = not self.target_time_lost and self.attack or nil
self._locked_object = self.attack
else
self._locked_object = nil
end
elseif self.following then elseif self.following then
self._locked_object = self.following self._locked_object = self.following
elseif self._locked_object then elseif self._locked_object then
if stop_look_at_player then if stop_look_at_player then self._locked_object = nil end
--minetest.log("Stop look: ".. self.name)
self._locked_object = nil
end
elseif not self._locked_object then elseif not self._locked_object then
if mcl_util.check_dtime_timer(self, dtime, "step_look_for_someone", 0.2) then if mcl_util.check_dtime_timer(self, dtime, "step_look_for_someone", 0.2) then
--minetest.log("Change look check: ".. self.name) local pos = self.object:get_pos()
-- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates.
-- but frequency of check isn't good as it is costly. Making others too infrequent requires testing
local chance = 150/self.curiosity
if chance < 1 then chance = 1 end
local look_at_player_chance = math.random(chance)
-- was 5000 but called in loop based on entities. so div by 12 as estimate avg of entities found,
-- then div by 20 as less freq lookup
local look_at_player = look_at_player_chance == 1
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 8)) do for _, obj in pairs(minetest.get_objects_inside_radius(pos, 8)) do
if obj:is_player() and vector.distance(pos,obj:get_pos()) < 4 then if obj:is_player() and vector.distance(pos, obj:get_pos()) < 4 then
--minetest.log("Change look to player: ".. self.name)
self._locked_object = obj self._locked_object = obj
break break
elseif obj:is_player() or (obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity()) then elseif obj:is_player() or (obj:get_luaentity() and self ~= obj:get_luaentity() and obj:get_luaentity().name == self.name) then
if look_at_player then -- For the wither this was 20/60=0.33, so probably need to rebalance and divide rates.
--minetest.log("Change look to mob: ".. self.name) -- but frequency of check isn't good as it is costly. Making others too infrequent requires testing
-- was 5000 but called in loop based on entities. so div by 12 as estimate avg of entities found,
-- then div by 20 as less freq lookup
if math.random() * 150 <= self.curiosity then
self._locked_object = obj self._locked_object = obj
break break
end end
end end
end end
end end
end end
end end
function mob_class:check_head_swivel(dtime) function mob_class:check_head_swivel(dtime)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
who_are_you_looking_at(self, dtime)
who_are_you_looking_at (self, dtime) local newr, oldp, oldr = vector.zero(), nil, nil
if self.object.get_bone_override then -- minetest >= 5.9
local ov = self.object:get_bone_override(self.head_swivel)
oldp, oldr = ov.position.vec, ov.rotation.vec
else -- minetest < 5.9
oldp, oldr = self.object:get_bone_position(self.head_swivel)
oldr = vector.apply(oldr, math.rad) -- old API uses radians
end
local final_rotation = vector.zero() local locked_object = self._locked_object
local oldp,oldr = self.object:get_bone_position(self.head_swivel) if locked_object and (locked_object:is_player() or locked_object:get_luaentity()) and locked_object:get_hp() > 0 then
if self._locked_object and (self._locked_object:is_player() or self._locked_object:get_luaentity()) and self._locked_object:get_hp() > 0 then
local _locked_object_eye_height = 1.5 local _locked_object_eye_height = 1.5
if self._locked_object:get_luaentity() then if locked_object:is_player() then
_locked_object_eye_height = self._locked_object:get_luaentity().head_eye_height _locked_object_eye_height = locked_object:get_properties().eye_height
end elseif locked_object:get_luaentity() then
if self._locked_object:is_player() then _locked_object_eye_height = locked_object:get_luaentity().head_eye_height
_locked_object_eye_height = self._locked_object:get_properties().eye_height
end end
if _locked_object_eye_height then if _locked_object_eye_height then
local self_rot = self.object:get_rotation() local self_rot = self.object:get_rotation()
-- If a mob is attached, should we really be messing with what they are looking at? -- If a mob is attached, should we really be messing with what they are looking at?
-- Should this be excluded? -- Should this be excluded?
@ -381,40 +362,48 @@ function mob_class:check_head_swivel(dtime)
self_rot = self.object:get_attach():get_rotation() self_rot = self.object:get_attach():get_rotation()
end end
local player_pos = self._locked_object:get_pos() local ps = self.object:get_pos()
local direction_player = vector.direction(vector.add(self.object:get_pos(), vector.new(0, self.head_eye_height*.7, 0)), vector.add(player_pos, vector.new(0, _locked_object_eye_height, 0))) ps.y = ps.y + self.head_eye_height * .7
local mob_yaw = math.deg(-(-(self_rot.y)-(-minetest.dir_to_yaw(direction_player))))+self.head_yaw_offset local pt = locked_object:get_pos()
local mob_pitch = math.deg(-dir_to_pitch(direction_player))*self.head_pitch_multiplier pt.y = pt.y + _locked_object_eye_height
local dir = vector.direction(ps, pt)
local mob_yaw = self_rot.y + math.atan2(dir.x, dir.z) + self.head_yaw_offset
local mob_pitch = math.asin(-dir.y) * self.head_pitch_multiplier
if (mob_yaw < -60 or mob_yaw > 60) and not (self.attack and self.state == "attack" and not self.runaway) then if (mob_yaw < -PI_THIRD or mob_yaw > PI_THIRD) and not (self.attack and self.state == "attack" and not self.runaway) then
final_rotation = vector.multiply(oldr, 0.9) newr = vector.multiply(oldr, 0.9)
elseif self.attack and self.state == "attack" and not self.runaway then elseif self.attack and self.state == "attack" and not self.runaway then
if self.head_yaw == "y" then if self.head_yaw == "y" then
final_rotation = vector.new(mob_pitch, mob_yaw, 0) newr = vector.new(mob_pitch, mob_yaw, 0)
elseif self.head_yaw == "z" then elseif self.head_yaw == "z" then
final_rotation = vector.new(mob_pitch, 0, -mob_yaw) newr = vector.new(mob_pitch, 0, -mob_yaw)
end end
else else
if self.head_yaw == "y" then if self.head_yaw == "y" then
final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, ((mob_yaw-oldr.y)*.3)+oldr.y, 0) newr = vector.new((mob_pitch-oldr.x)*.3+oldr.x, (mob_yaw-oldr.y)*.3+oldr.y, 0)
elseif self.head_yaw == "z" then elseif self.head_yaw == "z" then
final_rotation = vector.new(((mob_pitch-oldr.x)*.3)+oldr.x, 0, -(((mob_yaw-oldr.y)*.3)+oldr.y)*3) newr = vector.new((mob_pitch-oldr.x)*.3+oldr.x, 0, ((mob_yaw-oldr.y)*.3+oldr.y)*-3)
end end
end end
end end
elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then elseif not locked_object and math.abs(oldr.y) > 0.05 and math.abs(oldr.x) < 0.05 then
final_rotation = vector.multiply(oldr, 0.9) newr = vector.multiply(oldr, 0.9)
else
--final_rotation = vector.new(0,0,0)
end end
mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horizontal_head_height), final_rotation) -- 0.02 is about 1.14 degrees tolerance, to update less often
local newp = vector.new(0, self.bone_eye_height, self.horizontal_head_height)
if math.abs(oldr.x-newr.x) + math.abs(oldr.y-newr.y) + math.abs(oldr.z-newr.z) < 0.02 and vector.equals(oldp, newp) then return end
if self.object.get_bone_override then -- minetest >= 5.9
self.object:set_bone_override(self.head_swivel, {
position = { vec = newp, absolute = true },
rotation = { vec = newr, absolute = true } })
else -- minetest < 5.9
-- old API uses degrees not radians
self.object:set_bone_position(self.head_swivel, newp, vector.apply(newr, math.deg))
end
end end
function mob_class:set_animation_speed() function mob_class:set_animation_speed()
local v = self.object:get_velocity() local v = self.object:get_velocity()
if v then if v then

View File

@ -141,7 +141,7 @@ function mcl_mobs.register_mob(name, def)
local final_def = { local final_def = {
use_texture_alpha = def.use_texture_alpha, use_texture_alpha = def.use_texture_alpha,
head_swivel = def.head_swivel or nil, -- bool to activate this function head_swivel = def.head_swivel or nil, -- bool to activate this function
head_yaw_offset = def.head_yaw_offset or 0, -- for wonkey model bones head_yaw_offset = math.rad(def.head_yaw_offset or 0), -- for wonkey model bones
head_pitch_multiplier = def.head_pitch_multiplier or 1, --for inverted pitch head_pitch_multiplier = def.head_pitch_multiplier or 1, --for inverted pitch
bone_eye_height = def.bone_eye_height or 1.4, -- head bone offset bone_eye_height = def.bone_eye_height or 1.4, -- head bone offset
head_eye_height = def.head_eye_height or def.bone_eye_height or 0, -- how hight aproximatly the mobs head is fromm the ground to tell the mob how high to look up at the player head_eye_height = def.head_eye_height or def.bone_eye_height or 0, -- how hight aproximatly the mobs head is fromm the ground to tell the mob how high to look up at the player

View File

@ -928,8 +928,6 @@ end
-- falling and fall damage -- falling and fall damage
-- returns true if mob died -- returns true if mob died
function mob_class:falling(pos, moveresult) function mob_class:falling(pos, moveresult)
if moveresult and moveresult.touching_ground then return false end
if self.fly and self.state ~= "die" then if self.fly and self.state ~= "die" then
return return
end end
@ -952,7 +950,13 @@ function mob_class:falling(pos, moveresult)
new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0) new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0)
elseif v.y <= 0 and v.y > self.fall_speed then elseif v.y <= 0 and v.y > self.fall_speed then
-- fall downwards at set speed -- fall downwards at set speed
new_acceleration = vector.new(0, self.fall_speed, 0) if moveresult and moveresult.touching_ground then
-- when touching ground, retain a minimal gravity to keep the touching_ground flag
-- but also to not get upwards acceleration with large dtime when on bouncy ground
new_acceleration = vector.new(0, self.fall_speed * 0.01, 0)
else
new_acceleration = vector.new(0, self.fall_speed, 0)
end
else else
-- stop accelerating once max fall speed hit -- stop accelerating once max fall speed hit
new_acceleration =vector.zero() new_acceleration =vector.zero()

View File

@ -72,18 +72,24 @@ local axolotl = {
fly = true, fly = true,
fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" }, fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" },
breathes_in_water = true, breathes_in_water = true,
jump = true, jump = false, -- would get them out of the water too often
damage = 2, damage = 2,
reach = 2, reach = 2,
attack_type = "dogfight", attack_type = "dogfight",
attack_animals = true, attack_animals = true,
specific_attack = { specific_attack = {
"extra_mobs_cod", "mobs_mc:cod",
"extra_mobs_glow_squid", "mobs_mc:glow_squid",
"extra_mobs_salmon", "mobs_mc:salmon",
"extra_mobs_tropical_fish", "mobs_mc:tropical_fish",
"mobs_mc_squid" "mobs_mc:squid",
}, "mobs_mc:zombie", -- todo: only drowned?
"mobs_mc:baby_zombie",
"mobs_mc:husk",
"mobs_mc:baby_husk",
"mobs_mc:guardian_elder",
"mobs_mc:guardian",
},
runaway = true, runaway = true,
} }

View File

@ -7,12 +7,13 @@ local S = minetest.get_translator("mobs_mc")
--################### --###################
local function get_texture(self) local function get_texture(self, prev)
local on_name = self.standing_on local standing_on = minetest.registered_nodes[self.standing_on]
-- TODO: we do not have access to param2 here (color palette index) yet
local texture local texture
local texture_suff = "" local texture_suff = ""
if on_name and on_name ~= "air" then if standing_on and (standing_on.walkable or standing_on.groups.liquid) then
local tiles = minetest.registered_nodes[on_name].tiles local tiles = standing_on.tiles
if tiles then if tiles then
local tile = tiles[1] local tile = tiles[1]
local color local color
@ -25,7 +26,7 @@ local function get_texture(self)
texture = tile texture = tile
end end
if not color then if not color then
color = minetest.colorspec_to_colorstring(minetest.registered_nodes[on_name].color) color = minetest.colorspec_to_colorstring(standing_on.color)
end end
if color then if color then
texture_suff = "^[multiply:" .. color .. "^[hsl:0:0:20" texture_suff = "^[multiply:" .. color .. "^[hsl:0:0:20"
@ -33,14 +34,19 @@ local function get_texture(self)
end end
end end
if not texture or texture == "" then if not texture or texture == "" then
-- try to keep last texture when, e.g., falling
if prev and (not (not self.attack)) == (string.find(prev, "vl_mobs_stalker_overlay_angry.png") ~= nil) then
return prev
end
texture = "vl_stalker_default.png" texture = "vl_stalker_default.png"
end
texture = texture:gsub("([\\^:\\[])","\\%1") -- escape texture modifiers
texture = "([combine:16x24:0,0=(" .. texture .. "):0,16=(" .. texture ..")".. texture_suff
if self.attack then
texture = texture .. ")^vl_mobs_stalker_overlay_angry.png"
else else
texture = texture .. ")^vl_mobs_stalker_overlay.png" texture = texture:gsub("([\\^:\\[])", "\\%1") -- escape texture modifiers
texture = "(vl_stalker_default.png^[combine:16x24:0,0=(" .. texture .. "):0,16=(" .. texture .. ")" .. texture_suff .. ")"
end
if self.attack then
texture = texture .. "^vl_mobs_stalker_overlay_angry.png"
else
texture = texture .. "^vl_mobs_stalker_overlay.png"
end end
return texture return texture
end end
@ -132,7 +138,7 @@ mcl_mobs.register_mob("mobs_mc:stalker", {
self:boom(mcl_util.get_object_center(self.object), self.explosion_strength) self:boom(mcl_util.get_object_center(self.object), self.explosion_strength)
end end
end end
local new_texture = get_texture(self) local new_texture = get_texture(self, self._stalker_texture)
if self._stalker_texture ~= new_texture then if self._stalker_texture ~= new_texture then
self.object:set_properties({textures={new_texture, "mobs_mc_empty.png"}}) self.object:set_properties({textures={new_texture, "mobs_mc_empty.png"}})
self._stalker_texture = new_texture self._stalker_texture = new_texture

View File

@ -418,6 +418,18 @@ minetest.register_on_joinplayer(function(player)
end end
end) end)
---@param player mt.PlayerObjectRef
local function is_touch_enabled(playername)
-- Minetest < 5.7.0 support
if not minetest.get_player_window_information then
return false
end
local window = minetest.get_player_window_information(playername)
-- Always return a boolean (not nil) to avoid false-negatives when
-- comparing to a boolean later.
return window and window.touch_controls or false
end
---@param player mt.PlayerObjectRef ---@param player mt.PlayerObjectRef
function mcl_inventory.set_creative_formspec(player) function mcl_inventory.set_creative_formspec(player)
local playername = player:get_player_name() local playername = player:get_player_name()
@ -566,8 +578,10 @@ function mcl_inventory.set_creative_formspec(player)
bg_img = "crafting_creative_inactive" .. button_bg_postfix[this_tab] .. ".png" bg_img = "crafting_creative_inactive" .. button_bg_postfix[this_tab] .. ".png"
end end
return table.concat({ return table.concat({
"style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=;noclip=true]", "style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=]",
"image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]", "style[" .. this_tab .. "_outer;border=false;bgimg=" .. bg_img ..
";bgimg_pressed=" .. bg_img .. "]",
"button[" .. offset[this_tab] .. ";1.5,1.44;" .. this_tab .. "_outer;]",
"item_image_button[" .. boffset[this_tab] .. ";1,1;" .. tab_icon[this_tab] .. ";" .. this_tab .. ";]", "item_image_button[" .. boffset[this_tab] .. ";1,1;" .. tab_icon[this_tab] .. ";" .. this_tab .. ";]",
}) })
end end
@ -577,11 +591,21 @@ function mcl_inventory.set_creative_formspec(player)
caption = "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, filtername[name])) .. "]" caption = "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, filtername[name])) .. "]"
end end
local touch_enabled = is_touch_enabled(playername)
players[playername].last_touch_enabled = touch_enabled
local formspec = table.concat({ local formspec = table.concat({
"formspec_version[6]", "formspec_version[6]",
"size[13,8.75]", -- Original formspec height was 8.75, increased to include tab buttons.
-- This avoids tab buttons going off-screen with high scaling values.
"size[13,11.43]",
-- Use as much space as possible on mobile - the tab buttons are a lot
-- of padding already.
touch_enabled and "padding[-0.015,-0.015]" or "",
"style_type[image;noclip=true]", "no_prepend[]", mcl_vars.gui_nonbg, mcl_vars.gui_bg_color,
"background9[0,1.34;13,8.75;mcl_base_textures_background9.png;;7]",
"container[0,1.34]",
-- Hotbar -- Hotbar
mcl_formspec.get_itemslot_bg_v4(0.375, 7.375, 9, 1), mcl_formspec.get_itemslot_bg_v4(0.375, 7.375, 9, 1),
@ -638,6 +662,7 @@ function mcl_inventory.set_creative_formspec(player)
"set_focus[search;true]", "set_focus[search;true]",
}) })
end end
formspec = formspec .. "container_end[]"
if pagenum then formspec = formspec .. "p" .. tostring(pagenum) end if pagenum then formspec = formspec .. "p" .. tostring(pagenum) end
player:set_inventory_formspec(formspec) player:set_inventory_formspec(formspec)
end end
@ -655,54 +680,54 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name() local name = player:get_player_name()
if fields.blocks then if fields.blocks or fields.blocks_outer then
if players[name].page == "blocks" then return end if players[name].page == "blocks" then return end
set_inv_page("blocks", player) set_inv_page("blocks", player)
page = "blocks" page = "blocks"
elseif fields.deco then elseif fields.deco or fields.deco_outer then
if players[name].page == "deco" then return end if players[name].page == "deco" then return end
set_inv_page("deco", player) set_inv_page("deco", player)
page = "deco" page = "deco"
elseif fields.redstone then elseif fields.redstone or fields.redstone_outer then
if players[name].page == "redstone" then return end if players[name].page == "redstone" then return end
set_inv_page("redstone", player) set_inv_page("redstone", player)
page = "redstone" page = "redstone"
elseif fields.rail then elseif fields.rail or fields.rail_outer then
if players[name].page == "rail" then return end if players[name].page == "rail" then return end
set_inv_page("rail", player) set_inv_page("rail", player)
page = "rail" page = "rail"
elseif fields.misc then elseif fields.misc or fields.misc_outer then
if players[name].page == "misc" then return end if players[name].page == "misc" then return end
set_inv_page("misc", player) set_inv_page("misc", player)
page = "misc" page = "misc"
elseif fields.nix then elseif fields.nix or fields.nix_outer then
set_inv_page("all", player) set_inv_page("all", player)
page = "nix" page = "nix"
elseif fields.food then elseif fields.food or fields.food_outer then
if players[name].page == "food" then return end if players[name].page == "food" then return end
set_inv_page("food", player) set_inv_page("food", player)
page = "food" page = "food"
elseif fields.tools then elseif fields.tools or fields.tools_outer then
if players[name].page == "tools" then return end if players[name].page == "tools" then return end
set_inv_page("tools", player) set_inv_page("tools", player)
page = "tools" page = "tools"
elseif fields.combat then elseif fields.combat or fields.combat_outer then
if players[name].page == "combat" then return end if players[name].page == "combat" then return end
set_inv_page("combat", player) set_inv_page("combat", player)
page = "combat" page = "combat"
elseif fields.mobs then elseif fields.mobs or fields.mobs_outer then
if players[name].page == "mobs" then return end if players[name].page == "mobs" then return end
set_inv_page("mobs", player) set_inv_page("mobs", player)
page = "mobs" page = "mobs"
elseif fields.brew then elseif fields.brew or fields.brew_outer then
if players[name].page == "brew" then return end if players[name].page == "brew" then return end
set_inv_page("brew", player) set_inv_page("brew", player)
page = "brew" page = "brew"
elseif fields.matr then elseif fields.matr or fields.matr_outer then
if players[name].page == "matr" then return end if players[name].page == "matr" then return end
set_inv_page("matr", player) set_inv_page("matr", player)
page = "matr" page = "matr"
elseif fields.inv then elseif fields.inv or fields.inv_outer then
if players[name].page == "inv" then return end if players[name].page == "inv" then return end
page = "inv" page = "inv"
elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then elseif fields.search == "" and not fields.creative_next and not fields.creative_prev then
@ -818,3 +843,19 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
player:get_inventory():set_stack("main", inventory_info.index, stack) player:get_inventory():set_stack("main", inventory_info.index, stack)
end end
end) end)
-- This is necessary because get_player_window_information may return nil in
-- on_joinplayer.
-- (Also, Minetest plans to add support for toggling touchscreen mode in-game.)
minetest.register_globalstep(function(dtime)
for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
if minetest.is_creative_enabled(name) then
local touch_enabled = is_touch_enabled(name)
if touch_enabled ~= players[name].last_touch_enabled then
mcl_inventory.set_creative_formspec(player)
end
end
end
end)

View File

@ -5,9 +5,6 @@
--- Copyright (C) 2022 - 2023, Michieal. See License.txt --- Copyright (C) 2022 - 2023, Michieal. See License.txt
-- CONSTS -- CONSTS
local DOUBLE_DROP_CHANCE = 8
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
-- "BAMBOO" goes here.
local BAMBOO = "mcl_bamboo:bamboo" local BAMBOO = "mcl_bamboo:bamboo"
local BAMBOO_ENDCAP_NAME = "mcl_bamboo:bamboo_endcap" local BAMBOO_ENDCAP_NAME = "mcl_bamboo:bamboo_endcap"
local BAMBOO_PLANK = BAMBOO .. "_plank" local BAMBOO_PLANK = BAMBOO .. "_plank"
@ -16,7 +13,7 @@ local BAMBOO_PLANK = BAMBOO .. "_plank"
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname) local S = minetest.get_translator(modname)
local node_sound = mcl_sounds.node_sound_wood_defaults() local node_sound = mcl_sounds.node_sound_wood_defaults()
local pr = PseudoRandom((os.time() + 15766) * 12) -- switched from math.random() to PseudoRandom because the random wasn't very random. local pr = PseudoRandom((os.time() + 15766) * 12)
local on_rotate local on_rotate
if minetest.get_modpath("screwdriver") then if minetest.get_modpath("screwdriver") then
@ -31,38 +28,16 @@ local bamboo_def = {
paramtype = "light", paramtype = "light",
groups = {handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3}, groups = {handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3},
sounds = node_sound, sounds = node_sound,
drop = BAMBOO,
drop = {
max_items = 1,
-- From the API:
-- max_items: Maximum number of item lists to drop.
-- The entries in 'items' are processed in order. For each:
-- Item filtering is applied, chance of drop is applied, if both are
-- successful the entire item list is dropped.
-- Entry processing continues until the number of dropped item lists
-- equals 'max_items'.
-- Therefore, entries should progress from low to high drop chance.
items = {
-- Examples:
{
-- 1 in DOUBLE_DROP_CHANCE chance of dropping.
-- Default rarity is '1'.
rarity = DOUBLE_DROP_CHANCE,
items = {BAMBOO .. " 2"},
},
{
-- 1 in 1 chance of dropping. (Note: this means that it will drop 100% of the time.)
-- Default rarity is '1'.
rarity = 1,
items = {BAMBOO},
},
},
},
inventory_image = "mcl_bamboo_bamboo_shoot.png", inventory_image = "mcl_bamboo_bamboo_shoot.png",
wield_image = "mcl_bamboo_bamboo_shoot.png", wield_image = "mcl_bamboo_bamboo_shoot.png",
_mcl_blast_resistance = 1, _mcl_blast_resistance = 1,
_mcl_hardness = 1, _mcl_hardness = 1,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
return mcl_bamboo.grow_bamboo(pos, true)
end,
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
@ -86,7 +61,6 @@ local bamboo_def = {
on_rotate = on_rotate, on_rotate = on_rotate,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
if not pointed_thing then if not pointed_thing then
return itemstack return itemstack
end end
@ -241,9 +215,6 @@ local bamboo_def = {
if node_above and ((bamboo_node and bamboo_node > 0) or node_above.name == BAMBOO_ENDCAP_NAME) then if node_above and ((bamboo_node and bamboo_node > 0) or node_above.name == BAMBOO_ENDCAP_NAME) then
minetest.remove_node(new_pos) minetest.remove_node(new_pos)
minetest.sound_play(node_sound.dug, sound_params, true) minetest.sound_play(node_sound.dug, sound_params, true)
if pr:next(1, DOUBLE_DROP_CHANCE) == 1 then
minetest.add_item(new_pos, istack)
end
minetest.add_item(new_pos, istack) minetest.add_item(new_pos, istack)
end end
end, end,
@ -253,10 +224,12 @@ minetest.register_node(BAMBOO, bamboo_def)
local bamboo_top = table.copy(bamboo_def) local bamboo_top = table.copy(bamboo_def)
bamboo_top.groups = {not_in_creative_inventory = 1, handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3} bamboo_top.groups = {not_in_creative_inventory = 1, handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3}
bamboo_top.tiles = {"mcl_bamboo_endcap.png"} bamboo_top.tiles = {"mcl_bamboo_endcap.png"}
bamboo_top.drawtype = "plantlike_rooted" --"plantlike"
--bamboo_top.paramtype2 = "meshoptions" -- bamboo_top.drawtype = "plantlike_rooted" --"plantlike"
--bamboo_top.param2 = 2 bamboo_top.drawtype = "plantlike"
-- bamboo_top.waving = 2 bamboo_top.paramtype2 = "meshoptions"
bamboo_top.param2 = 2
bamboo_top.waving = 2
bamboo_top.special_tiles = {{name = "mcl_bamboo_endcap.png"}} bamboo_top.special_tiles = {{name = "mcl_bamboo_endcap.png"}}
bamboo_top.nodebox = nil bamboo_top.nodebox = nil
bamboo_top.selection_box = nil bamboo_top.selection_box = nil

View File

@ -9,8 +9,6 @@ local SIDE_SCAFFOLDING = false
local SIDE_SCAFFOLD_NAME = "mcl_bamboo:scaffolding_horizontal" local SIDE_SCAFFOLD_NAME = "mcl_bamboo:scaffolding_horizontal"
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
local SCAFFOLDING_NAME = "mcl_bamboo:scaffolding" local SCAFFOLDING_NAME = "mcl_bamboo:scaffolding"
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
-- "BAMBOO" goes here.
local BAMBOO = "mcl_bamboo:bamboo" local BAMBOO = "mcl_bamboo:bamboo"
local BAMBOO_PLANK = BAMBOO .. "_plank" local BAMBOO_PLANK = BAMBOO .. "_plank"

View File

@ -44,6 +44,10 @@ mcl_bamboo.bamboo_index = {
"mcl_bamboo:bamboo_2", "mcl_bamboo:bamboo_2",
"mcl_bamboo:bamboo_3", "mcl_bamboo:bamboo_3",
} }
mcl_bamboo.bamboo_set = {}
for _,key in pairs(mcl_bamboo.bamboo_index) do
mcl_bamboo.bamboo_set[key] = true
end
function mcl_bamboo.is_bamboo(node_name) function mcl_bamboo.is_bamboo(node_name)
local index = table.indexof(mcl_bamboo.bamboo_index, node_name) local index = table.indexof(mcl_bamboo.bamboo_index, node_name)
@ -94,172 +98,84 @@ end
--]] --]]
function mcl_bamboo.grow_bamboo(pos, bonemeal_applied) function mcl_bamboo.grow_bamboo(pos, bonemeal_applied)
local log = mcl_bamboo.mcl_log
local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0)) local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0))
mcl_bamboo.mcl_log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied)) log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied))
if not bonemeal_applied and mcl_bamboo.is_bamboo(node_above.name) ~= false then if not bonemeal_applied then
return false -- short circuit this function if we're trying to grow (std) the bamboo and it's not the top shoot. -- Only allow natural growth at the top of the bamboo
if mcl_bamboo.is_bamboo(node_above.name) ~= false then return false end
-- Don't perform natual growth in low light
if minetest.get_node_light(pos) < 8 then return false end
end end
if minetest.get_node_light(pos) < 8 then
-- Determine the location of soil
local soil_pos
soil_pos,a,b = mcl_util.trace_nodes(pos, -1, mcl_bamboo.bamboo_set, BAMBOO_MAX_HEIGHT - 1)
-- No soil found, return false so that bonemeal isn't used
if not soil_pos then return false end
log("Grow bamboo; soil found. ")
-- Find the first bamboo shoot and retrieve data about it
local first_shoot = vector.offset(soil_pos, 0, 1, 0)
local first_shoot_meta = minetest.get_meta(first_shoot)
-- Get or initialize bamboo height
local height = (first_shoot_meta and first_shoot_meta:get_int("height", -1)) or -1
if height == -1 then
height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1)
first_shoot_meta:set_int("height", height)
end
log("Grow bamboo; height: " .. height)
-- Locate the bamboo tip
local bamboo_tip,actual_height,bamboo_tip_node = mcl_util.trace_nodes(first_shoot, 1, mcl_bamboo.bamboo_set, height - 1)
log("Current height: "..tostring(actual_height))
-- Short circuit growth if the bamboo is already finished growing
if not bamboo_tip or not actual_height or actual_height >= height then
log("Bamboo is already as large as it can grow")
return false return false
end end
-- variables used in more than one spot. -- Now that we are actually going to add nodes, initialize some more information
local first_shoot local first_shoot_node_name = minetest.get_node(first_shoot).name
local chk_pos
local soil_pos
local node_name = ""
local dist = 0
local node_below
-- -------------------
mcl_bamboo.mcl_log("Grow bamboo; checking for soil: ") -- If applying bonemeal, randomly grow two segments instead of one
-- the soil node below the bamboo. local grow_amount = 1
for py = -1, BAMBOO_SOIL_DIST, -1 do
chk_pos = vector.offset(pos, 0, py, 0)
node_name = minetest.get_node(chk_pos).name
if mcl_bamboo.is_dirt(node_name) then
soil_pos = chk_pos
break
end
if mcl_bamboo.is_bamboo(node_name) == false then
break
end
end
-- requires knowing where the soil node is.
if soil_pos == nil then
return false -- returning false means don't use up the bonemeal.
end
mcl_bamboo.mcl_log("Grow bamboo; soil found. ")
local grow_amount = rand(1, GROW_DOUBLE_CHANCE)
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
grow_amount = rand(1, GROW_DOUBLE_CHANCE) -- because yeah, not truly random, or even a good prng.
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
local init_height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1)
mcl_bamboo.mcl_log("Grow bamboo; random height: " .. init_height)
node_name = ""
-- update: add randomized max height to first node's meta data.
first_shoot = vector.offset(soil_pos, 0, 1, 0)
local meta = minetest.get_meta(first_shoot)
node_below = minetest.get_node(first_shoot).name
mcl_bamboo.mcl_log("Grow bamboo; checking height meta ")
-- check the meta data for the first node, to see how high to make the stalk.
if not meta then
-- if no metadata, set the metadata!!!
meta:set_int("height", init_height)
end
local height = meta:get_int("height", -1)
mcl_bamboo.mcl_log("Grow bamboo; meta-height: " .. height)
if height <= 10 then
height = init_height
meta:set_int("height", init_height)
end
mcl_bamboo.mcl_log("Grow bamboo; height: " .. height)
-- Bonemeal: Grows the bamboo by 1-2 stems. (per the minecraft wiki.)
if bonemeal_applied then if bonemeal_applied then
-- handle applying bonemeal. local rng = PcgRandom(minetest.hash_node_position(pos) + minetest.get_us_time())
for py = 1, BAM_MAX_HEIGHT_TOP do if rng:next(1, GROW_DOUBLE_CHANGE) == 1 then
-- find the top node of bamboo. grow_amount = 2
chk_pos = vector.offset(pos, 0, py, 0)
node_name = minetest.get_node(chk_pos).name
dist = vector.distance(soil_pos, chk_pos)
if mcl_bamboo.is_bamboo(node_name) == false or node_name == BAMBOO_ENDCAP_NAME then
break
end
end
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
if node_name == BAMBOO_ENDCAP_NAME then
-- prevent overgrowth
return false
end
-- check to see if we have a full stalk of bamboo.
if dist >= height - 1 then
if dist == height - 1 then
-- equals top of the stalk before the cap
if node_name == "air" then
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap")
minetest.set_node(vector.offset(chk_pos, 0, 1, 0), { name = BAMBOO_ENDCAP_NAME })
return true -- returning true means use up the bonemeal.
else
return false
end
else
-- okay, we're higher than the end cap, fail out.
return false -- returning false means don't use up the bonemeal.
end
end
-- and now, the meat of the section... add bamboo to the stalk.
-- at this point, we should be lower than the generated maximum height. ~ about height -2 or lower.
if dist <= height - 2 then
if node_name == "air" then
-- here we can check to see if we can do up to 2 bamboo shoots onto the stalk
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
minetest.set_node(chk_pos, { name = node_below })
-- handle growing a second node.
if grow_amount == 2 then
chk_pos = vector.offset(chk_pos, 0, 1, 0)
if minetest.get_node(chk_pos).name == "air" then
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
minetest.set_node(chk_pos, { name = node_below })
end
end
return true -- exit out with a success. We've added 1-2 nodes, per the wiki.
end
end end
end end
log("Growing up to "..grow_amount.." segments")
-- Non-Bonemeal growth. -- Perform bamboo growth
for py = 1, BAM_MAX_HEIGHT_TOP do for i = 1,grow_amount do
-- Find the topmost node above the stalk, and check it for "air" -- Check for air to grow into
chk_pos = vector.offset(pos, 0, py, 0) local bamboo_tip_node = minetest.get_node(bamboo_tip)
node_below = minetest.get_node(pos).name if not bamboo_tip_node or bamboo_tip_node.name ~= "air" then
node_name = minetest.get_node(chk_pos).name -- Something is blocking growth, stop and signal that use bonemeal has been used if at least on segment has grown
dist = vector.distance(soil_pos, chk_pos) return i ~= 1
if node_name ~= "air" and mcl_bamboo.is_bamboo(node_name) == false then
break
end end
-- stop growing check. ie, handle endcap placement. if actual_height + 1 == height then
if dist >= height - 1 then -- This is the end cap
local above_node_name = minetest.get_node(vector.offset(chk_pos, 0, 1, 0)).name minetest.set_node(bamboo_tip, { name = BAMBOO_ENDCAP_NAME })
if node_name == "air" and above_node_name == "air" then return true
if height - 1 == dist then else
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap") -- This isn't the end cap, add a bamboo segment
minetest.set_node(chk_pos, { name = BAMBOO_ENDCAP_NAME }) minetest.set_node(bamboo_tip, { name = first_shoot_node_name })
end actual_height = actual_height + 1
end
break
end end
-- handle regular node placement. bamboo_tip = vector.offset(bamboo_tip, 0, 1, 0)
-- find the air node above the top shoot. place a node. And then, if short enough,
-- check for second node placement.
if node_name == "air" then
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
minetest.set_node(chk_pos, { name = node_below })
-- handle growing a second node. (1 in 32 chance.)
if grow_amount == 2 and dist <= height - 2 then
chk_pos = vector.offset(chk_pos, 0, 1, 0)
if minetest.get_node(chk_pos).name == "air" then
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
minetest.set_node(chk_pos, { name = node_below })
end
end
break
end
end end
return true
end end
-- Add Groups function, courtesy of Warr1024. -- Add Groups function, courtesy of Warr1024.

View File

@ -7,8 +7,6 @@
-- LOCALS -- LOCALS
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
-- "BAMBOO" goes here.
local BAMBOO = "mcl_bamboo:bamboo" local BAMBOO = "mcl_bamboo:bamboo"
mcl_bamboo = {} mcl_bamboo = {}

View File

@ -5,8 +5,6 @@
--- These are all of the fuel recipes and all of the crafting recipes, consolidated into one place. --- These are all of the fuel recipes and all of the crafting recipes, consolidated into one place.
--- Copyright (C) 2022 - 2023, Michieal. See License.txt --- Copyright (C) 2022 - 2023, Michieal. See License.txt
-- Used everywhere. Often this is just the name, but it makes sense to me as BAMBOO, because that's how I think of it...
-- "BAMBOO" goes here.
local BAMBOO = "mcl_bamboo:bamboo" local BAMBOO = "mcl_bamboo:bamboo"
local BAMBOO_PLANK = BAMBOO .. "_plank" local BAMBOO_PLANK = BAMBOO .. "_plank"
-- Craftings -- Craftings

View File

@ -2,4 +2,4 @@ name = mcl_beds
author = BlockMen author = BlockMen
description = description =
depends = playerphysics depends = playerphysics
optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecons optional_depends = mcl_sounds, mcl_worlds, mcl_wool, mcl_dye, mcl_explosions, mcl_weather, mcl_spawn, doc, mesecons, mesecons_mvps

View File

@ -0,0 +1,76 @@
# Bone meal API
Bonemealing callbacks and particle functions.
## _on_bone_meal(itemstack, placer, pointed_thing)
The bone meal API provides a callback definition that nodes can use to
register a handler that is executed when a bone meal item is used on it.
Nodes that wish to use the bone meal API should in their node registration
define a callback handler named `_on_bone_meal`.
Note that by registering the callback handler, the node declares that bone
meal can be used on it and as a result, when the user is not in creative
mode, the used bone meal is spent and taken from the itemstack passed to
the `on_place()` handler of the bone meal item used regardless of whether
the bone meal had an effect on the node and regardless of the result of
the callback handler.
It is for all intents and purposes up to the callback defined in the node to
decide how to handle the specific effect that bone meal has on that node.
The `_on_bone_meal` callback handler is a
`function(itemstack, placer, pointed_thing)`
Its arguments are:
* `itemstack`: the stack of bonem eal being applied
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
* `pointed_thing`: exact pointing location (see Minetest API), where the
bone meal is applied
The return value of the handler function indicates if the bonemealing had
its intended effect. If `true`, 'bone meal particles' are spawned at the
position of the bonemealed node.
The `on_place` code in the bone meal item will spawn bone meal particles and
decrease the bone meal itemstack if the handler returned `true` and the
`placer` is not in creative mode.
## mcl_bone_meal.add_bone_meal_particle(pos, def)
Spawns standard or custom bone meal particles.
* `pos`: position, is ignored if you define def.minpos and def.maxpos
* `def`: (optional) particle definition; see minetest.add_particlespawner()
for more details.
## mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
For use in on_rightclick handlers that need support bone meal processing in addition
to other behaviors. Before calling, verify that the player is wielding bone meal.
* `itemstack`: The stack of bone meal being used
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
* `pointed_thing`: exact pointing location (see Minetest API), where the
bone meal is applied
Returns itemstack with one bone meal consumed if not in creative mode.
# Legacy API
The bone meal API also provides a legacy compatibility function. This
function is not meant to be continued and callers should migrate to the
newer bonemealing API.
## mcl_bone_meal.register_on_bone_meal_apply(function(pointed_thing, placer))
Called when the bone meal is applied anywhere.
* `pointed_thing`: exact pointing location (see Minetest API), where the
bone meal is applied
* `placer`: ObjectRef of the player who aplied the bone meal, can be nil!
This function is deprecated and will be removed at some time in the future.
Bone meal is not consumed unless the provided function returns true.
## mcl_dye.add_bone_meal_particle(pos, def)
## mcl_dye.register_on_bone_meal_apply(function(pointed_thing, user))
These shims in mcl_dye that point to corresponding legacy compatibility
functions in mcl_bone_meal remain for legacy callers that have not yet been
updated to the new API. These shims will be removed at some time in the
future.

View File

@ -0,0 +1,156 @@
local S = minetest.get_translator(minetest.get_current_modname())
local longdesc = S(
"Bone meal is a white dye and also useful as a fertilizer to " ..
"speed up the growth of many plants."
)
local usagehelp = S(
"Rightclick a sheep to turn its wool white. Rightclick a plant " ..
"to speed up its growth. Note that not all plants can be " ..
"fertilized like this. When you rightclick a grass block, tall " ..
"grass and flowers will grow all over the place."
)
mcl_bone_meal = {}
-- Bone meal particle API:
--- Spawns bone meal particles.
-- pos: where the particles spawn
-- def: particle spawner parameters, see minetest.add_particlespawner() for
-- details on these parameters.
--
function mcl_bone_meal.add_bone_meal_particle(pos, def)
def = def or {}
minetest.add_particlespawner({
amount = def.amount or 10,
time = def.time or 0.1,
minpos = def.minpos or vector.subtract(pos, 0.5),
maxpos = def.maxpos or vector.add(pos, 0.5),
minvel = def.minvel or vector.new(-0.01, 0.01, -0.01),
maxvel = def.maxvel or vector.new(0.01, 0.01, 0.01),
minacc = def.minacc or vector.new(0, 0, 0),
maxacc = def.maxacc or vector.new(0, 0, 0),
minexptime = def.minexptime or 1,
maxexptime = def.maxexptime or 4,
minsize = def.minsize or 0.7,
maxsize = def.maxsize or 2.4,
texture = "mcl_particles_bonemeal.png^[colorize:#00EE00:125",
glow = def.glow or 1,
})
end
-- Begin legacy bone meal API.
--
-- Compatibility code for legacy users of the old bone meal API.
-- This code will be removed at some time in the future.
--
mcl_bone_meal.bone_meal_callbacks = {}
-- Shims for the old API are still available in mcl_dye and defer to
-- the real functions in mcl_bone_meal.
--
function mcl_bone_meal.register_on_bone_meal_apply(func)
minetest.log("warning", "register_on_bone_meal_apply(func) is deprecated. Read mcl_bone_meal/API.md!")
local lines = string.split(debug.traceback(),"\n")
for _,line in ipairs(lines) do
minetest.log("warning",line)
end
table.insert(mcl_bone_meal.bone_meal_callbacks, func)
end
-- Legacy registered users of the old API are handled through this function.
--
local function legacy_apply_bone_meal(pointed_thing, placer)
-- Legacy API support
local callbacks = mcl_bone_meal.bone_meal_callbacks
for i = 1,#callbacks do
if callbacks[i](pointed_thing, placer) then
return true
end
end
return false
end
-- End legacy bone meal API
function mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
local positions = {pointed_thing.under, pointed_thing.above}
for i = 1,2 do
local pos = positions[i]
-- Check protection
if mcl_util.check_area_protection(pos, pointed_thing.above, placer) then return false end
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
local success = false
local consume
-- If the pointed node can be bonemealed, let it handle the processing.
if ndef and ndef._on_bone_meal then
success = ndef._on_bone_meal(itemstack, placer, {under = pos, above = vector.offset(pos, 0, 1, 0)})
consume = true
else
-- Otherwise try the legacy API.
success = legacy_apply_bone_meal(pointed_thing, placer)
consume = success
end
-- Take the item
if consume then
-- Particle effects
mcl_bone_meal.add_bone_meal_particle(pos)
if not placer or not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()
end
return itemstack
end
if success then return itemstack end
end
return itemstack
end
minetest.register_craftitem("mcl_bone_meal:bone_meal", {
description = S("Bone Meal"),
_tt_help = S("Speeds up plant growth"),
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
inventory_image = "mcl_bone_meal.png",
groups = {craftitem=1},
on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
-- Use pointed node's on_rightclick function first, if present.
if placer and not placer:get_player_control().sneak then
if ndef and ndef.on_rightclick then
local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pointed_thing)
if new_stack and new_stack ~= itemstack then return new_stack end
end
end
return mcl_bone_meal.use_bone_meal(itemstack, placer, pointed_thing)
end,
_on_dispense = function(itemstack, pos, droppos, dropnode, dropdir)
local pointed_thing
if dropnode.name == "air" then
pointed_thing = {above = droppos, under = vector.offset(droppos, 0, -1 ,0)}
else
pointed_thing = {above = pos, under = droppos}
end
return mcl_bone_meal.use_bone_meal(itemstack, nil, pointed_thing)
end,
_dispense_into_walkable = true
})
minetest.register_craft({
output = "mcl_bone_meal:bone_meal 3",
recipe = {{"mcl_mobitems:bone"}},
})

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=Knochenmehl
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Knochenmehl ist ein weißer Farbstoff und auch nützlich als Dünger, um das Wachstum vieler Pflanzen zu beschleunigen.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Rechtsklicken Sie auf ein Schaf, um die Wolle weiß einzufärben. Rechtsklicken Sie auf eine Pflanze, um ihr Wachstum zu beschleunigen. Beachten Sie, dass nicht alle Pflanzen darauf ansprechen. Benutzen Sie es auf einem Grasblock, wächst viel hohes Gras und vielleicht auch ein paar Blumen.
Speeds up plant growth=Beschleunigt Pflanzenwachstum

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=Harina de hueso
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La harina de hueso es un tinte blanco y también es útil como fertilizante para acelerar el crecimiento de muchas plantas.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=RHaga clic derecho en una oveja para volver su lana blanca. Haga clic derecho en una planta para acelerar su crecimiento. Tenga en cuenta que no todas las plantas pueden ser fertilizadas de esta manera. Cuando haces clic derecho en un bloque de hierba, crecerán hierba alta y flores por todo el lugar.
Speeds up plant growth=Acelera el crecimiento de las plantas

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=Farine d'Os
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La farine d'os est une teinture blanche et est également utile comme engrais pour accélérer la croissance de nombreuses plantes.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Cliquez avec le bouton droit sur un mouton pour blanchir sa laine. Cliquez avec le bouton droit sur une plante pour accélérer sa croissance. Cependant, toutes les plantes ne peuvent pas être fertilisées de cette manière. Lorsque vous cliquez avec le bouton droit sur un bloc d'herbe, les hautes herbes et les fleurs poussent autour.
Speeds up plant growth=Accélère la croissance des plantes

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=Mączka kostna
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Mączka kostna to biała farba i przydatny nawóz, który przyspiesza rośnięcie wielu roślin.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Kliknij prawym na owcę, aby wybielić jej wełnę. Kliknij prawym na roślinę aby przyspieszyć jej wzrost. Zważ, że nie na wszystkie rośliny to tak działa. Gdy klikniesz prawym na blok trawy, wysoka trawa wyrośnie wokół.
Speeds up plant growth=Przyspiesza wzrost roślin

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=Костная мука
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Костная мука является белым красителем. Она также полезна в качестве удобрения, чтобы увеличить скорость роста многих растений.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Кликните правой по овце, чтобы сделать её шерсть белой. Кликните правой по растению, чтобы ускорить его рост. Имейте в виду, что не все растения можно удобрять таким способом. Если вы кликнете по травяному блоку, то на этом месте вырастет высокая трава и цветы.
Speeds up plant growth=Ускоряет рост растений

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=骨粉
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=骨粉是一種白色染料,也可作為肥料,加速許多植物的生長。
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=右鍵點擊一隻羊,使其羊毛變白。右鍵點擊一株植物以加快其生長速度。注意,不是所有的植物都能像這樣施肥。當你右鍵點擊一個草方時,高高的草和花會到處生長。
Speeds up plant growth=加速植物生長

View File

@ -0,0 +1,5 @@
# textdomain: mcl_bone_meal
Bone Meal=
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=
Speeds up plant growth=

View File

@ -0,0 +1,3 @@
name = mcl_bone_meal
description = Bone meal can be used as a fertilizer and as a dye.
author = kabou, teknomunk

View File

Before

Width:  |  Height:  |  Size: 165 B

After

Width:  |  Height:  |  Size: 165 B

View File

@ -35,6 +35,7 @@ local function random_arrow_positions(positions, placement)
end end
return 0 return 0
end end
mcl_bows.random_arrow_positions = random_arrow_positions
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements") local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
local mod_button = minetest.get_modpath("mesecons_button") local mod_button = minetest.get_modpath("mesecons_button")
@ -257,10 +258,10 @@ function ARROW_ENTITY.on_step(self, dtime)
mcl_burning.set_on_fire(obj, 5) mcl_burning.set_on_fire(obj, 5)
end end
if not self._in_player and not self._blocked then if not self._in_player and not self._blocked then
obj:punch(self.object, 1.0, { mcl_util.deal_damage(obj, self._damage, {type = "arrow", source = self._shooter, direct = self.object})
full_punch_interval=1.0, if self._extra_hit_func then
damage_groups={fleshy=self._damage}, self._extra_hit_func(obj)
}, self.object:get_velocity()) end
if obj:is_player() then if obj:is_player() then
if not mcl_shields.is_blocking(obj) then if not mcl_shields.is_blocking(obj) then
local placement local placement

View File

@ -1,6 +1,5 @@
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
mcl_bows = {}
-- local arrows = { -- local arrows = {
-- ["mcl_bows:arrow"] = "mcl_bows:arrow_entity", -- ["mcl_bows:arrow"] = "mcl_bows:arrow_entity",
@ -168,7 +167,8 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
itemstack:get_meta():set_string("active", "true") itemstack:get_meta():set_string("active", "true")
return itemstack return itemstack
end, end,
groups = {weapon=1,weapon_ranged=1,bow=1,enchantability=1}, groups = {weapon=1,weapon_ranged=1,bow=1,cannot_block=1,enchantability=1},
touch_interaction = "short_dig_long_place",
_mcl_uses = 385, _mcl_uses = 385,
}) })
@ -216,7 +216,7 @@ for level=0, 2 do
wield_scale = mcl_vars.tool_wield_scale, wield_scale = mcl_vars.tool_wield_scale,
stack_max = 1, stack_max = 1,
range = 0, -- Pointing range to 0 to prevent punching with bow :D range = 0, -- Pointing range to 0 to prevent punching with bow :D
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1}, groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, cannot_block=1, enchantability=1},
-- Trick to disable digging as well -- Trick to disable digging as well
on_use = function() return end, on_use = function() return end,
on_drop = function(itemstack, dropper, pos) on_drop = function(itemstack, dropper, pos)
@ -235,6 +235,7 @@ for level=0, 2 do
on_place = function(itemstack) on_place = function(itemstack)
return itemstack return itemstack
end, end,
touch_interaction = "short_dig_long_place",
_mcl_uses = 385, _mcl_uses = 385,
}) })
end end

View File

@ -158,7 +158,8 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
itemstack:get_meta():set_string("active", "true") itemstack:get_meta():set_string("active", "true")
return itemstack return itemstack
end, end,
groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1}, groups = {weapon=1,weapon_ranged=1,crossbow=1,cannot_block=1,enchantability=1},
touch_interaction = "short_dig_long_place",
_mcl_uses = 326, _mcl_uses = 326,
}) })
@ -193,7 +194,8 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
itemstack:get_meta():set_string("active", "true") itemstack:get_meta():set_string("active", "true")
return itemstack return itemstack
end, end,
groups = {weapon=1,weapon_ranged=1,crossbow=1,enchantability=1,not_in_creative_inventory=1}, groups = {weapon=1,weapon_ranged=1,crossbow=1,cannot_block=1,enchantability=1,not_in_creative_inventory=1},
touch_interaction = "short_dig_long_place",
_mcl_uses = 326, _mcl_uses = 326,
}) })
@ -238,7 +240,7 @@ for level=0, 2 do
wield_scale = mcl_vars.tool_wield_scale, wield_scale = mcl_vars.tool_wield_scale,
stack_max = 1, stack_max = 1,
range = 0, -- Pointing range to 0 to prevent punching with bow :D range = 0, -- Pointing range to 0 to prevent punching with bow :D
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1}, groups = {not_in_creative_inventory=1, not_in_craft_guide=1, cannot_block=1, bow=1, enchantability=1},
-- Trick to disable digging as well -- Trick to disable digging as well
on_use = function() return end, on_use = function() return end,
on_drop = function(itemstack, dropper, pos) on_drop = function(itemstack, dropper, pos)
@ -257,6 +259,7 @@ for level=0, 2 do
on_place = function(itemstack) on_place = function(itemstack)
return itemstack return itemstack
end, end,
touch_interaction = "short_dig_long_place",
_mcl_uses = 385, _mcl_uses = 385,
}) })
end end

View File

@ -1,3 +1,5 @@
mcl_bows = {}
--Bow --Bow
dofile(minetest.get_modpath("mcl_bows") .. "/arrow.lua") dofile(minetest.get_modpath("mcl_bows") .. "/arrow.lua")
dofile(minetest.get_modpath("mcl_bows") .. "/bow.lua") dofile(minetest.get_modpath("mcl_bows") .. "/bow.lua")

View File

@ -2,29 +2,34 @@ local S = minetest.get_translator(minetest.get_current_modname())
mcl_cocoas = {} mcl_cocoas = {}
-- Place cocoa --- Place a cocoa pod.
local function cocoa_place(itemstack, placer, pt, plantname) -- Attempt to place a cocoa pod on a jungle tree. Checks if attachment
-- point is a jungle tree and sets the correct orientation of the stem.
--
function mcl_cocoas.place(itemstack, placer, pt, plantname)
-- check if pointing at a node -- check if pointing at a node
if not pt or pt.type ~= "node" then if not pt or pt.type ~= "node" then
return return
end end
local under = minetest.get_node(pt.under) local node = minetest.get_node(pt.under)
-- return if any of the nodes are not registered -- return if any of the nodes are not registered
if not minetest.registered_nodes[under.name] then local def = minetest.registered_nodes[node.name]
if not def then
return return
end end
-- Am I right-clicking on something that has a custom on_rightclick set? -- Am I right-clicking on something that has a custom on_rightclick set?
if placer and not placer:get_player_control().sneak then if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[under.name] and minetest.registered_nodes[under.name].on_rightclick then if def and def.on_rightclick then
return minetest.registered_nodes[under.name].on_rightclick(pt.under, under, placer, itemstack) or itemstack local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pt)
if new_stack and new_stack ~= itemstack then return new_stack end
end end
end end
-- Check if pointing at jungle tree -- Check if pointing at jungle tree
if under.name ~= "mcl_core:jungletree" if node.name ~= "mcl_core:jungletree"
or minetest.get_node(pt.above).name ~= "air" then or minetest.get_node(pt.above).name ~= "air" then
return return
end end
@ -39,9 +44,7 @@ local function cocoa_place(itemstack, placer, pt, plantname)
-- Add the node, set facedir and remove 1 item from the itemstack -- Add the node, set facedir and remove 1 item from the itemstack
minetest.set_node(pt.above, {name = plantname, param2 = minetest.dir_to_facedir(clickdir)}) minetest.set_node(pt.above, {name = plantname, param2 = minetest.dir_to_facedir(clickdir)})
minetest.sound_play("default_place_node", {pos = pt.above, gain = 1.0}, true) minetest.sound_play("default_place_node", {pos = pt.above, gain = 1.0}, true)
if not minetest.is_creative_enabled(placer:get_player_name()) then if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
@ -49,111 +52,119 @@ local function cocoa_place(itemstack, placer, pt, plantname)
return itemstack return itemstack
end end
-- Attempts to grow a cocoa at pos, returns true when grown, returns false if there's no cocoa --- Grows cocoa pod one size larger.
-- or it is already at full size -- Attempts to grow a cocoa at pos, returns true when grown, returns false
-- if there's no cocoa or it is already at full size.
--
function mcl_cocoas.grow(pos) function mcl_cocoas.grow(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if node.name == "mcl_cocoas:cocoa_1" then if node.name == "mcl_cocoas:cocoa_1" then
minetest.set_node(pos, {name = "mcl_cocoas:cocoa_2", param2 = node.param2}) minetest.set_node(pos, {name = "mcl_cocoas:cocoa_2", param2 = node.param2})
elseif node.name == "mcl_cocoas:cocoa_2" then elseif node.name == "mcl_cocoas:cocoa_2" then
minetest.set_node(pos, {name = "mcl_cocoas:cocoa_3", param2 = node.param2}) minetest.set_node(pos, {name = "mcl_cocoas:cocoa_3", param2 = node.param2})
return true else
return false
end end
return false return true
end end
-- Cocoa definition -- only caller was mcl_dye, consider converting these into local functions.
-- 1st stage local cocoa_place = mcl_cocoas.place
local crop_def = { local cocoa_grow = mcl_cocoas.grow
description = S("Premature Cocoa Pod"),
_doc_items_create_entry = true, -- Cocoa pod variant definitions.
_doc_items_longdesc = S("Cocoa pods grow on the side of jungle trees in 3 stages."), --[[ TODO: Use a mesh for cocoas for perfect texture compability. ]]
drawtype = "mesh", local podinfo = {
mesh = "mcl_cocoas_cocoa_stage_0.obj", { desc = S("Premature Cocoa Pod"),
tiles = {"mcl_cocoas_cocoa_stage_0.png"}, longdesc = S("Cocoa pods grow on the side of jungle trees in 3 stages."),
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true, tiles = {
paramtype = "light", "mcl_cocoas_cocoa_stage_0.png",
sunlight_propagates = true,
paramtype2 = "facedir",
walkable = true,
drop = "mcl_cocoas:cocoa_beans",
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.0625, 0.1875, 0.125, 0.25, 0.4375}, -- Pod
}, },
n_box = {-0.125, -0.0625, 0.1875, 0.125, 0.25, 0.4375},
s_box = {-0.125, -0.0625, 0.1875, 0.125, 0.5, 0.5 },
}, },
selection_box = { { desc = S("Medium Cocoa Pod"),
type = "fixed", tiles = {
fixed = { "mcl_cocoas_cocoa_stage_1.png",
{-0.125, -0.0625, 0.1875, 0.125, 0.5, 0.5}, -- Pod
}, },
n_box = {-0.1875, -0.1875, 0.0625, 0.1875, 0.25, 0.4375},
s_box = {-0.1875, -0.1875, 0.0625, 0.1875, 0.5, 0.5 },
}, },
groups = { { desc = S("Mature Cocoa Pod"),
handy = 1, axey = 1, longdesc = S("A mature cocoa pod grew on a jungle tree to its full size and it is ready to be harvested for cocoa beans. It won't grow any further."),
dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1, tiles = {
attached_node_facedir=1, "mcl_cocoas_cocoa_stage_2.png",
not_in_creative_inventory=1, },
cocoa=1 n_box = {-0.25, -0.3125, -0.0625, 0.25, 0.25, 0.4375},
}, s_box = {-0.25, -0.3125, -0.0625, 0.25, 0.5, 0.5 },
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = false,
_mcl_blast_resistance = 3,
_mcl_hardness = 0.2,
}
-- 2nd stage
minetest.register_node("mcl_cocoas:cocoa_1", table.copy(crop_def))
crop_def.description = S("Medium Cocoa Pod")
crop_def._doc_items_create_entry = false
crop_def.groups.cocoa = 2
crop_def.mesh = "mcl_cocoas_cocoa_stage_1.obj"
crop_def.tiles = {"mcl_cocoas_cocoa_stage_1.png"}
crop_def.collision_box = {
type = "fixed",
fixed = {
{-0.1875, -0.1875, 0.0625, 0.1875, 0.25, 0.4375}, -- Pod
},
}
crop_def.selection_box = {
type = "fixed",
fixed = {
{-0.1875, -0.1875, 0.0625, 0.1875, 0.5, 0.5},
}, },
} }
minetest.register_node("mcl_cocoas:cocoa_2", table.copy(crop_def)) for i = 1, 3 do
local def = {
description = podinfo[i].desc,
_doc_items_create_entry = true,
_doc_items_longdesc = podinfo[i].longdesc,
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
tiles = podinfo[i].tiles,
use_texture_alpha = "clip",
node_box = {
type = "fixed",
fixed = {
podinfo[i].n_box, -- Pod
-- FIXME: This has a thickness of 0. Is this OK in Minetest?
{ 0, 0.25, 0.25, 0, 0.5, 0.5 }, }, -- Stem
},
collision_box = {
type = "fixed",
fixed = podinfo[i].n_box
},
selection_box = {
type = "fixed",
fixed = podinfo[i].s_box
},
groups = {
handy = 1, axey = 1, attached_node_facedir = 1,
dig_by_water = 1, destroy_by_lava_flow = 1, dig_by_piston = 1,
cocoa = i, not_in_creative_inventory = 1,
},
sunlight_propagates = true,
walkable = true,
drop = "mcl_cocoas:cocoa_beans",
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = false,
_mcl_blast_resistance = 3,
_mcl_hardness = 0.2,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
return cocoa_grow(pos)
end,
}
-- Final stage if i == 2 then
crop_def.description = S("Mature Cocoa Pod") def._doc_items_longdesc = nil
crop_def._doc_items_longdesc = S("A mature cocoa pod grew on a jungle tree to its full size and it is ready to be harvested for cocoa beans. It won't grow any further.") def._doc_items_create_entry = false
crop_def._doc_items_create_entry = true end
crop_def.groups.cocoa = 3 if i == 3 then
crop_def.mesh = "mcl_cocoas_cocoa_stage_2.obj" def.drop = "mcl_cocoas:cocoa_beans 3"
crop_def.tiles = {"mcl_cocoas_cocoa_stage_2.png"} def._on_bone_mealing = nil
crop_def.collision_box = { end
type = "fixed",
fixed = { minetest.register_node("mcl_cocoas:cocoa_" .. i, table.copy(def))
{-0.25, -0.3125, -0.0625, 0.25, 0.25, 0.4375}, -- Pod end
},
}
crop_def.selection_box = {
type = "fixed",
fixed = {
{-0.25, -0.3125, -0.0625, 0.25, 0.5, 0.5},
},
}
crop_def.drop = "mcl_cocoas:cocoa_beans 3"
minetest.register_node("mcl_cocoas:cocoa_3", table.copy(crop_def))
minetest.register_craftitem("mcl_cocoas:cocoa_beans", { minetest.register_craftitem("mcl_cocoas:cocoa_beans", {
description = S("Cocoa Beans"), inventory_image = "mcl_cocoa_beans.png",
_tt_help = S("Grows at the side of jungle trees"), _tt_help = S("Grows at the side of jungle trees"),
_doc_items_longdesc = S("Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye."), _doc_items_longdesc = S("Cocoa beans can be used to plant cocoa, bake cookies or cract brown dye."),
_doc_items_usagehelp = S("Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa."), _doc_items_usagehelp = S("Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa."),
inventory_image = "mcl_cocoas_cocoa_beans.png", description = S("Cocoa Beans"),
groups = {craftitem = 1, compostability = 65}, stack_max = 64,
groups = {
craftitem = 1, compostability = 65,
},
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
return cocoa_place(itemstack, placer, pointed_thing, "mcl_cocoas:cocoa_1") return cocoa_place(itemstack, placer, pointed_thing, "mcl_cocoas:cocoa_1")
end, end,

View File

@ -2,7 +2,7 @@
Cocoa Beans=Kakaobohnen Cocoa Beans=Kakaobohnen
Grows at the side of jungle trees=Wächst an der Seite von Dschungelbäumen Grows at the side of jungle trees=Wächst an der Seite von Dschungelbäumen
Cocoa beans can be used to plant cocoa pods, bake chocolate cookies or craft brown dye.=Kakaobohnen können benutzt werden, um Kakao anzupflanzen, Kekse zu backen oder braune Farbstoffe herzustellen. Cocoa beans can be used to plant cocoa pods, bake chocolate cookies or craft brown dye.=Kakaobohnen können benutzt werden, um Kakao anzupflanzen, Kekse zu backen oder braune Farbstoffe herzustellen.
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie auf ein Schaf, um die Wolle braun einzufärben. Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen.
Premature Cocoa Pod=Junge Kakaoschote Premature Cocoa Pod=Junge Kakaoschote
Cocoa pods grow on the side of jungle trees in 3 stages.=Kakaoschoten wachsen an der Seite von Dschungelbäumen in 3 Stufen. Cocoa pods grow on the side of jungle trees in 3 stages.=Kakaoschoten wachsen an der Seite von Dschungelbäumen in 3 Stufen.
Medium Cocoa Pod=Mittelgroße Kakaoschote Medium Cocoa Pod=Mittelgroße Kakaoschote

View File

@ -2,7 +2,7 @@
Cocoa Beans=Granos de cacao Cocoa Beans=Granos de cacao
Grows at the side of jungle trees=Crece al lado de los árboles de la jungla Grows at the side of jungle trees=Crece al lado de los árboles de la jungla
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Los granos de cacao se pueden usar para plantar cacao, hornear galletas o hacer tintes marrones. Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Los granos de cacao se pueden usar para plantar cacao, hornear galletas o hacer tintes marrones.
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en el costado del tronco de un árbol de la jungla para plantar un cacao joven. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en una oveja para convertir su lana en marrón. Haga clic derecho en el costado del tronco de un árbol de la jungla para plantar un cacao joven.
Premature Cocoa Pod=Vaina de cacao prematura Premature Cocoa Pod=Vaina de cacao prematura
Cocoa pods grow on the side of jungle trees in 3 stages.=Las vainas de cacao crecen al lado de los árboles de jungla en 3 etapas. Cocoa pods grow on the side of jungle trees in 3 stages.=Las vainas de cacao crecen al lado de los árboles de jungla en 3 etapas.
Medium Cocoa Pod=Vaina de cacao mediana Medium Cocoa Pod=Vaina de cacao mediana

View File

@ -2,7 +2,7 @@
Cocoa Beans=Fèves de Cacao Cocoa Beans=Fèves de Cacao
Grows at the side of jungle trees=Pousse à côté des arbres de la jungle Grows at the side of jungle trees=Pousse à côté des arbres de la jungle
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Les fèves de cacao peuvent être utilisées pour planter du cacao, faire des biscuits ou fabriquer de la teinture brune. Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Les fèves de cacao peuvent être utilisées pour planter du cacao, faire des biscuits ou fabriquer de la teinture brune.
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacaoyer. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Faites un clic droit sur un mouton pour brunir sa laine. Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacao.
Premature Cocoa Pod=Gousse de cacao prématurée Premature Cocoa Pod=Gousse de cacao prématurée
Cocoa pods grow on the side of jungle trees in 3 stages.=Les cabosses de cacao poussent sur le côté des arbres d'Acajou en 3 étapes. Cocoa pods grow on the side of jungle trees in 3 stages.=Les cabosses de cacao poussent sur le côté des arbres d'Acajou en 3 étapes.
Medium Cocoa Pod=Gousse de cacao moyenne Medium Cocoa Pod=Gousse de cacao moyenne

View File

@ -2,7 +2,7 @@
Cocoa Beans=Ziarna kakaowe Cocoa Beans=Ziarna kakaowe
Grows at the side of jungle trees=Rośnie na boku tropikalnych drzew Grows at the side of jungle trees=Rośnie na boku tropikalnych drzew
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Ziarna kakaowe mogą być używane do sadzenia kakao, pieczenia ciasteczek lub robienia brązowego barwnika. Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Ziarna kakaowe mogą być używane do sadzenia kakao, pieczenia ciasteczek lub robienia brązowego barwnika.
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym aby zafarbować wełnę owcy na brązowo. Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao.
Premature Cocoa Pod=Niedojrzała roślina kakao Premature Cocoa Pod=Niedojrzała roślina kakao
Cocoa pods grow on the side of jungle trees in 3 stages.=Roślina kakao rośnie na bokach tropikalnych drzew w 3 etapach Cocoa pods grow on the side of jungle trees in 3 stages.=Roślina kakao rośnie na bokach tropikalnych drzew w 3 etapach
Medium Cocoa Pod=Średnio-dojrzała roślina kakao Medium Cocoa Pod=Średnio-dojrzała roślina kakao

View File

@ -2,7 +2,7 @@
Cocoa Beans=Какао-бобы Cocoa Beans=Какао-бобы
Grows at the side of jungle trees=Растут на стволах тропических деревьев Grows at the side of jungle trees=Растут на стволах тропических деревьев
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Какао-бобы можно использовать для посадки какао, выпечки печенья или изготовления коричневого красителя. Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=Какао-бобы можно использовать для посадки какао, выпечки печенья или изготовления коричневого красителя.
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по овце, чтобы сделать её шерсть коричневой. Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао.
Premature Cocoa Pod=Молодой стручок какао Premature Cocoa Pod=Молодой стручок какао
Cocoa pods grow on the side of jungle trees in 3 stages.=Стручки какао растут на деревьях джунглей в 3 этапа. Cocoa pods grow on the side of jungle trees in 3 stages.=Стручки какао растут на деревьях джунглей в 3 этапа.
Medium Cocoa Pod=Средний стручок какао Medium Cocoa Pod=Средний стручок какао

View File

@ -2,7 +2,7 @@
Cocoa Beans=可可豆 Cocoa Beans=可可豆
Grows at the side of jungle trees=在叢林木側生長 Grows at the side of jungle trees=在叢林木側生長
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=可可豆可用於種植可可、烘烤餅乾或製作棕色染料。 Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=可可豆可用於種植可可、烘烤餅乾或製作棕色染料。
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊叢林木的一側,可以種植一個可可。 Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊一隻羊,使其羊毛變成褐色。右鍵點擊叢林木的一側,可以種植一個可可。
Premature Cocoa Pod=成長中的可可豆莢第1階段 Premature Cocoa Pod=成長中的可可豆莢第1階段
Cocoa pods grow on the side of jungle trees in 3 stages.=可可莢果分3個階段生長在叢林樹的側面。 Cocoa pods grow on the side of jungle trees in 3 stages.=可可莢果分3個階段生長在叢林樹的側面。
Medium Cocoa Pod=成長中的可可豆莢第2階段 Medium Cocoa Pod=成長中的可可豆莢第2階段

View File

@ -2,7 +2,7 @@
Cocoa Beans= Cocoa Beans=
Grows at the side of jungle trees= Grows at the side of jungle trees=
Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.= Cocoa beans can be used to plant cocoa, bake cookies or craft brown dye.=
Right click on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.= Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=
Premature Cocoa Pod= Premature Cocoa Pod=
Cocoa pods grow on the side of jungle trees in 3 stages.= Cocoa pods grow on the side of jungle trees in 3 stages.=
Medium Cocoa Pod= Medium Cocoa Pod=

View File

@ -1,4 +1,4 @@
name = mcl_cocoas name = mcl_cocoas
description = Cocoa pods which grow at jungle trees. Does not include cocoa beans. description = Cocoa pods which grow at jungle trees. Does not include cocoa beans.
depends = mcl_sounds, mcl_core depends = mcl_sounds, mcl_core, mcl_util
optional_depends = doc optional_depends = doc

View File

@ -11,7 +11,7 @@ local composter_description = S(
"Composter" "Composter"
) )
local composter_longdesc = S( local composter_longdesc = S(
"Composters can convert various organic items into bonemeal." "Composters can convert various organic items into bone meal."
) )
local composter_usagehelp = S( local composter_usagehelp = S(
"Use organic items on the composter to fill it with layers of compost. " .. "Use organic items on the composter to fill it with layers of compost. " ..
@ -48,6 +48,41 @@ local vector_offset = vector.offset
local is_protected = minetest.is_protected local is_protected = minetest.is_protected
local record_protection_violation = minetest.record_protection_violation local record_protection_violation = minetest.record_protection_violation
--- Math and node swap during compost progression
---@param pos Vector Position of the node
---@param node node
---@param chance integer Value of "compostability" group of inserted item
local function composter_progress_chance(pos, node, chance)
-- calculate leveling up chance
local rand = math.random(0,100)
if chance >= rand then
-- get current compost level
local level = registered_nodes[node.name]["_mcl_compost_level"]
-- spawn green particles above new layer
mcl_bone_meal.add_bone_meal_particle(vector_offset(pos, 0, level/8, 0))
-- update composter block
if level < 7 then
level = level + 1
else
level = "ready"
end
swap_node(pos, {name = "mcl_composters:composter_" .. level})
minetest.sound_play({name="default_grass_footstep", gain=0.4}, {
pos = pos,
gain= 0.4,
max_hear_distance = 16,
}, true)
-- a full composter becomes ready for harvest after one second
-- the block will get updated by the node timer callback set in node reg def
if level == 7 then
local timer = get_node_timer(pos)
if not timer:is_started() then
timer:start(1)
end
end
end
end
--- Fill the composter when rightclicked. --- Fill the composter when rightclicked.
-- --
-- `on_rightclick` handler for composter blocks of all fill levels except -- `on_rightclick` handler for composter blocks of all fill levels except
@ -86,41 +121,6 @@ local function composter_add_item(pos, node, player, itemstack, pointed_thing)
return itemstack return itemstack
end end
--- Math and node swap during compost progression
---@param pos Vector Position of the node
---@param node node
---@param chance integer Value of "compostability" group of inserted item
function composter_progress_chance(pos, node, chance)
-- calculate leveling up chance
local rand = math.random(0,100)
if chance >= rand then
-- get current compost level
local level = registered_nodes[node.name]["_mcl_compost_level"]
-- spawn green particles above new layer
mcl_dye.add_bone_meal_particle(vector_offset(pos, 0, level/8, 0))
-- update composter block
if level < 7 then
level = level + 1
else
level = "ready"
end
swap_node(pos, {name = "mcl_composters:composter_" .. level})
minetest.sound_play({name="default_grass_footstep", gain=0.4}, {
pos = pos,
gain= 0.4,
max_hear_distance = 16,
}, true)
-- a full composter becomes ready for harvest after one second
-- the block will get updated by the node timer callback set in node reg def
if level == 7 then
local timer = get_node_timer(pos)
if not timer:is_started() then
timer:start(1)
end
end
end
end
--- Update a full composter block to ready for harvesting. --- Update a full composter block to ready for harvesting.
-- --
-- `on_timer` handler. The timer is set in function 'composter_add_item' -- `on_timer` handler. The timer is set in function 'composter_add_item'
@ -203,7 +203,7 @@ end
-- --
minetest.register_node("mcl_composters:composter", { minetest.register_node("mcl_composters:composter", {
description = composter_description, description = composter_description,
_tt_help = S("Converts organic items into bonemeal"), _tt_help = S("Converts organic items into bone meal"),
_doc_items_longdesc = composter_longdesc, _doc_items_longdesc = composter_longdesc,
_doc_items_usagehelp = composter_usagehelp, _doc_items_usagehelp = composter_usagehelp,
paramtype = "light", paramtype = "light",

View File

@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=Les composteurs peuv
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Utiliser des objets organiques sur le composteur pour le remplir de couches de compost. Chaque fois qu'un objet est mis dans le composteur, il y a une chance d'ajouter une nouvelle couche de compost au composteur. Certains objets ont une plus grande chance que d'autres d'ajouter une couche supplémentaire. Après l'avoir rempli de 7 couches de compost, le composteur est plein. Après un délai d'approximativement une seconde, le composteur est prêt et on peut récupérer la farine d'os. Cliquer droit le composteur permet de récupérer la farine d'os et de vider le composteur. Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Utiliser des objets organiques sur le composteur pour le remplir de couches de compost. Chaque fois qu'un objet est mis dans le composteur, il y a une chance d'ajouter une nouvelle couche de compost au composteur. Certains objets ont une plus grande chance que d'autres d'ajouter une couche supplémentaire. Après l'avoir rempli de 7 couches de compost, le composteur est plein. Après un délai d'approximativement une seconde, le composteur est prêt et on peut récupérer la farine d'os. Cliquer droit le composteur permet de récupérer la farine d'os et de vider le composteur.
filled=rempli filled=rempli
ready for harvest=prêt pour la récolte ready for harvest=prêt pour la récolte
Converts organic items into bonemeal=Convertit les objets organiques en farine d'os. Converts organic items into bone meal=Convertit les objets organiques en farine d'os.

View File

@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=コンポスター
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter."=コンポスターに有機物を入れて、堆肥の層を作りましょう。コンポスターに有機物を入れるたびに、次の堆肥の層が追加されるチャンスが起きます。 追加される確率がより高くなっているアイテムもいくつかあります。 7層分の堆肥が充填されると、コンポスターは満杯となります。その約1秒後に、骨粉を取り出せる準備が完了します。右クリックして骨粉を取り出すと、コンポスターは空になります。 Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter."=コンポスターに有機物を入れて、堆肥の層を作りましょう。コンポスターに有機物を入れるたびに、次の堆肥の層が追加されるチャンスが起きます。 追加される確率がより高くなっているアイテムもいくつかあります。 7層分の堆肥が充填されると、コンポスターは満杯となります。その約1秒後に、骨粉を取り出せる準備が完了します。右クリックして骨粉を取り出すと、コンポスターは空になります。
filled=充足 filled=充足
ready for harvest=収穫可能 ready for harvest=収穫可能
Converts organic items into bonemeal=有機物を骨粉に変える Converts organic items into bone meal=有機物を骨粉に変える

View File

@ -4,4 +4,4 @@ Composters can convert various organic items into bonemeal.=Компостер
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Используйте органические предметы на компостере, чтобы заполнить его слоями перегноя. Каждый раз когда в компостер попадает предмет, есть шанс что в компостере появится новый слой перегноя. Некоторые предметы имеют больший шанс на появление нового слоя. После заполнения 7 слоями перегноя, компостер можно опустошить, забрав из него костную муку. После задержки в одну секунду компостер будет готов и костная мука будет извлечена из него. Правым кликом по компостеру чтобы забрать костную муку. Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=Используйте органические предметы на компостере, чтобы заполнить его слоями перегноя. Каждый раз когда в компостер попадает предмет, есть шанс что в компостере появится новый слой перегноя. Некоторые предметы имеют больший шанс на появление нового слоя. После заполнения 7 слоями перегноя, компостер можно опустошить, забрав из него костную муку. После задержки в одну секунду компостер будет готов и костная мука будет извлечена из него. Правым кликом по компостеру чтобы забрать костную муку.
filled=заполнен filled=заполнен
ready for harvest=готов к сбору ready for harvest=готов к сбору
Converts organic items into bonemeal=Перерабатывает органику в костную муку Converts organic items into bone meal=Перерабатывает органику в костную муку

View File

@ -1,7 +1,7 @@
# textdomain: mcl_composters # textdomain: mcl_composters
Composter= Composter=
Composters can convert various organic items into bonemeal.= Composters can convert various organic items into bone meal.=
Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.= Use organic items on the composter to fill it with layers of compost. Every time an item is put in the composter, there is a chance that the composter adds another layer of compost. Some items have a bigger chance of adding an extra layer than other items. After filling up with 7 layers of compost, the composter is full. After a delay of approximately one second the composter becomes ready and bone meal can be retrieved from it. Right-clicking the composter takes out the bone meal empties the composter.=
filled= filled=
ready for harvest= ready for harvest=
Converts organic items into bonemeal= Converts organic items into bone meal=

View File

@ -1,5 +1,5 @@
name = mcl_composters name = mcl_composters
author = kabou author = kabou
description = Composters can convert various organic items into bonemeal. description = Composters can convert various organic items into bonemeal.
depends = mcl_core, mcl_sounds, mcl_dye, mcl_hoppers depends = mcl_core, mcl_sounds, mcl_bone_meal, mcl_hoppers
optional_depends = doc optional_depends = doc

File diff suppressed because it is too large Load Diff

View File

@ -772,6 +772,7 @@ minetest.register_node("mcl_core:cobble", {
sounds = mcl_sounds.node_sound_stone_defaults(), sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 6, _mcl_blast_resistance = 6,
_mcl_hardness = 2, _mcl_hardness = 2,
_vl_crushing_drop = { "mcl_core:gravel" }
}) })
minetest.register_node("mcl_core:mossycobble", { minetest.register_node("mcl_core:mossycobble", {

View File

@ -280,6 +280,14 @@ function mcl_core.register_sapling(subname, description, longdesc, tt_help, text
nn == "mcl_core:podzol" or nn == "mcl_core:podzol_snow" or nn == "mcl_core:podzol" or nn == "mcl_core:podzol_snow" or
nn == "mcl_core:dirt" or nn == "mcl_core:mycelium" or nn == "mcl_core:coarse_dirt" nn == "mcl_core:dirt" or nn == "mcl_core:mycelium" or nn == "mcl_core:coarse_dirt"
end), end),
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
-- Saplings: 45% chance to advance growth stage
if math.random(1,100) <= 45 then
return mcl_core.grow_sapling(pos, n)
end
end,
node_placement_prediction = "", node_placement_prediction = "",
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_mcl_hardness = 0, _mcl_hardness = 0,

View File

@ -5,6 +5,8 @@ local modpath = minetest.get_modpath(modname)
-- by debiankaios -- by debiankaios
-- adapted for mcl2 by cora -- adapted for mcl2 by cora
local MAXIMUM_VINE_HEIGHT = 25
local wood_slab_groups = {handy = 1, axey = 1, material_wood = 1, wood_slab = 1} local wood_slab_groups = {handy = 1, axey = 1, material_wood = 1, wood_slab = 1}
local wood_stair_groups = {handy = 1, axey = 1, material_wood = 1, wood_stairs = 1} local wood_stair_groups = {handy = 1, axey = 1, material_wood = 1, wood_stairs = 1}
@ -16,21 +18,36 @@ function generate_crimson_tree(pos)
minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_1.mts","random",nil,false,"place_center_x,place_center_z") minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_1.mts","random",nil,false,"place_center_x,place_center_z")
end end
function grow_vines(pos, moreontop ,vine, dir) function grow_vines(pos, moreontop, vine, dir)
-- Sanity checks
if dir == nil then dir = 1 end if dir == nil then dir = 1 end
local n if not moreontop or moreontop < 1 then return false end
repeat
pos = vector.offset(pos,0,dir,0) local allowed_nodes = {}
n = minetest.get_node(pos) allowed_nodes[vine] = true
if n.name == "air" then
for i=0,math.max(moreontop,1) do -- Find the root, tip and calculate height
if minetest.get_node(pos).name == "air" then local root,_,root_node = mcl_util.trace_nodes(pos, -dir, allowed_nodes, MAXIMUM_VINE_HEIGHT)
minetest.set_node(vector.offset(pos,0,i*dir,0),{name=vine}) if not root then return false end
end local tip,height,tip_node = mcl_util.trace_nodes(vector.offset(root, 0, dir, 0), dir, allowed_nodes, MAXIMUM_VINE_HEIGHT)
end if not tip then return false end
break
end local res = false
until n.name ~= "air" and n.name ~= vine for i = 1,moreontop do
-- Check if we can grow into this position
if height >= MAXIMUM_VINE_HEIGHT then return res end
if tip_node.name ~= "air" then return res end
-- Update world map data
minetest.set_node(tip, {name = vine})
-- Move to the next position and flag that growth has occured
tip = vector.offset(tip, 0, dir, 0)
tip_node = minetest.get_node(tip)
height = height + 1
res = true
end
return res
end end
local nether_plants = { local nether_plants = {
@ -83,17 +100,20 @@ minetest.register_node("mcl_crimson:warped_fungus", {
light_source = 1, light_source = 1,
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
node_placement_prediction = "", node_placement_prediction = "",
on_rightclick = function(pos, node, pointed_thing, player, itemstack) _on_bone_meal = function(itemstack, placer, pointed_thing)
if pointed_thing:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then local pos = pointed_thing.under
local nodepos = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}) local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0))
if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then
local random = math.random(1, 5) if nodepos.name == "mcl_crimson:warped_nylium" or nodepos.name == "mcl_nether:netherrack" then
if random == 1 then local random = math.random(1, 5)
minetest.remove_node(pos) if random == 1 then
generate_warped_tree(pos) minetest.remove_node(pos)
end generate_warped_tree(pos)
return true
end end
end end
return false
end, end,
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })
@ -102,6 +122,12 @@ mcl_flowerpots.register_potted_flower("mcl_crimson:warped_fungus", {
name = "warped_fungus", name = "warped_fungus",
desc = S("Warped Fungus"), desc = S("Warped Fungus"),
image = "mcl_crimson_warped_fungus.png", image = "mcl_crimson_warped_fungus.png",
_on_bone_meal = function(itemstack, placer, pointed_thing)
local n = has_nylium_neighbor(pointed_thing.under)
if n then
minetest.set_node(pointed_thing.under,n)
end
end,
}) })
minetest.register_node("mcl_crimson:twisting_vines", { minetest.register_node("mcl_crimson:twisting_vines", {
@ -121,6 +147,9 @@ minetest.register_node("mcl_crimson:twisting_vines", {
fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 }, fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 },
}, },
node_placement_prediction = "", node_placement_prediction = "",
_on_bone_meal = function(itemstack, placer, pointed_thing)
return grow_vines(pointed_thing.under, math.random(1, 3),"mcl_crimson:twisting_vines")
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local pn = clicker:get_player_name() local pn = clicker:get_player_name()
if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then
@ -141,26 +170,28 @@ minetest.register_node("mcl_crimson:twisting_vines", {
end end
elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then return mcl_bone_meal.use_bone_meal(itemstack, clicker, {under=pos, above=pos})
itemstack:take_item()
end
grow_vines(pos, math.random(1, 3),"mcl_crimson:twisting_vines")
end end
return itemstack return itemstack
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under local under = pointed_thing.under
local above = pointed_thing.above
local unode = minetest.get_node(under) local unode = minetest.get_node(under)
local unode_def = minetest.registered_nodes[unode.name]
local above = pointed_thing.above
local anode = minetest.get_node(above)
local anode_def = minetest.registered_nodes[anode.name]
if under.y < above.y then if under.y < above.y then
minetest.set_node(above, {name = "mcl_crimson:twisting_vines"}) minetest.set_node(above, {name = "mcl_crimson:twisting_vines"})
if not minetest.is_creative_enabled(placer:get_player_name()) then if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
else elseif unode_def and unode_def.on_rightclick then
if unode.name == "mcl_crimson:twisting_vines" then return unode_def.on_rightclick(under, unode, placer, itemstack, pointed_thing)
return minetest.registered_nodes[unode.name].on_rightclick(under, unode, placer, itemstack, pointed_thing) elseif anode_def and anode_def.on_rightclick then
end return unode_def.on_rightclick(above, anode, placer, itemstack, pointed_thing)
end end
return itemstack return itemstack
end, end,
@ -168,7 +199,7 @@ minetest.register_node("mcl_crimson:twisting_vines", {
local above = vector.offset(pos,0,1,0) local above = vector.offset(pos,0,1,0)
local abovenode = minetest.get_node(above) local abovenode = minetest.get_node(above)
minetest.node_dig(pos, node, digger) minetest.node_dig(pos, node, digger)
if abovenode.name == node.name and (not mcl_core.check_vines_supported(above, abovenode)) then if abovenode.name == node.name then
minetest.registered_nodes[node.name].on_dig(above, node, digger) minetest.registered_nodes[node.name].on_dig(above, node, digger)
end end
end, end,
@ -211,6 +242,9 @@ minetest.register_node("mcl_crimson:weeping_vines", {
fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 }, fixed = { -3/16, -0.5, -3/16, 3/16, 0.5, 3/16 },
}, },
node_placement_prediction = "", node_placement_prediction = "",
_on_bone_meal = function(itemstack, placer, pointed_thing)
return grow_vines(pointed_thing.under, math.random(1, 3),"mcl_crimson:weeping_vines", -1)
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local pn = clicker:get_player_name() local pn = clicker:get_player_name()
if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then if clicker:is_player() and minetest.is_protected(vector.offset(pos,0,1,0), pn or "") then
@ -231,26 +265,28 @@ minetest.register_node("mcl_crimson:weeping_vines", {
end end
elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then elseif clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
if not minetest.is_creative_enabled(clicker:get_player_name()) then return mcl_bone_meal.use_bone_meal(itemstack, clicker, {under=pos, above=pos})
itemstack:take_item()
end
grow_vines(pos, math.random(1, 3),"mcl_crimson:weeping_vines", -1)
end end
return itemstack return itemstack
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under local under = pointed_thing.under
local above = pointed_thing.above
local unode = minetest.get_node(under) local unode = minetest.get_node(under)
local unode_def = minetest.registered_nodes[unode.name]
local above = pointed_thing.above
local anode = minetest.get_node(above)
local anode_def = minetest.registered_nodes[anode.name]
if under.y > above.y then if under.y > above.y then
minetest.set_node(above, {name = "mcl_crimson:weeping_vines"}) minetest.set_node(above, {name = "mcl_crimson:weeping_vines"})
if not minetest.is_creative_enabled(placer:get_player_name()) then if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item() itemstack:take_item()
end end
else elseif unode_def and unode_def.on_rightclick then
if unode.name == "mcl_crimson:weeping_vines" then return unode_def.on_rightclick(under, unode, placer, itemstack, pointed_thing)
return minetest.registered_nodes[unode.name].on_rightclick(under, unode, placer, itemstack, pointed_thing) elseif anode_def and anode_def.on_rightclick then
end return unode_def.on_rightclick(above, anode, placer, itemstack, pointed_thing)
end end
return itemstack return itemstack
end, end,
@ -258,7 +294,7 @@ minetest.register_node("mcl_crimson:weeping_vines", {
local below = vector.offset(pos,0,-1,0) local below = vector.offset(pos,0,-1,0)
local belownode = minetest.get_node(below) local belownode = minetest.get_node(below)
minetest.node_dig(pos, node, digger) minetest.node_dig(pos, node, digger)
if belownode.name == node.name and (not mcl_core.check_vines_supported(below, belownode)) then if belownode.name == node.name then
minetest.registered_nodes[node.name].on_dig(below, node, digger) minetest.registered_nodes[node.name].on_dig(below, node, digger)
end end
end, end,
@ -393,6 +429,11 @@ minetest.register_node("mcl_crimson:warped_nylium", {
_mcl_hardness = 0.4, _mcl_hardness = 0.4,
_mcl_blast_resistance = 0.4, _mcl_blast_resistance = 0.4,
_mcl_silk_touch_drop = true, _mcl_silk_touch_drop = true,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local node = minetest.get_node(pointed_thing.under)
spread_nether_plants(pointed_thing.under,node)
return true
end,
}) })
--Stem bark, stripped stem and bark --Stem bark, stripped stem and bark
@ -525,17 +566,21 @@ minetest.register_node("mcl_crimson:crimson_fungus", {
fixed = { -3/16, -0.5, -3/16, 3/16, -2/16, 3/16 }, fixed = { -3/16, -0.5, -3/16, 3/16, -2/16, 3/16 },
}, },
node_placement_prediction = "", node_placement_prediction = "",
on_rightclick = function(pos, node, pointed_thing, player) _on_bone_meal = function(itemstack, placer, pointed_thing)
if pointed_thing:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then local pos = pointed_thing.under
local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0)) local nodepos = minetest.get_node(vector.offset(pos, 0, -1, 0))
if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then if nodepos.name == "mcl_crimson:crimson_nylium" or nodepos.name == "mcl_nether:netherrack" then
local random = math.random(1, 5) local random = math.random(1, 5)
if random == 1 then if random == 1 then
minetest.remove_node(pos) minetest.remove_node(pos)
generate_crimson_tree(pos) generate_crimson_tree(pos)
end
return true
end end
end end
-- Failed to spread nylium
return false
end, end,
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })
@ -682,6 +727,11 @@ minetest.register_node("mcl_crimson:crimson_nylium", {
_mcl_hardness = 0.4, _mcl_hardness = 0.4,
_mcl_blast_resistance = 0.4, _mcl_blast_resistance = 0.4,
_mcl_silk_touch_drop = true, _mcl_silk_touch_drop = true,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local node = minetest.get_node(pointed_thing.under)
spread_nether_plants(pointed_thing.under,node)
return true
end,
}) })
minetest.register_craft({ minetest.register_craft({
@ -723,19 +773,6 @@ minetest.register_craft({
mcl_stairs.register_stair("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_stair_groups, false, S("Crimson Stair")) mcl_stairs.register_stair("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_stair_groups, false, S("Crimson Stair"))
mcl_stairs.register_slab("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_slab_groups, false, S("Crimson Slab")) mcl_stairs.register_slab("crimson_hyphae_wood", "mcl_crimson:crimson_hyphae_wood", wood_slab_groups, false, S("Crimson Slab"))
mcl_dye.register_on_bone_meal_apply(function(pt,user)
if not pt.type == "node" then return end
local node = minetest.get_node(pt.under)
if node.name == "mcl_nether:netherrack" then
local n = has_nylium_neighbor(pt.under)
if n then
minetest.set_node(pt.under,n)
end
elseif node.name == "mcl_crimson:warped_nylium" or node.name == "mcl_crimson:crimson_nylium" then
spread_nether_plants(pt.under,node)
end
end)
minetest.register_abm({ minetest.register_abm({
label = "Turn Crimson Nylium and Warped Nylium below solid block into Netherrack", label = "Turn Crimson Nylium and Warped Nylium below solid block into Netherrack",
nodenames = {"mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium"}, nodenames = {"mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium"},

View File

@ -1,14 +0,0 @@
# mcl_dye
# Bone meal API
Callback and particle functions.
## mcl_dye.add_bone_meal_particle(pos, def)
Spawns standard or custom bone meal particles.
* `pos`: position, is ignored if you define def.minpos and def.maxpos
* `def`: (optional) particle definition
## mcl_dye.register_on_bone_meal_apply(function(pointed_thing, user))
Called when the bone meal is applied anywhere.
* `pointed_thing`: exact pointing location (see Minetest API), where the bone meal is applied
* `user`: ObjectRef of the player who aplied the bone meal, can be nil!

View File

@ -15,7 +15,6 @@ mcl_dye = {}
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
local math = math
local string = string local string = string
-- Base color groups: -- Base color groups:
@ -115,328 +114,23 @@ for _, row in pairs(dyes) do
}) })
end end
-- Bone meal code to be moved into its own mod. -- Legacy support for things now in mcl_bone_meal.
-- These shims will at some time in the future be removed.
-- --
function mcl_dye.add_bone_meal_particle(pos, def) function mcl_dye.add_bone_meal_particle(pos, def)
if not def then minetest.log("warning", "mcl_dye.add_bone_meal_particles() is deprecated. Read mcl_bone_meal/API.md!")
def = {} local lines = string.split(debug.traceback(),"\n")
for _,line in ipairs(lines) do
minetest.log("warning",line)
end end
minetest.add_particlespawner({ mcl_bone_meal.add_bone_meal_particle(pos, def)
amount = def.amount or 10,
time = def.time or 0.1,
minpos = def.minpos or vector.subtract(pos, 0.5),
maxpos = def.maxpos or vector.add(pos, 0.5),
minvel = def.minvel or vector.new(-0.01, 0.01, -0.01),
maxvel = def.maxvel or vector.new(0.01, 0.01, 0.01),
minacc = def.minacc or vector.new(0, 0, 0),
maxacc = def.maxacc or vector.new(0, 0, 0),
minexptime = def.minexptime or 1,
maxexptime = def.maxexptime or 4,
minsize = def.minsize or 0.7,
maxsize = def.maxsize or 2.4,
texture = "mcl_particles_bonemeal.png^[colorize:#00EE00:125", -- TODO: real MC color
glow = def.glow or 1,
})
end end
mcl_dye.bone_meal_callbacks = {}
function mcl_dye.register_on_bone_meal_apply(func) function mcl_dye.register_on_bone_meal_apply(func)
table.insert(mcl_dye.bone_meal_callbacks, func) minetest.log("warning", "mcl_dye.register_on_bone_meal_apply() is deprecated. Read mcl_bone_meal/API.md!")
mcl_bone_meal.register_on_bone_meal_apply(func)
end end
local function apply_bone_meal(pointed_thing, user)
-- Bone meal currently spawns all flowers found in the plains.
local flowers_table_plains = {
"mcl_flowers:dandelion",
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
"mcl_flowers:oxeye_daisy",
"mcl_flowers:tulip_orange",
"mcl_flowers:tulip_red",
"mcl_flowers:tulip_white",
"mcl_flowers:tulip_pink",
"mcl_flowers:azure_bluet",
}
local flowers_table_simple = {
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
}
local flowers_table_swampland = {
"mcl_flowers:blue_orchid",
}
local flowers_table_flower_forest = {
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
"mcl_flowers:oxeye_daisy",
"mcl_flowers:tulip_orange",
"mcl_flowers:tulip_red",
"mcl_flowers:tulip_white",
"mcl_flowers:tulip_pink",
"mcl_flowers:azure_bluet",
"mcl_flowers:allium",
}
local pos = pointed_thing.under
local n = minetest.get_node(pos)
if n.name == "" then return false end
if mcl_util.check_area_protection(pos, pointed_thing.above, user) then
return false
end
for _, func in pairs(mcl_dye.bone_meal_callbacks) do
if func(pointed_thing, user) then
return true
end
end
if minetest.get_item_group(n.name, "sapling") >= 1 then
mcl_dye.add_bone_meal_particle(pos)
-- Saplings: 45% chance to advance growth stage
if math.random(1, 100) <= 45 then
if n.name == "mcl_cherry_blossom:cherrysapling" then
return mcl_cherry_blossom.generate_cherry_tree(pos) -- If cherry blossom sapling, run that callback instead.
else
return mcl_core.grow_sapling(pos, n)
end
end
elseif minetest.get_item_group(n.name, "mushroom") == 1 then
mcl_dye.add_bone_meal_particle(pos)
-- Try to grow huge mushroom
-- Must be on a dirt-type block
local below = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
if below.name ~= "mcl_core:mycelium" and below.name ~= "mcl_core:dirt" and minetest.get_item_group(below.name, "grass_block") ~= 1 and below.name ~= "mcl_core:coarse_dirt" and below.name ~= "mcl_core:podzol" then
return false
end
-- Select schematic
local schematic, offset, height
if n.name == "mcl_mushrooms:mushroom_brown" then
schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_brown.mts"
offset = { x = -3, y = -1, z = -3 }
height = 8
elseif n.name == "mcl_mushrooms:mushroom_red" then
schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_red.mts"
offset = { x = -2, y = -1, z = -2 }
height = 8
else
return false
end
-- 40% chance
if math.random(1, 100) <= 40 then
-- Check space requirements
for i=1,3 do
local cpos = vector.add(pos, {x=0, y=i, z=0})
if minetest.get_node(cpos).name ~= "air" then
return false
end
end
local yoff = 3
local minp, maxp = {x=pos.x-3, y=pos.y+yoff, z=pos.z-3}, {x=pos.x+3, y=pos.y+yoff+(height-3), z=pos.z+3}
local diff = vector.subtract(maxp, minp)
diff = vector.add(diff, {x=1,y=1,z=1})
local totalnodes = diff.x * diff.y * diff.z
local goodnodes = minetest.find_nodes_in_area(minp, maxp, {"air", "group:leaves"})
if #goodnodes < totalnodes then
return false
end
-- Place the huge mushroom
minetest.remove_node(pos)
local place_pos = vector.add(pos, offset)
local ok = minetest.place_schematic(place_pos, schematic, 0, nil, false)
return ok ~= nil
end
return false
-- Wheat, Potato, Carrot, Pumpkin Stem, Melon Stem: Advance by 2-5 stages
elseif string.find(n.name, "mcl_farming:wheat_") then
mcl_dye.add_bone_meal_particle(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_wheat", pos, n, stages, true)
elseif string.find(n.name, "mcl_farming:potato_") then
mcl_dye.add_bone_meal_particle(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_potato", pos, n, stages, true)
elseif string.find(n.name, "mcl_farming:carrot_") then
mcl_dye.add_bone_meal_particle(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_carrot", pos, n, stages, true)
elseif string.find(n.name, "mcl_farming:pumpkin_") then
mcl_dye.add_bone_meal_particle(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_pumpkin_stem", pos, n, stages, true)
elseif string.find(n.name, "mcl_farming:melontige_") then
mcl_dye.add_bone_meal_particle(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_melon_stem", pos, n, stages, true)
elseif string.find(n.name, "mcl_farming:beetroot_") then
mcl_dye.add_bone_meal_particle(pos)
-- Beetroot: 75% chance to advance to next stage
if math.random(1, 100) <= 75 then
return mcl_farming:grow_plant("plant_beetroot", pos, n, 1, true)
end
elseif string.find(n.name, "mcl_farming:sweet_berry_bush_") then
mcl_dye.add_bone_meal_particle(pos)
if n.name == "mcl_farming:sweet_berry_bush_3" then
return minetest.add_item(vector.offset(pos,math.random()-0.5,math.random()-0.5,math.random()-0.5),"mcl_farming:sweet_berry")
else
return mcl_farming:grow_plant("plant_sweet_berry_bush", pos, n, 1, true)
end
elseif n.name == "mcl_cocoas:cocoa_1" or n.name == "mcl_cocoas:cocoa_2" then
mcl_dye.add_bone_meal_particle(pos)
-- Cocoa: Advance by 1 stage
mcl_cocoas.grow(pos)
return true
elseif minetest.get_item_group(n.name, "grass_block") == 1 then
-- Grass Block: Generate tall grass and random flowers all over the place
for i = -7, 7 do
for j = -7, 7 do
for y = -1, 1 do
pos = vector.offset(pointed_thing.above, i, y, j)
n = minetest.get_node(pos)
local n2 = minetest.get_node(vector.offset(pos, 0, -1, 0))
if n.name ~= "" and n.name == "air" and (minetest.get_item_group(n2.name, "grass_block_no_snow") == 1) then
-- Randomly generate flowers, tall grass or nothing
if math.random(1, 100) <= 90 / ((math.abs(i) + math.abs(j)) / 2)then
-- 90% tall grass, 10% flower
mcl_dye.add_bone_meal_particle(pos, {amount = 4})
if math.random(1,100) <= 90 then
local col = n2.param2
minetest.add_node(pos, {name="mcl_flowers:tallgrass", param2=col})
else
local flowers_table
if mg_name == "v6" then
flowers_table = flowers_table_plains
else
local biome = minetest.get_biome_name(minetest.get_biome_data(pos).biome)
if biome == "Swampland" or biome == "Swampland_shore" or biome == "Swampland_ocean" or biome == "Swampland_deep_ocean" or biome == "Swampland_underground" then
flowers_table = flowers_table_swampland
elseif biome == "FlowerForest" or biome == "FlowerForest_beach" or biome == "FlowerForest_ocean" or biome == "FlowerForest_deep_ocean" or biome == "FlowerForest_underground" then
flowers_table = flowers_table_flower_forest
elseif biome == "Plains" or biome == "Plains_beach" or biome == "Plains_ocean" or biome == "Plains_deep_ocean" or biome == "Plains_underground" or biome == "SunflowerPlains" or biome == "SunflowerPlains_ocean" or biome == "SunflowerPlains_deep_ocean" or biome == "SunflowerPlains_underground" then
flowers_table = flowers_table_plains
else
flowers_table = flowers_table_simple
end
end
minetest.add_node(pos, {name=flowers_table[math.random(1, #flowers_table)]})
end
end
end
end
end
end
return true
-- Double flowers: Drop corresponding item
elseif n.name == "mcl_flowers:rose_bush" or n.name == "mcl_flowers:rose_bush_top" then
mcl_dye.add_bone_meal_particle(pos)
minetest.add_item(pos, "mcl_flowers:rose_bush")
return true
elseif n.name == "mcl_flowers:peony" or n.name == "mcl_flowers:peony_top" then
mcl_dye.add_bone_meal_particle(pos)
minetest.add_item(pos, "mcl_flowers:peony")
return true
elseif n.name == "mcl_flowers:lilac" or n.name == "mcl_flowers:lilac_top" then
mcl_dye.add_bone_meal_particle(pos)
minetest.add_item(pos, "mcl_flowers:lilac")
return true
elseif n.name == "mcl_flowers:sunflower" or n.name == "mcl_flowers:sunflower_top" then
mcl_dye.add_bone_meal_particle(pos)
minetest.add_item(pos, "mcl_flowers:sunflower")
return true
elseif n.name == "mcl_flowers:tallgrass" then
mcl_dye.add_bone_meal_particle(pos)
-- Tall Grass: Grow into double tallgrass
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
local topnode = minetest.get_node(toppos)
if minetest.registered_nodes[topnode.name].buildable_to then
minetest.set_node(pos, { name = "mcl_flowers:double_grass", param2 = n.param2 })
minetest.set_node(toppos, { name = "mcl_flowers:double_grass_top", param2 = n.param2 })
return true
end
--[[
Here for when Bonemeal becomes an api, there's code if needed for handling applying to bamboo.
-- Handle applying bonemeal to bamboo.
elseif mcl_bamboo.is_bamboo(n.name) then
local success = mcl_bamboo.grow_bamboo(pos, true)
if success then
mcl_dye.add_bone_meal_particle(pos)
end
return success
--]]
elseif n.name == "mcl_flowers:fern" then
mcl_dye.add_bone_meal_particle(pos)
-- Fern: Grow into large fern
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
local topnode = minetest.get_node(toppos)
if minetest.registered_nodes[topnode.name].buildable_to then
minetest.set_node(pos, { name = "mcl_flowers:double_fern", param2 = n.param2 })
minetest.set_node(toppos, { name = "mcl_flowers:double_fern_top", param2 = n.param2 })
return true
end
end
return false
end
mcl_dye.apply_bone_meal = apply_bone_meal
-- Bone meal item registration.
--
-- To be moved into its own mod.
--
minetest.register_craftitem(":mcl_bone_meal:bone_meal", {
inventory_image = "mcl_bone_meal_bone_meal.png",
description = S("Bone Meal"),
_tt_help = S("Speeds up plant growth"),
_doc_items_longdesc = S("Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants."),
_doc_items_usagehelp = S("Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place."),
stack_max = 64,
on_place = function(itemstack, user, pointed_thing)
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node(pointed_thing.under)
if user and not user:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
end
end
-- Use the bone meal on the ground
if (apply_bone_meal(pointed_thing, user) and (not minetest.is_creative_enabled(user:get_player_name()))) then
itemstack:take_item()
end
return itemstack
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Apply bone meal, if possible
local pointed_thing
if dropnode.name == "air" then
pointed_thing = { above = droppos, under = { x=droppos.x, y=droppos.y-1, z=droppos.z } }
else
pointed_thing = { above = pos, under = droppos }
end
local success = apply_bone_meal(pointed_thing, nil)
if success then
stack:take_item()
end
return stack
end,
_dispense_into_walkable = true
})
minetest.register_craft({
output = "mcl_bone_meal:bone_meal 3",
recipe = {{"mcl_mobitems:bone"}},
})
-- Dye creation recipes. -- Dye creation recipes.
-- --
minetest.register_craft({ minetest.register_craft({
@ -609,19 +303,16 @@ minetest.register_craft({
output = "mcl_dye:magenta 2", output = "mcl_dye:magenta 2",
recipe = {"mcl_dye:violet", "mcl_dye:pink"}, recipe = {"mcl_dye:violet", "mcl_dye:pink"},
}) })
minetest.register_craft({ minetest.register_craft({
type = "shapeless", type = "shapeless",
output = "mcl_dye:pink 2", output = "mcl_dye:pink 2",
recipe = {"mcl_dye:red", "mcl_dye:white"}, recipe = {"mcl_dye:red", "mcl_dye:white"},
}) })
minetest.register_craft({ minetest.register_craft({
type = "shapeless", type = "shapeless",
output = "mcl_dye:cyan 2", output = "mcl_dye:cyan 2",
recipe = {"mcl_dye:blue", "mcl_dye:dark_green"}, recipe = {"mcl_dye:blue", "mcl_dye:dark_green"},
}) })
minetest.register_craft({ minetest.register_craft({
type = "shapeless", type = "shapeless",
output = "mcl_dye:violet 2", output = "mcl_dye:violet 2",

View File

@ -17,11 +17,3 @@ Magenta Dye=Magenta Farbstoff
Pink Dye=Rosa Farbstoff Pink Dye=Rosa Farbstoff
This item is a dye which is used for dyeing and crafting.=Dieser Gegenstand ist ein Farbstoff, der zum Einfärben und in der Herstellung benutzt werden kann. This item is a dye which is used for dyeing and crafting.=Dieser Gegenstand ist ein Farbstoff, der zum Einfärben und in der Herstellung benutzt werden kann.
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Rechtsklicken Sie auf ein Schaf, um seine Wolle zu färben. Andere Dinge werden mit der Fertigung eingefärbt. Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Rechtsklicken Sie auf ein Schaf, um seine Wolle zu färben. Andere Dinge werden mit der Fertigung eingefärbt.
Bone Meal=Knochenmehl
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Knochenmehl ist ein weißer Farbstoff und auch nützlich als Dünger, um das Wachstum vieler Pflanzen zu beschleunigen.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Rechtsklicken Sie auf ein Schaf, um die Wolle weiß einzufärben. Rechtsklicken Sie auf eine Pflanze, um ihr Wachstum zu beschleunigen. Beachten Sie, dass nicht alle Pflanzen darauf ansprechen. Benutzen Sie es auf einem Grasblock, wächst viel hohes Gras und vielleicht auch ein paar Blumen.
Cocoa beans are a brown dye and can be used to plant cocoas.=Kakaobohnen sind ein brauner Farbstoff und werden benutzt, um Kakao anzupflanzen.
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Rechtsklicken Sie auf ein Schaf, um die Wolle braun einzufärben. Rechtsklicken Sie an die Seite eines Dschungelbaumstamms (Dschungelholz), um eine junge Kakaoschote zu pflanzen.
Cocoa Beans=Kakaobohnen
Grows at the side of jungle trees=Wächst an der Seite von Dschungelbäumen
Speeds up plant growth=Beschleunigt Pflanzenwachstum

View File

@ -17,9 +17,3 @@ Magenta Dye=Tinte magenta
Pink Dye=Tinte rosado Pink Dye=Tinte rosado
This item is a dye which is used for dyeing and crafting.=Este artículo es un tinte que se utiliza para teñir y elaborar. This item is a dye which is used for dyeing and crafting.=Este artículo es un tinte que se utiliza para teñir y elaborar.
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Haga clic derecho sobre una oveja para teñir su lana. Otras cosas pueden ser teñidas mediante la elaboración. Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Haga clic derecho sobre una oveja para teñir su lana. Otras cosas pueden ser teñidas mediante la elaboración.
Bone Meal=Harina de hueso
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La harina de hueso es un tinte blanco y también es útil como fertilizante para acelerar el crecimiento de muchas plantas.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=RHaga clic derecho en una oveja para volver su lana blanca. Haga clic derecho en una planta para acelerar su crecimiento. Tenga en cuenta que no todas las plantas pueden ser fertilizadas de esta manera. Cuando haces clic derecho en un bloque de hierba, crecerán hierba alta y flores por todo el lugar.
Cocoa beans are a brown dye and can be used to plant cocoas.=Los granos de cacao son un tinte marrón y se pueden usar para plantar cacao.
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Haga clic derecho en una oveja para convertir su lana en marrón. Haga clic derecho en el costado del tronco de un árbol de jungla para plantar un cacao joven.
Cocoa Beans=Granos de cacao

View File

@ -17,11 +17,3 @@ Magenta Dye=Teinture Magenta
Pink Dye=Teinture Rose Pink Dye=Teinture Rose
This item is a dye which is used for dyeing and crafting.=Cet objet est un colorant utilisé pour la teinture et l'artisanat. This item is a dye which is used for dyeing and crafting.=Cet objet est un colorant utilisé pour la teinture et l'artisanat.
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Clic droit sur un mouton pour teindre sa laine. D'autres choses sont teintes par l'artisanat. Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Clic droit sur un mouton pour teindre sa laine. D'autres choses sont teintes par l'artisanat.
Bone Meal=Farine d'Os
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=La farine d'os est une teinture blanche et également utile comme engrais pour accélérer la croissance de nombreuses plantes.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Cliquez avec le bouton droit sur un mouton pour blanchir sa laine. Cliquez avec le bouton droit sur une plante pour accélérer sa croissance. Notez que toutes les plantes ne peuvent pas être fertilisées comme ça. Lorsque vous cliquez avec le bouton droit sur un bloc d'herbe, les hautes herbes et les fleurs poussent partout.
Cocoa beans are a brown dye and can be used to plant cocoas.=Les fèves de cacao ont une teinture brune et peuvent être utilisées pour planter du cacao.
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Faites un clic droit sur un mouton pour brunir sa laine. Clic droit sur le côté d'un tronc d'arbre de la jungle (Bois Acajou) pour planter un jeune cacao.
Cocoa Beans=Fèves de Cacao
Grows at the side of jungle trees=Pousse à côté des arbres de la jungle
Speeds up plant growth=Accélère la croissance des plantes

View File

@ -17,11 +17,3 @@ Magenta Dye=Karmazynowa farba
Pink Dye=Różowa farba Pink Dye=Różowa farba
This item is a dye which is used for dyeing and crafting.=Ten przedmiot to farba wykorzystywana to farbowania i wytwarzania. This item is a dye which is used for dyeing and crafting.=Ten przedmiot to farba wykorzystywana to farbowania i wytwarzania.
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Kliknij prawym na owcę aby zafarbować jej wełnę. Inne rzeczy mogą być zafarbowane przy wytwarzaniu. Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=Kliknij prawym na owcę aby zafarbować jej wełnę. Inne rzeczy mogą być zafarbowane przy wytwarzaniu.
Bone Meal=Mączka kostna
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=Mączka kostna to biała farba i przydatny nawóz, który przyspiesza rośnięcie wielu roślin.
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Kliknij prawym na owcę, aby wybielić jej wełnę. Kliknij prawym na roślinę aby przyspieszyć jej wzrost. Zważ, że nie na wszystkie rośliny to tak działa. Gdy klikniesz prawym na blok trawy, wysoka trawa wyrośnie wokół.
Cocoa beans are a brown dye and can be used to plant cocoas.=Ziarna kakaowe mogą być wykorzystane do sadzenia kakao.
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Naciśnij prawym aby zafarbować wełnę owcy na brązowo. Naciśnij prawym na boku tropikalnego pnia (Tropikalne drewno) aby zasadzić młode kakao.
Cocoa Beans=Ziarna kakaowe
Grows at the side of jungle trees=Rośnie na boku tropikalnych drzew
Speeds up plant growth=Przyspiesza wzrost roślin

View File

@ -22,6 +22,3 @@ Bone meal is a white dye and also useful as a fertilizer to speed up the growth
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Кликните правой по овце, чтобы сделать её шерсть белой. Кликните правой по растению, чтобы ускорить его рост. Имейте в виду, что не все растения можно удобрять таким способом. Если вы кликнете по травяному блоку, то на этом месте вырастет высокая трава и цветы. Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=Кликните правой по овце, чтобы сделать её шерсть белой. Кликните правой по растению, чтобы ускорить его рост. Имейте в виду, что не все растения можно удобрять таким способом. Если вы кликнете по травяному блоку, то на этом месте вырастет высокая трава и цветы.
Cocoa beans are a brown dye and can be used to plant cocoas.=Какао-бобы являются коричневым красителем. Их также можно использовать, чтобы посадить какао. Cocoa beans are a brown dye and can be used to plant cocoas.=Какао-бобы являются коричневым красителем. Их также можно использовать, чтобы посадить какао.
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по овце, чтобы сделать её шерсть коричневой. Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао. Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=Кликните правой по овце, чтобы сделать её шерсть коричневой. Кликните правой по боковой части ствола тропического дерева, чтобы посадить молодое какао.
Cocoa Beans=Какао-бобы
Grows at the side of jungle trees=Растут на стволах тропических деревьев
Speeds up plant growth=Ускоряет рост растений

View File

@ -17,9 +17,3 @@ Magenta Dye=洋紅色染料
Pink Dye=粉紅色染料 Pink Dye=粉紅色染料
This item is a dye which is used for dyeing and crafting.=這個物品是一種用於染色和合成的染料。 This item is a dye which is used for dyeing and crafting.=這個物品是一種用於染色和合成的染料。
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=右鍵單擊綿羊以染它的毛。其他東西是通過合成染色的。 Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=右鍵單擊綿羊以染它的毛。其他東西是通過合成染色的。
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=骨粉是一種白色染料,也可作為肥料,加速許多植物的生長。
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=右鍵點擊一隻羊,使其羊毛變白。右鍵點擊一株植物以加快其生長速度。注意,不是所有的植物都能像這樣施肥。當你右鍵點擊一個草方時,高高的草和花會到處生長。
Cocoa beans are a brown dye and can be used to plant cocoas.=可可豆是一種棕色染料,也可用於種植可可。
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=右鍵點擊一隻羊,使其羊毛變成褐色。右鍵點擊叢林木的一側,可以種植一個可可。
Grows at the side of jungle trees=在叢林木側生長
Speeds up plant growth=加速植物生長

View File

@ -17,11 +17,3 @@ Magenta Dye=
Pink Dye= Pink Dye=
This item is a dye which is used for dyeing and crafting.= This item is a dye which is used for dyeing and crafting.=
Rightclick on a sheep to dye its wool. Other things are dyed by crafting.= Rightclick on a sheep to dye its wool. Other things are dyed by crafting.=
Bone Meal=
Bone meal is a white dye and also useful as a fertilizer to speed up the growth of many plants.=
Rightclick a sheep to turn its wool white. Rightclick a plant to speed up its growth. Note that not all plants can be fertilized like this. When you rightclick a grass block, tall grass and flowers will grow all over the place.=
Cocoa beans are a brown dye and can be used to plant cocoas.=
Rightclick a sheep to turn its wool brown. Rightclick on the side of a jungle tree trunk (Jungle Wood) to plant a young cocoa.=
Cocoa Beans=
Grows at the side of jungle trees=
Speeds up plant growth=

View File

@ -1,2 +1,3 @@
name = mcl_dye name = mcl_dye
depends = mcl_core, mcl_flowers, mcl_mobitems, mcl_cocoas description = Adds color to your world!
depends = mcl_bone_meal, mcl_cocoas

View File

@ -285,7 +285,8 @@ function minetest.calculate_knockback(player, hitter, time_from_last_punch, tool
local wielditem = hitter:get_wielded_item() local wielditem = hitter:get_wielded_item()
--knockback = knockback + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") --knockback = knockback + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback")
local enchant = mcl_enchanting.get_enchantment(wielditem, "knockback") local enchant = mcl_enchanting.get_enchantment(wielditem, "knockback")
knockback = knockback + 3.22 * enchant local hammer = minetest.get_item_group(wielditem:get_name(), "hammer")
knockback = knockback + 3.22 * enchant + 3.22 * hammer
-- add vertical lift to knockback -- add vertical lift to knockback
local v = player:get_velocity() local v = player:get_velocity()
local added_v = 0 local added_v = 0

View File

@ -13,78 +13,44 @@ minetest.register_craftitem("mcl_farming:beetroot_seeds", {
end end
}) })
minetest.register_node("mcl_farming:beetroot_0", { local size = {[0]=-5, -4, -3}
description = S("Premature Beetroot Plant (Stage 1)"),
_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,
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drop = "mcl_farming:beetroot_seeds",
tiles = {"mcl_farming_beetroot_0.png"},
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}
},
},
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},
sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0,
})
minetest.register_node("mcl_farming:beetroot_1", { for i = 0, 2 do
description = S("Premature Beetroot Plant (Stage 2)"), minetest.register_node("mcl_farming:beetroot_".. i, {
_doc_items_create_entry = false, description = S("Premature Beetroot Plant (Stage ".. i + 1 ..")"),
paramtype = "light", _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."),
paramtype2 = "meshoptions", _doc_items_entry_name = S("Premature Beetroot Plant"),
sunlight_propagates = true, paramtype = "light",
place_param2 = 3, paramtype2 = "meshoptions",
walkable = false, sunlight_propagates = true,
drawtype = "plantlike", place_param2 = 3,
drop = "mcl_farming:beetroot_seeds", walkable = false,
tiles = {"mcl_farming_beetroot_1.png"}, drawtype = "plantlike",
inventory_image = "mcl_farming_beetroot_1.png", drop = "mcl_farming:beetroot_seeds",
wield_image = "mcl_farming_beetroot_1.png", tiles = {"mcl_farming_beetroot_".. i ..".png"},
selection_box = { inventory_image = "mcl_farming_beetroot_".. i ..".png",
type = "fixed", wield_image = "mcl_farming_beetroot_".. i ..".png",
fixed = { selection_box = {
{-0.5, -0.5, -0.5, 0.5, -4/16, 0.5} type = "fixed",
fixed = { {-0.5, -0.5, -0.5, 0.5, size[i]/16, 0.5} },
}, },
}, groups = {
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}, dig_immediate=3, not_in_creative_inventory=1,
sounds = mcl_sounds.node_sound_leaves_defaults(), plant=1, attached_node=1, dig_by_water=1,
_mcl_blast_resistance = 0, destroy_by_lava_flow=1,dig_by_piston=1
})
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,
place_param2 = 3,
walkable = false,
drawtype = "plantlike",
drop = "mcl_farming:beetroot_seeds",
tiles = {"mcl_farming_beetroot_2.png"},
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, -3/16, 0.5}
}, },
}, sounds = mcl_sounds.node_sound_leaves_defaults(),
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}, _mcl_blast_resistance = 0,
sounds = mcl_sounds.node_sound_leaves_defaults(), _on_bone_meal = function(itemstack, placer, pointed_thing)
_mcl_blast_resistance = 0, local pos = pointed_thing.under
}) local n = minetest.get_node(pos)
-- 75% chance to advance to next stage
if math.random(1, 100) <= 75 then
return mcl_farming:grow_plant("plant_beetroot", pos, n, 1, true)
end
end
})
end
minetest.register_node("mcl_farming:beetroot", { minetest.register_node("mcl_farming:beetroot", {
description = S("Mature Beetroot Plant"), description = S("Mature Beetroot Plant"),
@ -171,7 +137,8 @@ minetest.register_craft({
}, },
}) })
mcl_farming:add_plant("plant_beetroot", "mcl_farming:beetroot", {"mcl_farming:beetroot_0", "mcl_farming:beetroot_1", "mcl_farming:beetroot_2"}, 68, 3) -- beetroots grow at 2/3rd of the default speed
mcl_farming:add_plant("plant_beetroot", "mcl_farming:beetroot", {"mcl_farming:beetroot_0", "mcl_farming:beetroot_1", "mcl_farming:beetroot_2"}, 8.7012, 35)
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
for i = 1, 2 do for i = 1, 2 do

View File

@ -45,6 +45,12 @@ for i=1, 7 do
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}, 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},
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_carrot", pos, n, stages, true)
end
}) })
end end
@ -118,7 +124,7 @@ minetest.register_craft({
} }
}) })
mcl_farming:add_plant("plant_carrot", "mcl_farming:carrot", {"mcl_farming:carrot_1", "mcl_farming:carrot_2", "mcl_farming:carrot_3", "mcl_farming:carrot_4", "mcl_farming:carrot_5", "mcl_farming:carrot_6", "mcl_farming:carrot_7"}, 25, 20) mcl_farming:add_plant("plant_carrot", "mcl_farming:carrot", {"mcl_farming:carrot_1", "mcl_farming:carrot_2", "mcl_farming:carrot_3", "mcl_farming:carrot_4", "mcl_farming:carrot_5", "mcl_farming:carrot_6", "mcl_farming:carrot_7"}, 5.8013, 35)
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
for i=2,7 do for i=2,7 do

View File

@ -65,7 +65,7 @@ local hoe_usagehelp = S("Use the hoe on a cultivatable block (by rightclicking i
minetest.register_tool("mcl_farming:hoe_wood", { minetest.register_tool("mcl_farming:hoe_wood", {
description = S("Wood Hoe"), description = S("Wood Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.wood), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
_doc_items_hidden = false, _doc_items_hidden = false,
@ -109,7 +109,7 @@ minetest.register_craft({
minetest.register_tool("mcl_farming:hoe_stone", { minetest.register_tool("mcl_farming:hoe_stone", {
description = S("Stone Hoe"), description = S("Stone Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.stone), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
inventory_image = "farming_tool_stonehoe.png", inventory_image = "farming_tool_stonehoe.png",
@ -147,7 +147,7 @@ minetest.register_craft({
minetest.register_tool("mcl_farming:hoe_iron", { minetest.register_tool("mcl_farming:hoe_iron", {
description = S("Iron Hoe"), description = S("Iron Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.iron), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
inventory_image = "farming_tool_steelhoe.png", inventory_image = "farming_tool_steelhoe.png",
@ -193,7 +193,7 @@ minetest.register_craft({
minetest.register_tool("mcl_farming:hoe_gold", { minetest.register_tool("mcl_farming:hoe_gold", {
description = S("Golden Hoe"), description = S("Golden Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.gold), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
inventory_image = "farming_tool_goldhoe.png", inventory_image = "farming_tool_goldhoe.png",
@ -240,7 +240,7 @@ minetest.register_craft({
minetest.register_tool("mcl_farming:hoe_diamond", { minetest.register_tool("mcl_farming:hoe_diamond", {
description = S("Diamond Hoe"), description = S("Diamond Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.diamond), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
inventory_image = "farming_tool_diamondhoe.png", inventory_image = "farming_tool_diamondhoe.png",
@ -280,7 +280,7 @@ minetest.register_craft({
minetest.register_tool("mcl_farming:hoe_netherite", { minetest.register_tool("mcl_farming:hoe_netherite", {
description = S("Netherite Hoe"), description = S("Netherite Hoe"),
_tt_help = hoe_tt.."\n"..S("Uses: @1", uses.netherite), _tt_help = hoe_tt,
_doc_items_longdesc = hoe_longdesc, _doc_items_longdesc = hoe_longdesc,
_doc_items_usagehelp = hoe_usagehelp, _doc_items_usagehelp = hoe_usagehelp,
inventory_image = "farming_tool_netheritehoe.png", inventory_image = "farming_tool_netheritehoe.png",

View File

@ -109,6 +109,12 @@ for s=1,7 do
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}, 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},
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_melon_stem", pos, n, stages, true)
end
}) })
end end
@ -123,10 +129,10 @@ local stem_def = {
} }
-- Register stem growth -- Register stem growth
mcl_farming:add_plant("plant_melon_stem", "mcl_farming:melontige_unconnect", {"mcl_farming:melontige_1", "mcl_farming:melontige_2", "mcl_farming:melontige_3", "mcl_farming:melontige_4", "mcl_farming:melontige_5", "mcl_farming:melontige_6", "mcl_farming:melontige_7"}, 30, 5) mcl_farming:add_plant("plant_melon_stem", "mcl_farming:melontige_unconnect", {"mcl_farming:melontige_1", "mcl_farming:melontige_2", "mcl_farming:melontige_3", "mcl_farming:melontige_4", "mcl_farming:melontige_5", "mcl_farming:melontige_6", "mcl_farming:melontige_7"}, 5.8014, 35)
-- Register actual melon, connected stems and stem-to-melon growth -- Register actual melon, connected stems and stem-to-melon growth
mcl_farming:add_gourd("mcl_farming:melontige_unconnect", "mcl_farming:melontige_linked", "mcl_farming:melontige_unconnect", stem_def, stem_drop, "mcl_farming:melon", melon_base_def, 25, 15, "mcl_farming_melon_stem_connected.png^[colorize:#FFA800:127") mcl_farming:add_gourd("mcl_farming:melontige_unconnect", "mcl_farming:melontige_linked", "mcl_farming:melontige_unconnect", stem_def, stem_drop, "mcl_farming:melon", melon_base_def, 5.8015, 35, "mcl_farming_melon_stem_connected.png^[colorize:#FFA800:127")
-- Items and crafting -- Items and crafting
minetest.register_craftitem("mcl_farming:melon_item", { minetest.register_craftitem("mcl_farming:melon_item", {

View File

@ -49,6 +49,12 @@ for i=1, 7 do
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}, 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},
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_potato", pos, n, stages, true)
end
}) })
end end
@ -135,7 +141,7 @@ minetest.register_craft({
cooktime = 10, cooktime = 10,
}) })
mcl_farming:add_plant("plant_potato", "mcl_farming:potato", {"mcl_farming:potato_1", "mcl_farming:potato_2", "mcl_farming:potato_3", "mcl_farming:potato_4", "mcl_farming:potato_5", "mcl_farming:potato_6", "mcl_farming:potato_7"}, 19.75, 20) mcl_farming:add_plant("plant_potato", "mcl_farming:potato", {"mcl_farming:potato_1", "mcl_farming:potato_2", "mcl_farming:potato_3", "mcl_farming:potato_4", "mcl_farming:potato_5", "mcl_farming:potato_6", "mcl_farming:potato_7"}, 5.8016, 35)
minetest.register_on_item_eat(function (hp_change, replace_with_item, itemstack, user, pointed_thing) minetest.register_on_item_eat(function (hp_change, replace_with_item, itemstack, user, pointed_thing)

View File

@ -79,6 +79,12 @@ for s=1,7 do
groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1,}, groups = {dig_immediate=3, not_in_creative_inventory=1, plant=1,attached_node=1, dig_by_water=1,destroy_by_lava_flow=1,},
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_pumpkin_stem", pos, n, stages, true)
end
}) })
end end
@ -180,10 +186,10 @@ if minetest.get_modpath("mcl_armor") then
end end
-- Register stem growth -- Register stem growth
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) 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"}, 5.8017, 35)
-- Register actual pumpkin, connected stems and stem-to-pumpkin growth -- 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", pumpkin_base_def, 30, 15, "mcl_farming_pumpkin_stem_connected.png^[colorize:#FFA800:127") 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, 5.8018, 35, "mcl_farming_pumpkin_stem_connected.png^[colorize:#FFA800:127")
-- Steal function to properly disconnect a carved pumpkin -- Steal function to properly disconnect a carved pumpkin
pumpkin_face_base_def.after_destruct = minetest.registered_nodes["mcl_farming:pumpkin"].after_destruct pumpkin_face_base_def.after_destruct = minetest.registered_nodes["mcl_farming:pumpkin"].after_destruct

View File

@ -5,73 +5,99 @@
-- --
local math = math local math = math
local vector = vector local vector = vector
local random = math.random
local floor = math.floor
local plant_lists = {} local plant_lists = {}
mcl_farming.plant_lists = plant_lists -- export mcl_farming.plant_lists = plant_lists -- export
local plant_nodename_to_id_list = {} local plant_nodename_to_id = {} -- map nodes to plants
local plant_step_from_name = {} -- map nodes to growth steps
local time_speed = tonumber(minetest.settings:get("time_speed")) or 72 local growth_factor = tonumber(minetest.settings:get("vl_plant_growth")) or 1.0
local time_multiplier = time_speed > 0 and (86400 / time_speed) or 0
local function get_intervals_counter(pos, interval, chance) -- wetness of the surroundings
if time_multiplier == 0 then return 0 end -- dry farmland = 1 point
-- "wall clock time", so plants continue to grow while sleeping -- wet farmland = 3 points
local current_game_time = (minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier -- center point gives + 1 point, so 2 resp. 4
local approx_interval = math.max(interval, 1) * math.max(chance, 1) -- neighbors only 25%
local function get_moisture_level(pos)
local meta = minetest.get_meta(pos) local n = vector.offset(pos, 0, -1, 0)
local last_game_time = meta:get_float("last_gametime") local totalm = 1
if last_game_time < 1 then for z = -1,1 do
last_game_time = current_game_time - approx_interval * 0.5 n.z = pos.z + z
elseif last_game_time == current_game_time then for x = -1,1 do
current_game_time = current_game_time + approx_interval n.x = pos.x + x
local ndef = minetest.registered_nodes[minetest.get_node(n).name]
local soil = ndef and ndef.groups.soil
if soil and soil >= 2 then
local m = soil > 2 and 3 or 1
-- corners have less weight
if x ~= 0 or z ~= 0 then m = m * 0.25 end
totalm = totalm + m
end
end
end end
meta:set_float("last_gametime", current_game_time) return totalm
return (current_game_time - last_game_time) / approx_interval
end end
local function get_avg_light_level(pos) -- moisture penalty function:
local meta = minetest.get_meta(pos) -- 0.5 if both on the x axis and the z axis at least one of the same plants grows
-- EWMA would use a single variable: -- 0.5 if at least one diagonal neighbor is the same
-- local avg = meta:get_float("avg_light") -- 1.0 otherwise
-- avg = avg + (node_light - avg) * 0.985 -- we cannot use the names directly, because growth is encoded in the names
-- meta.set_float("avg_light", avg) local function get_same_crop_penalty(pos)
local summary = meta:get_int("avg_light_summary") local name = minetest.get_node(pos).name
local counter = meta:get_int("avg_light_count") local plant = plant_nodename_to_id[name]
if counter > 99 then if not plant then return 1 end
summary, counter = math.ceil(summary * 0.5), 50 local n = vector.copy(pos)
-- check adjacent positions, avoid vector allocations and reduce node accesses
n.x = pos.x - 1
local dx = plant_nodename_to_id[minetest.get_node(n).name] == plant
n.x = pos.x + 1
dx = dx or plant_nodename_to_id[minetest.get_node(n).name] == plant
if dx then -- no need to check z otherwise
n.x = pos.x
n.z = pos.z - 1
local dz = plant_nodename_to_id[minetest.get_node(n).name] == plant
n.z = pos.z + 1
dz = dz or plant_nodename_to_id[minetest.get_node(n).name] == plant
if dz then return 0.5 end
end end
local node_light = minetest.get_node_light(pos) -- check diagonals, clockwise
if node_light ~= nil then n.x, n.z = pos.x - 1, pos.z - 1
summary, counter = summary + node_light, counter + 1 if plant_nodename_to_id[minetest.get_node(n).name] == plant then return 0.5 end
meta:set_int("avg_light_summary", summary) n.x = pos.x + 1
meta:set_int("avg_light_count", counter) if plant_nodename_to_id[minetest.get_node(n).name] == plant then return 0.5 end
end n.z = pos.z + 1
return math.ceil(summary / counter) if plant_nodename_to_id[minetest.get_node(n).name] == plant then return 0.5 end
n.x = pos.x - 1
if plant_nodename_to_id[minetest.get_node(n).name] == plant then return 0.5 end
return 1
end end
function mcl_farming:add_plant(identifier, full_grown, names, interval, chance) function mcl_farming:add_plant(identifier, full_grown, names, interval, chance)
interval = growth_factor > 0 and (interval / growth_factor) or 0
local plant_info = {} local plant_info = {}
plant_info.full_grown = full_grown plant_info.full_grown = full_grown
plant_info.names = names plant_info.names = names
plant_info.interval = interval plant_info.interval = interval
plant_info.chance = chance plant_info.chance = chance
plant_nodename_to_id[full_grown] = identifier
for _, nodename in pairs(names) do for _, nodename in pairs(names) do
plant_nodename_to_id_list[nodename] = identifier plant_nodename_to_id[nodename] = identifier
end end
plant_info.step_from_name = {}
for i, name in ipairs(names) do for i, name in ipairs(names) do
plant_info.step_from_name[name] = i plant_step_from_name[name] = i
end end
plant_lists[identifier] = plant_info plant_lists[identifier] = plant_info
if interval == 0 then return end -- growth disabled
minetest.register_abm({ minetest.register_abm({
label = string.format("Farming plant growth (%s)", identifier), label = string.format("Farming plant growth (%s)", identifier),
nodenames = names, nodenames = names,
interval = interval, interval = interval,
chance = chance, chance = chance,
action = function(pos, node) action = function(pos, node)
local low_speed = minetest.get_node(vector.offset(pos, 0, -1, 0)).name ~= "mcl_farming:soil_wet" mcl_farming:grow_plant(identifier, pos, node, 1, false)
mcl_farming:grow_plant(identifier, pos, node, 1, false, low_speed)
end, end,
}) })
end end
@ -81,40 +107,30 @@ end
-- pos: Position -- pos: Position
-- node: Node table -- node: Node table
-- stages: Number of stages to advance (optional, defaults to 1) -- stages: Number of stages to advance (optional, defaults to 1)
-- ignore_light: if true, ignore light requirements for growing -- ignore_light_water: if true, ignore light and water requirements for growing
-- low_speed: grow more slowly (not wet), default false
-- Returns true if plant has been grown by 1 or more stages. -- Returns true if plant has been grown by 1 or more stages.
-- Returns false if nothing changed. -- Returns false if nothing changed.
function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light, low_speed) function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light_water)
stages = stages or 1 -- number of missed interval ticks, for catch-up in block loading
local plant_info = plant_lists[identifier] local plant_info = plant_lists[identifier]
local intervals_counter = get_intervals_counter(pos, plant_info.interval, plant_info.chance) if not plant_info then return end
if stages > 0 then intervals_counters = intervals_counter - 1 end if not ignore_light_water then
if low_speed then -- 10% speed approximately if (minetest.get_node_light(pos, 0.5) or 0) < 0 then return false end -- day light
if intervals_counter < 1.01 and math.random(0, 9) > 0 then return false end local odds = floor(25 / (get_moisture_level(pos) * get_same_crop_penalty(pos))) + 1
intervals_counter = intervals_counter / 10 for i = 1,stages do
end -- compared to info from the MC wiki, our ABM runs a third as often, hence we use triple the chance
if not ignore_light and intervals_counter < 1.5 then if random() * odds >= 3 then stages = stages - 1 end
local light = minetest.get_node_light(pos)
if not light or light < 10 then return false end
end
if intervals_counter >= 1.5 then
local average_light_level = get_avg_light_level(pos)
if average_light_level < 0.1 then return false end
if average_light_level < 10 then
intervals_counter = intervals_counter * average_light_level / 10
end end
end end
local step = plant_info.step_from_name[node.name]
if step == nil then return false end
stages = stages + math.floor(intervals_counter)
if stages == 0 then return false end if stages == 0 then return false end
local new_node = { name = plant_info.names[step + stages] or plant_info.full_grown } local step = plant_step_from_name[node.name]
new_node.param = node.param if step == nil then return false end
new_node.param2 = node.param2 minetest.set_node(pos, {
minetest.set_node(pos, new_node) name = plant_info.names[step + stages] or plant_info.full_grown,
param = node.param,
param2 = node.param2,
})
return true return true
end end
@ -157,40 +173,13 @@ end
function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, stem_itemstring, stem_def, stem_drop, gourd_itemstring, gourd_def, grow_interval, grow_chance, connected_stem_texture) function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, stem_itemstring, stem_def, stem_drop, gourd_itemstring, gourd_def, grow_interval, grow_chance, connected_stem_texture)
grow_interval = growth_factor > 0 and (grow_interval / growth_factor) or 0
local connected_stem_names = { local connected_stem_names = {
connected_stem_basename .. "_r", connected_stem_basename .. "_r",
connected_stem_basename .. "_l", connected_stem_basename .. "_l",
connected_stem_basename .. "_t", connected_stem_basename .. "_t",
connected_stem_basename .. "_b" } connected_stem_basename .. "_b" }
-- Connect the stem at stempos to the first neighboring gourd block.
-- No-op if not a stem or no gourd block found
local function try_connect_stem(stempos)
local stem = minetest.get_node(stempos)
if stem.name ~= full_unconnected_stem then return false end
-- four directions, but avoid table allocation
local neighbor = vector.offset(stempos, 1, 0, 0)
if minetest.get_node(neighbor).name == gourd_itemstring then
minetest.swap_node(stempos, { name = connected_stem_names[1] })
return true
end
local neighbor = vector.offset(stempos, -1, 0, 0)
if minetest.get_node(neighbor).name == gourd_itemstring then
minetest.swap_node(stempos, { name = connected_stem_names[2] })
return true
end
local neighbor = vector.offset(stempos, 0, 0, 1)
if minetest.get_node(neighbor).name == gourd_itemstring then
minetest.swap_node(stempos, { name = connected_stem_names[3] })
return true
end
local neighbor = vector.offset(stempos, 0, 0, -1)
if minetest.get_node(neighbor).name == gourd_itemstring then
minetest.swap_node(stempos, { name = connected_stem_names[4] })
return true
end
end
-- Register gourd -- Register gourd
if not gourd_def.after_destruct then if not gourd_def.after_destruct then
gourd_def.after_destruct = function(blockpos, oldnode) gourd_def.after_destruct = function(blockpos, oldnode)
@ -200,34 +189,21 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
local stempos = vector.offset(blockpos, -1, 0, 0) local stempos = vector.offset(blockpos, -1, 0, 0)
if minetest.get_node(stempos).name == connected_stem_names[1] then if minetest.get_node(stempos).name == connected_stem_names[1] then
minetest.swap_node(stempos, { name = full_unconnected_stem }) minetest.swap_node(stempos, { name = full_unconnected_stem })
try_connect_stem(stempos)
end end
local stempos = vector.offset(blockpos, 1, 0, 0) local stempos = vector.offset(blockpos, 1, 0, 0)
if minetest.get_node(stempos).name == connected_stem_names[2] then if minetest.get_node(stempos).name == connected_stem_names[2] then
minetest.swap_node(stempos, { name = full_unconnected_stem }) minetest.swap_node(stempos, { name = full_unconnected_stem })
try_connect_stem(stempos)
end end
local stempos = vector.offset(blockpos, 0, 0, -1) local stempos = vector.offset(blockpos, 0, 0, -1)
if minetest.get_node(stempos).name == connected_stem_names[3] then if minetest.get_node(stempos).name == connected_stem_names[3] then
minetest.swap_node(stempos, { name = full_unconnected_stem }) minetest.swap_node(stempos, { name = full_unconnected_stem })
try_connect_stem(stempos)
end end
local stempos = vector.offset(blockpos, 0, 0, 1) local stempos = vector.offset(blockpos, 0, 0, 1)
if minetest.get_node(stempos).name == connected_stem_names[4] then if minetest.get_node(stempos).name == connected_stem_names[4] then
minetest.swap_node(stempos, { name = full_unconnected_stem }) minetest.swap_node(stempos, { name = full_unconnected_stem })
try_connect_stem(stempos)
end end
end end
end end
if not gourd_def.on_construct then
function gourd_def.on_construct(blockpos)
-- Connect all unconnected stems at full size
try_connect_stem(vector.offset(blockpos, 1, 0, 0))
try_connect_stem(vector.offset(blockpos, -1, 0, 0))
try_connect_stem(vector.offset(blockpos, 0, 0, 1))
try_connect_stem(vector.offset(blockpos, 0, 0, -1))
end
end
minetest.register_node(gourd_itemstring, gourd_def) minetest.register_node(gourd_itemstring, gourd_def)
-- Register unconnected stem -- Register unconnected stem
@ -243,8 +219,8 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
stem_def.drop = stem_def.drop or stem_drop stem_def.drop = stem_def.drop or stem_drop
stem_def.groups = stem_def.groups or { dig_immediate = 3, not_in_creative_inventory = 1, plant = 1, attached_node = 1, dig_by_water = 1, destroy_by_lava_flow = 1 } stem_def.groups = stem_def.groups or { dig_immediate = 3, not_in_creative_inventory = 1, plant = 1, attached_node = 1, dig_by_water = 1, destroy_by_lava_flow = 1 }
stem_def.sounds = stem_def.sounds or mcl_sounds.node_sound_leaves_defaults() stem_def.sounds = stem_def.sounds or mcl_sounds.node_sound_leaves_defaults()
stem_def.on_construct = stem_def.on_construct or try_connect_stem
minetest.register_node(stem_itemstring, stem_def) minetest.register_node(stem_itemstring, stem_def)
plant_nodename_to_id[stem_itemstring] = stem_itemstring
-- Register connected stems -- Register connected stems
@ -307,22 +283,14 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })
plant_nodename_to_id[connected_stem_names[i]] = stem_itemstring
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", full_unconnected_stem, "nodes", connected_stem_names[i]) doc.add_entry_alias("nodes", full_unconnected_stem, "nodes", connected_stem_names[i])
end end
end end
-- Check for a suitable spot to grow if grow_interval == 0 then return end
local function check_neighbor_soil(blockpos)
if minetest.get_node(blockpos).name ~= "air" then return false end
local floorpos = vector.offset(blockpos, 0, -1, 0)
local floorname = minetest.get_node(floorpos).name
if floorname == "mcl_core:dirt" then return true end
local floordef = minetest.registered_nodes[floorname]
return floordef.groups.grass_block or floordef.groups.dirt or (floordef.groups.soil or 0) >= 2
end
minetest.register_abm({ minetest.register_abm({
label = "Grow gourd stem to gourd (" .. full_unconnected_stem .. "" .. gourd_itemstring .. ")", label = "Grow gourd stem to gourd (" .. full_unconnected_stem .. "" .. gourd_itemstring .. ")",
nodenames = { full_unconnected_stem }, nodenames = { full_unconnected_stem },
@ -330,39 +298,27 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
interval = grow_interval, interval = grow_interval,
chance = grow_chance, chance = grow_chance,
action = function(stempos) action = function(stempos)
local light = minetest.get_node_light(stempos) local light = minetest.get_node_light(stempos, 0.5)
if not light or light <= 10 then return end if not light or light < 9 then return end
-- Check the four neighbors and filter out neighbors where gourds can't grow -- Pick one neighbor and check if it can be used to grow
local neighbor, dir, nchance = nil, -1, 1 -- reservoir sampling local dir = random(1, 4) -- pick direction at random
if nchance == 1 or math.random(1, nchance) == 1 then local neighbor = (dir == 1 and vector.offset(stempos, 1, 0, 0))
local blockpos = vector.offset(stempos, 1, 0, 0) or (dir == 2 and vector.offset(stempos, -1, 0, 0))
if check_neighbor_soil(blockpos) then or (dir == 3 and vector.offset(stempos, 0, 0, 1))
neighbor, dir, nchance = blockpos, 1, nchance + 1 or vector.offset(stempos, 0, 0, -1)
end if minetest.get_node(neighbor).name ~= "air" then return end -- occupied
end -- check for suitable floor -- in contrast to MC, we think everything solid is fine
if nchance == 1 or math.random(1, nchance) == 1 then local floorpos = vector.offset(neighbor, 0, -1, 0)
local blockpos = vector.offset(stempos, -1, 0, 0) local floorname = minetest.get_node(floorpos).name
if check_neighbor_soil(blockpos) then local floordef = minetest.registered_nodes[floorname]
neighbor, dir, nchance = blockpos, 2, nchance + 1 if not floordef or not floordef.walkable then return end
end
end -- check moisture level
if nchance == 1 or math.random(1, nchance) == 1 then local odds = floor(25 / (get_moisture_level(stempos) * get_same_crop_penalty(stempos))) + 1
local blockpos = vector.offset(stempos, 0, 0, 1) -- we triple the odds, and rather call the ABM less often
if check_neighbor_soil(blockpos) then if random() * odds >= 3 then return end
neighbor, dir, nchance = blockpos, 3, nchance + 1
end
end
if nchance == 1 or math.random(1, nchance) == 1 then
local blockpos = vector.offset(stempos, 0, 0, -1)
if check_neighbor_soil(blockpos) then
neighbor, dir, nchance = blockpos, 4, nchance + 1
end
end
-- Gourd needs at least 1 free neighbor to grow
if not neighbor then return end
minetest.swap_node(stempos, { name = connected_stem_names[dir] }) minetest.swap_node(stempos, { name = connected_stem_names[dir] })
-- Place the gourd
if gourd_def.paramtype2 == "facedir" then if gourd_def.paramtype2 == "facedir" then
local p2 = (dir == 1 and 3) or (dir == 2 and 1) or (dir == 3 and 2) or 0 local p2 = (dir == 1 and 3) or (dir == 2 and 1) or (dir == 3 and 2) or 0
minetest.add_node(neighbor, { name = gourd_itemstring, param2 = p2 }) minetest.add_node(neighbor, { name = gourd_itemstring, param2 = p2 })
@ -371,8 +327,7 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
end end
-- Reset farmland, etc. to dirt when the gourd grows on top -- Reset farmland, etc. to dirt when the gourd grows on top
local floorpos = vector.offset(neighbor, 0, -1, 0) if (floordef.groups.dirtifies_below_solid or 0) > 0 then
if minetest.get_item_group(minetest.get_node(floorpos).name, "dirtifies_below_solid") == 1 then
minetest.set_node(floorpos, { name = "mcl_core:dirt" }) minetest.set_node(floorpos, { name = "mcl_core:dirt" })
end end
end, end,
@ -409,10 +364,21 @@ minetest.register_lbm({
nodenames = { "group:plant" }, nodenames = { "group:plant" },
run_at_every_load = true, run_at_every_load = true,
action = function(pos, node, dtime_s) action = function(pos, node, dtime_s)
local identifier = plant_nodename_to_id_list[node.name] local identifier = plant_nodename_to_id[node.name]
if not identifier then return end if not identifier then return end
local low_speed = minetest.get_node(vector.offset(pos, 0, -1, 0)).name ~= "mcl_farming:soil_wet"
mcl_farming:grow_plant(identifier, pos, node, 0, false, low_speed) local plant_info = plant_lists[identifier]
if not plant_info then return end
local rolls = floor(dtime_s / plant_info.interval)
if rolls <= 0 then return end
-- simulate how often the block will be ticked
local stages = 0
for i = 1,rolls do
if random(1, plant_info.chance) == 1 then stages = stages + 1 end
end
if stages > 0 then
mcl_farming:grow_plant(identifier, pos, node, stages, false)
end
end, end,
}) })

View File

@ -15,10 +15,6 @@ minetest.register_node("mcl_farming:soil", {
{-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5}, {-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5},
} }
}, },
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("wet", 0)
end,
groups = {handy=1,shovely=1, dirtifies_below_solid=1, dirtifier=1, soil=2, soil_sapling=1, deco_block=1 }, groups = {handy=1,shovely=1, dirtifies_below_solid=1, dirtifier=1, soil=2, soil_sapling=1, deco_block=1 },
sounds = mcl_sounds.node_sound_dirt_defaults(), sounds = mcl_sounds.node_sound_dirt_defaults(),
_mcl_blast_resistance = 0.6, _mcl_blast_resistance = 0.6,
@ -38,10 +34,6 @@ minetest.register_node("mcl_farming:soil_wet", {
{-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5}, {-0.5, -0.5, -0.5, 0.5, 0.4375, 0.5},
} }
}, },
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("wet", 7)
end,
groups = {handy=1,shovely=1, not_in_creative_inventory=1, dirtifies_below_solid=1, dirtifier=1, soil=3, soil_sapling=1 }, groups = {handy=1,shovely=1, not_in_creative_inventory=1, dirtifies_below_solid=1, dirtifier=1, soil=3, soil_sapling=1 },
sounds = mcl_sounds.node_sound_dirt_defaults(), sounds = mcl_sounds.node_sound_dirt_defaults(),
_mcl_blast_resistance = 0.6, _mcl_blast_resistance = 0.6,
@ -51,75 +43,54 @@ minetest.register_node("mcl_farming:soil_wet", {
minetest.register_abm({ minetest.register_abm({
label = "Farmland hydration", label = "Farmland hydration",
nodenames = {"mcl_farming:soil", "mcl_farming:soil_wet"}, nodenames = {"mcl_farming:soil", "mcl_farming:soil_wet"},
interval = 15, interval = 2.73,
chance = 4, chance = 25,
action = function(pos, node) action = function(pos, node)
-- Get wetness value
local meta = minetest.get_meta(pos)
local wet = meta:get_int("wet")
if not wet then
if node.name == "mcl_farming:soil" then
wet = 0
else
wet = 7
end
end
-- Turn back into dirt when covered by solid node -- Turn back into dirt when covered by solid node
local above_node = minetest.get_node_or_nil({x=pos.x,y=pos.y+1,z=pos.z}) local above_node = minetest.get_node_or_nil(vector.offset(pos, 0, 1, 0))
if above_node then if above_node and minetest.get_item_group(above_node.name, "solid") ~= 0 then
if minetest.get_item_group(above_node.name, "solid") ~= 0 then node.name = "mcl_core:dirt"
node.name = "mcl_core:dirt" minetest.set_node(pos, node)
minetest.set_node(pos, node) return
return
end
end end
-- Check an area of 9×2×9 around the node for nodename (9×9 on same level and 9×9 below) -- in rain, become wet, do not decay
local function check_surroundings(pos, nodename) if mcl_weather and mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then
local nodes = minetest.find_nodes_in_area({x=pos.x-4,y=pos.y,z=pos.z-4}, {x=pos.x+4,y=pos.y+1,z=pos.z+4}, {nodename}) if node.name == "mcl_farming:soil" then
return #nodes > 0
end
if check_surroundings(pos, "group:water") then
if node.name ~= "mcl_farming:soil_wet" then
-- Make it wet
node.name = "mcl_farming:soil_wet" node.name = "mcl_farming:soil_wet"
minetest.set_node(pos, node) minetest.set_node(pos, node)
end end
else -- No water nearby. return
-- The decay branch (make farmland dry or turn back to dirt) end
-- Don't decay while it's raining -- Check an area of 9x2x9 around the node for nodename (9x9 on same level and 9x9 above)
if mcl_weather.rain.raining then -- include "ignore" to detect unloaded blocks
if mcl_weather.is_outdoor(pos) then local nodes, counts = minetest.find_nodes_in_area(vector.offset(pos, -4, 0, -4), vector.offset(pos, 4, 1, 4), {"group:water", "ignore"})
return local ignore = counts.ignore or 0
end local has_water, fully_loaded = #nodes > ignore, ignore == 0
end
-- No decay near unloaded areas since these might include water.
if not check_surroundings(pos, "ignore") then
if wet <= 0 then
--local n_def = minetest.registered_nodes[node.name] or nil
local nn = minetest.get_node_or_nil({x=pos.x,y=pos.y+1,z=pos.z})
if not nn or not nn.name then
return
end
local nn_def = minetest.registered_nodes[nn.name] or nil
if nn_def and minetest.get_item_group(nn.name, "plant") == 0 then -- Hydrate by rain or water, do not decay
node.name = "mcl_core:dirt" if has_water then
minetest.set_node(pos, node) if node.name == "mcl_farming:soil" then
return node.name = "mcl_farming:soil_wet"
end minetest.set_node(pos, node)
else
if wet == 7 then
node.name = "mcl_farming:soil"
minetest.swap_node(pos, node)
end
-- Slowly count down wetness
meta:set_int("wet", wet-1)
end
end end
return
end
-- No decay near unloaded areas (ignore) since these might include water.
if not fully_loaded then return end
-- Decay: make wet farmland dry up
if node.name == "mcl_farming:soil_wet" then
node.name = "mcl_farming:soil"
minetest.set_node(pos, node)
return
end
-- Revert to dirt if wetness is 0, and no plant above
local above = minetest.get_node_or_nil(vector.offset(pos, 0, 1, 0))
if minetest.get_item_group(above.name, "plant") == 0 then
node.name = "mcl_core:dirt"
minetest.set_node(pos, node)
end end
end, end,
}) })

View File

@ -12,6 +12,25 @@ for i=0, 3 do
local drop_berries = (i >= 2) local drop_berries = (i >= 2)
local berries_to_drop = drop_berries and {i - 1, i} or nil local berries_to_drop = drop_berries and {i - 1, i} or nil
local on_bonemealing = nil
local function do_berry_drop(pos)
for j=1, berries_to_drop[math.random(2)] do
minetest.add_item(pos, "mcl_farming:sweet_berry")
end
minetest.swap_node(pos, {name = "mcl_farming:sweet_berry_bush_1"})
end
if i ~= 3 then
on_bonemealing = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local node = minetest.get_node(pos)
return mcl_farming:grow_plant("plant_sweet_berry_bush", pos, node, 0, true)
end
else
on_bonemealing = function(itemstack, placer, pointed_thing)
do_berry_drop(pointed_thing.under)
end
end
minetest.register_node(node_name, { minetest.register_node(node_name, {
drawtype = "plantlike", drawtype = "plantlike",
tiles = {texture}, tiles = {texture},
@ -45,6 +64,7 @@ for i=0, 3 do
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_mcl_hardness = 0, _mcl_hardness = 0,
_on_bone_meal = on_bonemealing,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local pn = clicker:get_player_name() local pn = clicker:get_player_name()
if clicker:is_player() and minetest.is_protected(pos, pn) then if clicker:is_player() and minetest.is_protected(pos, pn) then
@ -60,11 +80,13 @@ for i=0, 3 do
return return
end end
if drop_berries then if i >= 2 then
for j=1, berries_to_drop[math.random(2)] do do_berry_drop(pos)
minetest.add_item(pos, "mcl_farming:sweet_berry") else
-- Use bonemeal
if mcl_bone_meal and clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
return mcl_bone_meal.use_bone_meal(itemstack, clicker, pointed_thing)
end end
minetest.swap_node(pos, {name = "mcl_farming:sweet_berry_bush_1"})
end end
return itemstack return itemstack
end, end,
@ -99,8 +121,8 @@ minetest.register_craftitem("mcl_farming:sweet_berry", {
}) })
minetest.register_alias("mcl_sweet_berry:sweet_berry", "mcl_farming:sweet_berry") minetest.register_alias("mcl_sweet_berry:sweet_berry", "mcl_farming:sweet_berry")
-- TODO: Find proper interval and chance values for sweet berry bushes. Current interval and chance values are copied from mcl_farming:beetroot which has similar growth stages. -- TODO: Find proper interval and chance values for sweet berry bushes. Current interval and chance values are copied from mcl_farming:beetroot which has similar growth stages, 2/3rd of the default.
mcl_farming:add_plant("plant_sweet_berry_bush", "mcl_farming:sweet_berry_bush_3", {"mcl_farming:sweet_berry_bush_0", "mcl_farming:sweet_berry_bush_1", "mcl_farming:sweet_berry_bush_2"}, 68, 3) mcl_farming:add_plant("plant_sweet_berry_bush", "mcl_farming:sweet_berry_bush_3", {"mcl_farming:sweet_berry_bush_0", "mcl_farming:sweet_berry_bush_1", "mcl_farming:sweet_berry_bush_2"}, 8.7019, 35)
local function berry_damage_check(obj) local function berry_damage_check(obj)
local p = obj:get_pos() local p = obj:get_pos()

View File

@ -60,6 +60,12 @@ for i=1,7 do
dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1}, dig_by_water=1,destroy_by_lava_flow=1, dig_by_piston=1},
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
local stages = math.random(2, 5)
return mcl_farming:grow_plant("plant_wheat", pos, n, stages, true)
end
}) })
end end
@ -99,7 +105,7 @@ minetest.register_node("mcl_farming:wheat", {
} }
}) })
mcl_farming:add_plant("plant_wheat", "mcl_farming:wheat", {"mcl_farming:wheat_1", "mcl_farming:wheat_2", "mcl_farming:wheat_3", "mcl_farming:wheat_4", "mcl_farming:wheat_5", "mcl_farming:wheat_6", "mcl_farming:wheat_7"}, 25, 20) mcl_farming:add_plant("plant_wheat", "mcl_farming:wheat", {"mcl_farming:wheat_1", "mcl_farming:wheat_2", "mcl_farming:wheat_3", "mcl_farming:wheat_4", "mcl_farming:wheat_5", "mcl_farming:wheat_6", "mcl_farming:wheat_7"}, 5.8020, 35)
minetest.register_craftitem("mcl_farming:wheat_item", { minetest.register_craftitem("mcl_farming:wheat_item", {
description = S("Wheat"), description = S("Wheat"),

View File

@ -0,0 +1,136 @@
-- bonemealing grass nodes
--
-- When bonemealing "mcl_core:dirt_with_grass", it spawns grass and flowers
-- over a 7x7 patch of adjacent grassy nodes.
--
-- Because of potential dependency complications it is not advisable to add
-- callbacks to mcl_core that create dependencies on mods that depend on
-- mcl_core, such as mcl_flowers.
--
-- To work around this restriction, the bonemealing callback is defined here
-- and the _on_bone_meal callback in "mcl_core:dirt_with_grass" node
-- definition is overwritten with it.
local mg_name = minetest.get_mapgen_setting("mg_name")
local flowers_table_simple = {
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
}
local flowers_table_plains = {
"mcl_flowers:dandelion",
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
"mcl_flowers:oxeye_daisy",
"mcl_flowers:tulip_orange",
"mcl_flowers:tulip_red",
"mcl_flowers:tulip_white",
"mcl_flowers:tulip_pink",
"mcl_flowers:azure_bluet",
}
local flowers_table_swampland = {
"mcl_flowers:blue_orchid",
}
local flowers_table_flower_forest = {
"mcl_flowers:dandelion",
"mcl_flowers:poppy",
"mcl_flowers:oxeye_daisy",
"mcl_flowers:tulip_orange",
"mcl_flowers:tulip_red",
"mcl_flowers:tulip_white",
"mcl_flowers:tulip_pink",
"mcl_flowers:azure_bluet",
"mcl_flowers:allium",
}
local biome_flowers_tables = {
["Plains"] = flowers_table_plains,
["Plains_beach"] = flowers_table_plains,
["Plains_ocean"] = flowers_table_plains,
["Plains_deep_ocean"] = flowers_table_plains,
["Plains_underground"] = flowers_table_plains,
["SunflowerPlains"] = flowers_table_plains,
["SunflowerPlains_ocean"] = flowers_table_plains,
["SunflowerPlains_deep_ocean"] = flowers_table_plains,
["SunflowerPlains_underground"] = flowers_table_plains,
["Swampland"] = flowers_table_swampland,
["Swampland_shore"] = flowers_table_swampland,
["Swampland_ocean"] = flowers_table_swampland,
["Swampland_deep_ocean"] = flowers_table_swampland,
["Swampland_underground"] = flowers_table_swampland,
["FlowerForest"] = flowers_table_flower_forest,
["FlowerForest_beach"] = flowers_table_flower_forest,
["FlowerForest_ocean"] = flowers_table_flower_forest,
["FlowerForest_deep_ocean"] = flowers_table_flower_forest,
["FlowerForest_underground"] = flowers_table_flower_forest,
}
-- Randomly generate flowers, tall grass or nothing
-- pos: node to place into
-- color: param2 value for tall grass
--
local function add_random_flower(pos, color)
-- 90% tall grass, 10% flower
local rnd = math.random(1,100)
if rnd <= 60 then
minetest.add_node(pos, {name="mcl_flowers:tallgrass", param2=color})
elseif rnd <= 80 then
-- double tallgrass
local toppos = vector.offset(pos, 0, 1, 0)
local topnode = minetest.get_node(toppos)
if minetest.registered_nodes[topnode.name].buildable_to then
minetest.set_node(pos, { name = "mcl_flowers:double_grass", param2 = color })
minetest.set_node(toppos, { name = "mcl_flowers:double_grass_top", param2 = color })
return true
end
else
local flowers_table
if mg_name == "v6" then
flowers_table = flowers_table_plains
else
local biome = minetest.get_biome_name(minetest.get_biome_data(pos).biome)
flowers_table = biome_flowers_tables[biome] or flowers_table_simple
end
minetest.add_node(pos, {name=flowers_table[math.random(1, #flowers_table)]})
end
end
--- Generate tall grass and random flowers in a 7x7 area
-- Bonemealing callback handler for "mcl_core:dirt_with_grass"
--
local function bonemeal_grass(pointed_thing, placer)
local pos, below, r, color
for i = -7, 7 do for j = -7, 7 do for y = -1, 1 do
pos = vector.offset(pointed_thing.above, i, y, j)
if minetest.get_node(pos).name == "air" then
below = minetest.get_node(vector.offset(pos, 0, -1, 0))
r = ((math.abs(i) + math.abs(j)) / 2)
if (minetest.get_item_group(below.name, "grass_block_no_snow") == 1) and
math.random(1, 100) <= 90 / r then
color = below.param2
add_random_flower(pos, color)
if math.random(1,5) == 1 then
mcl_bone_meal.add_bone_meal_particle(pos)
end
end
end
end end end
return true
end
-- Override "mcl_core:dirt_with_grass" bonemealing handler.
local nodename = "mcl_core:dirt_with_grass"
local olddef = minetest.registered_nodes[nodename]
if not olddef then
minetest.log("warning", "'mcl_core:dirt_with_grass' not registered, cannot add override!")
else
local oldhandler = olddef._on_bone_meal
local newhandler = function(itemstack, placer, pointed_thing)
local res = bonemeal_grass(pointed_thing, placer)
if oldhandler then
res = oldhandler(itemstack, placer, pointed_thing) or res
end
return res
end
minetest.override_item(nodename, {_on_bone_meal = newhandler})
end

View File

@ -162,6 +162,18 @@ local def_tallgrass = {
_mcl_fortune_drop = fortune_wheat_seed_drop, _mcl_fortune_drop = fortune_wheat_seed_drop,
node_placement_prediction = "", node_placement_prediction = "",
on_place = on_place_flower, on_place = on_place_flower,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
-- Grow into double tallgrass
local toppos = vector.offset(pos, 0, 1, 0)
local topnode = minetest.get_node(toppos)
if minetest.registered_nodes[topnode.name].buildable_to then
minetest.set_node(pos, { name = "mcl_flowers:double_grass", param2 = n.param2 })
minetest.set_node(toppos, { name = "mcl_flowers:double_grass_top", param2 = n.param2 })
return true
end
end,
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_mcl_hardness = 0, _mcl_hardness = 0,
} }
@ -180,6 +192,18 @@ def_fern.selection_box = {
fixed = { -6/16, -0.5, -6/16, 6/16, 5/16, 6/16 }, fixed = { -6/16, -0.5, -6/16, 6/16, 5/16, 6/16 },
} }
def_fern.groups.compostability = 65 def_fern.groups.compostability = 65
def_fern._on_bone_meal = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
local n = minetest.get_node(pos)
-- Grow into double fern.
local toppos = vector.offset(pos, 0, 1, 0)
local topnode = minetest.get_node(toppos)
if minetest.registered_nodes[topnode.name].buildable_to then
minetest.set_node(pos, { name = "mcl_flowers:double_fern", param2 = n.param2 })
minetest.set_node(toppos, { name = "mcl_flowers:double_fern_top", param2 = n.param2 })
return true
end
end
minetest.register_node("mcl_flowers:fern", def_fern) minetest.register_node("mcl_flowers:fern", def_fern)
@ -243,10 +267,16 @@ local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_im
if name == "double_grass" then if name == "double_grass" then
bottom_groups.compostability = 50 bottom_groups.compostability = 50
end end
local on_bonemealing
if is_flower then if is_flower then
bottom_groups.flower = 1 bottom_groups.flower = 1
bottom_groups.place_flowerlike = 1 bottom_groups.place_flowerlike = 1
bottom_groups.dig_immediate = 3 bottom_groups.dig_immediate = 3
on_bonemealing = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.under
minetest.add_item(pos, "mcl_flowers:"..name)
return true
end
else else
bottom_groups.place_flowerlike = 2 bottom_groups.place_flowerlike = 2
bottom_groups.handy = 1 bottom_groups.handy = 1
@ -381,6 +411,7 @@ local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_im
minetest.remove_node(top) minetest.remove_node(top)
end end
end, end,
_on_bone_meal = on_bonemealing,
groups = bottom_groups, groups = bottom_groups,
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
mesh = mesh mesh = mesh
@ -419,6 +450,7 @@ local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_im
minetest.remove_node(bottom) minetest.remove_node(bottom)
end end
end, end,
_on_bone_meal = on_bonemealing,
groups = top_groups, groups = top_groups,
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
}) })
@ -572,3 +604,6 @@ if mod_mcimport and mg_name == "singlenode" and fix_doubleplants == true then
end end
dofile(modpath.."/register.lua") dofile(modpath.."/register.lua")
-- Bonemealing handler and override for "mcl_core:dirt_with_grass":
dofile(modpath.."/bonemealing.lua")

View File

@ -1,3 +1,3 @@
name=mcl_flowers name=mcl_flowers
depends=mcl_core, mcl_util, mcl_sounds depends=mcl_core, mcl_util, mcl_sounds, mcl_bone_meal
optional_depends=screwdriver, doc, mcl_flowerpots optional_depends=screwdriver, doc, mcl_flowerpots

View File

@ -1,5 +1,8 @@
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
local modpath = minetest.get_modpath(minetest.get_current_modname())
local schempath = modpath .. "/schematics/"
local on_place = mcl_util.generate_on_place_plant_function(function(place_pos, place_node) local on_place = mcl_util.generate_on_place_plant_function(function(place_pos, place_node)
local soil_node = minetest.get_node_or_nil({x=place_pos.x, y=place_pos.y-1, z=place_pos.z}) local soil_node = minetest.get_node_or_nil({x=place_pos.x, y=place_pos.y-1, z=place_pos.z})
if not soil_node then return false end if not soil_node then return false end
@ -16,6 +19,40 @@ local on_place = mcl_util.generate_on_place_plant_function(function(place_pos, p
return ((snn == "mcl_core:podzol" or snn == "mcl_core:podzol_snow" or snn == "mcl_core:mycelium" or snn == "mcl_core:mycelium_snow") or (light_ok and minetest.get_item_group(snn, "solid") == 1 and minetest.get_item_group(snn, "opaque") == 1)) return ((snn == "mcl_core:podzol" or snn == "mcl_core:podzol_snow" or snn == "mcl_core:mycelium" or snn == "mcl_core:mycelium_snow") or (light_ok and minetest.get_item_group(snn, "solid") == 1 and minetest.get_item_group(snn, "opaque") == 1))
end) end)
-- Try to grow huge mushroom
local function apply_bonemeal(pos, schematic, offset)
-- Must be on a dirt-type block
local below = minetest.get_node(vector.offset(pos, 0, -1, 0))
if minetest.get_item_group(below.name, "grass_block") ~= 1
and below.name ~= "mcl_core:mycelium"
and below.name ~= "mcl_core:dirt"
and below.name ~= "mcl_core:coarse_dirt"
and below.name ~= "mcl_core:podzol" then
return false
end
-- 40% chance
if math.random(1, 100) <= 40 then
-- Check space requirements
for i= 1, 3 do
local cpos = vector.offset(pos, 0, i, 0)
if minetest.get_node(cpos).name ~= "air" then
return false
end
end
local minp = vector.offset(pos, -3, 3, -3)
local maxp = vector.offset(pos, 3, 8, 3)
local diff = maxp - minp
local goodnodes = minetest.find_nodes_in_area(minp, maxp, {"air", "group:leaves"})
if #goodnodes < (diff.x + 1) * (diff.y + 1) * (diff.z + 1) then
return false
end
-- Place the huge mushroom
minetest.remove_node(pos)
return minetest.place_schematic(pos + offset, schematic, 0, nil, false)
end
return false
end
local longdesc_intro_brown = S("Brown mushrooms are fungi which grow and spread in darkness, but are sensitive to light. They are inedible as such, but they can be used to craft food items.") local longdesc_intro_brown = S("Brown mushrooms are fungi which grow and spread in darkness, but are sensitive to light. They are inedible as such, but they can be used to craft food items.")
local longdesc_intro_red = S("Red mushrooms are fungi which grow and spread in darkness, but are sensitive to light. They are inedible as such, but they can be used to craft food items.") local longdesc_intro_red = S("Red mushrooms are fungi which grow and spread in darkness, but are sensitive to light. They are inedible as such, but they can be used to craft food items.")
@ -51,6 +88,11 @@ minetest.register_node("mcl_mushrooms:mushroom_brown", {
}, },
node_placement_prediction = "", node_placement_prediction = "",
on_place = on_place, on_place = on_place,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local schematic = schempath .. "mcl_mushrooms_huge_brown.mts"
local offset = vector.new(-3, -1, -3)
return apply_bonemeal(pointed_thing.under, schematic, offset)
end,
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })
@ -78,6 +120,11 @@ minetest.register_node("mcl_mushrooms:mushroom_red", {
}, },
node_placement_prediction = "", node_placement_prediction = "",
on_place = on_place, on_place = on_place,
_on_bone_meal = function(itemstack, placer, pointed_thing)
local schematic = schempath .. "mcl_mushrooms_huge_red.mts"
local offset = vector.new(-2, -1, -2)
return apply_bonemeal(pointed_thing.under, schematic, offset)
end,
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })

View File

@ -211,16 +211,37 @@ local function set_interact(player, interact)
return return
end end
local meta = player:get_meta() local meta = player:get_meta()
if meta:get_int("mcl_privs:interact_revoked") ~= 1 then
privs.interact = interact if interact and meta:get_int("mcl_shields:interact_revoked") ~= 0 then
minetest.set_player_privs(player_name, privs) meta:set_int("mcl_shields:interact_revoked", 0)
meta:set_int("mcl_privs:interact_revoked",0) privs.interact = true
elseif not interact then
meta:set_int("mcl_shields:interact_revoked", privs.interact and 1 or 0)
privs.interact = nil
end end
minetest.set_player_privs(player_name, privs)
end end
-- Prevent player from being able to circumvent interact privilage removal by
-- using shield.
minetest.register_on_priv_revoke(function(name, revoker, priv)
if priv == "interact" and revoker then
local player = minetest.get_player_by_name(name)
if not player then
return
end
local meta = player:get_meta()
meta:set_int("mcl_shields:interact_revoked", 0)
end
end)
local shield_hud = {} local shield_hud = {}
local function remove_shield_hud(player) local function remove_shield_hud(player)
set_interact(player, true)
playerphysics.remove_physics_factor(player, "speed", "shield_speed")
if not shield_hud[player] then return end --this function takes a long time. only run it when necessary if not shield_hud[player] then return end --this function takes a long time. only run it when necessary
player:hud_remove(shield_hud[player]) player:hud_remove(shield_hud[player])
shield_hud[player] = nil shield_hud[player] = nil
@ -231,9 +252,6 @@ local function remove_shield_hud(player)
if not hf.wielditem then if not hf.wielditem then
player:hud_set_flags({wielditem = true}) player:hud_set_flags({wielditem = true})
end end
playerphysics.remove_physics_factor(player, "speed", "shield_speed")
set_interact(player, true)
end end
local function add_shield_entity(player, i) local function add_shield_entity(player, i)
@ -251,6 +269,11 @@ local function remove_shield_entity(player, i)
end end
end end
local function is_rmb_conflicting_node(nodename)
local nodedef = minetest.registered_nodes[nodename] or {}
return nodedef.on_rightclick
end
local function handle_blocking(player) local function handle_blocking(player)
local player_shield = mcl_shields.players[player] local player_shield = mcl_shields.players[player]
local rmb = player:get_player_control().RMB local rmb = player:get_player_control().RMB
@ -259,14 +282,25 @@ local function handle_blocking(player)
return return
end end
local pointed_thing = mcl_util.get_pointed_thing(player, true)
local wielded_stack = player:get_wielded_item()
local shield_in_offhand = mcl_shields.wielding_shield(player, 1) local shield_in_offhand = mcl_shields.wielding_shield(player, 1)
local shield_in_hand = mcl_shields.wielding_shield(player) local shield_in_hand = mcl_shields.wielding_shield(player)
local not_blocking = player_shield.blocking == 0 local not_blocking = player_shield.blocking == 0
local pos = player:get_pos() if pointed_thing and pointed_thing.type == "node" then
local pointed_node = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(pointed_node.name, "container") > 1
or is_rmb_conflicting_node(pointed_node.name)
or wielded_stack:get_definition().type == "node" then
return
end
end
if shield_in_hand then if shield_in_hand then
if not_blocking then if not_blocking then
minetest.after(0.25, function() minetest.after(0.05, function()
if (not_blocking or not shield_in_offhand) and shield_in_hand and rmb then if (not_blocking or not shield_in_offhand) and shield_in_hand and rmb then
player_shield.blocking = 2 player_shield.blocking = 2
set_shield(player, true, 2) set_shield(player, true, 2)
@ -276,22 +310,15 @@ local function handle_blocking(player)
player_shield.blocking = 2 player_shield.blocking = 2
end end
elseif shield_in_offhand then elseif shield_in_offhand then
local pointed_thing = mcl_util.get_pointed_thing(player, true) local offhand_can_block = minetest.get_item_group(wielded_item(player), "cannot_block") ~= 1
local offhand_can_block = (wielded_item(player) == "" or not pointed_thing)
and (minetest.get_item_group(wielded_item(player), "bow") ~= 1 and minetest.get_item_group(wielded_item(player), "crossbow") ~= 1)
if pointed_thing and pointed_thing.type == "node" then
if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "container") > 1 then
return
end
end
if not offhand_can_block then if not offhand_can_block then
return return
end end
if not_blocking then if not_blocking then
minetest.after(0.25, function() minetest.after(0.05, function()
if (not_blocking or not shield_in_hand) and shield_in_offhand and rmb and offhand_can_block then if (not_blocking or not shield_in_hand) and shield_in_offhand
and rmb and offhand_can_block then
player_shield.blocking = 1 player_shield.blocking = 1
set_shield(player, true, 1) set_shield(player, true, 1)
end end
@ -344,7 +371,7 @@ local function add_shield_hud(shieldstack, player, blocking)
z_index = -200, z_index = -200,
}) })
playerphysics.add_physics_factor(player, "speed", "shield_speed", 0.5) playerphysics.add_physics_factor(player, "speed", "shield_speed", 0.5)
set_interact(player, nil) set_interact(player, false)
end end
local function update_shield_hud(player, blocking, shieldstack) local function update_shield_hud(player, blocking, shieldstack)

View File

@ -1,4 +1,4 @@
name = mcl_signs name = mcl_signs
description = New and Improved signs - can be colored and made to glow. description = New and Improved signs - can be colored and made to glow.
depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors, mcl_util depends = mcl_core, mcl_sounds, mcl_dye, mcl_colors, mcl_util, mesecons_mvps
optional_depends = doc optional_depends = doc

View File

@ -167,6 +167,12 @@ minetest.register_node("mcl_smithing_table:table", {
end, end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player) allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
end
local stackname = stack:get_name() local stackname = stack:get_name()
local def = stack:get_definition() local def = stack:get_definition()
if if
@ -187,6 +193,16 @@ minetest.register_node("mcl_smithing_table:table", {
return 0 return 0
end, end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0 return 0
end, end,

View File

@ -6,6 +6,7 @@ minetest.register_tool("mcl_spyglass:spyglass",{
inventory_image = "mcl_spyglass.png", inventory_image = "mcl_spyglass.png",
stack_max = 1, stack_max = 1,
_mcl_toollike_wield = true, _mcl_toollike_wield = true,
touch_interaction = "short_dig_long_place",
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -22,9 +22,13 @@ dig_speed_class group:
-- Help texts -- Help texts
local pickaxe_longdesc = S("Pickaxes are mining tools to mine hard blocks, such as stone. A pickaxe can also be used as weapon, but it is rather inefficient.") local pickaxe_longdesc = S("Pickaxes are mining tools to mine hard blocks, such as stone. A pickaxe can also be used as weapon, but it is rather inefficient.")
local axe_longdesc = S("An axe is your tool of choice to cut down trees, wood-based blocks and other blocks. Axes deal a lot of damage as well, but they are rather slow.") local axe_longdesc = S("An axe is your tool of choice to cut down trees, wood-based blocks and other blocks. Axes deal a lot of damage as well, but they are rather slow.")
local sword_longdesc = S("Swords are great in melee combat, as they are fast, deal high damage and can endure countless battles. Swords can also be used to cut down a few particular blocks, such as cobwebs.") local sword_longdesc = S("Swords are great in melee combat, as they are fast, deal high damage and can endure countless battles. Swords can also be used to cut down a few particular blocks, such as cobwebs.")
local sword_use = S("To slash multiple enemies, hold the sword in your hand, then use (rightclick) an enemy.")
local shovel_longdesc = S("Shovels are tools for digging coarse blocks, such as dirt, sand and gravel. They can also be used to turn grass blocks to grass paths. Shovels can be used as weapons, but they are very weak.") local shovel_longdesc = S("Shovels are tools for digging coarse blocks, such as dirt, sand and gravel. They can also be used to turn grass blocks to grass paths. Shovels can be used as weapons, but they are very weak.")
local shovel_use = S("To turn a grass block into a grass path, hold the shovel in your hand, then use (rightclick) the top or side of a grass block. This only works when there's air above the grass block.") local shovel_use = S("To turn a grass block into a grass path, hold the shovel in your hand, then use (rightclick) the top or side of a grass block. This only works when there's air above the grass block.")
local shears_longdesc = S("Shears are tools to shear sheep and to mine a few block types. Shears are a special mining tool and can be used to obtain the original item from grass, leaves and similar blocks that require cutting.") local shears_longdesc = S("Shears are tools to shear sheep and to mine a few block types. Shears are a special mining tool and can be used to obtain the original item from grass, leaves and similar blocks that require cutting.")
local shears_use = S("To shear sheep or carve faceless pumpkins, use the “place” key on them. Faces can only be carved at the side of faceless pumpkins. Mining works as usual, but the drops are different for a few blocks.") local shears_use = S("To shear sheep or carve faceless pumpkins, use the “place” key on them. Faces can only be carved at the side of faceless pumpkins. Mining works as usual, but the drops are different for a few blocks.")

View File

@ -0,0 +1,799 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
local hammer_tt = S("Can crush blocks") .. "\n" .. S("Increased knockback")
local hammer_longdesc = S("Hammers are great in melee combat, as they deal high damage with increased knockback and can endure countless battles. Hammers can also be used to crush things.")
local hammer_use = S("To crush a block, dig the block with the hammer. This only works with some blocks.")
local spear_tt = S("Reaches farther") .. "\n" .. S("Can be thrown")
local spear_longdesc = S("Spears are great in melee combat, as they have an increased reach. They can also be thrown.")
local spear_use = S("To throw a spear, hold it in your hand, then hold use (rightclick) in the air.")
local wield_scale = mcl_vars.tool_wield_scale
local GRAVITY = 9.81
local YAW_OFFSET = -math.pi/2
local function dir_to_pitch(dir)
--local dir2 = vector.normalize(dir)
local xz = math.abs(dir.x) + math.abs(dir.z)
return -math.atan2(-dir.y, xz)
end
-- Time after which stuck spear is rechecked for being stuck
local STUCK_RECHECK_TIME = 5
-- Time in seconds after which a stuck spear is deleted
local SPEAR_TIMEOUT = 180
local SPEAR_ENTITY={
physical = true,
pointable = false,
visual = "item",
visual_size = {x=-0.5, y=-0.5},
textures = {"vl_weaponry:spear_wood"},
collisionbox = {-0.19, -0.125, -0.19, 0.19, 0.125, 0.19},
collide_with_objects = false,
_fire_damage_resistant = true,
_lastpos={},
_startpos=nil,
_damage=1, -- Damage on impact
_is_critical=false, -- Whether this spear would deal critical damage
_stuck=false, -- Whether spear is stuck
_stucktimer=nil,-- Amount of time (in seconds) the spear has been stuck so far
_stuckrechecktimer=nil,-- An additional timer for periodically re-checking the stuck status of an spear
_stuckin=nil, --Position of node in which spear is stuck.
_shooter=nil, -- ObjectRef of player or mob who threw it
_is_arrow = true,
_in_player = false,
_blocked = false,
_viscosity = 0, -- Viscosity of node the spear is currently in
_deflection_cooloff = 0, -- Cooloff timer after an spear deflection, to prevent many deflections in quick succession
_itemstack = nil, -- ItemStack of the original object
}
-- Destroy spear entity self at pos and drops it as an item
local function spawn_item(self, pos)
if not minetest.is_creative_enabled("") then
local item = minetest.add_item(pos, self._itemstack)
item:set_velocity(vector.new(0, 0, 0))
item:set_yaw(self.object:get_yaw())
end
mcl_burning.extinguish(self.object)
self.object:remove()
end
local function damage_particles(pos, is_critical)
if is_critical then
minetest.add_particlespawner({
amount = 15,
time = 0.1,
minpos = vector.offset(pos, -0.5, -0.5, -0.5),
maxpos = vector.offset(pos, 0.5, 0.5, 0.5),
minvel = vector.new(-0.1, -0.1, -0.1),
maxvel = vector.new(0.1, 0.1, 0.1),
minexptime = 1,
maxexptime = 2,
minsize = 1.5,
maxsize = 1.5,
collisiondetection = false,
vertical = false,
texture = "mcl_particles_crit.png^[colorize:#bc7a57:127",
})
end
end
function SPEAR_ENTITY.on_step(self, dtime)
mcl_burning.tick(self.object, dtime, self)
-- mcl_burning.tick may remove object immediately
if not self.object:get_pos() then return end
self._time_in_air = self._time_in_air + .001
local pos = self.object:get_pos()
local dpos = vector.round(vector.new(pos)) -- digital pos
local node = minetest.get_node(dpos)
if self._stuck then
self._stucktimer = self._stucktimer + dtime
self._stuckrechecktimer = self._stuckrechecktimer + dtime
if self._stucktimer > SPEAR_TIMEOUT then
spawn_item(self, pos)
return
end
-- Drop spear as item when it is no longer stuck
if self._stuckrechecktimer > STUCK_RECHECK_TIME then
local stuckin_def
if self._stuckin then
stuckin_def = minetest.registered_nodes[minetest.get_node(self._stuckin).name]
end
-- TODO: fall down without turning into an item?
if stuckin_def and stuckin_def.walkable == false then
spawn_item(self, pos)
return
end
self._stuckrechecktimer = 0
end
-- Pickup spear if player is nearby (not in Creative Mode)
local objects = minetest.get_objects_inside_radius(pos, 1)
for _,obj in ipairs(objects) do
if obj:is_player() then
if self._collectable and not minetest.is_creative_enabled(obj:get_player_name()) then
if obj:get_inventory():room_for_item("main", self._itemstack) then
obj:get_inventory():add_item("main", self._itemstack)
minetest.sound_play("item_drop_pickup", {
pos = pos,
max_hear_distance = 16,
gain = 1.0,
}, true)
mcl_burning.extinguish(self.object)
self.object:remove()
end
else
spawn_item(self, pos)
end
return
end
end
-- Check for object "collision". Done every tick (hopefully this is not too stressing)
else
if self._damage >= 9 and self._in_player == false then
minetest.add_particlespawner({
amount = 20,
time = .2,
minpos = vector.new(0,0,0),
maxpos = vector.new(0,0,0),
minvel = vector.new(-0.1,-0.1,-0.1),
maxvel = vector.new(0.1,0.1,0.1),
minexptime = 0.5,
maxexptime = 0.5,
minsize = 2,
maxsize = 2,
attached = self.object,
collisiondetection = false,
vertical = false,
texture = "mobs_mc_arrow_particle.png",
glow = 1,
})
end
local closest_object
local closest_distance
if self._deflection_cooloff > 0 then
self._deflection_cooloff = self._deflection_cooloff - dtime
end
local spear_dir = self.object:get_velocity()
--create a raycast from the spear based on the velocity of the spear to deal with lag
local raycast = minetest.raycast(pos, vector.add(pos, vector.multiply(spear_dir, 0.1)), true, false)
for hitpoint in raycast do
if hitpoint.type == "object" then
-- find the closest object that is in the way of the spear
local ok = false
if hitpoint.ref:is_player() and enable_pvp then
ok = true
elseif not hitpoint.ref:is_player() and hitpoint.ref:get_luaentity() then
if (hitpoint.ref:get_luaentity().is_mob or hitpoint.ref:get_luaentity()._hittable_by_projectile) then
ok = true
end
end
if ok then
local dist = vector.distance(hitpoint.ref:get_pos(), pos)
if not closest_object or not closest_distance then
closest_object = hitpoint.ref
closest_distance = dist
elseif dist < closest_distance then
closest_object = hitpoint.ref
closest_distance = dist
end
end
end
end
if closest_object then
local obj = closest_object
local is_player = obj:is_player()
local lua = obj:get_luaentity()
if obj == self._shooter and self._time_in_air > 1.02 or obj ~= self._shooter and (is_player or (lua and (lua.is_mob or lua._hittable_by_projectile))) then
if obj:get_hp() > 0 then
-- Check if there is no solid node between spear and object
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)
for pointed_thing in ray do
if pointed_thing.type == "object" and pointed_thing.ref == closest_object then
-- Target reached! We can proceed now.
break
elseif pointed_thing.type == "node" then
local nn = minetest.get_node(minetest.get_pointed_thing_position(pointed_thing)).name
local def = minetest.registered_nodes[nn]
if (not def) or def.walkable then
-- There's a node in the way. Delete spear without damage
spawn_item(self, pos)
return
end
end
end
-- Punch target object but avoid hurting enderman.
if not lua or lua.name ~= "mobs_mc:enderman" then
if not self._in_player then
damage_particles(vector.add(pos, vector.multiply(self.object:get_velocity(), 0.1)), self._is_critical)
end
if mcl_burning.is_burning(self.object) then
mcl_burning.set_on_fire(obj, 5)
end
if not self._in_player and not self._blocked then
obj:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=self._damage},
}, self.object:get_velocity())
if obj:is_player() then
if not mcl_shields.is_blocking(obj) then
spawn_item(self, pos)
else
self._blocked = true
self.object:set_velocity(vector.multiply(self.object:get_velocity(), -0.25))
end
minetest.after(150, function()
spawn_item(self, pos)
end)
else
spawn_item(self, pos)
end
end
end
if is_player then
if self._shooter and self._shooter:is_player() and not self._in_player and not self._blocked 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
end
if not self._in_player and not self._blocked then
minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true)
end
end
if not obj:is_player() then
mcl_burning.extinguish(self.object)
if self._piercing == 0 then
spawn_item(self, pos)
end
end
return
end
end
end
-- Check for node collision
if self._lastpos.x~=nil and not self._stuck then
local def = minetest.registered_nodes[node.name]
local vel = self.object:get_velocity()
-- Spear has stopped in one axis, so it probably hit something.
-- This detection is a bit clunky, but sadly, MT does not offer a direct collision detection for us. :-(
if (math.abs(vel.x) < 0.0001) or (math.abs(vel.z) < 0.0001) or (math.abs(vel.y) < 0.00001) then
-- Check for the node to which the spear is pointing
local dir
if math.abs(vel.y) < 0.00001 then
if self._lastpos.y < pos.y then
dir = vector.new(0, 1, 0)
else
dir = vector.new(0, -1, 0)
end
else
dir = minetest.facedir_to_dir(minetest.dir_to_facedir(minetest.yaw_to_dir(self.object:get_yaw()-YAW_OFFSET)))
end
self._stuckin = vector.add(dpos, dir)
local snode = minetest.get_node(self._stuckin)
local sdef = minetest.registered_nodes[snode.name]
-- If node is non-walkable, unknown or ignore, don't make spear stuck.
-- This causes a deflection in the engine.
if not sdef or sdef.walkable == false or snode.name == "ignore" then
self._stuckin = nil
if self._deflection_cooloff <= 0 then
-- Lose 1/3 of velocity on deflection
local newvel = vector.multiply(vel, 0.6667)
self.object:set_velocity(newvel)
-- Reset deflection cooloff timer to prevent many deflections happening in quick succession
self._deflection_cooloff = 1.0
end
else
-- Node was walkable, make spear stuck
self._stuck = true
self._stucktimer = 0
self._stuckrechecktimer = 0
self.object:set_velocity(vector.new(0, 0, 0))
self.object:set_acceleration(vector.new(0, 0, 0))
minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true)
if mcl_burning.is_burning(self.object) and snode.name == "mcl_tnt:tnt" then
tnt.ignite(self._stuckin)
end
-- Ignite Campfires
if mod_campfire and mcl_burning.is_burning(self.object) and minetest.get_item_group(snode.name, "campfire") ~= 0 then
mcl_campfires.light_campfire(self._stuckin)
end
-- Activate target
if mod_target and snode.name == "mcl_target:target_off" then
mcl_target.hit(self._stuckin, 1) --10 redstone ticks
end
-- Push the button! Push, push, push the button!
if mod_button and minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 then
local bdir = minetest.wallmounted_to_dir(node.param2)
-- Check the button orientation
if vector.equals(vector.add(dpos, bdir), self._stuckin) then
mesecon.push_button(dpos, node)
end
end
end
elseif (def and def.liquidtype ~= "none") then
-- Slow down spear in liquids
local v = def.liquid_viscosity
if not v then
v = 0
end
--local old_v = self._viscosity
self._viscosity = v
local vpenalty = math.max(0.1, 0.98 - 0.1 * v)
if math.abs(vel.x) > 0.001 then
vel.x = vel.x * vpenalty
end
if math.abs(vel.z) > 0.001 then
vel.z = vel.z * vpenalty
end
self.object:set_velocity(vel)
end
end
-- Update yaw
if not self._stuck then
local vel = self.object:get_velocity()
local yaw = minetest.dir_to_yaw(vel)+YAW_OFFSET
local pitch = dir_to_pitch(vel)
self.object:set_rotation({ x = 0, y = yaw, z = pitch })
end
-- Update internal variable
self._lastpos = pos
end
-- Force recheck of stuck spears when punched.
-- Otherwise, punching has no effect.
function SPEAR_ENTITY.on_punch(self)
if self._stuck then
self._stuckrechecktimer = STUCK_RECHECK_TIME
end
end
function SPEAR_ENTITY.get_staticdata(self)
local out = {
lastpos = self._lastpos,
startpos = self._startpos,
damage = self._damage,
is_critical = self._is_critical,
stuck = self._stuck,
stuckin = self._stuckin,
stuckin_player = self._in_player,
}
if self._stuck then
-- If _stucktimer is missing for some reason, assume the maximum
if not self._stucktimer then
self._stucktimer = SPEAR_TIMEOUT
end
out.stuckstarttime = minetest.get_gametime() - self._stucktimer
end
if self._shooter and self._shooter:is_player() then
out.shootername = self._shooter:get_player_name()
end
return minetest.serialize(out)
end
function SPEAR_ENTITY.on_activate(self, staticdata, dtime_s)
self._time_in_air = 1.0
local data = minetest.deserialize(staticdata)
if data then
self._stuck = data.stuck
if data.stuck then
if data.stuckstarttime then
-- First, check if the stuck spear is aleady past its life timer.
-- If yes, delete it.
self._stucktimer = minetest.get_gametime() - data.stuckstarttime
if self._stucktimer > SPEAR_TIMEOUT then
spawn_item(self, pos)
return
end
end
-- Perform a stuck recheck on the next step.
self._stuckrechecktimer = STUCK_RECHECK_TIME
self._stuckin = data.stuckin
end
-- Get the remaining spear state
self._lastpos = data.lastpos
self._startpos = data.startpos
self._damage = data.damage
self._is_critical = data.is_critical
if data.shootername then
local shooter = minetest.get_player_by_name(data.shootername)
if shooter and shooter:is_player() then
self._shooter = shooter
end
end
if data.stuckin_player then
spawn_item(self, pos)
end
end
self.object:set_armor_groups({ immortal = 1 })
end
minetest.register_entity("vl_weaponry:spear_entity", SPEAR_ENTITY)
local spear_throw_power = 25
local spear_on_place = function(wear_divisor)
return function(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
-- Call on_rightclick if the pointed node defines it
local node = minetest.get_node(pointed_thing.under)
if user and not user:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack
end
end
end
if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
minetest.record_protection_violation(pointed_thing.under, user:get_player_name())
return itemstack
end
local pos = user:get_pos()
pos.y = pos.y + 1.5
local dir = user:get_look_dir()
local yaw = user:get_look_horizontal()
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, "vl_weaponry:spear_entity")
obj:set_velocity({x=dir.x*spear_throw_power, y=dir.y*spear_throw_power, z=dir.z*spear_throw_power})
obj:set_acceleration({x=0, y=-GRAVITY, z=0})
obj:set_yaw(yaw-math.pi/2)
obj:set_properties({textures = {itemstack:get_name()}})
local le = obj:get_luaentity()
le._shooter = user
le._source_object = user
le._damage = itemstack:get_definition()._mcl_spear_thrown_damage
le._is_critical = false
le._startpos = pos
le._collectable = true
le._itemstack = itemstack
minetest.sound_play("mcl_bows_bow_shoot", {pos=pos, max_hear_distance=16}, true)
if user and user:is_player() then
if obj:get_luaentity().player == "" then
obj:get_luaentity().player = user
end
-- obj:get_luaentity().node = shooter:get_inventory():get_stack("main", 1):get_name()
end
return ItemStack()
end
end
local uses = {
wood = 60,
stone = 132,
iron = 251,
gold = 33,
diamond = 1562,
netherite = 2031,
}
local SPEAR_RANGE = 4.5
--Hammers
minetest.register_tool("vl_weaponry:hammer_wood", {
description = S("Wooden Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
_doc_items_hidden = false,
inventory_image = "vl_tool_woodhammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=15 },
tool_capabilities = {
full_punch_interval = 1.2,
max_drop_level=1,
damage_groups = {fleshy=4},
punch_attack_uses = 60,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 1, level = 1, uses = 60 },
shovely = { speed = 1, level = 2, uses = 60 }
},
})
minetest.register_tool("vl_weaponry:hammer_stone", {
description = S("Stone Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
inventory_image = "vl_tool_stonehammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=5 },
tool_capabilities = {
full_punch_interval = 1.3,
max_drop_level=3,
damage_groups = {fleshy=5},
punch_attack_uses = 132,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 2, level = 3, uses = 132 },
shovely = { speed = 2, level = 3, uses = 132 }
},
})
minetest.register_tool("vl_weaponry:hammer_iron", {
description = S("Iron Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
inventory_image = "vl_tool_steelhammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=14 },
tool_capabilities = {
full_punch_interval = 1.2,
max_drop_level=4,
damage_groups = {fleshy=6},
punch_attack_uses = 251,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 3, level = 4, uses = 251 },
shovely = { speed = 3, level = 4, uses = 251 }
},
})
minetest.register_tool("vl_weaponry:hammer_gold", {
description = S("Golden Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
inventory_image = "vl_tool_goldhammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=22 },
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=2,
damage_groups = {fleshy=5},
punch_attack_uses = 33,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 8, level = 4, uses = 33 },
shovely = { speed = 8, level = 4, uses = 33 }
},
})
minetest.register_tool("vl_weaponry:hammer_diamond", {
description = S("Diamond Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
inventory_image = "vl_tool_diamondhammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=10 },
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=5,
damage_groups = {fleshy=7},
punch_attack_uses = 1562,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 4, level = 5, uses = 1562 },
pickaxey = { speed = 4, level = 5, uses = 1562 }
},
_mcl_upgradable = true,
_mcl_upgrade_item = "vl_weaponry:hammer_netherite"
})
minetest.register_tool("vl_weaponry:hammer_netherite", {
description = S("Netherite Hammer"),
_tt_help = hammer_tt,
_doc_items_longdesc = hammer_longdesc,
_doc_items_usagehelp = hammer_use,
inventory_image = "vl_tool_netheritehammer.png",
wield_scale = wield_scale,
groups = { weapon=1, hammer=1, dig_speed_class=2, enchantability=10, fire_immune=1 },
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=5,
damage_groups = {fleshy=9},
punch_attack_uses = 2031,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_nether:netherite_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
pickaxey = { speed = 6, level = 6, uses = 2031 },
shovely = { speed = 6, level = 6, uses = 2031 }
},
})
--Spears
minetest.register_tool("vl_weaponry:spear_wood", {
description = S("Wooden Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
_doc_items_hidden = false,
inventory_image = "vl_tool_woodspear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.wood),
on_secondary_use = spear_on_place(uses.wood),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=15 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=1,
damage_groups = {fleshy=3},
punch_attack_uses = 60,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:wood",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 60 },
swordy_cobweb = { speed = 2, level = 1, uses = 60 }
},
_mcl_spear_thrown_damage = 5,
})
minetest.register_tool("vl_weaponry:spear_stone", {
description = S("Stone Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
inventory_image = "vl_tool_stonespear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.stone),
on_secondary_use = spear_on_place(uses.stone),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=5 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=3,
damage_groups = {fleshy=4},
punch_attack_uses = 132,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:cobble",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 132 },
swordy_cobweb = { speed = 2, level = 1, uses = 132 }
},
_mcl_spear_thrown_damage = 6,
})
minetest.register_tool("vl_weaponry:spear_iron", {
description = S("Iron Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
inventory_image = "vl_tool_steelspear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.iron),
on_secondary_use = spear_on_place(uses.iron),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=14 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=4,
damage_groups = {fleshy=5},
punch_attack_uses = 251,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 251 },
swordy_cobweb = { speed = 2, level = 1, uses = 251 }
},
_mcl_spear_thrown_damage = 7,
})
minetest.register_tool("vl_weaponry:spear_gold", {
description = S("Golden Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
inventory_image = "vl_tool_goldspear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.gold),
on_secondary_use = spear_on_place(uses.gold),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=22 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=2,
damage_groups = {fleshy=3},
punch_attack_uses = 33,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 33 },
swordy_cobweb = { speed = 2, level = 1, uses = 33 }
},
_mcl_spear_thrown_damage = 5,
})
minetest.register_tool("vl_weaponry:spear_diamond", {
description = S("Diamond Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
inventory_image = "vl_tool_diamondspear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.diamond),
on_secondary_use = spear_on_place(uses.diamond),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=10 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=5,
damage_groups = {fleshy=6},
punch_attack_uses = 1562,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 1562 },
swordy_cobweb = { speed = 2, level = 1, uses = 1562 }
},
_mcl_spear_thrown_damage = 8,
_mcl_upgradable = true,
_mcl_upgrade_item = "vl_weaponry:spear_netherite"
})
minetest.register_tool("vl_weaponry:spear_netherite", {
description = S("Netherite Spear"),
_tt_help = spear_tt,
_doc_items_longdesc = spear_longdesc,
_doc_items_usagehelp = spear_use,
inventory_image = "vl_tool_netheritespear.png",
wield_scale = wield_scale,
on_place = spear_on_place(uses.netherite),
on_secondary_use = spear_on_place(uses.netherite),
groups = { weapon=1, spear=1, dig_speed_class=2, enchantability=10, fire_immune=1 },
range = SPEAR_RANGE,
tool_capabilities = {
full_punch_interval = 0.75,
max_drop_level=5,
damage_groups = {fleshy=8},
punch_attack_uses = 2031,
},
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_nether:netherite_ingot",
_mcl_toollike_wield = true,
_mcl_diggroups = {
swordy = { speed = 2, level = 1, uses = 2031 },
swordy_cobweb = { speed = 2, level = 1, uses = 2031 }
},
_mcl_spear_thrown_damage = 12,
})

View File

@ -0,0 +1,3 @@
name = vl_weaponry
author = Herowl
depends = mcl_sounds, mcl_init, mcl_bows

View File

@ -36,7 +36,11 @@ else
end end
end end
tsm_railcorridors.carts = { "mcl_minecarts:chest_minecart" } tsm_railcorridors.carts = {
"mcl_minecarts:minecart", "mcl_minecarts:minecart",
"mcl_minecarts:chest_minecart", "mcl_minecarts:chest_minecart",
"mcl_minecarts:tnt_minecart"
}
-- This is called after a spawner has been placed by the game. -- This is called after a spawner has been placed by the game.
-- Use this to properly set up the metadata and stuff. -- Use this to properly set up the metadata and stuff.
@ -54,9 +58,11 @@ end
function tsm_railcorridors.on_construct_cart(_, cart, pr_carts) function tsm_railcorridors.on_construct_cart(_, cart, pr_carts)
local l = cart:get_luaentity() local l = cart:get_luaentity()
local inv = mcl_entity_invs.load_inv(l,27) local inv = mcl_entity_invs.load_inv(l,27)
local items = tsm_railcorridors.get_treasures(pr_carts) if inv then -- otherwise probably not a chest minecart
mcl_loot.fill_inventory(inv, "main", items, pr_carts) local items = tsm_railcorridors.get_treasures(pr_carts)
mcl_entity_invs.save_inv(l) mcl_loot.fill_inventory(inv, "main", items, pr_carts)
mcl_entity_invs.save_inv(l)
end
end end
-- Fallback function. Returns a random treasure. This function is called for chests -- Fallback function. Returns a random treasure. This function is called for chests

View File

@ -397,7 +397,9 @@ end
-- This is a workaround thanks to the fact that minetest.add_entity is unreliable as fuck -- This is a workaround thanks to the fact that minetest.add_entity is unreliable as fuck
-- See: https://github.com/minetest/minetest/issues/4759 -- See: https://github.com/minetest/minetest/issues/4759
-- FIXME: Kill this horrible hack with fire as soon you can. -- FIXME: Kill this horrible hack with fire as soon you can.
local function RecheckCartHack(params) local RecheckCartHack = nil
if not minetest.features.random_state_restore then -- proxy for minetest > 5.9.0, this feature will not be removed
RecheckCartHack = function(params)
local pos = params[1] local pos = params[1]
local cart_id = params[2] local cart_id = params[2]
-- Find cart -- Find cart
@ -412,6 +414,7 @@ local function RecheckCartHack(params)
end end
minetest.log("info", "[tsm_railcorridors] Cart spawn FAILED: "..minetest.pos_to_string(pos)) minetest.log("info", "[tsm_railcorridors] Cart spawn FAILED: "..minetest.pos_to_string(pos))
end end
end
-- Try to place a cobweb. -- Try to place a cobweb.
-- pos: Position of cobweb -- pos: Position of cobweb
@ -935,13 +938,17 @@ local function spawn_carts()
-- See <https://github.com/minetest/minetest/issues/4759> -- See <https://github.com/minetest/minetest/issues/4759>
local cart_id = tsm_railcorridors.carts[cart_type] local cart_id = tsm_railcorridors.carts[cart_type]
minetest.log("info", "[tsm_railcorridors] Cart spawn attempt: "..minetest.pos_to_string(cpos)) minetest.log("info", "[tsm_railcorridors] Cart spawn attempt: "..minetest.pos_to_string(cpos))
minetest.add_entity(cpos, cart_id) local obj = minetest.add_entity(cpos, cart_id)
-- This checks if the cart is actually spawned, it's a giant hack! -- This checks if the cart is actually spawned, it's a giant hack!
-- Note that the callback function is also called there. -- Note that the callback function is also called there.
-- TODO: Move callback function to this position when the -- TODO: Move callback function to this position when the
-- minetest.add_entity bug has been fixed (supposedly in 5.9.0?) -- minetest.add_entity bug has been fixed (supposedly in 5.9.0?)
minetest.after(3, RecheckCartHack, {cpos, cart_id}) if RecheckCartHack then
minetest.after(3, RecheckCartHack, {cpos, cart_id})
else
tsm_railcorridors.on_construct_cart(cpos, obj, pr_carts)
end
end end
end end
carts_table = {} carts_table = {}

View File

@ -0,0 +1,33 @@
bonemeal = {
item_list = {
bucket_water = "mcl_buckets:bucket_water",
bucket_empty = "mcl_buckets:bucket_empty",
dirt = "mcl_core:dirt",
torch = "mcl_torches:torch",
coral = "mcl_ocean:dead_horn_coral_block"
}
}
function bonemeal:on_use(pos, strength, node)
-- Fake itemstack for bone meal
local itemstack = ItemStack("mcl_bone_meal:bone_meal")
local pointed_thing = {
above = pos,
under = vector.offset(pos, 0, -1, 0)
}
mcl_bone_meal.use_bone_meal(itemstack, nil, pointed_thing)
end
function bonemeal:is_creative(player_name)
return minetest.is_creative_enabled(player_name)
end
function bonemeal:add_deco(list)
minetest.log("TODO: implement bonemeal:add_deco("..dump(list).."..)")
for i = 1,#list do
local item = list[i]
end
end
minetest.register_alias("bonemeal:bone", "mcl_mobitems:bone")

View File

@ -0,0 +1,4 @@
name = bonemeal
author = teknomunk
description = Compatibility shim for WorldEdit-Additions bonemeal support
depends = mcl_bone_meal, mcl_mobitems, mcl_flowers

View File

@ -30,17 +30,5 @@ for _, action in pairs({"grant", "revoke"}) do
if priv == "fly" then if priv == "fly" then
meta:set_int("mcl_privs:fly_changed", 1) meta:set_int("mcl_privs:fly_changed", 1)
end end
--[[
so e.g. hackers who have been revoked of the interact privilege
will not automatically get the interact privilege through the mcl shields code back
]]
if priv == "interact" then
if action == "revoke" then
meta:set_int("mcl_privs:interact_revoked", 1)
else
meta:set_int("mcl_privs:interact_revoked", 0)
end
end
end) end)
end end

View File

@ -752,9 +752,10 @@ end, -200)
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage) minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
-- attack reach limit -- attack reach limit
if hitter and hitter:is_player() then if hitter and hitter:is_player() then
local weapon = hitter:get_wielded_item()
local player_pos = player:get_pos() local player_pos = player:get_pos()
local hitter_pos = hitter:get_pos() local hitter_pos = hitter:get_pos()
if vector.distance(player_pos, hitter_pos) > 3 then if vector.distance(player_pos, hitter_pos) > (weapon:get_definition().range or 3) then
damage = 0 damage = 0
return damage return damage
end end

View File

@ -45,6 +45,9 @@ mcl_disabled_structures (Disabled structures) string
# Comma separated list of disabled event names # Comma separated list of disabled event names
mcl_disabled_events (Disabled events) string mcl_disabled_events (Disabled events) string
# Control the relative plant growth speed (default: 1)
vl_plant_growth (Plant growth factor) float 1.0 0 100
[Players] [Players]
# If enabled, players respawn at the bed they last lay on instead of normal # If enabled, players respawn at the bed they last lay on instead of normal
# spawn. # spawn.

View File

Before

Width:  |  Height:  |  Size: 244 B

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

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