This commit is contained in:
BlockMen 2015-02-24 11:59:15 +01:00
parent 3b526a7276
commit edb02e9d33
24 changed files with 564 additions and 0 deletions

@ -24,6 +24,42 @@ The bucket API allows registering new types of buckets for non-default liquids.
"Lava Bucket" -- Bucket description
)
Beds API
--------
beds.register_bed(
"beds:bed", -- Bed name
def: See [#Bed definition] -- Bed definition
)
beds.read_spawns() -- returns a table containing players respawn positions
beds.kick_players() -- forces all players to leave bed
beds.skip_night() -- sets world time to morning and saves respawn position of all players currently sleeping
#Bed definition
---------------
{
description = "Simple Bed",
inventory_image = "beds_bed.png",
wield_image = "beds_bed.png",
tiles = {
bottom = {[Tile definition],
^ the tiles of the bottom part of the bed
},
top = {[Tile definition],
^ the tiles of the bottom part of the bed
}
},
nodebox = {
bottom = regular nodebox, see [Node boxes], -- bottm part of bed
top = regular nodebox, see [Node boxes], -- top part of bed
},
selectionbox = regular nodebox, see [Node boxes], -- for both nodeboxes
recipe = { -- Craft recipe
{"group:wool", "group:wool", "group:wool"},
{"group:wood", "group:wood", "group:wood"}
}
}
Doors API
---------
The doors mod allows modders to register custom doors and trapdoors.

18
mods/beds/Changelog.txt Normal file

@ -0,0 +1,18 @@
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

45
mods/beds/README.txt Normal file

@ -0,0 +1,45 @@
Minetest mod "Beds"
===================
by BlockMen (c) 2014-2015
Version: 1.1.1
About
~~~~~
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 imideatly. If playing on server you get shown how many other
players are in bed too. If all players are sleeping the night gets skipped aswell. Also 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 controled respawning. If you have slept in bed (not just lying in it) your respawn point
is set to the beds location. If dying you will respawn there.
You can craft two types of beds:
Simple shaped bed:
wool wool wool
wood wood wood
Fancy shaped bed:
wool wool stick
wood wood wood
Notice: You can use any color of wood or wool, mixing different is also possible.
License of source code, textures: WTFPL
---------------------------------------
(c) Copyright BlockMen (2014-2015)
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.

78
mods/beds/api.lua Normal file

@ -0,0 +1,78 @@
function beds.register_bed(name, def)
minetest.register_node(name .. "_bottom", {
description = def.description,
inventory_image = def.inventory_image,
wield_image = def.wield_image,
drawtype = "nodebox",
tiles = def.tiles.bottom,
paramtype = "light",
paramtype2 = "facedir",
stack_max = 1,
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
sounds = default.node_sound_wood_defaults(),
node_box = {
type = "fixed",
fixed = def.nodebox.bottom,
},
selection_box = {
type = "fixed",
fixed = def.selectionbox,
},
after_place_node = function(pos, placer, itemstack)
local n = minetest.get_node_or_nil(pos)
if not n or not n.param2 then
minetest.remove_node(pos)
return true
end
local dir = minetest.facedir_to_dir(n.param2)
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
local n2 = minetest.get_node_or_nil(p)
local def = minetest.registered_items[n2.name] or nil
if not n2 or not def or not def.buildable_to then
minetest.remove_node(pos)
return true
end
minetest.set_node(p, {name = n.name:gsub("%_bottom", "_top"), param2 = n.param2})
return false
end,
on_destruct = function(pos)
local n = minetest.get_node_or_nil(pos)
if not n then return end
local dir = minetest.facedir_to_dir(n.param2)
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
local n2 = minetest.get_node(p)
if minetest.get_item_group(n2.name, "bed") == 2 and n.param2 == n2.param2 then
minetest.remove_node(p)
end
end,
on_rightclick = function(pos, node, clicker)
beds.on_rightclick(pos, clicker)
end,
})
minetest.register_node(name .. "_top", {
drawtype = "nodebox",
tiles = def.tiles.top,
paramtype = "light",
paramtype2 = "facedir",
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
sounds = default.node_sound_wood_defaults(),
node_box = {
type = "fixed",
fixed = def.nodebox.top,
},
selection_box = {
type = "fixed",
fixed = {0, 0, 0, 0, 0, 0},
},
})
minetest.register_alias(name, name .. "_bottom")
-- register recipe
minetest.register_craft({
output = name,
recipe = def.recipe
})
end

104
mods/beds/beds.lua Normal file

@ -0,0 +1,104 @@
-- fancy shaped bed
beds.register_bed("beds:fancy_bed", {
description = "Fancy Bed",
inventory_image = "beds_bed_fancy.png",
wield_image = "beds_bed_fancy.png",
tiles = {
bottom = {
"beds_bed_top1.png",
"default_wood.png",
"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 = {
{"group:wool", "group:wool", "group:stick"},
{"group:wood", "group:wood", "group:wood"},
},
})
-- simple shaped bed
beds.register_bed("beds:bed", {
description = "Simple Bed",
inventory_image = "beds_bed.png",
wield_image = "beds_bed.png",
tiles = {
bottom = {
"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},
recipe = {
{"group:wool", "group:wool", "group:wool"},
{"group:wood", "group:wood", "group:wood"}
},
})
-- aliases for PA's beds mod
minetest.register_alias("beds:bed_bottom_red", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_orange", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_yellow", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_green", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_blue", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_violet", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_black", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_grey", "beds:bed_bottom")
minetest.register_alias("beds:bed_bottom_white", "beds:bed_bottom")
minetest.register_alias("beds:bed_top_red", "beds:bed_top")
minetest.register_alias("beds:bed_top_orange", "beds:bed_top")
minetest.register_alias("beds:bed_top_yellow", "beds:bed_top")
minetest.register_alias("beds:bed_top_green", "beds:bed_top")
minetest.register_alias("beds:bed_top_blue", "beds:bed_top")
minetest.register_alias("beds:bed_top_violet", "beds:bed_top")
minetest.register_alias("beds:bed_top_black", "beds:bed_top")
minetest.register_alias("beds:bed_top_grey", "beds:bed_top")
minetest.register_alias("beds:bed_top_white", "beds:bed_top")

2
mods/beds/depends.txt Normal file

@ -0,0 +1,2 @@
default
wool

205
mods/beds/functions.lua Normal file

@ -0,0 +1,205 @@
local player_in_bed = 0
local is_sp = minetest.is_singleplayer()
-- helper functions
local function get_look_yaw(pos)
local n = minetest.get_node(pos)
if n.param2 == 1 then
return 7.9, n.param2
elseif n.param2 == 3 then
return 4.75, n.param2
elseif n.param2 == 0 then
return 3.15, n.param2
else
return 6.28, n.param2
end
end
local function check_in_beds(players)
local in_bed = beds.player
if not players then
players = minetest.get_connected_players()
end
for n, player in ipairs(players) do
local name = player:get_player_name()
if not in_bed[name] then
return false
end
end
return true
end
local function lay_down(player, pos, bed_pos, state, skip)
local name = player:get_player_name()
local hud_flags = player:hud_get_flags()
if not player or not name then
return
end
-- stand up
if state ~= nil and not state then
local p = beds.pos[name] or nil
if beds.player[name] ~= nil then
beds.player[name] = nil
player_in_bed = player_in_bed - 1
end
-- skip here to prevent sending player specific changes (used for leaving players)
if skip then
return
end
if p then
player:setpos(p)
end
-- physics, eye_offset, etc
player:set_eye_offset({x=0,y=0,z=0}, {x=0,y=0,z=0})
player:set_look_yaw(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
else
beds.player[name] = 1
beds.pos[name] = pos
player_in_bed = player_in_bed + 1
-- physics, eye_offset, etc
player:set_eye_offset({x=0,y=-13,z=0}, {x=0,y=0,z=0})
local yaw, param2 = get_look_yaw(bed_pos)
player:set_look_yaw(yaw)
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)
player:setpos(p)
default.player_attached[name] = true
hud_flags.wielditem = false
default.player_set_animation(player, "lay" , 0)
end
player:hud_set_flags(hud_flags)
end
local function update_formspecs(finished)
local ges = #minetest.get_connected_players()
local form_n = ""
local is_majority = (ges/2) < player_in_bed
if finished then
form_n = beds.formspec ..
"label[2.7,11; Good morning.]"
else
form_n = beds.formspec ..
"label[2.2,11;"..tostring(player_in_bed).." of "..tostring(ges).." players are in bed]"
if is_majority then
form_n = form_n ..
"button_exit[2,8;4,0.75;force;Force night skip]"
end
end
for name,_ in pairs(beds.player) do
minetest.show_formspec(name, "beds_form", form_n)
end
end
-- public functions
function beds.kick_players()
for name,_ in pairs(beds.player) do
local player = minetest.get_player_by_name(name)
lay_down(player, nil, nil, false)
end
end
function beds.skip_night()
minetest.set_timeofday(0.23)
beds.set_spawns()
end
function beds.on_rightclick(pos, player)
local name = player:get_player_name()
local ppos = player:getpos()
local tod = minetest.get_timeofday()
if tod > 0.2 and tod < 0.805 then
if beds.player[name] then
lay_down(player, nil, nil, false)
end
minetest.chat_send_player(name, "You can only sleep at night.")
return
end
-- move to bed
if not beds.player[name] then
lay_down(player, ppos, pos)
else
lay_down(player, nil, nil, false)
end
if not is_sp then
update_formspecs(false)
end
-- skip the night and let all players stand up
if check_in_beds() then
minetest.after(2, function()
beds.skip_night()
if not is_sp then
update_formspecs(true)
end
beds.kick_players()
end)
end
end
-- callbacks
minetest.register_on_joinplayer(function(player)
beds.read_spawns()
end)
minetest.register_on_respawnplayer(function(player)
local name = player:get_player_name()
local pos = beds.spawn[name] or nil
if pos then
player:setpos(pos)
return true
end
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
lay_down(player, nil, nil, false, true)
beds.player[name] = nil
if check_in_beds() then
minetest.after(2, function()
beds.skip_night()
update_formspecs(true)
beds.kick_players()
end)
end
end)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "beds_form" then
return
end
if fields.quit or fields.leave then
lay_down(player, nil, nil, false)
update_formspecs(false)
end
if fields.force then
beds.skip_night()
update_formspecs(true)
beds.kick_players()
end
end)

16
mods/beds/init.lua Normal file

@ -0,0 +1,16 @@
beds = {}
beds.player = {}
beds.pos = {}
beds.spawn = {}
beds.formspec = "size[8,15;true]"..
"bgcolor[#080808BB; true]"..
"button_exit[2,12;4,0.75;leave;Leave Bed]"
local modpath = minetest.get_modpath("beds")
-- load files
dofile(modpath.."/functions.lua")
dofile(modpath.."/api.lua")
dofile(modpath.."/beds.lua")
dofile(modpath.."/spawns.lua")

60
mods/beds/spawns.lua Normal file

@ -0,0 +1,60 @@
local world_path = minetest.get_worldpath()
local org_file = world_path .. "/beds_spawns"
local file = world_path .. "/beds_spawns"
local bkwd = false
-- check for PA's beds mod spawns
local cf = io.open(world_path .. "/beds_player_spawns", "r")
if cf ~= nil then
io.close(cf)
file = world_path .. "/beds_player_spawns"
bkwd = true
end
function beds.read_spawns()
local spawns = beds.spawn
local input = io.open(file, "r")
if input and not bkwd then
repeat
local x = input:read("*n")
if x == nil then
break
end
local y = input:read("*n")
local z = input:read("*n")
local name = input:read("*l")
spawns[name:sub(2)] = {x = x, y = y, z = z}
until input:read(0) == nil
io.close(input)
elseif input and bkwd then
beds.spawn = minetest.deserialize(input:read("*all"))
input:close()
beds.save_spawns()
os.rename(file, file .. ".backup")
file = org_file
else
spawns = {}
end
end
function beds.save_spawns()
if not beds.spawn then
return
end
writing = true
local output = io.open(org_file, "w")
for i, v in pairs(beds.spawn) do
output:write(v.x.." "..v.y.." "..v.z.." "..i.."\n")
end
io.close(output)
writing = false
end
function beds.set_spawns()
for name,_ in pairs(beds.player) do
local player = minetest.get_player_by_name(name)
local p = player:getpos()
beds.spawn[name] = p
end
beds.save_spawns()
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B