Skip to content

Commit edb02e9

Browse files
committedFeb 24, 2015
Add beds
1 parent 3b526a7 commit edb02e9

24 files changed

+564
-0
lines changed
 

Diff for: ‎game_api.txt

+36
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,42 @@ The bucket API allows registering new types of buckets for non-default liquids.
2424
"Lava Bucket" -- Bucket description
2525
)
2626

27+
Beds API
28+
--------
29+
beds.register_bed(
30+
"beds:bed", -- Bed name
31+
def: See [#Bed definition] -- Bed definition
32+
)
33+
34+
beds.read_spawns() -- returns a table containing players respawn positions
35+
beds.kick_players() -- forces all players to leave bed
36+
beds.skip_night() -- sets world time to morning and saves respawn position of all players currently sleeping
37+
38+
#Bed definition
39+
---------------
40+
{
41+
description = "Simple Bed",
42+
inventory_image = "beds_bed.png",
43+
wield_image = "beds_bed.png",
44+
tiles = {
45+
bottom = {[Tile definition],
46+
^ the tiles of the bottom part of the bed
47+
},
48+
top = {[Tile definition],
49+
^ the tiles of the bottom part of the bed
50+
}
51+
},
52+
nodebox = {
53+
bottom = regular nodebox, see [Node boxes], -- bottm part of bed
54+
top = regular nodebox, see [Node boxes], -- top part of bed
55+
},
56+
selectionbox = regular nodebox, see [Node boxes], -- for both nodeboxes
57+
recipe = { -- Craft recipe
58+
{"group:wool", "group:wool", "group:wool"},
59+
{"group:wood", "group:wood", "group:wood"}
60+
}
61+
}
62+
2763
Doors API
2864
---------
2965
The doors mod allows modders to register custom doors and trapdoors.

Diff for: ‎mods/beds/Changelog.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
1.0.1 beta
2+
----------
3+
- Add backwards compatibility with PilzAdam's beds mod
4+
- Fix placement
5+
- Fix small bugs
6+
- Prevent possible crash
7+
8+
1.1
9+
---
10+
- Add fancy bed model (based on jp's model)
11+
- Add API to register beds
12+
- Allow players always to detach from bed (by donat-b)
13+
- If more than 50% of players want sleep they can skip the night
14+
- Don't show sleep dialog in singleplayer
15+
16+
1.1.1
17+
-----
18+
- Prevent possbile crash by trying to reposition leaving players

Diff for: ‎mods/beds/README.txt

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
Minetest mod "Beds"
2+
===================
3+
by BlockMen (c) 2014-2015
4+
5+
Version: 1.1.1
6+
7+
About
8+
~~~~~
9+
This mod adds a bed to Minetest which allows to skip the night. To sleep rightclick the bed, if playing
10+
in singleplayer mode the night gets skipped imideatly. If playing on server you get shown how many other
11+
players are in bed too. If all players are sleeping the night gets skipped aswell. Also the night skip can be forced
12+
if more than 50% of the players are lying in bed and use this option.
13+
14+
Another feature is a controled respawning. If you have slept in bed (not just lying in it) your respawn point
15+
is set to the beds location. If dying you will respawn there.
16+
17+
18+
19+
You can craft two types of beds:
20+
21+
22+
Simple shaped bed:
23+
24+
wool wool wool
25+
wood wood wood
26+
27+
Fancy shaped bed:
28+
29+
wool wool stick
30+
wood wood wood
31+
32+
Notice: You can use any color of wood or wool, mixing different is also possible.
33+
34+
35+
License of source code, textures: WTFPL
36+
---------------------------------------
37+
(c) Copyright BlockMen (2014-2015)
38+
39+
40+
41+
This program is free software. It comes without any warranty, to
42+
the extent permitted by applicable law. You can redistribute it
43+
and/or modify it under the terms of the Do What The Fuck You Want
44+
To Public License, Version 2, as published by Sam Hocevar. See
45+
http://sam.zoy.org/wtfpl/COPYING for more details.

Diff for: ‎mods/beds/api.lua

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
function beds.register_bed(name, def)
2+
minetest.register_node(name .. "_bottom", {
3+
description = def.description,
4+
inventory_image = def.inventory_image,
5+
wield_image = def.wield_image,
6+
drawtype = "nodebox",
7+
tiles = def.tiles.bottom,
8+
paramtype = "light",
9+
paramtype2 = "facedir",
10+
stack_max = 1,
11+
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
12+
sounds = default.node_sound_wood_defaults(),
13+
node_box = {
14+
type = "fixed",
15+
fixed = def.nodebox.bottom,
16+
},
17+
selection_box = {
18+
type = "fixed",
19+
fixed = def.selectionbox,
20+
21+
},
22+
after_place_node = function(pos, placer, itemstack)
23+
local n = minetest.get_node_or_nil(pos)
24+
if not n or not n.param2 then
25+
minetest.remove_node(pos)
26+
return true
27+
end
28+
local dir = minetest.facedir_to_dir(n.param2)
29+
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
30+
local n2 = minetest.get_node_or_nil(p)
31+
local def = minetest.registered_items[n2.name] or nil
32+
if not n2 or not def or not def.buildable_to then
33+
minetest.remove_node(pos)
34+
return true
35+
end
36+
minetest.set_node(p, {name = n.name:gsub("%_bottom", "_top"), param2 = n.param2})
37+
return false
38+
end,
39+
on_destruct = function(pos)
40+
local n = minetest.get_node_or_nil(pos)
41+
if not n then return end
42+
local dir = minetest.facedir_to_dir(n.param2)
43+
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
44+
local n2 = minetest.get_node(p)
45+
if minetest.get_item_group(n2.name, "bed") == 2 and n.param2 == n2.param2 then
46+
minetest.remove_node(p)
47+
end
48+
end,
49+
on_rightclick = function(pos, node, clicker)
50+
beds.on_rightclick(pos, clicker)
51+
end,
52+
})
53+
54+
minetest.register_node(name .. "_top", {
55+
drawtype = "nodebox",
56+
tiles = def.tiles.top,
57+
paramtype = "light",
58+
paramtype2 = "facedir",
59+
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
60+
sounds = default.node_sound_wood_defaults(),
61+
node_box = {
62+
type = "fixed",
63+
fixed = def.nodebox.top,
64+
},
65+
selection_box = {
66+
type = "fixed",
67+
fixed = {0, 0, 0, 0, 0, 0},
68+
},
69+
})
70+
71+
minetest.register_alias(name, name .. "_bottom")
72+
73+
-- register recipe
74+
minetest.register_craft({
75+
output = name,
76+
recipe = def.recipe
77+
})
78+
end

Diff for: ‎mods/beds/beds.lua

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
-- fancy shaped bed
2+
beds.register_bed("beds:fancy_bed", {
3+
description = "Fancy Bed",
4+
inventory_image = "beds_bed_fancy.png",
5+
wield_image = "beds_bed_fancy.png",
6+
tiles = {
7+
bottom = {
8+
"beds_bed_top1.png",
9+
"default_wood.png",
10+
"beds_bed_side1.png",
11+
"beds_bed_side1.png^[transformFX",
12+
"default_wood.png",
13+
"beds_bed_foot.png",
14+
},
15+
top = {
16+
"beds_bed_top2.png",
17+
"default_wood.png",
18+
"beds_bed_side2.png",
19+
"beds_bed_side2.png^[transformFX",
20+
"beds_bed_head.png",
21+
"default_wood.png",
22+
}
23+
},
24+
nodebox = {
25+
bottom = {
26+
{-0.5, -0.5, -0.5, -0.375, -0.065, -0.4375},
27+
{0.375, -0.5, -0.5, 0.5, -0.065, -0.4375},
28+
{-0.5, -0.375, -0.5, 0.5, -0.125, -0.4375},
29+
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
30+
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
31+
{-0.4375, -0.3125, -0.4375, 0.4375, -0.0625, 0.5},
32+
},
33+
top = {
34+
{-0.5, -0.5, 0.4375, -0.375, 0.1875, 0.5},
35+
{0.375, -0.5, 0.4375, 0.5, 0.1875, 0.5},
36+
{-0.5, 0, 0.4375, 0.5, 0.125, 0.5},
37+
{-0.5, -0.375, 0.4375, 0.5, -0.125, 0.5},
38+
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
39+
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
40+
{-0.4375, -0.3125, -0.5, 0.4375, -0.0625, 0.4375},
41+
}
42+
},
43+
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
44+
recipe = {
45+
{"group:wool", "group:wool", "group:stick"},
46+
{"group:wood", "group:wood", "group:wood"},
47+
},
48+
})
49+
50+
-- simple shaped bed
51+
beds.register_bed("beds:bed", {
52+
description = "Simple Bed",
53+
inventory_image = "beds_bed.png",
54+
wield_image = "beds_bed.png",
55+
tiles = {
56+
bottom = {
57+
"beds_bed_top_bottom.png^[transformR90",
58+
"default_wood.png",
59+
"beds_bed_side_bottom_r.png",
60+
"beds_bed_side_bottom_r.png^[transformfx",
61+
"beds_transparent.png",
62+
"beds_bed_side_bottom.png"
63+
},
64+
top = {
65+
"beds_bed_top_top.png^[transformR90",
66+
"default_wood.png",
67+
"beds_bed_side_top_r.png",
68+
"beds_bed_side_top_r.png^[transformfx",
69+
"beds_bed_side_top.png",
70+
"beds_transparent.png",
71+
}
72+
},
73+
nodebox = {
74+
bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
75+
top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
76+
},
77+
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
78+
recipe = {
79+
{"group:wool", "group:wool", "group:wool"},
80+
{"group:wood", "group:wood", "group:wood"}
81+
},
82+
83+
})
84+
85+
-- aliases for PA's beds mod
86+
minetest.register_alias("beds:bed_bottom_red", "beds:bed_bottom")
87+
minetest.register_alias("beds:bed_bottom_orange", "beds:bed_bottom")
88+
minetest.register_alias("beds:bed_bottom_yellow", "beds:bed_bottom")
89+
minetest.register_alias("beds:bed_bottom_green", "beds:bed_bottom")
90+
minetest.register_alias("beds:bed_bottom_blue", "beds:bed_bottom")
91+
minetest.register_alias("beds:bed_bottom_violet", "beds:bed_bottom")
92+
minetest.register_alias("beds:bed_bottom_black", "beds:bed_bottom")
93+
minetest.register_alias("beds:bed_bottom_grey", "beds:bed_bottom")
94+
minetest.register_alias("beds:bed_bottom_white", "beds:bed_bottom")
95+
96+
minetest.register_alias("beds:bed_top_red", "beds:bed_top")
97+
minetest.register_alias("beds:bed_top_orange", "beds:bed_top")
98+
minetest.register_alias("beds:bed_top_yellow", "beds:bed_top")
99+
minetest.register_alias("beds:bed_top_green", "beds:bed_top")
100+
minetest.register_alias("beds:bed_top_blue", "beds:bed_top")
101+
minetest.register_alias("beds:bed_top_violet", "beds:bed_top")
102+
minetest.register_alias("beds:bed_top_black", "beds:bed_top")
103+
minetest.register_alias("beds:bed_top_grey", "beds:bed_top")
104+
minetest.register_alias("beds:bed_top_white", "beds:bed_top")

Diff for: ‎mods/beds/depends.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
default
2+
wool

Diff for: ‎mods/beds/functions.lua

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
local player_in_bed = 0
2+
local is_sp = minetest.is_singleplayer()
3+
4+
5+
-- helper functions
6+
7+
local function get_look_yaw(pos)
8+
local n = minetest.get_node(pos)
9+
if n.param2 == 1 then
10+
return 7.9, n.param2
11+
elseif n.param2 == 3 then
12+
return 4.75, n.param2
13+
elseif n.param2 == 0 then
14+
return 3.15, n.param2
15+
else
16+
return 6.28, n.param2
17+
end
18+
end
19+
20+
local function check_in_beds(players)
21+
local in_bed = beds.player
22+
if not players then
23+
players = minetest.get_connected_players()
24+
end
25+
26+
for n, player in ipairs(players) do
27+
local name = player:get_player_name()
28+
if not in_bed[name] then
29+
return false
30+
end
31+
end
32+
33+
return true
34+
end
35+
36+
local function lay_down(player, pos, bed_pos, state, skip)
37+
local name = player:get_player_name()
38+
local hud_flags = player:hud_get_flags()
39+
40+
if not player or not name then
41+
return
42+
end
43+
44+
-- stand up
45+
if state ~= nil and not state then
46+
local p = beds.pos[name] or nil
47+
if beds.player[name] ~= nil then
48+
beds.player[name] = nil
49+
player_in_bed = player_in_bed - 1
50+
end
51+
-- skip here to prevent sending player specific changes (used for leaving players)
52+
if skip then
53+
return
54+
end
55+
if p then
56+
player:setpos(p)
57+
end
58+
59+
-- physics, eye_offset, etc
60+
player:set_eye_offset({x=0,y=0,z=0}, {x=0,y=0,z=0})
61+
player:set_look_yaw(math.random(1, 180)/100)
62+
default.player_attached[name] = false
63+
player:set_physics_override(1, 1, 1)
64+
hud_flags.wielditem = true
65+
default.player_set_animation(player, "stand" , 30)
66+
67+
-- lay down
68+
else
69+
beds.player[name] = 1
70+
beds.pos[name] = pos
71+
player_in_bed = player_in_bed + 1
72+
73+
-- physics, eye_offset, etc
74+
player:set_eye_offset({x=0,y=-13,z=0}, {x=0,y=0,z=0})
75+
local yaw, param2 = get_look_yaw(bed_pos)
76+
player:set_look_yaw(yaw)
77+
local dir = minetest.facedir_to_dir(param2)
78+
local p = {x=bed_pos.x+dir.x/2,y=bed_pos.y,z=bed_pos.z+dir.z/2}
79+
player:set_physics_override(0, 0, 0)
80+
player:setpos(p)
81+
default.player_attached[name] = true
82+
hud_flags.wielditem = false
83+
default.player_set_animation(player, "lay" , 0)
84+
end
85+
86+
player:hud_set_flags(hud_flags)
87+
end
88+
89+
local function update_formspecs(finished)
90+
local ges = #minetest.get_connected_players()
91+
local form_n = ""
92+
local is_majority = (ges/2) < player_in_bed
93+
94+
if finished then
95+
form_n = beds.formspec ..
96+
"label[2.7,11; Good morning.]"
97+
else
98+
form_n = beds.formspec ..
99+
"label[2.2,11;"..tostring(player_in_bed).." of "..tostring(ges).." players are in bed]"
100+
if is_majority then
101+
form_n = form_n ..
102+
"button_exit[2,8;4,0.75;force;Force night skip]"
103+
end
104+
end
105+
106+
for name,_ in pairs(beds.player) do
107+
minetest.show_formspec(name, "beds_form", form_n)
108+
end
109+
end
110+
111+
112+
-- public functions
113+
114+
function beds.kick_players()
115+
for name,_ in pairs(beds.player) do
116+
local player = minetest.get_player_by_name(name)
117+
lay_down(player, nil, nil, false)
118+
end
119+
end
120+
121+
function beds.skip_night()
122+
minetest.set_timeofday(0.23)
123+
beds.set_spawns()
124+
end
125+
126+
function beds.on_rightclick(pos, player)
127+
local name = player:get_player_name()
128+
local ppos = player:getpos()
129+
local tod = minetest.get_timeofday()
130+
131+
if tod > 0.2 and tod < 0.805 then
132+
if beds.player[name] then
133+
lay_down(player, nil, nil, false)
134+
end
135+
minetest.chat_send_player(name, "You can only sleep at night.")
136+
return
137+
end
138+
139+
-- move to bed
140+
if not beds.player[name] then
141+
lay_down(player, ppos, pos)
142+
else
143+
lay_down(player, nil, nil, false)
144+
end
145+
146+
if not is_sp then
147+
update_formspecs(false)
148+
end
149+
150+
-- skip the night and let all players stand up
151+
if check_in_beds() then
152+
minetest.after(2, function()
153+
beds.skip_night()
154+
if not is_sp then
155+
update_formspecs(true)
156+
end
157+
beds.kick_players()
158+
end)
159+
end
160+
end
161+
162+
163+
-- callbacks
164+
165+
minetest.register_on_joinplayer(function(player)
166+
beds.read_spawns()
167+
end)
168+
169+
minetest.register_on_respawnplayer(function(player)
170+
local name = player:get_player_name()
171+
local pos = beds.spawn[name] or nil
172+
if pos then
173+
player:setpos(pos)
174+
return true
175+
end
176+
end)
177+
178+
minetest.register_on_leaveplayer(function(player)
179+
local name = player:get_player_name()
180+
lay_down(player, nil, nil, false, true)
181+
beds.player[name] = nil
182+
if check_in_beds() then
183+
minetest.after(2, function()
184+
beds.skip_night()
185+
update_formspecs(true)
186+
beds.kick_players()
187+
end)
188+
end
189+
end)
190+
191+
minetest.register_on_player_receive_fields(function(player, formname, fields)
192+
if formname ~= "beds_form" then
193+
return
194+
end
195+
if fields.quit or fields.leave then
196+
lay_down(player, nil, nil, false)
197+
update_formspecs(false)
198+
end
199+
200+
if fields.force then
201+
beds.skip_night()
202+
update_formspecs(true)
203+
beds.kick_players()
204+
end
205+
end)

Diff for: ‎mods/beds/init.lua

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
beds = {}
2+
beds.player = {}
3+
beds.pos = {}
4+
beds.spawn = {}
5+
6+
beds.formspec = "size[8,15;true]"..
7+
"bgcolor[#080808BB; true]"..
8+
"button_exit[2,12;4,0.75;leave;Leave Bed]"
9+
10+
local modpath = minetest.get_modpath("beds")
11+
12+
-- load files
13+
dofile(modpath.."/functions.lua")
14+
dofile(modpath.."/api.lua")
15+
dofile(modpath.."/beds.lua")
16+
dofile(modpath.."/spawns.lua")

Diff for: ‎mods/beds/spawns.lua

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
local world_path = minetest.get_worldpath()
2+
local org_file = world_path .. "/beds_spawns"
3+
local file = world_path .. "/beds_spawns"
4+
local bkwd = false
5+
6+
-- check for PA's beds mod spawns
7+
local cf = io.open(world_path .. "/beds_player_spawns", "r")
8+
if cf ~= nil then
9+
io.close(cf)
10+
file = world_path .. "/beds_player_spawns"
11+
bkwd = true
12+
end
13+
14+
function beds.read_spawns()
15+
local spawns = beds.spawn
16+
local input = io.open(file, "r")
17+
if input and not bkwd then
18+
repeat
19+
local x = input:read("*n")
20+
if x == nil then
21+
break
22+
end
23+
local y = input:read("*n")
24+
local z = input:read("*n")
25+
local name = input:read("*l")
26+
spawns[name:sub(2)] = {x = x, y = y, z = z}
27+
until input:read(0) == nil
28+
io.close(input)
29+
elseif input and bkwd then
30+
beds.spawn = minetest.deserialize(input:read("*all"))
31+
input:close()
32+
beds.save_spawns()
33+
os.rename(file, file .. ".backup")
34+
file = org_file
35+
else
36+
spawns = {}
37+
end
38+
end
39+
40+
function beds.save_spawns()
41+
if not beds.spawn then
42+
return
43+
end
44+
writing = true
45+
local output = io.open(org_file, "w")
46+
for i, v in pairs(beds.spawn) do
47+
output:write(v.x.." "..v.y.." "..v.z.." "..i.."\n")
48+
end
49+
io.close(output)
50+
writing = false
51+
end
52+
53+
function beds.set_spawns()
54+
for name,_ in pairs(beds.player) do
55+
local player = minetest.get_player_by_name(name)
56+
local p = player:getpos()
57+
beds.spawn[name] = p
58+
end
59+
beds.save_spawns()
60+
end

Diff for: ‎mods/beds/textures/beds_bed.png

540 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_fancy.png

537 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_foot.png

390 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_head.png

387 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side1.png

296 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side2.png

316 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side_bottom.png

561 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side_bottom_r.png

537 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side_top.png

611 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_side_top_r.png

596 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_top1.png

583 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_top2.png

616 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_top_bottom.png

495 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_bed_top_top.png

556 Bytes
Loading

Diff for: ‎mods/beds/textures/beds_transparent.png

143 Bytes
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.