upgrade beds,boats,bucket,carts,creative,doors,farming,fire,stairs,tnt,wool

* beds 7b6fae96d5
* boats 3832de08f7
* bucket 1d9f32295a
* carts dcbca916cf
* creative ca09e77370
* doors a89ab0454d
* farming 10de84d12d
* fire 4e5f7ad553
* stairs c3a5af6c45
* tnt 8195861f90
* wool de642a08e8
This commit is contained in:
mckaygerhard 2022-03-01 23:26:11 -04:00
parent c7cb79422b
commit 2f97407591
662 changed files with 16413 additions and 2965 deletions

View File

@ -5,28 +5,31 @@ For information check [../README.md](../README.md)
## Content ## Content
* api | mod name | origin or work | version | info |
* beds | ------------------ | --------------------------------------------------- | -------- | --- |
* bucket | api | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | [api](../game_api.md) |
* bones | beds | https://codeberg.org/minenux/minetest-mod-beds | https://codeberg.org/minenux/minetest-mod-beds/commit/7b6fae96d5e273dad9a373e63eb958145c9bfbef | [beds/README.md](beds/README.md) |
* boats | boats | https://codeberg.org/minenux/minetest-mod-boats | https://codeberg.org/minenux/minetest-mod-boats/commit/3832de08f705d5d2e7b5a971760e5fad1653305f | [boats/README.md](boats/README.md) |
* creative | bucket | https://codeberg.org/minenux/minetest-mod-bucket.git | https://codeberg.org/minenux/minetest-mod-bucket/commit/1d9f32295aba3ef2a86be302050f34c1766e93d5 | [bucket/README.md](bucket/README.md) |
* default | bones | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* doors | carts | https://codeberg.org/minenux/minetest-mod-carts | https://codeberg.org/minenux/minetest-mod-carts/commit/dcbca916cffdcec281f0129ef350db2686bda933 | [carts/README.md](carts/README.md) |
* farming | creative | https://codeberg.org/minenux/minetest-mod-creative | https://codeberg.org/minenux/minetest-mod-creative/commit/ca09e773701f834fec7de18bf13598b3323778db | [creative/README.md](creative/README.md) |
* fire | default | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* give_initial_stuff | doors | https://codeberg.org/minenux/minetest-mod-doors | https://codeberg.org/minenux/minetest-mod-doors/commit/a89ab0454deb4933b6e4971c57055c40b7938e5b | [doors/README.md](doors/README.md) |
* stairs | dye | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* carts | farming | https://codeberg.org/minenux/minetest-mod-farming | https://codeberg.org/minenux/minetest-mod-farming/commit/10de84d12d24a87f3aa9abef73f87c6cebb2614c | [farming/README.md](farming/README.md) |
* dye | fire | https://codeberg.org/minenux/minetest-mod-fire | https://codeberg.org/minenux/minetest-mod-fire/commit/4e5f7ad55314bd9b126fb133cfc5a32fa58b20d2 | [fire/README.md](fire/README.md) |
* flowers | flowers | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* screwdriver | give_initial_stuff | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* tnt | killme | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* xpanes | sfinv | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* sfinv | stairs | https://codeberg.org/minenux/minetest-mod-stairs | https://codeberg.org/minenux/minetest-mod-stairs/commit/c3a5af6c452daca599d226df694df1b75f15c110 | [stairs/README.md](stairs/README.md) |
* vessels | screwdriver | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
* walls | tnt | https://codeberg.org/minenux/minetest-mod-tnt | https://codeberg.org/minenux/minetest-mod-tnt/commit/8195861f905a90b53cd52348deb34df41a053027 | [tnt/README.md](tnt/README.md) |
* wool | vessels | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
| walls | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
| wool | https://codeberg.org/minenux/minetest-mod-wool | https://codeberg.org/minenux/minetest-mod-wool/commit/de642a08e80bfd7a4a1e5629e50458a609dbda3a | [wool/README.md](wool/README.md) |
| xpanes | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/c7cb79422ba19c696966472942db6177c934838d | |
The default mod provides sethome and player_api call ones, binoculars from v5 are The default mod provides sethome and player_api call ones, binoculars from v5 are
just separate privilegies for zoom, butterflies and fireflies from v5 can be set just separate privilegies for zoom, butterflies and fireflies from v5 can be set

26
mods/beds/Changelog.txt Normal file
View File

@ -0,0 +1,26 @@
1.0.1 beta
----------
- Add backwards compatibility with PilzAdam's beds mod
- Fix placement
- Fix small bugs
- Prevent possible crash
1.1
---
- Add fancy bed model (based on jp's model)
- Add API to register beds
- Allow players always to detach from bed (by donat-b)
- If more than 50% of players want sleep they can skip the night
- Don't show sleep dialog in singleplayer
1.1.1
-----
- Prevent possbile crash by trying to reposition leaving players
1.2
---
- Updated to use default bed functions
- Texture check to fix beds using old api
- 'bed_sleep_divide' setting added [1 for all, 2 for half, 3 for third]
- Add POVA support
- Add pink fancy bed and blue simple bed

96
mods/beds/README.md Normal file
View File

@ -0,0 +1,96 @@
minetest mod Beds
=========================
This mod improves beds which allows sleep, featured to (auto) skip the night.
Information
-----------
This mod is named `beds` to sleep, by rightclick the bed. It featured
in singleplayer mode that the night gets skipped immediately. If playing
in multiplayer you get shown how many other players are in bed too,
if all players are sleeping the night gets skipped.
![screenshot.jpg](screenshot.jpg)
Tech information
----------------
This mod sustitute default one, you must disable the default of minetest
game if present or override it.
#### Features
* Night Skypping:
This mod auto featured night skip in singleplayer, in multiplayer it skipped
if more than a set percentage (default 50%) of the players are lying
in bed and use this option. Check configuration section for more info.
* Controlled respawning:
If you have slept in bed (not just lying in it) your respawn point
is set to the beds location and you will respawn there after
death. Check configuration section for more info.
* More beds:
It features two more beds, the "Blue Simple Bed" like the "Simple Bed"
but in blue, and the "Pink Fancy Bed" like the "Fancy Bed" but in pink.
#### Dependencies
* default
* player_api (for newer engines)
Optional dependences:
* intllib (only for older engines)
* pova (optional)
The pova mod are not xplicit set as optional depends, due the circular depends bug,
its detected and used.
#### Configuration
| Configuration | type | default | place file | Notes about |
| --------------------- | ----- | ------- | ------------ | ----------------------------------------- |
| enable_bed_respawn | bool | true | minetest.conf | Enable respawn point set to last sleep bed |
| enable_bed_night_skip | bool | false | minetest.conf | You can disable the night skip feature |
| bed_sleep_divide | int | 2 | minetest.conf | Division of players needed to skip night |
#### Nodes
Crafting are same as original default mod, but colored uses a white plus the other color.
| Node name | Description name |
| ----------------------- | --------------------- |
| beds:bed | Simple bed |
| beds:bed_blue | Simple bed blue |
| beds:fancy_bed | Fancy shaped bed |
| beds:fancy_bed_pink | Fancy shaped bed pink |
#### Nodes and Aliasing
| mod name : node name | new mod name : new node |
| --------------------------- | ----------------------- |
| beds:bed_top_red | beds:bed_top |
| beds:bed_bottom_red | beds:bed_bottom |
License
------
### Authors of source code
Originally by BlockMen (MIT)
Various Minetest developers and contributors (MIT)
### Authors of media (textures)
BlockMen (CC BY-SA 3.0)
All textures unless otherwise noted
JP (WTFPL)
All models unless otherwise noted
Check [license.txt](license.txt)

View File

@ -1,26 +0,0 @@
Minetest Game mod: beds
=======================
See license.txt for license information.
Authors of source code
----------------------
Originally by BlockMen (MIT)
Various Minetest developers and contributors (MIT)
Authors of media (textures)
---------------------------
BlockMen (CC BY-SA 3.0)
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
immediately. If playing multiplayer you get shown how many other players are in bed too,
if all players are sleeping the night gets skipped. The night skip can be forced if more
than 50% of the players are lying in bed and use this option.
Another feature is a controlled respawning. If you have slept in bed (not just lying in
it) your respawn point is set to the beds location and you will respawn there after
death.
You can disable the respawn at beds by setting "enable_bed_respawn = false" in
minetest.conf.
You can disable the night skip feature by setting "enable_bed_night_skip = false" in
minetest.conf or by using the /set command in-game.

View File

@ -1,61 +1,62 @@
local reverse = true
local function destruct_bed(pos, n)
local node = minetest.get_node(pos)
local other
if n == 2 then
local dir = minetest.facedir_to_dir(node.param2)
other = vector.subtract(pos, dir)
elseif n == 1 then
local dir = minetest.facedir_to_dir(node.param2)
other = vector.add(pos, dir)
end
if reverse then
reverse = not reverse
minetest.remove_node(other)
minetest.check_for_falling(other)
else
reverse = not reverse
end
end
function beds.register_bed(name, def) function beds.register_bed(name, def)
minetest.register_node(name .. "_bottom", {
local new_tiles
local new_mesh = "beds_simple_bed.obj"
-- old api texture check
if def.tiles and def.tiles.bottom then
new_tiles = "beds_simple_bed.png" -- default
-- check for fancy bed
if def.nodebox and def.nodebox.bottom and #def.nodebox.bottom > 3 then
new_tiles = "beds_fancy_bed.png"
new_mesh = "beds_fancy_bed.obj"
end
end
-- register bed node
minetest.register_node(name, {
description = def.description, description = def.description,
inventory_image = def.inventory_image, inventory_image = def.inventory_image,
wield_image = def.wield_image, wield_image = def.wield_image,
drawtype = "nodebox", drawtype = "mesh",
tiles = def.tiles.bottom, mesh = def.mesh or new_mesh,
tiles = new_tiles or def.tiles,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
is_ground_content = false,
stack_max = 1, stack_max = 1,
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1}, groups = {
sounds = def.sounds or default.node_sound_wood_defaults(), choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1,
node_box = { fall_damage_add_percent = -40, bouncy = 85
type = "fixed",
fixed = def.nodebox.bottom,
}, },
sounds = default.node_sound_wood_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = def.selectionbox, fixed = def.selectionbox
},
collision_box = {
type = "fixed",
fixed = def.collisionbox
}, },
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under local under = pointed_thing.under
local node = minetest.get_node(under) local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name] local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and
not (placer and placer:is_player() and if udef and udef.on_rightclick
placer:get_player_control().sneak) then and not (placer and placer:is_player()
and placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack, return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end
local pos local pos
if udef and udef.buildable_to then if udef and udef.buildable_to then
pos = under pos = under
else else
@ -64,13 +65,16 @@ function beds.register_bed(name, def)
local player_name = placer and placer:get_player_name() or "" local player_name = placer and placer:get_player_name() or ""
if minetest.is_protected(pos, player_name) and if minetest.is_protected(pos, player_name)
not minetest.check_player_privs(player_name, "protection_bypass") then and not minetest.check_player_privs(player_name, "protection_bypass") then
minetest.record_protection_violation(pos, player_name) minetest.record_protection_violation(pos, player_name)
return itemstack return itemstack
end end
local node_def = minetest.registered_nodes[minetest.get_node(pos).name] local node_def = minetest.registered_nodes[minetest.get_node(pos).name]
if not node_def or not node_def.buildable_to then if not node_def or not node_def.buildable_to then
return itemstack return itemstack
end end
@ -79,91 +83,46 @@ function beds.register_bed(name, def)
minetest.dir_to_facedir(placer:get_look_dir()) or 0 minetest.dir_to_facedir(placer:get_look_dir()) or 0
local botpos = vector.add(pos, minetest.facedir_to_dir(dir)) local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
if minetest.is_protected(botpos, player_name) and if minetest.is_protected(botpos, player_name)
not minetest.check_player_privs(player_name, "protection_bypass") then and not minetest.check_player_privs(player_name, "protection_bypass") then
minetest.record_protection_violation(botpos, player_name) minetest.record_protection_violation(botpos, player_name)
return itemstack return itemstack
end end
local botdef = minetest.registered_nodes[minetest.get_node(botpos).name] local botdef = minetest.registered_nodes[minetest.get_node(botpos).name]
if not botdef or not botdef.buildable_to then if not botdef or not botdef.buildable_to then
return itemstack return itemstack
end end
minetest.set_node(pos, {name = name .. "_bottom", param2 = dir}) minetest.set_node(pos, {name = name, param2 = dir})
minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
if not (creative and creative.is_enabled_for if not beds.is_creative(player_name) then
and creative.is_enabled_for(player_name)) then
itemstack:take_item() itemstack:take_item()
end end
return itemstack return itemstack
end, end,
on_destruct = function(pos) on_rightclick = function(pos, node, clicker)
destruct_bed(pos, 1)
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
beds.on_rightclick(pos, clicker) beds.on_rightclick(pos, clicker)
return itemstack
end, end,
on_rotate = function(pos, node, user, mode, new_param2)
local dir = minetest.facedir_to_dir(node.param2)
local p = vector.add(pos, dir)
local node2 = minetest.get_node_or_nil(p)
if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
not node.param2 == node2.param2 then
return false
end
if minetest.is_protected(p, user:get_player_name()) then
minetest.record_protection_violation(p, user:get_player_name())
return false
end
if mode ~= screwdriver.ROTATE_FACE then
return false
end
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
local node3 = minetest.get_node_or_nil(newp)
local node_def = node3 and minetest.registered_nodes[node3.name]
if not node_def or not node_def.buildable_to then
return false
end
if minetest.is_protected(newp, user:get_player_name()) then
minetest.record_protection_violation(newp, user:get_player_name())
return false
end
node.param2 = new_param2
-- do not remove_node here - it will trigger destroy_bed()
minetest.set_node(p, {name = "air"})
minetest.set_node(pos, node)
minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
return true
end,
})
minetest.register_node(name .. "_top", {
drawtype = "nodebox",
tiles = def.tiles.top,
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
pointable = false,
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
sounds = def.sounds or default.node_sound_wood_defaults(),
drop = name .. "_bottom",
node_box = {
type = "fixed",
fixed = def.nodebox.top,
},
on_destruct = function(pos) on_destruct = function(pos)
destruct_bed(pos, 2) beds.remove_spawns_at(pos)
end, end,
can_dig = function(pos, player)
return beds.can_dig(pos)
end
}) })
minetest.register_alias(name, name .. "_bottom") minetest.register_alias(name .. "_bottom", name)
minetest.register_alias(name .. "_top", "air")
-- register recipe
minetest.register_craft({ minetest.register_craft({
output = name, output = name,
recipe = def.recipe recipe = def.recipe

View File

@ -1,87 +1,65 @@
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 = {"beds_fancy_bed.png", "default_wood.png"},
bottom = { mesh = "beds_fancy_bed.obj",
"beds_bed_top1.png", selectionbox = {-0.5, -0.5, -0.5, 0.5, -0.06, 1.5},
"default_wood.png", collisionbox = {-0.5, -0.5, -0.5, 0.5, -0.06, 1.5},
"beds_bed_side1.png",
"beds_bed_side1.png^[transformFX",
"default_wood.png",
"beds_bed_foot.png",
},
top = {
"beds_bed_top2.png",
"default_wood.png",
"beds_bed_side2.png",
"beds_bed_side2.png^[transformFX",
"beds_bed_head.png",
"default_wood.png",
}
},
nodebox = {
bottom = {
{-0.5, -0.5, -0.5, -0.375, -0.065, -0.4375},
{0.375, -0.5, -0.5, 0.5, -0.065, -0.4375},
{-0.5, -0.375, -0.5, 0.5, -0.125, -0.4375},
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
{-0.4375, -0.3125, -0.4375, 0.4375, -0.0625, 0.5},
},
top = {
{-0.5, -0.5, 0.4375, -0.375, 0.1875, 0.5},
{0.375, -0.5, 0.4375, 0.5, 0.1875, 0.5},
{-0.5, 0, 0.4375, 0.5, 0.125, 0.5},
{-0.5, -0.375, 0.4375, 0.5, -0.125, 0.5},
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
{-0.4375, -0.3125, -0.5, 0.4375, -0.0625, 0.4375},
}
},
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"}
}, }
})
beds.register_bed("beds:fancy_bed_pink", {
description = S("Pink Fancy Bed"),
inventory_image = "beds_bed_fancy_pink.png",
wield_image = "beds_bed_fancy_pink.png",
tiles = {"beds_fancy_bed_pink.png", "default_wood.png"},
mesh = "beds_fancy_bed.obj",
selectionbox = {-0.5, -0.5, -0.5, 0.5, -0.06, 1.5},
collisionbox = {-0.5, -0.5, -0.5, 0.5, -0.06, 1.5},
recipe = {
{"", "", "group:stick"},
{"wool:pink", "wool:pink", "wool:white"},
{"group:wood", "group:wood", "group:wood"}
}
}) })
-- 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 = {"beds_simple_bed.png"},
bottom = { mesh = "beds_simple_bed.obj",
"beds_bed_top_bottom.png^[transformR90",
"default_wood.png",
"beds_bed_side_bottom_r.png",
"beds_bed_side_bottom_r.png^[transformfx",
"beds_transparent.png",
"beds_bed_side_bottom.png"
},
top = {
"beds_bed_top_top.png^[transformR90",
"default_wood.png",
"beds_bed_side_top_r.png",
"beds_bed_side_top_r.png^[transformfx",
"beds_bed_side_top.png",
"beds_transparent.png",
}
},
nodebox = {
bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
},
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},
collisionbox = {-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"}
}, }
})
beds.register_bed("beds:bed_blue", {
description = S("Blue Simple Bed"),
inventory_image = "beds_bed_blue.png",
wield_image = "beds_bed_blue.png",
tiles = {"beds_simple_bed_blue.png"},
mesh = "beds_simple_bed.obj",
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
recipe = {
{"wool:blue", "wool:blue", "wool:white"},
{"group:wood", "group:wood", "group:wood"}
}
}) })
-- Aliases for PilzAdam's beds mod -- Aliases for PilzAdam's beds mod
@ -93,12 +71,12 @@ minetest.register_alias("beds:bed_top_red", "beds:bed_top")
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "beds:fancy_bed_bottom", recipe = "beds:fancy_bed",
burntime = 13, burntime = 13
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "beds:bed_bottom", recipe = "beds:bed",
burntime = 12, burntime = 12
}) })

