2021-06-07 23:32:05 +03:00
--Based on:
--https://www.digminecraft.com/game_commands/title_command.php
--https://youtu.be/oVrtQRO2hpY
2021-06-02 12:12:15 +03:00
2021-06-02 01:23:11 +03:00
--TODO: use SSCSM to reduce lag and network trafic (just send modchannel messages)
2021-06-02 01:25:15 +03:00
--TODO: fadeIn and fadeOut animation (needs engine change: SSCSM or native support)
2021-06-07 23:32:05 +03:00
--TODO: allow obfuscating text (needs engine change: SSCSM or native support)
--TODO: allow colorizing and styling of part of the text (NEEDS ENGINE CHANGE!!!)
2021-06-02 01:23:11 +03:00
--TODO: exactly mc like layout
2021-07-09 12:34:23 +03:00
--Note that the table storing timeouts use playername as index insteed of player objects (faster)
--This is intended in order to speedup the process of removing HUD elements the the timeout is up
2022-10-08 13:11:26 +03:00
---@type table<string, table<ObjectRef, any>>
2021-06-02 01:23:11 +03:00
local huds_idx = { }
2022-10-08 13:11:26 +03:00
---@type table<string, table<string, number>>
2021-07-09 12:34:23 +03:00
local hud_hide_timeouts = { }
hud_hide_timeouts.title = { }
hud_hide_timeouts.subtitle = { }
hud_hide_timeouts.actionbar = { }
2021-06-02 01:23:11 +03:00
huds_idx.title = { }
huds_idx.subtitle = { }
huds_idx.actionbar = { }
mcl_title = { }
2022-10-08 13:11:26 +03:00
mcl_title.defaults = { fadein = 10 , stay = 70 , fadeout = 20 }
2021-06-02 01:23:11 +03:00
mcl_title.layout = { }
2022-10-08 13:11:26 +03:00
mcl_title.layout . title = { position = { x = 0.5 , y = 0.5 } , alignment = { x = 0 , y = - 1.3 } , size = 7 }
mcl_title.layout . subtitle = { position = { x = 0.5 , y = 0.5 } , alignment = { x = 0 , y = 1.7 } , size = 4 }
mcl_title.layout . actionbar = { position = { x = 0.5 , y = 1 } , alignment = { x = 0 , y = 0 } , size = 1 }
2021-06-02 01:23:11 +03:00
local get_color = mcl_util.get_color
2021-08-19 20:21:33 +03:00
--local string = string
2021-07-09 12:34:23 +03:00
local pairs = pairs
2022-10-08 13:11:26 +03:00
---@param gametick integer
---@return number?
2021-06-02 01:23:11 +03:00
local function gametick_to_secondes ( gametick )
2021-08-16 14:48:08 +03:00
if gametick then
return gametick / 20
else
return nil
end
2021-06-02 01:23:11 +03:00
end
2021-08-16 15:19:50 +03:00
--https://github.com/minetest/minetest/blob/b3b075ea02034306256b486dd45410aa765f035a/doc/lua_api.txt#L8477
2022-10-08 13:11:26 +03:00
---@param bold? boolean
---@param italic? boolean
---@return integer
2021-08-16 15:19:50 +03:00
local function style_to_bits ( bold , italic )
if bold then
if italic then
return 3
else
return 1
end
else
if italic then
return 2
else
return 0
end
end
end
2021-06-02 01:23:11 +03:00
2022-10-08 13:11:26 +03:00
local no_style = style_to_bits ( false , false )
---PARAMS SYSTEM
---@type table<ObjectRef, {stay: integer}>
2021-06-02 01:23:11 +03:00
local player_params = { }
minetest.register_on_joinplayer ( function ( player )
2021-08-19 20:21:33 +03:00
--local playername = player:get_player_name()
2021-07-20 16:47:26 +03:00
player_params [ player ] = {
2021-08-16 14:48:08 +03:00
stay = mcl_title.defaults . stay ,
--fadeIn = mcl_title.defaults.fadein,
--fadeOut = mcl_title.defaults.fadeout,
2021-07-09 12:34:23 +03:00
}
2021-08-19 20:21:33 +03:00
local _ , hex_color = get_color ( " white " )
2021-07-09 12:34:23 +03:00
huds_idx.title [ player ] = player : hud_add ( {
hud_elem_type = " text " ,
2022-10-08 13:11:26 +03:00
position = mcl_title.layout . title.position ,
alignment = mcl_title.layout . title.alignment ,
text = " " ,
style = no_style ,
size = { x = mcl_title.layout . title.size } ,
number = hex_color ,
z_index = 100 ,
2021-07-09 12:34:23 +03:00
} )
huds_idx.subtitle [ player ] = player : hud_add ( {
hud_elem_type = " text " ,
2022-10-08 13:11:26 +03:00
position = mcl_title.layout . subtitle.position ,
alignment = mcl_title.layout . subtitle.alignment ,
text = " " ,
style = no_style ,
size = { x = mcl_title.layout . subtitle.size } ,
number = hex_color ,
z_index = 100 ,
2021-07-09 12:34:23 +03:00
} )
huds_idx.actionbar [ player ] = player : hud_add ( {
hud_elem_type = " text " ,
2022-10-08 13:11:26 +03:00
position = mcl_title.layout . actionbar.position ,
offset = { x = 0 , y = - 210 } ,
alignment = mcl_title.layout . actionbar.alignment ,
style = no_style ,
text = " " ,
size = { x = mcl_title.layout . actionbar.size } ,
number = hex_color ,
z_index = 100 ,
2021-07-09 12:34:23 +03:00
} )
2021-06-02 01:23:11 +03:00
end )
minetest.register_on_leaveplayer ( function ( player )
2021-07-09 12:34:23 +03:00
local playername = player : get_player_name ( )
--remove player params from the list
player_params [ player ] = nil
--remove HUD idx from the list (HUD elements are removed by the engine)
huds_idx.title [ player ] = nil
huds_idx.subtitle [ player ] = nil
huds_idx.actionbar [ player ] = nil
2021-08-19 20:21:33 +03:00
--remove timers from list
2021-07-09 12:34:23 +03:00
hud_hide_timeouts.title [ playername ] = nil
hud_hide_timeouts.subtitle [ playername ] = nil
hud_hide_timeouts.actionbar [ playername ] = nil
2021-06-02 01:23:11 +03:00
end )
2022-10-08 13:11:26 +03:00
---@param player ObjectRef
---@param data {stay: integer}
2021-06-02 01:23:11 +03:00
function mcl_title . params_set ( player , data )
player_params [ player ] = {
2021-08-16 14:48:08 +03:00
stay = data.stay or mcl_title.defaults . stay ,
--fadeIn = data.fadeIn or mcl_title.defaults.fadein,
--fadeOut = data.fadeOut or mcl_title.defaults.fadeout,
2021-06-02 01:23:11 +03:00
}
end
2022-10-08 13:11:26 +03:00
---@param player ObjectRef
---@return {stay: integer}
2021-06-02 01:23:11 +03:00
function mcl_title . params_get ( player )
return player_params [ player ]
end
--API FUNCTIONS
2022-10-08 13:11:26 +03:00
---@param player ObjectRef
---@param type '"title"'|'"subtitle"'|'"actionbar"'
---@param data {text: string, color: string, stay: integer, bold: boolean, italic: boolean}
---@return boolean
2021-06-02 01:23:11 +03:00
function mcl_title . set ( player , type , data )
if not data.color then
data.color = " white "
end
local _ , hex_color = get_color ( data.color )
if not hex_color then
return false
end
2021-07-09 12:34:23 +03:00
player : hud_change ( huds_idx [ type ] [ player ] , " text " , data.text )
player : hud_change ( huds_idx [ type ] [ player ] , " number " , hex_color )
2021-08-16 15:19:50 +03:00
2022-10-08 13:11:26 +03:00
-- Apply bold and italic
player : hud_change ( huds_idx [ type ] [ player ] , " style " , style_to_bits ( data.bold , data.italic ) )
hud_hide_timeouts [ type ] [ player : get_player_name ( ) ] = gametick_to_secondes ( data.stay ) or
gametick_to_secondes ( mcl_title.params_get ( player ) . stay )
2021-08-16 15:19:50 +03:00
2021-06-02 01:23:11 +03:00
return true
end
2022-10-08 13:11:26 +03:00
---@param player ObjectRef?
---@param type '"title"'|'"subtitle"'|'"actionbar"'
2021-06-02 01:23:11 +03:00
function mcl_title . remove ( player , type )
2021-07-09 12:34:23 +03:00
if player then
player : hud_change ( huds_idx [ type ] [ player ] , " text " , " " )
2022-10-08 13:11:26 +03:00
player : hud_change ( huds_idx [ type ] [ player ] , " style " , no_style )
2021-06-02 01:23:11 +03:00
end
end
2022-10-08 13:11:26 +03:00
---@param player ObjectRef
2021-06-02 01:23:11 +03:00
function mcl_title . clear ( player )
mcl_title.remove ( player , " title " )
mcl_title.remove ( player , " subtitle " )
mcl_title.remove ( player , " actionbar " )
end
minetest.register_on_dieplayer ( function ( player )
mcl_title.clear ( player )
end )
2021-07-09 12:34:23 +03:00
minetest.register_globalstep ( function ( dtime )
local new_timeouts = {
title = { } ,
subtitle = { } ,
actionbar = { } ,
}
2022-10-08 13:11:26 +03:00
2021-07-09 12:34:23 +03:00
for element , content in pairs ( hud_hide_timeouts ) do
for name , timeout in pairs ( content ) do
timeout = timeout - dtime
if timeout <= 0 then
local player = minetest.get_player_by_name ( name )
mcl_title.remove ( player , element )
else
new_timeouts [ element ] [ name ] = timeout
end
end
end
2022-10-08 13:11:26 +03:00
2021-07-09 12:34:23 +03:00
hud_hide_timeouts = new_timeouts
end )
2021-06-02 01:23:11 +03:00
2021-08-19 20:21:33 +03:00
--DEBUG STUFF!!
2022-10-09 22:31:23 +03:00
--TODO:Proper /title command that can send the title to other players.
--These commands are just for debugging right now.
local dbg_msg = " Note that these are just debug commands right now. e.g. the title is only sent to he player issuing the command. Proper /title commands will be added in the future. "
2021-06-02 01:23:11 +03:00
minetest.register_chatcommand ( " title " , {
2022-10-08 23:56:40 +03:00
privs = { debug = true } ,
2021-06-02 01:23:11 +03:00
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
2022-10-08 13:11:26 +03:00
if player then
mcl_title.set ( player , " title " , { text = param , color = " gold " , bold = true , italic = true } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 13:11:26 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 13:11:26 +03:00
end
2021-06-02 01:23:11 +03:00
end ,
} )
minetest.register_chatcommand ( " subtitle " , {
2022-10-08 23:56:40 +03:00
privs = { debug = true } ,
2021-06-02 01:23:11 +03:00
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
2022-10-08 13:11:26 +03:00
if player then
mcl_title.set ( player , " subtitle " , { text = param , color = " gold " } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 13:11:26 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 13:11:26 +03:00
end
2021-06-02 01:23:11 +03:00
end ,
} )
minetest.register_chatcommand ( " actionbar " , {
2022-10-08 23:56:40 +03:00
privs = { debug = true } ,
2021-06-02 01:23:11 +03:00
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
2022-10-08 13:11:26 +03:00
if player then
2022-10-08 23:56:40 +03:00
mcl_title.set ( player , " actionbar " , { text = param , color = " gold " , bold = true , italic = true } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 13:11:26 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 13:11:26 +03:00
end
2021-06-02 01:23:11 +03:00
end ,
} )
2022-10-08 23:56:40 +03:00
minetest.register_chatcommand ( " title_timeout " , {
privs = { debug = true } ,
2021-06-02 01:23:11 +03:00
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
2022-10-08 13:11:26 +03:00
if player then
mcl_title.params_set ( player , { stay = 600 } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 13:11:26 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 13:11:26 +03:00
end
2021-06-02 01:23:11 +03:00
end ,
} )
2022-10-08 23:56:40 +03:00
minetest.register_chatcommand ( " title_all " , {
privs = { debug = true } ,
2021-06-02 01:23:11 +03:00
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
2022-10-08 13:11:26 +03:00
if player then
mcl_title.params_set ( player , { stay = 600 } )
mcl_title.set ( player , " title " , { text = param , color = " gold " } )
mcl_title.set ( player , " subtitle " , { text = param , color = " gold " } )
mcl_title.set ( player , " actionbar " , { text = param , color = " gold " } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 13:11:26 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 13:11:26 +03:00
end
2021-06-02 01:23:11 +03:00
end ,
2021-08-19 20:21:33 +03:00
} )
2022-10-08 23:56:40 +03:00
minetest.register_chatcommand ( " title_all_styles " , {
privs = { debug = true } ,
func = function ( name , param )
local player = minetest.get_player_by_name ( name )
if player then
mcl_title.params_set ( player , { stay = 600 } )
mcl_title.set ( player , " title " , { text = param , color = " gold " } )
mcl_title.set ( player , " subtitle " , { text = param , color = " gold " , bold = true } )
mcl_title.set ( player , " actionbar " , { text = param , color = " gold " , italic = true } )
2022-10-09 22:31:23 +03:00
return true , dbg_msg
2022-10-08 23:56:40 +03:00
else
2022-10-09 22:31:23 +03:00
return false , dbg_msg
2022-10-08 23:56:40 +03:00
end
end ,
} )