functions.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. local pi = math.pi
  2. local player_in_bed = 0
  3. local is_sp = minetest.is_singleplayer()
  4. local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
  5. if enable_respawn == nil then
  6. enable_respawn = true
  7. end
  8. -- Helper functions
  9. local function get_look_yaw(pos)
  10. local rotation = minetest.get_node(pos).param2
  11. if rotation > 3 then
  12. rotation = rotation % 4 -- Mask colorfacedir values
  13. end
  14. if rotation == 1 then
  15. return pi / 2, rotation
  16. elseif rotation == 3 then
  17. return -pi / 2, rotation
  18. elseif rotation == 0 then
  19. return pi, rotation
  20. else
  21. return 0, rotation
  22. end
  23. end
  24. local function is_night_skip_enabled()
  25. local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip")
  26. if enable_night_skip == nil then
  27. enable_night_skip = true
  28. end
  29. return enable_night_skip
  30. end
  31. local function check_in_beds(players)
  32. local in_bed = beds.player
  33. if not players then
  34. players = minetest.get_connected_players()
  35. end
  36. for n, player in ipairs(players) do
  37. local name = player:get_player_name()
  38. if not in_bed[name] then
  39. return false
  40. end
  41. end
  42. return #players > 0
  43. end
  44. local function lay_down(player, pos, bed_pos, state, skip)
  45. local name = player:get_player_name()
  46. local hud_flags = player:hud_get_flags()
  47. if not player or not name then
  48. return
  49. end
  50. -- stand up
  51. if state ~= nil and not state then
  52. local p = beds.pos[name] or nil
  53. if beds.player[name] ~= nil then
  54. beds.player[name] = nil
  55. beds.bed_position[name] = nil
  56. player_in_bed = player_in_bed - 1
  57. end
  58. -- skip here to prevent sending player specific changes (used for leaving players)
  59. if skip then
  60. return
  61. end
  62. if p then
  63. player:set_pos(p)
  64. end
  65. -- physics, eye_offset, etc
  66. player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
  67. default.player_attached[name] = false
  68. player:set_physics_override(1, 1, 1)
  69. hud_flags.wielditem = true
  70. player_api.set_animation(player, "stand" , 30)
  71. -- lay down
  72. else
  73. beds.player[name] = 1
  74. beds.pos[name] = pos
  75. beds.bed_position[name] = bed_pos
  76. player_in_bed = player_in_bed + 1
  77. -- physics, eye_offset, etc
  78. player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
  79. local yaw, param2 = get_look_yaw(bed_pos)
  80. player:set_look_horizontal(yaw)
  81. local dir = minetest.facedir_to_dir(param2)
  82. local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2}
  83. player:set_physics_override(0, 0, 0)
  84. player:set_pos(p)
  85. default.player_attached[name] = true
  86. hud_flags.wielditem = false
  87. player_api.set_animation(player, "lay" , 0)
  88. end
  89. player:hud_set_flags(hud_flags)
  90. end
  91. -- Public functions
  92. function beds.kick_players()
  93. for name, _ in pairs(beds.player) do
  94. local player = minetest.get_player_by_name(name)
  95. lay_down(player, nil, nil, false)
  96. end
  97. end
  98. function beds.skip_night()
  99. minetest.set_timeofday(0.23)
  100. end
  101. function beds.on_rightclick(pos, player)
  102. local name = player:get_player_name()
  103. local ppos = player:get_pos()
  104. local tod = minetest.get_timeofday()
  105. -- move to bed
  106. if not beds.player[name] then
  107. lay_down(player, ppos, pos)
  108. beds.set_spawns() -- save respawn positions when entering bed
  109. else
  110. lay_down(player, nil, nil, false)
  111. end
  112. -- skip the night and let all players stand up
  113. if tod > 0.8 or tod < 0.2 then
  114. if check_in_beds() then
  115. minetest.after(2, function()
  116. if is_night_skip_enabled() then
  117. beds.skip_night()
  118. beds.kick_players()
  119. end
  120. end)
  121. end
  122. end
  123. end
  124. function beds.can_dig(bed_pos)
  125. -- Check all players in bed which one is at the expected position
  126. for _, player_bed_pos in pairs(beds.bed_position) do
  127. if vector.equals(bed_pos, player_bed_pos) then
  128. return false
  129. end
  130. end
  131. return true
  132. end
  133. -- Callbacks
  134. -- Only register respawn callback if respawn enabled
  135. if enable_respawn then
  136. -- respawn player at bed if enabled and valid position is found
  137. minetest.register_on_respawnplayer(function(player)
  138. local name = player:get_player_name()
  139. local pos = beds.spawn[name]
  140. if pos then
  141. player:set_pos(pos)
  142. return true
  143. end
  144. end)
  145. end
  146. minetest.register_on_leaveplayer(function(player)
  147. local name = player:get_player_name()
  148. lay_down(player, nil, nil, false, true)
  149. beds.player[name] = nil
  150. if check_in_beds() then
  151. minetest.after(2, function()
  152. if is_night_skip_enabled() then
  153. beds.skip_night()
  154. beds.kick_players()
  155. end
  156. end)
  157. end
  158. end)