View File

@ -1,2 +1,4 @@
default default
wool wool
pova?
intllib?

View File

@ -0,0 +1 @@
beds which allows sleep, featured to (auto) skip the night.

View File

@ -1,7 +1,11 @@
local S = beds.get_translator
local is_50 = beds.is_50
local is_54 = beds.is_54
local is_pova = minetest.get_modpath("pova")
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
enable_respawn = true enable_respawn = true
end end
@ -9,34 +13,49 @@ end
-- Helper functions -- Helper functions
local function get_look_yaw(pos) local function get_look_yaw(pos)
local n = minetest.get_node(pos)
if n.param2 == 1 then local rotation = minetest.get_node(pos).param2
return pi / 2, n.param2
elseif n.param2 == 3 then if rotation > 3 then
return -pi / 2, n.param2 rotation = rotation % 4 -- Mask colorfacedir values
elseif n.param2 == 0 then end
return pi, n.param2
if rotation == 1 then
return pi / 2, rotation
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
local function is_night_skip_enabled() local function is_night_skip_enabled()
local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip") local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip")
if enable_night_skip == nil then if enable_night_skip == nil then
enable_night_skip = true enable_night_skip = true
end end
return enable_night_skip return enable_night_skip
end end
local function check_in_beds(players) local function check_in_beds(players)
local in_bed = beds.player local in_bed = beds.player
if not players then if not players then
players = minetest.get_connected_players() players = minetest.get_connected_players()
end end
for n, player in ipairs(players) do for n, player in ipairs(players) do
local name = player:get_player_name() local name = player:get_player_name()
if not in_bed[name] then if not in_bed[name] then
return false return false
end end
@ -45,7 +64,9 @@ local function check_in_beds(players)
return #players > 0 return #players > 0
end end
local function lay_down(player, pos, bed_pos, state, skip) local function lay_down(player, pos, bed_pos, state, skip)
local name = player:get_player_name() local name = player:get_player_name()
local hud_flags = player:hud_get_flags() local hud_flags = player:hud_get_flags()
@ -55,61 +76,156 @@ 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
if beds.player[name] ~= nil then if not beds.player[name] then
beds.player[name] = nil return false -- player not in bed, do nothing
player_in_bed = player_in_bed - 1
end end
beds.bed_position[name] = nil
-- 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
player:setpos(p) player:set_pos(beds.pos[name])
end
-- physics, eye_offset, etc -- physics, eye_offset, etc
local physics_override = beds.player[name].physics_override
beds.player[name] = nil
if is_pova then
pova.del_override(name, "force")
pova.do_override(player)
else
player:set_physics_override({
speed = physics_override.speed,
jump = physics_override.jump,
gravity = physics_override.gravity
})
end
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
player:set_look_horizontal(math.random(1, 180) / 100) player:set_look_horizontal(math.random(1, 180) / 100)
default.player_attached[name] = false
player:set_physics_override(1, 1, 1)
hud_flags.wielditem = true
default.player_set_animation(player, "stand" , 30)
-- lay down if beds.is_50 then
else player_api.player_attached[name] = false
beds.player[name] = 1 player_api.set_animation(player, "stand" , 30)
else
default.player_attached[name] = false
default.player_set_animation(player, "stand" , 30)
end
hud_flags.wielditem = true
else -- lay down
-- Check if bed is occupied
for _, other_pos in pairs(beds.bed_position) do
if vector.distance(bed_pos, other_pos) < 0.1 then
minetest.chat_send_player(name, S("This bed is already occupied!"))
return false
end
end
if beds.is_54 then
-- Check if player is moving
if vector.length(player:get_velocity()) > 0.001 then
minetest.chat_send_player(name,
S("You have to stop moving before going to bed!"))
return false
end
end
-- Check if player is attached to an object
if player:get_attach() then
return false
end
if beds.player[name] then
-- player already in bed, do nothing
return false
end
beds.pos[name] = pos beds.pos[name] = pos
player_in_bed = player_in_bed + 1 beds.bed_position[name] = bed_pos
beds.player[name] = {physics_override = player:get_physics_override()}
-- 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})
local yaw, param2 = get_look_yaw(bed_pos) local yaw, param2 = get_look_yaw(bed_pos)
player:set_look_horizontal(yaw) player:set_look_horizontal(yaw)
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}
player:set_physics_override(0, 0, 0) -- p.y is just above the nodebox height of the 'Simple Bed' (the highest bed),
player:setpos(p) -- to avoid sinking down through the bed.
default.player_attached[name] = true local p = {
x = bed_pos.x + dir.x / 2,
y = bed_pos.y + 0.07,
z = bed_pos.z + dir.z / 2
}
if is_pova then
pova.add_override(name, "force", {speed = 0, jump = 0, gravity = 0})
pova.do_override(player)
else
player:set_physics_override({speed = 0, jump = 0, gravity = 0})
end
player:set_pos(p)
if beds.is_50 then
player_api.player_attached[name] = true
player_api.set_animation(player, "lay" , 0)
else
default.player_attached[name] = true
default.player_set_animation(player, "lay" , 0)
end
hud_flags.wielditem = false hud_flags.wielditem = false
default.player_set_animation(player, "lay" , 0)
end end
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 player_in_bed = get_player_in_bed_count()
local is_majority = (ges / 2) < player_in_bed local is_majority = (ges / 2) < player_in_bed
local form_n
local esc = minetest.formspec_escape
if finished then if finished then
form_n = beds.formspec .. "label[2.7,11; Good morning.]" form_n = beds.formspec .. "label[2.7,9;" .. esc(S("Good morning.")) .. "]"
else else
form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) .. form_n = beds.formspec .. "label[2.2,9;" ..
" of " .. tostring(ges) .. " players are in bed]" esc(S("@1 of @2 players are in bed", player_in_bed, ges)) .. "]"
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;" ..
esc(S("Force night skip")) .. "]"
end end
end end
@ -118,36 +234,46 @@ local function update_formspecs(finished)
end end
end end
-- Public functions -- Public functions
function beds.kick_players() function beds.kick_players()
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)
lay_down(player, nil, nil, false) lay_down(player, nil, nil, false)
end end
end end
function beds.skip_night() function beds.skip_night()
minetest.set_timeofday(0.23) minetest.set_timeofday(0.23)
end 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
if beds.player[name] then if beds.player[name] then
lay_down(player, nil, nil, false) lay_down(player, nil, nil, false)
end end
minetest.chat_send_player(name, "You can only sleep at night.")
minetest.chat_send_player(name, S("You can only sleep at night."))
return return
end end
-- move to bed -- move to bed
if not beds.player[name] then if not beds.player[name] then
lay_down(player, ppos, pos) lay_down(player, ppos, pos)
beds.set_spawns() -- save respawn positions when entering bed beds.set_spawns() -- save respawn positions when entering bed
else else
lay_down(player, nil, nil, false) lay_down(player, nil, nil, false)
@ -159,10 +285,13 @@ function beds.on_rightclick(pos, player)
-- skip the night and let all players stand up -- skip the night and let all players stand up
if check_in_beds() then if check_in_beds() then
minetest.after(2, function() minetest.after(2, function()
if not is_sp then if not is_sp then
update_formspecs(is_night_skip_enabled()) update_formspecs(is_night_skip_enabled())
end end
if is_night_skip_enabled() then if is_night_skip_enabled() then
beds.skip_night() beds.skip_night()
beds.kick_players() beds.kick_players()
@ -172,27 +301,56 @@ function beds.on_rightclick(pos, player)
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
if enable_respawn then if enable_respawn then
-- respawn player at bed if enabled and valid position is found -- respawn player at bed if enabled and valid position is found
minetest.register_on_respawnplayer(function(player) minetest.register_on_respawnplayer(function(player)
if not player then return end
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)
end end
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
if not player then return end
local name = player:get_player_name() local name = player:get_player_name()
lay_down(player, nil, nil, false, true) lay_down(player, nil, nil, false, true)
beds.player[name] = nil beds.player[name] = nil
if check_in_beds() then if check_in_beds() then
minetest.after(2, function() minetest.after(2, function()
update_formspecs(is_night_skip_enabled()) update_formspecs(is_night_skip_enabled())
if is_night_skip_enabled() then if is_night_skip_enabled() then
beds.skip_night() beds.skip_night()
beds.kick_players() beds.kick_players()
@ -201,20 +359,54 @@ minetest.register_on_leaveplayer(function(player)
end end
end) end)
minetest.register_on_dieplayer(function(player)
if not player then return end
local name = player:get_player_name()
local in_bed = beds.player
local pos = player:get_pos()
local yaw = get_look_yaw(pos)
if in_bed[name] then
lay_down(player, nil, pos, false)
player:set_look_horizontal(yaw)
player:set_pos(pos)
end
end)
local div = tonumber(minetest.settings:get("bed_sleep_divide")) or 2
minetest.register_on_player_receive_fields(function(player, formname, fields) 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())
if is_night_skip_enabled() then -- check if enough players are sleeping to skip night (was half)
local is_majority = (
#minetest.get_connected_players() / div) < last_player_in_bed
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)

View File

@ -1,17 +1,62 @@
beds = {} local is_50 = nil
beds.player = {} local is_53 = minetest.has_feature("object_step_has_moveresult")
beds.pos = {} local is_54 = minetest.has_feature("direct_velocity_on_players")
beds.spawn = {}
beds.formspec = "size[8,15;true]" .. -- Load support for MT game translation.
"bgcolor[#080808BB; true]" .. local S
"button_exit[2,12;4,0.75;leave;Leave Bed]" if minetest.get_translator ~= nil then
S = minetest.get_translator("beds") -- 5.x translation function
is_50 = true
else
if minetest.get_modpath("intllib") then
dofile(minetest.get_modpath("intllib") .. "/init.lua")
if intllib.make_gettext_pair then
gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
else
gettext = intllib.Getter() -- old text file method
end
S = gettext
else -- boilerplate function for 0.4
S = function(str, ...)
local args = {...}
return str:gsub("@%d+", function(match)
return args[tonumber(match:sub(2))]
end)
end
end
end
beds = {
player = {},
bed_position = {},
pos = {},
spawn = {},
get_translator = S,
formspec = "size[8,11;true]"
.. "no_prepend[]"
.. "bgcolor[#080808BB;true]"
.. "button_exit[2,10;4,0.75;leave;" .. minetest.formspec_escape(S("Leave Bed")) .. "]"
}
beds.is_50 = is_50
beds.is_53 = is_53
beds.is_54 = is_54
local modpath = minetest.get_modpath("beds") local modpath = minetest.get_modpath("beds")
-- check for minetest 5.x/0.4 compatibility
function beds.is_creative(name)
if is_53 then
return minetest.is_creative_enabled(name)
else
return creative.is_enabled_for(name) or minetest.settings:get_bool("creative_mode")
end
end
-- Load files -- Load files
dofile(modpath .. "/functions.lua") dofile(modpath .. "/functions.lua")
dofile(modpath .. "/api.lua") dofile(modpath .. "/api.lua")
dofile(modpath .. "/beds.lua") dofile(modpath .. "/beds.lua")
dofile(modpath .. "/spawns.lua") dofile(modpath .. "/spawns.lua")
print("[MOD] Beds loaded")

View File

@ -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.

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Schickes Bett
Simple Bed=Schlichtes Bett
This bed is already occupied!=Dieses Bett ist bereits belegt!
You have to stop moving before going to bed!=Sie müssen stehen bleiben, bevor Sie zu Bett gehen können!
Good morning.=Guten Morgen.
@1 of @2 players are in bed=@1 von @2 Spielern sind im Bett
Force night skip=Überspringen der Nacht erzwingen
You can only sleep at night.=Sie können nur nachts schlafen.
Leave Bed=Bett verlassen

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Cama de lujo
Simple Bed=Cama sencilla
This bed is already occupied!=Esta cama esta ocupada
You have to stop moving before going to bed!=Deja de moverte o no podras acostarte
Good morning.=Buenos días.
@1 of @2 players are in bed=@1 de @2 jugadores están durmiendo
Force night skip=Forzar hacer de dia
You can only sleep at night.=Sólo puedes dormir por la noche.
Leave Bed=Levantarse

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Lit chic
Simple Bed=Lit simple
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=Bonjour.
@1 of @2 players are in bed=@1 joueur(s) sur @2 sont au lit
Force night skip=Forcer le passage de la nuit
You can only sleep at night.=Vous ne pouvez dormir que la nuit.
Leave Bed=Se lever du lit

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Ranjang Mewah
Simple Bed=Ranjang Sederhana
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=Selamat pagi.
@1 of @2 players are in bed=@1 dari @2 pemain sedang tidur
Force night skip=Paksa lewati malam
You can only sleep at night.=Anda hanya dapat tidur pada waktu malam.
Leave Bed=Tinggalkan Ranjang

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Letto decorato
Simple Bed=Letto semplice
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=
@1 of @2 players are in bed=
Force night skip=
You can only sleep at night.=
Leave Bed=Alzati dal letto

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=lo selja'i ckana
Simple Bed=lo sampu ckana
This bed is already occupied!=.i lo ti ckana cu canlu
You have to stop moving before going to bed!=lo nu do cando cu sarcu lo nu do sipna
Good morning.=.i .uise'inai cerni
@1 of @2 players are in bed=.i @1 cmima be lu'i @2 le pilno cu vreta lo ckana
Force night skip=bapli le nu co'u nicte
You can only sleep at night.=.i steci le ka nicte kei fa le ka do kakne le ka sipna ca pa ckaji be ce'u
Leave Bed=cliva lo ckana

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Katil Beragam
Simple Bed=Katil Biasa
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=Selamat pagi.
@1 of @2 players are in bed=@1 daripada @2 pemain sedang tidur
Force night skip=Paksa langkau malam
You can only sleep at night.=Anda hanya boleh tidur pada waktu malam.
Leave Bed=Bangun

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Cama Bonita
Simple Bed=Cama Simples
This bed is already occupied!=Esta cama já está ocupada!
You have to stop moving before going to bed!=Você precisa parar de se mover antes de ir para cama!
Good morning.=Bom dia.
@1 of @2 players are in bed=@1 de @2 jogadores estão na cama
Force night skip=Forçar o amanhecer
You can only sleep at night.=Você só pode dormir à noite
Leave Bed=Sair da Cama

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Детализированная Кровать
Simple Bed=Обычная Кровать
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=Доброе утро.
@1 of @2 players are in bed=@1 из @2 игроков в кровати
Force night skip=Пропустить ночь
You can only sleep at night.=Вы можете спать только ночью.
Leave Bed=Встать с кровати

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Fin säng
Simple Bed=Enkel Säng
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.= God morgon.
@1 of @2 players are in bed=@1 av @2 spelar försöker sover.
Force night skip=Tvinga över natten
You can only sleep at night.=Du kan bara sova på natten.
Leave Bed=Lämna Säng

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=Pekná posteľ
Simple Bed=Jednoduchá posteľ
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=Dobré ráno.
@1 of @2 players are in bed=@1 z @2 hráčov sú v posteli
Force night skip=Nútene preskočiť noc
You can only sleep at night.=Môžeš spať len v noci.
Leave Bed=Opusti posteľ

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=花式床
Simple Bed=简易床
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=早安!
@1 of @2 players are in bed=@2位玩家中的@1位在床上
Force night skip=强制跳过夜晚
You can only sleep at night.=你只能在晚上睡觉。
Leave Bed=离开床

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=花式床
Simple Bed=簡易床
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=早安!
@1 of @2 players are in bed=@2位玩家中的@1位在床上
Force night skip=強制跳過夜晚
You can only sleep at night.=你只能在晚上睡覺。
Leave Bed=離開床

View File

@ -0,0 +1,10 @@
# textdomain: beds
Fancy Bed=
Simple Bed=
This bed is already occupied!=
You have to stop moving before going to bed!=
Good morning.=
@1 of @2 players are in bed=
Force night skip=
You can only sleep at night.=
Leave Bed=

4
mods/beds/mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = beds
description = beds which allows sleep, featured to (auto) skip the night.
depends = default, wool
optional_depends = player_api, pova, intllib

View File

@ -0,0 +1,160 @@
# Blender v2.69 (sub 0) OBJ File: ''
# www.blender.org
mtllib fancy_bed.mtl
o mattress_Mattress_nodebox-6_none.001_fancy_bed.png.001
v 0.437500 -0.312500 -0.437501
v 0.437500 -0.062500 -0.437501
v 0.437500 -0.062500 1.437499
v 0.437500 -0.312500 1.437499
v -0.437500 -0.312500 -0.437501
v -0.437500 -0.312500 1.437499
v -0.437500 -0.062500 1.437499
v -0.437500 -0.062500 -0.437501
v 0.437500 -0.176793 -0.437501
v -0.437500 -0.176793 -0.437501
vt 0.000171 0.499972
vt 0.000161 0.000182
vt 0.999791 0.000253
vt 0.999873 0.500022
vt 0.749576 0.000208
vt 0.749876 0.499854
vt 0.999848 0.999750
vt 0.000152 0.999750
vt 0.749276 0.130648
vt 0.000112 0.130648
g mattress_Mattress_nodebox-6_none.001_fancy_bed.png.001_none.001_fancy_bed.png.001
usemtl none.001_fancy_bed.png.001
s off
f 1/1 2/2 3/3 4/4
f 5/2 6/3 7/4 8/1
f 4/5 3/2 7/1 6/6
f 1/1 4/4 6/7 5/8
f 2/1 8/2 7/3 3/4
f 8/2 2/5 9/9 10/10
o wood_structure_Wood_structure_nodebox-4.001_none.002
v 0.374999 -0.375000 1.437499
v 0.374999 -0.125000 1.437499
v 0.374999 -0.125000 1.499999
v 0.374999 -0.375000 1.499999
v -0.374999 -0.375000 1.437499
v -0.374999 -0.375000 1.499999
v -0.374999 -0.125000 1.499999
v -0.374999 -0.125000 1.437499
v -0.375000 -0.500000 1.437499
v -0.375000 0.187500 1.437499
v -0.375000 0.187500 1.499999
v -0.375000 -0.500000 1.499999
v -0.500000 -0.500000 1.437499
v -0.500000 -0.500000 1.499999
v -0.500000 0.187500 1.499999
v -0.500000 0.187500 1.437499
v -0.437500 -0.375000 -0.437501
v -0.437500 -0.125000 -0.437501
v -0.437500 -0.125000 1.437498
v -0.437500 -0.375000 1.437498
v -0.500000 -0.375000 -0.437501
v -0.500000 -0.375000 1.437498
v -0.500000 -0.125000 1.437498
v -0.500000 -0.125000 -0.437501
v 0.375001 -0.000000 1.437499
v 0.375001 0.125000 1.437499
v 0.375001 0.125000 1.499999
v 0.375001 -0.000000 1.499999
v -0.375001 -0.000000 1.437499
v -0.375001 -0.000000 1.499999
v -0.375001 0.125000 1.499999
v -0.375001 0.125000 1.437499
v 0.500000 -0.500000 1.437499
v 0.500000 0.187500 1.437499
v 0.500000 0.187500 1.499999
v 0.500000 -0.500000 1.499999
v 0.375000 -0.500000 1.437499
v 0.375000 -0.500000 1.499999
v 0.375000 0.187500 1.499999
v 0.375000 0.187500 1.437499
v 0.500000 -0.375000 -0.437501
v 0.500000 -0.125000 -0.437501
v 0.500000 -0.125000 1.437499
v 0.500000 -0.375000 1.437499
v 0.437500 -0.375000 -0.437501
v 0.437500 -0.375000 1.437499
v 0.437500 -0.125000 1.437499
v 0.437500 -0.125000 -0.437501
v -0.375000 -0.500000 -0.500000
v -0.375000 -0.065000 -0.500000
v -0.375000 -0.065000 -0.437500
v -0.375000 -0.500000 -0.437500
v -0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 -0.437500
v -0.500000 -0.065000 -0.437500
v -0.500000 -0.065000 -0.500000
v 0.375006 -0.375000 -0.500000
v 0.375006 -0.125000 -0.500000
v 0.375006 -0.125000 -0.437500
v 0.375006 -0.375000 -0.437500
v -0.375006 -0.375000 -0.500000
v -0.375006 -0.375000 -0.437500
v -0.375006 -0.125000 -0.437500
v -0.375006 -0.125000 -0.500000
v 0.500000 -0.500000 -0.500000
v 0.500000 -0.065000 -0.500000
v 0.500000 -0.065000 -0.437500
v 0.500000 -0.500000 -0.437500
v 0.375000 -0.500000 -0.500000
v 0.375000 -0.500000 -0.437500
v 0.375000 -0.065000 -0.437500
v 0.375000 -0.065000 -0.500000
vt 0.377610 0.378205
vt 0.622484 0.378175
vt 0.622515 0.623120
vt 0.377671 0.623151
g wood_structure_Wood_structure_nodebox-4.001_none.002_none.002
usemtl none.002
s off
f 59/11 60/12 61/13 62/14
f 63/14 64/11 65/12 66/13
f 59/11 63/14 66/13 60/12
f 62/14 61/13 65/12 64/11
f 59/11 62/14 64/13 63/12
f 60/12 66/11 65/14 61/13
f 67/11 71/12 74/13 68/14
f 70/14 69/11 73/12 72/13
f 67/11 70/12 72/13 71/14
f 68/11 74/12 73/13 69/14
f 75/11 76/12 77/13 78/14
f 79/14 80/11 81/12 82/13
f 75/14 79/11 82/12 76/13
f 78/11 77/12 81/13 80/14
f 75/11 78/12 80/13 79/14
f 76/11 82/12 81/13 77/14
g wood_structure_Wood_structure_nodebox-4.001_none.002_none.003
usemtl none.003
f 15/11 16/12 17/13 18/14
f 11/13 15/14 18/11 12/12
f 14/14 13/11 17/12 16/13
f 11/14 14/11 16/12 15/13
f 12/11 18/12 17/13 13/14
f 19/11 20/12 21/13 22/14
f 23/14 24/11 25/12 26/13
f 19/14 23/11 26/12 20/13
f 22/11 21/12 25/13 24/14
f 19/11 22/12 24/13 23/14
f 20/11 26/12 25/13 21/14
f 27/14 28/11 29/12 30/13
f 31/11 32/12 33/13 34/14
f 27/11 30/12 32/13 31/14
f 28/14 34/11 33/12 29/13
f 35/11 39/12 42/13 36/14
f 38/14 37/11 41/12 40/13
f 35/14 38/11 40/12 39/13
f 36/11 42/12 41/13 37/14
f 43/11 44/12 45/13 46/14
f 47/14 48/11 49/12 50/13
f 43/14 47/11 50/12 44/13
f 46/11 45/12 49/13 48/14
f 43/11 46/12 48/13 47/14
f 44/11 50/12 49/13 45/14
f 51/14 52/11 53/12 54/13
f 55/13 56/14 57/11 58/12
f 51/11 54/12 56/13 55/14
f 52/14 58/11 57/12 53/13

View File

@ -0,0 +1,32 @@
# Blender v2.69 (sub 0) OBJ File: ''
# www.blender.org
mtllib simple_bed.mtl
o Simple_Bed
v 0.500000 -0.500000 -0.500000
v 0.500000 0.060000 -0.500000
v 0.500000 0.060000 1.500000
v 0.500000 -0.500000 1.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 1.500000
v -0.500000 0.060000 1.500000
v -0.500000 0.060000 -0.500000
vt 0.000112 0.780442
vt 0.000110 0.999969
vt 0.780324 0.999889
vt 0.780377 0.780471
vt 0.780636 0.390284
vt 0.999906 0.780382
vt 0.999906 0.390284
vt 0.780636 0.000047
vt 0.999906 0.000094
vt 0.390235 0.780320
vt 0.390235 0.000071
vt 0.000142 0.000142
usemtl none.002
s off
f 1/1 2/2 3/3 4/4
f 5/1 6/4 7/3 8/2
f 1/5 5/4 8/6 2/7
f 4/8 3/9 7/7 6/5
f 1/8 4/4 6/10 5/11
f 2/11 8/12 7/1 3/10

BIN
mods/beds/screenshot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

View File

@ -0,0 +1,5 @@
enable_bed_respawn (Enable bed respawn) bool true
enable_bed_night_skip (Enable night skip) bool true
bed_sleep_divide (Division of players needed to skip night) float 2

View File

@ -3,30 +3,44 @@ local org_file = world_path .. "/beds_spawns"
local file = world_path .. "/beds_spawns" local file = world_path .. "/beds_spawns"
local bkwd = false local bkwd = false
-- check for PA's beds mod spawns -- check for PA's beds mod spawns
local cf = io.open(world_path .. "/beds_player_spawns", "r") local cf = io.open(world_path .. "/beds_player_spawns", "r")
if cf ~= nil then if cf ~= nil then
io.close(cf) io.close(cf)
file = world_path .. "/beds_player_spawns" file = world_path .. "/beds_player_spawns"
bkwd = true bkwd = true
end end
function beds.read_spawns() function beds.read_spawns()
local spawns = beds.spawn local spawns = beds.spawn
local input = io.open(file, "r") local input = io.open(file, "r")
if input and not bkwd then if input and not bkwd then
repeat repeat
local x = input:read("*n") local x = input:read("*n")
if x == nil then if x == nil then
break break
end end
local y = input:read("*n") local y = input:read("*n")
local z = input:read("*n") local z = input:read("*n")
local name = input:read("*l") local name = input:read("*l")
spawns[name:sub(2)] = {x = x, y = y, z = z} spawns[name:sub(2)] = {x = x, y = y, z = z}
until input:read(0) == nil until input:read(0) == nil
io.close(input) io.close(input)
elseif input and bkwd then elseif input and bkwd then
beds.spawn = minetest.deserialize(input:read("*all")) beds.spawn = minetest.deserialize(input:read("*all"))
input:close() input:close()
beds.save_spawns() beds.save_spawns()
@ -35,29 +49,53 @@ function beds.read_spawns()
end end
end end
beds.read_spawns() beds.read_spawns()
function beds.save_spawns() function beds.save_spawns()
if not beds.spawn then if not beds.spawn then
return return
end end
local data = {} local data = {}
local output = io.open(org_file, "w") local output = io.open(org_file, "w")
for k, v in pairs(beds.spawn) do for k, v in pairs(beds.spawn) do
table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, k)) table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, k))
end end
output:write(table.concat(data)) output:write(table.concat(data))
io.close(output) io.close(output)
end 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
end end
end end
beds.save_spawns()
end
function beds.remove_spawns_at(pos)
for name, p in pairs(beds.spawn) do
if vector.equals(vector.round(p), pos) then
beds.spawn[name] = nil
end
end
beds.save_spawns() beds.save_spawns()
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 B

