Compare commits
313 Commits
stable-0.4
...
master
Author | SHA1 | Date |
---|---|---|
|
5baf5c1c51 | |
|
2fd4c32ce7 | |
|
2faa769a1f | |
|
dad270a296 | |
|
592ed84831 | |
|
6c7f03ce0f | |
|
0f80116e97 | |
|
bfc11fe83c | |
|
4d55f99548 | |
|
1d21646644 | |
|
835ac73e0a | |
|
1718494306 | |
|
97c2de8b79 | |
|
3e54b6e430 | |
|
5c82aa3d14 | |
|
c32552f8ef | |
|
4b99c82c73 | |
|
4e12030bab | |
|
cc3664cc82 | |
|
f4d49861f5 | |
|
d99a176b69 | |
|
7e16ec7a2f | |
|
e8097c9e87 | |
|
5c3e4b1d20 | |
|
553b0f9d72 | |
|
7269711911 | |
|
3a3f71aa50 | |
|
fac8f390b1 | |
|
4eadf80634 | |
|
e5ebb36cd5 | |
|
2063fcd075 | |
|
a2254bd0af | |
|
7f830124f7 | |
|
a5bde8e9ba | |
|
6716fc74ec | |
|
c32b8adaa3 | |
|
4282a93a02 | |
|
d16612c1cb | |
|
9fe877ef99 | |
|
a81a7e0c78 | |
|
9b226c7045 | |
|
773011fd85 | |
|
c3403936d3 | |
|
b701e500aa | |
|
37710866f0 | |
|
bfb84da39c | |
|
3bca295da8 | |
|
83fb6fe872 | |
|
95aaec6670 | |
|
5b1d5819e5 | |
|
3d530e0c25 | |
|
e7be81242b | |
|
a6a719967a | |
|
54bb0afe7f | |
|
0f771a27c3 | |
|
ca7c131133 | |
|
61bfac0fa2 | |
|
e19f42d648 | |
|
76a08a7058 | |
|
80c10cee15 | |
|
aee5ba64f9 | |
|
5c48c76aa2 | |
|
f21bab2ff9 | |
|
0291c6b210 | |
|
b20725026e | |
|
88d79881b8 | |
|
efd090228d | |
|
dfe6fd6560 | |
|
dd3f3b2032 | |
|
8b5e0a914b | |
|
e3cd961a15 | |
|
eaf6eac723 | |
|
02e2cab375 | |
|
b853c8a509 | |
|
891f00e9db | |
|
b38b5b2357 | |
|
196f206d3e | |
|
1ca25eec9d | |
|
b92f7431ef | |
|
7f687777a6 | |
|
6b2887e3bf | |
|
14cc07bfd3 | |
|
ad6c2cf035 | |
|
2033b2cc65 | |
|
bfde214c52 | |
|
6e0e2b8be9 | |
|
64a923f7fb | |
|
2ff9058a62 | |
|
a2c9523bce | |
|
7fa03c7a9b | |
|
8af8dc49a0 | |
|
ccf03ea404 | |
|
6688ddf6d4 | |
|
da10af919e | |
|
bae58b3806 | |
|
ec248d3cb0 | |
|
667e130c52 | |
|
1fa8180e7f | |
|
068e0b167f | |
|
21f5eaade0 | |
|
5f61379757 | |
|
ad486bc863 | |
|
5ccf965825 | |
|
58f6994e08 | |
|
cf0e49fb4a | |
|
382e2acd9b | |
|
b042106fdc | |
|
f583d90c94 | |
|
ab1a79b13c | |
|
2696b0cd91 | |
|
5b3b609270 | |
|
24900f7da5 | |
|
f42deb4026 | |
|
e10e0f94d6 | |
|
be6fe9f592 | |
|
7fedf0b5d9 | |
|
aafe31c14e | |
|
ef20f9e12b | |
|
5673a71752 | |
|
02c4a05e60 | |
|
6f80fd3737 | |
|
3484ff23ad | |
|
689f0c5478 | |
|
f4f90520ec | |
|
20b433881b | |
|
3d02145271 | |
|
70c0181b59 | |
|
ab3b1a35f5 | |
|
c284e52963 | |
|
ab4940505e | |
|
506eca22bc | |
|
bf3efa0bb7 | |
|
ee72bc722c | |
|
57db3f748c | |
|
9318c71659 | |
|
d4b0b73ae0 | |
|
ef7bd43829 | |
|
513609dcfd | |
|
5c8bd34957 | |
|
7e1b07fddd | |
|
ecea5364f1 | |
|
59dbeebc2f | |
|
876a9ca5d2 | |
|
255031fc91 | |
|
0df2753a68 | |
|
0ea6065a09 | |
|
5692c15b4d | |
|
e9fbd3d75d | |
|
abe1b9f559 | |
|
bcf76eab1d | |
|
e376d57bd2 | |
|
37b206e49f | |
|
e74e091e78 | |
|
ed1d64d8aa | |
|
145b7bfef3 | |
|
b389f38120 | |
|
64470dc786 | |
|
3d709dfa1d | |
|
ace7ec953e | |
|
b52ea3de15 | |
|
aedd209440 | |
|
bbb88e6387 | |
|
0b025e6392 | |
|
8d8f2f79d0 | |
|
8c71f3d826 | |
|
9c459e77ac | |
|
11b3407671 | |
|
b0e55c52c8 | |
|
f3ce25fc72 | |
|
7e9000b502 | |
|
fb0217042b | |
|
465d8cae3e | |
|
c0557b2c23 | |
|
c2209c120e | |
|
da877ccf57 | |
|
160dc21bc1 | |
|
ac50b3e3ce | |
|
d4a007c051 | |
|
1afb8f249e | |
|
3afcd68e9b | |
|
c2001b3b52 | |
|
63ebdfd139 | |
|
702070accb | |
|
04a46d0671 | |
|
70d91bc64d | |
|
280f1b1c39 | |
|
283636bfdb | |
|
094ad004a4 | |
|
b90aabec80 | |
|
495fa32873 | |
|
7754555707 | |
|
1e9c61f241 | |
|
7f3e9e65b3 | |
|
ca81e9b8c6 | |
|
a587972010 | |
|
d5907d5f1e | |
|
12f1703537 | |
|
8f85ca57f3 | |
|
496a1a24d2 | |
|
5f121b586d | |
|
ee6d2f2468 | |
|
41a4073d4c | |
|
a6aa68d5b4 | |
|
223562d687 | |
|
f52085a40f | |
|
faa088e2c5 | |
|
bd0c627a20 | |
|
d1ece74652 | |
|
d1db66bf4f | |
|
8ab7c54d76 | |
|
5b57815af1 | |
|
dfe74948e2 | |
|
62d5d5954e | |
|
d603707e1a | |
|
5134510356 | |
|
21b3c841bd | |
|
0c841771a7 | |
|
0132bfe41e | |
|
2824e4bb7c | |
|
ed83e30d68 | |
|
2c5670563a | |
|
b75a17984a | |
|
a2d7678ffd | |
|
3ae382c913 | |
|
91997d9342 | |
|
8b5ad0f028 | |
|
319b9eeeaf | |
|
d4e1bd053e | |
|
9d9e9b6709 | |
|
dbfe435abf | |
|
08c60cfc30 | |
|
9596d00a18 | |
|
49cc4c7c63 | |
|
36df80fc45 | |
|
3f14d1012d | |
|
045abbd6d7 | |
|
454e0da531 | |
|
5870fd48f6 | |
|
47d6fbf884 | |
|
7c3854de27 | |
|
cc371ac726 | |
|
eb5a5b56e1 | |
|
3ff296961e | |
|
12a971660d | |
|
b6626f76b5 | |
|
e40f25f1fb | |
|
3611af1dda | |
|
809e5933c4 | |
|
2d8207a924 | |
|
a4b94a3347 | |
|
db08c0d721 | |
|
74ed63f46b | |
|
f33cc02080 | |
|
c5c9e423ca | |
|
4ccafd1518 | |
|
bf8404fcf7 | |
|
edba1dcb02 | |
|
fe67ffda7c | |
|
bcf98df5fa | |
|
08727bcd69 | |
|
f928780946 | |
|
bb084294ce | |
|
20687a6301 | |
|
b431ae1c77 | |
|
fe710c99a6 | |
|
c5e97867f3 | |
|
8817d1c696 | |
|
d883012491 | |
|
67c01a44c2 | |
|
77c9408721 | |
|
3294a2a515 | |
|
57577596d6 | |
|
b4abb07572 | |
|
271b2befaa | |
|
5d19fd6923 | |
|
7ffd176f48 | |
|
8f1f3760f0 | |
|
71dff2ac4a | |
|
fa4c77feba | |
|
c81165b2c8 | |
|
996f168aa3 | |
|
40ed77185e | |
|
a1d35f3d69 | |
|
c2f3c99cad | |
|
48baf1acb5 | |
|
886537ef50 | |
|
e5189760b3 | |
|
1d5bc15f9a | |
|
1aafcdd7e0 | |
|
0cdee1d8f5 | |
|
b66a61a10f | |
|
57979686d9 | |
|
2e413b521a | |
|
0f7d0bfd7a | |
|
c51ebcb74a | |
|
bae17cd88c | |
|
7b46d3b6af | |
|
bdc09d2313 | |
|
2c666891a8 | |
|
3d1fc42f66 | |
|
36d024a716 | |
|
120e96938d | |
|
502720b14d | |
|
0157175346 | |
|
b3f17cda9f | |
|
15ba96467d | |
|
da7e8e4810 | |
|
175a9f8ff5 | |
|
b91e047868 | |
|
7e9c5a3576 | |
|
c714d43319 | |
|
626cd8e9c7 | |
|
f855beeda5 |
|
@ -7,11 +7,12 @@ read_globals = {
|
||||||
"dump",
|
"dump",
|
||||||
"vector",
|
"vector",
|
||||||
"VoxelManip", "VoxelArea",
|
"VoxelManip", "VoxelArea",
|
||||||
"PseudoRandom", "ItemStack",
|
"PseudoRandom", "PcgRandom",
|
||||||
|
"ItemStack",
|
||||||
"Settings",
|
"Settings",
|
||||||
"unpack",
|
"unpack",
|
||||||
-- Silence "accessing undefined field copy of global table".
|
-- Silence errors about custom table methods.
|
||||||
table = { fields = { "copy" } }
|
table = { fields = { "copy", "indexof" } }
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Overwrites minetest.handle_node_drops
|
-- Overwrites minetest.handle_node_drops
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
language: generic
|
language: generic
|
||||||
sudo: false
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
@ -7,6 +6,6 @@ addons:
|
||||||
before_install:
|
before_install:
|
||||||
- luarocks install --local luacheck
|
- luarocks install --local luacheck
|
||||||
script:
|
script:
|
||||||
- $HOME/.luarocks/bin/luacheck --no-color ./mods
|
- $HOME/.luarocks/bin/luacheck ./mods
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Minetest Game
|
||||||
|
|
||||||
|
The default game bundled in the Minetest engine.
|
||||||
|
|
||||||
|
For further information, check [this forum topic](https://forum.minetest.net/viewtopic.php?f=15&t=9724).
|
||||||
|
Also see the [Minetest Wiki](https://wiki.minetest.net/Subgames/Minetest_Game) for more information.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
- Unzip the archive, rename the folder to minetest_game and
|
||||||
|
place it in .. minetest/games/
|
||||||
|
|
||||||
|
- GNU/Linux: If you use a system-wide installation place
|
||||||
|
it in ~/.minetest/games/.
|
||||||
|
|
||||||
|
The Minetest engine can be found at
|
||||||
|
[GitHub](https://github.com/minetest/minetest).
|
||||||
|
|
||||||
|
For further information or help, see:
|
||||||
|
https://wiki.minetest.net/Installing_Mods
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
The Minetest Game GitHub master HEAD is generally compatible with the GitHub
|
||||||
|
master HEAD of the Minetest engine.
|
||||||
|
Additionally, when the Minetest engine is tagged to be a certain version (e.g.
|
||||||
|
0.4.10), Minetest Game is tagged with the version too.
|
||||||
|
|
||||||
|
When stable releases are made, Minetest Game and the Minetest engine is packaged and made available at
|
||||||
|
https://minetest.net/downloads/
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
|
||||||
|
See `LICENSE.txt`
|
28
README.txt
28
README.txt
|
@ -1,28 +0,0 @@
|
||||||
Minetest Game [minetest_game]
|
|
||||||
=============================
|
|
||||||
The main subgame for the Minetest engine
|
|
||||||
========================================
|
|
||||||
|
|
||||||
To use this subgame with the Minetest engine, insert this repository as
|
|
||||||
/games/minetest_game
|
|
||||||
|
|
||||||
The Minetest engine can be found in:
|
|
||||||
https://github.com/minetest/minetest/
|
|
||||||
|
|
||||||
Compatibility
|
|
||||||
--------------
|
|
||||||
The Minetest Game github master HEAD is generally compatible with the github
|
|
||||||
master HEAD of the Minetest engine.
|
|
||||||
|
|
||||||
Additionally, when the Minetest engine is tagged to be a certain version (eg.
|
|
||||||
0.4.10), Minetest Game is tagged with the version too.
|
|
||||||
|
|
||||||
When stable releases are made, Minetest Game is packaged and made available in
|
|
||||||
http://minetest.net/download
|
|
||||||
and in case the repository has grown too much, it may be reset. In that sense,
|
|
||||||
this is not a "real" git repository. (Package maintainers please note!)
|
|
||||||
|
|
||||||
Licensing
|
|
||||||
---------
|
|
||||||
|
|
||||||
See LICENSE.txt
|
|
|
@ -1 +1,3 @@
|
||||||
name = Minetest Game
|
name = Minetest Game
|
||||||
|
author = Minetest
|
||||||
|
description = Bundled by default with Minetest, and aims to be lightweight, moddable, and fairly playable without mods.
|
||||||
|
|
405
game_api.txt
405
game_api.txt
|
@ -2,10 +2,11 @@ Minetest Game API
|
||||||
=================
|
=================
|
||||||
GitHub Repo: https://github.com/minetest/minetest_game
|
GitHub Repo: https://github.com/minetest/minetest_game
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The Minetest Game subgame offers multiple new possibilities in addition to the Minetest engine's built-in API,
|
The Minetest Game game offers multiple new possibilities in addition to the Minetest engine's built-in API,
|
||||||
allowing you to add new plants to farming mod, buckets for new liquids, new stairs and custom panes.
|
allowing you to add new plants to farming mod, buckets for new liquids, new stairs and custom panes.
|
||||||
For information on the Minetest API, visit https://github.com/minetest/minetest/blob/master/doc/lua_api.txt
|
For information on the Minetest API, visit https://github.com/minetest/minetest/blob/master/doc/lua_api.txt
|
||||||
Please note:
|
Please note:
|
||||||
|
@ -14,6 +15,7 @@ Please note:
|
||||||
* [#ABC] refers to a section in this document
|
* [#ABC] refers to a section in this document
|
||||||
* [pos] refers to a position table `{x = -5, y = 0, z = 200}`
|
* [pos] refers to a position table `{x = -5, y = 0, z = 200}`
|
||||||
|
|
||||||
|
|
||||||
Bucket API
|
Bucket API
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -34,6 +36,7 @@ The bucket API allows registering new types of buckets for non-default liquids.
|
||||||
The filled bucket item is returned to the player that uses an empty bucket pointing to the given liquid source.
|
The filled bucket item is returned to the player that uses an empty bucket pointing to the given liquid source.
|
||||||
When punching with an empty bucket pointing to an entity or a non-liquid node, the on_punch of the entity or node will be triggered.
|
When punching with an empty bucket pointing to an entity or a non-liquid node, the on_punch of the entity or node will be triggered.
|
||||||
|
|
||||||
|
|
||||||
Beds API
|
Beds API
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -42,6 +45,7 @@ Beds API
|
||||||
def -- See [#Bed definition]
|
def -- See [#Bed definition]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
* `beds.can_dig(bed_pos)` Returns a boolean whether the bed at `bed_pos` may be dug
|
||||||
* `beds.read_spawns() ` Returns a table containing players respawn positions
|
* `beds.read_spawns() ` Returns a table containing players respawn positions
|
||||||
* `beds.kick_players()` Forces all players to leave bed
|
* `beds.kick_players()` Forces all players to leave bed
|
||||||
* `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping
|
* `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping
|
||||||
|
@ -67,6 +71,17 @@ Beds API
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Bones API
|
||||||
|
---------
|
||||||
|
|
||||||
|
An ordered list of listnames (default: "main", "craft") of the player inventory,
|
||||||
|
that will be placed into bones or dropped on player death can be looked up or changed
|
||||||
|
in `bones.player_inventory_lists`.
|
||||||
|
|
||||||
|
e.g. `table.insert(bones.player_inventory_lists, "backpack")`
|
||||||
|
|
||||||
|
|
||||||
Creative API
|
Creative API
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@ -88,11 +103,69 @@ The contents of `creative.formspec_add` is appended to every creative inventory
|
||||||
page. Mods can use it to add additional formspec elements onto the default
|
page. Mods can use it to add additional formspec elements onto the default
|
||||||
creative inventory formspec to be drawn after each update.
|
creative inventory formspec to be drawn after each update.
|
||||||
|
|
||||||
|
|
||||||
|
Chests API
|
||||||
|
----------
|
||||||
|
|
||||||
|
The chests API allows the creation of chests, which have their own inventories for holding items.
|
||||||
|
|
||||||
|
`default.chest.get_chest_formspec(pos)`
|
||||||
|
|
||||||
|
* Returns a formspec for a specific chest.
|
||||||
|
* `pos` Location of the chest node, e.g `{x = 1, y = 1, z = 1}`
|
||||||
|
|
||||||
|
`default.chest.chest_lid_obstructed(pos)`
|
||||||
|
|
||||||
|
* Returns a boolean depending on whether or not a chest has its top obstructed by a solid node.
|
||||||
|
* `pos` Location of the chest node, e.g `{x = 1, y = 1, z = 1}`
|
||||||
|
|
||||||
|
`default.chest.chest_lid_close(pn)`
|
||||||
|
|
||||||
|
* Closes the chest that a player is currently looking in.
|
||||||
|
* `pn` The name of the player whose chest is going to be closed
|
||||||
|
|
||||||
|
`default.chest.open_chests`
|
||||||
|
|
||||||
|
* A table indexed by player name to keep track of who opened what chest.
|
||||||
|
* Key: The name of the player.
|
||||||
|
* Value: A table containing information about the chest the player is looking at.
|
||||||
|
e.g `{ pos = {1, 1, 1}, sound = null, swap = "chest" }`
|
||||||
|
|
||||||
|
`default.chest.register_chest(name, def)`
|
||||||
|
|
||||||
|
* Registers new chest
|
||||||
|
* `name` Name for chest
|
||||||
|
* `def` See [#Chest Definition]
|
||||||
|
|
||||||
|
### Chest Definition
|
||||||
|
|
||||||
|
description = "Chest",
|
||||||
|
tiles = {
|
||||||
|
"default_chest_top.png",
|
||||||
|
"default_chest_top.png",
|
||||||
|
"default_chest_side.png",
|
||||||
|
"default_chest_side.png",
|
||||||
|
"default_chest_front.png",
|
||||||
|
"default_chest_inside.png"
|
||||||
|
}, -- Textures which are applied to the chest model.
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
sound_open = "default_chest_open",
|
||||||
|
sound_close = "default_chest_close",
|
||||||
|
groups = {choppy = 2, oddly_breakable_by_hand = 2},
|
||||||
|
protected = false, -- If true, only placer can modify chest.
|
||||||
|
|
||||||
|
|
||||||
Doors API
|
Doors API
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The doors mod allows modders to register custom doors and trapdoors.
|
The doors mod allows modders to register custom doors and trapdoors.
|
||||||
|
|
||||||
|
`doors.registered_doors[name] = Door definition`
|
||||||
|
* Table of registered doors, indexed by door name
|
||||||
|
|
||||||
|
`doors.registered_trapdoors[name] = Trapdoor definition`
|
||||||
|
* Table of registered trap doors, indexed by trap door name
|
||||||
|
|
||||||
`doors.register_door(name, def)`
|
`doors.register_door(name, def)`
|
||||||
|
|
||||||
* Registers new door
|
* Registers new door
|
||||||
|
@ -128,17 +201,28 @@ The doors mod allows modders to register custom doors and trapdoors.
|
||||||
has the permissions needed to open this door. If omitted then no
|
has the permissions needed to open this door. If omitted then no
|
||||||
permission checks are performed.
|
permission checks are performed.
|
||||||
|
|
||||||
|
`doors.door_toggle(pos, node, clicker)`
|
||||||
|
|
||||||
|
* Toggle door open or shut
|
||||||
|
* `pos` Position of the door
|
||||||
|
* `node` Node definition
|
||||||
|
* `clicker` Player definition for the player that clicked on the door
|
||||||
|
|
||||||
### Door definition
|
### Door definition
|
||||||
|
|
||||||
description = "Door description",
|
description = "Door description",
|
||||||
inventory_image = "mod_door_inv.png",
|
inventory_image = "mod_door_inv.png",
|
||||||
groups = {choppy = 2},
|
groups = {choppy = 2},
|
||||||
tiles = {"mod_door.png"}, -- UV map.
|
tiles = {"mod_door.png"}, -- UV map.
|
||||||
|
-- The front and back of the door must be identical in appearence as they swap on
|
||||||
|
-- open/close.
|
||||||
recipe = craftrecipe,
|
recipe = craftrecipe,
|
||||||
sounds = default.node_sound_wood_defaults(), -- optional
|
sounds = default.node_sound_wood_defaults(), -- optional
|
||||||
sound_open = sound play for open door, -- optional
|
sound_open = sound play for open door, -- optional
|
||||||
sound_close = sound play for close door, -- optional
|
sound_close = sound play for close door, -- optional
|
||||||
protected = false, -- If true, only placer can open the door (locked for others)
|
protected = false, -- If true, only placer can open the door (locked for others)
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
-- optional function containing the on_rightclick callback, defaults to a doors.door_toggle-wrapper
|
||||||
|
|
||||||
### Trapdoor definition
|
### Trapdoor definition
|
||||||
|
|
||||||
|
@ -146,11 +230,20 @@ The doors mod allows modders to register custom doors and trapdoors.
|
||||||
inventory_image = "mod_trapdoor_inv.png",
|
inventory_image = "mod_trapdoor_inv.png",
|
||||||
groups = {choppy = 2},
|
groups = {choppy = 2},
|
||||||
tile_front = "doors_trapdoor.png", -- the texture for the front and back of the trapdoor
|
tile_front = "doors_trapdoor.png", -- the texture for the front and back of the trapdoor
|
||||||
tile_side = "doors_trapdoor_side.png", -- the tiles of the four side parts of the trapdoor
|
tile_side = "doors_trapdoor_side.png",
|
||||||
|
-- The texture for the four sides of the trapdoor.
|
||||||
|
-- The texture should have the trapdoor side drawn twice, in the lowest and highest
|
||||||
|
-- 1/8ths of the texture, both upright. The area between is not used.
|
||||||
|
-- The lower 1/8th will be used for the closed trapdoor, the higher 1/8th will be used
|
||||||
|
-- for the open trapdoor.
|
||||||
sounds = default.node_sound_wood_defaults(), -- optional
|
sounds = default.node_sound_wood_defaults(), -- optional
|
||||||
sound_open = sound play for open door, -- optional
|
sound_open = sound play for open door, -- optional
|
||||||
sound_close = sound play for close door, -- optional
|
sound_close = sound play for close door, -- optional
|
||||||
protected = false, -- If true, only placer can open the door (locked for others)
|
protected = false, -- If true, only placer can open the door (locked for others)
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
-- function containing the on_rightclick callback
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
-- function containing the on_rightclick callback
|
||||||
|
|
||||||
### Fence gate definition
|
### Fence gate definition
|
||||||
|
|
||||||
|
@ -160,6 +253,43 @@ The doors mod allows modders to register custom doors and trapdoors.
|
||||||
material = "default:wood",
|
material = "default:wood",
|
||||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||||
sounds = default.node_sound_wood_defaults(), -- optional
|
sounds = default.node_sound_wood_defaults(), -- optional
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
-- function containing the on_rightclick callback
|
||||||
|
|
||||||
|
|
||||||
|
Dungeon Loot API
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The mod that places chests with loot in dungeons provides an API to register additional loot.
|
||||||
|
|
||||||
|
`dungeon_loot.register(def)`
|
||||||
|
|
||||||
|
* Registers one or more loot items
|
||||||
|
* `def` Can be a single [#Loot definition] or a list of them
|
||||||
|
|
||||||
|
`dungeon_loot.registered_loot`
|
||||||
|
|
||||||
|
* Table of all registered loot, not to be modified manually
|
||||||
|
|
||||||
|
### Loot definition
|
||||||
|
|
||||||
|
name = "item:name",
|
||||||
|
chance = 0.5,
|
||||||
|
-- ^ chance value from 0.0 to 1.0 that the item will appear in the chest when chosen
|
||||||
|
-- Due to an extra step in the selection process, 0.5 does not(!) mean that
|
||||||
|
-- on average every second chest will have this item
|
||||||
|
count = {1, 4},
|
||||||
|
-- ^ table with minimum and maximum amounts of this item
|
||||||
|
-- optional, defaults to always single item
|
||||||
|
y = {-32768, -512},
|
||||||
|
-- ^ table with minimum and maximum heights this item can be found at
|
||||||
|
-- optional, defaults to no height restrictions
|
||||||
|
types = {"desert"},
|
||||||
|
-- ^ table with types of dungeons this item can be found in
|
||||||
|
-- supported types: "normal" (the cobble/mossycobble one), "sandstone"
|
||||||
|
-- "desert" and "ice"
|
||||||
|
-- optional, defaults to no type restrictions
|
||||||
|
|
||||||
|
|
||||||
Fence API
|
Fence API
|
||||||
---------
|
---------
|
||||||
|
@ -182,6 +312,7 @@ Allows creation of new fences with "fencelike" drawtype.
|
||||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
|
||||||
|
|
||||||
Walls API
|
Walls API
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -194,6 +325,7 @@ walls.register(name, desc, texture, mat, sounds)
|
||||||
^ mat = "default:stone". Used to auto-generate crafting recipe.
|
^ mat = "default:stone". Used to auto-generate crafting recipe.
|
||||||
^ sounds = sounds: see [#Default sounds]
|
^ sounds = sounds: see [#Default sounds]
|
||||||
|
|
||||||
|
|
||||||
Farming API
|
Farming API
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -234,9 +366,12 @@ The farming API allows you to easily register plants and hoes.
|
||||||
maxlight = default.LIGHT_MAX -- Maximum light to grow
|
maxlight = default.LIGHT_MAX -- Maximum light to grow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Fire API
|
Fire API
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
Add group flammable when registering a node to make fire seek for it.
|
||||||
|
Add it to an item to make it burn up when dropped in lava or fire.
|
||||||
New node def property:
|
New node def property:
|
||||||
|
|
||||||
`on_burn(pos)`
|
`on_burn(pos)`
|
||||||
|
@ -284,8 +419,62 @@ Give Initial Stuff API
|
||||||
^ Adds items to the list of items to be given
|
^ Adds items to the list of items to be given
|
||||||
|
|
||||||
|
|
||||||
|
Players API
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The player API can register player models and update the player's appearence
|
||||||
|
|
||||||
|
* `player_api.register_model(name, def)`
|
||||||
|
* Register a new model to be used by players
|
||||||
|
* name: model filename such as "character.x", "foo.b3d", etc.
|
||||||
|
* def: See [#Model definition]
|
||||||
|
* saved to player_api.registered_models
|
||||||
|
|
||||||
|
* `player_api.registered_player_models[name]`
|
||||||
|
* Get a model's definition
|
||||||
|
* see [#Model definition]
|
||||||
|
|
||||||
|
* `player_api.set_model(player, model_name)`
|
||||||
|
* Change a player's model
|
||||||
|
* `player`: PlayerRef
|
||||||
|
* `model_name`: model registered with player_api.register_model()
|
||||||
|
|
||||||
|
* `player_api.set_animation(player, anim_name [, speed])`
|
||||||
|
* Applies an animation to a player
|
||||||
|
* anim_name: name of the animation.
|
||||||
|
* speed: frames per second. If nil, default from the model is used
|
||||||
|
|
||||||
|
* `player_api.set_textures(player, textures)`
|
||||||
|
* Sets player textures
|
||||||
|
* `player`: PlayerRef
|
||||||
|
* `textures`: array of textures, If `textures` is nil the default
|
||||||
|
textures from the model def are used
|
||||||
|
|
||||||
|
* `player_api.get_animation(player)`
|
||||||
|
* Returns a table containing fields `model`, `textures` and `animation`.
|
||||||
|
* Any of the fields of the returned table may be nil.
|
||||||
|
* player: PlayerRef
|
||||||
|
|
||||||
|
### Model Definition
|
||||||
|
|
||||||
|
{
|
||||||
|
animation_speed = 30, -- Default animation speed, in FPS.
|
||||||
|
textures = {"character.png", }, -- Default array of textures.
|
||||||
|
visual_size = {x = 1, y = 1}, -- Used to scale the model.
|
||||||
|
animations = {
|
||||||
|
-- <anim_name> = {x = <start_frame>, y = <end_frame>},
|
||||||
|
foo = {x = 0, y = 19},
|
||||||
|
bar = {x = 20, y = 39},
|
||||||
|
-- ...
|
||||||
|
},
|
||||||
|
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, -- In nodes from feet position
|
||||||
|
stepheight = 0.6, -- In nodes
|
||||||
|
eye_height = 1.47, -- In nodes above feet position
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TNT API
|
TNT API
|
||||||
----------
|
-------
|
||||||
|
|
||||||
`tnt.register_tnt(definition)`
|
`tnt.register_tnt(definition)`
|
||||||
|
|
||||||
|
@ -295,6 +484,7 @@ TNT API
|
||||||
* `description` A description for your TNT.
|
* `description` A description for your TNT.
|
||||||
* `radius` The radius within which the TNT can destroy nodes. The default is 3.
|
* `radius` The radius within which the TNT can destroy nodes. The default is 3.
|
||||||
* `damage_radius` The radius within which the TNT can damage players and mobs. By default it is twice the `radius`.
|
* `damage_radius` The radius within which the TNT can damage players and mobs. By default it is twice the `radius`.
|
||||||
|
* `sound` The sound played when explosion occurs. By default it is `tnt_explode`.
|
||||||
* `disable_drops` Disable drops. By default it is set to false.
|
* `disable_drops` Disable drops. By default it is set to false.
|
||||||
* `ignore_protection` Don't check `minetest.is_protected` before removing a node.
|
* `ignore_protection` Don't check `minetest.is_protected` before removing a node.
|
||||||
* `ignore_on_blast` Don't call `on_blast` even if a node has one.
|
* `ignore_on_blast` Don't call `on_blast` even if a node has one.
|
||||||
|
@ -402,11 +592,15 @@ set a players home position and teleport a player to home position.
|
||||||
Sfinv API
|
Sfinv API
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
It is recommended that you read this link for a good introduction to the
|
||||||
|
sfinv API by its author: https://rubenwardy.com/minetest_modding_book/en/chapters/sfinv.html
|
||||||
|
|
||||||
### sfinv Methods
|
### sfinv Methods
|
||||||
|
|
||||||
**Pages**
|
**Pages**
|
||||||
|
|
||||||
* sfinv.set_page(player, pagename) - changes the page
|
* sfinv.set_page(player, pagename) - changes the page
|
||||||
|
* sfinv.get_page(player) - get the current page name. Will never return nil
|
||||||
* sfinv.get_homepage_name(player) - get the page name of the first page to show to a player
|
* sfinv.get_homepage_name(player) - get the page name of the first page to show to a player
|
||||||
* sfinv.register_page(name, def) - register a page, see section below
|
* sfinv.register_page(name, def) - register a page, see section below
|
||||||
* sfinv.override_page(name, def) - overrides fields of an page registered with register_page.
|
* sfinv.override_page(name, def) - overrides fields of an page registered with register_page.
|
||||||
|
@ -503,39 +697,65 @@ And override this function to change the layout:
|
||||||
return table.concat(tmp, "")
|
return table.concat(tmp, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
Stairs API
|
Stairs API
|
||||||
----------
|
----------
|
||||||
|
|
||||||
The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those
|
The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those
|
||||||
delivered with Minetest Game, to keep them compatible with other mods.
|
delivered with Minetest Game, to keep them compatible with other mods.
|
||||||
|
|
||||||
`stairs.register_stair(subname, recipeitem, groups, images, description, sounds)`
|
`stairs.register_stair(subname, recipeitem, groups, images, description, sounds, worldaligntex)`
|
||||||
|
|
||||||
* Registers a stair.
|
* Registers a stair
|
||||||
* `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname"
|
* `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname"
|
||||||
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil`
|
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil`
|
||||||
* `groups`: see [Known damage and digging time defining groups]
|
* `groups`: See [Known damage and digging time defining groups]
|
||||||
* `images`: see [Tile definition]
|
* `images`: See [Tile definition]
|
||||||
* `description`: used for the description field in the stair's definition
|
* `description`: Used for the description field in the stair's definition
|
||||||
* `sounds`: see [#Default sounds]
|
* `sounds`: See [#Default sounds]
|
||||||
|
* `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition]
|
||||||
|
|
||||||
`stairs.register_slab(subname, recipeitem, groups, images, description, sounds)`
|
`stairs.register_slab(subname, recipeitem, groups, images, description, sounds, worldaligntex)`
|
||||||
|
|
||||||
* Registers a slabs
|
* Registers a slab
|
||||||
* `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname"
|
* `subname`: Basically the material name (e.g. cobble) used for the slab name. Nodename pattern: "stairs:slab_subname"
|
||||||
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble"
|
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble"
|
||||||
* `groups`: see [Known damage and digging time defining groups]
|
* `groups`: See [Known damage and digging time defining groups]
|
||||||
* `images`: see [Tile definition]
|
* `images`: See [Tile definition]
|
||||||
* `description`: used for the description field in the stair's definition
|
* `description`: Used for the description field in the slab's definition
|
||||||
* `sounds`: see [#Default sounds]
|
* `sounds`: See [#Default sounds]
|
||||||
|
* `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition]
|
||||||
|
|
||||||
`stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds)`
|
`stairs.register_stair_inner(subname, recipeitem, groups, images, description, sounds, worldaligntex)`
|
||||||
|
|
||||||
* A wrapper for stairs.register_stair and stairs.register_slab
|
* Registers an inner corner stair
|
||||||
|
* `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_inner_subname"
|
||||||
|
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil`
|
||||||
|
* `groups`: See [Known damage and digging time defining groups]
|
||||||
|
* `images`: See [Tile definition]
|
||||||
|
* `description`: Used for the description field in the stair's definition
|
||||||
|
* `sounds`: See [#Default sounds]
|
||||||
|
* `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition]
|
||||||
|
|
||||||
|
`stairs.register_stair_outer(subname, recipeitem, groups, images, description, sounds, worldaligntex)`
|
||||||
|
|
||||||
|
* Registers an outer corner stair
|
||||||
|
* `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_outer_subname"
|
||||||
|
* `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil`
|
||||||
|
* `groups`: See [Known damage and digging time defining groups]
|
||||||
|
* `images`: See [Tile definition]
|
||||||
|
* `description`: Used for the description field in the stair's definition
|
||||||
|
* `sounds`: See [#Default sounds]
|
||||||
|
* `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition]
|
||||||
|
|
||||||
|
`stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds, worldaligntex)`
|
||||||
|
|
||||||
|
* A wrapper for stairs.register_stair, stairs.register_slab, stairs.register_stair_inner, stairs.register_stair_outer
|
||||||
* Uses almost the same arguments as stairs.register_stair
|
* Uses almost the same arguments as stairs.register_stair
|
||||||
* `desc_stair`: Description for stair node
|
* `desc_stair`: Description for stair nodes. For corner stairs 'Inner' or 'Outer' will be prefixed
|
||||||
* `desc_slab`: Description for slab node
|
* `desc_slab`: Description for slab node
|
||||||
|
|
||||||
|
|
||||||
Xpanes API
|
Xpanes API
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -553,8 +773,10 @@ Creates panes that automatically connect to each other
|
||||||
groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups]
|
groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups]
|
||||||
sounds = SoundSpec, -- See [#Default sounds]
|
sounds = SoundSpec, -- See [#Default sounds]
|
||||||
recipe = {{"","","","","","","","",""}}, -- Recipe field only
|
recipe = {{"","","","","","","","",""}}, -- Recipe field only
|
||||||
|
use_texture_alpha = true, -- Optional boolean (default: `false`) for colored glass panes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Raillike definitions
|
Raillike definitions
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -588,64 +810,48 @@ Sounds inside the default table can be used within the sounds field of node defi
|
||||||
* `default.node_sound_glass_defaults()`
|
* `default.node_sound_glass_defaults()`
|
||||||
* `default.node_sound_metal_defaults()`
|
* `default.node_sound_metal_defaults()`
|
||||||
|
|
||||||
|
|
||||||
Default constants
|
Default constants
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
`default.LIGHT_MAX` The maximum light level (see [Node definition] light_source)
|
`default.LIGHT_MAX` The maximum light level (see [Node definition] light_source)
|
||||||
|
|
||||||
Player API
|
|
||||||
----------
|
|
||||||
|
|
||||||
The player API can register player models and update the player's appearence
|
GUI and formspecs
|
||||||
|
-----------------
|
||||||
|
|
||||||
`default.player_register_model(name, def)`
|
`default.get_hotbar_bg(x, y)`
|
||||||
|
|
||||||
* Register a new model to be used by players.
|
* Get the hotbar background as string, containing the formspec elements
|
||||||
* name: model filename such as "character.x", "foo.b3d", etc.
|
* x: Horizontal position in the formspec
|
||||||
* def: See [#Model definition]
|
* y: Vertical position in the formspec
|
||||||
|
|
||||||
`default.registered_player_models[name]`
|
`default.gui_bg`
|
||||||
|
|
||||||
* Get a model's definition
|
* Deprecated, remove from mods.
|
||||||
* see [#Model definition]
|
|
||||||
|
|
||||||
`default.player_set_model(player, model_name)`
|
`default.gui_bg_img`
|
||||||
|
|
||||||
* Change a player's model
|
* Deprecated, remove from mods.
|
||||||
* `player`: PlayerRef
|
|
||||||
* `model_name`: model registered with player_register_model()
|
|
||||||
|
|
||||||
`default.player_set_animation(player, anim_name [, speed])`
|
`default.gui_slots`
|
||||||
|
|
||||||
* Applies an animation to a player
|
* Deprecated, remove from mods.
|
||||||
* anim_name: name of the animation.
|
|
||||||
* speed: frames per second. If nil, default from the model is used
|
|
||||||
|
|
||||||
`default.player_set_textures(player, textures)`
|
`default.gui_survival_form`
|
||||||
|
|
||||||
* Sets player textures
|
* Entire formspec for the survival inventory
|
||||||
* `player`: PlayerRef
|
|
||||||
* `textures`: array of textures, If `textures` is nil, the default textures from the model def are used
|
|
||||||
|
|
||||||
default.player_get_animation(player)
|
`default.get_furnace_active_formspec(fuel_percent, item_percent)`
|
||||||
|
|
||||||
* Returns a table containing fields `model`, `textures` and `animation`.
|
* Get the active furnace formspec using the defined GUI elements
|
||||||
* Any of the fields of the returned table may be nil.
|
* fuel_percent: Percent of how much the fuel is used
|
||||||
* player: PlayerRef
|
* item_percent: Percent of how much the item is cooked
|
||||||
|
|
||||||
### Model Definition
|
`default.get_furnace_inactive_formspec()`
|
||||||
|
|
||||||
|
* Get the inactive furnace formspec using the defined GUI elements
|
||||||
|
|
||||||
{
|
|
||||||
animation_speed = 30, -- Default animation speed, in FPS.
|
|
||||||
textures = {"character.png", }, -- Default array of textures.
|
|
||||||
visual_size = {x = 1, y = 1}, -- Used to scale the model.
|
|
||||||
animations = {
|
|
||||||
-- <anim_name> = {x = <start_frame>, y = <end_frame>},
|
|
||||||
foo = {x = 0, y = 19},
|
|
||||||
bar = {x = 20, y = 39},
|
|
||||||
-- ...
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Leafdecay
|
Leafdecay
|
||||||
---------
|
---------
|
||||||
|
@ -684,70 +890,39 @@ callback overridden. All the nodes listed in `leaves` have their
|
||||||
Dyes
|
Dyes
|
||||||
----
|
----
|
||||||
|
|
||||||
To make recipes that will work with any dye ever made by anybody, define
|
Minetest Game dyes are registered with:
|
||||||
them based on groups. You can select any group of groups, based on your need for
|
|
||||||
amount of colors.
|
|
||||||
|
|
||||||
### Color groups
|
groups = {dye = 1, color_<color> = 1},
|
||||||
|
|
||||||
Base color groups:
|
To make recipes that will work with dyes from many mods, define them using the
|
||||||
|
dye group and the color groups.
|
||||||
|
|
||||||
* `basecolor_white`
|
Dye color groups:
|
||||||
* `basecolor_grey`
|
|
||||||
* `basecolor_black`
|
|
||||||
* `basecolor_red`
|
|
||||||
* `basecolor_yellow`
|
|
||||||
* `basecolor_green`
|
|
||||||
* `basecolor_cyan`
|
|
||||||
* `basecolor_blue`
|
|
||||||
* `basecolor_magenta`
|
|
||||||
|
|
||||||
Extended color groups ( * means also base color )
|
* `color_white`
|
||||||
|
* `color_grey`
|
||||||
|
* `color_dark_grey`
|
||||||
|
* `color_black`
|
||||||
|
* `color_red`
|
||||||
|
* `color_pink`
|
||||||
|
* `color_orange`
|
||||||
|
* `color_brown`
|
||||||
|
* `color_yellow`
|
||||||
|
* `color_green`
|
||||||
|
* `color_dark_green`
|
||||||
|
* `color_blue`
|
||||||
|
* `color_cyan`
|
||||||
|
* `color_violet`
|
||||||
|
* `color_magenta`
|
||||||
|
|
||||||
* `excolor_white` *
|
Example of one shapeless recipe using the dye group and a color group:
|
||||||
* `excolor_lightgrey`
|
|
||||||
* `excolor_grey` *
|
|
||||||
* `excolor_darkgrey`
|
|
||||||
* `excolor_black` *
|
|
||||||
* `excolor_red` *
|
|
||||||
* `excolor_orange`
|
|
||||||
* `excolor_yellow` *
|
|
||||||
* `excolor_lime`
|
|
||||||
* `excolor_green` *
|
|
||||||
* `excolor_aqua`
|
|
||||||
* `excolor_cyan` *
|
|
||||||
* `excolor_sky_blue`
|
|
||||||
* `excolor_blue` *
|
|
||||||
* `excolor_violet`
|
|
||||||
* `excolor_magenta` *
|
|
||||||
* `excolor_red_violet`
|
|
||||||
|
|
||||||
The whole unifieddyes palette as groups:
|
|
||||||
|
|
||||||
* `unicolor_<excolor>`
|
|
||||||
|
|
||||||
For the following, no white/grey/black is allowed:
|
|
||||||
|
|
||||||
* `unicolor_medium_<excolor>`
|
|
||||||
* `unicolor_dark_<excolor>`
|
|
||||||
* `unicolor_light_<excolor>`
|
|
||||||
* `unicolor_<excolor>_s50`
|
|
||||||
* `unicolor_medium_<excolor>_s50`
|
|
||||||
* `unicolor_dark_<excolor>_s50`
|
|
||||||
|
|
||||||
Example of one shapeless recipe using a color group:
|
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = '<mod>:item_yellow',
|
output = "<mod>:item_yellow",
|
||||||
recipe = {'<mod>:item_no_color', 'group:basecolor_yellow'},
|
recipe = {"<mod>:item_no_color", "group:dye,color_yellow"},
|
||||||
})
|
})
|
||||||
|
|
||||||
### Color lists
|
|
||||||
|
|
||||||
* `dye.basecolors` are an array containing the names of available base colors
|
|
||||||
|
|
||||||
* `dye.excolors` are an array containing the names of the available extended colors
|
|
||||||
|
|
||||||
Trees
|
Trees
|
||||||
-----
|
-----
|
||||||
|
@ -785,6 +960,13 @@ Trees
|
||||||
* `default.grow_acacia_bush(pos)`
|
* `default.grow_acacia_bush(pos)`
|
||||||
* Grows an acaia bush at pos
|
* Grows an acaia bush at pos
|
||||||
|
|
||||||
|
* `default.grow_pine_bush(pos)`
|
||||||
|
* Grows a pine bush at pos
|
||||||
|
|
||||||
|
* `default.grow_blueberry_bush(pos)`
|
||||||
|
* Grows a blueberry bush at pos
|
||||||
|
|
||||||
|
|
||||||
Carts
|
Carts
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -807,6 +989,7 @@ Carts
|
||||||
likely be called many times per second, so the function needs
|
likely be called many times per second, so the function needs
|
||||||
to make sure that the event is handled properly.
|
to make sure that the event is handled properly.
|
||||||
|
|
||||||
|
|
||||||
Key API
|
Key API
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,63 @@
|
||||||
|
# Transforms the generic po file produced by weblate into a series of
|
||||||
|
# locale/[modname].ja.tr files.
|
||||||
|
|
||||||
|
# TODO: make it work for all languages!
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
strings=dict()
|
||||||
|
modstr=defaultdict(list)
|
||||||
|
for modname in os.listdir("../mods/"):
|
||||||
|
for fn in os.listdir("../mods/"+modname):
|
||||||
|
if fn.endswith(".lua"):
|
||||||
|
s=open("../mods/"+modname+"/"+fn).read()
|
||||||
|
for gtstring in re.findall("S\(.*\)", s):
|
||||||
|
k=gtstring[3:-2]
|
||||||
|
strings[k]=modname
|
||||||
|
modstr[modname].append(k)
|
||||||
|
"""
|
||||||
|
for m in modstr.keys():
|
||||||
|
print(m)
|
||||||
|
for v in modstr[m]:
|
||||||
|
print("\t"+v)
|
||||||
|
"""
|
||||||
|
locales = list()
|
||||||
|
for fn in os.listdir("."):
|
||||||
|
if fn .endswith(".po"):
|
||||||
|
locales.append(fn[:-3])
|
||||||
|
print(locales)
|
||||||
|
|
||||||
|
notused=set()
|
||||||
|
for loc in locales:
|
||||||
|
matches = 0
|
||||||
|
nom = 0
|
||||||
|
msgid = None
|
||||||
|
translation = dict()
|
||||||
|
for line in open(loc+".po"):
|
||||||
|
match = re.match('[^#]*msgstr[ \t]+"(.*)"', line)
|
||||||
|
if match and msgid is not None:
|
||||||
|
translation[msgid]=match.group(1)
|
||||||
|
match = re.match('[^#]*msgid[ \t]+"(.*)"', line)
|
||||||
|
if match:
|
||||||
|
msgid = match.group(1)
|
||||||
|
if msgid in strings:
|
||||||
|
matches+=1
|
||||||
|
else:
|
||||||
|
nom+=1
|
||||||
|
notused.add(msgid)
|
||||||
|
else:
|
||||||
|
msgid=None
|
||||||
|
|
||||||
|
print("{}: {}/{}".format(loc, matches, matches+nom))
|
||||||
|
|
||||||
|
for modname in os.listdir("../mods/"):
|
||||||
|
os.makedirs("../mods/{0}/locale".format(modname), exist_ok=True)
|
||||||
|
localefile = open("../mods/{0}/locale/{0}.{1}.tr".format(modname, loc), "w")
|
||||||
|
localefile.write("# textdomain: "+modname+"\n\n")
|
||||||
|
for k in modstr[modname]:
|
||||||
|
if k in translation:
|
||||||
|
localefile.write("{}={}\n\n".format(k,translation[k]))
|
||||||
|
localefile.close()
|
||||||
|
print(notused)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,21 @@
|
||||||
# This file contains settings of Minetest Game that can be changed in minetest.conf
|
# This file contains settings of Minetest Game that can be changed in
|
||||||
|
# minetest.conf.
|
||||||
# By default, all the settings are commented and not functional.
|
# By default, all the settings are commented and not functional.
|
||||||
# Uncomment settings by removing the preceding #.
|
# Uncomment settings by removing the preceding #.
|
||||||
|
|
||||||
# Whether creative mode (fast digging of all blocks, unlimited resources) should be enabled
|
# Whether creative mode (fast digging of all blocks, unlimited resources) should
|
||||||
|
# be enabled.
|
||||||
#creative_mode = false
|
#creative_mode = false
|
||||||
|
|
||||||
# Sets the behaviour of the inventory items when a player dies.
|
# Sets the behaviour of the inventory items when a player dies.
|
||||||
# "bones": Store all items inside a bone node but drop items if inside protected area
|
# bones: Store items in a bone node but drop items if inside protected area.
|
||||||
# "drop": Drop all items on the ground
|
# drop: Drop items on the ground.
|
||||||
# "keep": Player keeps all items
|
# keep: Player keeps items.
|
||||||
#bones_mode = "bones"
|
#bones_mode = bones
|
||||||
|
|
||||||
# The time in seconds after which the bones of a dead player can be looted by everyone
|
# The time in seconds after which the bones of a dead player can be looted by
|
||||||
# 0 to disable
|
# everyone.
|
||||||
|
# 0 to disable.
|
||||||
#share_bones_time = 1200
|
#share_bones_time = 1200
|
||||||
|
|
||||||
# How much earlier the bones of a dead player can be looted by
|
# How much earlier the bones of a dead player can be looted by
|
||||||
|
@ -20,8 +23,12 @@
|
||||||
# 0 to disable. By default it is "share_bones_time" divide by four.
|
# 0 to disable. By default it is "share_bones_time" divide by four.
|
||||||
#share_bones_time_early = 300
|
#share_bones_time_early = 300
|
||||||
|
|
||||||
# Whether fire should be enabled. If disabled, 'basic flame' nodes will disappear.
|
# Inform player of condition and location of new bones.
|
||||||
# 'permanent flame' nodes will remain with either setting.
|
#bones_position_message = false
|
||||||
|
|
||||||
|
# Whether fire should be enabled. If disabled, 'basic_flame' nodes will
|
||||||
|
# disappear.
|
||||||
|
# 'permanent_flame' nodes will remain with either setting.
|
||||||
#enable_fire = true
|
#enable_fire = true
|
||||||
|
|
||||||
# Enable flame sound.
|
# Enable flame sound.
|
||||||
|
@ -30,24 +37,30 @@
|
||||||
# Whether lavacooling should be enabled.
|
# Whether lavacooling should be enabled.
|
||||||
#enable_lavacooling = true
|
#enable_lavacooling = true
|
||||||
|
|
||||||
# Whether the stuff in initial_stuff should be given to new players
|
# Whether the stuff in initial_stuff should be given to new players.
|
||||||
#give_initial_stuff = false
|
#give_initial_stuff = false
|
||||||
#initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,default:torch 99,default:cobble 99
|
#initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,
|
||||||
|
default:torch 99,default:cobble 99
|
||||||
|
|
||||||
# Whether the TNT mod should be enabled
|
# Whether the TNT mod should be enabled.
|
||||||
#enable_tnt = <true in singleplayer, false in multiplayer>
|
#enable_tnt = <true in singleplayer, false in multiplayer>
|
||||||
|
|
||||||
# The radius of a TNT explosion
|
# The radius of a TNT explosion.
|
||||||
#tnt_radius = 3
|
#tnt_radius = 3
|
||||||
|
|
||||||
# Enable the stairs mod ABM that replaces the old 'upside down'
|
# Enable the stairs mod ABM that replaces the old 'upside down'
|
||||||
# stair and slab nodes in old maps with the new param2 versions.
|
# stair and slab nodes in old maps with the new param2 versions.
|
||||||
#enable_stairs_replace_abm = false
|
#enable_stairs_replace_abm = false
|
||||||
|
|
||||||
# Whether you allow respawning in beds
|
# Whether to allow respawning in beds.
|
||||||
# Default value is true
|
# Default value is true.
|
||||||
#enable_bed_respawn = true
|
#enable_bed_respawn = true
|
||||||
|
|
||||||
# Whether players can skip night by sleeping
|
# Whether players can skip night by sleeping.
|
||||||
# Default value is true
|
# Default value is true.
|
||||||
#enable_bed_night_skip = true
|
#enable_bed_night_skip = true
|
||||||
|
|
||||||
|
# Whether the engine's spawn search, which does not check for a suitable
|
||||||
|
# starting biome, is used.
|
||||||
|
# Default value is false.
|
||||||
|
#engine_spawn = false
|
||||||
|
|
|
@ -10,6 +10,10 @@ Various Minetest developers and contributors (MIT)
|
||||||
Authors of media (textures)
|
Authors of media (textures)
|
||||||
---------------------------
|
---------------------------
|
||||||
BlockMen (CC BY-SA 3.0)
|
BlockMen (CC BY-SA 3.0)
|
||||||
|
All textures unless otherwise noted
|
||||||
|
|
||||||
|
TumeniNodes (CC BY-SA 3.0)
|
||||||
|
beds_bed_under.png
|
||||||
|
|
||||||
This mod adds a bed to Minetest which allows to skip the night.
|
This mod adds a bed to Minetest which allows to skip the night.
|
||||||
To sleep, rightclick the bed. If playing in singleplayer mode the night gets skipped
|
To sleep, rightclick the bed. If playing in singleplayer mode the night gets skipped
|
||||||
|
|
|
@ -109,7 +109,7 @@ function beds.register_bed(name, def)
|
||||||
return itemstack
|
return itemstack
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_rotate = function(pos, node, user, mode, new_param2)
|
on_rotate = function(pos, node, user, _, new_param2)
|
||||||
local dir = minetest.facedir_to_dir(node.param2)
|
local dir = minetest.facedir_to_dir(node.param2)
|
||||||
local p = vector.add(pos, dir)
|
local p = vector.add(pos, dir)
|
||||||
local node2 = minetest.get_node_or_nil(p)
|
local node2 = minetest.get_node_or_nil(p)
|
||||||
|
@ -121,7 +121,7 @@ function beds.register_bed(name, def)
|
||||||
minetest.record_protection_violation(p, user:get_player_name())
|
minetest.record_protection_violation(p, user:get_player_name())
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if mode ~= screwdriver.ROTATE_FACE then
|
if new_param2 % 32 > 3 then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
|
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
|
||||||
|
@ -141,6 +141,9 @@ function beds.register_bed(name, def)
|
||||||
minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
|
minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
return beds.can_dig(pos)
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node(name .. "_top", {
|
minetest.register_node(name .. "_top", {
|
||||||
|
@ -160,6 +163,12 @@ function beds.register_bed(name, def)
|
||||||
on_destruct = function(pos)
|
on_destruct = function(pos)
|
||||||
destruct_bed(pos, 2)
|
destruct_bed(pos, 2)
|
||||||
end,
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
local dir = minetest.facedir_to_dir(node.param2)
|
||||||
|
local p = vector.add(pos, dir)
|
||||||
|
return beds.can_dig(p)
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_alias(name, name .. "_bottom")
|
minetest.register_alias(name, name .. "_bottom")
|
||||||
|
|
|
@ -1,25 +1,30 @@
|
||||||
|
-- beds/beds.lua
|
||||||
|
|
||||||
|
-- support for MT game translation.
|
||||||
|
local S = beds.get_translator
|
||||||
|
|
||||||
-- Fancy shaped bed
|
-- Fancy shaped bed
|
||||||
|
|
||||||
beds.register_bed("beds:fancy_bed", {
|
beds.register_bed("beds:fancy_bed", {
|
||||||
description = "Fancy Bed",
|
description = S("Fancy Bed"),
|
||||||
inventory_image = "beds_bed_fancy.png",
|
inventory_image = "beds_bed_fancy.png",
|
||||||
wield_image = "beds_bed_fancy.png",
|
wield_image = "beds_bed_fancy.png",
|
||||||
tiles = {
|
tiles = {
|
||||||
bottom = {
|
bottom = {
|
||||||
"beds_bed_top1.png",
|
"beds_bed_top1.png",
|
||||||
"default_wood.png",
|
"beds_bed_under.png",
|
||||||
"beds_bed_side1.png",
|
"beds_bed_side1.png",
|
||||||
"beds_bed_side1.png^[transformFX",
|
"beds_bed_side1.png^[transformFX",
|
||||||
"default_wood.png",
|
"beds_bed_foot.png",
|
||||||
"beds_bed_foot.png",
|
"beds_bed_foot.png",
|
||||||
},
|
},
|
||||||
top = {
|
top = {
|
||||||
"beds_bed_top2.png",
|
"beds_bed_top2.png",
|
||||||
"default_wood.png",
|
"beds_bed_under.png",
|
||||||
"beds_bed_side2.png",
|
"beds_bed_side2.png",
|
||||||
"beds_bed_side2.png^[transformFX",
|
"beds_bed_side2.png^[transformFX",
|
||||||
"beds_bed_head.png",
|
"beds_bed_head.png",
|
||||||
"default_wood.png",
|
"beds_bed_head.png",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nodebox = {
|
nodebox = {
|
||||||
|
@ -44,7 +49,7 @@ beds.register_bed("beds:fancy_bed", {
|
||||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
||||||
recipe = {
|
recipe = {
|
||||||
{"", "", "group:stick"},
|
{"", "", "group:stick"},
|
||||||
{"wool:red", "wool:red", "wool:white"},
|
{"wool:white", "wool:white", "wool:white"},
|
||||||
{"group:wood", "group:wood", "group:wood"},
|
{"group:wood", "group:wood", "group:wood"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -52,13 +57,13 @@ beds.register_bed("beds:fancy_bed", {
|
||||||
-- Simple shaped bed
|
-- Simple shaped bed
|
||||||
|
|
||||||
beds.register_bed("beds:bed", {
|
beds.register_bed("beds:bed", {
|
||||||
description = "Simple Bed",
|
description = S("Simple Bed"),
|
||||||
inventory_image = "beds_bed.png",
|
inventory_image = "beds_bed.png",
|
||||||
wield_image = "beds_bed.png",
|
wield_image = "beds_bed.png",
|
||||||
tiles = {
|
tiles = {
|
||||||
bottom = {
|
bottom = {
|
||||||
"beds_bed_top_bottom.png^[transformR90",
|
"beds_bed_top_bottom.png^[transformR90",
|
||||||
"default_wood.png",
|
"beds_bed_under.png",
|
||||||
"beds_bed_side_bottom_r.png",
|
"beds_bed_side_bottom_r.png",
|
||||||
"beds_bed_side_bottom_r.png^[transformfx",
|
"beds_bed_side_bottom_r.png^[transformfx",
|
||||||
"beds_transparent.png",
|
"beds_transparent.png",
|
||||||
|
@ -66,7 +71,7 @@ beds.register_bed("beds:bed", {
|
||||||
},
|
},
|
||||||
top = {
|
top = {
|
||||||
"beds_bed_top_top.png^[transformR90",
|
"beds_bed_top_top.png^[transformR90",
|
||||||
"default_wood.png",
|
"beds_bed_under.png",
|
||||||
"beds_bed_side_top_r.png",
|
"beds_bed_side_top_r.png",
|
||||||
"beds_bed_side_top_r.png^[transformfx",
|
"beds_bed_side_top_r.png^[transformfx",
|
||||||
"beds_bed_side_top.png",
|
"beds_bed_side_top.png",
|
||||||
|
@ -79,7 +84,7 @@ beds.register_bed("beds:bed", {
|
||||||
},
|
},
|
||||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
||||||
recipe = {
|
recipe = {
|
||||||
{"wool:red", "wool:red", "wool:white"},
|
{"wool:white", "wool:white", "wool:white"},
|
||||||
{"group:wood", "group:wood", "group:wood"}
|
{"group:wood", "group:wood", "group:wood"}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
default
|
|
||||||
wool
|
|
|
@ -1,5 +1,4 @@
|
||||||
local pi = math.pi
|
local pi = math.pi
|
||||||
local player_in_bed = 0
|
|
||||||
local is_sp = minetest.is_singleplayer()
|
local is_sp = minetest.is_singleplayer()
|
||||||
local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
|
local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
|
||||||
if enable_respawn == nil then
|
if enable_respawn == nil then
|
||||||
|
@ -9,15 +8,18 @@ end
|
||||||
-- Helper functions
|
-- Helper functions
|
||||||
|
|
||||||
local function get_look_yaw(pos)
|
local function get_look_yaw(pos)
|
||||||
local n = minetest.get_node(pos)
|
local rotation = minetest.get_node(pos).param2
|
||||||
if n.param2 == 1 then
|
if rotation > 3 then
|
||||||
return pi / 2, n.param2
|
rotation = rotation % 4 -- Mask colorfacedir values
|
||||||
elseif n.param2 == 3 then
|
end
|
||||||
return -pi / 2, n.param2
|
if rotation == 1 then
|
||||||
elseif n.param2 == 0 then
|
return pi / 2, rotation
|
||||||
return pi, n.param2
|
elseif rotation == 3 then
|
||||||
|
return -pi / 2, rotation
|
||||||
|
elseif rotation == 0 then
|
||||||
|
return pi, rotation
|
||||||
else
|
else
|
||||||
return 0, n.param2
|
return 0, rotation
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,16 +58,14 @@ local function lay_down(player, pos, bed_pos, state, skip)
|
||||||
-- stand up
|
-- stand up
|
||||||
if state ~= nil and not state then
|
if state ~= nil and not state then
|
||||||
local p = beds.pos[name] or nil
|
local p = beds.pos[name] or nil
|
||||||
if beds.player[name] ~= nil then
|
|
||||||
beds.player[name] = nil
|
beds.player[name] = nil
|
||||||
player_in_bed = player_in_bed - 1
|
beds.bed_position[name] = nil
|
||||||
end
|
|
||||||
-- skip here to prevent sending player specific changes (used for leaving players)
|
-- skip here to prevent sending player specific changes (used for leaving players)
|
||||||
if skip then
|
if skip then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if p then
|
if p then
|
||||||
player:setpos(p)
|
player:set_pos(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- physics, eye_offset, etc
|
-- physics, eye_offset, etc
|
||||||
|
@ -78,9 +78,9 @@ local function lay_down(player, pos, bed_pos, state, skip)
|
||||||
|
|
||||||
-- lay down
|
-- lay down
|
||||||
else
|
else
|
||||||
beds.player[name] = 1
|
|
||||||
beds.pos[name] = pos
|
beds.pos[name] = pos
|
||||||
player_in_bed = player_in_bed + 1
|
beds.bed_position[name] = bed_pos
|
||||||
|
beds.player[name] = 1
|
||||||
|
|
||||||
-- physics, eye_offset, etc
|
-- physics, eye_offset, etc
|
||||||
player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
|
player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
@ -89,7 +89,7 @@ local function lay_down(player, pos, bed_pos, state, skip)
|
||||||
local dir = minetest.facedir_to_dir(param2)
|
local dir = minetest.facedir_to_dir(param2)
|
||||||
local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2}
|
local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2}
|
||||||
player:set_physics_override(0, 0, 0)
|
player:set_physics_override(0, 0, 0)
|
||||||
player:setpos(p)
|
player:set_pos(p)
|
||||||
default.player_attached[name] = true
|
default.player_attached[name] = true
|
||||||
hud_flags.wielditem = false
|
hud_flags.wielditem = false
|
||||||
default.player_set_animation(player, "lay" , 0)
|
default.player_set_animation(player, "lay" , 0)
|
||||||
|
@ -98,18 +98,27 @@ local function lay_down(player, pos, bed_pos, state, skip)
|
||||||
player:hud_set_flags(hud_flags)
|
player:hud_set_flags(hud_flags)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function get_player_in_bed_count()
|
||||||
|
local c = 0
|
||||||
|
for _, _ in pairs(beds.player) do
|
||||||
|
c = c + 1
|
||||||
|
end
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
local function update_formspecs(finished)
|
local function update_formspecs(finished)
|
||||||
local ges = #minetest.get_connected_players()
|
local ges = #minetest.get_connected_players()
|
||||||
local form_n
|
local form_n
|
||||||
|
local player_in_bed = get_player_in_bed_count()
|
||||||
local is_majority = (ges / 2) < player_in_bed
|
local is_majority = (ges / 2) < player_in_bed
|
||||||
|
|
||||||
if finished then
|
if finished then
|
||||||
form_n = beds.formspec .. "label[2.7,11; Good morning.]"
|
form_n = beds.formspec .. "label[2.7,9; Good morning.]"
|
||||||
else
|
else
|
||||||
form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) ..
|
form_n = beds.formspec .. "label[2.2,9;" .. tostring(player_in_bed) ..
|
||||||
" of " .. tostring(ges) .. " players are in bed]"
|
" of " .. tostring(ges) .. " players are in bed]"
|
||||||
if is_majority and is_night_skip_enabled() then
|
if is_majority and is_night_skip_enabled() then
|
||||||
form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night skip]"
|
form_n = form_n .. "button_exit[2,6;4,0.75;force;Force night skip]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -134,7 +143,7 @@ end
|
||||||
|
|
||||||
function beds.on_rightclick(pos, player)
|
function beds.on_rightclick(pos, player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local ppos = player:getpos()
|
local ppos = player:get_pos()
|
||||||
local tod = minetest.get_timeofday()
|
local tod = minetest.get_timeofday()
|
||||||
|
|
||||||
if tod > 0.2 and tod < 0.805 then
|
if tod > 0.2 and tod < 0.805 then
|
||||||
|
@ -171,6 +180,15 @@ function beds.on_rightclick(pos, player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function beds.can_dig(bed_pos)
|
||||||
|
-- Check all players in bed which one is at the expected position
|
||||||
|
for _, player_bed_pos in pairs(beds.bed_position) do
|
||||||
|
if vector.equals(bed_pos, player_bed_pos) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- Callbacks
|
-- Callbacks
|
||||||
-- Only register respawn callback if respawn enabled
|
-- Only register respawn callback if respawn enabled
|
||||||
|
@ -180,7 +198,7 @@ if enable_respawn then
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local pos = beds.spawn[name]
|
local pos = beds.spawn[name]
|
||||||
if pos then
|
if pos then
|
||||||
player:setpos(pos)
|
player:set_pos(pos)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -205,16 +223,25 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
if formname ~= "beds_form" then
|
if formname ~= "beds_form" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Because "Force night skip" button is a button_exit, it will set fields.quit
|
||||||
|
-- and lay_down call will change value of player_in_bed, so it must be taken
|
||||||
|
-- earlier.
|
||||||
|
local last_player_in_bed = get_player_in_bed_count()
|
||||||
|
|
||||||
if fields.quit or fields.leave then
|
if fields.quit or fields.leave then
|
||||||
lay_down(player, nil, nil, false)
|
lay_down(player, nil, nil, false)
|
||||||
update_formspecs(false)
|
update_formspecs(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.force then
|
if fields.force then
|
||||||
update_formspecs(is_night_skip_enabled())
|
local is_majority = (#minetest.get_connected_players() / 2) < last_player_in_bed
|
||||||
if is_night_skip_enabled() then
|
if is_majority and is_night_skip_enabled() then
|
||||||
|
update_formspecs(true)
|
||||||
beds.skip_night()
|
beds.skip_night()
|
||||||
beds.kick_players()
|
beds.kick_players()
|
||||||
|
else
|
||||||
|
update_formspecs(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
|
-- beds/init.lua
|
||||||
|
|
||||||
|
-- Load support for MT game translation.
|
||||||
|
local S = minetest.get_translator("beds")
|
||||||
|
|
||||||
|
|
||||||
beds = {}
|
beds = {}
|
||||||
beds.player = {}
|
beds.player = {}
|
||||||
|
beds.bed_position = {}
|
||||||
beds.pos = {}
|
beds.pos = {}
|
||||||
beds.spawn = {}
|
beds.spawn = {}
|
||||||
|
beds.get_translator = S
|
||||||
|
|
||||||
beds.formspec = "size[8,15;true]" ..
|
beds.formspec = "size[8,11;true]" ..
|
||||||
|
"no_prepend[]" ..
|
||||||
"bgcolor[#080808BB;true]" ..
|
"bgcolor[#080808BB;true]" ..
|
||||||
"button_exit[2,12;4,0.75;leave;Leave Bed]"
|
"button_exit[2,10;4,0.75;leave;" .. S("Leave Bed") .. "]"
|
||||||
|
|
||||||
local modpath = minetest.get_modpath("beds")
|
local modpath = minetest.get_modpath("beds")
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ Licenses of media (textures)
|
||||||
|
|
||||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
Copyright (C) 2014-2016 BlockMen
|
Copyright (C) 2014-2016 BlockMen
|
||||||
|
Copyright (C) 2018 TumeniNodes
|
||||||
|
|
||||||
You are free to:
|
You are free to:
|
||||||
Share — copy and redistribute the material in any medium or format.
|
Share — copy and redistribute the material in any medium or format.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Незвычайны ложак
|
||||||
|
|
||||||
|
Simple Bed=Просты ложак
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Zdobená postel
|
||||||
|
|
||||||
|
Simple Bed=Prostá postel
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Schönes Bett
|
||||||
|
|
||||||
|
Simple Bed=Schlichtes Bett
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=
|
||||||
|
|
||||||
|
Simple Bed=
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Luksa lito
|
||||||
|
|
||||||
|
Simple Bed=Simpla lito
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Cama sofisticada
|
||||||
|
|
||||||
|
Simple Bed=Cama sencilla
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Lit fantaisie
|
||||||
|
|
||||||
|
Simple Bed=Lit Simple
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Csinos ágy
|
||||||
|
|
||||||
|
Simple Bed=Egyszerű ágy
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Dipan Mewah
|
||||||
|
|
||||||
|
Simple Bed=Dipan Sederhana
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Letto elegante
|
||||||
|
|
||||||
|
Simple Bed=Letto semplice
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=お洒落なベッド
|
||||||
|
|
||||||
|
Simple Bed=簡素なベッド
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=se jadni ckana
|
||||||
|
|
||||||
|
Simple Bed=sampu ckana
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Katil Beragam
|
||||||
|
|
||||||
|
Simple Bed=Katil Biasa
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Mooi Bed
|
||||||
|
|
||||||
|
Simple Bed=Simpel bed
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Łóżko ozdobne
|
||||||
|
|
||||||
|
Simple Bed=Proste łóżko
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Cama com Cabeceira
|
||||||
|
|
||||||
|
Simple Bed=Cama Simples
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Cama com Cabeceira
|
||||||
|
|
||||||
|
Simple Bed=Cama Simples
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Pat Luxos
|
||||||
|
|
||||||
|
Simple Bed=Pat Simplu
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Необычная кровать
|
||||||
|
|
||||||
|
Simple Bed=Обычная кровать
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Китњаст кревет
|
||||||
|
|
||||||
|
Simple Bed=Једноставан кревет
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Süslü Yatak
|
||||||
|
|
||||||
|
Simple Bed=Basit Yatak
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=Чепурне Ліжко
|
||||||
|
|
||||||
|
Simple Bed=Просте Ліжко
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=豪华大床
|
||||||
|
|
||||||
|
Simple Bed=简单的床
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# textdomain: beds
|
||||||
|
|
||||||
|
Fancy Bed=
|
||||||
|
|
||||||
|
Simple Bed=
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = beds
|
||||||
|
description = Minetest Game mod: beds
|
||||||
|
depends = default, wool
|
|
@ -53,7 +53,7 @@ end
|
||||||
function beds.set_spawns()
|
function beds.set_spawns()
|
||||||
for name,_ in pairs(beds.player) do
|
for name,_ in pairs(beds.player) do
|
||||||
local player = minetest.get_player_by_name(name)
|
local player = minetest.get_player_by_name(name)
|
||||||
local p = player:getpos()
|
local p = player:get_pos()
|
||||||
-- but don't change spawn location if borrowing a bed
|
-- but don't change spawn location if borrowing a bed
|
||||||
if not minetest.is_protected(p, name) then
|
if not minetest.is_protected(p, name) then
|
||||||
beds.spawn[name] = p
|
beds.spawn[name] = p
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 304 B |
|
@ -0,0 +1,37 @@
|
||||||
|
Minetest Game mod: binoculars
|
||||||
|
=============================
|
||||||
|
See license.txt for license information.
|
||||||
|
|
||||||
|
Authors of source code
|
||||||
|
----------------------
|
||||||
|
paramat (MIT)
|
||||||
|
|
||||||
|
Authors of media (textures)
|
||||||
|
---------------------------
|
||||||
|
paramat (CC BY-SA 3.0):
|
||||||
|
binoculars_binoculars.png
|
||||||
|
|
||||||
|
Crafting
|
||||||
|
--------
|
||||||
|
binoculars:binoculars
|
||||||
|
|
||||||
|
default:obsidian_glass O
|
||||||
|
default:bronze_ingot B
|
||||||
|
|
||||||
|
O_O
|
||||||
|
BBB
|
||||||
|
O_O
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
In survival mode, use of zoom requires the binoculars item in your inventory,
|
||||||
|
they will allow a 10 degree field of view.
|
||||||
|
It can take up to 5 seconds for adding to or removal from inventory to have an
|
||||||
|
effect, however to instantly allow the use of this zoom 'use' (leftclick) the
|
||||||
|
item.
|
||||||
|
|
||||||
|
Zoom with a field of view of 15 degrees is automatically allowed in creative
|
||||||
|
mode and for any player with the 'creative' privilege.
|
||||||
|
|
||||||
|
The 'binoculars.update_player_property()' function is global so can be
|
||||||
|
redefined by a mod for alternative behaviour.
|
|
@ -0,0 +1,81 @@
|
||||||
|
-- binoculars/init.lua
|
||||||
|
|
||||||
|
-- Mod global namespace
|
||||||
|
|
||||||
|
binoculars = {}
|
||||||
|
|
||||||
|
-- Load support for MT game translation.
|
||||||
|
local S = minetest.get_translator("binoculars")
|
||||||
|
|
||||||
|
|
||||||
|
-- Detect creative mod
|
||||||
|
local creative_mod = minetest.get_modpath("creative")
|
||||||
|
-- Cache creative mode setting as fallback if creative mod not present
|
||||||
|
local creative_mode_cache = minetest.settings:get_bool("creative_mode")
|
||||||
|
|
||||||
|
|
||||||
|
-- Update player property
|
||||||
|
-- Global to allow overriding
|
||||||
|
|
||||||
|
function binoculars.update_player_property(player)
|
||||||
|
local creative_enabled =
|
||||||
|
(creative_mod and creative.is_enabled_for(player:get_player_name())) or
|
||||||
|
creative_mode_cache
|
||||||
|
local new_zoom_fov = 0
|
||||||
|
|
||||||
|
if player:get_inventory():contains_item(
|
||||||
|
"main", "binoculars:binoculars") then
|
||||||
|
new_zoom_fov = 10
|
||||||
|
elseif creative_enabled then
|
||||||
|
new_zoom_fov = 15
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Only set property if necessary to avoid player mesh reload
|
||||||
|
if player:get_properties().zoom_fov ~= new_zoom_fov then
|
||||||
|
player:set_properties({zoom_fov = new_zoom_fov})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Set player property 'on joinplayer'
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
binoculars.update_player_property(player)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
-- Cyclic update of player property
|
||||||
|
|
||||||
|
local function cyclic_update()
|
||||||
|
for _, player in ipairs(minetest.get_connected_players()) do
|
||||||
|
binoculars.update_player_property(player)
|
||||||
|
end
|
||||||
|
minetest.after(4.7, cyclic_update)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.after(4.7, cyclic_update)
|
||||||
|
|
||||||
|
|
||||||
|
-- Binoculars item
|
||||||
|
|
||||||
|
minetest.register_craftitem("binoculars:binoculars", {
|
||||||
|
description = S("Binoculars\nUse with 'Zoom' key"),
|
||||||
|
inventory_image = "binoculars_binoculars.png",
|
||||||
|
stack_max = 1,
|
||||||
|
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
binoculars.update_player_property(user)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Crafting
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "binoculars:binoculars",
|
||||||
|
recipe = {
|
||||||
|
{"default:obsidian_glass", "", "default:obsidian_glass"},
|
||||||
|
{"default:bronze_ingot", "default:bronze_ingot", "default:bronze_ingot"},
|
||||||
|
{"default:obsidian_glass", "", "default:obsidian_glass"},
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,59 @@
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2017 paramat
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
Licenses of media (textures)
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
Copyright (C) 2017 paramat
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
Share — copy and redistribute the material in any medium or format.
|
||||||
|
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
||||||
|
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
|
||||||
|
Attribution — You must give appropriate credit, provide a link to the license, and
|
||||||
|
indicate if changes were made. You may do so in any reasonable manner, but not in any way
|
||||||
|
that suggests the licensor endorses you or your use.
|
||||||
|
|
||||||
|
ShareAlike — If you remix, transform, or build upon the material, you must distribute
|
||||||
|
your contributions under the same license as the original.
|
||||||
|
|
||||||
|
No additional restrictions — You may not apply legal terms or technological measures that
|
||||||
|
legally restrict others from doing anything the license permits.
|
||||||
|
|
||||||
|
Notices:
|
||||||
|
|
||||||
|
You do not have to comply with the license for elements of the material in the public
|
||||||
|
domain or where your use is permitted by an applicable exception or limitation.
|
||||||
|
No warranties are given. The license may not give you all of the permissions necessary
|
||||||
|
for your intended use. For example, other rights such as publicity, privacy, or moral
|
||||||
|
rights may limit how you use the material.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
http://creativecommons.org/licenses/by-sa/3.0/
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: binoculars
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
name = binoculars
|
||||||
|
description = Minetest Game mod: binoculars
|
||||||
|
depends = default
|
||||||
|
optional_depends = creative
|
Binary file not shown.
After Width: | Height: | Size: 219 B |
|
@ -13,3 +13,19 @@ Textures: Zeg9 (CC BY-SA 3.0)
|
||||||
Model: thetoon and Zeg9 (CC BY-SA 3.0),
|
Model: thetoon and Zeg9 (CC BY-SA 3.0),
|
||||||
modified by PavelS(SokolovPavel) (CC BY-SA 3.0),
|
modified by PavelS(SokolovPavel) (CC BY-SA 3.0),
|
||||||
modified by sofar (CC BY-SA 3.0)
|
modified by sofar (CC BY-SA 3.0)
|
||||||
|
|
||||||
|
Controls
|
||||||
|
--------
|
||||||
|
Right mouse button = Enter or exit boat when pointing at boat.
|
||||||
|
Forward = Speed up.
|
||||||
|
Slow down when moving backwards.
|
||||||
|
Forward + backward = Enable cruise mode: Boat will accelerate to maximum forward
|
||||||
|
speed and remain at that speed without needing to hold the
|
||||||
|
forward key.
|
||||||
|
Backward = Slow down.
|
||||||
|
Speed up when moving backwards.
|
||||||
|
Disable cruise mode.
|
||||||
|
Left = Turn to the left.
|
||||||
|
Turn to the right when moving backwards.
|
||||||
|
Right = Turn to the right.
|
||||||
|
Turn to the left when moving backwards.
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
default
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
-- boats/init.lua
|
||||||
|
|
||||||
|
-- Load support for MT game translation.
|
||||||
|
local S = minetest.get_translator("boats")
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Helper functions
|
-- Helper functions
|
||||||
--
|
--
|
||||||
|
@ -33,6 +38,7 @@ end
|
||||||
--
|
--
|
||||||
|
|
||||||
local boat = {
|
local boat = {
|
||||||
|
initial_properties = {
|
||||||
physical = true,
|
physical = true,
|
||||||
-- Warning: Do not change the position of the collisionbox top surface,
|
-- Warning: Do not change the position of the collisionbox top surface,
|
||||||
-- lowering it causes the boat to fall through the world if underwater
|
-- lowering it causes the boat to fall through the world if underwater
|
||||||
|
@ -40,11 +46,13 @@ local boat = {
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "boats_boat.obj",
|
mesh = "boats_boat.obj",
|
||||||
textures = {"default_wood.png"},
|
textures = {"default_wood.png"},
|
||||||
|
},
|
||||||
|
|
||||||
driver = nil,
|
driver = nil,
|
||||||
v = 0,
|
v = 0,
|
||||||
last_v = 0,
|
last_v = 0,
|
||||||
removed = false
|
removed = false,
|
||||||
|
auto = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,15 +61,16 @@ function boat.on_rightclick(self, clicker)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local name = clicker:get_player_name()
|
local name = clicker:get_player_name()
|
||||||
if self.driver and clicker == self.driver then
|
if self.driver and name == self.driver then
|
||||||
self.driver = nil
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
clicker:set_detach()
|
clicker:set_detach()
|
||||||
default.player_attached[name] = false
|
player_api.player_attached[name] = false
|
||||||
default.player_set_animation(clicker, "stand" , 30)
|
player_api.set_animation(clicker, "stand" , 30)
|
||||||
local pos = clicker:getpos()
|
local pos = clicker:get_pos()
|
||||||
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
|
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
|
||||||
minetest.after(0.1, function()
|
minetest.after(0.1, function()
|
||||||
clicker:setpos(pos)
|
clicker:set_pos(pos)
|
||||||
end)
|
end)
|
||||||
elseif not self.driver then
|
elseif not self.driver then
|
||||||
local attach = clicker:get_attach()
|
local attach = clicker:get_attach()
|
||||||
|
@ -72,18 +81,25 @@ function boat.on_rightclick(self, clicker)
|
||||||
end
|
end
|
||||||
clicker:set_detach()
|
clicker:set_detach()
|
||||||
end
|
end
|
||||||
self.driver = clicker
|
self.driver = name
|
||||||
clicker:set_attach(self.object, "",
|
clicker:set_attach(self.object, "",
|
||||||
{x = 0, y = 11, z = -3}, {x = 0, y = 0, z = 0})
|
{x = 0.5, y = 1, z = -3}, {x = 0, y = 0, z = 0})
|
||||||
default.player_attached[name] = true
|
player_api.player_attached[name] = true
|
||||||
minetest.after(0.2, function()
|
minetest.after(0.2, function()
|
||||||
default.player_set_animation(clicker, "sit" , 30)
|
player_api.set_animation(clicker, "sit" , 30)
|
||||||
end)
|
end)
|
||||||
clicker:set_look_horizontal(self.object:getyaw())
|
clicker:set_look_horizontal(self.object:get_yaw())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- If driver leaves server while driving boat
|
||||||
|
function boat.on_detach_child(self, child)
|
||||||
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function boat.on_activate(self, staticdata, dtime_s)
|
function boat.on_activate(self, staticdata, dtime_s)
|
||||||
self.object:set_armor_groups({immortal = 1})
|
self.object:set_armor_groups({immortal = 1})
|
||||||
if staticdata then
|
if staticdata then
|
||||||
|
@ -102,21 +118,23 @@ function boat.on_punch(self, puncher)
|
||||||
if not puncher or not puncher:is_player() or self.removed then
|
if not puncher or not puncher:is_player() or self.removed then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if self.driver and puncher == self.driver then
|
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
self.driver = nil
|
self.driver = nil
|
||||||
puncher:set_detach()
|
puncher:set_detach()
|
||||||
default.player_attached[puncher:get_player_name()] = false
|
player_api.player_attached[name] = false
|
||||||
end
|
end
|
||||||
if not self.driver then
|
if not self.driver then
|
||||||
self.removed = true
|
self.removed = true
|
||||||
local inv = puncher:get_inventory()
|
local inv = puncher:get_inventory()
|
||||||
if not (creative and creative.is_enabled_for
|
if not (creative and creative.is_enabled_for
|
||||||
and creative.is_enabled_for(puncher:get_player_name()))
|
and creative.is_enabled_for(name))
|
||||||
or not inv:contains_item("main", "boats:boat") then
|
or not inv:contains_item("main", "boats:boat") then
|
||||||
local leftover = inv:add_item("main", "boats:boat")
|
local leftover = inv:add_item("main", "boats:boat")
|
||||||
-- if no room in inventory add a replacement boat to the world
|
-- if no room in inventory add a replacement boat to the world
|
||||||
if not leftover:is_empty() then
|
if not leftover:is_empty() then
|
||||||
minetest.add_item(self.object:getpos(), leftover)
|
minetest.add_item(self.object:get_pos(), leftover)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- delay remove to ensure player is detached
|
-- delay remove to ensure player is detached
|
||||||
|
@ -128,38 +146,49 @@ end
|
||||||
|
|
||||||
|
|
||||||
function boat.on_step(self, dtime)
|
function boat.on_step(self, dtime)
|
||||||
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
|
self.v = get_v(self.object:get_velocity()) * get_sign(self.v)
|
||||||
if self.driver then
|
if self.driver then
|
||||||
local ctrl = self.driver:get_player_control()
|
local driver_objref = minetest.get_player_by_name(self.driver)
|
||||||
local yaw = self.object:getyaw()
|
if driver_objref then
|
||||||
if ctrl.up then
|
local ctrl = driver_objref:get_player_control()
|
||||||
self.v = self.v + 0.1
|
if ctrl.up and ctrl.down then
|
||||||
|
if not self.auto then
|
||||||
|
self.auto = true
|
||||||
|
minetest.chat_send_player(self.driver, S("[boats] Cruise on"))
|
||||||
|
end
|
||||||
elseif ctrl.down then
|
elseif ctrl.down then
|
||||||
self.v = self.v - 0.1
|
self.v = self.v - dtime * 1.8
|
||||||
|
if self.auto then
|
||||||
|
self.auto = false
|
||||||
|
minetest.chat_send_player(self.driver, S("[boats] Cruise off"))
|
||||||
|
end
|
||||||
|
elseif ctrl.up or self.auto then
|
||||||
|
self.v = self.v + dtime * 1.8
|
||||||
end
|
end
|
||||||
if ctrl.left then
|
if ctrl.left then
|
||||||
if self.v < 0 then
|
if self.v < -0.001 then
|
||||||
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
self.object:set_yaw(self.object:get_yaw() - dtime * 0.9)
|
||||||
else
|
else
|
||||||
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
self.object:set_yaw(self.object:get_yaw() + dtime * 0.9)
|
||||||
end
|
end
|
||||||
elseif ctrl.right then
|
elseif ctrl.right then
|
||||||
if self.v < 0 then
|
if self.v < -0.001 then
|
||||||
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
self.object:set_yaw(self.object:get_yaw() + dtime * 0.9)
|
||||||
else
|
else
|
||||||
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
self.object:set_yaw(self.object:get_yaw() - dtime * 0.9)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local velo = self.object:getvelocity()
|
end
|
||||||
|
local velo = self.object:get_velocity()
|
||||||
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
|
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
|
||||||
self.object:setpos(self.object:getpos())
|
self.object:set_pos(self.object:get_pos())
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local s = get_sign(self.v)
|
local s = get_sign(self.v)
|
||||||
self.v = self.v - 0.02 * s
|
self.v = self.v - dtime * 0.6 * s
|
||||||
if s ~= get_sign(self.v) then
|
if s ~= get_sign(self.v) then
|
||||||
self.object:setvelocity({x = 0, y = 0, z = 0})
|
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||||
self.v = 0
|
self.v = 0
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -167,7 +196,7 @@ function boat.on_step(self, dtime)
|
||||||
self.v = 5 * get_sign(self.v)
|
self.v = 5 * get_sign(self.v)
|
||||||
end
|
end
|
||||||
|
|
||||||
local p = self.object:getpos()
|
local p = self.object:get_pos()
|
||||||
p.y = p.y - 0.5
|
p.y = p.y - 0.5
|
||||||
local new_velo
|
local new_velo
|
||||||
local new_acce = {x = 0, y = 0, z = 0}
|
local new_acce = {x = 0, y = 0, z = 0}
|
||||||
|
@ -179,13 +208,13 @@ function boat.on_step(self, dtime)
|
||||||
else
|
else
|
||||||
new_acce = {x = 0, y = -9.8, z = 0}
|
new_acce = {x = 0, y = -9.8, z = 0}
|
||||||
end
|
end
|
||||||
new_velo = get_velocity(self.v, self.object:getyaw(),
|
new_velo = get_velocity(self.v, self.object:get_yaw(),
|
||||||
self.object:getvelocity().y)
|
self.object:get_velocity().y)
|
||||||
self.object:setpos(self.object:getpos())
|
self.object:set_pos(self.object:get_pos())
|
||||||
else
|
else
|
||||||
p.y = p.y + 1
|
p.y = p.y + 1
|
||||||
if is_water(p) then
|
if is_water(p) then
|
||||||
local y = self.object:getvelocity().y
|
local y = self.object:get_velocity().y
|
||||||
if y >= 5 then
|
if y >= 5 then
|
||||||
y = 5
|
y = 5
|
||||||
elseif y < 0 then
|
elseif y < 0 then
|
||||||
|
@ -193,24 +222,24 @@ function boat.on_step(self, dtime)
|
||||||
else
|
else
|
||||||
new_acce = {x = 0, y = 5, z = 0}
|
new_acce = {x = 0, y = 5, z = 0}
|
||||||
end
|
end
|
||||||
new_velo = get_velocity(self.v, self.object:getyaw(), y)
|
new_velo = get_velocity(self.v, self.object:get_yaw(), y)
|
||||||
self.object:setpos(self.object:getpos())
|
self.object:set_pos(self.object:get_pos())
|
||||||
else
|
else
|
||||||
new_acce = {x = 0, y = 0, z = 0}
|
new_acce = {x = 0, y = 0, z = 0}
|
||||||
if math.abs(self.object:getvelocity().y) < 1 then
|
if math.abs(self.object:get_velocity().y) < 1 then
|
||||||
local pos = self.object:getpos()
|
local pos = self.object:get_pos()
|
||||||
pos.y = math.floor(pos.y) + 0.5
|
pos.y = math.floor(pos.y) + 0.5
|
||||||
self.object:setpos(pos)
|
self.object:set_pos(pos)
|
||||||
new_velo = get_velocity(self.v, self.object:getyaw(), 0)
|
new_velo = get_velocity(self.v, self.object:get_yaw(), 0)
|
||||||
else
|
else
|
||||||
new_velo = get_velocity(self.v, self.object:getyaw(),
|
new_velo = get_velocity(self.v, self.object:get_yaw(),
|
||||||
self.object:getvelocity().y)
|
self.object:get_velocity().y)
|
||||||
self.object:setpos(self.object:getpos())
|
self.object:set_pos(self.object:get_pos())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.object:setvelocity(new_velo)
|
self.object:set_velocity(new_velo)
|
||||||
self.object:setacceleration(new_acce)
|
self.object:set_acceleration(new_acce)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,7 +247,7 @@ minetest.register_entity("boats:boat", boat)
|
||||||
|
|
||||||
|
|
||||||
minetest.register_craftitem("boats:boat", {
|
minetest.register_craftitem("boats:boat", {
|
||||||
description = "Boat",
|
description = S("Boat"),
|
||||||
inventory_image = "boats_inventory.png",
|
inventory_image = "boats_inventory.png",
|
||||||
wield_image = "boats_wield.png",
|
wield_image = "boats_wield.png",
|
||||||
wield_scale = {x = 2, y = 2, z = 1},
|
wield_scale = {x = 2, y = 2, z = 1},
|
||||||
|
@ -246,7 +275,7 @@ minetest.register_craftitem("boats:boat", {
|
||||||
boat = minetest.add_entity(pointed_thing.under, "boats:boat")
|
boat = minetest.add_entity(pointed_thing.under, "boats:boat")
|
||||||
if boat then
|
if boat then
|
||||||
if placer then
|
if placer then
|
||||||
boat:setyaw(placer:get_look_horizontal())
|
boat:set_yaw(placer:get_look_horizontal())
|
||||||
end
|
end
|
||||||
local player_name = placer and placer:get_player_name() or ""
|
local player_name = placer and placer:get_player_name() or ""
|
||||||
if not (creative and creative.is_enabled_for and
|
if not (creative and creative.is_enabled_for and
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# textdomain: boats
|
||||||
|
|
||||||
|
Boat=Човен
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue