mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2025-03-11 06:07:44 +01:00
Integrate mcl_cozy
: add the ability to sit and lay on blocks
This commit is contained in:
parent
03f46eceda
commit
33000e5f8c
12 changed files with 450 additions and 0 deletions
53
mods/PLAYER/mcl_cozy/.luacheckrc
Normal file
53
mods/PLAYER/mcl_cozy/.luacheckrc
Normal file
|
@ -0,0 +1,53 @@
|
|||
unused_args = false
|
||||
allow_defined_top = true
|
||||
|
||||
globals = {
|
||||
"mcl_player"
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
"core",
|
||||
"mcl_tmp_message",
|
||||
|
||||
string = {fields = {"split"}},
|
||||
table = {fields = {"copy", "getn"}},
|
||||
-- My mod
|
||||
"mcl_cozy",
|
||||
|
||||
-- Builtin
|
||||
"vector", "ItemStack",
|
||||
"dump", "DIR_DELIM", "VoxelArea", "Settings",
|
||||
|
||||
-- MTG
|
||||
"default", "sfinv", "creative",
|
||||
|
||||
-- Mineclone
|
||||
"mcl_loot", "tga_encoder", "mcl_util", "flowlib", "mcl_sounds", "mcl_autogroup",
|
||||
"mcl_events", "biomeinfo", "mcl_damage", "mcl_particles", "mcl_worlds", "mcl_colors",
|
||||
"mcl_explosions", "mcl_vars", "controls", "walkover", "mcl_meshhand", "mcl_fovapi",
|
||||
"playerphysics", "mcl_hunger", "mcl_death_drop", "mcl_playerplus",
|
||||
"mcl_gamemode", "mcl_spawn", "mcl_skins", "mcl_sprint", "mcl_playerinfo",
|
||||
"mcl_item_id", "tt", "mcl_craftguide", "doc", "mcl_dripping",
|
||||
"mcl_entity_invs", "mcl_item_entity", "mcl_burning",
|
||||
"mcl_minecarts", "pillager", "mobs_mc", "sounds",
|
||||
"textures", "mcl_mobs", "mcl_paintings",
|
||||
"mcl_grindstone", "mcl_walls", "mcl_bamboo",
|
||||
"mcl_maps", "mcl_clock", "mcl_end", "mcl_starting_inventory",
|
||||
"mcl_bows", "mcl_bows_s", "mcl_dye", "mcl_copper",
|
||||
"mcl_flowerpots", "mcl_furnaces", "mcl_farming",
|
||||
"mcl_campfires", "mcl_crafting_table", "mcl_doors",
|
||||
"mcl_jukebox", "screwdriver", "mcl_itemframes",
|
||||
"mcl_heads", "mcl_beacons", "xpanes", "mcl_enchanting",
|
||||
"mcl_beds", "mcl_throwing", "mcl_banners", "mcl_mobspawners",
|
||||
"mcl_cocoas", "mcl_smithing_table", "mcl_flowers",
|
||||
"mcl_core", "mcl_torches", "mcl_target", "mesecon", "mcl_observers",
|
||||
"mcl_sculk", "mcl_armor", "mcl_lanterns", "mcl_stairs", "mcl_bells",
|
||||
"mcl_hamburger", "mcl_signs", "mcl_honey", "mcl_stonecutter", "mcl_fire",
|
||||
"mcl_compass", "mcl_ocean", "mcl_fences", "mcl_buckets", "mcl_potions",
|
||||
"tnt", "mcl_cherry_blossom", "mcl_portals", "mcl_chests", "mcl_shields",
|
||||
"mcl_wip", "mcl_raids", "mcl_moon", "lightning", "mcl_weather",
|
||||
"mcl_formspec", "mcl_death_messages", "mcl_bossbars", "awards",
|
||||
"mcl_inventory", "mcl_title", "mcl_offhand", "hb", "mcl_experience",
|
||||
"mcl_info", "mcl_credits", "tsm_railcorridors", "mcl_mapgen_core",
|
||||
"mcl_structures", "settlements", "mcl_dungeons", "mcl_colors_official"
|
||||
}
|
65
mods/PLAYER/mcl_cozy/API.md
Normal file
65
mods/PLAYER/mcl_cozy/API.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
# VoxeLibre Get Comfortable API
|
||||
|
||||
## Actions
|
||||
|
||||
The mod provides 2 types of player actions: `"sit"` and `"lay"`. Both attach
|
||||
players to blocks, but show different animations. Whenever there's a mention
|
||||
of `action`, it means that it has to either be `"sit"` or `"lay"`.
|
||||
|
||||
There is currently no way to register new actions.
|
||||
|
||||
## `function mcl_cozy[action](pos, _, player)`
|
||||
|
||||
A function provided for every action that applies the action to `player`.
|
||||
If `pos` is nil, the player will be mounted to their current position.
|
||||
|
||||
```lua
|
||||
core.register_node("mymod:sit_on_me", {
|
||||
description = "Sit on me!",
|
||||
-- ...
|
||||
on_rightclick = mcl_cozy.sit
|
||||
})
|
||||
```
|
||||
|
||||
## `function mcl_cozy.stand_up(player)`
|
||||
|
||||
Stands `player` up, unmounting them, resetting their eye offset and setting
|
||||
their animation back to standing.
|
||||
|
||||
## `function mcl_cozy.print_action(name, action)`
|
||||
|
||||
Outputs the `action` of `name`, if the corresponding setting is enabled.
|
||||
|
||||
```
|
||||
<coolguy> I'm sleepy
|
||||
* coolguy lies
|
||||
<coolguy> Zzz
|
||||
```
|
||||
|
||||
## `function mcl_cozy.actionbar_show_status(player, message)`
|
||||
|
||||
Shows `message` on the actionbar of `player`. If `message` is nil, it defaults
|
||||
to `S("Move to stand up")`.
|
||||
|
||||
Historically, this wrapper was needed because Mineclonia had `mcl_tmp_message`
|
||||
instead of `mcl_title`. Nowadays, it exists purely for convenience and
|
||||
simplicity.
|
||||
|
||||
## `def._mcl_cozy_offset = vector.new(x, y, z)`
|
||||
|
||||
It is possible to offset the body point for a player to be mounted to. Usually,
|
||||
this is a vector with very small values, just enough to make the player feel
|
||||
comfortable.
|
||||
|
||||
* `+x` and `-x` move the player left and right
|
||||
* `+y` and `-y` move the player up and down
|
||||
* `+z` and `-z` move the player front and back
|
||||
|
||||
```lua
|
||||
core.register_node("mymod:lay_on_me", {
|
||||
description = "Lay on me!",
|
||||
on_rightclick = mcl_cozy.lay,
|
||||
-- ...
|
||||
_mcl_cozy_offset = vector.new(0, 0.1, -0.2) -- a bit higher and to the back
|
||||
})
|
||||
```
|
10
mods/PLAYER/mcl_cozy/LICENSE
Normal file
10
mods/PLAYER/mcl_cozy/LICENSE
Normal file
|
@ -0,0 +1,10 @@
|
|||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
21
mods/PLAYER/mcl_cozy/README.md
Normal file
21
mods/PLAYER/mcl_cozy/README.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# VoxeLibre Get Comfortable
|
||||
|
||||
Adds commands to /lay or /sit to VoxeLibre (ex. MineClone2), as well as the
|
||||
ability to sit on some blocks (stairs and slabs out-of-the-box) by
|
||||
right-clicking them.
|
||||
|
||||
Port of the good old [cozy mod](https://forum.luanti.org/viewtopic.php?t=14143)
|
||||
(originally made for MTG by everamzah) to work with VL properly and even
|
||||
provide some nice new features!
|
||||
|
||||
|
||||
## License
|
||||
|
||||
The source code is licensed under 0BSD ("public domain"). See `LICENSE` file
|
||||
for details.
|
||||
|
||||
|
||||
## API
|
||||
|
||||
This mod provides its own APIs for other mods to use. See [`API.md`](API.md)
|
||||
for details.
|
233
mods/PLAYER/mcl_cozy/init.lua
Normal file
233
mods/PLAYER/mcl_cozy/init.lua
Normal file
|
@ -0,0 +1,233 @@
|
|||
local S = core.get_translator(core.get_current_modname())
|
||||
local mcl_cozy_sit_on_stairs = core.settings:get_bool("mcl_cozy_sit_on_stairs", true)
|
||||
local mcl_cozy_print_actions = core.settings:get_bool("mcl_cozy_print_actions", false)
|
||||
|
||||
local SIT_EYE_OFFSET = vector.new(0, -7, 2)
|
||||
local LAY_EYE_OFFSET = vector.new(0, -13, -5)
|
||||
|
||||
local DISTANCE_THRESHOLD = 3
|
||||
local VELOCITY_THRESHOLD = 0.125
|
||||
local PLAYERSP_THRESHOLD = 0.1
|
||||
|
||||
-- used to partially avoid a race condition(?) causing the player animation to not be set properly when mounting onto
|
||||
-- a block (e.g. stair)
|
||||
local ACTION_APPLY_DELAY = 0.05
|
||||
|
||||
mcl_cozy = {}
|
||||
mcl_cozy.pos = {}
|
||||
|
||||
-- TODO: when the API is more polished and there is demand, un-internalize this
|
||||
local actions = {
|
||||
["sit"] = {
|
||||
description = S("Sit down"),
|
||||
message = {
|
||||
chat = "@1 sits",
|
||||
actionbar = {
|
||||
distance_fail = S("You can't sit, the block's too far away!"),
|
||||
movement_fail = S("You have to stop moving before sitting down!"),
|
||||
},
|
||||
},
|
||||
eye_offset = {SIT_EYE_OFFSET, SIT_EYE_OFFSET},
|
||||
on_apply = function(player)
|
||||
mcl_player.player_set_animation(player, "sit", 30)
|
||||
end,
|
||||
},
|
||||
["lay"] = {
|
||||
description = S("Lie down"),
|
||||
message = {
|
||||
chat = "@1 lies",
|
||||
actionbar = {
|
||||
distance_fail = S("You can't lay, the block's too far away!"),
|
||||
movement_fail = S("You have to stop moving before lying down!"),
|
||||
},
|
||||
},
|
||||
eye_offset = {LAY_EYE_OFFSET, LAY_EYE_OFFSET},
|
||||
on_apply = function(player)
|
||||
mcl_player.player_set_animation(player, "lay", 30)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local function is_attached(player)
|
||||
return mcl_player.player_attached[player:get_player_name()]
|
||||
end
|
||||
local function set_attach(player, bool)
|
||||
mcl_player.player_attached[player:get_player_name()] = bool
|
||||
end
|
||||
local function is_air_below(player)
|
||||
return mcl_playerinfo[player:get_player_name()].node_stand == "air"
|
||||
end
|
||||
--[[if mcl_player.players then
|
||||
is_attached = function(player)
|
||||
return mcl_player.players[player].attached
|
||||
end
|
||||
set_attach = function(player, bool)
|
||||
mcl_player.players[player].attached = bool
|
||||
end
|
||||
is_air_below = function(player)
|
||||
return mcl_player.players[player].nodes.stand == "air"
|
||||
end
|
||||
end]]
|
||||
|
||||
function mcl_cozy.print_action(name, action)
|
||||
if not mcl_cozy_print_actions then return end
|
||||
|
||||
local msg = "@1 stands up"
|
||||
if actions[action] then
|
||||
msg = actions[action].message.chat
|
||||
end
|
||||
core.chat_send_all("* "..S(msg, name))
|
||||
end
|
||||
|
||||
function mcl_cozy.actionbar_show_status(player, message)
|
||||
if not message then message = S("Move to stand up") end
|
||||
|
||||
mcl_title.set(player, "actionbar", {text=message, color="white", stay=60})
|
||||
end
|
||||
|
||||
function mcl_cozy.stand_up(player)
|
||||
local name = player:get_player_name()
|
||||
|
||||
player:set_eye_offset(vector.zero(), vector.zero())
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_cozy:attached")
|
||||
playerphysics.remove_physics_factor(player, "jump", "mcl_cozy:attached")
|
||||
set_attach(player, false)
|
||||
mcl_player.player_set_animation(player, "stand", 30)
|
||||
mcl_cozy.pos[name] = nil
|
||||
mcl_cozy.print_action(name, "stand")
|
||||
end
|
||||
|
||||
-- register actions
|
||||
for action, def in pairs(actions) do
|
||||
if not def or type(def) ~= "table" then return end
|
||||
|
||||
mcl_cozy[action] = function(pos, _, player)
|
||||
if not player or not player:is_player() then return end
|
||||
|
||||
local name = player:get_player_name()
|
||||
local ppos = player:get_pos()
|
||||
|
||||
-- check attachment
|
||||
if is_attached(player) then
|
||||
mcl_cozy.pos[name] = nil
|
||||
mcl_cozy.stand_up(player)
|
||||
return
|
||||
end
|
||||
|
||||
local delay = 0
|
||||
if pos then
|
||||
-- check distance
|
||||
if vector.distance(pos, ppos) > DISTANCE_THRESHOLD then
|
||||
mcl_cozy.actionbar_show_status(player, def.message.actionbar.distance_fail)
|
||||
return
|
||||
end
|
||||
-- check movement
|
||||
if vector.length(player:get_velocity()) > VELOCITY_THRESHOLD then
|
||||
mcl_cozy.actionbar_show_status(player, def.message.actionbar.movement_fail)
|
||||
return
|
||||
end
|
||||
-- check if occupied
|
||||
for _, other_pos in pairs(mcl_cozy.pos) do
|
||||
if vector.distance(pos, other_pos) < PLAYERSP_THRESHOLD then
|
||||
mcl_cozy.actionbar_show_status(player,
|
||||
def.message.actionbar.occupancy_fail or S("This block is already occupied!"))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- all checks pass
|
||||
local node = core.get_node(pos)
|
||||
local param2 = node.param2
|
||||
local ndef = core.registered_nodes[node.name]
|
||||
|
||||
local rot
|
||||
if ndef.paramtype2:find("dir") then
|
||||
local dir = core.facedir_to_dir(param2)
|
||||
rot = vector.dir_to_rotation(dir)
|
||||
|
||||
-- set player's yaw to match the direction of the block they mount onto
|
||||
local yaw = rot.y
|
||||
if param2 % 2 == 0 then
|
||||
yaw = -yaw
|
||||
end
|
||||
if yaw == 0 then
|
||||
yaw = -math.pi
|
||||
elseif yaw == math.pi then
|
||||
yaw = 0
|
||||
end
|
||||
player:set_look_horizontal(-yaw)
|
||||
else
|
||||
rot = vector.zero()
|
||||
end
|
||||
|
||||
if ndef._mcl_cozy_offset then -- account for the body point offset
|
||||
local off = ndef._mcl_cozy_offset
|
||||
pos = pos + vector.rotate(off, rot)
|
||||
end
|
||||
|
||||
delay = ACTION_APPLY_DELAY
|
||||
|
||||
player:move_to(pos)
|
||||
else
|
||||
pos = ppos
|
||||
end
|
||||
|
||||
player:set_eye_offset(unpack(def.eye_offset))
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_cozy:attached", 0)
|
||||
playerphysics.add_physics_factor(player, "jump", "mcl_cozy:attached", 0)
|
||||
|
||||
set_attach(player, true)
|
||||
mcl_cozy.pos[name] = pos
|
||||
|
||||
core.after(delay, function()
|
||||
if player then
|
||||
def.on_apply(player)
|
||||
end
|
||||
end)
|
||||
|
||||
mcl_cozy.print_action(name, action)
|
||||
mcl_cozy.actionbar_show_status(player)
|
||||
end
|
||||
|
||||
core.register_chatcommand(action, {
|
||||
description = def.description,
|
||||
func = function(name)
|
||||
local player = core.get_player_by_name(name)
|
||||
-- check the node below player (and if it's air, just don't sit)
|
||||
if is_air_below(player) then return end
|
||||
|
||||
mcl_cozy[action](nil, nil, player)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
core.register_globalstep(function(dtime)
|
||||
for _, player in ipairs(core.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local ctrl = player:get_player_control()
|
||||
|
||||
if mcl_cozy.pos[name] then
|
||||
-- unmount when player tries to move
|
||||
if (ctrl.up == true or ctrl.down == true or
|
||||
ctrl.left == true or ctrl.right == true or
|
||||
ctrl.jump == true or ctrl.sneak == true) then
|
||||
mcl_cozy.stand_up(player)
|
||||
-- check the node below player (and if it's air, just unmount)
|
||||
elseif is_air_below(player) then
|
||||
mcl_cozy.stand_up(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- fix players getting stuck after they leave while still sitting
|
||||
core.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_cozy:attached")
|
||||
playerphysics.remove_physics_factor(player, "jump", "mcl_cozy:attached")
|
||||
mcl_cozy.pos[name] = nil
|
||||
end)
|
||||
|
||||
if core.get_modpath("mcl_stairs") and mcl_cozy_sit_on_stairs then
|
||||
dofile(core.get_modpath("mcl_cozy") .. "/stairs_slabs.lua")
|
||||
end
|
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.fr.tr
Normal file
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.fr.tr
Normal file
|
@ -0,0 +1,8 @@
|
|||
# textdomain: mcl_cozy
|
||||
Sit down=S'assoir
|
||||
Lay down=Se coucher
|
||||
Move to stand up=Se déplacer pour se lever
|
||||
This spot is already occupied!=Cette place est déjà occupée !
|
||||
@1 sits=@1 s'assoit
|
||||
@1 lies=@1 se couche
|
||||
@1 stands up=@1 se lève
|
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.pl.tr
Normal file
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.pl.tr
Normal file
|
@ -0,0 +1,8 @@
|
|||
# textdomain: mcl_cozy
|
||||
Sit down=Usiądź
|
||||
Lay down=Połóź się
|
||||
Move to stand up=Porusz się aby wstać
|
||||
This spot is already occupied!=To miejsce jest już zajęte!
|
||||
@1 sits=@1 siedzi
|
||||
@1 lies=@1 leży
|
||||
@1 stands up=@1 wstaje
|
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.ru.tr
Normal file
8
mods/PLAYER/mcl_cozy/locale/mcl_cozy.ru.tr
Normal file
|
@ -0,0 +1,8 @@
|
|||
# textdomain: mcl_cozy
|
||||
Sit down=Сесть
|
||||
Lay down=Лечь
|
||||
Move to stand up=Двиньтесь чтобы встать
|
||||
This spot is already occupied!=Это место уже занято!
|
||||
@1 sits=@1 сел(а)
|
||||
@1 lies=@1 лег(ла)
|
||||
@1 stands up=@1 встал(а)
|
8
mods/PLAYER/mcl_cozy/locale/template.txt
Normal file
8
mods/PLAYER/mcl_cozy/locale/template.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# textdomain: mcl_cozy
|
||||
Sit down=
|
||||
Lay down=
|
||||
Move to stand up=
|
||||
This spot is already occupied!=
|
||||
@1 sits=
|
||||
@1 lies=
|
||||
@1 stands up=
|
5
mods/PLAYER/mcl_cozy/mod.conf
Normal file
5
mods/PLAYER/mcl_cozy/mod.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
name = mcl_cozy
|
||||
author = rudzik8
|
||||
description = Sit and lay using chat command and by right-clicking blocks
|
||||
depends = mcl_player, playerphysics
|
||||
optional_depends = mcl_title, mcl_stairs, mcl_playerinfo
|
23
mods/PLAYER/mcl_cozy/stairs_slabs.lua
Normal file
23
mods/PLAYER/mcl_cozy/stairs_slabs.lua
Normal file
|
@ -0,0 +1,23 @@
|
|||
local function check_param2_and_sit(pos, ...)
|
||||
local param2 = core.get_node(pos).param2
|
||||
-- avoid inverted stairs
|
||||
if param2 >= 20 then return end
|
||||
return mcl_cozy.sit(pos, ...)
|
||||
end
|
||||
|
||||
core.register_on_mods_loaded(function()
|
||||
for name, def in pairs(core.registered_nodes) do
|
||||
-- bottom slabs
|
||||
if name:find("^mcl_stairs:slab") and not (name:find("_top$")) then
|
||||
core.override_item(name, {
|
||||
on_rightclick = mcl_cozy.sit,
|
||||
})
|
||||
-- stairs
|
||||
elseif name:find("^mcl_stairs:stair") then
|
||||
core.override_item(name, {
|
||||
on_rightclick = check_param2_and_sit,
|
||||
_mcl_cozy_offset = vector.new(0, 0, -0.15),
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
|
@ -87,6 +87,14 @@ mcl_craftguide_progressive_mode (Learn crafting recipes progressively) bool true
|
|||
# If disabled, the skin of all players will be character.png
|
||||
mcl_enable_skin_customization (Enable player skin customization) bool true
|
||||
|
||||
# If enabled, players will be able to sit on stairs and slabs by right-clicking
|
||||
# them
|
||||
mcl_cozy_sit_on_stairs (Sit on stairs & slabs) bool true
|
||||
|
||||
# If enabled, messages like "* player stands up" (in style of /me) will be sent
|
||||
# each time a player sits, lays or stands up
|
||||
mcl_cozy_print_actions (Print actions) bool false
|
||||
|
||||
# How far the player hand can reach
|
||||
# Default:4.5
|
||||
mcl_hand_range (Hand range) float 4.5 1 128
|
||||
|
|
Loading…
Reference in a new issue