77
mods/boats/README.md Normal file
View File

@ -0,0 +1,77 @@
minetest mod boats
==========================
Boats improved for better performance and more realistic..
Information
-----------
This mod is named `boats`, it features work from original mod,
code changed to make it turn **quicker, better performance agains lag**,
and if you hit the shore too hard the boat is destroyed and drops 3 wood
![screenshot.png](screenshot.png)
#### Additions by TenPlus1
changed by TenPlus1 to add some new features
- boat is destroyed when crashing at speed (drops 3 wood)
- boats drop after 10 seconds if no driver
- boats can be damaged by mobs attacking player
- Improve physics of boat by implementing drag force (thanks gnag65)
- nil player check functions by misterskullz
Technical informaton
--------------------
When crafted you can use by putting and right click on,
then control with your directional keys:
#### Dependencies
* default
* mesecons (optional)
#### Crafting
W = any thing from wood group
```
W W
WWW
```
#### nodes
| Name | node | notes |
| ------------ | --------------- | ----- |
| Boat | boats:boat | it destroyed when crash at speed |
#### Controls (by default if not changed)
| Default key assigned | Action |
| -------------------- | -------------------------------------- |
| Right mouse button | Enter or exit boat when pointing at boat. |
| Forward | Speed up. Slow down when moving backwards. |
| Forward + backward | Enable cruise mode: accelerate to maximum speed without needing to hold. |
| 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. |
Licence
------
**Source code**
Modifications by TenPlus1
Originally by PilzAdam (MIT)
Various Minetest developers and contributors (MIT)
**Media (textures and model)**
Textures: Zeg9 (CC BY-SA 3.0)
original Model thetoon and Zeg9 (CC BY-SA 3.0),
modified by PavelS(SokolovPavel) (CC BY-SA 3.0),
modified by sofar (CC BY-SA 3.0)
Check [lisence.txt](lisence.txt)

