Compare commits

...

92 Commits

Author SHA1 Message Date
Kristian ed8319e013 TOM bøger 2023-01-29 19:37:44 +01:00
Kristian 6f8bd8a8d7 Banners done 2023-01-28 13:36:05 +01:00
Kristian 75899036df Indtil banner 2023-01-26 13:47:43 +01:00
Kristian 8350bbc6ac Skift til items. TOM ambolt. 2023-01-22 20:53:59 +01:00
Kristian 8d2410f697 TOM docs_items 2023-01-20 23:35:56 +01:00
Kristian 7911a18e00 TOM doc/doc 2023-01-14 16:31:02 +01:00
Kristian 42c5bf0be9 TOM doc/doc 2023-01-14 16:30:48 +01:00
Kristian 62f31a4649 TOM Mobs 2023-01-13 22:17:43 +01:00
Kristian e87c38d653 Three fully translated 2023-01-12 16:05:35 +01:00
ancientmarinerdev 482a6071f5 Merge pull request 'Beetroot Seed fix' (#3294) from beetroot_seed_fix into master
Reviewed-on: MineClone2/MineClone2#3294
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-11 22:27:58 +00:00
Michieal ff7299a444 Fix beetroot seeds not dropping.
Changed drop rate to 1-4.

Added in Fortune drops too. (Per the minecraft wiki.)
2023-01-10 21:38:42 -05:00
ancientmarinerdev 2ed3c1c480 Merge pull request 'Mob Fixes' (#3242) from mob_fixes into master
Reviewed-on: MineClone2/MineClone2#3242
Reviewed-by: Michieal <michieal@noreply.git.minetest.land>
2023-01-11 01:11:07 +00:00
ancientmarinerdev 111c885417 Added burger alias 2023-01-11 01:07:18 +00:00
ancientmarinerdev 8e1f00d428 Villager breeding is now unburgered. Burger now needs right click to initiate follow. 2023-01-11 01:07:18 +00:00
ancientmarinerdev 4fd4425aae Improved mob debug 2023-01-11 01:07:18 +00:00
ancientmarinerdev ac4cd2c325 Improve performance for head swivel check 2023-01-11 01:07:18 +00:00
ancientmarinerdev 01c8009c6a Tidy on_step function 2023-01-11 01:07:18 +00:00
ancientmarinerdev ef90820f67 Fix farm animals so they don't get into combat state 2023-01-11 01:07:18 +00:00
ancientmarinerdev d6d11b9526 Zombie villagers cannot despawn during curing process 2023-01-11 01:07:17 +00:00
ancientmarinerdev b0264b2736 Endermen now despawn when not holding a block. 2023-01-11 01:07:17 +00:00
PrairieWind b3da85be64 Merge pull request 'mcl_music_without_menu_music' (#3291) from mcl_music_without_menu_music into master
Reviewed-on: MineClone2/MineClone2#3291
Reviewed-by: PrairieWind <prairie.astronomer1@gmail.com>
2023-01-10 19:15:22 +00:00
ancientmarinerdev 3ed32abc4e Add credit for nether music 2023-01-10 19:05:56 +00:00
kay27 9db6050638 Fix music interruption 2023-01-10 19:05:56 +00:00
kay27 7ceb953a56 Add different music for different dimensions 2023-01-10 19:05:56 +00:00
kay27 1894d8c5f0 Fix mcl_music: play to all players, play every day, overworld only 2023-01-10 19:05:56 +00:00
kay27 419d61edde Add trivial mcl_music mod and a piano track by diminixed 2023-01-10 19:05:55 +00:00
PrairieWind 9820309762 Merge pull request 'mcl_crimson_update' (#3289) from mcl_crimson_update into master
Reviewed-on: MineClone2/MineClone2#3289
Reviewed-by: PrairieWind <prairie.astronomer1@gmail.com>
2023-01-10 18:17:39 +00:00
Michieal f46581905a Added veins to the Hyphae log sides. 2023-01-10 04:30:29 -05:00
Michieal 4f6de581dd fixed the warped fungus mushroom texture.
fixed the warped fungus selection box.
2023-01-10 04:29:47 -05:00
ancientmarinerdev db62631540 Merge pull request 'mcl_lectern' (#3282) from mcl_lectern into master
Reviewed-on: MineClone2/MineClone2#3282
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-09 22:33:31 +00:00
ancientmarinerdev fb30564827 Ooooooh, lecterns. My favourite. 2023-01-09 22:32:14 +00:00
Michieal 8c355db3ce Made Lecterns solid. 2023-01-09 22:32:14 +00:00
Michieal eae08f3010 Finished Lecterns.
Added in License.txt.
2023-01-09 22:32:14 +00:00
Michieal 4701c4d6e7 Built basic lectern model, texture, and node definition.
Created crafting recipe.

Marked Lecterns as WIP.

Started defining placement.

Added in README.txt.
2023-01-09 22:32:14 +00:00
ancientmarinerdev 66f368531d Merge pull request 'Fix Country Lode HUD Issue' (#3268) from advancement_bug_fix into master
Reviewed-on: MineClone2/MineClone2#3268
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-09 21:17:41 +00:00
PrairieWind 7cb5c55d68 Update Translation Files
Fixes the translation error for other languages
2023-01-09 13:36:36 -07:00
PrairieWind 6fd799ac42 Fix Country Lode HUD Issue
Fixed the error that was thrown when the advancement is unlocked and also fixed the popup HUD so the advancement title fits correctly
2023-01-06 16:35:59 +00:00
ancientmarinerdev 01bb753549 Merge pull request 'Refactor mob_step and do_states' (#3231) from mob_tweaks into master
Reviewed-on: MineClone2/MineClone2#3231
Reviewed-by: Michieal <michieal@noreply.git.minetest.land>
2023-01-06 14:10:39 +00:00
ancientmarinerdev 59694ebc7c Fix merge conflict 2023-01-06 13:52:03 +00:00
ancientmarinerdev 00c4ecf643 Merge pull request 'Villagers and pathfinding improvements' (#3083) from village_town_bell_pathfix into master
Reviewed-on: MineClone2/MineClone2#3083
Reviewed-by: Michieal <michieal@noreply.git.minetest.land>
2023-01-06 02:59:48 +00:00
ancientmarinerdev e4db91d35c Fix crash bug 2023-01-06 02:59:02 +00:00
ancientmarinerdev 2527479401 Clean up on isle 5, please 2023-01-06 02:59:02 +00:00
ancientmarinerdev 85f7bbdb80 Optimisation. Don't even prepare to path if not ready to path 2023-01-06 02:59:02 +00:00
ancientmarinerdev 465a919f6b Villager will now reclaim job during the day even when it isn't work time 2023-01-06 02:59:02 +00:00
ancientmarinerdev 325a666c62 Added pathfinder constants to make it easier to tweak 2023-01-06 02:59:02 +00:00
ancientmarinerdev e9b54e85c2 Pathfinding clean up 2023-01-06 02:59:02 +00:00
ancientmarinerdev 4324fe2489 Villager will now path from one house to another in search of available job or bed 2023-01-06 02:59:02 +00:00
ancientmarinerdev d6804bf4b7 Fix distance to target issue, and refactor pathing actions 2023-01-06 02:59:02 +00:00
ancientmarinerdev 87f04bdd9f Prevent attempting to path through 2 doors until code supports it. Clean up also. 2023-01-06 02:59:02 +00:00
ancientmarinerdev e3307d647b Fix pathing to bell that is sat on the ground 2023-01-06 02:59:02 +00:00
ancientmarinerdev 29cd73cb84 Pathfinding through door should also check door closest to position so villager can leave current house 2023-01-06 02:59:02 +00:00
ancientmarinerdev 5c0a763b83 Optimisation - Only check for town bell if ready to path 2023-01-06 02:59:02 +00:00
ancientmarinerdev 9b1ceebf0d Villagers will now pathfind to town bell that isn't on the ground 2023-01-06 02:59:02 +00:00
ancientmarinerdev 856a60bcc2 Merge pull request 'Fix a few issues with sweet berries.' (#3187) from CyberMango/MineClone2:bug/mango/sweet_berry_fixes into master
Reviewed-on: MineClone2/MineClone2#3187
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-06 00:09:41 +00:00
𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 ddd004c0f0 Merge pull request 'Fix incorrect foundation size for belltower' (#3147) from village_tweaks into master
Reviewed-on: MineClone2/MineClone2#3147
Reviewed-by: 𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 <mrrar@noreply.git.minetest.land>
2023-01-04 21:45:47 +00:00
ancientmarinerdev 609ef220ad Village building and paths should not spawn on top of snowy trees 2023-01-04 15:14:40 -06:00
ancientmarinerdev 32a7eb4087 Fix incorrect foundation size for belltower 2023-01-04 15:14:37 -06:00
CyberMango 5e969ba928 Added sweet berries death messages. 2023-01-04 23:04:19 +02:00
CyberMango 17e02aec3c Applying bone meal on a stage 3 sweet berry no longer grows it.
It now ignores the bone meal and harvests the sweet berry as normal.
2023-01-04 23:04:19 +02:00
CyberMango fb28e192e6 Bone meal applied on sweet berries only grows them by 1 stage now.
The interface of the grow plant is a bit confusing since even with
stages set to 0 the plant grows by 1 stage (if other conditions such as
light are met). Therefore changing it to 0 makes the plant grow by 1.
2023-01-04 23:04:19 +02:00
CyberMango 0f569fdbaa Bone meal on sweet berries in creative mode is no longer wasted and
minor fixes.

removed an unnecessary -- in a comment.
Removed a redundant concatination.
2023-01-04 23:04:19 +02:00
CyberMango 8a7fcfde82 Fixed sweet berries bugs.
Now they can only be placed a tile's upper part.
Also when destroyed bushes at stage 2 drop 1 or 2 berries, while bushes
at stage 3 drop 2 or 3 (instead of fixed numbers of 1 and 3
respectively).
Also harvesting sweet berries at stage 3 (final) brings them to stage 1
instead of just to stage 2. Number of dropped berries was adjusted.
2023-01-04 23:04:19 +02:00
CyberMango fb51067c78 Created a shared function for planting a seed that can also be consumed. 2023-01-04 23:04:19 +02:00
ancientmarinerdev 7ea41a2f21 Merge pull request 'Fix baby zombies going through 1 node high space' (#3241) from short_baby_zombies into master
Reviewed-on: MineClone2/MineClone2#3241
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-04 14:56:26 +00:00
𝕵𝖔𝖍𝖆𝖓𝖓𝖊𝖘 𝕱𝖗𝖎𝖙𝖟 0b1916b807 Fix baby zombies going through 1 node high space 2023-01-04 07:52:48 -06:00
ancientmarinerdev 0fca1ce469 Merge pull request 'Fix crash for sky colour if cannot find biome' (#3239) from fix_colour_crash_risk into master
Reviewed-on: MineClone2/MineClone2#3239
Reviewed-by: Michieal <michieal@noreply.git.minetest.land>
2023-01-03 01:02:19 +00:00
ancientmarinerdev df6d1c026a Fix crash for sky colour if cannot find biome 2023-01-02 21:48:58 +00:00
ancientmarinerdev f8ae702ce4 Function name consistency 2023-01-02 00:58:23 +00:00
ancientmarinerdev 5faf060122 Fix crash and remove unused duplicate variables 2023-01-02 00:54:08 +00:00
ancientmarinerdev 8c648d1fc3 Refactor mob_step and do_states 2023-01-02 00:00:40 +00:00
ancientmarinerdev 46052e5b7e Merge pull request 'Add templates for issues and pull requests' (#3220) from gitea_templates into master
Reviewed-on: MineClone2/MineClone2#3220
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2023-01-01 19:04:12 +00:00
iliekprogrammar 6430fcf103 Clarify *missing feature request* template 2023-01-01 19:03:34 +00:00
iliekprogrammar 7376b08c61 Better headers. More distinct *missing feature* template 2023-01-01 19:03:34 +00:00
iliekprogrammar 2e28a3386b Revert "Add "Testing/Review needed" tag to pull request templates"
This reverts commit 45656d8b747eac6400b2752fe2de603308ca69ef.
2023-01-01 19:03:34 +00:00
iliekprogrammar 98dac6dcd7 Add "Testing/Review needed" tag to pull request templates 2023-01-01 19:03:34 +00:00
iliekprogrammar 3026808a71 Add templates for issues and pull requests 2023-01-01 19:03:34 +00:00
test1 7c7521ff15 Merge pull request 'Update readme' (#3223) from updated_readme into master
Reviewed-on: MineClone2/MineClone2#3223
Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
2022-12-31 13:23:03 +00:00
test1 50d8e95c16 Update readme 2022-12-31 13:16:52 +00:00
iliekprogrammar fc74bd5cfe Merge pull request 'fix-cocoa-place' (#3221) from fix-cocoa-place into master
Reviewed-on: MineClone2/MineClone2#3221
Reviewed-by: iliekprogrammar <iliekprogrammar@gmail.com>
2022-12-31 10:49:57 +00:00
kabou 2a37d38f6c Reformat cocoa pod node definition groups. 2022-12-31 11:18:04 +01:00
kabou 89821a8329 Rename cocoa pod placement function.
* Rename cocoa pod placement function to match the `on_place` call in
  the cocoa pods item definition.
* Make the function local, there are no callers outside of mcl_cocoas.
2022-12-31 10:41:39 +01:00
iliekprogrammar 3249c13752 Merge pull request '`mcl_meshhand` fixes' (#2939) from mcl-meshhand-fixes into master
Reviewed-on: MineClone2/MineClone2#2939
Reviewed-by: iliekprogrammar <iliekprogrammar@gmail.com>
2022-12-30 18:50:46 +00:00
iliekprogrammar 2ea72ccda8 Merge branch 'master' into mcl-meshhand-fixes 2022-12-30 18:47:55 +00:00
iliekprogrammar 5237eca31e Merge pull request '`mcl_item_entity` fixes' (#2936) from mcl-item-entity-fixes into master
Reviewed-on: MineClone2/MineClone2#2936
Reviewed-by: iliekprogrammar <iliekprogrammar@gmail.com>
2022-12-30 18:39:34 +00:00
iliekprogrammar c2ba70a601 Merge branch 'master' into mcl-item-entity-fixes 2022-12-30 18:34:41 +00:00
iliekprogrammar 723fe9c532 Merge pull request 'mcl_init fixes' (#2862) from mcl-init-fixes into master
Reviewed-on: MineClone2/MineClone2#2862
Reviewed-by: iliekprogrammar <iliekprogrammar@gmail.com>
2022-12-30 18:18:21 +00:00
iliekprogrammar 661afed46c Merge branch 'master' into mcl-init-fixes 2022-12-30 18:11:08 +00:00
AFCMS 96e83e866c
Make `mcl_item_entity` API public 2022-11-15 21:48:58 +01:00
AFCMS 3bb86fd436
Fix warnings + add type annotations
- fix wrong usage of `mcl_enchanting.get_enchantments`
- use new vectors everywhere
- simplify code
- make code lines less long
2022-11-15 21:48:57 +01:00
AFCMS 4acee8e64e
Fixes to `mcl_meshhand`
- fix actual crash when placing hand in world (undefined function)
- remove node fields redundant with default values
- remove support for `use_texture_alpha_string_modes`
- type annotation
- more explicit functions
2022-11-13 21:54:59 +01:00
AFCMS bacec2c7e6
Make 2 last params of `mcl_vars.get_node` optional 2022-10-25 11:01:44 +02:00
AFCMS a3d459f020
Refactor `mcl_init`
- use new vectors
- make code less confuse
- type annotations
2022-10-25 11:01:44 +02:00
87 changed files with 3562 additions and 1126 deletions

View File

@ -0,0 +1,36 @@
---
name: "Bug report"
about: "File a bug report"
labels:
- unconfirmed
- bug
---
<!--
Thanks for taking the time to fill out this bug report!
Please follow our contributing guidelines first:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CONTRIBUTING.md#rules-about-both-bugs-and-feature-requests
By submitting this issue, you agree to follow our Code of Conduct:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CODE_OF_CONDUCT.md
-->
<!--
What version of MineClone2 are you using? We do not provide support for outdated versions of MineClone2.
Current latest version is listed here, at the top:
https://git.minetest.land/MineClone2/MineClone2/tags
-->
MineClone2 version:
### What happened?
Report about the bug! Please send large log snippets as an attachement file.
### What should happen:
Tell us what should happen!
### Steps to reproduce
Tell us how we can reproduce the bug!

View File

@ -0,0 +1,26 @@
---
name: "Feature request"
about: "File a feature request not in Minecraft"
labels:
- "non-Minecraft feature"
- "needs discussion"
---
<!--
Got a new non-Minecraft feature request? Explain to us why we should consider your idea.
Please follow our contributing guidelines first:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CONTRIBUTING.md#rules-about-both-bugs-and-feature-requests
By submitting this issue, you agree to follow our Code of Conduct:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CODE_OF_CONDUCT.md
-->
### Feature
Tell us about your requested feature not in Minecraft!
### Why
Tell us why should we implement it!

View File

@ -0,0 +1,25 @@
---
name: "Missing Feature request"
about: "File a missing feature request in Minecraft but not in MineClone2"
labels:
- "missing feature"
---
<!--
Thanks for taking the time to fill out this missing feature request!
Please follow our contributing guidelines first:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CONTRIBUTING.md#rules-about-both-bugs-and-feature-requests
By submitting this issue, you agree to follow our Code of Conduct:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CODE_OF_CONDUCT.md
-->
### Current feature in Minecraft
Tell us about the feature currently in Minecraft! What is it like on Minecraft?
### Current feature in MineClone2
Tell us about the feature currently in MineClone2! What is different?

View File

@ -0,0 +1,20 @@
---
name: "Pull request"
about: "Submit a pull request"
labels:
---
<!--
Please follow our contributing guidelines first:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CONTRIBUTING.md#how-you-can-help-as-a-programmer
By submitting this pull request, you agree to follow our Code of Conduct:
https://git.minetest.land/MineClone2/MineClone2/src/branch/master/CODE_OF_CONDUCT.md
-->
Tell us about your pull request! Reference related issues, if necessary
### Testing
Tell us how to test your changes!

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
*.blend2
*.blend3
/.idea/
.Rproj.user

View File

@ -158,7 +158,7 @@ The following features are incomplete:
* Some monsters and animals
* Redstone-related things
* Special minecarts
* Some special minecarts (hopper and chest minecarts work)
* A couple of non-trivial blocks and items
Bonus features (not found in Minecraft):

View File

@ -3,26 +3,26 @@ mcl_vars = {}
mcl_vars.redstone_tick = 0.1
--- GUI / inventory menu settings
-- GUI / inventory menu settings
mcl_vars.gui_slots = "listcolors[#9990;#FFF7;#FFF0;#000;#FFF]"
-- nonbg is added as formspec prepend in mcl_formspec_prepend
mcl_vars.gui_nonbg = mcl_vars.gui_slots ..
"style_type[image_button;border=false;bgimg=mcl_inventory_button9.png;bgimg_pressed=mcl_inventory_button9_pressed.png;bgimg_middle=2,2]"..
"style_type[button;border=false;bgimg=mcl_inventory_button9.png;bgimg_pressed=mcl_inventory_button9_pressed.png;bgimg_middle=2,2]"..
"style_type[field;textcolor=#323232]"..
"style_type[label;textcolor=#323232]"..
"style_type[textarea;textcolor=#323232]"..
"style_type[checkbox;textcolor=#323232]"
mcl_vars.gui_nonbg = table.concat({
mcl_vars.gui_slots,
"style_type[image_button;border=false;bgimg=mcl_inventory_button9.png;bgimg_pressed=mcl_inventory_button9_pressed.png;bgimg_middle=2,2]",
"style_type[button;border=false;bgimg=mcl_inventory_button9.png;bgimg_pressed=mcl_inventory_button9_pressed.png;bgimg_middle=2,2]",
"style_type[field;textcolor=#323232]",
"style_type[label;textcolor=#323232]",
"style_type[textarea;textcolor=#323232]",
"style_type[checkbox;textcolor=#323232]",
})
-- Background stuff must be manually added by mods (no formspec prepend)
mcl_vars.gui_bg_color = "bgcolor[#00000000]"
mcl_vars.gui_bg_img = "background9[1,1;1,1;mcl_base_textures_background9.png;true;7]"
-- Legacy
mcl_vars.inventory_header = ""
-- Tool wield size
mcl_vars.tool_wield_scale = { x = 1.8, y = 1.8, z = 1 }
mcl_vars.tool_wield_scale = vector.new(1.8, 1.8, 1)
-- Mapgen variables
local mg_name = minetest.get_mapgen_setting("mg_name")
@ -35,53 +35,67 @@ mcl_vars.chunksize = math.max(1, tonumber(minetest.get_mapgen_setting("chunksize
mcl_vars.MAP_BLOCKSIZE = math.max(1, minetest.MAP_BLOCKSIZE or 16)
mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000)
mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, minetest.MAX_MAP_GENERATION_LIMIT or 31000)
local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2)
mcl_vars.central_chunk_offset_in_nodes = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
mcl_vars.chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE
local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE
local central_chunk_max_pos = central_chunk_min_pos + mcl_vars.chunk_size_in_nodes - 1
local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes
local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE)
local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) /
mcl_vars.MAP_BLOCKSIZE)
local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE
local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1
local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / mcl_vars.chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk
local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / mcl_vars.chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits.
mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * mcl_vars.chunk_size_in_nodes
mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * mcl_vars.chunk_size_in_nodes
---@param x integer
---@return integer
local function coordinate_to_block(x)
return math.floor(x / mcl_vars.MAP_BLOCKSIZE)
end
---@param x integer
---@return integer
local function coordinate_to_chunk(x)
return math.floor((coordinate_to_block(x) - central_chunk_offset) / mcl_vars.chunksize)
end
---@param pos Vector
---@return Vector
function mcl_vars.pos_to_block(pos)
return {
x = coordinate_to_block(pos.x),
y = coordinate_to_block(pos.y),
z = coordinate_to_block(pos.z)
}
return vector.new(
coordinate_to_block(pos.x),
coordinate_to_block(pos.y),
coordinate_to_block(pos.z)
)
end
---@param pos Vector
---@return Vector
function mcl_vars.pos_to_chunk(pos)
return {
x = coordinate_to_chunk(pos.x),
y = coordinate_to_chunk(pos.y),
z = coordinate_to_chunk(pos.z)
}
return vector.new(
coordinate_to_chunk(pos.x),
coordinate_to_chunk(pos.y),
coordinate_to_chunk(pos.z)
)
end
local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / mcl_vars.chunk_size_in_nodes)
local k_positive_z = k_positive * 2
local k_positive_y = k_positive_z * k_positive_z
---@param pos Vector
---@return integer
function mcl_vars.get_chunk_number(pos) -- unsigned int
local c = mcl_vars.pos_to_chunk(pos)
return
(c.y + k_positive) * k_positive_y +
return (c.y + k_positive) * k_positive_y +
(c.z + k_positive) * k_positive_z +
c.x + k_positive
end
@ -117,11 +131,8 @@ elseif singlenode then
mcl_vars.mg_bedrock_is_rough = false
else
-- Classic superflat
local ground = minetest.get_mapgen_setting("mgflat_ground_level")
ground = tonumber(ground)
if not ground then
ground = 8
end
local ground = tonumber(minetest.get_mapgen_setting("mgflat_ground_level")) or 8
mcl_vars.mg_overworld_min = ground - 3
mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit
mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min
@ -181,6 +192,8 @@ minetest.craftitemdef_default.stack_max = 64
math.randomseed(os.time())
local chunks = {} -- intervals of chunks generated
---@param pos Vector
function mcl_vars.add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
@ -207,6 +220,9 @@ function mcl_vars.add_chunk(pos)
end
chunks[#chunks + 1] = { n, n }
end
---@param pos Vector
---@return boolean
function mcl_vars.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
@ -217,47 +233,46 @@ function mcl_vars.is_generated(pos)
return false
end
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_vars.get_node(p, force, us_timeout)
---"Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
---@param pos Vector Position, if it's wrong, `{name="error"}` node will return.
---@param force? boolean Optional (default: `false`), Do the maximum to still read the node within us_timeout.
---@param us_timeout? number Optional (default: `244 = 0.000244 s = 1/80/80/80`), set it at least to `3000000` to let mapgen to finish its job
---@return node # Node definition, eg. `{name="air"}`. Unfortunately still can return `{name="ignore"}`.
---@nodiscard
function mcl_vars.get_node(pos, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
if not pos or not pos.x or not pos.y or not pos.z then return { name = "error" } end
-- try common way
local node = minetest.get_node(p)
local node = minetest.get_node(pos)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- copy vector to get sure it won't changed by other threads
local pos_copy = vector.copy(pos)
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
minetest.get_voxel_manip():read_from_map(pos_copy, pos_copy)
node = minetest.get_node(pos_copy)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_vars.is_generated(pos) then
if mcl_vars.is_generated(pos_copy) then
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
minetest.forceload_block(pos)
minetest.forceload_block(pos_copy)
else
minetest.emerge_area(pos, pos)
minetest.emerge_area(pos_copy, pos_copy)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
node = minetest.get_node(pos_copy)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < (us_timeout or 244)) do
node = minetest.get_node(pos_copy)
end
return node

View File

@ -0,0 +1,13 @@
# textdomain: mcl_boats
Acacia Boat=Akaciebåd
Birch Boat=Birkebåd
Boat=Båd
Boats are used to travel on the surface of water.=Både blier brugt til at rejse på vandoverflader.
Dark Oak Boat=Mørk egetræsbåd
Jungle Boat=Junglebåd
Oak Boat=Egetræsbåd
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Højre-klik på en vand for at placere båden. Højre-klik på båden for at gå ombord. Brug [Left] og [Right] til at styre. [Forwards] for at øge hastigheden, og [Backwards] for at sænke farten eller sejle bagud. Brug [Sneak] for at forlade båden, slå båden for at lave den om til en genstand.
Spruce Boat=Granbåd
Water vehicle=Vandfartøj
Sneak to dismount=Snig for at stige ud
Obsidian Boat=Obsidianbåd

View File

@ -0,0 +1,3 @@
# textdomain: mcl_falling_nodes
@1 was smashed by a falling anvil.=@1 blev smadret af en nedfaldende ambolt.
@1 was smashed by a falling block.=@1 blev smadret af en nedfaldende blok.

View File

@ -14,24 +14,17 @@ local function mcl_log (message)
end
end
minetest.register_on_joinplayer(function(player)
local name
name = player:get_player_name()
pool[name] = 0
pool[player:get_player_name()] = 0
end)
minetest.register_on_leaveplayer(function(player)
local name
name = player:get_player_name()
pool[name] = nil
pool[player:get_player_name()] = nil
end)
local has_awards = minetest.get_modpath("awards")
local mcl_item_entity = {}
mcl_item_entity = {}
--basic settings
local item_drop_settings = {} --settings table
@ -52,16 +45,23 @@ local function get_gravity()
return tonumber(minetest.settings:get("movement_gravity")) or 9.81
end
local registered_pickup_achievement = {}
mcl_item_entity.registered_pickup_achievement = {}
--TODO: remove limitation of 1 award per itemname
---Register an achievement that will be unlocked on pickup.
---
---TODO: remove limitation of 1 award per itemname
---@param itemname string
---@param award string
function mcl_item_entity.register_pickup_achievement(itemname, award)
if not has_awards then
minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing")
elseif registered_pickup_achievement[itemname] then
minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]")
minetest.log("warning",
"[mcl_item_entity] Trying to register pickup achievement [" .. award .. "] for [" ..
itemname .. "] while awards missing")
elseif mcl_item_entity.registered_pickup_achievement[itemname] then
minetest.log("error",
"[mcl_item_entity] Trying to register already existing pickup achievement [" .. award .. "] for [" .. itemname .. "]")
else
registered_pickup_achievement[itemname] = award
mcl_item_entity.registered_pickup_achievement[itemname] = award
end
end
@ -74,11 +74,13 @@ mcl_item_entity.register_pickup_achievement("mcl_nether:ancient_debris", "mcl:hi
mcl_item_entity.register_pickup_achievement("mcl_end:dragon_egg", "mcl:PickUpDragonEgg")
mcl_item_entity.register_pickup_achievement("mcl_armor:elytra", "mcl:skysTheLimit")
---@param object ObjectRef
---@param player ObjectRef
local function check_pickup_achievements(object, player)
if has_awards then
local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
local playername = player:get_player_name()
for name,award in pairs(registered_pickup_achievement) do
for name, award in pairs(mcl_item_entity.registered_pickup_achievement) do
if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
awards.unlock(playername, award)
end
@ -86,16 +88,23 @@ local function check_pickup_achievements(object, player)
end
end
---@param object ObjectRef
---@param luaentity Luaentity
---@param ignore_check? boolean
local function enable_physics(object, luaentity, ignore_check)
if luaentity.physical_state == false or ignore_check == true then
luaentity.physical_state = true
object:set_properties({
physical = true
})
object:set_acceleration({x=0,y=-get_gravity(),z=0})
object:set_acceleration(vector.new(0, -get_gravity(), 0))
end
end
---@param object ObjectRef
---@param luaentity Luaentity
---@param ignore_check? boolean
---@param reset_movement? boolean
local function disable_physics(object, luaentity, ignore_check, reset_movement)
if luaentity.physical_state == true or ignore_check == true then
luaentity.physical_state = false
@ -103,14 +112,13 @@ local function disable_physics(object, luaentity, ignore_check, reset_movement)
physical = false
})
if reset_movement ~= false then
object:set_velocity({x=0,y=0,z=0})
object:set_acceleration({x=0,y=0,z=0})
object:set_velocity(vector.zero())
object:set_acceleration(vector.zero())
end
end
end
minetest.register_globalstep(function(dtime)
minetest.register_globalstep(function(_)
tick = not tick
for _, player in pairs(minetest.get_connected_players()) do
@ -135,15 +143,18 @@ minetest.register_globalstep(function(dtime)
end
local inv = player:get_inventory()
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
local checkpos = vector.offset(pos, 0, item_drop_settings.player_collect_height, 0)
--magnet and collection
for _, object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and
object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer
and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
if object:get_luaentity()._magnet_timer >= 0 and
object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and
inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
-- Collection
if not object:get_luaentity()._removed then
@ -158,8 +169,8 @@ minetest.register_globalstep(function(dtime)
object:get_luaentity().target = checkpos
object:get_luaentity()._removed = true
object:set_velocity({x=0,y=0,z=0})
object:set_acceleration({x=0,y=0,z=0})
object:set_velocity(vector.zero())
object:set_acceleration(vector.zero())
object:move_to(checkpos)
@ -179,7 +190,6 @@ minetest.register_globalstep(function(dtime)
local entity = object:get_luaentity()
entity.collector = player:get_player_name()
entity.collected = true
end
end
@ -194,6 +204,11 @@ end)
local tmp_id = 0
---@param drop string|drop_definition
---@param toolname string
---@param param2 integer
---@param paramtype2 paramtype2
---@return string[]
local function get_drops(drop, toolname, param2, paramtype2)
tmp_id = tmp_id + 1
local tmp_node_name = "mcl_item_entity:" .. tmp_id
@ -265,7 +280,7 @@ function minetest.handle_node_drops(pos, drops, digger)
* table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop
]]
local enchantments = tool and mcl_enchanting.get_enchantments(tool, "silk_touch")
local enchantments = tool and mcl_enchanting.get_enchantments(tool)
local silk_touch_drop = false
local nodedef = minetest.registered_nodes[dug_node.name]
@ -294,7 +309,8 @@ function minetest.handle_node_drops(pos, drops, digger)
local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1)
local chance = fortune_drop.chance or fortune_drop.get_chance and fortune_drop.get_chance(fortune_level)
if not chance or math.random() < chance then
drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count, fortune_drop.cap)
drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count,
fortune_drop.cap)
elseif fortune_drop.override then
drops = {}
end
@ -348,7 +364,7 @@ end
function minetest.item_drop(itemstack, dropper, pos)
if dropper and dropper:is_player() then
local v = dropper:get_look_dir()
local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
local p = vector.offset(pos, 0, 1.2, 0)
local cs = itemstack:get_count()
if dropper:get_player_control().sneak then
cs = 1
@ -548,7 +564,7 @@ minetest.register_entity(":__builtin:item", {
local z = math.random(5, 10) / 10 * v
if math.random(0, 10) < 5 then z = -z end
local y = math.random(2, 4)
self.object:set_velocity({x=x, y=y, z=z})
self.object:set_velocity(vector.new(x, y, z))
end
self.random_velocity = 0
end,
@ -696,8 +712,8 @@ minetest.register_entity(":__builtin:item", {
self._forcetimer = 0
self.object:set_armor_groups({ immortal = 1 })
-- self.object:set_velocity({x = 0, y = 2, z = 0})
self.object:set_acceleration({x = 0, y = -get_gravity(), z = 0})
-- self.object:set_velocity(vector.new(0, 2, 0))
self.object:set_acceleration(vector.new(0, -get_gravity(), 0))
self:set_item(self.itemstring)
end,
@ -745,8 +761,8 @@ minetest.register_entity(":__builtin:item", {
self.object:set_properties({
physical = false
})
self.object:set_velocity({x=0,y=0,z=0})
self.object:set_acceleration({x=0,y=0,z=0})
self.object:set_velocity(vector.zero())
self.object:set_acceleration(vector.zero())
return
end
self.age = self.age + dtime
@ -761,21 +777,22 @@ minetest.register_entity(":__builtin:item", {
-- Delete corrupted item entities. The itemstring MUST be non-empty on its first step,
-- otherwise there might have some data corruption.
if self.itemstring == "" then
minetest.log("warning", "Item entity with empty itemstring found at "..minetest.pos_to_string(self.object:get_pos()).. "! Deleting it now.")
minetest.log("warning",
"Item entity with empty itemstring found at " .. minetest.pos_to_string(self.object:get_pos()) ..
"! Deleting it now.")
self._removed = true
self.object:remove()
return
end
local p = self.object:get_pos()
-- If hopper has taken item, it has gone, and no operations should be conducted on this item
if hopper_take_item(self, p) then
return
end
local node = minetest.get_node_or_nil(p)
local in_unloaded = (node == nil)
local node = minetest.get_node(p)
local in_unloaded = node.name == "ignore"
if in_unloaded then
-- Don't infinetly fall into unloaded map
@ -791,7 +808,7 @@ minetest.register_entity(":__builtin:item", {
local nn = node.name
local is_in_water = (minetest.get_item_group(nn, "liquid") ~= 0)
local nn_above = minetest.get_node({x=p.x, y=p.y+0.1, z=p.z}).name
local nn_above = minetest.get_node(vector.offset(p, 0, 0.1, 0)).name
-- make sure it's more or less stationary and is at water level
local sleep_threshold = 0.3
local is_floating = false
@ -804,8 +821,8 @@ minetest.register_entity(":__builtin:item", {
end
if is_floating and self.physical_state == true then
self.object:set_velocity({x = 0, y = 0, z = 0})
self.object:set_acceleration({x = 0, y = 0, z = 0})
self.object:set_velocity(vector.zero())
self.object:set_acceleration(vector.zero())
disable_physics(self.object, self)
end
-- If no collector was found for a long enough time, declare the magnet as disabled
@ -875,7 +892,7 @@ minetest.register_entity(":__builtin:item", {
end
-- If none of the 4 sides is free, shoot upwards
if shootdir == nil then
shootdir = { x=0, y=1, z=0 }
shootdir = vector.new(0, 1, 0)
local nn = minetest.get_node(vector.add(p, shootdir)).name
if nn == "ignore" then
-- Do not push into ignore
@ -885,7 +902,7 @@ minetest.register_entity(":__builtin:item", {
-- Set new item moving speed accordingly
local newv = vector.multiply(shootdir, 3)
self.object:set_acceleration({x = 0, y = 0, z = 0})
self.object:set_acceleration(vector.zero())
self.object:set_velocity(newv)
disable_physics(self.object, self, false, false)
@ -941,7 +958,7 @@ minetest.register_entity(":__builtin:item", {
-- Set new item moving speed into the direciton of the liquid
local newv = vector.multiply(vec, f)
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
self.object:set_acceleration({x = newv.x, y = -0.22, z = newv.z})
self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z))
self.physical_state = true
self._flowing = true
@ -956,7 +973,8 @@ minetest.register_entity(":__builtin:item", {
local vec = {
x = 0 - cur_vec.x * 0.9,
y = 3 - cur_vec.y * 0.9,
z = 0 -cur_vec.z*0.9}
z = 0 - cur_vec.z * 0.9
}
self.object:set_acceleration(vec)
-- slow down the item in water
local vel = self.object:get_velocity()
@ -980,7 +998,7 @@ minetest.register_entity(":__builtin:item", {
end
-- If node is not registered or node is walkably solid and resting on nodebox
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name
local def = minetest.registered_nodes[nn]
local v = self.object:get_velocity()
local is_on_floor = def and (def.walkable

View File

@ -0,0 +1,36 @@
# textdomain: mcl_minecarts
Minecart=Minevogn
Minecarts can be used for a quick transportion on rails.=Minevogne kan bruges til hurtig transport på spor.
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Minevogne kan kun køre på spor, og følger dem altid. Ved et T-kryds uden en vej ligeud drejer de altid til venstre. Farten påvirkes af sportypen.
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Du kan placere minevogne på spor. Højre-klik for at stige ombord.
To obtain the minecart, punch it while holding down the sneak key.=For at at få minevognen i din oppakning.
A minecart with TNT is an explosive vehicle that travels on rail.=En minevogn med TNT as et eksplosivt fartøj som kører på spor.
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placér den på spor. Slå den for at flytte den. TNTet bliver antændt med flint og stål eller når minevognen er på et aktiveringsspor.
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=For at få minevognen med TNT i din oppakning skal du slå den mens du holder snigeknappen nede. Du kan ikke gøre dette hvis TNTen er antændt.
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=En minevogn med ovn er et fartøj som kører på spor. Den kan køre af sig selv med brændstof.
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Placér den på spor. Hvis du putter kul i den vil ovnen brænde i lang tid, og minevognen vil køre af sig selv. Slå den for at sætte den i bevægelse.
To obtain the minecart and furnace, punch them while holding down the sneak key.=For at få minevognen med ovn i din oppakning skal du slå den mens du holder snigeknappen nede.
Minecart with Chest=Minevogn med kiste
Minecart with Furnace=Minevogn med ovn
Minecart with Command Block=Minevogn med kommandoblok
Minecart with Hopper=Minevogn med tragt
Minecart with TNT=Minevogn med TNT
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Placér dem på jorden for at bygge din jerbane. Sporene kobler sig automatisk sammen med hinanden og laver sving, T-kryds, kryds og skråninger efter behov.
Rail=Spor
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Spor kan bruges til at bygge jernbaner til minevogne. Normale spor sænker minevognene en smule på grund af friktionsmodstand.
Powered Rail=Strømspor
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Spor kan bruges til at bygge jernbaner til minevogne. Strømspor kan accelerere eller bremse minevogne.
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Uden redstonekraft vil sporet bremse minevognen. For at accelerere minevognen skal den bruge redstoneskraft.
Activator Rail=Aktiveringsspor
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Spor kan bruges til at bygge jernbaner til minevogne. Aktiveringsspor bruges til at aktivere specielle minevogne.
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=For at få dette spor til at aktiere minevogne skal du give det redstonekraft og sende en minevogn over dette sporstykke.
Detector Rail=Detektorspor
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Spor kan bruges til at bygge jernbaner til minevogne. Et detektorspor kan opdage en minevogn som kører over det og give kraft til redstonemekanismer.
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=For at opdage en minevogn og give redstonekraft skal den forbindes til redstonestøv eller redstonemekanismer og send en hvilkensomhelst minevogn hen over sporet.
Track for minecarts=Spor til minevogne.
Speed up when powered, slow down when not powered=Accelerérer når der er strøm, sænk hastigheden når der ikke er strøm.
Activates minecarts when powered=Aktieverer minevogne når der er strøm.
Emits redstone power when a minecart is detected=Udsender redstonekraft når en minevogn bliver opdaget.
Vehicle for fast travel on rails=Fartøj til hurtig kørsel på spor.
Can be ignited by tools or powered activator rail=Kan antændes med værktøj eller et aktivatorspor med strøm.
Sneak to dismount=Snig for at stige af.

View File

@ -2,8 +2,6 @@ local mob_class = mcl_mobs.mob_class
local mob_class_meta = {__index = mcl_mobs.mob_class}
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
-- API for Mobs Redo: MineClone 2 Edition (MRM)
local MAX_MOB_NAME_LENGTH = 30
local DEFAULT_FALL_SPEED = -9.81*1.5
local PATHFINDING = "gowp"
@ -17,21 +15,9 @@ local function mcl_log (message)
end
end
-- Invisibility mod check
mcl_mobs.invis = {}
-- localize math functions
local atann = math.atan
local function atan(x)
if not x or x ~= x then
return 0
else
return atann(x)
end
end
local remove_far = true
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
@ -297,51 +283,65 @@ function mob_class:mob_activate(staticdata, def, dtime)
end
end
-- execute current state (stand, walk, run, attacks)
-- returns true if mob has died
function mob_class:do_states(dtime)
--if self.can_open_doors then check_doors(self) end
if self.state == "stand" then
self:do_states_stand()
elseif self.state == PATHFINDING then
self:check_gowp(dtime)
elseif self.state == "walk" then
self:do_states_walk()
elseif self.state == "runaway" then
-- runaway when punched
self:do_states_runaway()
elseif self.state == "attack" then
-- attack routines (explode, dogfight, shoot, dogshoot)
if self:do_states_attack(dtime) then
return true
end
end
end
local function update_timers (self, dtime)
-- knockback timer. set in on_punch
if self.pause_timer > 0 then
self.pause_timer = self.pause_timer - dtime
return true
end
-- attack timer
self.timer = self.timer + dtime
if self.state ~= "attack" and self.state ~= PATHFINDING then
if self.timer < 1 then
return true
end
self.timer = 0
end
-- never go over 100
if self.timer > 100 then
self.timer = 1
end
end
-- main mob function
function mob_class:on_step(dtime)
self.lifetimer = self.lifetimer - dtime
local pos = self.object:get_pos()
if not pos then return end
if self:check_despawn(pos) then return true end
local d = 0.85
if self:check_dying() then d = 0.92 end
local v = self.object:get_velocity()
if v then
--diffuse object velocity
self.object:set_velocity({x = v.x*d, y = v.y, z = v.z*d})
end
if self:check_despawn(pos, dtime) then return true end
self:slow_mob()
if self:falling(pos) then return end
self:check_suspend()
self:check_water_flow()
local yaw = 0
if self:is_at_water_danger() and self.state ~= "attack" then
if math.random(1, 10) <= 6 then
self:set_velocity(0)
self.state = "stand"
self:set_animation( "stand")
yaw = yaw + math.random(-0.5, 0.5)
yaw = self:set_yaw( yaw, 8)
end
else
if self.move_in_group ~= false then
self:check_herd(dtime)
end
end
if self:is_at_cliff_or_danger() then
self:set_velocity(0)
self.state = "stand"
self:set_animation( "stand")
local yaw = self.object:get_yaw() or 0
yaw = self:set_yaw( yaw + 0.78, 8)
end
self:env_danger_movement_checks (dtime)
if not self.fire_resistant then
mcl_burning.tick(self.object, dtime, self)
@ -353,21 +353,17 @@ function mob_class:on_step(dtime)
if self.state == "die" then return end
if self.jump_sound_cooloff > 0 then
self.jump_sound_cooloff = self.jump_sound_cooloff - dtime
end
if self.opinion_sound_cooloff > 0 then
self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime
end
self:follow_flop() -- Mob following code.
--Mob following code.
self:follow_flop()
--set animation speed relitive to velocity
self:set_animation_speed()
self:set_animation_speed() -- set animation speed relitive to velocity
self:check_smooth_rotation(dtime)
self:check_head_swivel(dtime)
if self.jump_sound_cooloff > 0 then
self.jump_sound_cooloff = self.jump_sound_cooloff - dtime
end
self:do_jump()
self:set_armor_texture()
self:check_runaway_from()
@ -378,63 +374,26 @@ function mob_class:on_step(dtime)
-- run custom function (defined in mob lua file)
if self.do_custom then
-- when false skip going any further
if self.do_custom(self, dtime) == false then
return
end
end
-- knockback timer
if self.pause_timer > 0 then
if update_timers(self, dtime) then return end
self.pause_timer = self.pause_timer - dtime
return
end
-- attack timer
self.timer = self.timer + dtime
if self.state ~= "attack" and self.state ~= PATHFINDING then
if self.timer < 1 then
return
end
self.timer = 0
end
self:check_particlespawners(dtime)
self:check_item_pickup()
-- never go over 100
if self.timer > 100 then
self.timer = 1
if self.opinion_sound_cooloff > 0 then
self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime
end
-- mob plays random sound at times
-- mob plays random sound at times. Should be 120. Zombie and mob farms are ridiculous
if math.random(1, 70) == 1 then
self:mob_sound("random", true)
end
-- environmental damage timer (every 1 second)
self.env_damage_timer = self.env_damage_timer + dtime
if (self.state == "attack" and self.env_damage_timer > 1)
or self.state ~= "attack" then
self:check_entity_cramming()
self.env_damage_timer = 0
-- check for environmental damage (water, fire, lava etc.)
if self:do_env_damage() then
return
end
-- node replace check (cow eats grass etc.)
self:replace(pos)
end
if self:do_states(dtime) then
return
end
if self:env_damage (dtime, pos) then return end
if self:do_states(dtime) then return end
if not self.object:get_luaentity() then
return false

View File

@ -1,7 +1,6 @@
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
local mob_class = mcl_mobs.mob_class
local MAX_MOB_NAME_LENGTH = 30
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 300
local CHILD_GROW_TIME = 60*20

View File

@ -8,6 +8,18 @@ local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching
local stuck_path_timeout = 10 -- how long will mob follow path before giving up
local enable_pathfinding = true
local atann = math.atan
local function atan(x)
if not x or x ~= x then
return 0
else
return atann(x)
end
end
-- check if daytime and also if mob is docile during daylight hours
function mob_class:day_docile()
if self.docile_by_day == false then
@ -794,3 +806,397 @@ function mob_class:check_aggro(dtime)
end
self._check_aggro_timer = self._check_aggro_timer + dtime
end
function mob_class:do_states_attack (dtime)
local yaw = self.object:get_yaw() or 0
local s = self.object:get_pos()
local p = self.attack:get_pos() or s
-- stop attacking if player invisible or out of range
if not self.attack
or not self.attack:get_pos()
or not self:object_in_range(self.attack)
or self.attack:get_hp() <= 0
or (self.attack:is_player() and mcl_mobs.invis[ self.attack:get_player_name() ]) then
self.state = "stand"
self:set_velocity( 0)
self:set_animation( "stand")
self.attack = nil
self.v_start = false
self.timer = 0
self.blinktimer = 0
self.path.way = nil
return
end
-- calculate distance from mob and enemy
local dist = vector.distance(p, s)
if self.attack_type == "explode" then
local vec = {
x = p.x - s.x,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if p.x > s.x then yaw = yaw +math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
local node_break_radius = self.explosion_radius or 1
local entity_damage_radius = self.explosion_damage_radius
or (node_break_radius * 2)
-- start timer when in reach and line of sight
if not self.v_start
and dist <= self.reach
and self:line_of_sight( s, p, 2) then
self.v_start = true
self.timer = 0
self.blinktimer = 0
self:mob_sound("fuse", nil, false)
-- stop timer if out of reach or direct line of sight
elseif self.allow_fuse_reset
and self.v_start
and (dist >= self.explosiontimer_reset_radius
or not self:line_of_sight( s, p, 2)) then
self.v_start = false
self.timer = 0
self.blinktimer = 0
self.blinkstatus = false
self:remove_texture_mod("^[brighten")
end
-- walk right up to player unless the timer is active
if self.v_start and (self.stop_to_explode or dist < self.reach) then
self:set_velocity( 0)
else
self:set_velocity( self.run_velocity)
end
if self.animation and self.animation.run_start then
self:set_animation( "run")
else
self:set_animation( "walk")
end
if self.v_start then
self.timer = self.timer + dtime
self.blinktimer = (self.blinktimer or 0) + dtime
if self.blinktimer > 0.2 then
self.blinktimer = 0
if self.blinkstatus then
self:remove_texture_mod("^[brighten")
else
self:add_texture_mod("^[brighten")
end
self.blinkstatus = not self.blinkstatus
end
if self.timer > self.explosion_timer then
local pos = self.object:get_pos()
if mobs_griefing and not minetest.is_protected(pos, "") then
mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object)
else
minetest.sound_play(self.sounds.explode, {
pos = pos,
gain = 1.0,
max_hear_distance = self.sounds.distance or 32
}, true)
self:entity_physics(pos,entity_damage_radius)
mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0)
end
mcl_burning.extinguish(self.object)
self.object:remove()
return true
end
end
elseif self.attack_type == "dogfight"
or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 2) and (dist >= self.avoid_distance or not self.shooter_avoid_enemy)
or (self.attack_type == "dogshoot" and dist <= self.reach and self:dogswitch() == 0) then
if self.fly
and dist > self.reach then
local p1 = s
local me_y = math.floor(p1.y)
local p2 = p
local p_y = math.floor(p2.y + 1)
local v = self.object:get_velocity()
if self:flight_check( s) then
if me_y < p_y then
self.object:set_velocity({
x = v.x,
y = 1 * self.walk_velocity,
z = v.z
})
elseif me_y > p_y then
self.object:set_velocity({
x = v.x,
y = -1 * self.walk_velocity,
z = v.z
})
end
else
if me_y < p_y then
self.object:set_velocity({
x = v.x,
y = 0.01,
z = v.z
})
elseif me_y > p_y then
self.object:set_velocity({
x = v.x,
y = -0.01,
z = v.z
})
end
end
end
-- rnd: new movement direction
if self.path.following
and self.path.way
and self.attack_type ~= "dogshoot" then
-- no paths longer than 50
if #self.path.way > 50
or dist < self.reach then
self.path.following = false
return
end
local p1 = self.path.way[1]
if not p1 then
self.path.following = false
return
end
if math.abs(p1.x-s.x) + math.abs(p1.z - s.z) < 0.6 then
-- reached waypoint, remove it from queue
table.remove(self.path.way, 1)
end
-- set new temporary target
p = {x = p1.x, y = p1.y, z = p1.z}
end
local vec = {
x = p.x - s.x,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) + math.pi / 2) - self.rotate
if p.x > s.x then yaw = yaw + math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
-- move towards enemy if beyond mob reach
if dist > self.reach then
-- path finding by rnd
if self.pathfinding -- only if mob has pathfinding enabled
and enable_pathfinding then
self:smart_mobs(s, p, dist, dtime)
end
if self:is_at_cliff_or_danger() then
self:set_velocity( 0)
self:set_animation( "stand")
local yaw = self.object:get_yaw() or 0
yaw = self:set_yaw( yaw + 0.78, 8)
else
if self.path.stuck then
self:set_velocity( self.walk_velocity)
else
self:set_velocity( self.run_velocity)
end
if self.animation and self.animation.run_start then
self:set_animation( "run")
else
self:set_animation( "walk")
end
end
else -- rnd: if inside reach range
self.path.stuck = false
self.path.stuck_timer = 0
self.path.following = false -- not stuck anymore
self:set_velocity( 0)
if not self.custom_attack then
if self.timer > 1 then
self.timer = 0
if self.double_melee_attack
and math.random(1, 2) == 1 then
self:set_animation( "punch2")
else
self:set_animation( "punch")
end
local p2 = p
local s2 = s
p2.y = p2.y + .5
s2.y = s2.y + .5
if self:line_of_sight( p2, s2) == true then
-- play attack sound
self:mob_sound("attack")
-- punch player (or what player is attached to)
local attached = self.attack:get_attach()
if attached then
self.attack = attached
end
self.attack:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self.damage}
}, nil)
end
end
else -- call custom attack every second
if self.custom_attack
and self.timer > 1 then
self.timer = 0
self.custom_attack(self, p)
end
end
end
elseif self.attack_type == "shoot"
or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 1)
or (self.attack_type == "dogshoot" and (dist > self.reach or dist < self.avoid_distance and self.shooter_avoid_enemy) and self:dogswitch() == 0) then
p.y = p.y - .5
s.y = s.y + .5
local dist = vector.distance(p, s)
local vec = {
x = p.x - s.x,
y = p.y - s.y,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if p.x > s.x then yaw = yaw +math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
local stay_away_from_player = vector.new(0,0,0)
--strafe back and fourth
--stay away from player so as to shoot them
if dist < self.avoid_distance and self.shooter_avoid_enemy then
self:set_animation( "shoot")
stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33)
end
if self.strafes then
if not self.strafe_direction then
self.strafe_direction = 1.57
end
if math.random(40) == 1 then
self.strafe_direction = self.strafe_direction*-1
end
self.acc = vector.add(vector.multiply(vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction), 0.3*self.walk_velocity), stay_away_from_player)
else
self:set_velocity( 0)
end
local p = self.object:get_pos()
p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2
if self.shoot_interval
and self.timer > self.shoot_interval
and not minetest.raycast(vector.add(p, vector.new(0,self.shoot_offset,0)), vector.add(self.attack:get_pos(), vector.new(0,1.5,0)), false, false):next()
and math.random(1, 100) <= 60 then
self.timer = 0
self:set_animation( "shoot")
-- play shoot attack sound
self:mob_sound("shoot_attack")
-- Shoot arrow
if minetest.registered_entities[self.arrow] then
local arrow, ent
local v = 1
if not self.shoot_arrow then
self.firing = true
minetest.after(1, function()
self.firing = false
end)
arrow = minetest.add_entity(p, self.arrow)
ent = arrow:get_luaentity()
if ent.velocity then
v = ent.velocity
end
ent.switch = 1
ent.owner_id = tostring(self.object) -- add unique owner id to arrow
-- important for mcl_shields
ent._shooter = self.object
ent._saved_shooter_pos = self.object:get_pos()
end
local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5
-- offset makes shoot aim accurate
vec.y = vec.y + self.shoot_offset
vec.x = vec.x * (v / amount)
vec.y = vec.y * (v / amount)
vec.z = vec.z * (v / amount)
if self.shoot_arrow then
vec = vector.normalize(vec)
self:shoot_arrow(p, vec)
else
arrow:set_velocity(vec)
end
end
end
else
end
end

View File

@ -116,6 +116,7 @@ function mob_class:mob_sound(soundname, is_opinion, fixed_pitch)
-- randomize the pitch a bit
pitch = pitch + math.random(-10, 10) * 0.005
end
-- Should be 0.1 to 0.2 for mobs. Cow and zombie farms loud. At least have cool down.
minetest.sound_play(sound, {
object = self.object,
gain = 1.0,
@ -279,30 +280,55 @@ local function dir_to_pitch(dir)
return -math.atan2(-dir.y, xz)
end
function mob_class:check_head_swivel(dtime)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
local final_rotation = vector.new(0,0,0)
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
local function who_are_you_looking_at (self)
local pos = self.object:get_pos()
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 10)) do
if obj:is_player() and not self.attack or obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity() then
if not self._locked_object then
if math.random(5000/self.curiosity) == 1 or vector.distance(pos,obj:get_pos())<4 and obj:is_player() then
self._locked_object = obj
end
else
if math.random(10000/self.curiosity) == 1 then
self._locked_object = nil
end
end
end
end
local stop_look_at_player_chance = math.random(833/self.curiosity)
-- was 10000 - div by 12 for avg entities as outside loop
local stop_look_at_player = stop_look_at_player_chance == 1
if self.attack or self.following then
self._locked_object = self.attack or self.following
elseif self._locked_object then
if stop_look_at_player then
--minetest.log("Stop look: ".. self.name)
self._locked_object = nil
end
elseif not self._locked_object then
if math.random(1, 30) then
--minetest.log("Change look check: ".. self.name)
local look_at_player_chance = math.random(20/self.curiosity)
-- 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
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
break
elseif obj:is_player() or (obj:get_luaentity() and obj:get_luaentity().name == self.name and self ~= obj:get_luaentity()) then
if look_at_player then
--minetest.log("Change look to mob: ".. self.name)
self._locked_object = obj
break
end
end
end
end
end
end
function mob_class:check_head_swivel(dtime)
if not self.head_swivel or type(self.head_swivel) ~= "string" then return end
who_are_you_looking_at (self)
local final_rotation = vector.new(0,0,0)
local oldp,oldr = self.object:get_bone_position(self.head_swivel)
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
@ -317,6 +343,7 @@ function mob_class:check_head_swivel(dtime)
if self.object:get_attach() then
self_rot = self.object:get_attach():get_rotation()
end
if self.rot then
local player_pos = self._locked_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)))
@ -345,7 +372,7 @@ function mob_class:check_head_swivel(dtime)
elseif not self._locked_object and math.abs(oldr.y) > 3 and math.abs(oldr.x) < 3 then
final_rotation = vector.multiply(oldr, 0.9)
else
final_rotation = vector.new(0,0,0)
--final_rotation = vector.new(0,0,0)
end
mcl_util.set_bone_position(self.object,self.head_swivel, vector.new(0,self.bone_eye_height,self.horrizonatal_head_height), final_rotation)

View File

@ -0,0 +1,11 @@
# textdomain: mcl_mobs
Peaceful mode active! No monsters will spawn.=Fredelig tilstand aktiveret! Ingen monstre vil spawne.
This allows you to place a single mob.=Dette gør dig i stand til at placere et enkelt monster.
Just place it where you want the mob to appear. Animals will spawn tamed, unless you hold down the sneak key while placing. If you place this on a mob spawner, you change the mob it spawns.=Placér det blot der hvor du ønsker, at monsteret skal komme. Dyr vil spawne tamme, medmindre du holder snige-knappen nede mens du placerer dem. Hvis du placerer denne på et monsterspawn, ændrer du hvilket monster det spawner.
You need the “maphack” privilege to change the mob spawner.=Du skal have "maphack" privilegier for at ændre monsterspawneren.
Name Tag=Navneskilt
A name tag is an item to name a mob.=Et navneskilt bruges til at navngive et monster.
Before you use the name tag, you need to set a name at an anvil. Then you can use the name tag to name a mob. This uses up the name tag.=Før du bruger navneskiltet, skal du vælge navnet ved en ambolt. Derefter kan du bruge navneskiltet til at navngive et monster. Dette opbruger navneskiltet.
Only peaceful mobs allowed!=Kun fredelige monstre er tilladt!
Give names to mobs=Giv navne til monstre
Set name at anvil=Vælg navn ved en ambolt.

View File

@ -4,7 +4,6 @@ local DEFAULT_FALL_SPEED = -9.81*1.5
local FLOP_HEIGHT = 6
local FLOP_HOR_SPEED = 1.5
local PATHFINDING = "gowp"
local enable_pathfinding = true
local node_ice = "mcl_core:ice"
local node_snowblock = "mcl_core:snowblock"
@ -269,6 +268,31 @@ function mob_class:is_at_water_danger()
return false
end
function mob_class:env_danger_movement_checks(dtime)
local yaw = 0
if self:is_at_water_danger() and self.state ~= "attack" then
if math.random(1, 10) <= 6 then
self:set_velocity(0)
self.state = "stand"
self:set_animation( "stand")
yaw = yaw + math.random(-0.5, 0.5)
yaw = self:set_yaw( yaw, 8)
end
else
if self.move_in_group ~= false then
self:check_herd(dtime)
end
end
if self:is_at_cliff_or_danger() then
self:set_velocity(0)
self.state = "stand"
self:set_animation( "stand")
local yaw = self.object:get_yaw() or 0
yaw = self:set_yaw( yaw + 0.78, 8)
end
end
-- jump if facing a solid node (not fences or gates)
function mob_class:do_jump()
if not self.jump
@ -769,70 +793,9 @@ function mob_class:teleport(target)
end
end
-- execute current state (stand, walk, run, attacks)
-- returns true if mob has died
function mob_class:do_states(dtime)
--if self.can_open_doors then check_doors(self) end
function mob_class:do_states_walk()
local yaw = self.object:get_yaw() or 0
if self.state == "stand" then
if math.random(1, 4) == 1 then
local s = self.object:get_pos()
local objs = minetest.get_objects_inside_radius(s, 3)
local lp
for n = 1, #objs do
if objs[n]:is_player() then
lp = objs[n]:get_pos()
break
end
end
-- look at any players nearby, otherwise turn randomly
if lp and self.look_at_players then
local vec = {
x = lp.x - s.x,
z = lp.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if lp.x > s.x then yaw = yaw +math.pi end
else
yaw = yaw + math.random(-0.5, 0.5)
end
yaw = self:set_yaw( yaw, 8)
end
if self.order == "sit" then
self:set_animation( "sit")
self:set_velocity(0)
else
self:set_animation( "stand")
self:set_velocity(0)
end
-- npc's ordered to stand stay standing
if self.order == "stand" or self.order == "sleep" or self.order == "work" then
else
if self.walk_chance ~= 0
and self.facing_fence ~= true
and math.random(1, 100) <= self.walk_chance
and self:is_at_cliff_or_danger() == false then
self:set_velocity(self.walk_velocity)
self.state = "walk"
self:set_animation( "walk")
end
end
elseif self.state == PATHFINDING then
self:check_gowp(dtime)
elseif self.state == "walk" then
local s = self.object:get_pos()
local lp = nil
@ -840,21 +803,13 @@ function mob_class:do_states(dtime)
if (self.water_damage > 0
and self.lava_damage > 0)
or self.breath_max ~= -1 then
lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"})
elseif self.water_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:water"})
elseif self.lava_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:lava"})
elseif self.fire_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:fire"})
end
local is_in_danger = false
@ -939,9 +894,66 @@ function mob_class:do_states(dtime)
self:set_animation( "walk")
end
end
end
-- runaway when punched
elseif self.state == "runaway" then
function mob_class:do_states_stand()
local yaw = self.object:get_yaw() or 0
if math.random(1, 4) == 1 then
local s = self.object:get_pos()
local objs = minetest.get_objects_inside_radius(s, 3)
local lp
for n = 1, #objs do
if objs[n]:is_player() then
lp = objs[n]:get_pos()
break
end
end
-- look at any players nearby, otherwise turn randomly
if lp and self.look_at_players then
local vec = {
x = lp.x - s.x,
z = lp.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if lp.x > s.x then yaw = yaw +math.pi end
else
yaw = yaw + math.random(-0.5, 0.5)
end
yaw = self:set_yaw( yaw, 8)
end
if self.order == "sit" then
self:set_animation( "sit")
self:set_velocity(0)
else
self:set_animation( "stand")
self:set_velocity(0)
end
-- npc's ordered to stand stay standing
if self.order == "stand" or self.order == "sleep" or self.order == "work" then
else
if self.walk_chance ~= 0
and self.facing_fence ~= true
and math.random(1, 100) <= self.walk_chance
and self:is_at_cliff_or_danger() == false then
self:set_velocity(self.walk_velocity)
self.state = "walk"
self:set_animation( "walk")
end
end
end
function mob_class:do_states_runaway()
local yaw = self.object:get_yaw() or 0
self.runaway_timer = self.runaway_timer + 1
@ -958,401 +970,12 @@ function mob_class:do_states(dtime)
self:set_velocity( self.run_velocity)
self:set_animation( "run")
end
-- attack routines (explode, dogfight, shoot, dogshoot)
elseif self.state == "attack" then
local s = self.object:get_pos()
local p = self.attack:get_pos() or s
-- stop attacking if player invisible or out of range
if not self.attack
or not self.attack:get_pos()
or not self:object_in_range(self.attack)
or self.attack:get_hp() <= 0
or (self.attack:is_player() and mcl_mobs.invis[ self.attack:get_player_name() ]) then
self.state = "stand"
self:set_velocity( 0)
self:set_animation( "stand")
self.attack = nil
self.v_start = false
self.timer = 0
self.blinktimer = 0
self.path.way = nil
return
end
-- calculate distance from mob and enemy
local dist = vector.distance(p, s)
if self.attack_type == "explode" then
local vec = {
x = p.x - s.x,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if p.x > s.x then yaw = yaw +math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
local node_break_radius = self.explosion_radius or 1
local entity_damage_radius = self.explosion_damage_radius
or (node_break_radius * 2)
-- start timer when in reach and line of sight
if not self.v_start
and dist <= self.reach
and self:line_of_sight( s, p, 2) then
self.v_start = true
self.timer = 0
self.blinktimer = 0
self:mob_sound("fuse", nil, false)
-- stop timer if out of reach or direct line of sight
elseif self.allow_fuse_reset
and self.v_start
and (dist >= self.explosiontimer_reset_radius
or not self:line_of_sight( s, p, 2)) then
self.v_start = false
self.timer = 0
self.blinktimer = 0
self.blinkstatus = false
self:remove_texture_mod("^[brighten")
end
-- walk right up to player unless the timer is active
if self.v_start and (self.stop_to_explode or dist < self.reach) then
self:set_velocity( 0)
else
self:set_velocity( self.run_velocity)
end
if self.animation and self.animation.run_start then
self:set_animation( "run")
else
self:set_animation( "walk")
end
if self.v_start then
self.timer = self.timer + dtime
self.blinktimer = (self.blinktimer or 0) + dtime
if self.blinktimer > 0.2 then
self.blinktimer = 0
if self.blinkstatus then
self:remove_texture_mod("^[brighten")
else
self:add_texture_mod("^[brighten")
end
self.blinkstatus = not self.blinkstatus
end
if self.timer > self.explosion_timer then
local pos = self.object:get_pos()
if mobs_griefing and not minetest.is_protected(pos, "") then
mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object)
else
minetest.sound_play(self.sounds.explode, {
pos = pos,
gain = 1.0,
max_hear_distance = self.sounds.distance or 32
}, true)
self:entity_physics(pos,entity_damage_radius)
mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0)
end
mcl_burning.extinguish(self.object)
self.object:remove()
return true
end
end
elseif self.attack_type == "dogfight"
or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 2) and (dist >= self.avoid_distance or not self.shooter_avoid_enemy)
or (self.attack_type == "dogshoot" and dist <= self.reach and self:dogswitch() == 0) then
if self.fly
and dist > self.reach then
local p1 = s
local me_y = math.floor(p1.y)
local p2 = p
local p_y = math.floor(p2.y + 1)
local v = self.object:get_velocity()
if self:flight_check( s) then
if me_y < p_y then
self.object:set_velocity({
x = v.x,
y = 1 * self.walk_velocity,
z = v.z
})
elseif me_y > p_y then
self.object:set_velocity({
x = v.x,
y = -1 * self.walk_velocity,
z = v.z
})
end
else
if me_y < p_y then
self.object:set_velocity({
x = v.x,
y = 0.01,
z = v.z
})
elseif me_y > p_y then
self.object:set_velocity({
x = v.x,
y = -0.01,
z = v.z
})
end
end
end
-- rnd: new movement direction
if self.path.following
and self.path.way
and self.attack_type ~= "dogshoot" then
-- no paths longer than 50
if #self.path.way > 50
or dist < self.reach then
self.path.following = false
return
end
local p1 = self.path.way[1]
if not p1 then
self.path.following = false
return
end
if math.abs(p1.x-s.x) + math.abs(p1.z - s.z) < 0.6 then
-- reached waypoint, remove it from queue
table.remove(self.path.way, 1)
end
-- set new temporary target
p = {x = p1.x, y = p1.y, z = p1.z}
end
local vec = {
x = p.x - s.x,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) + math.pi / 2) - self.rotate
if p.x > s.x then yaw = yaw + math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
-- move towards enemy if beyond mob reach
if dist > self.reach then
-- path finding by rnd
if self.pathfinding -- only if mob has pathfinding enabled
and enable_pathfinding then
self:smart_mobs(s, p, dist, dtime)
end
if self:is_at_cliff_or_danger() then
self:set_velocity( 0)
self:set_animation( "stand")
local yaw = self.object:get_yaw() or 0
yaw = self:set_yaw( yaw + 0.78, 8)
else
if self.path.stuck then
self:set_velocity( self.walk_velocity)
else
self:set_velocity( self.run_velocity)
end
if self.animation and self.animation.run_start then
self:set_animation( "run")
else
self:set_animation( "walk")
end
end
else -- rnd: if inside reach range
self.path.stuck = false
self.path.stuck_timer = 0
self.path.following = false -- not stuck anymore
self:set_velocity( 0)
if not self.custom_attack then
if self.timer > 1 then
self.timer = 0
if self.double_melee_attack
and math.random(1, 2) == 1 then
self:set_animation( "punch2")
else
self:set_animation( "punch")
end
local p2 = p
local s2 = s
p2.y = p2.y + .5
s2.y = s2.y + .5
if self:line_of_sight( p2, s2) == true then
-- play attack sound
self:mob_sound("attack")
-- punch player (or what player is attached to)
local attached = self.attack:get_attach()
if attached then
self.attack = attached
end
self.attack:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = self.damage}
}, nil)
end
end
else -- call custom attack every second
if self.custom_attack
and self.timer > 1 then
self.timer = 0
self.custom_attack(self, p)
end
end
end
elseif self.attack_type == "shoot"
or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 1)
or (self.attack_type == "dogshoot" and (dist > self.reach or dist < self.avoid_distance and self.shooter_avoid_enemy) and self:dogswitch() == 0) then
p.y = p.y - .5
s.y = s.y + .5
local dist = vector.distance(p, s)
local vec = {
x = p.x - s.x,
y = p.y - s.y,
z = p.z - s.z
}
yaw = (atan(vec.z / vec.x) +math.pi/ 2) - self.rotate
if p.x > s.x then yaw = yaw +math.pi end
yaw = self:set_yaw( yaw, 0, dtime)
local stay_away_from_player = vector.new(0,0,0)
--strafe back and fourth
--stay away from player so as to shoot them
if dist < self.avoid_distance and self.shooter_avoid_enemy then
self:set_animation( "shoot")
stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33)
end
if self.strafes then
if not self.strafe_direction then
self.strafe_direction = 1.57
end
if math.random(40) == 1 then
self.strafe_direction = self.strafe_direction*-1
end
self.acc = vector.add(vector.multiply(vector.rotate_around_axis(vector.direction(s, p), vector.new(0,1,0), self.strafe_direction), 0.3*self.walk_velocity), stay_away_from_player)
else
self:set_velocity( 0)
end
local p = self.object:get_pos()
p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2
if self.shoot_interval
and self.timer > self.shoot_interval
and not minetest.raycast(vector.add(p, vector.new(0,self.shoot_offset,0)), vector.add(self.attack:get_pos(), vector.new(0,1.5,0)), false, false):next()
and math.random(1, 100) <= 60 then
self.timer = 0
self:set_animation( "shoot")
-- play shoot attack sound
self:mob_sound("shoot_attack")
-- Shoot arrow
if minetest.registered_entities[self.arrow] then
local arrow, ent
local v = 1
if not self.shoot_arrow then
self.firing = true
minetest.after(1, function()
self.firing = false
end)
arrow = minetest.add_entity(p, self.arrow)
ent = arrow:get_luaentity()
if ent.velocity then
v = ent.velocity
end
ent.switch = 1
ent.owner_id = tostring(self.object) -- add unique owner id to arrow
-- important for mcl_shields
ent._shooter = self.object
ent._saved_shooter_pos = self.object:get_pos()
end
local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5
-- offset makes shoot aim accurate
vec.y = vec.y + self.shoot_offset
vec.x = vec.x * (v / amount)
vec.y = vec.y * (v / amount)
vec.z = vec.z * (v / amount)
if self.shoot_arrow then
vec = vector.normalize(vec)
self:shoot_arrow(p, vec)
else
arrow:set_velocity(vec)
end
end
end
else
end
end
end
function mob_class:check_smooth_rotation(dtime)
-- smooth rotation by ThomasMonroe314

View File

@ -1,11 +1,24 @@
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
local mob_class = mcl_mobs.mob_class
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false)
local PATHFINDING = "gowp"
local enable_pathfinding = true
local PATHFINDING_FAIL_THRESHOLD = 100 -- no. of ticks to fail before giving up. 20p/s. 5s helps them get through door
local PATHFINDING_FAIL_WAIT = 30 -- how long to wait before trying to path again
local LOG_MODULE = "[Mobs]"
local PATHFINDING = "gowp"
local one_down = vector.new(0,-1,0)
local one_up = vector.new(0,1,0)
local plane_adjacents = {
vector.new(1,0,0),
vector.new(-1,0,0),
vector.new(0,0,1),
vector.new(0,0,-1),
}
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_pathfinding",false)
local LOG_MODULE = "[Mobs Pathfinding]"
local function mcl_log (message)
if LOGGING_ON and message then
minetest.log(LOG_MODULE .. " " .. message)
@ -21,7 +34,7 @@ function output_table (wp)
end
function append_paths (wp1, wp2)
mcl_log("Start append")
--mcl_log("Start append")
if not wp1 or not wp2 then
mcl_log("Cannot append wp's")
return
@ -31,7 +44,7 @@ function append_paths (wp1, wp2)
for _,a in pairs (wp2) do
table.insert(wp1, a)
end
mcl_log("End append")
--mcl_log("End append")
end
local function output_enriched (wp_out)
@ -43,11 +56,12 @@ local function output_enriched (wp_out)
local action = outy["action"]
if action then
--mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"]))
mcl_log("type: " .. action["type"])
mcl_log("action: " .. action["action"])
mcl_log("target: " .. minetest.pos_to_string(action["target"]))
end
mcl_log("failed attempts: " .. outy["failed_attempts"])
--mcl_log("failed attempts: " .. outy["failed_attempts"])
end
end
@ -56,34 +70,26 @@ end
-- an action, such as to open or close a door where we know that pos requires that action
local function generate_enriched_path(wp_in, door_open_pos, door_close_pos, cur_door_pos)
local wp_out = {}
-- TODO Just pass in door position and the index before is open, the index after is close
local current_door_index = -1
for i, cur_pos in pairs(wp_in) do
local action = nil
local one_down = vector.new(0,-1,0)
local cur_pos_to_add = vector.add(cur_pos, one_down)
if door_open_pos and vector.equals (cur_pos, door_open_pos) then
mcl_log ("Door open match")
--action = {type = "door", action = "open"}
action = {}
action["type"] = "door"
action["action"] = "open"
action["target"] = cur_door_pos
action = {type = "door", action = "open", target = cur_door_pos}
cur_pos_to_add = vector.add(cur_pos, one_down)
elseif door_close_pos and vector.equals(cur_pos, door_close_pos) then
mcl_log ("Door close match")
--action = {type = "door", action = "closed"}
action = {}
action["type"] = "door"
action["action"] = "close"
action["target"] = cur_door_pos
action = {type = "door", action = "close", target = cur_door_pos}
cur_pos_to_add = vector.add(cur_pos, one_down)
elseif cur_door_pos and vector.equals(cur_pos, cur_door_pos) then
mcl_log("Current door pos")
action = {type = "door", action = "open", target = cur_door_pos}
cur_pos_to_add = vector.add(cur_pos, one_down)
action = {}
action["type"] = "door"
action["action"] = "open"
action["target"] = cur_door_pos
else
cur_pos_to_add = cur_pos
--mcl_log ("Pos doesn't match")
@ -101,106 +107,156 @@ local function generate_enriched_path(wp_in, door_open_pos, door_close_pos, cur_
return wp_out
end
local plane_adjacents = {
vector.new(1,0,0),
vector.new(-1,0,0),
vector.new(0,0,1),
vector.new(0,0,-1),
}
function mob_class:ready_to_path()
mcl_log("Check ready to path")
if self._pf_last_failed and (os.time() - self._pf_last_failed) < PATHFINDING_FAIL_WAIT then
mcl_log("Not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
return false
else
mcl_log("We are ready to pathfind, no previous fail or we are past threshold")
return true
end
end
-- This function is used to see if we can path. We could use to check a route, rather than making people move.
local function calculate_path_through_door (p, t, target)
-- target is the same as t, just 1 square difference. Maybe we don't need target
mcl_log("Plot route from mob: " .. minetest.pos_to_string(p) .. ", to target: " .. minetest.pos_to_string(t))
local function calculate_path_through_door (p, cur_door_pos, t)
if t then
mcl_log("Plot route through door from pos: " .. minetest.pos_to_string(p) .. ", to target: " .. minetest.pos_to_string(t))
else
mcl_log("Plot route through door from pos: " .. minetest.pos_to_string(p))
end
local enriched_path = nil
local wp, prospective_wp
local cur_door_pos = nil
local pos_closest_to_door = nil
local other_side_of_door = nil
--Path to door first
local wp = minetest.find_path(p,t,150,1,4)
if not wp then
mcl_log("No direct path. Path through door")
-- This could improve. There could be multiple doors. Check you can path from door to target first.
local cur_door_pos = minetest.find_node_near(target,16,{"group:door"})
if cur_door_pos then
mcl_log("Found a door near: " .. minetest.pos_to_string(cur_door_pos))
for _,v in pairs(plane_adjacents) do
pos_closest_to_door = vector.add(cur_door_pos,v)
other_side_of_door = vector.add(cur_door_pos,-v)
local n = minetest.get_node(pos_closest_to_door)
if n.name == "air" then
wp = minetest.find_path(p,pos_closest_to_door,150,1,4)
if wp then
mcl_log("We have air space next to door at: " .. minetest.pos_to_string(pos_closest_to_door))
prospective_wp = minetest.find_path(p,pos_closest_to_door,150,1,4)
if prospective_wp then
mcl_log("Found a path to next to door".. minetest.pos_to_string(pos_closest_to_door))
other_side_of_door = vector.add(cur_door_pos,-v)
mcl_log("Opposite is: ".. minetest.pos_to_string(other_side_of_door))
table.insert(prospective_wp, cur_door_pos)
if t then
mcl_log("We have t, lets go from door to target")
local wp_otherside_door_to_target = minetest.find_path(other_side_of_door,t,150,1,4)
if wp_otherside_door_to_target and #wp_otherside_door_to_target > 0 then
table.insert(wp, cur_door_pos)
append_paths (wp, wp_otherside_door_to_target)
enriched_path = generate_enriched_path(wp, pos_closest_to_door, other_side_of_door, cur_door_pos)
append_paths (prospective_wp, wp_otherside_door_to_target)
wp = prospective_wp
mcl_log("We have a path from outside door to target")
else
mcl_log("We cannot path from outside door to target")
end
break
else
mcl_log("This block next to door doesn't work.")
end
else
mcl_log("Block is not air, it is: ".. n.name)
mcl_log("No t, just add other side of door")
table.insert(prospective_wp, other_side_of_door)
wp = prospective_wp
end
if wp then
enriched_path = generate_enriched_path(wp, pos_closest_to_door, other_side_of_door, cur_door_pos)
break
end
else
mcl_log("Cannot path to this air block next to door.")
end
end
end
else
mcl_log("No door found")
end
else
mcl_log("We have a direct route")
end
if wp and not enriched_path then
mcl_log("Wp but not enriched")
enriched_path = generate_enriched_path(wp)
end
return enriched_path
end
local gopath_last = os.time()
function mob_class:gopath(target,callback_arrived)
if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end
if self._pf_last_failed and (os.time() - self._pf_last_failed) < 30 then
mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
return
else
mcl_log("We are ready to pathfind, no previous fail or we are past threshold")
end
--if os.time() - gopath_last < 5 then
-- mcl_log("Not ready to path yet")
-- return
--end
--gopath_last = os.time()
if not self:ready_to_path() then return end
self.order = nil
local p = self.object:get_pos()
local t = vector.offset(target,0,1,0)
local wp = calculate_path_through_door(p, t, target)
--Check direct route
local wp = minetest.find_path(p,t,150,1,4)
if not wp then
mcl_log("### No direct path. Path through door closest to target.")
local door_near_target = minetest.find_node_near(target, 16, {"group:door"})
wp = calculate_path_through_door(p, door_near_target, t)
if not wp then
mcl_log("### No path though door closest to target. Try door closest to origin.")
local door_closest = minetest.find_node_near(p, 16, {"group:door"})
wp = calculate_path_through_door(p, door_closest, t)
-- Path through 2 doors
if not wp then
mcl_log("### Still not wp. Need to path through 2 doors.")
local path_through_closest_door = calculate_path_through_door(p, door_closest)
if path_through_closest_door and #path_through_closest_door > 0 then
mcl_log("We have path through first door")
mcl_log("Number of pos in path through door: " .. tostring(#path_through_closest_door))
local pos_after_door_entry = path_through_closest_door[#path_through_closest_door]
if pos_after_door_entry then
local pos_after_door = vector.add(pos_after_door_entry["pos"], one_up)
mcl_log("pos_after_door: " .. minetest.pos_to_string(pos_after_door))
local path_after_door = calculate_path_through_door(pos_after_door, door_near_target, t)
if path_after_door and #path_after_door > 1 then
mcl_log("We have path after first door")
table.remove(path_after_door, 1) -- Remove duplicate
wp = path_through_closest_door
append_paths (wp, path_after_door)
else
mcl_log("Path after door is not good")
end
else
mcl_log("No pos after door")
end
else
mcl_log("Path through closest door empty or null")
end
else
mcl_log("ok, we have a path through 1 door")
end
end
else
wp = generate_enriched_path(wp)
mcl_log("We have a direct route")
end
if not wp then
mcl_log("Could not calculate path")
self._pf_last_failed = os.time()
-- Cover for a flaw in pathfind where it chooses the wrong door and gets stuck. Take a break, allow others.
-- If cannot path, don't immediately try again
end
--output_table(wp)
if wp and #wp > 0 then
--output_table(wp)
self._target = t
self.callback_arrived = callback_arrived
local current_location = table.remove(wp,1)
@ -269,17 +325,7 @@ function mob_class:do_pathfind_action(action)
end
end
local gowp_etime = 0
function mob_class:check_gowp(dtime)
gowp_etime = gowp_etime + dtime
-- 0.1 is optimal.
--less frequently = villager will get sent back after passing a point.
--more frequently = villager will fail points they shouldn't they just didn't get there yet
--if gowp_etime < 0.05 then return end
--gowp_etime = 0
local p = self.object:get_pos()
-- no destination
@ -292,7 +338,7 @@ function mob_class:check_gowp(dtime)
-- arrived at location, finish gowp
local distance_to_targ = vector.distance(p,self._target)
--mcl_log("Distance to targ: ".. tostring(distance_to_targ))
if distance_to_targ < 2 then
if distance_to_targ < 1.8 then
mcl_log("Arrived at _target")
self.waypoints = nil
self._target = nil
@ -303,6 +349,8 @@ function mob_class:check_gowp(dtime)
self.object:set_acceleration({x = 0, y = 0, z = 0})
if self.callback_arrived then return self.callback_arrived(self) end
return true
elseif not self.current_target then
mcl_log("Not close enough to targ: ".. tostring(distance_to_targ))
end
-- More pathing to be done
@ -315,7 +363,7 @@ function mob_class:check_gowp(dtime)
-- 0.8 is optimal for 0.025 frequency checks and also 1... Actually. 0.8 is winning
-- 0.9 and 1.0 is also good. Stick with unless door open or closing issues
if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < 0.9 ) then
-- We have waypoints, and no current target, or we're at it. We need a new current_target.
-- We have waypoints, and are at current_target or have no current target. We need a new current_target.
self:do_pathfind_action (self.current_target["action"])
local failed_attempts = self.current_target["failed_attempts"]
@ -325,10 +373,11 @@ function mob_class:check_gowp(dtime)
self:go_to_pos(self.current_target["pos"])
return
elseif self.current_target and self.current_target["pos"] then
-- No waypoints left, but have current target. Potentially last waypoint to go to.
-- No waypoints left, but have current target and not close enough. Potentially last waypoint to go to.
self.current_target["failed_attempts"] = self.current_target["failed_attempts"] + 1
local failed_attempts = self.current_target["failed_attempts"]
if failed_attempts >= 50 then
if failed_attempts >= PATHFINDING_FAIL_THRESHOLD then
mcl_log("Failed to reach position (" .. minetest.pos_to_string(self.current_target["pos"]) .. ") too many times. Abandon route. Times tried: " .. failed_attempts)
self.state = "stand"
self.current_target = nil
@ -348,9 +397,22 @@ function mob_class:check_gowp(dtime)
-- Is a little sensitive and could take 1 - 7 times. A 10 fail count might be a good exit condition.
mcl_log("We don't have waypoints or a current target. Let's try to path to target")
if self.waypoints then
mcl_log("WP: " .. tostring(self.waypoints))
mcl_log("WP num: " .. tostring(#self.waypoints))
else
mcl_log("No wp set")
end
if self.current_target then
mcl_log("Current target: " .. tostring(self.current_target))
else
mcl_log("No current target")
end
local final_wp = minetest.find_path(p,self._target,150,1,4)
if final_wp then
mcl_log("We might be able to get to target here.")
mcl_log("We can get to target here.")
-- self.waypoints = final_wp
self:go_to_pos(self._target)
else
@ -374,9 +436,9 @@ function mob_class:check_gowp(dtime)
self:go_to_pos(self._current_target)
else
mcl_log("close to current target: ".. minetest.pos_to_string(self.current_target["pos"]))
mcl_log("target is: ".. minetest.pos_to_string(self._target))
self.current_target = nil
end
return
end
end

View File

@ -5,8 +5,7 @@ local ENTITY_CRAMMING_MAX = 24
local CRAMMING_DAMAGE = 3
local DEATH_DELAY = 0.5
local DEFAULT_FALL_SPEED = -9.81*1.5
local FLOP_HEIGHT = 6
local FLOP_HOR_SPEED = 1.5
local PATHFINDING = "gowp"
local mobs_debug = minetest.settings:get_bool("mobs_debug", false)
local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false
@ -183,6 +182,17 @@ function mob_class:collision()
return({x,z})
end
function mob_class:slow_mob()
local d = 0.85
if self:check_dying() then d = 0.92 end
local v = self.object:get_velocity()
if v then
--diffuse object velocity
self.object:set_velocity({x = v.x*d, y = v.y, z = v.z*d})
end
end
-- move mob in facing direction
function mob_class:set_velocity(v)
local c_x, c_y = 0, 0
@ -778,6 +788,25 @@ function mob_class:do_env_damage()
return self:check_for_death("", {type = "unknown"})
end
function mob_class:env_damage (dtime, pos)
-- environmental damage timer (every 1 second)
self.env_damage_timer = self.env_damage_timer + dtime
if (self.state == "attack" and self.env_damage_timer > 1)
or self.state ~= "attack" then
self:check_entity_cramming()
self.env_damage_timer = 0
-- check for environmental damage (water, fire, lava etc.)
if self:do_env_damage() then
return true
end
-- node replace check (cow eats grass etc.)
self:replace(pos)
end
end
function mob_class:damage_mob(reason,damage)
if not self.health then return end
damage = math.floor(damage)

View File

@ -244,6 +244,24 @@ local function count_mobs_total(mob_type)
return num
end
local function count_mobs_all()
local mobs_found = {}
local num = 0
for _,entity in pairs(minetest.luaentities) do
if entity.is_mob then
local mob_type = entity.type -- animal / monster / npc
local mob_name = entity.name
if mobs_found[mob_name] then
mobs_found[mob_name] = mobs_found[mob_name] + 1
else
mobs_found[mob_name] = 1
end
num = num + 1
end
end
return mobs_found, num
end
local function count_mobs_total_cap(mob_type)
local num = 0
for _,l in pairs(minetest.luaentities) do
@ -628,6 +646,9 @@ if mobs_spawn then
local perlin_noise
-- Get pos to spawn, x and z are randomised, y is range
local function spawn_a_mob(pos, dimension, y_min, y_max)
--create a disconnected clone of the spawn dictionary
--prevents memory leak
@ -722,7 +743,9 @@ if mobs_spawn then
end)
end
function mob_class:check_despawn(pos)
function mob_class:check_despawn(pos, dtime)
self.lifetimer = self.lifetimer - dtime
-- Despawning: when lifetimer expires, remove mob
if remove_far
and self.can_despawn == true
@ -755,5 +778,18 @@ minetest.register_chatcommand("mobstats",{
minetest.chat_send_player(n,"total mobs:"..count_mobs_total())
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
local mob_counts, total_mobs = count_mobs_all()
if (total_mobs) then
minetest.log("action", "Total mobs found: " .. total_mobs)
end
if mob_counts then
for k, v1 in pairs(mob_counts) do
minetest.log("action", "k: " .. tostring(k))
minetest.log("action", "v1: " .. tostring(v1))
end
end
end
})

View File

@ -0,0 +1,2 @@
# textdomain:mcl_paintings
Painting=Maleri

View File

@ -12,13 +12,13 @@ mcl_mobs.register_mob("mobs_mc:chicken", {
description = S("Chicken"),
type = "animal",
spawn_class = "passive",
passive = true,
runaway = true,
hp_min = 4,
hp_max = 4,
xp_min = 1,
xp_max = 3,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.69, 0.2},
runaway = true,
floats = 1,
head_swivel = "head.control",
bone_eye_height = 4,

View File

@ -7,6 +7,7 @@ local cow_def = {
type = "animal",
spawn_class = "passive",
passive = true,
runaway = true,
hp_min = 10,
hp_max = 10,
xp_min = 1,
@ -40,7 +41,6 @@ local cow_def = {
max = 2,
looting = "common",},
},
runaway = true,
sounds = {
random = "mobs_mc_cow",
damage = "mobs_mc_cow_hurt",

View File

@ -259,6 +259,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
description = S("Enderman"),
type = "monster",
spawn_class = "passive",
can_despawn = true,
passive = true,
pathfinding = 1,
hp_min = 40,
@ -442,6 +443,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
end
end
end
-- TAKE AND PLACE STUFF BEHAVIOUR BELOW.
if not mobs_griefing then
return
@ -469,6 +471,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
local dug = minetest.get_node_or_nil(take_pos)
if dug and dug.name == "air" then
self._taken_node = node.name
self.can_despawn = false
local def = minetest.registered_nodes[self._taken_node]
-- Update animation and texture accordingly (adds visibly carried block)
local block_type
@ -519,6 +522,7 @@ mcl_mobs.register_mob("mobs_mc:enderman", {
if success then
local def = minetest.registered_nodes[self._taken_node]
-- Update animation accordingly (removes visible block)
self.can_despawn = true
self.animation = select_enderman_animation("normal")
self:set_animation(self.animation.current)
if def.sounds and def.sounds.place then

View File

@ -0,0 +1,70 @@
# textdomain: mobs_mc
Agent=Agent
Axolotl=Salamander
Bat=Flagermus
Blaze=Blaze
Chicken=Kylling
Cow=Ko
Mooshroom=Svamp
Creeper=Creeper
Ender Dragon=Enderdrage
Enderman=Enderman
Endermite=Endermide
Ghast=Ghast
Elder Guardian=Gammel beskytter
Guardian=Beskytter
Horse=Hest
Skeleton Horse=Skelethest
Zombie Horse=Zombiehest
Donkey=Æsel
Mule=Muldyr
Iron Golem=Jerngolem
Llama=Lama
Ocelot=Ozelot
Parrot=Papegøje
Pig=Gris
Polar Bear=Isbjørn
Rabbit=Kanin
Killer Bunny=Dræberkanin
Sheep=Får
Shulker=Shulker
Silverfish=Sølvfisk
Skeleton=Skelet
Stray=Omstrejfer
Wither Skeleton=Wither-skelet
Magma Cube=Magmakube
Slime=Slimklump
Snow Golem=Snegolem
Spider=Edderkop
Cave Spider=Huleedderkop
Squid=Blæksprutte
Vex=Vex
Evoker=Fremkalder
Illusioner=Illusionist
Villager=Landsbyboer
Vindicator=Hævner
Zombie Villager=Zombie landsbyboer
Witch=Heks
Wither=Wither
Wolf=Ulv
Husk=Udtørretskal
Zombie=Zombie
Zombie Pigman=Zombificeret piglin
Farmer=Landmand
Fisherman=Fisker
Fletcher=Pilemager
Shepherd=Fårehyrde
Librarian=Bibliotikar
Cartographer=Kartograf
Armorer=Rustningesmed
Leatherworker=Læderarbejder
Butcher=Slagter
Weapon Smith=Våbensmed
Tool Smith=Værktøjssmed
Cleric=Gejstlig
Nitwit=Tåbe
Cod=Torsk
Salmon=Laks
Dolphin=Delfin
Pillager=Plyndrer
Tropical fish=Tropisk fisk

View File

@ -6,6 +6,7 @@ mcl_mobs.register_mob("mobs_mc:pig", {
description = S("Pig"),
type = "animal",
spawn_class = "passive",
passive = true,
runaway = true,
hp_min = 10,
hp_max = 10,

View File

@ -56,6 +56,7 @@ mcl_mobs.register_mob("mobs_mc:sheep", {
description = S("Sheep"),
type = "animal",
spawn_class = "passive",
passive = true,
hp_min = 8,
hp_max = 8,
xp_min = 1,

View File

@ -235,7 +235,7 @@ local professions = {
librarian = {
name = N("Librarian"),
texture = "mobs_mc_villager_librarian.png",
jobsite = "mcl_books:bookshelf", --FIXME: lectern
jobsite = "mcl_lectern:lectern",
trades = {
{
{ { "mcl_core:paper", 24, 36 }, E1 },
@ -641,7 +641,7 @@ function get_activity(tod)
else
activity = "chill"
end
mcl_log("Time is " .. tod ..". Activity is: ".. activity)
--mcl_log("Time is " .. tod ..". Activity is: ".. activity)
return activity
end
@ -770,7 +770,7 @@ local function check_bed (entity)
local n = minetest.get_node(b)
local is_bed_bottom = string.find(n.name,"_bottom")
mcl_log("" .. tostring(is_bed_bottom))
--mcl_log("is bed bottom: " .. tostring(is_bed_bottom))
if n and not is_bed_bottom then
mcl_log("Where did my bed go?!")
entity._bed = nil --the stormtroopers have killed uncle owen
@ -836,6 +836,7 @@ end
local function take_bed (entity)
if not entity then return end
if not entity:ready_to_path() then return end
local p = entity.object:get_pos()
@ -1059,9 +1060,9 @@ local function look_for_job(self, requested_jobsites)
end
local function get_a_job(self)
if self.order == WORK then self.order = nil end
if not self:ready_to_path() then return end
mcl_log("I'm unemployed or lost my job block and have traded. Can I get a job?")
@ -1135,22 +1136,19 @@ local function validate_jobsite(self)
end
local function do_work (self)
--debug_trades(self)
if self.child then
mcl_log("A child so don't send to work")
if not self or self.child then
mcl_log("No self, or a child so don't work")
return
end
--mcl_log("Time for work")
local jobsite_node = retrieve_my_jobsite (self)
-- Don't try if looking_for_work, or gowp possibly
if validate_jobsite(self) then
--mcl_log("My jobsite is valid. Do i need to travel?")
local jobsite2 = retrieve_my_jobsite (self)
if jobsite_node then
local jobsite = self._jobsite
if self and jobsite2 and self._jobsite then
local distance_to_jobsite = vector.distance(self.object:get_pos(),self._jobsite)
local distance_to_jobsite = vector.distance(self.object:get_pos(), jobsite)
--mcl_log("Villager: ".. minetest.pos_to_string(self.object:get_pos()) .. ", jobsite: " .. minetest.pos_to_string(self._jobsite) .. ", distance to jobsite: ".. distance_to_jobsite)
if distance_to_jobsite < 2 then
@ -1185,18 +1183,38 @@ local function do_work (self)
end)
end
end
elseif self._profession == "unemployed" or has_traded(self) then
get_a_job(self)
end
local below_vec = vector.new(0, -1, 0)
local function get_ground_below_floating_object (float_pos)
local pos = float_pos
repeat
mcl_log("Current pos: " .. minetest.pos_to_string(pos))
pos = vector.add(pos, below_vec)
local node = minetest.get_node(pos)
mcl_log("First non air materials: ".. tostring(node.name))
until node.name ~= "air"
-- If pos is 1 below float_pos, then just return float_pos as there is no air below it
if pos.y == float_pos.y - 1 then
--mcl_log("pos is only 1 lower than float pos so no air below")
return float_pos
else
--mcl_log("pos is more than 1 lower than float pos so air is below")
return pos
end
return pos
end
local function go_to_town_bell(self)
if self.order == GATHERING then
mcl_log("Already gathering")
return
else
mcl_log("Current order" .. self.order)
end
if self.order == GATHERING then return
else mcl_log("Current order" .. self.order) end
if not self:ready_to_path() then return end
mcl_log("Go to town bell")
local looking_for_type={}
@ -1208,8 +1226,9 @@ local function go_to_town_bell(self)
--Ideally should check for closest available. It'll make pathing easier.
for _,n in pairs(nn) do
mcl_log("Found bell")
local target_point = get_ground_below_floating_object(n)
local gp = self:gopath(n,function(self)
local gp = self:gopath(target_point,function(self)
if self then
self.order = GATHERING
mcl_log("Callback has a self")
@ -1277,22 +1296,45 @@ local function validate_bed(self)
end
local function do_activity (self)
-- Maybe just check we're pathfinding first?
if self.following then
mcl_log("Following, so do not do activity.")
return
end
if self.state == PATHFINDING then
mcl_log("Pathfinding, so do not do activity.")
return
end
if not validate_bed(self) and self.state ~= PATHFINDING then
local jobsite_valid = false
if not mcl_beds.is_night() then
if self.order == SLEEP then self.order = nil end
mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos()))
if not validate_jobsite(self) then
--debug_trades(self)
if self._profession == "unemployed" or has_traded(self) then
get_a_job(self)
return
end
else
jobsite_valid = true
--mcl_log("My jobsite is valid. Do i need to travel?")
end
else
if self.order == WORK then self.order = nil end
if not validate_bed(self) then
if self.order == SLEEP then self.order = nil end
mcl_log("Villager at this location has no bed: " .. minetest.pos_to_string(self.object:get_pos()))
take_bed (self)
end
end
-- Only check in day or during thunderstorm but wandered_too_far code won't work
local wandered_too_far = false
if check_bed (self) then
wandered_too_far = ( self.state ~= PATHFINDING ) and (vector.distance(self.object:get_pos(),self._bed) > 50 )
wandered_too_far = vector.distance(self.object:get_pos(),self._bed) > 50
end
if wandered_too_far then
@ -1300,7 +1342,7 @@ local function do_activity (self)
go_home(self, false)
elseif get_activity() == SLEEP then
go_home(self, true)
elseif get_activity() == WORK then
elseif get_activity() == WORK and jobsite_valid then
do_work(self)
elseif get_activity() == GATHERING then
go_to_town_bell(self)
@ -1309,13 +1351,6 @@ local function do_activity (self)
self.order = nil
end
-- Daytime is work and play time
if not mcl_beds.is_night() then
if self.order == SLEEP then self.order = nil end
else
if self.order == WORK then self.order = nil end
end
end
local function update_max_tradenum(self)
@ -1895,8 +1930,6 @@ end)
--[=======[ MOB REGISTRATION AND SPAWNING ]=======]
local pick_up = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" }
mcl_mobs.register_mob("mobs_mc:villager", {
description = S("Villager"),
type = "npc",
@ -1941,7 +1974,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
head_shake_start = 131, head_shake_end = 141, head_shake_loop = false,
head_nod_start = 121, head_nod_end = 131, head_nod_loop = false,
},
follow = pick_up,
follow = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" },
nofollow = true,
view_range = 16,
fear_height = 4,
@ -1951,7 +1984,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
_id = nil,
_profession = "unemployed",
look_at_player = true,
pick_up = pick_up,
pick_up = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" },
can_open_doors = true,
on_pick_up = function(self,itementity)
local clicker
@ -1968,6 +2001,7 @@ mcl_mobs.register_mob("mobs_mc:villager", {
return it
end,
on_rightclick = function(self, clicker)
--minetest.log("In villager right click")
if self.child or self._profession == "unemployed" or self._profession == "nitwit" then
self.order = nil
return

View File

@ -109,6 +109,7 @@ mcl_mobs.register_mob("mobs_mc:villager_zombie", {
clicker:set_wielded_item(wielditem)
self._curing = math.random(3 * 60, 5 * 60)
self.shaking = true
self.can_despawn = false
end
end
end,

View File

@ -109,7 +109,7 @@ mcl_mobs.register_mob("mobs_mc:zombie", zombie)
local baby_zombie = table.copy(zombie)
baby_zombie.description = S("Baby Zombie")
baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 1, 0.25}
baby_zombie.collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.98, 0.25}
baby_zombie.xp_min = 12
baby_zombie.xp_max = 12
baby_zombie.walk_velocity = 1.2

View File

@ -0,0 +1,3 @@
# textdomain: lightning
Let lightning strike at the specified position or player. No parameter will strike yourself.=Lad lynet slå ned på den angivne position eller spiller. Hvis du ikke skriver et parameter vil lynet ramme dig selv.
No position specified and unknown player=Ingen position og ukendt spiller.

View File

@ -0,0 +1,3 @@
# textdomain: mcl_void_damage
The void is off-limits to you!=Tomrummet er forbudt område for dig!
@1 fell into the endless void.=@1 faldt ned i det uendelige tomrum.

View File

@ -0,0 +1,8 @@
# textdomain: mcl_weather
Gives ability to control weather=Gør en i stand til at styre vejret
Changes the weather to the specified parameter.=Ændrer vejret til det angivne.
Error: No weather specified.=Fejl: Intet vejr angivet.
Error: Invalid parameters.=Fejl: Ugyldige parametre.
Error: Duration can't be less than 1 second.=Fejl: Vargihed kan ikke være under 1 sekund.
Error: Invalid weather specified. Use “clear”, “rain”, “snow” or “thunder”.=Fejl: Ugyldigt vejr angivet. Brug "clear","rain","snow" eller "thunder".
Toggles between clear weather and weather with downfall (randomly rain, thunderstorm or snow)=Skifter mellem klart vejr og vejr med nedbør (tilfældigt enten regn, tordenstorm eller sne)

View File

@ -136,9 +136,16 @@ mcl_weather.skycolor = {
local biomesky
local biomefog
if mg_name ~= "v6" and mg_name ~= "singlenode" then
local biome = minetest.get_biome_name(minetest.get_biome_data(player:get_pos()).biome)
biomesky = minetest.registered_biomes[biome]._mcl_skycolor
biomefog = minetest.registered_biomes[biome]._mcl_fogcolor
local biome_index = minetest.get_biome_data(player:get_pos()).biome
local biome_name = minetest.get_biome_name(biome_index)
local biome = minetest.registered_biomes[biome_name]
if biome then
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name))
biomesky = biome._mcl_skycolor
biomefog = biome._mcl_fogcolor
else
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
end
end
if (mcl_weather.state == "none") then
-- Clear weather

View File

@ -0,0 +1,51 @@
# textdomain:doc
<=<
>=>
Access to the requested entry has been denied; this entry is secret. You may unlock access by progressing in the game. Figure out on your own how to unlock this entry.=Adgang til det forespurgte blev nægtet; det er hemmeligt. Du kan få adgang ved at nå længere i spillet. Find selv ud af, hvordan du får adgang.
All entries read.=Alle indtastninger læst.
All help entries revealed!=Alle hjælpeindtastninger afsløret!
All help entries are already revealed.=Alle hjælpeindtasterninger er allerede afsløret.
Allows you to reveal all hidden help entries with /help_reveal=Gør dig i stand til at afsløre alle skjulte hjælpeindtaster med /help_reveal
Category list=Kategoriliste
Currently all entries in this category are hidden from you.=Alle indtastninger i denne kategori er i øjeblikket skjult for dig.
Unlock new entries by progressing in the game.=Lås nye indtastninger op ved at nå længere i spillet.
Help=Hjælp
Entry=Indtastning
Entry list=Indtastningsliste
Error: Access denied.=Fejl: Adgang nægtet.
Error: No help available.=Fejl: Igen hjælp tilgængelig.
Go to category list=Gå til kategoriliste
Go to entry list=Gå til indtastningsliste
Help > @1=Hjælp > @1
Help > @1 > @2= Hjælp > @1 > @2
Help > @1 > (No Entry)=Hjælp > @1 > (Ingen indtasting)
Help > (No Category)=Hjælp > (Ingen kategori)
Hidden entries: @1=Skjult indtastning: @1
Nameless entry (@1)=Unavngiven indtastning (@1)
New entries: @1=Nye indtastninger: @1
New help entry unlocked: @1 > @2=Ny hjælpeindtastning låst op: @1 > @2
No categories have been registered, but they are required to provide help.=Nye kategorier er blevet registreret, men de er påkrævede for at give hjælp.
The Documentation System [doc] does not come with help contents on its own, it needs additional mods to add help content. Please make sure such mods are enabled on for this world, and try again.= Dokumentationssystemet [doc] har ikke medfølgende hjælpeindhold, det behøver yderligere mods for at tilføje hjælpeindhold.
Number of entries: @1=Antal indtastninger: @1
OK=OK
Open a window providing help entries about Minetest and more=Åbn et vindue med hjælpeindtastninger om Minetest og mere
Please select a category you wish to learn more about:=Vælg venlist en kategori som du ønsker at lære mere om:
Recommended mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.=Anbefalede mods: doc_basics, doc_items, doc_identifier, doc_encyclopedia.
Reveal all hidden help entries to you=Afslør alle gemte hjælpeindtastninger for dig.
Show entry=Vis indtastning
Show category=Vis kategori
Show next entry=Vis næste indtastning
Show previous entry=Vis forrige indtastning
This category does not have any entries.=Denne kategori har ingen indtastninger.
This category has the following entries:=Denne kategori har følgende indtastninger:
This category is empty.=Denne kategori er tom.
This is the help.=Dette er hjælpen.
You haven't chosen a category yet. Please choose one in the category list first.=Du har endnu ikke vagt en kategori. Vælg venligst én i kategoriliste før.
You haven't chosen an entry yet. Please choose one in the entry list first.=Du har ikke valgt en indtastning endnu. Vælg venligst en fra indtastningslisten først.
Collection of help texts=Samling at hjælpetekster.
Notify me when new help is available=Giv mig besked når ny hjælp er tilgængelig.
Play notification sound when new help is available=Afspil lyd når ny hjælp er tilgængeig.
Show previous image=Vis forrige billede
Show previous gallery page=Vis forrige galleriside
Show next image=Vis næste billede
Show next gallery page=Vis næste galleriside

View File

@ -0,0 +1,18 @@
# textdomain:doc_identifier
Error: This node, item or object is undefined. This is always an error.=Fejl: Dette knudepunkt, genstand eller objekt er ikke defineret.
This can happen for the following reasons:=Dette kan ske af følgende grunde:
• The mod which is required for it is not enabled=• Det mod som er krævet er ikke aktiveret
• The author of the game or a mod has made a mistake=• Ophavsmanden til spillet eller moddet har lavet en fejltagelse
It appears to originate from the mod “@1”, which is enabled.=Det ser ud til at stamme fra moddet "@1" som er aktiveret.
It appears to originate from the mod “@1”, which is not enabled!=Det ser ud til at stamme fra moddet "01" som er deaktiveret!
Its identifier is “@1”.=Dets identificering er "@1".
Lookup Tool=Opslagsværktøj
No help entry for this block could be found.=Der kunne ikke findes nogen hjælpeindtastning til denne blok.
No help entry for this item could be found.=Der kunne ikke findes nogen hjælpeindtastning til denne genstand.
No help entry for this object could be found.=Der kunne ikke findes nogen hjælpeindtastning for stte objekt.
OK=OK
Punch any block, item or other thing about you wish to learn more about. This will open up the appropriate help entry. The tool comes in two modes which are changed by using. In liquid mode, this tool points to liquids as well while in solid mode this is not the case.=Slå en hvilkensomhelst blok, genstand eller andre ting som du ønsker at vide mere om. Dette vil åbne den relevante hjælpeindtastning. Værktøjet findes i to tilstande som skiftes ved brug. I flydende tilstand vil værktøjet også peje på væsker, mens dette ikke er tilfældet i fast tilstand.
This block cannot be identified because the world has not materialized at this point yet. Try again in a few seconds.=Denne blok kan ikke identificeres fordi verdenen ikke har materialiseret sig endnu. Forsøg igen om et par sekunder.
This is a player.=Dette er en spiller.
This useful little helper can be used to quickly learn more about about one's closer environment. It identifies and analyzes blocks, items and other things and it shows extensive information about the thing on which it is used.=Denne smarte lille hjælper kan bruges til hurtigt at lære mere om omgivelserne. Den identificerer og analyserer blokke, genstande og andre ting, og den viser udtømmende informationer om den ting den bliver brugt på.
Show help for pointed thing=Vis hjælp til tingen

View File

@ -0,0 +1,143 @@
# textdomain:doc_items
Using it as fuel turns it into: @1.=At bruge det som brændstof laver det om til: @1.
@1 seconds=@1 sekunder
# Item count times item name
@1×@2=@1x@2
# Itemname (25%)
@1 (@2%)=@1 (@2%)
# Itemname (<0.5%)
@1 (<0.5%)= @1 (<0.5%)
# Itemname (ca. 25%)
@1 (ca. @2%)=@1 (ca. @2%)
# List separator (e.g. “one, two, three”)
, = ,
# Final list separator (e.g. “One, two and three”)
and = and
1 second=1 sekund
A transparent block, basically empty space. It is usually left behind after digging something.=En gennemsigtig blok, egentlig bare tom luft. Det efterlades typisk efter at have gravet.
Air=Luft
Blocks=Blokke
Building another block at this block will place it inside and replace it.=At sætte en ny blok ved denne blok vil placere den indeni og erstatte den.
Building this block is completely silent.=Det er helt lydløst at bygge denne blok.
Collidable: @1=Kan kollidere: @1
Description: @1=Beskrivelse: @1
Falling blocks can go through this block; they destroy it when doing so.=Faldende blokke kan gå igennem denne blok; de ødelægger den idet i går igennem den.
Full punch interval: @1 s=Tid mellem hele slag: @1
Hand=Hånd
Hold it in your hand, then leftclick to eat it.=Hold det i din hånd, og venstre-klik for at spise det.
Hold it in your hand, then leftclick to eat it. But why would you want to do this?=Hold det i din hånd, og venstre-klik for at spise det. Men hvorfor i alverden ville du have lyst til dét?
Item reference of all wieldable tools and weapons=Genstandsreference til alt værktøj og alle våden man kan bære.
Item reference of blocks and other things which are capable of occupying space=Genstandsreference til blokke og andre ting som kan optage plads.
Item reference of items which are neither blocks, tools or weapons (esp. crafting items)=Genstandsreference til genstanse som hverken er blokke, værktøj eller våben (især håndværksmateriale)
Liquids can flow into this block and destroy it.=Væsker kan flyde ind i denne blok og ødelægge den.
Maximum stack size: @1=Største stakstørrelse: @1
Mining level: @1=Udvindingsevneevne: @1
Mining ratings:=Udvindelsesvurdering
• @1, rating @2: @3 s - @4 s=• @1, vurdering @2: @3 s -@4 s
• @1, rating @2: @3 s=• @1, vurdering @2: @3 s
Mining times:=Udvindingstider
Mining this block is completely silent.=Det er helt lydløst at udvinde denne blok.
Miscellaneous items=Diverse genstande
No=Nej
Pointable: No=Retningsbestemt: Nej
Pointable: Only by special items=Retningsbestemt: Kun af særlige genstande
Pointable: Yes=Retningsbestemt: Ja
Punches with this block don't work as usual; melee combat and mining are either not possible or work differently.=Slag med denne blok virker ikke som normalt; nærkamp og udvinding er enten umulig eller virker anderledes.
Punches with this item don't work as usual; melee combat and mining are either not possible or work differently.=Slag med dette objekt virker ikke som normalt; nærkamp og udvinding er enten umulig eller virker anderledes.
Punches with this tool don't work as usual; melee combat and mining are either not possible or work differently.=Slag med dette værktøj virker ikke som normalt; nærkamp og udvinding er enten umulig eller virker anderledes.
Range: @1=Rækkevidde: @1
# Range: <Hand> (<Range>)
Range: @1 (@2)=Rækkevidde: @1 (@2)
Range: 4=Rækkevidde: 4
# Rating used for digging times
Rating @1=Vurdering: @1
# @1 is minimal rating, @2 is maximum rating
Rating @1-@2=Vurdering @1-@2
The fall damage on this block is increased by @1%.=Faldskade på denne blok er øget med @1%.
The fall damage on this block is reduced by @1%.=Faldskade på denne blok er reduceret med @1%.
This block allows light to propagate with a small loss of brightness, and sunlight can even go through losslessly.=Denne blok lader lys sprede sig med et lille tab af styrke, og sollys kan endda gå igennem uden tab.
This block allows light to propagate with a small loss of brightness.=Denne blok tillader lys at sprede med et lille tab af styrke.
This block allows sunlight to propagate without loss in brightness.=Denne blok tillader sollys at sprede sig uden tab af styrke.
This block belongs to the @1 group.=Denne blok tilhører @1gruppen
This block belongs to these groups: @1.=Denne blok hører til følgende grupper: @1.
This block can be climbed.=Man kan klatre på denne blok.
This block can be destroyed by any mining tool immediately.=Denne blok kan ødelægges straks med ethvert udvindingsværktøj.
This block can be destroyed by any mining tool in half a second.=Denne blok kan ødelægges på et halvt sekund med ethvert udvindingsværktøj.
This block can be mined by any mining tool immediately.=Denne blok kan udvindes straks med ethvert udvindingsværktøj.
This block can be mined by any mining tool in half a second.=Denne blok kan udvindes på et halvt sekund med ethvert udvindingsværktøj.
This block can be mined by mining tools which match any of the following mining ratings and its toughness level.=Denne blok kan udvindes med ethvert udvindingsværktøj som svarer til en hvilkensomhelst af følgende udvindingsvurderinger og hårdhedsgrad.
This block can not be destroyed by ordinary mining tools.=Denne blok kan ikke ødelægges af normalt udvindingsværktøj.
This block can not be mined by ordinary mining tools.=Denne blok kan ikke udvindes med normalt udvindingsværktøj.
This block can serve as a smelting fuel with a burning time of @1.=Denne blok virker som brændstof til at smelte og har en brændetid på @1.
This block causes a damage of @1 hit point per second.=Denne blok giver @1 skade per sekund.
This block causes a damage of @1 hit points per second.=Denne blok giver @1 skade per sekund.
This block connects to blocks of the @1 group.=Denne blok forbindes til blokke i @1gruppen.
This block connects to blocks of the following groups: @1.=Denne blok forbindes til blokke i følgende grupper: @1.
This block connects to these blocks: @1.=Denne blok forbindes til disse blokke: @1.
This block connects to this block: @1.=Denne blok forbindes til denne blok: @1.
This block decreases your breath and causes a drowning damage of @1 hit point every 2 seconds.=Denne blok nedsætter dit åndedræt og giver @1 drukningsskade hvert 2. sekund.
This block decreases your breath and causes a drowning damage of @1 hit points every 2 seconds.=Denne blok nedsætter dit åndedræt og giver @1 drukneskade hvert 2. sekund.
This block is a light source with a light level of @1.=Denne blok er en lyskilde med lysniveau @1.
This block glows faintly with a light level of @1.=Denne blok gløder svagt med et lysniveau på @1.
This block is a building block for creating various buildings.=Denne blok er en byggesten til at bygge forskellige bygninger.
This block is a liquid with these properties:=Denne blok er en væske med følgende egenskaber:
This block is affected by gravity and can fall.=Denne blok påvirkes af tyngdekraften og kan falde ned.
This block is completely silent when mined or built.=Denne blok er helt lydløs når den udvindes eller bygges.
This block is completely silent when walked on, mined or built.=Denne blok er helt lydløs når den betrædes, udvindes eller bygges.
This block is destroyed when a falling block ends up inside it.=Denne blok ødelægges når en nedfaldende blok ender indeni den.
This block negates all fall damage.=Denne blok modvirker al faldskade.
This block points to liquids.=Denne blok orienteres mod væsker.
This block will drop as an item when a falling block ends up inside it.=Denne blok dropper som genstand når en faldende blok ender indeni den.
This block will drop as an item when it is not attached to a surrounding block.=Denne blok dropper som genstand når den ikke sidder fast på en tilstødende blok.
This block will drop as an item when no collidable block is below it.=Denne blok dropper som genstand når der ikke er en bæredygtig blok under den.
This block will drop the following items when mined: @1.=Denne blok dropper følgende genstande når den udvindes: @1.
This block will drop the following when mined: @1×@2.=Denne blok dropper følgende når den udvindes: @1x@2.
This block will drop the following when mined: @1.=Denne blok dropper følgende når den udvindes: @1.
This block will drop the following when mined: @1.=Denne blok dropper følgende når den udvindes: @1.
This block will make you bounce off with an elasticity of @1%.=Denne blok får dig til at hoppe af med en elasticitet på @1%.
This block will randomly drop one of the following when mined: @1.=Denne blok dropper en vilkårlig af følgende genstande når den udvindes: @1.
This block will randomly drop up to @1 drops of the following possible drops when mined: @2.=Denne blok dropper et vilkårligt antal op til @1 af følgende mulige ting når den udvindes: @2.
This block won't drop anything when mined.=Denne blok dropper ikke noget når den udvindes.
This is a decorational block.=Dette er en pynteblok.
This is a melee weapon which deals damage by punching.=Dette er et nærkampsvåben som giver skade ved at slå.
Maximum damage per hit:=Højeste skade per slag:
This item belongs to the @1 group.=Denne genstand hører til @1gruppen.
This item belongs to these groups: @1.=Denne genstand hører til disse grupper: @1.
This item can serve as a smelting fuel with a burning time of @1.=Denne genstand virker som brændstof til at smelte og har en brændetid på @1.
This item is primarily used for crafting other items.=Denne genstand bruges mest til at lave andre genstande.
This item points to liquids.=Denne genstand orienterer sig mod væsker.
This tool belongs to the @1 group.=Dette værktøj hører til @1gruppen
This tool belongs to these groups: @1.=Dette værktøj hører til disse grupper:
This tool can serve as a smelting fuel with a burning time of @1.=Dette værktøj virker som brændstof til at smelte og har en brændetid på @1.
This tool is capable of mining.=Dette værktøj kan bruges til udvinding.
Maximum toughness levels:=Højeste hårdhedsgrad.
This tool points to liquids.=Dette værktøj orienterer sig mod væsker.
Tools and weapons=Værktøj og våben
Unknown Node=Ukendt knudepunkt
Usage help: @1=Hjælp til brug: @1
Walking on this block is completely silent.=Det er helt lydløst at gå på denne blok.
Whenever you are not wielding any item, you use the hand which acts as a tool with its own capabilities. When you are wielding an item which is not a mining tool or a weapon it will behave as if it would be the hand.=Når du ikke anvender en genstand, bruger du din hånd som fungerer som et værktøj med sine egne egenskaber. Når du anvender en genstand som ikke er et værktøj til udvinding eller våben virker det som om du bruger din hånd.
Yes=Ja
You can not jump while standing on this block.=Du kan ikke hoppe mens du står på dene blok.
any level=hvilketsomhelst level
level 0=level 0
level 0-@1=level 0-@1
unknown=ukendt
Unknown item (@1)=ukendt genstand (@1)
• @1: @2=
• @1: @2 HP=• @1: @2 HP
• @1: @2, @3=• @1: @2, @3
• Flowing range: @1=• Flydende rækkevidde: @1
• No flowing=• Ingen strøm
• Not renewable=• Kan ikke genopfriskes
• Renewable=• Kan genopfriskes
• Viscosity: @1=• Viskositet: @1
Itemstring: "@1"=Genstandsstreng: "@1"
Durability: @1 uses=Holdbarhed: @1 anvendelser
Durability: @1=Holdbarhed: @1
Mining durability:=Udvindingsholdbarhed:
• @1, level @2: @3 uses=• @1, level @2: @3 anvendelser
• @1, level @2: Unlimited=• @1, level @2: Uendelig
This block's rotation is affected by the way you place it: Place it on the floor or ceiling for a vertical orientation; place it at the side for a horizontal orientation. Sneaking while placing it leads to a perpendicular orientation instead.=Denne bloks rotation påvirkes af måden du placerer den på: Placér den på gulvet eller loftet for en lodret orientering; placér den på siden for en horisontal orientering. Hvis du sniger dig mens den placeres den vinkelret i stedet.
Toughness level: @1=Hårdhedsgrad: @1
This block is slippery.=Denne blok er glat.

View File

@ -0,0 +1,37 @@
# textdomain: craftguide
Any shulker box=Hvilkensomhelst shulkerboks
Any wool=Hvilkensomhelst uld
Any wood planks=Hvilkensomhelst træplanker
Any wood=Hvilkensomhelst træ
Any sand=Hvilkensomhelst sand
Any normal sandstone=Hvilkensomhelst normal sandsten
Any red sandstone=Hvilkensomhelst rød sandsten
Any carpet=HVilketsomhelst tæppe
Any dye=Hvilkensomhelst farvestof
Any water bucket=Hvilkensomhelst vandpand
Any flower=Hvilkensomhelst blomst
Any mushroom=Hvilkensomhelst svamp
Any wooden slab=Hvilkensomhelst træplade
Any wooden stairs=Hvilkensomhelst trætrappe
Any coal=Hvilketsomhelst kul
Any kind of quartz block=Hvilkensomhelst quartzblok
Any kind of purpur block=Hvilkensomhelst pupurblok
Any stone bricks=Hvilkensomhelst mursten af sten
Any stick=Hvilkensomhelst pind
Any item belonging to the @1 group=Hvilkensomhelst genstant i @1gruppen
Any item belonging to the groups: @1=Hvilkensomhelst genstand som hører til grupperne: @1
Search=Søg
Reset=Nulstil
Previous page=Forrige side
Next page=Næste side
Usage @1 of @2=Brug @1 af @2
Recipe @1 of @2=Opskrift @1 af @2
Burning time: @1=Brændetid: @1
Cooking time: @1=Tilberedelsestid: @1
Recipe is too big to be displayed (@1×@2)=Formen er for stor til at blive vist (@1x@2)
Shapeless=Uformelig
Cooking=Madlavning
Increase window size=Øg vinduesstørrelsen
Decrease window size=Mindsk vinduesstørrelsen
No item to show=Ingen genstande at vise
Collect items to reveal more recipes=Saml genstande for at afsløre flere opskrifter

View File

@ -0,0 +1,79 @@
# textdomain: mcl_doc
Water can flow into this block and cause it to drop as an item.=Der kan flyde vandt i denne blok, hvilket får den til at droppe som en genstand.
This block can be turned into dirt with a hoe.=Denne blok kan omdannes til jord med en hakke.
This block can be turned into farmland with a hoe.=Denne blok kan omdannes til landbrugsjord med en hakke.
This block acts as a soil for all saplings.=Denne blok virker som jord for alle spirer.
This block acts as a soil for some saplings.=Denne blok virker som jord for nogle spirer.
Sugar canes will grow on this block.=Sukkerrør gror på denne blok.
Nether wart will grow on this block.=Nethervorder gror på denne blok.
This block quickly decays when there is no wood block of any species within a distance of @1. When decaying, it disappears and may drop one of its regular drops. The block does not decay when the block has been placed by a player.=Denne blok forgår hurtigt når der ikke er træblokke af nogen art af træblokke indenfor en afstand af @1. Når den forgår, forsvinder den, og dropper måske et af sine normale drops. Blokken forgår ikke når den er blevet placeret af en spiller.
This block quickly decays and disappears when there is no wood block of any species within a distance of @1. The block does not decay when the block has been placed by a player.=Denne blok forgår hurtigt og forsvinder når der ikke er nogen art af træblokke indenfor en afstand af @1. Blokken forgår ikke når den er blevet placeret af en spiller.
This plant can only grow on grass blocks and dirt. To survive, it needs to have an unobstructed view to the sky above or be exposed to a light level of 8 or higher.=Denne plante kan kun gro på græsblokke eller jord. For at overleve, har den brug for direkte udsyn til himlen, eller et lysniveau på 8 eller derover.
This plant can grow on grass blocks, podzol, dirt and coarse dirt. To survive, it needs to have an unobstructed view to the sky above or be exposed to a light level of 8 or higher.=Denne plante kan gro på græsblokke, podsol, jord eller grov jord. For at overleve, har den brug for direkte udsyn til himlen, eller et lysniveau på 8 eller derover.
This block is flammable.=Denne blok er brændfarlig.
This block destroys any item it touches.=Denne blok ødelægger enhver genstand den berør.
To eat it, wield it, then rightclick.=For at spise det skal du bære det og højre-klikke.
You can eat this even when your hunger bar is full.=Du kan spise dette selvom din sultbjælke er fuld.
You cannot eat this when your hunger bar is full.=Du kan ikke spise dette når din sultbjælke er fuld.
To drink it, wield it, then rightclick.=For at drikke det skal du bære det og højre-klikke.
You cannot drink this when your hunger bar is full.=Du kan ikke drikke dette når din sultbjælke er fuld.
To consume it, wield it, then rightclick.=For at indtage det skal du bære det og højre-klikke.
You cannot consume this when your hunger bar is full.=Du kan ikke indtage dette når din sultbjælke er fuld.
You have to wait for about 2 seconds before you can eat or drink again.=Du er nødt til at vente omkring 2 sekunder før du kan drikke eller spise igen.
Hunger points restored: @1=Sultpoint genvundet: @1
Saturation points restored: @1%.1f=Mæthedspoint genvundet: @1%.1f
This item can be repaired at an anvil with: @1.=Denne genstand kan repareres ved en ambolt med: @1.
This item can be repaired at an anvil with any wooden planks.=Denne genstand kan repareres ved en ambolt med hvilkensomhelst træplanke.
This item can be repaired at an anvil with any item in the “@1” group.=Denne genstand kan repareres ved en ambolt med hvilkensomhelst genstand i "@1"gruppen
This item cannot be renamed at an anvil.=Denne genstand kan ikke omdøbes ved en ambolt.
This block crushes any block it falls into.=Denn blok knuser enhver blok den falder ind i.
When this block falls deeper than 1 block, it causes damage to any player it hits. The damage dealt is B×22 hit points with B @= number of blocks fallen. The damage can never be more than 40 HP.=Denne blok falder dybere end 1 blok, og giver skade til enhver spiller den rammer. Skaden givet er Bx2-2 ned B @= antal faldne blokke.
Diamond Pickaxe=Minehakke i diamant
Iron Pickaxe=Jernhakke
Stone Pickaxe=Stenhakke
Golden Pickaxe=Guldhakke
Wooden Pickaxe=Træhakke
Diamond Axe=Diamantøkse
Iron Axe=Jernøkse
Stone Axe=Stenøkse
Golden Axe=Guldøkse
Wooden Axe=Træøkse
Diamond Shovel=Diamantskovl
Iron Shovel=Jernskovl
Stone Shovel=Stenskovl
Golden Shovel=Guldskovl
Wooden Shovel=Træskovl
This block can be mined by any tool instantly.=Denne blok kan udvindes momentant med ethvert værktøj.
This block can be mined by:=Denne blok kan udvindes med:
Hardness: ∞= Hårdhed:∞
Hardness: @1=Hårdhed @1
This block will not be destroyed by TNT explosions.=Denne blok ødelægges ikke af TNT-eksplosioner.
This block drops itself when mined by shears.=Denne blok dropper sig selv når den udvindes med sakse.
@1×@2=@1x@2
This blocks drops the following when mined by shears: @1=Denne blok dropper følgende når den udvindes med sakse: @1
, =,
• Shears=• Sakse
• Sword=• Sværd
• Hand=• Hånd
This is a melee weapon which deals damage by punching.=Dette er et nærkampsvåben som giver skade ved at slå.
Maximum damage: @1 HP=Højeste skade: @1
Full punch interval: @1 s=Helt interval mellem slag: @1 s
This tool is capable of mining.=Dette værktøj kan bruges til udvinding.
Mining speed: @1=Udvindingshastighed: @1
Painfully slow=Pinagtig langsom
Very slow=Meget langsom
Slow=Langsom
Fast=Hurtig
Very fast=Meget hurtig
Extremely fast=Ekstremt hurtig
Instantaneous=Momentan
@1 uses=@1 anvendelser
Unlimited uses=Uendelige anvendelser
Block breaking strength: @1=Blokkens brudstyrke: @1
Mining durability: @1=Udvindingsholdbarhed: @1
Armor points: @1=Rustningspoint: @1
Armor durability: @1=Rustningens holdbarhed: @1
It can be worn on the head.=Den kan bæres på hovedet.
It can be worn on the torso.=Den kan bæres på kroppen.
It can be worn on the legs.=De kan bæres på benene.
It can be worn on the feet.=De kan bæres på fødderne.

View File

@ -0,0 +1,511 @@
# textdomain: mcl_doc_basics
Basics=
Everything you need to know to get started with playing=
Advanced usage=
Advanced information which may be nice to know, but is not crucial to gameplay=
Quick start=
This is a very brief introduction to the basic gameplay:=
Basic controls:=
• Move mouse to look=
• [W], [A], [S] and [D] to move=
• [E] to sprint=
• [Space] to jump or move upwards=
• [Shift] to sneak or move downwards=
• Mouse wheel or [1]-[9] to select item=
• Left-click to mine blocks or attack=
• Recover from swings to deal full damage=
• Right-click to build blocks and use things=
• [I] for the inventory=
• First items in inventory appear in hotbar below=
• Lowest row in inventory appears in hotbar below=
• [Esc] to close this window=
How to play:=
• Punch a tree trunk until it breaks and collect wood=
• Place the wood into the 2×2 grid (your “crafting grid”) in your inventory menu and craft 4 wood planks=
• Place them in a 2×2 shape in the crafting grid to craft a crafting table=
• Place the crafting table on the ground=
• Rightclick it for a 3×3 crafting grid=
• Use the crafting guide (book icon) to learn all the possible crafting recipes=
• Craft a wooden pickaxe so you can dig stone=
• Different tools break different kinds of blocks. Try them out!=
• Read entries in this help to learn the rest=
• Continue playing as you wish. There's no goal. Have fun!=
Minetest=
Minetest is a free software game engine for games based on voxel gameplay, inspired by InfiniMiner, Minecraft, and the like. Minetest was originally created by Perttu Ahola (alias “celeron55”).=
The player is thrown into a huge world made out of cubes or blocks. These cubes usually make the landscape they blocks can be removed and placed almost entirely freely. Using the collected items, new tools and other items can be crafted. Games in Minetest can, however, be much more complex than this.=
A core feature of Minetest is the built-in modding capability. Mods modify existing gameplay. They can be as simple as adding a few decorational blocks or be very complex by e.g. introducing completely new gameplay concepts, generating a completely different kind of world, and many other things.=
Minetest can be played alone or online together with multiple players. Online play will work out of the box with any mods, with no need for additional software as they are entirely provided by the server.=
Minetest is usually bundled with a simple default game, named “Minetest Game” (shown in images 1 and 2). You probably already have it. Other games for Minetest can be downloaded from the official Minetest forums <https://forum.minetest.net/viewforum.php?f@=48>.=
Minetest as well as Minetest Game are both unfinished at the moment, so please forgive us when not everything works out perfectly.=
Sneaking=
Sneaking makes you walk slower and prevents you from falling off the edge of a block.=
To sneak, hold down the sneak key (default: [Shift]). When you release it, you stop sneaking. Careful: When you release the sneak key at a ledge, you might fall!=
• Sneak: [Shift]=
Sneaking only works when you stand on solid ground, are not in a liquid and don't climb.=
If you jump while holding the sneak key, you also jump slightly higher than usual.=
Sneaking might be disabled by mods. In this case, you still walk slower by sneaking, but you will no longer be stopped at ledges.=
Controls=
These are the default controls:=
Basic movement:=
• Moving the mouse around: Look around=
• W: Move forwards=
• A: Move to the left=
• D: Move to the right=
• S: Move backwards=
• E: Sprint=
While standing on solid ground:=
• Space: Jump=
• Shift: Sneak=
While on a ladder, swimming in a liquid or fly mode is active=
• Space: Move up=
• Shift: Move down=
Extended movement (requires privileges):=
• J: Toggle fast mode, makes you run or fly fast (requires “fast” privilege)=
• K: Toggle fly mode, makes you move freely in all directions (requires “fly” privilege)=
• H: Toggle noclip mode, makes you go through walls in fly mode (requires “noclip” privilege)=
• E: Move even faster when in fast mode=
• E: Walk fast in fast mode=
World interaction:=
• Left mouse button: Punch / mine blocks / take items=
• Left mouse button: Punch / mine blocks=
• Right mouse button: Build or use pointed block=
• Shift+Right mouse button: Build=
• Roll mouse wheel: Select next/previous item in hotbar=
• Roll mouse wheel / B / N: Select next/previous item in hotbar=
• 1-9: Select item in hotbar directly=
• Q: Drop item stack=
• Shift+Q: Drop 1 item=
• I: Show/hide inventory menu=
Inventory interaction:=
See the entry “Basics > Inventory”.=
Camera:=
• Z: Zoom=
• F7: Toggle camera mode=
• F8: Toggle cinematic mode=
Interface:=
• Esc: Open menu window (pauses in single-player mode) or close window=
• F1: Show/hide HUD=
• F2: Show/hide chat=
• F9: Toggle minimap=
• Shift+F9: Toggle minimap rotation mode=
• F10: Open/close console/chat log=
• F12: Take a screenshot=
Server interaction:=
• T: Open chat window (chat requires the “shout” privilege)=
• /: Start issuing a server command=
Technical:=
• R: Toggle far view (disables all fog and allows viewing far away, can make game very slow)=
• +: Increase minimal viewing distance=
• -: Decrease minimal viewing distance=
• F3: Enable/disable fog=
• F5: Enable/disable debug screen which also shows your coordinates=
• F6: Only useful for developers. Enables/disables profiler=
• P: Only useful for developers. Writes current stack traces=
Players=
Players (actually: “player characters”) are the characters which users control.=
Players are living beings. They start with a number of health points (HP) and a number of breath points (BP).=
Players are capable of walking, sneaking, jumping, climbing, swimming, diving, mining, building, fighting and using tools and blocks.=
Players can take damage for a variety of reasons, here are some:=
• Taking fall damage=
• Touching a block which causes direct damage=
• Drowning=
• Being attacked by another player=
• Being attacked by a computer enemy=
At a health of 0, the player dies. The player can just respawn in the world.=
Other consequences of death depend on the game. The player could lose all items, or lose the round in a competitive game.=
Some blocks reduce breath. While being with the head in a block which causes drowning, the breath points are reduced by 1 for every 2 seconds. When all breath is gone, the player starts to suffer drowning damage. Breath is quickly restored in any other block.=
Damage can be disabled on any world. Without damage, players are immortal and health and breath are unimportant.=
In multi-player mode, the name of other players is written above their head.=
Items=
Items are things you can carry along and store in inventories. They can be used for crafting, smelting, building, mining, and more. Types of items include blocks, tools, weapons and items only used for crafting.=
An item stack is a collection of items of the same type which fits into a single item slot. Item stacks can be dropped on the ground. Items which drop into the same coordinates will form an item stack.=
Dropped item stacks will be collected automatically when you stand close to them.=
Items have several properties, including the following:=
• Maximum stack size: Number of items which fit on 1 item stack=
• Pointing range: How close things must be to be pointed while wielding this item=
• Group memberships: See “Basics > Groups”=
• May be used for crafting or cooking=
Tools=
Some items may serve as a tool when wielded. Any item which has some special use which can be directly used by its wielder is considered a tool.=
A common subset of tools is mining tools. These are important to break all kinds of blocks. Weapons are a kind of tool. There are of course many other possible tools. Special actions of tools are usually done by left-click or right-click.=
When nothing is wielded, players use their hand which may act as tool and weapon.=
Mining tools are important to break all kinds of blocks. Weapons are another kind of tool. There are some other more specialized tools. Special actions of tools are usually done by right-click.=
When nothing is wielded, players use their hand which may act as tool and weapon. The hand is capable of punching and deals minimum damage.=
Many tools will wear off when using them and may eventually get destroyed. The damage is displayed in a damage bar below the tool icon. If no damage bar is shown, the tool is in mint condition. Tools may be repairable by crafting, see “Basics > Crafting”.=
Weapons=
Some items are usable as a melee weapon when wielded. Weapons share most of the properties of tools.=
Melee weapons deal damage by punching players and other animate objects. There are two ways to attack:=
• Single punch: Left-click once to deal a single punch=
• Quick punching: Hold down the left mouse button to deal quick repeated punches=
There are two core attributes of melee weapons:=
• Maximum damage: Damage which is dealt after a hit when the weapon was fully recovered=
• Full punch interval: Time it takes for fully recovering from a punch=
A weapon only deals full damage when it has fully recovered from a previous punch. Otherwise, the weapon will deal only reduced damage. This means, quick punching is very fast, but also deals rather low damage. Note the full punch interval does not limit how fast you can attack.=
There is a rule which sometimes makes attacks impossible: Players, animate objects and weapons belong to damage groups. A weapon only deals damage to those who share at least one damage group with it. So if you're using the wrong weapon, you might not deal any damage at all.=
Pointing=
“Pointing” means looking at something in range with the crosshair. Pointing is needed for interaction, like mining, punching, using, etc. Pointable things include blocks, players, computer enemies and objects.=
To point something, it must be in the pointing range (also just called “range”) of your wielded item. There's a default range when you are not wielding anything. A pointed thing will be outlined or highlighted (depending on your settings). Pointing is not possible with the 3rd person front camera.=
A few things can not be pointed. Most blocks are pointable. A few blocks, like air, can never be pointed. Other blocks, like liquids can only be pointed by special items.=
Camera=
There are 3 different views which determine the way you see the world. The modes are:=
• 1: First-person view (default)=
• 2: Third-person view from behind=
• 3: Third-person view from the front=
You can change the camera mode by pressing [F7].=
You might be able to zoom with [Z] to zoom the view at the crosshair. This allows you to look further.=
Zooming is a gameplay feature that might be enabled or disabled by the game. By default, zooming is enabled when in Creative Mode but disabled otherwise.=
There is also Cinematic Mode which can be toggled with [F8]. With Cinematic Mode enabled, the camera movements become more smooth. Some players don't like it, it is a matter of taste.=
By holding down [Z], you can zoom the view at your crosshair. You need the “zoom” privilege to do this.=
• Switch camera mode: [F7]=
• Toggle Cinematic Mode: [F8]=
• Zoom: [Z]=
Blocks=
The world of MineClone 2 is made entirely out of blocks (voxels, to be precise). Blocks can be added or removed with the correct tools.=
The world is made entirely out of blocks (voxels, to be precise). Blocks can be added or removed with the correct tools.=
Blocks can have a wide range of different properties which determine mining times, behavior, looks, shape, and much more. Their properties include:=
• Collidable: Collidable blocks can not be passed through; players can walk on them. Non-collidable blocks can be passed through freely=
• Pointable: Pointable blocks show a wireframe or a halo box when pointed. But you will just point through non-pointable blocks. Liquids are usually non-pointable but they can be pointed at by some special tools=
• Mining properties: By which tools it can be mined, how fast and how much it wears off tools=
• Climbable: While you are at a climbable block, you won't fall and you can move up and down with the jump and sneak keys=
• Drowning damage: See the entry “Basics > Player”=
• Liquids: See the entry “Basics > Liquids”=
• Group memberships: Group memberships are used to determine mining properties, crafting, interactions between blocks and more=
Mining=
Mining (or digging) is the process of breaking blocks to remove them. To mine a block, point it and hold down the left mouse button until it breaks.=
Blocks require a mining tool to be mined. Different blocks are mined by different mining tools, and some blocks can not be mined by any tool. Blocks vary in hardness and tools vary in strength. Mining tools will wear off over time. The mining time and the tool wear depend on the block and the mining tool. The fastest way to find out how efficient your mining tools are is by just trying them out on various blocks. Any items you gather by mining will drop on the ground, ready to be collected.=
After mining, a block may leave a “drop” behind. This is a number of items you get after mining. Most commonly, you will get the block itself. There are other possibilities for a drop which depends on the block type. The following drops are possible:=
• Always drops itself (the usual case)=
• Always drops the same items=
• Drops items based on probability=
• Drops nothing=
Building=
Almost all blocks can be built (or placed). Building is very simple and has no delay.=
To build your wielded block, point at a block in the world and right-click. If this is not possible because the pointed block has a special right-click action, hold down the sneak key before right-clicking.=
Blocks can almost always be built at pointable blocks. One exception are blocks attached to the floor; these can only be built on the floor.=
Normally, blocks are built in front of the pointed side of the pointed block. A few blocks are different: When you try to build at them, they are replaced.=
Liquids=
Liquids are special dynamic blocks. Liquids like to spread and flow to their surrounding blocks. Players can swim and drown in them.=
Liquids usually come in two forms: In source form (S) and in flowing form (F).=
Liquid sources have the shape of a full cube. A liquid source will generate flowing liquids around it from time to time, and, if the liquid is renewable, it also generates liquid sources. A liquid source can sustain itself. As long it is left alone, a liquid source will normally keep its place and does not drain out.=
Flowing liquids take a sloped form. Flowing liquids spread around the world until they drain. A flowing liquid can not sustain itself and always comes from a liquid source, either directly or indirectly. Without a liquid source, a flowing liquid will eventually drain out and disappear.=
All liquids share the following properties:=
• All properties of blocks (including drowning damage)=
• Renewability: Renewable liquids can create new sources=
• Flowing range: How many flowing liquids are created at maximum per liquid source, it determines how far the liquid will spread. Possible are ranges from 0 to 8. At 0, no flowing liquids will be created. Image 5 shows a liquid of flowing range 2=
• Viscosity: How slow players move through it and how slow the liquid spreads=
Renewable liquids create new liquid sources at open spaces (image 2). A new liquid source is created when:=
• Two renewable liquid blocks of the same type touch each other diagonally=
• These blocks are also on the same height=
• One of the two “corners” is open space which allows liquids to flow in=
When those criteria are met, the open space is filled with a new liquid source of the same type (image 3).=
Swimming in a liquid is fairly straightforward: The usual direction keys for basic movement, the jump key for rising and the sneak key for sinking.=
The physics for swimming and diving in a liquid are:=
• The higher the viscosity, the slower you move=
• If you rest, you'll slowly sink=
• There is no fall damage for falling into a liquid as such=
• If you fall into a liquid, you will be slowed down on impact (but don't stop instantly). Your impact depth is determined by your speed and the liquid viscosity. For a safe high drop into a liquid, make sure there is enough liquid above the ground, otherwise you might hit the ground and take fall damage=
Liquids are often not pointable. But some special items are able to point all liquids.=
Crafting=
Crafting is the task of combining several items to form a new item.=
To craft something, you need one or more items, a crafting grid (C) and a crafting recipe. A crafting grid is like a normal inventory which can also be used for crafting. Items need to be put in a certain pattern into the crafting grid. Next to the crafting grid is an output slot (O). Here the result will appear when you placed items correctly. This is just a preview, not the actual item. Crafting grids can come in different sizes which limits the possible recipes you can craft.=
To complete the craft, take the result item from the output slot, which will consume items from the crafting grid and creates a new item. It is not possible to place items into the output slot.=
A description on how to craft an item is called a “crafting recipe”. You need this knowledge to craft. There are multiple ways to learn crafting recipes. One way is by using a crafting guide, which contains a list of available crafting recipes. Some games provide crafting guides. There are also some mods which you can download online for installing a crafting guide. Another way is by reading the online manual of the game (if one is available).=
Crafting recipes consist of at least one input item and exactly one stack of output items. When performing a single craft, it will consume exactly one item from each stack of the crafting grid, unless the crafting recipe defines replacements.=
There are multiple types of crafting recipes:=
• Shaped (image 2): Items need to be placed in a particular shape=
• Shapeless (images 3 and 4): Items need to be placed somewhere in input (both images show the same recipe)=
• Cooking: Explained in “Basics > Cooking”=
• Repairing (image 5): Place two damaged tools into the crafting grid anywhere to get a tool which is repaired by 5%=
In some crafting recipes, some input items do not need to be a concrete item, instead they need to be a member of a group (see “Basics > Groups”). These recipes offer a bit more freedom in the input items. Images 6-8 show the same group-based recipe. Here, 8 items of the “stone” group are required, which is true for all of the shown items.=
Rarely, crafting recipes have replacements. This means, whenever you perform a craft, some items in the crafting grid will not be consumed, but instead will be replaced by another item.=
Cooking=
Cooking (or smelting) is a form of crafting which does not involve a crafting grid. Cooking is done with a special block (like a furnace), an cookable item, a fuel item and time in order to yield a new item.=
Each fuel item has a burning time. This is the time a single item of the fuel keeps a furnace burning.=
Each cookable item requires time to be cooked. This time is specific to the item type and the item must be “on fire” for the whole cooking time to actually yield the result.=
Hotbar=
At the bottom of the screen you see some squares. This is called the “hotbar”. The hotbar allows you to quickly access the first items from your player inventory.=
You can change the selected item with the mouse wheel or the keyboard.=
• Select previous item in hotbar: [Mouse wheel up] or [B]=
• Select next item in hotbar: [Mouse wheel down] or [N]=
• Select item in hotbar directly: [1]-[9]=
The selected item is also your wielded item.=
Minimap=
If you have a map item in any of your hotbar slots, you can use the minimap.=
Press [F9] to make a minimap appear on the top right. The minimap helps you to find your way around the world. Press it again to select different minimap modes and zoom levels. The minimap also shows the positions of other players.=
There are 2 minimap modes and 3 zoom levels.=
Surface mode (image 1) is a top-down view of the world, roughly resembling the colors of the blocks this world is made of. It only shows the topmost blocks, everything below is hidden, like a satellite photo. Surface mode is useful if you got lost.=
Radar mode (image 2) is more complicated. It displays the “denseness” of the area around you and changes with your height. Roughly, the more green an area is, the less “dense” it is. Black areas have many blocks. Use the radar to find caverns, hidden areas, walls and more. The rectangular shapes in image 2 clearly expose the position of a dungeon.=
There are also two different rotation modes. In “square mode”, the rotation of the minimap is fixed. If you press [Shift]+[F9] to switch to “circle mode”, the minimap will instead rotate with your looking direction, so “up” is always your looking direction.=
In some games, the minimap may be disabled.=
• Toggle minimap mode: [F9]=
• Toggle minimap rotation mode: [Shift]+[F9]=
Inventory=
Inventories are used to store item stacks. There are other uses, such as crafting. An inventory consists of a rectangular grid of item slots. Each item slot can either be empty or hold one item stack. Item stacks can be moved freely between most slots.=
You have your own inventory which is called your “player inventory”, you can open it with the inventory key (default: [I]). The first inventory slots are also used as slots in your hotbar.=
Blocks can also have their own inventory, e.g. chests and furnaces.=
Inventory controls:=
Taking: You can take items from an occupied slot if the cursor holds nothing.=
• Left click: take entire item stack=
• Right click: take half from the item stack (rounded up)=
• Middle click: take 10 items from the item stack=
• Mouse wheel down: take 1 item from the item stack=
Putting: You can put items onto a slot if the cursor holds 1 or more items and the slot is either empty or contains an item stack of the same item type.=
• Left click: put entire item stack=
• Right click: put 1 item of the item stack=
• Right click or mouse wheel up: put 1 item of the item stack=
• Middle click: put 10 items of the item stack=
Exchanging: You can exchange items if the cursor holds 1 or more items and the destination slot is occupied by a different item type.=
• Click: exchange item stacks=
Throwing away: If you hold an item stack and click with it somewhere outside the menu, the item stack gets thrown away into the environment.=
Quick transfer: You can quickly transfer an item stack to/from the player inventory to/from another item's inventory slot like a furnace, chest, or any other item with an inventory slot when that item's inventory is accessed. The target inventory is generally the most relevant inventory in this context.=
• Sneak+Left click: Automatically transfer item stack=
Online help=
You may want to check out these online resources related to MineClone 2.=
MineClone 2 download and forum discussion: <https://forum.minetest.net/viewtopic.php?f@=50&t@=16407>=
Here you find the most recent version of MineClone 2 and can discuss it.=
Bug tracker: <https://github.com/Wuzzy2/MineClone2-Bugs>=
Report bugs here.=
Minetest links:=
You may want to check out these online resources related to Minetest:=
Official homepage of Minetest: <https://minetest.net/>=
The main place to find the most recent version of Minetest, the engine used by MineClone 2.=
The main place to find the most recent version of Minetest.=
Community wiki: <https://wiki.minetest.net/>=
A community-based documentation website for Minetest. Anyone with an account can edit it! It also features a documentation of Minetest Game.=
Minetest forums: <https://forums.minetest.net/>=
A web-based discussion platform where you can discuss everything related to Minetest. This is also a place where player-made mods and games are published and discussed. The discussions are mainly in English, but there is also space for discussion in other languages.=
Chat: <irc://irc.freenode.net#minetest>=
A generic Internet Relay Chat channel for everything related to Minetest where people can meet to discuss in real-time. If you do not understand IRC, see the Community Wiki for help.=
Groups=
Items, players and objects (animate and inanimate) can be members of any number of groups. Groups serve multiple purposes:=
• Crafting recipes: Slots in a crafting recipe may not require a specific item, but instead an item which is a member of a particular group, or multiple groups=
• Digging times: Diggable blocks belong to groups which are used to determine digging times. Mining tools are capable of digging blocks belonging to certain groups=
• Block behavior: Blocks may show a special behaviour and interact with other blocks when they belong to a particular group=
• Damage and armor: Objects and players have armor groups, weapons have damage groups. These groups determine damage. See also: “Basics > Weapons”=
• Other uses=
In the item help, many important groups are usually mentioned and explained.=
Glossary=
This is a list of commonly used terms:=
Controls:=
• Wielding: Holding an item in hand=
• Pointing: Looking with the crosshair at something in range=
• Dropping: Throwing an item or item stack to the ground=
• Punching: Attacking with left-click, is also used on blocks=
• Sneaking: Walking slowly while (usually) avoiding to fall over edges=
• Climbing: Moving up or down a climbable block=
Blocks:=
• Block: Cubes that the worlds are made of=
• Mining/digging: Using a mining tool to break a block=
• Building/placing: Putting a block somewhere=
• Drop: Items you get after mining a block=
• Using a block: Right-clicking a block to access its special function=
Items:=
• Item: A single thing that players can possess=
• Item stack: A collection of items of the same kind=
• Maximum stack size: Maximum amount of items in an item stack=
• Slot / inventory slot: Can hold one item stack=
• Inventory: Provides several inventory slots for storage=
• Player inventory: The main inventory of a player=
• Tool: An item which you can use to do special things with when wielding=
• Range: How far away things can be to be pointed by an item=
• Mining tool: A tool which allows to break blocks=
• Craftitem: An item which is (primarily or only) used for crafting=
Gameplay:=
• “heart”: A single health symbol, indicates 2 HP=
• “bubble”: A single breath symbol, indicates 1 BP=
• HP: Hit point (equals half 1 “heart”)=
• BP: Breath point, indicates breath when diving=
• Mob: Computer-controlled enemy=
• Crafting: Combining multiple items to create new ones=
• Crafting guide: A helper which shows available crafting recipes=
• Spawning: Appearing in the world=
• Respawning: Appearing again in the world after death=
• Group: Puts similar things together, often affects gameplay=
• noclip: Allows to fly through walls=
Interface=
• Hotbar: Inventory slots at the bottom=
• Statbar: Indicator made out of half-symbols, used for health and breath=
• Minimap: The map or radar at the top right=
• Crosshair: Seen in the middle, used to point at things=
Online multiplayer:=
• PvP: Player vs Player. If active, players can deal damage to each other=
• Griefing: Destroying the buildings of other players against their will=
• Protection: Mechanism to own areas of the world, which only allows the owners to modify blocks inside=
Technical terms:=
• Minetest: This game engine=
• MineClone 2: What you play right now=
• Minetest Game: A game for Minetest by the Minetest developers=
• Game: A complete playing experience to be used in Minetest; such as a game or sandbox or similar=
• Mod: A single subsystem which adds or modifies functionality; is the basic building block of games and can be used to further enhance or modify them=
• Privilege: Allows a player to do something=
• Node: Other word for “block”=
Settings=
There is a large variety of settings to configure Minetest. Pretty much every aspect can be changed that way.=
These are a few of the most important gameplay settings:=
• Damage enabled (enable_damage): Enables the health and breath attributes for all players. If disabled, players are immortal=
• Creative Mode (creative_mode): Enables sandbox-style gameplay focusing on creativity rather than a challenging gameplay. The meaning depends on the game; usual changes are: Reduced dig times, easy access to almost all items, tools never wear off, etc.=
• PvP (enable_pvp): Short for “Player vs Player”. If enabled, players can deal damage to each other=
For a full list of all available settings, use the “All Settings” dialog in the main menu.=
Movement modes=
You can enable some special movement modes that change how you move.=
Pitch movement mode:=
• Description: If this mode is activated, the movement keys will move you relative to your current view pitch (vertical look angle) when you're in a liquid or in fly mode.=
• Default key: [L]=
• No privilege required=
Fast mode:=
• Description: Allows you to move much faster. Hold down the the “Use” key [E] to move faster. In the client configuration, you can further customize fast mode.=
• Default key: [J]=
• Required privilege: fast=
Fly mode:=
• Description: Gravity doesn't affect you and you can move freely in all directions. Use the jump key to rise and the sneak key to sink.=
• Default key: [K]=
• Required privilege: fly=
Noclip mode:=
• Description: Allows you to move through walls. Only works when fly mode is enabled, too.=
• Default key: [H]=
• Required privilege: noclip=
Console=
With [F10] you can open and close the console. The main use of the console is to show the chat log and enter chat messages or server commands.=
Using the chat or server command key also opens the console, but it is smaller and will be closed after you sent a message.=
Use the chat to communicate with other players. This requires you to have the “shout” privilege.=
Just type in the message and hit [Enter]. Public chat messages can not begin with “/”.=
You can send private messages: Say “/msg <player> <message>” in chat to send “<message>” which can only be seen by <player>.=
There are some special controls for the console:=
• [F10] Open/close console=
• [Enter]: Send message or command=
• [Tab]: Try to auto-complete a partially-entered player name=
• [Ctrl]+[Left]: Move cursor to the beginning of the previous word=
• [Ctrl]+[Right]: Move cursor to the beginning of the next word=
• [Ctrl]+[Backspace]: Delete previous word=
• [Ctrl]+[Delete]: Delete next word=
• [Ctrl]+[U]: Delete all text before the cursor=
• [Ctrl]+[K]: Delete all text after the cursor=
• [Page up]: Scroll up=
• [Page down]: Scroll down=
There is also an input history. Minetest saves your previous console inputs which you can quickly access later:=
• [Up]: Go to previous entry in history=
• [Down]: Go to next entry in history=
Server commands=
Server commands (also called “chat commands”) are little helpers for advanced users. You don't need to use these commands when playing. But they might come in handy to perform some more technical tasks. Server commands work both in multi-player and single-player mode.=
Server commands can be entered by players using the chat to perform a special server action. There are a few commands which can be issued by everyone, but some commands only work if you have certain privileges granted on the server. There is a small set of basic commands which are always available, other commands can be added by mods.=
To issue a command, simply type it like a chat message or press Minetest's command key (default: [/]). All commands have to begin with “/”, for example “/mods”. The Minetest command key does the same as the chat key, except that the slash is already entered.=
Commands may or may not give a response in the chat log, but errors will generally be shown in the chat. Try it for yourselves: Close this window and type in the “/mods” command. This will give you the list of available mods on this server.=
“/help all” is a very important command: You get a list of all available commands on the server, a short explanation and the allowed parameters. This command is also important because the available commands often differ per server.=
Commands are followed by zero or more parameters.=
In the command reference, you see some placeholders which you need to replace with an actual value. Here's an explanation:=
• Text in greater-than and lower-than signs (e.g. “<param>”): Placeholder for a parameter=
• Anything in square brackets (e.g. “[text]”) is optional and can be omitted=
• Pipe or slash (e.g. “text1 | text2 | text3”): Alternation. One of multiple texts must be used (e.g. “text2”)=
• Parenthesis: (e.g. “(word1 word2) | word3”): Groups multiple words together, used for alternations=
• Everything else is to be read as literal text=
Here are some examples to illustrate the command syntax:=
• /mods: No parameters. Just enter “/mods”=
• /me <action>: 1 parameter. You have to enter “/me ” followed by any text, e.g. “/me orders pizza”=
• /give <name> <ItemString>: Two parameters. Example: “/give Player default:apple”=
• /help [all|privs|<cmd>]: Valid inputs are “/help”, “/help all”, “/help privs”, or “/help ” followed by a command name, like “/help time”=
• /spawnentity <EntityName> [<X>,<Y>,<Z>]: Valid inputs include “/spawnentity boats:boat” and “/spawnentity boats:boat 0,0,0”=
Some final remarks:=
• For /give and /giveme, you need an itemstring. This is an internally used unique item identifier which you may find in the item help if you have the “give” or “debug” privilege=
• For /spawnentity you need an entity name, which is another identifier=
Privileges=
Each player has a set of privileges, which differs from server to server. Your privileges determine what you can and can't do. Privileges can be granted and revoked from other players by any player who has the privilege called “privs”.=
On a multiplayer server with the default configuration, new players start with the privileges called “interact” and “shout”. The “interact” privilege is required for the most basic gameplay actions such as building, mining, using, etc. The “shout” privilege allows to chat.=
There is a small set of core privileges which you'll find on every server, other privileges might be added by mods.=
To view your own privileges, issue the server command “/privs”.=
Here are a few basic privilege-related commands:=
• /privs: Lists your privileges=
• /privs <player>: Lists the privileges of <player>=
• /help privs: Shows a list and description about all privileges=
Players with the “privs” privilege can modify privileges at will:=
• /grant <player> <privilege>: Grant <privilege> to <player>=
• /revoke <player> <privilege>: Revoke <privilege> from <player>=
In single-player mode, you can use “/grantme all” to unlock all abilities.=
Light=
As the world is entirely block-based, so is the light in the world. Each block has its own brightness. The brightness of a block is expressed in a “light level” which ranges from 0 (total darkness) to 15 (as bright as the sun).=
There are two types of light: Sunlight and artificial light.=
Artificial light is emitted by luminous blocks. Artificial light has a light level from 1-14.=
Sunlight is the brightest light and always goes perfectly straight down from the sky at each time of the day. At night, the sunlight will become moonlight instead, which still provides a small amount of light. The light level of sunlight is 15.=
Blocks have 3 levels of transparency:=
• Transparent: Sunlight goes through limitless, artificial light goes through with losses=
• Semi-transparent: Sunlight and artificial light go through with losses=
• Opaque: No light passes through=
Artificial light will lose one level of brightness for each transparent or semi-transparent block it passes through, until only darkness remains (image 1).=
Sunlight will preserve its brightness as long it only passes fully transparent blocks. When it passes through a semi-transparent block, it turns to artificial light. Image 2 shows the difference.=
Note that “transparency” here only means that the block is able to carry brightness from its neighboring blocks. It is possible for a block to be transparent to light but you can't see trough the other side.=
Coordinates=
The world is a large cube. And because of this, a position in the world can be easily expressed with Cartesian coordinates. That is, for each position in the world, there are 3 values X, Y and Z.=
Like this: (5, 45, -12)=
This refers to the position where X@=5, Y@=45 and Z@=-12. The 3 letters are called “axes”: Y is for the height. X and Z are for the horizontal position.=
The values for X, Y and Z work like this:=
• If you go up, Y increases=
• If you go down, Y decreases=
• If you follow the sun, X increases=
• If you go to the reverse direction, X decreases=
• Follow the sun, then go right: Z increases=
• Follow the sun, then go left: Z decreases=
• The side length of a full cube is 1=
You can view your current position in the debug screen (open with [F5]).=
# MCL2 extensions
Creative Mode=
Enabling Creative Mode in MineClone 2 applies the following changes:=
• You keep the things you've placed=
• Creative inventory is available to obtain most items easily=
• Hand breaks all default blocks instantly=
• Greatly increased hand pointing range=
• Mined blocks don't drop items=
• Items don't get used up=
• Tools don't wear off=
• You can eat food whenever you want=
• You can always use the minimap (including radar mode)=
Damage is not affected by Creative Mode, it needs to be disabled separately.=
Mobs=
Mobs are the living beings in the world. This includes animals and monsters.=
Mobs appear randomly throughout the world. This is called “spawning”. Each mob kind appears on particular block types at a given light level. The height also plays a role. Peaceful mobs tend to spawn at daylight while hostile ones prefer darkness. Most mobs can spawn on any solid block but some mobs only spawn on particular blocks (like grass blocks).=
Like players, mobs have hit points and sometimes armor points, too (which means you need better weapons to deal any damage at all). Also like players, hostile mobs can attack directly or at a distance. Mobs may drop random items after they die.=
Most animals roam the world aimlessly while most hostile mobs hunt players. Animals can be fed, tamed and bred.=
Animals=
Animals are peaceful beings which roam the world aimlessly. You can feed, tame and breed them.=
Feeding:=
Each animal has its own taste for food and doesn't just accept any food. To feed, hold an item in your hand and rightclick the animal.=
Animals are attraced to the food they like and follow you as long you hold the food item in hand.=
Feeding an animal has three uses: Taming, healing and breeding.=
Feeding heals animals instantly, depending on the quality of the food item.=
Taming:=
A few animals can be tamed. You can generally do more things with tamed animals and use other items on them. For example, tame horses can be saddled and tame wolves fight on your side.=
Breeding:=
When you have fed an animal up to its maximum health, then feed it again, you will activate “Love Mode” and many hearts appear around the animal.=
Two animals of the same species will start to breed if they are in Love Mode and close to each other. Soon a baby animal will pop up.=
Baby animals:=
Baby animals are just like their adult couterparts, but they can't be tamed or bred and don't drop anything when they die. They grow to adults after a short time. When fed, they grow to adults faster.=
Hunger=
Hunger affects your health and your ability to sprint. Hunger is not in effect when damage is disabled.=
Core hunger rules:=
• You start with 20/20 hunger points (more points @= less hungry)=
• Actions like combat, jumping, sprinting, etc. decrease hunger points=
• Food restores hunger points=
• If your hunger bar decreases, you're hungry=
• At 18-20 hunger points, you regenerate 1 HP every 4 seconds=
• At 6 hunger points or less, you can't sprint=
• At 0 hunger points, you lose 1 HP every 4 seconds (down to 1 HP)=
• Poisonous food decreases your health=
Details:=
You have 0-20 hunger points, indicated by 20 drumstick half-icons above the hotbar. You also have an invisible attribute: Saturation.=
Hunger points reflect how full you are while saturation points reflect how long it takes until you're hungry again.=
Each food item increases both your hunger level as well your saturation.=
Food with a high saturation boost has the advantage that it will take longer until you get hungry again.=
A few food items might induce food poisoning by chance. When you're poisoned, the health and hunger symbols turn sickly green. Food poisoning drains your health by 1 HP per second, down to 1 HP. Food poisoning also drains your saturation. Food poisoning goes away after a while or when you drink milk.=
You start with 5 saturation points. The maximum saturation is equal to your current hunger level. So with 20 hunger points your maximum saturation is 20. What this means is that food items which restore many saturation points are more effective the more hunger points you have. This is because at low hunger levels, a lot of the saturation boost will be lost due to the low saturation cap.=
If your saturation reaches 0, you're hungry and start to lose hunger points. Whenever you see the hunger bar decrease, it is a good time to eat.=
Saturation decreases by doing things which exhaust you (highest exhaustion first):=
• Regenerating 1 HP=
• Suffering food poisoning=
• Sprint-jumping=
• Sprinting=
• Attacking=
• Taking damage=
• Swimming=
• Jumping=
• Mining a block=
Other actions, like walking, do not exaust you.=
If you have a map item in any of your hotbar slots, you can use the minimap.=

View File

@ -305,7 +305,7 @@ function awards.unlock(name, award)
local one = player:hud_add({
hud_elem_type = "image",
name = "award_bg",
scale = {x = 1, y = 1},
scale = {x = 1.25, y = 1},
text = background,
position = {x = 0.5, y = 0},
offset = {x = 0, y = 138},
@ -329,7 +329,7 @@ function awards.unlock(name, award)
scale = {x = 100, y = 20},
text = hud_announce,
position = {x = 0.5, y = 0},
offset = {x = 0, y = 40},
offset = {x = 30, y = 40},
alignment = {x = 0, y = -1},
z_index = 102,
})
@ -340,7 +340,7 @@ function awards.unlock(name, award)
scale = {x = 100, y = 20},
text = title,
position = {x = 0.5, y = 0},
offset = {x = 30, y = 100},
offset = {x = 35, y = 100},
alignment = {x = 0, y = -1},
z_index = 102,
})
@ -355,7 +355,7 @@ function awards.unlock(name, award)
number = 2,
text = icon,
position = {x = 0.5, y = 0},
offset = {x = -110, y = 62},
offset = {x = -138, y = 62},
alignment = {x = 0, y = 0},
direction = 0,
z_index = 102,

View File

@ -337,7 +337,7 @@ awards.register_achievement("mcl:fishyBusiness", {
-- Triggered in mcl_compass
awards.register_achievement("mcl:countryLode", {
title = S("Country Lode,\nTake Me Home"),
title = S("Country Lode, Take Me Home"),
description = S("Use a compass on a Lodestone."),
icon = "lodestone_side4.png",
type = "Advancement",

View File

@ -67,7 +67,7 @@ Withering Heights=Les Witherables
Summon the wither from the dead.=Invoquez le Wither d'entre les morts.
Fishy Business=Merci pour le poisson
Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=Attrapez un poisson. \nAstuce : attrapez un poisson, saumon, poisson-clown, ou poisson-globe.
Country Lode,@nTake Me Home=Petit Poucet
Country Lode, Take Me Home=Petit Poucet
Use a compass on a Lodestone.=utiliser une boussole sur une magnétite.
Serious Dedication=Sérieux dévouement
Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices.=Utilisez un lingot de netherite pour améliorez une houe, puis réévaluez complètement vos choix de vie.

View File

@ -69,7 +69,7 @@ The Cutest Predator=いちばんカワイイ捕食者
Catch an Axolotl with a bucket!=バケツでウーパールーパーを捕まえよう!
Fishy Business=フィッシー・ビジネス
Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=魚を獲ろう。@nヒントタラ、サケ、クマミ、フグ等を釣ります。
Country Lode,@nTake Me Home=この道ずっとゆけば@n鉱脈につづいてる
Country Lode, Take Me Home=この道ずっとゆけば 鉱脈につづいてる
Use a compass on a Lodestone.=ロードストーンにコンパスを使おう。
Serious Dedication=真摯な取り組み
Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices.=ネザライトインゴットでクワをアップグレードしたら、人生設計の完全な見直しを図ろう。

View File

@ -69,7 +69,7 @@ The Cutest Predator=
Catch an Axolotl with a bucket!
Fishy Business=
Catch a fish.@nHint: Catch a fish, salmon, clownfish, or pufferfish.=
Country Lode,@nTake Me Home=
Country Lode, Take Me Home=
Use a compass on a Lodestone.=
Serious Dedication=
Use a Netherite Ingot to upgrade a hoe, and then completely reevaluate your life choices.=

View File

@ -149,6 +149,11 @@ mcl_death_messages = {
plain = "@1 went off with a bang",
item = "@1 went off with a bang due to a firework fired from @3 by @2", -- order is intentional
},
sweet_berry = {
_translator = S,
plain = "@1 died a sweet death",
assist = "@1 was poked to death by a sweet berry bush whilst trying to escape @2",
},
-- Missing snowballs: The Minecraft wiki mentions them but the MC source code does not.
},
}

View File

@ -0,0 +1,19 @@
# textdomain: mcl_amethyst
Amethyst Cluster=Ametystklynge
Amethyst Cluster is the final growth of amethyst bud.=En ameystklynge er den sidste udvikling af en ametystspire.
Amethyst Shard=Ametystskår
An amethyst shard is a crystalline mineral.=Et ametystskår er et krystallisk mineral.
Block of Amethyst=Blok af ametyst
Budding Amethyst=Spirende ametyst
Calcite=Calcedon
Calcite can be found as part of amethyst geodes.=Calcedon kan findes som en del af krystalhuler med ametyst.
Large Amethyst Bud=Stor ametystknop
Large Amethyst Bud is the third growth of amethyst bud.=En stor ametystknop er den trejde udvikling af en ametystspire.
Medium Amethyst Bud=Mellem ametystknop
Medium Amethyst Bud is the second growth of amethyst bud.=En mellem ametystknop er den anden udvikling af en ametystspire.
Small Amethyst Bud=Lille ametystknop
Small Amethyst Bud is the first growth of amethyst bud.=En lille ametystknop er den første udvikling af en ametystspire.
The Block of Amethyst is a decoration block crafted from amethyst shards.=En blok af ametyst er en udsmykningsblok som kan laves ametystskår.
The Budding Amethyst can grow amethyst=Den spirende ametyst kan gro ametyst
Tinted Glass=Farvet glas
Tinted Glass is a type of glass which blocks lights while it is visually transparent.=Farvet glas er en glastype som er gennemsigtig, men lukker lys ude.

View File

@ -0,0 +1,16 @@
# textdomain: mcl_anvils
Set Name=Navngiv
Repair and Name=Reparér og navngiv
Inventory=Oppakning
Anvil=Ambolt
The anvil allows you to repair tools and armor, and to give names to items. It has a limited durability, however. Don't let it fall on your head, it could be quite painful!=Ambolten gør dig i stand til at reparere værktøj og rustninger, og til at navngive genstande. Den har dog begrænset holdbarhed. Lad den ikke falde ned i hovedet på dig, det kunne gøre meget ondt!
To use an anvil, rightclick it. An anvil has 2 input slots (on the left) and one output slot.=For at bruge ambolten skal du højre-klikke på den. En ambolt har to indgangspladser (til venstre), og én udgangsplads.
To rename items, put an item stack in one of the item slots while keeping the other input slot empty. Type in a name, hit enter or “Set Name”, then take the renamed item from the output slot.=For at omdøbe en genstande skal du putte dem i den ene indgangsplads og lade den anden indgangsplads være tom. Skriv et navn, tryk på enter eller "Giv navn", og tag så den omdøbte genstand fra udgangspladsen.
There are two possibilities to repair tools (and armor):=Der er to muligheder for at reparere værktøj (og rustninger)
• Tool + Tool: Place two tools of the same type in the input slots. The “health” of the repaired tool is the sum of the “health” of both input tools, plus a 12% bonus.=• Værktøj + Værktøj: Placér to stykker værktøj af samme type i indgangspladserne. Holbarheden af det reparerede stykke værktøj er summen af holdbarheden på begge stykker værktøj plus 12% bonus.
• Tool + Material: Some tools can also be repaired by combining them with an item that it's made of. For example, iron pickaxes can be repaired with iron ingots. This repairs the tool by 25%.=• Værktøj + Materiale: Noget værktøj kan også repareres ved at kombinere dem med en genstand de er lavet af. For eksempel kan en jernhakke repareres med jernbarre. Dette reparerer værktøjet med 25%.
Armor counts as a tool. It is possible to repair and rename a tool in a single step.=Rustninger tæller som værktøj. Det er muligt at reparere og omdøbe værktøj i ét enkelt trin.
The anvil has limited durability and 3 damage levels: undamaged, slightly damaged and very damaged. Each time you repair or rename something, there is a 12% chance the anvil gets damaged. Anvils also have a chance of being damaged when they fall by more than 1 block. If a very damaged anvil is damaged again, it is destroyed.=Ambolten har en begrænset holdbarhed og 3 skadeniveauer: Ubeskadiget, let beskadiget og meget beskadiget. Hver gang du reparerer eller omdøber noget er der en 12% chance for, at ambolten bliver beskadiget. Ambolte har også en risiko for at blive beskadiget når de falder mere end én blok ned. Hvis en beskadiget ambolt beskadiges igen bliver den ødelagt.
Slightly Damaged Anvil=Let beskadiget ambolt
Very Damaged Anvil=Meget beskadiget ambolt
Repair and rename items=Reparér og omdøb genstande

View File

@ -0,0 +1,48 @@
# textdomain: mcl_armor
This is a piece of equippable armor which reduces the amount of damage you receive.=Dette er et stykke rustning du kan tage på for at reducere den mængde du tager.
To equip it, put it on the corresponding armor slot in your inventory menu.=For at tage den på, skal du putte den i den tilsvarende rustningsplads i din oppakningsmenu.
Leather Cap=Læderhat
Iron Helmet=Jernhjelm
Golden Helmet=Guldhjelm
Diamond Helmet=Diamanthjelm
Chain Helmet=Brynjehjelm
Netherite Helmet=Netherritehjelm
Leather Tunic=Lædertunika
Iron Chestplate=Jernbrystplade
Golden Chestplate=Guldbrystplade
Diamond Chestplate=Diamantbrystplade
Chain Chestplate=Brynjeskjorte
Netherite Chestplate=Netheritebrystplade
Leather Pants=Læderbukser
Iron Leggings=Jernbenplader
Golden Leggings=Guldbenplader
Diamond Leggings=Diamantbenplader
Chain Leggings=Brynjebukser
Netherite Leggings=Netheritebenplader
Leather Boots=Læderstøvler
Iron Boots=Jernstøvler
Golden Boots=Guldstøvler
Diamond Boots=Diamantstøvler
Chain Boots=Brynjestøvler
Netherite Boots=Netheritestøvler
Elytra=Elytra
#Translations of enchantements
Increases underwater mining speed.=Øger udvindingshastigheden under vand.
Blast Protection=Eksplosionsbeskyttelse
Reduces explosion damage and knockback.=Reducerer eksplosionsskade og -tilbageslag.
Curse of Binding=Bindende forbandelse.
Item cannot be removed from armor slots except due to death, breaking or in Creative Mode.=Objektet kan ikke fjernes fra rustninspladser undtagen ved død, hvis den går i stykker ikke i kreativ tilstand.
Feather Falling=Fjerfald
Reduces fall damage.=Reduerer faldskade.
Fire Protection=Ildbeskyttelse
Reduces fire damage.=Reducerer ildskade.
Shooting consumes no regular arrows.=Det bruger ingen normale pile at skyde.
Shoot 3 arrows at the cost of one.=Skyd 3 pile for én pils pris.
Projectile Protection=Projektilbeskyttelse
Reduces projectile damage.=Reducerer projektilskade
Protection=Beskyttelse
Reduces most types of damage by 4% for each level.=Reducerer det fleste skadestyper med 4% for hvert level.
Thorns=Torne
Reflects some of the damage taken when hit, at the cost of reducing durability with each proc.=Reflekterer skade ved træfning, men koster holdbarhed ved hver brug.
Aqua Affinity=Vandaffinitet

View File

@ -0,0 +1,5 @@
# textdomain: mcl_armor_stand
Armor Stand=Rustningsstativ
An armor stand is a decorative object which can display different pieces of armor. Anything which players can wear as armor can also be put on an armor stand.=Et rustningsstativ er en udsmykningsgenstand som kan fremvise forskellige rustninger. Alt hvad spillere kan bære som rusning kan sættes på rustningsstativet.
Just place an armor item on the armor stand. To take the top piece of armor from the armor stand, select your hand and use the place key on the armor stand.=Placér blot et rustningsstykke på rustningsstativet. For at take den øverste rustningsstykke skal du vælge din hånd og bruge placér knappen på rustningsstativet.
Displays pieces of armor=Fremviser rustningsstykker.

View File

@ -0,0 +1,36 @@
# textdomain: mcl_bamboo
### init.lua ###
A bamboo button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second.=En bambusknap er en rødstenskomponent lavet af sten som giver rødstensenergi når den aktiveres. Når den aktiveres forsyner den tilstøende rødstenskomponenter i 1 sekund.
A wooden pressure plate is a redstone component which supplies its surrounding blocks with redstone power while any movable object (including dropped items, players and mobs) rests on top of it.=En trætrykplade er en rødstenskomponent som forsyner omkringliggende blokke med rødstensenergi når et bevægeligt objekt (inklusiv tabte genstande, spillere og monstre) er ovenpå den.
Bamboo=Bambus
Bamboo Button=Bambusknap
Bamboo Door.=Bambusdør
Bamboo Fence=Bambushegn
Bamboo Fence Gate=Bambushegnslåge
Bamboo Plank=Bambusplanke
Bamboo Plank Slab=Bambusplankeplade
Bamboo Plank Stair=Bambusplanketrappe
Bamboo Pressure Plate=Bambustrykplade
Bamboo Sign=Bambusskilt
Bamboo Slab=Bambusplade
Bamboo Stair=Bambustrappe
Bamboo Trapdoor.=Bambusfaldlem
Double Bamboo Plank Slab=Dobbelbambusplanke
Double Bamboo Slab=Dobbelbambusplade
Double Stripped Bamboo Slab=Afbarket dobbelbambus
Nether Brick Fence=Netherstenshegn
Scaffolding=Stillads
Scaffolding (horizontal)=Stillads (horisontal)
Scaffolding block used to climb up or out across areas.=Stilladsblok som bruges til at kravle op ad eller på tværs af områder
Stripped Bamboo Slab=Afbarket bambusplade
Stripped Bamboo Stair=Afbarket bambustrappe
To open or close the trapdoor, rightclick it or send a redstone signal to it.=Højre-klik eller send rødstensenergi til en faldlem for at åbne eller lukke den,
Wooden trapdoors are horizontal barriers which can be opened and closed by hand or a redstone signal. They occupy the upper or lower part of a block, depending on how they have been placed. When open, they can be climbed like a ladder.=Træfaldlemme er horisontale barrierer som kan åbnes og lukkes med håndkraft eller med rødstensenergi. De kan udgøre den øverste eller den nederste del af en blok afhængigt af hvordan de placeres. Når de er åbne, kan man bruge dem ligesom en stige.

View File

@ -0,0 +1,77 @@
# textdomain: mcl_banners
White Banner=Hvidt vanner
White=Hvid
Grey Banner=Gråt banner
Grey=Grå
Light Grey Banner=Lysegråt banner
Light Grey=Lysegrå
Black Banner=Sort banner
Black=Sort
Red Banner=Rødt banner
Red=Rød
Yellow Banner=Gult banner
Yellow=Gul
Green Banner=Grønt banner
Green=Grøn
Cyan Banner=Cyanblåt banner
Cyan=Cyanblå
Blue Banner=Blåt banner
Blue=Blå
Magenta Banner=Magenta banner
Magenta=Magenta
Orange Banner=Orange banner
Orange=Orange
Purple Banner=Lilla banner
Violet=Lilla
Brown Banner=Brunt banner
Brown=Brund
Pink Banner=Lyserødt banner
Pink=Lyserøde
Lime Banner=Limegrønt banner
Lime=Limegrøn
Light Blue Banner=Lyseblåt banner
Light Blue=Lyseblå
Banners are tall colorful decorative blocks. They can be placed on the floor and at walls. Banners can be emblazoned with a variety of patterns using a lot of dye in crafting.=Bannere er høje, farverige udsmykningsblokke. De kan placeres på gulve og vægge. Bannere kan præges med et væld af mønste ved at bruge meget farvestof ved produktion.
Use crafting to draw a pattern on top of the banner. Emblazoned banners can be emblazoned again to combine various patterns. You can draw up to 12 layers on a banner that way. If the banner includes a gradient, only 3 layers are possible.=Brug håndværk til at tegne et mønster på banneret. Prægede bannere kan præges igen for at skabe forskellige mønstre. Du kan lave op til 12 lag ovenpå hinanden. Hvis banneret har en gradient, kan du kun lave 3 lag.
You can copy the pattern of a banner by placing two banners of the same color in the crafting grid—one needs to be emblazoned, the other one must be clean. Finally, you can use a banner on a cauldron with water to wash off its top-most layer.=Du kan kopiere menteret på et banner ved at placere to bannere i den samme farve i håndværksgitteret. Det ene skal være præget, det andet rent. Du kan også bruge et banner på en keddel med vand for at vaske det øverste lag af.
@1 Bordure=@1 kantbånd
@1 Bricks=@1 mursten
@1 Roundel=@1 rundstok
@1 Creeper Charge=@1 creeper
@1 Saltire=@1 saltire
@1 Bordure Indented=@1 kantbånd med savtakker
@1 Per Bend Inverted=@1 nederste venstre diagnoal halvfarvning
@1 Per Bend Sinister Inverted=@1 nederste højre diagonal halvfarvning
@1 Per Bend=@1 øverste højre diagonal halvfarvning
@1 Per Bend Sinister=@1 øverste venstre diagonal halvfarvning
@1 Flower Charge=@1 blomst
@1 Gradient=@1 gradvist oppefra
@1 Base Gradient=@1 gradvist nedefra
@1 Per Fess Inverted=@1 nederste halvdel
@1 Per Fess=@1 øverste halvdel
@1 Per Pale=@1 venstre halvdel
@1 Per Pale Inverted=@1 højre halvdel
@1 Thing Charge=Mojang
@1 Lozenge=Rhombe
@1 Skull Charge=@1 dødningehovde
@1 Paly=@1 lodrette striber
@1 Base Dexter Canton=@1 nederste højre hjørne
@1 Base Sinister Canton=@1 nederste venstre hjørne
@1 Chief Dexter Canton=@1 øverste højre hjørne
@1 Chief Sinister Canton=@1 øverste venstre hjørne
@1 Cross=@1 kryds
@1 Base=@1 bundstribe
@1 Pale=@1 lodret centerstribe
@1 Bend Sinister=@1 diagonal stribe fra nederste venstre hjørne
@1 Bend=@1 diagonal stribe fra nederste højre hjørne
@1 Pale Dexter=@1 venstrestribe
@1 Fess=@1 vandret midterstribe
@1 Pale Sinister=@1 højrestribe
@1 Chief=@1 topstribe
@1 Chevron=@1 bundtrekant
@1 Chevron Inverted=@1 toptrekant
@1 Base Indented=@1 savtakker i bunden
@1 Chief Indented=@1 savtakker i toppen
And one additional layer=Og ét yderligere lag
And @1 additional layers=Og @1 yderligere lag
Paintable decoration=Udsmykning som kan males

View File

@ -0,0 +1,5 @@
# textdomain: mcl_barrels
Barrel=Tønde
Barrels are containers which provide 27 inventory slots.=Tønder er beholdere som kan give 27 oppakningspladser.
To access its inventory, rightclick it. When broken, the items will drop out.=For at tilgå dens indhold kan du højre-klikke. Når den ødelægges falder genstandene ud.
27 inventory slots=27 indholdsspladser.

View File

@ -0,0 +1,6 @@
# textdomain: mcl_beacons
Beacon=Magisk fyrtårn
Beacon:=Magisk fyrtårn:
Primary Power:=Primær kraft:
Inventory:=Indhold:

View File

@ -0,0 +1,43 @@
# textdomain: mcl_beds
Beds allow you to sleep at night and make the time pass faster.=Senge giver dig mulighed for at sove om natten, og få tiden til at gå hurtigere.
To use a bed, stand close to it and right-click the bed to sleep in it. Sleeping only works when the sun sets, at night or during a thunderstorm. The bed must also be clear of any danger.=For at lægge dig til at sove i en seng skal du stå tæt på den og højre-klikke. Man kan kun sove når solen går ned, om natten eller i tordenvejr.
You have heard of other worlds in which a bed would set the start point for your next life. But this world is not one of them.=Du har hørt om andre verdener hvor en seng var udgangspunktet for dit næste liv, men denne verden er ikke en af dem.
By using a bed, you set the starting point for your next life. If you die, you will start your next life at this bed, unless it is obstructed or destroyed.=Ved at bruge en sætter du udgangspunktet for dit næste liv. Hvis du dør, vil dit næste liv starte i denne seng, medmindre sengen bliver blokeret eller ødelagt.
In this world, going to bed won't skip the night, but it will skip thunderstorms.=I denne verden, springer det ikke natten over at sove, men det springer tordenvejr over.
Sleeping allows you to skip the night. The night is skipped when all players in this world went to sleep. The night is skipped after sleeping for a few seconds. Thunderstorms can be skipped in the same manner.=Du kan springe natten over ved at sove. Natten bliver sprunget over hvis alle spillere i verdenen sover. Natten bliver sprunget over efter at have sovet i nogle få sekunder. Tordenvejr kan springes over på samme måde.
Bed=Seng
Red Bed=Rød seng
Blue Bed=Blå seng
Cyan Bed=Cyanblå seng
Grey Bed=Grå seng
Light Grey Bed=Lysegrå seng
Black Bed=Sort senge
Yellow Bed=Gul senge
Green Bed=Grøn seng
Magenta Bed=Magenta seng
Orange Bed=Orange seng
Purple Bed=Lilla seng
Brown Bed=Brun seng
Pink Bed=Lyserød seng
Lime Bed=Limegrøn seng
Light Blue Bed=Lyseblå seng
White Bed=Hvid seng
You can't sleep, the bed's too far away!=Du kan ikke gå i seng, sengen er for langt væk!
This bed is already occupied!=Denne seng er optaget!
You have to stop moving before going to bed!=Du skal stå stille før du kan gå i seng.
You can't sleep now, monsters are nearby!=Du kan ikke lægge dig til at sove nu, der er monstre tæt på!
You can't sleep, the bed is obstructed!=Du kan ikke gå i seng, denne seng er blokeret!
It's too dangerous to sleep here!=Det er for farligt at sove her!
New respawn position set! But you can only sleep at night or during a thunderstorm.=Nyt genopståelsespunt sat! Men du kan kun sover om natten eller under et tordenvejr.
You can only sleep at night or during a thunderstorm.=Du kan kun sover om natten eller under et tordenvejr.
New respawn position set!=Nyt genopståelsespunkt sat!
Leave bed=Forlad seng
Abort sleep=Afbryd søvn
Players in bed: @1/@2=@1 af @2 spillere er gået i seng.
Note: Night skip is disabled.=Bemærk: Det er slået fra at springe natten over.
You're sleeping.=Du sover.
You will fall asleep when all players are in bed.=Du falder i søvn når alle andre spillere er gået i seng.
You will fall asleep when @1% of all players are in bed.=Du falder i søvn når @1% af alle spillere er gået i seng.
You're in bed.=Du er gået i seng.
Allows you to sleep=Gør dig i stand til at sove.
Respawn Anchor=Genopståelsesanker

View File

@ -0,0 +1,4 @@
Beehive=Bistade
Artificial bee nest.=Kunstigt bibo.
Bee Nest=Bibo
A naturally generating block that houses bees and a tasty treat...if you can get it.=En naturligt genereret blok som indeholde bier og velsmagende godter... hvis du kan få fat i dem.

View File

@ -0,0 +1,2 @@
# textdomain: mcl_bells
Bell=Klokke

View File

@ -0,0 +1,28 @@
# textdomain: mcl_blackstone
Blackstone=Sortsten
Polished Blackstone=Poleret sortsten
Chiseled Polished Blackstone=Majslet poleret sortsten
Polished Blackstone Bricks=Poleret sortsten-mursten
Basalt=Basalt
Polished Basalt=Poleret basalt
Blackstone Slab=Sortstensflise
Polished Blackstone Slab=Poleret sortstensflise
Chiseled Polished Blackstone Slab=Majslet poleret sortstensflise
Polished Blackstone Brick Slab=Poleret sortstens-murstensflise
Blackstone Stair=Sortstenstrappe
Polished Blackstone Stair=Poleret sortstenstrappe
Chiseled Polished Blackstone Stair=Majslet poleret sortstenstrappe
Polished Blackstone Brick Stair=Poleret sortstens-murstenstrappe
Quartz Bricks=Qvarts-mursten
Soul Torch=Sjæleildsfakkel
Soul Lantern=Sjældeildslaterne
Soul Soil=Sjælejord
Eternal Soul Fire=Evig sjæleild
Gilded Blackstone=Forgyldt sortsten
Nether Gold Ore=Nether guldmalm
Smooth Basalt=Glat basalt
Blackstone Wall=Sorstensmur
Double Blackstone Slab=Dobbelt sortstensflise
Polished Double Blackstone Slab=Poleret dobbelt sortstensflise
Double Chiseled Polished Blackstone Slab=Dobbelt majslet poleret sortstensflise
Double Polished Blackstone Brick Slab=Dobbelt poleret sortstens-murstensflise

View File

@ -0,0 +1,8 @@
# textdomain: mcl_blast_furnace
Inventory=Indhold
Blast Furnace=Højovn
Smelts ores faster than furnace=Smelter malm hurtere end en normal ovn.
Use the recipe book to see what you can smelt, what you can use as fuel and how long it will burn.=Brug opskriftsbogen for at se hvad du kan smelte, hvad du kan bruge som brændsel og hvor længe det brænder.
Use the furnace to open the furnace menu.\nPlace a furnace fuel in the lower slot and the source material in the upper slot.\nThe furnace will slowly use its fuel to smelt the item.\nThe result will be placed into the output slot at the right side.=Brug ovnen for at åbne ovnmenuen. \nPut ovnbrændsel i den nederste plads og det som skal smeltes i den øverste plads.\nOvnen vil langsom bruge dens brændsel til at smelte genstanden.\nResultatet vil blive puttet i pladsen på højre side.
Blast Furnaces smelt several items, mainly ores and armor, using a furnace fuel, into something else.=Højovne kan, ved brug af brændsel, smelte flere genstande, hovedsageligt malm og rustning, og lave dem til noget andet.
Active Blast Furnace=Aktiv højovn

View File

@ -0,0 +1,28 @@
# textdomain: mcl_books
Book=Bog
Books are used to make bookshelves and book and quills.=Bøger bruges til at lave bogreoler og bog og fjerpen
“@1”="@1"
Copy of “@1”=Kopi af "@1"
Copy of Copy of “@1”=Kopi af kopi af "@1"
Tattered Book=Flosset bog
by @1=af @1
# as in “to sign a book”
Sign=Underskriv
Done=Færdig
This item can be used to write down some notes.=Denne genstand kan bruges til at skrive notater.
Hold it in the hand, then rightclick to read the current notes and edit then. You can edit the text as often as you like. You can also sign the book which turns it into a written book which you can stack, but it can't be edited anymore.=Hold den i hånden, højre-klik så for at læse og redigere aktuelle notater. Du kan redigere teksten så ofte du har lyst. Du kan også signere bogen hvilken gør den til en skrevet bog som du kan gemme, men som ikke kan redigeres mere.
A book can hold up to 4500 characters. The title length is limited to 64 characters.=En bog kan indeholde op til 4500 anslag. Titellængden er begrænset til 64 anslag.
Enter book title:=Indtast bogens titel:
by @1=af @1
Note: The book will no longer be editable after signing=Bemærk: Bogen vil ikke længere kunne redigeres efter signering.
Sign and Close=Signér og luk
Cancel=Afbryd
Nameless Book=Unavngiven bog
Written Book=Skrevet bog
Written books contain some text written by someone. They can be read and copied, but not edited.=Skrevne bøger indeholder tekst som nogen har skrevet. De kan læses og kopieres, men ikke redigeres.
Hold it in your hand, then rightclick to read the book.=Hold den i hånden og højre-klik for at læse bogen.
To copy the text of the written book, place it into the crafting grid together with a book and quill (or multiple of those) and craft. The written book will not be consumed. Copies of copies can not be copied.=For at kopiere teksten i den skrevne bog skal du placere den i arbejdsgitteret sammen med en (eller flere) bog og fjerdpen og udfør. Den skrevne bog bliver ikke opbrugt. Kopier kan ikke kopieres.
Bookshelf=Bogreol
Bookshelves are used for decoration.=Bogreoler bruges til udsmykning.
Book and Quill=Bog og fjerdpen
Write down some notes=Skriv nogle notater

View File

@ -3,7 +3,7 @@ local S = minetest.get_translator(minetest.get_current_modname())
mcl_cocoas = {}
-- Place cocoa
function mcl_cocoas.place(itemstack, placer, pt, plantname)
local function cocoa_place(itemstack, placer, pt, plantname)
-- check if pointing at a node
if not pt or pt.type ~= "node" then
return
@ -90,7 +90,11 @@ local crop_def = {
},
},
groups = {
handy=1,axey=1, cocoa=1, not_in_creative_inventory=1, dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1, attached_node_facedir=1,
handy = 1, axey = 1,
dig_by_water=1, destroy_by_lava_flow=1, dig_by_piston=1,
attached_node_facedir=1,
not_in_creative_inventory=1,
cocoa=1
},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = false,

View File

@ -76,10 +76,10 @@ minetest.register_node("mcl_crimson:warped_fungus", {
walkable = false,
groups = {dig_immediate=3,mushroom=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,enderman_takable=1,deco_block=1},
light_source = 1,
selection_box = {
--[[ selection_box = {
type = "fixed",
fixed = { -3/16, -0.5, -3/16, 3/16, -2/16, 3/16 },
},
},]]
node_placement_prediction = "",
on_rightclick = function(pos, node, pointed_thing, player, itemstack)
if pointed_thing:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 259 B

View File

@ -275,7 +275,7 @@ local function apply_bone_meal(pointed_thing,user)
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)
return mcl_farming:grow_plant("plant_sweet_berry_bush", pos, n, 0, true)
end
elseif n.name == "mcl_cocoas:cocoa_1" or n.name == "mcl_cocoas:cocoa_2" then
mcl_dye.add_bone_meal_particle(pos)

View File

@ -102,15 +102,27 @@ minetest.register_node("mcl_farming:beetroot", {
0 seeds: 42.18%
1 seed: 14.06%
2 seeds: 18.75%
3 seeds: 25% ]]
3 seeds: 25%
correction: should always drop at least 1 seed. (1-4 seeds, per the minecraft wiki)
--]]
max_items = 2,
items = {
{ items = {"mcl_farming:beetroot_item"}, rarity = 1 },
{items = {"mcl_farming:beetroot_item"}},
{items = {"mcl_farming:beetroot_seeds 4"}, rarity = 6},
{items = {"mcl_farming:beetroot_seeds 3"}, rarity = 4},
{ items = {"mcl_farming:beetroot_seeds 2"}, rarity = 4 },
{ items = {"mcl_farming:beetroot_seeds 1"}, rarity = 4 },
{items = {"mcl_farming:beetroot_seeds 2"}, rarity = 3},
{items = {"mcl_farming:beetroot_seeds"}, rarity = 1},
},
},
_mcl_fortune_drop = {
discrete_uniform_distribution = true,
items = {"mcl_farming:beetroot_item", "mcl_farming:beetroot_seeds"},
min_count = 1,
max_count = 3,
cap = 5,
},
tiles = {"mcl_farming_beetroot_3.png"},
inventory_image = "mcl_farming_beetroot_3.png",
wield_image = "mcl_farming_beetroot_3.png",
@ -165,3 +177,6 @@ if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_farming:beetroot_0", "nodes", "mcl_farming:beetroot_" .. i)
end
end
minetest.register_alias("beetroot_seeds", "mcl_farming:beetroot_seeds")
minetest.register_alias("beetroot", "mcl_farming:beetroot_item")

View File

@ -89,14 +89,7 @@ minetest.register_craftitem("mcl_farming:carrot_item", {
groups = {food = 2, eatable = 3, compostability = 65},
_mcl_saturation = 3.6,
on_secondary_use = minetest.item_eat(3),
on_place = function(itemstack, placer, pointed_thing)
local new = mcl_farming:place_seed(itemstack, placer, pointed_thing, "mcl_farming:carrot_1")
if new then
return new
else
return minetest.do_item_eat(3, nil, itemstack, placer, pointed_thing)
end
end,
on_place = mcl_farming:get_seed_or_eat_callback("mcl_farming:carrot_1", 3),
})
minetest.register_craftitem("mcl_farming:carrot_item_gold", {

View File

@ -95,14 +95,7 @@ minetest.register_craftitem("mcl_farming:potato_item", {
_mcl_saturation = 0.6,
stack_max = 64,
on_secondary_use = minetest.item_eat(1),
on_place = function(itemstack, placer, pointed_thing)
local new = mcl_farming:place_seed(itemstack, placer, pointed_thing, "mcl_farming:potato_1")
if new then
return new
else
return minetest.do_item_eat(1, nil, itemstack, placer, pointed_thing)
end
end,
on_place = mcl_farming:get_seed_or_eat_callback("mcl_farming:potato_1", 1),
})
minetest.register_craftitem("mcl_farming:potato_item_baked", {

View File

@ -469,6 +469,21 @@ function mcl_farming:stem_color(startcolor, endcolor, step, step_count)
return colorstring
end
--[[Get a callback that either eats the item or plants it.
Used for on_place callbacks for craft items which are seeds that can also be consumed.
]]
function mcl_farming:get_seed_or_eat_callback(plantname, hp_change)
return function(itemstack, placer, pointed_thing)
local new = mcl_farming:place_seed(itemstack, placer, pointed_thing, plantname)
if new then
return new
else
return minetest.do_item_eat(hp_change, nil, itemstack, placer, pointed_thing)
end
end
end
minetest.register_lbm({
label = "Add growth for unloaded farming plants",
name = "mcl_farming:growth",

View File

@ -9,6 +9,9 @@ for i=0, 3 do
if i > 0 then
groups.sweet_berry_thorny = 1
end
local drop_berries = (i >= 2)
local berries_to_drop = drop_berries and {i - 1, i} or nil
minetest.register_node(node_name, {
drawtype = "plantlike",
tiles = {texture},
@ -24,7 +27,14 @@ for i=0, 3 do
liquid_renewable = false,
liquid_range = 0,
walkable = false,
drop = (i>=2) and ("mcl_farming:sweet_berry" .. (i==3 and " 3" or "")) or "",
-- Dont even create a table if no berries are dropped.
drop = not drop_berries and "" or {
max_items = 1,
items = {
{ items = {"mcl_farming:sweet_berry " .. berries_to_drop[1] }, rarity = 2 },
{ items = {"mcl_farming:sweet_berry " .. berries_to_drop[2] } }
}
},
selection_box = {
type = "fixed",
fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, (-0.30 + (i*0.25)), 6 / 16},
@ -41,22 +51,20 @@ for i=0, 3 do
minetest.record_protection_violation(pos, pn)
return itemstack
end
if mcl_dye and clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
if 3 ~= i and mcl_dye and
clicker:get_wielded_item():get_name() == "mcl_bone_meal:bone_meal" then
mcl_dye.apply_bone_meal({under=pos},clicker)
if not minetest.is_creative_enabled(pn) then
itemstack:take_item()
end
return
end
local stage
if node.name:find("_2") then
stage = 2
elseif node.name:find("_3") then
stage = 3
end
if stage then
for i=1,math.random(stage) do
if drop_berries then
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_" .. stage - 1 })
minetest.swap_node(pos, {name = "mcl_farming:sweet_berry_bush_1"})
end
return itemstack
end,
@ -76,7 +84,10 @@ minetest.register_craftitem("mcl_farming:sweet_berry", {
minetest.record_protection_violation(pointed_thing.above, pn)
return itemstack
end
if pointed_thing.type == "node" and table.indexof(planton,minetest.get_node(pointed_thing.under).name) ~= -1 and minetest.get_node(pointed_thing.above).name == "air" then
if pointed_thing.type == "node" and
table.indexof(planton, minetest.get_node(pointed_thing.under).name) ~= -1 and
pointed_thing.above.y > pointed_thing.under.y and
minetest.get_node(pointed_thing.above).name == "air" then
minetest.set_node(pointed_thing.above, {name="mcl_farming:sweet_berry_bush_0"})
if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()

View File

@ -22,6 +22,8 @@ local DEBUG = false
local enable_burger = minetest.settings:get_bool("mcl_enable_hamburger",true)
local use_alt = minetest.settings:get_bool("mcl_hamburger_alt_texture",false)
local HAMBURGER_NAME = "mcl_hamburger:hamburger"
mcl_hamburger = {}
if DEBUG then
@ -32,12 +34,12 @@ end
function mcl_hamburger.register_burger_craft(cooked_meat)
minetest.register_craft({
type = "fuel",
recipe = "mcl_hamburger:hamburger",
recipe = HAMBURGER_NAME,
burntime = 2,
})
minetest.register_craft({
output = "mcl_hamburger:hamburger",
output = HAMBURGER_NAME,
recipe = {
{ "mcl_farming:bread"},
{ cooked_meat }, -- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac.
@ -45,7 +47,7 @@ function mcl_hamburger.register_burger_craft(cooked_meat)
},
})
minetest.register_craft({
output = "mcl_hamburger:hamburger",
output = HAMBURGER_NAME,
recipe = {
-- "mcl_mobitems:cooked_beef" for a reg hamburger. Grind up clowns for a Big Mac.
{ "mcl_farming:bread", cooked_meat, "mcl_farming:bread"},
@ -72,23 +74,23 @@ if not enable_burger then
end
if use_alt == false then
minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_def)
minetest.register_craftitem(HAMBURGER_NAME, hamburger_def)
else
local hamburger_alt = table.copy(hamburger_def)
hamburger_alt.inventory_image = "mcl_hamburger_alt.png"
hamburger_alt.wield_image = "mcl_hamburger_alt.png"
minetest.register_craftitem("mcl_hamburger:hamburger", hamburger_alt)
minetest.register_craftitem(HAMBURGER_NAME, hamburger_alt)
end
local function register_achievements()
awards.register_achievement("mcl_hamburger:hamburger", {
awards.register_achievement(HAMBURGER_NAME, {
title = S("Burger Time!"),
description = S("Craft a Hamburger."),
icon = "mcl_hamburger_alt.png",
trigger = {
type = "craft",
item = "mcl_hamburger:hamburger",
item = HAMBURGER_NAME,
target = 1
},
type = "Advancement",
@ -101,19 +103,47 @@ local function register_doc_entry()
-- register Doc entry
if minetest.get_modpath("doc") then
doc.add_entry_alias("craftitems", "mcl_hamburger:hamburger", "craftitems", "mcl_hamburger:hamburger")
doc.add_entry_alias("craftitems", HAMBURGER_NAME, "craftitems", HAMBURGER_NAME)
end
end
if enable_burger then
-- make the villagers follow the item
minetest.registered_entities["mobs_mc:villager"].nofollow = false
-- add it to the follow items.
table.insert(minetest.registered_entities["mobs_mc:villager"].follow,"mcl_hamburger:hamburger")
-- register the item and crafting recipe.
local villager = minetest.registered_entities["mobs_mc:villager"]
table.insert(villager.follow, HAMBURGER_NAME)
local original_rightclick = villager.on_rightclick
local new_on_rightclick = function(self, clicker)
--minetest.log("In wrapper function")
local item = clicker:get_wielded_item()
if item:get_name() == HAMBURGER_NAME then
if self.nofollow == true then
--minetest.log("Turn off nofollow")
self.nofollow = false
elseif self.nofollow == false then
--minetest.log("Turn on nofollow")
self.nofollow = true
end
else
--minetest.log("Not holding burger")
if self.nofollow == false then
--minetest.log("Turn on nofollow")
self.nofollow = true
end
original_rightclick(self, clicker)
end
--minetest.log("Finishing wrapper")
end
villager.on_rightclick = new_on_rightclick
mcl_hamburger.register_burger_craft("mcl_mobitems:cooked_beef")
-- add in the super cool achievement(s)!
minetest.register_alias("hamburger", HAMBURGER_NAME)
register_achievements()
register_doc_entry()
end

View File

@ -0,0 +1,226 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for software and other kinds of works.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based on the Program.
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -0,0 +1,15 @@
---
# Mineclone2-Lectern
---
A ground up creation of a lectern to be used in MineClone 2. Requires Minetest and Mineclone2.
---
Created by Michieal (FaerRaven) @ DateTime: 01/07/2023 (07JAN2023)
* Made for MineClone 2 by Michieal.
* Texture made by Michieal; The model borrows the top from NathanS21's (Nathan Salapat) Lectern model; The rest of the
lectern model was created by Michieal.
* Creation date: 01/07/2023 (07JAN2023)
* License for Code: GPL3
* License for Media: CC-BY-SA 4

View File

@ -0,0 +1,131 @@
-- Made for MineClone 2 by Michieal.
-- Texture made by Michieal; The model borrows the top from NathanS21's (Nathan Salapat) Lectern model; The rest of the
-- lectern model was created by Michieal.
-- Creation date: 01/07/2023 (07JAN2023)
-- License for Code: GPL3
-- License for Media: CC-BY-SA 4
-- Copyright (C) 2023, Michieal. See: License.txt.
-- LOCALS
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local node_sound = mcl_sounds.node_sound_wood_defaults()
local pi = 3.1415926
local lectern_def = {
description = S("Lectern"),
_tt_help = S("Lecterns not only look good, but are job site blocks for Librarians."),
_doc_items_longdesc = S("Lecterns not only look good, but are job site blocks for Librarians."),
_doc_items_usagehelp = S("Place the Lectern on a solid node for best results. May attract villagers, so it's best to place outside of where you call 'home'."),
sounds = node_sound,
paramtype = "light",
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype2 = "facedir",
drawtype = "mesh",
-- visual_scale = 1.0, -- Default is 1.0.
mesh = "mcl_lectern_lectern.obj",
tiles = {"mcl_lectern_lectern.png", },
groups = {handy = 1, axey = 1, flammable = 2, fire_encouragement = 5, fire_flammability = 5, solid = 1},
drops = "mcl_lectern:lectern",
sunlight_propagates = true,
walkable = true,
is_ground_content = false,
node_placement_prediction = "",
_mcl_blast_resistance = 3,
_mcl_hardness = 2,
selection_box = {
type = "fixed",
fixed = {
-- L, T, Ba, R, Bo, F.
{-0.32, 0.46, -0.32, 0.32, 0.175, 0.32},
{-0.18, 0.175, -0.055, 0.18, -0.37, 0.21},
{-0.32, -0.37, -0.32, 0.32, -0.5, 0.32},
}
},
collision_box = {
type = "fixed",
fixed = {
-- L, T, Ba, R, Bo, F.
{-0.32, 0.46, -0.32, 0.32, 0.175, 0.32},
{-0.18, 0.175, -0.055, 0.18, -0.37, 0.21},
{-0.32, -0.37, -0.32, 0.32, -0.5, 0.32},
}
},
on_place = function(itemstack, placer, pointed_thing)
local above = pointed_thing.above
local under = pointed_thing.under
local pos = under
local pname = placer:get_player_name()
if minetest.is_protected(pos, pname) then
minetest.record_protection_violation(pos, pname)
return
end
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
local dir = vector.subtract(under, above)
local wdir = minetest.dir_to_wallmounted(dir)
local fdir = minetest.dir_to_facedir(dir)
if wdir == 0 then
return itemstack
-- IE., no Hanging Lecterns for you!
end
if wdir == 1 then
-- (only make standing nodes...)
-- Determine the rotation based on player's yaw
local yaw = pi * 2 - placer:get_look_horizontal()
-- Convert to 16 dir.
local rotation_level = math.round((yaw / (pi * 2)) * 16)
-- put the rotation level within bounds.
if rotation_level > 15 then
rotation_level = 0
elseif rotation_level < 0 then
rotation_level = 15
end
fdir = math.floor(rotation_level / 4) -- collapse that to 4 dir.
local lectern_node = ItemStack(itemstack)
-- Place the node!
local _, success = minetest.item_place_node(lectern_node, placer, pointed_thing, fdir)
if not success then
return itemstack
end
if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()
end
end
return itemstack
end,
}
minetest.register_node("mcl_lectern:lectern", lectern_def)
mcl_wip.register_wip_item("mcl_lectern:lectern")
-- April Fools setup
local date = os.date("*t")
if (date.month == 4 and date.day == 1) then
minetest.override_item("mcl_lectern:lectern", {waving = 2})
else
minetest.override_item("mcl_lectern:lectern", {waving = 0})
end
minetest.register_craft({
output = "mcl_lectern:lectern",
recipe = {
{"group:slab", "group:slab", "group:slab"},
{"", "mcl_books:bookshelf", ""},
{"", "group:slab", ""},
}
})
-- Base Aliases.
minetest.register_alias("lectern", "mcl_lectern:lectern")

View File

@ -0,0 +1,3 @@
name = mcl_lectern
depends = mcl_core, mcl_sounds, mcl_tools
author = Michieal

View File

@ -0,0 +1,223 @@
# Blender 3.5.0 Alpha
# www.blender.org
mtllib mcl_lectern_lectern.mtl
o Lectern_Cube.012
v 0.179604 0.312500 -0.062500
v -0.179604 0.312500 -0.062500
v 0.179604 0.363193 0.205629
v -0.179604 0.363193 0.205629
v 0.179604 -0.375000 -0.062500
v -0.179604 -0.375000 -0.062500
v 0.179604 -0.375000 0.205629
v -0.179604 -0.375000 0.205629
v 0.311850 -0.500000 0.312500
v 0.311850 -0.375000 0.312500
v -0.311649 -0.500000 0.312500
v -0.311649 -0.375000 0.312500
v 0.311850 -0.500000 -0.312500
v 0.311850 -0.375000 -0.312500
v -0.311649 -0.500000 -0.312500
v -0.311649 -0.375000 -0.312500
v 0.312500 0.186356 -0.272278
v 0.312500 0.245087 -0.293654
v 0.312500 0.400118 0.315030
v 0.312500 0.458849 0.293654
v -0.312500 0.186356 -0.272278
v -0.312500 0.245087 -0.293654
v -0.312500 0.400118 0.315030
v -0.312500 0.458849 0.293654
v 0.312500 0.207732 -0.213547
v 0.312500 0.266463 -0.234923
v -0.312500 0.207732 -0.213547
v -0.312500 0.266463 -0.234923
v -0.312500 0.325194 -0.256299
v -0.312500 0.303817 -0.315030
v 0.312500 0.303817 -0.315030
v 0.312500 0.325194 -0.256299
v 0.151506 0.084133 0.146440
v -0.157381 0.084133 0.146440
v -0.157381 -0.203113 0.146441
v 0.151506 -0.203113 0.146441
v 0.151523 0.084130 -0.062500
v -0.157397 0.084130 -0.062500
v 0.151523 -0.203120 -0.062500
v -0.157397 -0.203120 -0.062500
v 0.151768 0.044855 0.077978
v 0.064092 -0.203638 0.077978
v 0.151797 0.044842 -0.062023
v 0.064120 -0.203654 -0.062023
v 0.028419 -0.191051 0.077979
v 0.116095 0.057441 0.077979
v 0.116124 0.057428 -0.062022
v 0.028447 -0.191068 -0.062022
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -0.0000 -1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.0000 0.3420 0.9397
vn -0.0000 -0.3420 -0.9397
vn -0.0000 -0.9397 0.3420
vn -0.0000 0.9397 -0.3420
vn -0.0000 -1.0000 -0.0000
vn -1.0000 -0.0000 -0.0001
vn 1.0000 -0.0000 -0.0001
vn 0.9430 -0.3327 0.0002
vn -0.9430 0.3327 -0.0002
vn 0.3327 0.9430 -0.0000
vn -0.3327 -0.9430 -0.0000
vt 0.000000 0.000000
vt 0.343750 -0.000000
vt 0.312500 0.000000
vt -0.000000 -0.000000
vt 0.312500 0.000000
vt 0.000000 0.000000
vt 0.312500 0.000000
vt 0.000000 0.000000
vt 0.000000 0.437500
vt 0.343750 0.625000
vt 0.312500 0.437500
vt -0.000000 0.625000
vt 0.312500 0.437500
vt 0.000000 0.437500
vt 0.312500 0.437500
vt 0.000000 0.437500
vt 0.312500 0.593750
vt 0.000000 0.593750
vt 0.312500 0.656250
vt 0.000000 0.656250
vt 1.000000 1.000000
vt 0.000000 0.593750
vt 0.312500 0.593750
vt 0.000000 0.656250
vt 0.312500 0.656250
vt 1.000000 0.437500
vt 0.000000 0.593750
vt 0.312500 0.593750
vt 0.000000 0.656250
vt 0.312500 0.656250
vt 0.437500 1.000000
vt 0.000000 0.593750
vt 0.312500 0.593750
vt 0.000000 0.656250
vt 0.312500 0.656250
vt 0.437500 0.437500
vt 0.125000 1.000000
vt 0.125000 0.687500
vt 0.062500 0.687500
vt 0.187500 1.000000
vt 0.125000 1.000000
vt 0.312500 1.000000
vt 0.437500 1.000000
vt 0.062500 1.000000
vt 0.250000 1.000000
vt 1.000000 1.000000
vt 0.125000 0.687500
vt 0.062500 0.687500
vt 0.187500 0.687500
vt 0.312500 0.687500
vt 0.437500 0.437500
vt 0.125000 1.000000
vt 0.250000 0.687500
vt 1.000000 0.437500
vt 0.062500 1.000000
vt 1.000000 1.000000
vt 0.062500 1.000000
vt 0.125000 0.718750
vt 0.437500 1.000000
vt 0.062500 0.718750
vt 1.000000 0.437500
vt 0.062500 0.687500
vt 0.125000 0.718750
vt 0.437500 0.437500
vt 0.062500 0.718750
vt 0.437500 0.687500
vt -0.000000 0.718750
vt 0.375000 0.687500
vt -0.000000 0.687500
vt 0.312500 0.687500
vt 0.250000 0.687500
vt 0.312500 1.000000
vt -0.000000 0.687500
vt 0.250000 1.000000
vt 0.375000 1.000000
vt -0.000000 0.718750
vt 0.687500 0.375000
vt 0.312500 0.375000
vt 0.687500 0.375000
vt 0.312500 0.000000
vt 0.312500 0.375000
vt 0.687500 0.000000
vt 0.687500 0.375000
vt 0.312500 0.375000
vt 0.312500 0.218750
vt 0.687500 -0.000000
vt 0.031250 0.218750
vt 0.312500 -0.000000
vt 0.687500 -0.000000
vt 0.312500 0.468750
vt 0.687500 -0.000000
vt 0.312500 -0.000000
vt 0.031250 0.468750
vt 0.312500 -0.000000
vt 0.937500 -0.000000
vt 0.937500 0.437500
vt 0.937500 0.437500
vt 1.000000 0.437500
vt 0.687500 0.000000
vt 0.937500 0.218750
vt 0.750000 0.000000
vt 0.687500 0.437500
vt 0.750000 0.437500
vt 1.000000 0.218750
vt 0.937500 0.000000
vt 1.000000 0.437500
vt 0.937500 0.437500
vt 0.937500 0.437500
vt 1.000000 -0.000000
vt 1.000000 0.437500
vt 0.687500 0.437500
vt 1.000000 0.218750
vt 0.687500 0.000000
vt 0.687500 0.000000
vt 0.687500 0.437500
vt 0.937500 0.218750
s 0
usemtl Material
f 1/1/1 3/5/1 7/13/1 5/9/1
f 3/6/2 4/7/2 8/15/2 7/14/2
f 9/17/2 10/19/2 12/24/2 11/22/2
f 36/82/3 35/80/3 34/78/3 33/77/3
f 8/16/4 4/8/4 2/3/4 6/11/4
f 11/23/4 12/25/4 16/34/4 15/32/4
f 15/33/3 16/35/3 14/29/3 13/27/3
f 13/28/1 14/30/1 10/20/1 9/18/1
f 16/36/5 12/26/5 10/21/5 14/31/5
f 25/58/1 26/60/1 20/44/1 19/41/1
f 19/42/6 20/45/6 24/53/6 23/50/6
f 27/63/4 28/65/4 22/48/4 21/47/4
f 21/47/7 22/49/7 18/40/7 17/37/7
f 22/48/4 28/65/4 29/67/4 30/69/4
f 25/56/8 19/43/8 23/51/8 27/61/8
f 17/37/8 25/57/8 27/62/8 21/47/8
f 24/54/9 20/46/9 26/59/9 28/64/9
f 23/52/4 24/55/4 28/65/4 27/63/4
f 17/38/1 18/39/1 26/60/1 25/58/1
f 29/68/9 32/75/9 31/72/9 30/70/9
f 28/66/6 26/59/6 32/75/6 29/68/6
f 26/60/1 18/39/1 31/73/1 32/76/1
f 18/40/7 22/49/7 30/71/7 31/74/7
f 37/85/3 38/87/3 2/4/3 1/2/3
f 39/90/3 37/85/3 1/2/3 5/10/3
f 40/93/3 39/90/3 5/10/3 6/12/3
f 38/87/3 40/93/3 6/12/3 2/4/3
f 33/77/10 34/78/10 38/88/10 37/86/10
f 35/81/5 36/83/5 39/91/5 40/94/5
f 36/84/11 33/77/11 37/86/11 39/92/11
f 34/79/12 35/81/12 40/94/12 38/89/12
f 44/102/13 43/99/13 41/95/13 42/97/13
f 45/105/14 46/108/14 47/111/14 48/114/14
f 41/95/2 46/109/2 45/106/2 42/97/2
f 43/100/15 47/112/15 46/110/15 41/96/15
f 44/103/3 48/115/3 47/113/3 43/101/3
f 42/98/16 45/107/16 48/116/16 44/104/16

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -79,19 +79,27 @@ function settlements.create_site_plan(maxp, minp, pr)
local settlement_info = {}
local building_all_info
local possible_rotations = {"0", "90", "180", "270"}
-- find center of chunk
local center = {
x=math.floor((minp.x+maxp.x)/2),
y=maxp.y,
z=math.floor((minp.z+maxp.z)/2)
}
-- find center_surface of chunk
local center_surface , surface_material = settlements.find_surface(center, true)
local chunks = {}
chunks[mcl_vars.get_chunk_number(center)] = true
-- go build settlement around center
if not center_surface then return false end
if not center_surface then
minetest.log("action", "Cannot build village at: " .. minetest.pos_to_string(center))
return false
else
minetest.log("action", "Village built.")
--minetest.log("action", "Build village at: " .. minetest.pos_to_string(center) .. " with surface material: " .. surface_material)
end
-- initialize all settlement_info table
local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr)
@ -190,6 +198,7 @@ local function construct_node(p1, p2, name)
end
local function spawn_iron_golem(pos)
--minetest.log("action", "Attempt to spawn iron golem.")
local p = minetest.find_node_near(pos,50,"mcl_core:grass_path")
if p then
local l=minetest.add_entity(p,"mobs_mc:iron_golem"):get_luaentity()
@ -200,6 +209,7 @@ local function spawn_iron_golem(pos)
end
local function spawn_villagers(minp,maxp)
--minetest.log("action", "Attempt to spawn villagers.")
local beds=minetest.find_nodes_in_area(vector.offset(minp,-20,-20,-20),vector.offset(maxp,20,20,20),{"mcl_beds:bed_red_bottom"})
for _,bed in pairs(beds) do
local m = minetest.get_meta(bed)
@ -235,23 +245,6 @@ end
function settlements.place_schematics(settlement_info, pr)
local building_all_info
--attempt to place one belltower in the center of the village - this doesn't always work out great but it's a lot better than doing it first or last.
local belltower = table.remove(settlement_info,math.floor(#settlement_info/2))
if belltower then
mcl_structures.place_schematic(
vector.offset(belltower["pos"],0,0,0),
settlements.modpath.."/schematics/belltower.mts",
belltower["rotation"],
nil,
true,
nil,
function(p1, p2, size, rotation, pr)
spawn_iron_golem(p1)
end,
pr
)
end
for i, built_house in ipairs(settlement_info) do
local is_last = i == #settlement_info
@ -262,6 +255,9 @@ function settlements.place_schematics(settlement_info, pr)
end
end
local pos = settlement_info[i]["pos"]
local rotation = settlement_info[i]["rotat"]
-- get building node material for better integration to surrounding
@ -313,8 +309,11 @@ function settlements.place_schematics(settlement_info, pr)
-- format schematic string
local schematic = loadstring(schem_lua)()
local is_belltower = building_all_info["name"] == "belltower"
-- build foundation for the building an make room above
-- place schematic
mcl_structures.place_schematic(
pos,
schematic,
@ -323,8 +322,12 @@ function settlements.place_schematics(settlement_info, pr)
true,
nil,
function(p1, p2, size, rotation, pr)
if is_belltower then
spawn_iron_golem(p1)
else
init_nodes(p1, p2, size, rotation, pr)
spawn_villagers(p1,p2)
end
end,
pr
)

View File

@ -52,6 +52,7 @@ schem_path = settlements.modpath.."/schematics/"
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
settlements.schematic_table = {
{name = "belltower", mts = schem_path.."belltower.mts", hwidth = 5, hdepth = 5, hheight = 9, hsize = 14, max_num = 0 , rplc = basic_pseudobiome_villages },
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 12, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 8, hdepth = 11, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 12, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages },

View File

@ -40,23 +40,33 @@ function settlements.find_surface(pos, wait)
-- go through nodes an find surface
while cnt < cnt_max do
-- Check Surface_node and Node above
--
if settlements.surface_mat[surface_node.name] then
if surface_node and settlements.surface_mat[surface_node.name] then
local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z})
if surface_node_plus_1 and surface_node and
(string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"snow") or
if surface_node_plus_1 then
local surface_node_minus_1 = get_node({ x=p6.x, y=p6.y-1, z=p6.z})
local is_leaf_below = minetest.get_item_group(surface_node_minus_1, "leaves") ~= 0 or
string.find(surface_node_minus_1.name,"leaves")
if not is_leaf_below and ((string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"fern") or
string.find(surface_node_plus_1.name,"flower") or
string.find(surface_node_plus_1.name,"bush") or
string.find(surface_node_plus_1.name,"tree") or
string.find(surface_node_plus_1.name,"grass"))
string.find(surface_node_plus_1.name,"grass")) or
string.find(surface_node_plus_1.name,"snow"))
then
settlements.debug("find_surface7: " ..surface_node.name.. " " .. surface_node_plus_1.name)
settlements.debug("find_surface success: " ..surface_node.name.. " " .. surface_node_plus_1.name)
settlements.debug("node below: " .. tostring(surface_node_minus_1.name))
settlements.debug("node below leaves group: " .. tostring(minetest.get_item_group(surface_node_minus_1, "leaves")))
return p6, surface_node.name
else
settlements.debug("find_surface2: wrong surface+1")
end
else
settlements.debug("find_surface8: missing node or plus_1")
end
else
settlements.debug("find_surface3: wrong surface "..surface_node.name.." at pos "..minetest.pos_to_string(p6))
end

View File

@ -1,11 +1,9 @@
local mcl_skins_enabled = minetest.global_exists("mcl_skins")
-- This is a fake node that should never be placed in the world
---This is a fake node that should never be placed in the world
---@type node_definition
local node_def = {
description = "",
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
visual_scale = 1,
wield_scale = {x=1,y=1,z=1},
use_texture_alpha = "opaque",
paramtype = "light",
drawtype = "mesh",
node_placement_prediction = "",
@ -16,7 +14,7 @@ local node_def = {
minetest.remove_node(pos)
end,
drop = "",
on_drop = function() return "" end,
on_drop = function(_, _, _) return ItemStack() end,
groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
range = minetest.registered_items[""].range
}
@ -54,6 +52,6 @@ if mcl_skins_enabled then
end)
else
minetest.register_on_joinplayer(function(player)
player:get_inventory():set_stack("hand", 1, "mcl_meshhand:hand")
player:get_inventory():set_stack("hand", 1, ItemStack("mcl_meshhand:hand"))
end)
end

View File

@ -0,0 +1,113 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local pianowtune = "diminixed-pianowtune01"
local end_tune = "diminixed-ambientwip"
local nether_tune = "horizonchris96-traitor"
local dimension_to_base_track = {
["overworld"] = pianowtune,
["nether"] = nether_tune,
["end"] = end_tune,
}
local listeners = {}
local weather_state
local function stop_music_for_listener_name(listener_name)
if not listener_name then return end
local listener = listeners[listener_name]
if not listener then return end
local handle = listener.handle
if not handle then return end
minetest.sound_stop(handle)
listeners[listener_name].handle = nil
end
local function stop()
for _, player in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
stop_music_for_listener_name(player_name)
end
end
local function play()
local new_weather_state = mcl_weather.get_weather()
local was_good_weather = weather_state == "none" or weather_state == "clear"
weather_state = new_weather_state
local is_good_weather = weather_state == "none" or weather_state == "clear"
local is_weather_changed = weather_state ~= new_weather_state
local time = minetest.get_timeofday()
if time < 0.25 or time >= 0.75 then
stop()
minetest.after(10, play)
return
end
local day_count = minetest.get_day_count()
for _, player in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
local hp = player:get_hp()
local pos = player:get_pos()
local dimension = mcl_worlds.pos_to_dimension(pos)
local listener = listeners[player_name]
local old_hp = listener and listener.hp
local old_dimension = listener and listener.dimension
local is_dimension_changed = old_dimension and (old_dimension ~= dimension) or false
local is_hp_changed = old_hp and (math.abs(old_hp - hp) > 0.00001) or false
local handle = listener and listener.handle
local track = dimension_to_base_track[dimension]
if is_hp_changed
or is_dimension_changed
or (dimension == "overworld" and (is_weather_changed or not is_good_weather))
or not track
then
stop_music_for_listener_name(player_name)
if not listeners[player_name] then
listeners[player_name] = {}
end
listeners[player_name].hp = hp
listeners[player_name].dimension = dimension
elseif not handle and (not listener or (listener.day_count ~= day_count)) then
local spec = {
name = track,
gain = 0.3,
pitch = 1.0,
}
local parameters = {
to_player = player_name,
gain = 1.0,
fade = 0.0,
pitch = 1.0,
}
handle = minetest.sound_play(spec, parameters, false)
listeners[player_name] = {
spec = spec,
parameters = parameters,
handle = handle,
hp = hp,
dimension = dimension,
day_count = day_count,
}
end
end
minetest.after(7, play)
end
minetest.after(15, play)
minetest.register_on_joinplayer(function(player, last_login)
local player_name = player:get_player_name()
stop_music_for_listener_name(player_name)
end)
minetest.register_on_respawnplayer(function(player)
local player_name = player:get_player_name()
stop_music_for_listener_name(player_name)
end)

View File

@ -0,0 +1,4 @@
name = mcl_music
author = diminixed, horizonchris96, kay27
description = Mod check some conditions and plays music
depends = mcl_player, mcl_weather, mcl_worlds

Binary file not shown.