diff --git a/README.md b/README.md index 6529a37..41f2e1f 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,6 @@ Maintenance updates: * Storage blocks now drop their inventory when exploded * Made several strings translatable * Translation updates -* Add support for playerphysics mod * Add description to every setting * Add tooltip extensions for some interactive items (uses `tt` mod) * Add crafting guide support for `unified_inventory` mod (honey) diff --git a/handlers/animations.lua b/handlers/animations.lua index 0f06374..4479952 100644 --- a/handlers/animations.lua +++ b/handlers/animations.lua @@ -1,48 +1,76 @@ -local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil local mod_player_api = minetest.get_modpath("player_api") ~= nil +local sitting = {} +local seats_occupied = {} + local function top_face(pointed_thing) - if not pointed_thing then return end + if not pointed_thing then + return + end return pointed_thing.above.y > pointed_thing.under.y end +local function stand_up(player_name) + if not mod_player_api then + return + end + local player = minetest.get_player_by_name(player_name) + if not player then + return + end + player_api.player_attached[player_name] = false + + local old_anim = player_api.get_animation(player) + if old_anim and old_anim.animation == "sit" then + player_api.set_animation(player, "stand", 30) + end + + local hash = minetest.hash_node_position(sitting[player_name]) + seats_occupied[hash] = nil + sitting[player_name] = nil + + minetest.log("action", "[xdecor] "..player_name.." stands up at "..minetest.pos_to_string(player:get_pos(), 0)) +end + +--[[ Used when player interacts with "sittable" node to sit down +or stand up when interacting with that node again. Should +be used in `on_rightclick` handler +* `pos`: Position where to sit down player (MUST only use integers for coordinates!) +* `node`: Node table of node to sit on +* `clicker`: Player who interacted with node (from `on_rightclick`) +* `pointed_thing`: From `on_rightclick` ]] function xdecor.sit(pos, node, clicker, pointed_thing) - if not mod_player_api then return end - if not top_face(pointed_thing) then return end + if not mod_player_api then + return + end + -- Must click on top face to sit down + if not top_face(pointed_thing) then + return + end local player_name = clicker:get_player_name() local objs = minetest.get_objects_inside_radius(pos, 0.1) local vel = clicker:get_velocity() local ctrl = clicker:get_player_control() - for _, obj in pairs(objs) do - if obj:is_player() and obj:get_player_name() ~= player_name then - return - end - end + -- Stand up if sitting + if sitting[player_name] then + stand_up(player_name) - if player_api.player_attached[player_name] then - clicker:set_pos(pos) - if mod_playerphysics then - playerphysics.remove_physics_factor(clicker, "speed", "xdecor:sit_speed") - playerphysics.remove_physics_factor(clicker, "jump", "xdecor:sit_jump") - else - clicker:set_physics_override({speed = 1, jump = 1}) - end - player_api.player_attached[player_name] = false - player_api.set_animation(clicker, "stand", 30) - - elseif not player_api.player_attached[player_name] and node.param2 <= 3 and + -- Sit down if not sitting and not attached + elseif not sitting[player_name] and not player_api.player_attached[player_name] and node.param2 <= 3 and not ctrl.sneak and vector.equals(vel, vector.new()) then - if mod_playerphysics then - playerphysics.add_physics_factor(clicker, "speed", "xdecor:sit_speed", 0) - playerphysics.add_physics_factor(clicker, "jump", "xdecor:sit_jump", 0) - else - clicker:set_physics_override({speed = 0, jump = 0}) + -- Can't sit down on note already occupied by player + local hash = minetest.hash_node_position(pos) + if seats_occupied[hash] then + return end - clicker:set_pos(pos) + player_api.player_attached[player_name] = true player_api.set_animation(clicker, "sit", 30) + sitting[player_name] = table.copy(pos) + seats_occupied[hash] = true + clicker:set_pos(pos) if node.param2 == 0 then clicker:set_look_horizontal(0) @@ -53,19 +81,61 @@ function xdecor.sit(pos, node, clicker, pointed_thing) elseif node.param2 == 3 then clicker:set_look_horizontal(math.pi/2) end + + minetest.log("action", "[xdecor] "..player_name.." sits down at "..minetest.pos_to_string(pos, 0)) end end +-- Called when `digger` (a player object) wants to +-- dig a node at pos. Returns true if it's allowed, +-- false otherwise. This checks if the node at pos +-- is an occupied sittable node. +-- Can be used for the `can_dig` node function. function xdecor.sit_dig(pos, digger) if not mod_player_api then return true end - for _, player in pairs(minetest.get_objects_inside_radius(pos, 0.1)) do - if player:is_player() and - player_api.player_attached[player:get_player_name()] then - return false - end + local hash = minetest.hash_node_position(pos) + if seats_occupied[hash] then + return false end return true end + +-- Automatically cause players to stand up if they pressed a control +-- or moved away from the seat +minetest.register_globalstep(function(dtime) + local to_stand_up = {} + for player_name, sitting_pos in pairs(sitting) do + local player = minetest.get_player_by_name(player_name) + if player then + local ctrl = player:get_player_control() + if ctrl.up or ctrl.down or ctrl.left or ctrl.right or ctrl.sneak or ctrl.jump then + table.insert(to_stand_up, player_name) + elseif vector.distance(player:get_pos(), sitting_pos) > 0.55 then + table.insert(to_stand_up, player_name) + end + end + end + for s=1, #to_stand_up do + stand_up(to_stand_up[s]) + end +end) + +-- Force player to stand on death (to the seat is released) +minetest.register_on_dieplayer(function(player) + local player_name = player:get_player_name() + if sitting[player_name] then + stand_up(player_name) + end +end) + +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + if sitting[player_name] then + local hash = minetest.hash_node_position(sitting[player_name]) + seats_occupied[hash] = nil + sitting[player_name] = nil + end +end) diff --git a/mod.conf b/mod.conf index c5f3d66..c9d90c7 100644 --- a/mod.conf +++ b/mod.conf @@ -2,5 +2,5 @@ name = xdecor title = X-Decor-libre description = A libre decoration mod meant to be simple and well-featured. depends = default, bucket, doors, farming, stairs, xpanes -optional_depends = playerphysics, player_api, fire, moreblocks, mesecons, unified_inventory, tt +optional_depends = player_api, fire, moreblocks, mesecons, unified_inventory, tt min_minetest_version = 5.7.0