View File

@ -1,15 +0,0 @@
Minetest Game mod: boats
========================
See license.txt for license information.
Authors of source code
----------------------
Originally by PilzAdam (MIT)
Various Minetest developers and contributors (MIT)
Authors of media (textures and model)
-------------------------------------
Textures: 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 sofar (CC BY-SA 3.0)

View File

@ -1 +1,3 @@
default default
player_api?
creative?

View File

@ -1,3 +1,32 @@
-- boats/init.lua
-- translation support and 5.x version check
local S, is_50, is_53
if minetest.get_translator ~= nil then
S = minetest.get_translator("boats") -- 5.x translation function
is_50 = true
is_53 = false
else
if minetest.get_modpath("intllib") then
dofile(minetest.get_modpath("intllib") .. "/init.lua")
if intllib.make_gettext_pair then
gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
else
gettext = intllib.Getter() -- old text file method
end
S = gettext
else -- boilerplate function
S = function(str, ...)
local args = {...}
return str:gsub("@%d+", function(match)
return args[tonumber(match:sub(2))]
end)
end
end
end
-- check for minetest 5.x compatibility
is_53 = minetest.has_feature("direct_velocity_on_players") or minetest.has_feature("is_creative_enabled") of false
-- --
-- Helper functions -- Helper functions
-- --
@ -8,15 +37,6 @@ local function is_water(pos)
end end
local function get_sign(i)
if i == 0 then
return 0
else
return i / math.abs(i)
end
end
local function get_velocity(v, yaw, y) local function get_velocity(v, yaw, y)
local x = -math.sin(yaw) * v local x = -math.sin(yaw) * v
local z = math.cos(yaw) * v local z = math.cos(yaw) * v
@ -28,23 +48,34 @@ local function get_v(v)
return math.sqrt(v.x ^ 2 + v.z ^ 2) return math.sqrt(v.x ^ 2 + v.z ^ 2)
end end
local function is_creative_enabled(name)
if is_53 then
return minetest.is_creative_enabled(name)
else
return creative.is_enabled_for(name) or minetest.settings:get_bool("creative_mode")
end
end
-- --
-- Boat entity -- Boat entity
-- --
local boat = { local boat = {
physical = true, initial_properties = {
-- Warning: Do not change the position of the collisionbox top surface, physical = true,
-- lowering it causes the boat to fall through the world if underwater -- Warning: Do not change the position of the collisionbox top surface,
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5}, -- lowering it causes the boat to fall through the world if underwater
visual = "mesh", collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
mesh = "boats_boat.obj", visual = "mesh",
textures = {"default_wood.png"}, mesh = "boats_boat.obj",
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,39 +84,58 @@ 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 -- Cleanup happens in boat.on_detach_child
clicker:set_detach() clicker:set_detach()
default.player_attached[name] = false if is_50 then
default.player_set_animation(clicker, "stand" , 30) player_api.set_animation(clicker, "stand", 30)
local pos = clicker:getpos() else
default.player_set_animation(clicker, "stand", 30)
end
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()
if attach and attach:get_luaentity() then
local luaentity = attach:get_luaentity()
if luaentity.driver then
luaentity.driver = nil
end
clicker:set_detach()
end
self.driver = clicker
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
self.driver = name
if is_50 then
player_api.player_attached[name] = true
else
default.player_attached[name] = true
end
minetest.after(0.2, function() minetest.after(0.2, function()
default.player_set_animation(clicker, "sit" , 30) if is_50 then
player_api.set_animation(clicker, "sit", 30)
else
default.player_set_animation(clicker, "sit", 30)
end
end) end)
clicker:set_look_horizontal(self.object:getyaw()) clicker:set_look_horizontal(self.object:get_yaw())
end
end
-- If driver leaves server while driving boat
function boat.on_detach_child(self, child)
if child and child:get_player_name() == self.driver then
if is_50 then
player_api.player_attached[child:get_player_name()] = false
else
default.player_attached[child:get_player_name()] = false
end
self.driver = nil
self.auto = false
end end
end 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({fleshy = 100})
if staticdata then if staticdata then
self.v = tonumber(staticdata) self.v = tonumber(staticdata)
end end
@ -102,21 +152,26 @@ 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 if is_50 then
player_api.player_attached[name] = false
else
default.player_attached[name] = false
end
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 is_creative_enabled(name)
and creative.is_enabled_for(puncher:get_player_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,46 +183,73 @@ end
function boat.on_step(self, dtime) function boat.on_step(self, dtime)
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
if self.driver then -- after 10 seconds remove boat and drop as item if not boarded
local ctrl = self.driver:get_player_control() self.count = (self.count or 0) + dtime
local yaw = self.object:getyaw()
if ctrl.up then if self.count > 10 then
self.v = self.v + 0.1 minetest.add_item(self.object:get_pos(), "boats:boat")
elseif ctrl.down then self.object:remove()
self.v = self.v - 0.1
end
if ctrl.left then
if self.v < 0 then
self.object:setyaw(yaw - (1 + dtime) * 0.03)
else
self.object:setyaw(yaw + (1 + dtime) * 0.03)
end
elseif ctrl.right then
if self.v < 0 then
self.object:setyaw(yaw + (1 + dtime) * 0.03)
else
self.object:setyaw(yaw - (1 + dtime) * 0.03)
end
end
end
local velo = self.object:getvelocity()
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
self.object:setpos(self.object:getpos())
return return
end end
local s = get_sign(self.v)
self.v = self.v - 0.02 * s
if s ~= get_sign(self.v) then
self.object:setvelocity({x = 0, y = 0, z = 0})
self.v = 0
return
end
if math.abs(self.v) > 5 then
self.v = 5 * get_sign(self.v)
end
local p = self.object:getpos() self.v = get_v(self.object:get_velocity()) * math.sign(self.v)
if self.driver then
self.count = 0 -- reset 10 second drop counter
local driver_objref = minetest.get_player_by_name(self.driver)
if driver_objref then
local ctrl = driver_objref:get_player_control()
if ctrl.up and ctrl.down then
if not self.auto then
self.auto = true
minetest.chat_send_player(self.driver, S("Boat cruise mode on"))
end
elseif ctrl.down then
self.v = self.v - dtime * 2.0
if self.auto then
self.auto = false
minetest.chat_send_player(self.driver, S("Boat cruise mode off"))
end
elseif ctrl.up or self.auto then
self.v = self.v + dtime * 2.0
end
if ctrl.left then
if self.v < -0.001 then
self.object:set_yaw(self.object:get_yaw() - dtime * 0.9)
else
self.object:set_yaw(self.object:get_yaw() + dtime * 0.9)
end
elseif ctrl.right then
if self.v < -0.001 then
self.object:set_yaw(self.object:get_yaw() + dtime * 0.9)
else
self.object:set_yaw(self.object:get_yaw() - dtime * 0.9)
end
end
else
-- If driver leaves server while driving 'driver' is present
-- but driver objectref is nil. Reset boat properties.
self.driver = nil
self.auto = false
end
end
local velo = self.object:get_velocity()
if not self.driver and
self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
self.object:set_pos(self.object:get_pos())
return
end
-- We need to preserve velocity sign to properly apply drag force
-- while moving backward
local drag = dtime * math.sign(self.v) * (0.01 + 0.0796 * self.v * self.v)
-- If drag is larger than velocity, then stop horizontal movement
if math.abs(self.v) <= math.abs(drag) then
self.v = 0
else
self.v = self.v - drag
end
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 +261,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 +275,48 @@ 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)
-- if boat comes to sudden stop then destroy boat and drop 3x wood
if (self.v2 or 0) - self.v >= 3 then
if self.driver then
--print ("Crash! with driver", self.v2 - self.v)
local driver_objref = minetest.get_player_by_name(self.driver)
default.player_attached[self.driver] = false
driver_objref:set_detach()
if is_50 then
player_api.set_animation(driver_objref, "stand" , 30)
else
default.player_set_animation(driver_objref, "stand" , 30)
end
else
--print ("Crash! no driver")
end
minetest.add_item(self.object:get_pos(), "default:wood 3")
self.object:remove()
return
end
self.v2 = self.v
end end
@ -218,7 +324,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,11 +352,10 @@ 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 is_creative_enabled(player_name) then
creative.is_enabled_for(player_name)) then
itemstack:take_item() itemstack:take_item()
end end
end end
@ -273,3 +378,6 @@ minetest.register_craft({
recipe = "boats:boat", recipe = "boats:boat",
burntime = 20, burntime = 20,
}) })
print ("[MOD] Boats loaded")

View File

@ -33,6 +33,7 @@ Copyright (C) 2012-2016 Zeg9
Copyright (C) 2012-2016 thetoon Copyright (C) 2012-2016 thetoon
Copyright (C) 2012-2016 PavelS(SokolovPavel) Copyright (C) 2012-2016 PavelS(SokolovPavel)
Copyright (C) 2016 sofar (sofar@foo-projects.org) Copyright (C) 2016 sofar (sofar@foo-projects.org)
Copyright (C) 2019 Bartosz (gang65@poczta.onet.pl)
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.

2
mods/boats/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = boats
depends = default, player_api, creative

BIN
mods/boats/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

56
mods/bucket/README.md Normal file
View File

@ -0,0 +1,56 @@
minetest mod Bucket
=========================
This mod is just bucket, but compatible with any engine
Information
-----------
This mod must be named `bucket` it permits to handle liquids
in a tool named bucket.
![screenshot.png](screenshot.png)
Tech information
----------------
This mod sustitute default one, you must disable the default of minetest
game if present or override it.
#### Dependencies
* default
Optional dependences:
* intllib
* dungeon_loot
#### Nodes
It does not provide any new node.
#### Items tools
| Node name | Description name |
| ----------------------- | --------------------- |
| bucket:bucket_empty | Empty Bucket |
| bucket:bucket_water | Water Bucket |
| bucket:bucket_river_water | River Water Bucket |
| bucket:bucket_lava | Lava Bucket |
License
-------
#### Authors of source code
Kahrl <kahrl@gmx.net> (LGPLv2.1+)
celeron55, Perttu Ahola <celeron55@gmail.com> (LGPLv2.1+)
Various Minetest developers and contributors (LGPLv2.1+)
#### Authors of media (textures)
ElementW (CC BY-SA 3.0)
Check [license.txt](license.txt)

View File

@ -1,13 +1,56 @@
Minetest Game mod: bucket minetest mod Bucket
========================= =========================
See license.txt for license information.
Authors of source code This mod is just bucket, but compatible with any engine
----------------------
Kahrl <kahrl@gmx.net> (LGPL 2.1) Information
celeron55, Perttu Ahola <celeron55@gmail.com> (LGPL 2.1) -----------
Various Minetest developers and contributors (LGPL 2.1)
This mod must be named `bucket` it permits to handle liquids
in a tool named bucket.
![screenshot.png](screenshot.png)
Tech information
----------------
This mod sustitute default one, you must disable the default of minetest
game if present or override it.
#### Dependencies
* default
Optional dependences:
* intllib
* dungeon_loot
#### Nodes
It does not provide any new node.
#### Items tools
| Node name | Description name |
| ----------------------- | --------------------- |
| bucket:bucket_empty | Empty Bucket |
| bucket:bucket_water | Water Bucket |
| bucket:bucket_river_water | River Water Bucket |
| bucket:bucket_lava | Lava Bucket |
License
-------
#### Authors of source code
Kahrl <kahrl@gmx.net> (LGPLv2.1+)
celeron55, Perttu Ahola <celeron55@gmail.com> (LGPLv2.1+)
Various Minetest developers and contributors (LGPLv2.1+)
#### Authors of media (textures)
Authors of media (textures)
---------------------------
ElementW (CC BY-SA 3.0) ElementW (CC BY-SA 3.0)
Check [license.txt](license.txt)

View File

@ -1,2 +1,2 @@
default default
intllib?

View File

@ -0,0 +1 @@
handle liquids in a tool named bucket

View File

@ -1,15 +1,39 @@
-- Minetest 0.4 mod: bucket -- Minetest mod: bucket
-- See README.txt for licensing and other information. -- See README.txt for licensing and other information.
-- Load support for MT game translation.
local S
if minetest.get_translator ~= nil then
S = minetest.get_translator("bucket") -- 5.x translation function
else
if minetest.get_modpath("intllib") then
dofile(minetest.get_modpath("intllib") .. "/init.lua")
if intllib.make_gettext_pair then
gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
else
gettext = intllib.Getter() -- old text file method
end
S = gettext
else -- boilerplate function
S = function(str, ...)
local args = {...}
return str:gsub("@%d+", function(match)
return args[tonumber(match:sub(2))]
end)
end
end
end
minetest.register_alias("bucket", "bucket:bucket_empty") minetest.register_alias("bucket", "bucket:bucket_empty")
minetest.register_alias("bucket_water", "bucket:bucket_water") minetest.register_alias("bucket_water", "bucket:bucket_water")
minetest.register_alias("bucket_lava", "bucket:bucket_lava") minetest.register_alias("bucket_lava", "bucket:bucket_lava")
minetest.register_craft({ minetest.register_craft({
output = 'bucket:bucket_empty 1', output = "bucket:bucket_empty 1",
recipe = { recipe = {
{'default:steel_ingot', '', 'default:steel_ingot'}, {"default:steel_ingot", "", "default:steel_ingot"},
{'', 'default:steel_ingot', ''}, {"", "default:steel_ingot", ""},
} }
}) })
@ -65,6 +89,7 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name
end end
local node = minetest.get_node_or_nil(pointed_thing.under) local node = minetest.get_node_or_nil(pointed_thing.under)
if not node then return end
local ndef = node and minetest.registered_nodes[node.name] local ndef = node and minetest.registered_nodes[node.name]
-- Call on_rightclick if the pointed node defines it -- Call on_rightclick if the pointed node defines it
@ -111,9 +136,9 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name
end end
minetest.register_craftitem("bucket:bucket_empty", { minetest.register_craftitem("bucket:bucket_empty", {
description = "Empty Bucket", description = S("Empty Bucket"),
inventory_image = "bucket.png", inventory_image = "bucket.png",
stack_max = 99, groups = {tool = 1},
liquids_pointable = true, liquids_pointable = true,
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "object" then if pointed_thing.type == "object" then
@ -125,6 +150,7 @@ minetest.register_craftitem("bucket:bucket_empty", {
end end
-- Check if pointing to a liquid source -- Check if pointing to a liquid source
local node = minetest.get_node(pointed_thing.under) local node = minetest.get_node(pointed_thing.under)
if not node then return end
local liquiddef = bucket.liquids[node.name] local liquiddef = bucket.liquids[node.name]
local item_count = user:get_wielded_item():get_count() local item_count = user:get_wielded_item():get_count()
@ -148,7 +174,7 @@ minetest.register_craftitem("bucket:bucket_empty", {
if inv:room_for_item("main", {name=liquiddef.itemname}) then if inv:room_for_item("main", {name=liquiddef.itemname}) then
inv:add_item("main", liquiddef.itemname) inv:add_item("main", liquiddef.itemname)
else else
local pos = user:getpos() local pos = user:get_pos()
pos.y = math.floor(pos.y + 0.5) pos.y = math.floor(pos.y + 0.5)
minetest.add_item(pos, liquiddef.itemname) minetest.add_item(pos, liquiddef.itemname)
end end
@ -185,17 +211,23 @@ bucket.register_liquid(
"default:water_flowing", "default:water_flowing",
"bucket:bucket_water", "bucket:bucket_water",
"bucket_water.png", "bucket_water.png",
"Water Bucket", S("Water Bucket"),
{water_bucket = 1} {tool = 1, water_bucket = 1}
) )
-- River water source is 'liquid_renewable = false' to avoid horizontal spread
-- of water sources in sloping rivers that can cause water to overflow
-- riverbanks and cause floods.
-- River water source is instead made renewable by the 'force renew' option
-- used here.
bucket.register_liquid( bucket.register_liquid(
"default:river_water_source", "default:river_water_source",
"default:river_water_flowing", "default:river_water_flowing",
"bucket:bucket_river_water", "bucket:bucket_river_water",
"bucket_river_water.png", "bucket_river_water.png",
"River Water Bucket", S("River Water Bucket"),
{water_bucket = 1}, {tool = 1, water_bucket = 1},
true true
) )
@ -204,7 +236,8 @@ bucket.register_liquid(
"default:lava_flowing", "default:lava_flowing",
"bucket:bucket_lava", "bucket:bucket_lava",
"bucket_lava.png", "bucket_lava.png",
"Lava Bucket" S("Lava Bucket"),
{tool = 1}
) )
minetest.register_craft({ minetest.register_craft({
@ -214,3 +247,16 @@ minetest.register_craft({
replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}}, replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}},
}) })
-- Register buckets as dungeon loot
if minetest.global_exists("dungeon_loot") then
dungeon_loot.register({
{name = "bucket:bucket_empty", chance = 0.55},
-- water in deserts/ice or above ground, lava otherwise
{name = "bucket:bucket_water", chance = 0.45,
types = {"sandstone", "desert", "ice"}},
{name = "bucket:bucket_water", chance = 0.45, y = {0, 32768},
types = {"normal"}},
{name = "bucket:bucket_lava", chance = 0.45, y = {-32768, -1},
types = {"normal"}},
})
end

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Leerer Eimer
Water Bucket=Wassereimer
River Water Bucket=Flusswassereimer
Lava Bucket=Lavaeimer

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Malplena Sitelo
Water Bucket=Sitelo da Akvo
River Water Bucket=Sitelo da Rivera Akvo
Lava Bucket=Sitelo da Lafo

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Cubo vacío
Water Bucket=Cubo con agua
River Water Bucket=Cubo con agua de río
Lava Bucket=Cubo con lava

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Seau vide
Water Bucket=Seau d'eau
River Water Bucket=Seau d'eau de rivière
Lava Bucket=Seau de lave

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Ember Kosong
Water Bucket=Ember Air
River Water Bucket=Ember Air Sungai
Lava Bucket=Ember Lava

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Secchio vuoto
Water Bucket=Secchio d'acqua
River Water Bucket=Secchio d'acqua di fiume
Lava Bucket=Secchio di lava

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=空のバケツ
Water Bucket=水入りバケツ
River Water Bucket=川の水入りバケツ
Lava Bucket=溶岩入りバケツ

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=lo baktu be no da
Water Bucket=lo baktu be lo djacu
River Water Bucket=lo baktu be lo rirxe djacu
Lava Bucket=lo baktu be lo likro'i

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Baldi Kosong
Water Bucket=Baldi Air
River Water Bucket=Baldi Air Sungai
Lava Bucket=Baldi Lava

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Balde Vazio
Water Bucket=Balde de Água
River Water Bucket=Balde de Água do Rio
Lava Bucket=Balde de Lava

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Пустое Ведро
Water Bucket=Ведро с Водой
River Water Bucket=Ведро с Речной Водой
Lava Bucket=Ведро с Лавой

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Prázdne vedro
Water Bucket=Vedro s vodou
River Water Bucket=Vedro s vodou z rieky
Lava Bucket=Vedro s lávou

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Tom hink
Water Bucket=Vattenhink
River Water Bucket=Flodvattenshink
Lava Bucket=Lavahink

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=Пусте Відро
Water Bucket=Відро З Водою
River Water Bucket=Відро З Річною Водою
Lava Bucket=Відро З Лавою

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=空桶
Water Bucket=水桶
River Water Bucket=河水桶
Lava Bucket=岩浆桶

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=空桶
Water Bucket=水桶
River Water Bucket=河水桶
Lava Bucket=岩漿桶

View File

@ -0,0 +1,5 @@
# textdomain: bucket
Empty Bucket=
Water Bucket=
River Water Bucket=
Lava Bucket=

4
mods/bucket/mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = bucket
description = handle liquids in a tool named bucket
depends = default
optional_depends = dungeon_loot

0
mods/bucket/textures/bucket.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 205 B

After

Width:  |  Height:  |  Size: 205 B

74
mods/carts/README.md Normal file
View File

@ -0,0 +1,74 @@
minetest mod Carts (formerly boost_cart)
==========================
Carts and rails (formerly boost_cart)
Information
-----------
This mod is named `carts`, it features work from `boost_cart` mod.
This is improved rail carts mod and featured boots rails..
![screenshot.png](screenshot.png)
#### Features
- A fast cart for your railway or roller coaster (up to 7 m/s!)
- Boost and brake rails
- Rail junction switching with the 'right-left' walking keys
- Handbrake with the 'back' key
#### Additions by TenPlus1
- Mesecon detector rail added
- 10 second cart drop when player or item not inside
- Alias' set to replace rails from boost_cart mod
Technical informaton
--------------------
Carts, based almost entirely on the mod boost_cart [1], which
itself is based on (and fully compatible with) the carts mod [2]
and the model was originally designed by stujones11 [3] (CC-0).
This mod can (and maybe must) replace the default carts mod of minetest game.
[1] https://github.com/SmallJoker/boost_cart/
[2] https://github.com/PilzAdam/carts/
[3] https://github.com/stujones11/railcart/
#### Dependencies
* default
* mesecons (optional)
#### nodes
| Name | node | notes |
| ------------ | --------------- | ----- |
| Rail | carts:rail | to use and travel over rails with carts |
| Bracke rails | carts:brakerail | rail to downgrade velocity of carts |
| Powered rail | carts:powerrail | rail to impulse velocity of a cart |
| Detector rail | carts:detectorrail | it depends on mesecons for detection of mese |
Alias:
| original | carts alias |
| -------------------- | -------------- |
| default:rail | carts:rail |
| carts:copperrail | default:rail |
| boost_cart:copperrail | default:rail |
| boost_cart:powerrail | carts:powerrail |
| boost_cart:brakerail | carts:brakerail |
| boost_cart:detectorrail | carts:detectorrail |
Licence
------
The model was originally designed by stujones11 [3] (CC-0).
Cart textures are based on original work from PixelBOX by Gambit (permissive
license).
Check [lisence.txt](lisence.txt)

View File

@ -1,22 +0,0 @@
Carts (formerly boost_cart)
==========================
Carts, based almost entirely on the mod boost_cart [1], which
itself is based on (and fully compatible with) the carts mod [2].
The model was originally designed by stujones11 [3] (CC-0).
Cart textures are based on original work from PixelBOX (WTFPL).
[1] https://github.com/SmallJoker/boost_cart/
[2] https://github.com/PilzAdam/carts/
[3] https://github.com/stujones11/railcart/
Features
----------
- A fast cart for your railway or roller coaster (up to 7 m/s!)
- Boost and brake rails
- Rail junction switching with the 'right-left' walking keys
- Handbrake with the 'back' key

View File

@ -1,10 +1,23 @@
-- carts/cart_entity.lua
-- support for MT game translation.
local S = carts.get_translator
-- is mesecons enabled ?
local HAVE_MESECONS_ENABLED = minetest.get_modpath("mesecons")
if HAVE_MESECONS_ENABLED then
dofile(minetest.get_modpath("carts") .. "/detector.lua")
end
local cart_entity = { local cart_entity = {
physical = false, -- otherwise going uphill breaks initial_properties = {
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, physical = false, -- otherwise going uphill breaks
visual = "mesh", collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
mesh = "carts_cart.b3d", visual = "mesh",
visual_size = {x=1, y=1}, mesh = "carts_cart.b3d",
textures = {"carts_cart.png"}, visual_size = {x=1, y=1},
textures = {"carts_cart.png"},
},
driver = nil, driver = nil,
punched = false, -- used to re-send velocity and position punched = false, -- used to re-send velocity and position
@ -22,40 +35,45 @@ function cart_entity:on_rightclick(clicker)
end end
local player_name = clicker:get_player_name() local player_name = clicker:get_player_name()
if self.driver and player_name == self.driver then if self.driver and player_name == self.driver then
self.driver = nil
carts:manage_attachment(clicker, nil) carts:manage_attachment(clicker, nil)
elseif not self.driver then elseif not self.driver then
self.driver = player_name
carts:manage_attachment(clicker, self.object) carts:manage_attachment(clicker, self.object)
self.driver = player_name
end end
end end
function cart_entity:on_activate(staticdata, dtime_s) function cart_entity:on_activate(staticdata, dtime_s)
self.object:set_armor_groups({immortal=1}) self.object:set_armor_groups({immortal=1})
self.attached_items = {} -- needed to stop itemcount glitch
if string.sub(staticdata, 1, string.len("return")) ~= "return" then if string.sub(staticdata, 1, string.len("return")) ~= "return" then
return return
end end
local data = minetest.deserialize(staticdata) local data = minetest.deserialize(staticdata)
if not data or type(data) ~= "table" then if type(data) ~= "table" then
return return
end end
self.railtype = data.railtype self.railtype = data.railtype
if data.old_dir then if data.old_dir then
self.old_dir = data.old_dir self.old_dir = data.old_dir
end end
if data.old_vel then
self.old_vel = data.old_vel
end
end end
function cart_entity:get_staticdata() function cart_entity:get_staticdata()
return minetest.serialize({ return minetest.serialize({
railtype = self.railtype, railtype = self.railtype,
old_dir = self.old_dir, old_dir = self.old_dir
old_vel = self.old_vel
}) })
end end
-- 0.5.x and later: When the driver leaves
function cart_entity:on_detach_child(child)
if child and child:get_player_name() == self.driver then
-- Clean up eye height
carts:manage_attachment(child, nil)
self.driver = nil
end
end
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
local pos = self.object:get_pos() local pos = self.object:get_pos()
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
@ -86,7 +104,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
local player = minetest.get_player_by_name(self.driver) local player = minetest.get_player_by_name(self.driver)
carts:manage_attachment(player, nil) carts:manage_attachment(player, nil)
end end
for _,obj_ in ipairs(self.attached_items) do for _, obj_ in ipairs(self.attached_items) do
if obj_ then if obj_ then
obj_:set_detach() obj_:set_detach()
end end
@ -120,7 +138,8 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
end end
local punch_interval = 1 local punch_interval = 1
if tool_capabilities and tool_capabilities.full_punch_interval then -- Faulty tool registrations may cause the interval to be set to 0 !
if tool_capabilities and (tool_capabilities.full_punch_interval or 0) > 0 then
punch_interval = tool_capabilities.full_punch_interval punch_interval = tool_capabilities.full_punch_interval
end end
time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval) time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval)
@ -153,6 +172,9 @@ local function rail_sound(self, dtime)
minetest.after(0.2, minetest.sound_stop, handle) minetest.after(0.2, minetest.sound_stop, handle)
end end
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
if not vel then return end -- nil check
local speed = vector.length(vel) local speed = vector.length(vel)
if speed > 0 then if speed > 0 then
self.sound_handle = minetest.sound_play( self.sound_handle = minetest.sound_play(
@ -169,7 +191,27 @@ local function get_railparams(pos)
return carts.railparams[node.name] or {} return carts.railparams[node.name] or {}
end end
local v3_len = vector.length
local function rail_on_step(self, dtime) local function rail_on_step(self, dtime)
-- if cart contains nothing then drop as item after 10 seconds
if not self.driver and #self.attached_items == 0 then
self.count = (self.count or 0) + dtime
if self.count > 10 then
minetest.add_item(self.object:get_pos(), "carts:cart")
if self.sound_handle then
local handle = self.sound_handle
self.sound_handle = nil
minetest.after(0.2, minetest.sound_stop, handle)
end
self.object:remove()
return
end
else
self.count = 0
end
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
if self.punched then if self.punched then
vel = vector.add(vel, self.velocity) vel = vector.add(vel, self.velocity)
@ -180,21 +222,11 @@ local function rail_on_step(self, dtime)
end end
local pos = self.object:get_pos() local pos = self.object:get_pos()
local cart_dir = carts:velocity_to_dir(vel)
local same_dir = vector.equals(cart_dir, self.old_dir)
local update = {} local update = {}
-- stop cart if velocity vector flips if self.old_pos and not self.punched and same_dir then
if self.old_vel and self.old_vel.y == 0 and
(self.old_vel.x * vel.x < 0 or self.old_vel.z * vel.z < 0) then
self.old_vel = {x = 0, y = 0, z = 0}
self.old_pos = pos
self.object:set_velocity(vector.new())
self.object:set_acceleration(vector.new())
rail_on_step_event(get_railparams(pos).on_step, self, dtime)
return
end
self.old_vel = vector.new(vel)
if self.old_pos and not self.punched then
local flo_pos = vector.round(pos) local flo_pos = vector.round(pos)
local flo_old = vector.round(self.old_pos) local flo_old = vector.round(self.old_pos)
if vector.equals(flo_pos, flo_old) then if vector.equals(flo_pos, flo_old) then
@ -213,20 +245,29 @@ local function rail_on_step(self, dtime)
end end
end end
if self.old_pos then local stop_wiggle = false
-- Detection for "skipping" nodes if self.old_pos and same_dir then
local found_path = carts:pathfinder( -- Detection for "skipping" nodes (perhaps use average dtime?)
pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype -- It's sophisticated enough to take the acceleration in account
local acc = self.object:get_acceleration()
local distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc))
local new_pos, new_dir = carts:pathfinder(
pos, self.old_pos, self.old_dir, distance, ctrl,
self.old_switch, self.railtype
) )
if not found_path then if new_pos then
-- No rail found: reset back to the expected position -- No rail found: set to the expected position
pos = vector.new(self.old_pos) pos = new_pos
update.pos = true update.pos = true
cart_dir = new_dir
end end
elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then
-- Stop wiggle
stop_wiggle = true
end end
local cart_dir = carts:velocity_to_dir(vel)
local railparams local railparams
-- dir: New moving direction of the cart -- dir: New moving direction of the cart
@ -234,16 +275,25 @@ local function rail_on_step(self, dtime)
local dir, switch_keys = carts:get_rail_direction( local dir, switch_keys = carts:get_rail_direction(
pos, cart_dir, ctrl, self.old_switch, self.railtype pos, cart_dir, ctrl, self.old_switch, self.railtype
) )
local dir_changed = not vector.equals(dir, self.old_dir)
local new_acc = {x=0, y=0, z=0} local new_acc = {x=0, y=0, z=0}
if vector.equals(dir, {x=0, y=0, z=0}) then if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
vel = {x = 0, y = 0, z = 0} vel = {x = 0, y = 0, z = 0}
pos = vector.round(pos) local pos_r = vector.round(pos)
if not carts:is_rail(pos_r, self.railtype)
and self.old_pos then
pos = self.old_pos
elseif not stop_wiggle then
pos = pos_r
else
pos.y = math.floor(pos.y + 0.5)
end
update.pos = true update.pos = true
update.vel = true update.vel = true
else else
-- Direction change detected -- Direction change detected
if not vector.equals(dir, self.old_dir) then if dir_changed then
vel = vector.multiply(dir, math.abs(vel.x + vel.z)) vel = vector.multiply(dir, math.abs(vel.x + vel.z))
update.vel = true update.vel = true
if dir.y ~= self.old_dir.y then if dir.y ~= self.old_dir.y then
@ -284,6 +334,11 @@ local function rail_on_step(self, dtime)
new_acc = vector.multiply(dir, acc) new_acc = vector.multiply(dir, acc)
end end
-- mesecon detector rail
if HAVE_MESECONS_ENABLED then
carts:signal_detector_rail(vector.round(pos))
end
-- Limits -- Limits
local max_vel = carts.speed_max local max_vel = carts.speed_max
for _, v in pairs({"x","y","z"}) do for _, v in pairs({"x","y","z"}) do
@ -295,8 +350,8 @@ local function rail_on_step(self, dtime)
end end
self.object:set_acceleration(new_acc) self.object:set_acceleration(new_acc)
self.old_pos = vector.new(pos) self.old_pos = vector.round(pos)
if not vector.equals(dir, {x=0, y=0, z=0}) then if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then
self.old_dir = vector.new(dir) self.old_dir = vector.new(dir)
end end
self.old_switch = switch_keys self.old_switch = switch_keys
@ -306,7 +361,7 @@ local function rail_on_step(self, dtime)
for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do
if not obj_:is_player() and if not obj_:is_player() and
obj_:get_luaentity() and obj_:get_luaentity() and
not obj_:get_luaentity().physical_state and -- not obj_:get_luaentity().physical_state and
obj_:get_luaentity().name == "__builtin:item" then obj_:get_luaentity().name == "__builtin:item" then
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}) obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
@ -332,7 +387,7 @@ local function rail_on_step(self, dtime)
elseif self.old_dir.z < 0 then elseif self.old_dir.z < 0 then
yaw = 1 yaw = 1
end end
self.object:setyaw(yaw * math.pi) self.object:set_yaw(yaw * math.pi)
local anim = {x=0, y=0} local anim = {x=0, y=0}
if dir.y == -1 then if dir.y == -1 then
@ -342,9 +397,15 @@ local function rail_on_step(self, dtime)
end end
self.object:set_animation(anim, 1, 0) self.object:set_animation(anim, 1, 0)
self.object:set_velocity(vel) if update.vel then
self.object:set_velocity(vel)
end
if update.pos then if update.pos then
self.object:set_pos(pos) if dir_changed then
self.object:set_pos(pos)
else
self.object:move_to(pos)
end
end end
-- call event handler -- call event handler
@ -359,8 +420,9 @@ end
minetest.register_entity("carts:cart", cart_entity) minetest.register_entity("carts:cart", cart_entity)
minetest.register_craftitem("carts:cart", { minetest.register_craftitem("carts:cart", {
description = "Cart (Sneak+Click to pick up)", description = S("Cart") .. "\n" .. S("(Sneak+Click to pick up)"),
inventory_image = minetest.inventorycube("carts_cart_top.png", "carts_cart_side.png", "carts_cart_side.png"), inventory_image = minetest.inventorycube(
"carts_cart_top.png", "carts_cart_front.png", "carts_cart_side.png"),
wield_image = "carts_cart_side.png", wield_image = "carts_cart_side.png",
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under local under = pointed_thing.under
@ -385,7 +447,7 @@ minetest.register_craftitem("carts:cart", {
end end
minetest.sound_play({name = "default_place_node_metal", gain = 0.5}, minetest.sound_play({name = "default_place_node_metal", gain = 0.5},
{pos = pointed_thing.above}) {pos = pointed_thing.above}, true)
if not (creative and creative.is_enabled_for if not (creative and creative.is_enabled_for
and creative.is_enabled_for(placer:get_player_name())) then and creative.is_enabled_for(placer:get_player_name())) then

View File

@ -1 +1,4 @@
default default
intllib?
mesecons?
dungeon_loot?

75
mods/carts/detector.lua Normal file
View File

@ -0,0 +1,75 @@
local mesecons_rules = mesecon.rules.flat
function carts:turnoff_detector_rail(pos)
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, "detector_rail") == 1 then
if node.name == "carts:detectorrail_on" then --has not been dug
minetest.swap_node(pos, {name = "carts:detectorrail", param2 = node.param2})
end
mesecon.receptor_off(pos, mesecons_rules)
end
end
function carts:signal_detector_rail(pos)
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, "detector_rail") ~= 1 then
return
end
if node.name == "carts:detectorrail" then
minetest.swap_node(pos, {name = "carts:detectorrail_on", param2 = node.param2})
end
mesecon.receptor_on(pos, mesecons_rules)
minetest.after(0.5, carts.turnoff_detector_rail, carts, pos)
end
carts:register_rail("carts:detectorrail", {
description = "Detector rail",
tiles = {
"carts_rail_straight_dtc.png", "carts_rail_curved_dtc.png",
"carts_rail_t_junction_dtc.png", "carts_rail_crossing_dtc.png"
},
groups = carts:get_rail_groups({detector_rail = 1}),
mesecons = {receptor = {state = "off", rules = mesecons_rules}},
})
minetest.register_alias("boost_cart:detectorrail", "carts:detectorrail")
carts:register_rail("carts:detectorrail_on", {
description = "Detector rail ON (you hacker you)",
tiles = {
"carts_rail_straight_dtc_on.png", "carts_rail_curved_dtc_on.png",
"carts_rail_t_junction_dtc_on.png", "carts_rail_crossing_dtc_on.png"
},
groups = carts:get_rail_groups({
detector_rail = 1, not_in_creative_inventory = 1
}),
drop = "carts:detectorrail",
mesecons = {receptor = {state = "on", rules = mesecons_rules}},
})
minetest.register_alias("boost_cart:detectorrail_on", "carts:detectorrail_on")
minetest.register_craft({
output = "boost_cart:detectorrail 6",
recipe = {
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
},
})

View File

@ -1,3 +1,5 @@
local is_50 = minetest.get_translator
function carts:get_sign(z) function carts:get_sign(z)
if z == 0 then if z == 0 then
return 0 return 0
@ -12,14 +14,28 @@ function carts:manage_attachment(player, obj)
end end
local status = obj ~= nil local status = obj ~= nil
local player_name = player:get_player_name() local player_name = player:get_player_name()
if default.player_attached[player_name] == status then if obj and player:get_attach() == obj then
return return
end end
default.player_attached[player_name] = status
if is_50 then
player_api.player_attached[player_name] = status
else
default.player_attached[player_name] = status
end
if status then if status then
player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0}) player:set_attach(obj, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0}) player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
-- player_api does not update the animation
-- when the player is attached, reset to default animation
if is_50 then
player_api.set_animation(player, "stand")
else
default.player_set_animation(player, "stand")
end
else else
player:set_detach() player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
@ -99,6 +115,16 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
right.z = -dir.x right.z = -dir.x
end end
local straight_priority = ctrl and dir.y ~= 0
-- Normal, to disallow rail switching up- & downhill
if straight_priority then
cur = self:check_front_up_down(pos, dir, true, railtype)
if cur then
return cur
end
end
if ctrl then if ctrl then
if old_switch == 1 then if old_switch == 1 then
left_check = false left_check = false
@ -106,14 +132,14 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
right_check = false right_check = false
end end
if ctrl.left and left_check then if ctrl.left and left_check then
cur = carts:check_front_up_down(pos, left, false, railtype) cur = self:check_front_up_down(pos, left, false, railtype)
if cur then if cur then
return cur, 1 return cur, 1
end end
left_check = false left_check = false
end end
if ctrl.right and right_check then if ctrl.right and right_check then
cur = carts:check_front_up_down(pos, right, false, railtype) cur = self:check_front_up_down(pos, right, false, railtype)
if cur then if cur then
return cur, 2 return cur, 2
end end
@ -122,9 +148,11 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
end end
-- Normal -- Normal
cur = carts:check_front_up_down(pos, dir, true, railtype) if not straight_priority then
if cur then cur = self:check_front_up_down(pos, dir, true, railtype)
return cur if cur then
return cur
end
end end
-- Left, if not already checked -- Left, if not already checked
@ -158,33 +186,37 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
return {x=0, y=0, z=0} return {x=0, y=0, z=0}
end end
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) function carts:pathfinder(pos_, old_pos, old_dir, distance, ctrl,
if vector.equals(old_pos, pos_) then pf_switch, railtype)
return true
end
local pos = vector.round(pos_) local pos = vector.round(pos_)
if vector.equals(old_pos, pos) then
return
end
local pf_pos = vector.round(old_pos) local pf_pos = vector.round(old_pos)
local pf_dir = vector.new(old_dir) local pf_dir = vector.new(old_dir)
distance = math.min(carts.path_distance_max,
math.floor(distance + 1))
for i = 1, 3 do for i = 1, distance do
pf_dir, pf_switch = carts:get_rail_direction( pf_dir, pf_switch = self:get_rail_direction(
pf_pos, pf_dir, ctrl, pf_switch, railtype) pf_pos, pf_dir, ctrl, pf_switch or 0, railtype)
if vector.equals(pf_dir, {x=0, y=0, z=0}) then if vector.equals(pf_dir, {x=0, y=0, z=0}) then
-- No way forwards -- No way forwards
return false return pf_pos, pf_dir
end end
pf_pos = vector.add(pf_pos, pf_dir) pf_pos = vector.add(pf_pos, pf_dir)
if vector.equals(pf_pos, pos) then if vector.equals(pf_pos, pos) then
-- Success! Cart moved on correctly -- Success! Cart moved on correctly
return true return
end end
end end
-- Cart not found -- Not found. Put cart to predicted position
return false return pf_pos, pf_dir
end end
function carts:register_rail(name, def_overwrite, railparams) function carts:register_rail(name, def_overwrite, railparams)

View File

@ -1,20 +1,48 @@
-- carts/init.lua
-- translation support
local S
if minetest.get_translator ~= nil then
S = minetest.get_translator("carts") -- 5.x translation function
else
if minetest.get_modpath("intllib") then
dofile(minetest.get_modpath("intllib") .. "/init.lua")
if intllib.make_gettext_pair then
gettext, ngettext = intllib.make_gettext_pair() -- new gettext method
else
gettext = intllib.Getter() -- old text file method
end
S = gettext
else -- boilerplate function
S = function(str, ...)
local args = {...}
return str:gsub("@%d+", function(match)
return args[tonumber(match:sub(2))]
end)
end
end
end
carts = {} carts = {}
carts.modpath = minetest.get_modpath("carts") carts.modpath = minetest.get_modpath("carts")
carts.railparams = {} carts.railparams = {}
carts.get_translator = S
-- Maximal speed of the cart in m/s (min = -1) -- Maximal speed of the cart in m/s (min = -1)
carts.speed_max = 7 carts.speed_max = 7
-- Set to -1 to disable punching the cart from inside (min = -1) -- Set to -1 to disable punching the cart from inside (min = -1)
carts.punch_speed_max = 5 carts.punch_speed_max = 5
-- Maximal distance for the path correction (for dtime peaks)
carts.path_distance_max = 3
dofile(carts.modpath.."/functions.lua") dofile(carts.modpath.."/functions.lua")
dofile(carts.modpath.."/rails.lua") dofile(carts.modpath.."/rails.lua")
-- Support for non-default games
if not default.player_attached then
default.player_attached = {}
end
dofile(carts.modpath.."/cart_entity.lua") dofile(carts.modpath.."/cart_entity.lua")
-- Register rails as dungeon loot
if minetest.global_exists("dungeon_loot") then
dungeon_loot.register({
name = "carts:rail", chance = 0.35, count = {1, 6}
})
end

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Lore
(Sneak+Click to pick up)=(Schleichen u. Klicken zum Aufheben)
Rail=Schiene
Powered Rail=Antriebsschiene
Brake Rail=Bremsschiene

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Vagoneta
(Sneak+Click to pick up)=(Agacharse+Clic para recoger)
Rail=Raíl
Powered Rail=Raíl energizado
Brake Rail=Raíl de frenado

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Chariot
(Sneak+Click to pick up)=(Se baisser + clic pour ramasser)
Rail=Rail
Powered Rail=Rail de traction
Brake Rail=Rail de freinage

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Vagone
(Sneak+Click to pick up)=(Strisciare+Click per raccoglierlo)
Rail=Binario
Powered Rail=Binario alimentato
Brake Rail=Binario freno

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Pedati
(Sneak+Click to pick up)=(Selinap+Klik untuk ambil balik)
Rail=Landasan
Powered Rail=Landasan Berkuasa
Brake Rail=Landasan Brek

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Вагонетка
(Sneak+Click to pick up)=(Пригнитесь и кликните по вагонетке, чтобы забрать)
Rail=Рельса
Powered Rail=Механизированная Рельса
Brake Rail=Рельса с тормозом

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=Vagn
(Sneak+Click to pick up)=(Shift+Klicka för att plocka upp)
Rail=Räls
Powered Rail=Aktiverad räls
Brake Rail=Broms räls

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=矿车
(Sneak+Click to pick up)=(潜行+单击以捡起)
Rail=铁轨
Powered Rail=动力铁轨
Brake Rail=制动铁轨

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=礦車
(Sneak+Click to pick up)=(潛行+單擊以撿起)
Rail=鐵軌
Powered Rail=動力鐵軌
Brake Rail=制動鐵軌

View File

@ -0,0 +1,6 @@
# textdomain: carts
Cart=
(Sneak+Click to pick up)=
Rail=
Powered Rail=
Brake Rail=

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