Implement arena regions (pos1 and pos2 parameter)

This commit is contained in:
Zughy 2023-03-30 17:52:07 +00:00
parent 544228bfd7
commit 601af6d1c4
10 changed files with 222 additions and 60 deletions

12
DOCS.md
View File

@ -38,8 +38,10 @@
* [2.2.2.8 Music](#2228-music)
* [2.2.2.9 Celestial vault](#2229-celestial-vault)
* [2.2.2.10 Lighting](#22210-lighting)
* [2.2.2.11 Region](#22211-region)
* [2.3 Arena phases](#23-arena-phases)
* [2.4 Spectate mode](#24-spectate-mode)
* [2.5 Arena region](#25-arena-region)
* [3. About the author(s)](#3-about-the-authors)
## 1. Minigame configuration
@ -312,6 +314,7 @@ There are also some other functions which might turn useful. They are:
* `arena_lib.is_area_spectated(mod, arena_name, pos_name)`: returns whether an area is being spectated
* `arena_lib.is_arena_in_edit_mode(arena_name)`: returns whether the arena is in edit mode or not, as a boolean
* `arena_lib.is_player_in_edit_mode(p_name)`: returns whether a player is editing an arena, as a boolean
* `arena_lib.is_player_in_region(arena, p_name)`: returns whether a player is inside the region of `arena`, if declared
### 1.8 Getters
* `arena_lib.get_arena_by_name(mod, arena_name)`: returns the ID and the whole arena. Contrary to the duo `get_arena_by_player` and `get_arenaID_by_player`, this is not split in two as these two variables are often needed together inside arena_lib
@ -398,6 +401,8 @@ An arena is a table having as a key an ID and as a value its parameters. They ar
* `entrance_type`: (string) the type of the entrance of the arena. By default it takes the `arena_lib.DEFAULT_ENTRANCE` settings (which is `"sign"` by default)
* `entrance`: (can vary) the value used by arena_lib to retrieve the entrance linked to the arena. Built-in signs use their coordinates
* `custom_return_point`: (table) a position that, if declared, overrides the `hub_spawn_point` server setting (see [1.1 Per server configuration](#11-per-server-configuration)). Default is `nil`
* `pos1`: (table) one of the corners that determine the region of the arena, alongside `pos2`. Check [#2.5 - Arena region](#25-arena-region) to learn more. Default is `nil`
* `pos2`: ^
* `players`: (table) where to store players information, such as their team ID (`teamID`) and `player_properties`. Format `{[p_name] = {stuff}, [p_name2] = {stuff}, ...}`
* `spectators`: (table) where to store spectators information. Format `{[sp_name] = true}`
* `players_and_spectators`: (table) where to store both players and spectators names. Format `{[psp_name] = true}`
@ -512,6 +517,9 @@ NOTE: EXPERIMENTAL FEATURE. EXPECT BREAKAGE IN THE FUTURE (according to the dire
By default, the arena's lighting settings reflect the lighting settings of the player before entering the match (meaning there are no default values inside arena_lib).
`arena_lib.set_lighting(sender, mod, arena_name, light_table)` allows you to override those settings. As for now, `light_table` only takes one field, `light`, a float between 0 and 1 that changes the intensity of the global lighting. If `light_table` is `nil`, it'll reset the whole lighting settings.
##### 2.2.2.11 Region
`arena_lib.set_region(sender, mod, arena_name, pos1, pos2)` allows you to set the region of the arena. `pos1` and `pos2` are both mandatory and they both need to be vectors (sending a table such as `{x=3,z=4,y=2}` won't work).
### 2.3 Arena phases
An arena comes in 4 phases:
* `queuing phase`: the queuing process. People interact with the entrance waiting for other players to play with
@ -525,5 +533,9 @@ Every minigame has this mode enabled by default. As the name suggests, it allows
By default, spectate mode allows to follow players, but it also allows modders to expand it to entities and areas. To do that, have a look at `arena_lib.add_spectate_entity(...)` and `arena_lib.add_spectate_area(...)`
<br>
### 2.5 Arena region
An arena region is an optional cuboid wrapping the arena (there can be only one per arena), that can be used for several purposes. An example is to save and then restore the arena map once the match is over, or eliminate any player that goes outside of it. As for now, a region serves no purpose by default, so it's up to the single minigame to implement the logic behind it. However, with arena_lib 7.0, the map reset is going to be a built-in feature.
An util function that comes with it is `arena_lib.is_player_in_region(..)`
## 3. About the author(s)
I'm Zughy (Marco), a professional Italian pixel artist who fights for FOSS and digital ethics. If this library spared you a lot of time and you want to support me somehow, please consider donating on [Liberapay](https://liberapay.com/Zughy/). Also, this project wouldn't have been possible if it hadn't been for some friends who helped me testing through: `Giov4`, `SonoMichele`, `_Zaizen_` and `Xx_Crazyminer_xX`

View File

@ -1,4 +1,4 @@
# version 6.1.0
# version 6.2.0-dev
# author(s): Zughy
# reviewer(s):
# textdomain: arena_lib
@ -93,6 +93,7 @@ Entrance type of arena @1 successfully changed (@2)=Tipo d'entrata dell'arena @1
Entrance of arena @1 successfully removed=Entrata dell'arena @1 rimosso con successo
Custom return point of arena @1 succesfully removed=Punto di ritorno personalizzato dell'arena @1 rimosso con successo
Custom return point of arena @1 succesfully set=Punto di ritorno personalizzato dell'arena @1 impostato con successo
Region of arena @1 successfully overwritten=Regione dell'arena @1 sovrascritta con successo
[!] There is already an entrance for this arena!=[!] Esiste già un'entrata per quest'arena!
Entrance of arena @1 successfully set=Entrata dell'arena @1 impostata con successo
Lighting of arena @1 successfully overwritten=Illuminazione dell'arena @1 sovrascritta con successo
@ -185,10 +186,12 @@ Teams: on (click to toggle off)=Squadre: attive (premi per disattivare)
Teams: off (click to toggle on)=Squadre: non attive (premi per attivare)
# editor/tools_settings.lua
Arena region (LMB pos1, RMB pos2, Q removes)=Regione dell'arena (sx pos1, dx pos2, Q rimuovi)
Custom return point (LMB sets, RMB removes)=Punto di ritorno personalizzato (sx imposta, dx rimuove)
Arena name, author and thumbnail=Nome arena, autorə e miniatura
Arena properties=Proprietà arena
Custom return point (LMB sets, RMB removes)=Punto di ritorno personalizzato (sx imposta, dx rimuove)
Delete arena=Cancella arena
Are you sure you want to delete the region of the arena?=Sei sicurə di voler eliminare la regione dell'arena?
Rename arena=Rinomina arena
Set author=Imposta autorə
Set thumbnail=Imposta miniatura
@ -317,6 +320,7 @@ Past and present players inside: =Giocatorɜ presenti e passatɜ dentro:
Enabled: =Abilitata:
Status: =Stato:
Entrance: =Entrata:
Region: =Regione:
Custom return point: =Punto di ritorno personalizzato:
Spawn points: =Punti di rinascita:
Custom sky: =Cielo personalizzato:

View File

@ -1,4 +1,4 @@
# version 6.1.0
# version 6.2.0-dev
# author(s):
# reviewer(s):
# textdomain: arena_lib
@ -93,6 +93,7 @@ Entrance type of arena @1 successfully changed (@2)=
Entrance of arena @1 successfully removed=
Custom return point of arena @1 succesfully removed=
Custom return point of arena @1 succesfully set=
Region of arena @1 successfully overwritten=
[!] There is already an entrance for this arena!=
Entrance of arena @1 successfully set=
Lighting of arena @1 successfully overwritten=
@ -185,10 +186,12 @@ Teams: on (click to toggle off)=
Teams: off (click to toggle on)=
# editor/tools_settings.lua
Arena region (LMB pos1, RMB pos2, Q removes)=
Custom return point (LMB sets, RMB removes)=
Arena name, author and thumbnail=
Arena properties=
Custom return point (LMB sets, RMB removes)=
Delete arena=
Are you sure you want to delete the region of the arena?=
Rename arena=
Set author=
Set thumbnail=
@ -317,6 +320,7 @@ Past and present players inside: =
Enabled: =
Status: =
Entrance: =
Region: =
Custom return point: =
Spawn points: =
Custom sky: =

View File

@ -55,6 +55,8 @@ local arena_optional_fields = {
spectators_amount_per_team = true,
spectate_entities_amount = true,
spectate_areas_amount = true,
pos1 = true,
pos2 = true,
celestial_vault = true, -- sky = {...}, sun = {...}, moon = {...}, stars = {...}, clouds = {...}
lighting = true, -- light = override_day_night_ratio
bgm = true,
@ -1012,6 +1014,33 @@ end
function arena_lib.set_region(sender, mod, arena_name, pos1, pos2, in_editor)
local id, arena = arena_lib.get_arena_by_name(mod, arena_name)
if not arena_lib.is_player_in_edit_mode(sender) then
if not ARENA_LIB_EDIT_PRECHECKS_PASSED(sender, arena) then return end
end
if not pos1 and not pos2 then
arena.pos1 = nil
arena.pos2 = nil
else
if not pos1 or not pos2 or not vector.check(pos1) or not vector.check(pos2) then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", S("[!] Parameters don't seem right!")))
return end
arena.pos1 = vector.round(pos1)
arena.pos2 = vector.round(pos2)
end
arena_lib.update_waypoints(sender, mod, arena)
update_storage(false, mod, id, arena)
minetest.chat_send_player(sender, arena_lib.mods[mod].prefix .. S("Region of arena @1 successfully overwritten", arena_name))
end
function arena_lib.set_lighting(sender, mod, arena_name, light_table, in_editor)
local id, arena = arena_lib.get_arena_by_name(mod, arena_name)

View File

@ -1,3 +1,23 @@
----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------
function arena_lib.is_player_in_region(arena, p_name)
if not arena then return end
if not arena.pos1 then
minetest.log("[ARENA_LIB] Attempt to check whether a player is inside an arena region (" .. arena.name .. "), when the arena has got no region declared")
return end
local v1, v2 = vector.sort(arena.pos1, arena.pos2)
local region = VoxelArea:new({MinEdge=v1, MaxEdge=v2})
local p_pos = minetest.get_player_by_name(p_name):get_pos()
return region:containsp(p_pos)
end
-- channel: "players", "spectators", "both"
function arena_lib.send_message_in_arena(arena, channel, msg, teamID, except_teamID)
@ -83,7 +103,6 @@ end
----------------------------------------------
------------------DEPRECATED------------------
----------------------------------------------

View File

@ -68,7 +68,6 @@ minetest.register_tool("arena_lib:editor_settings", {
on_use = function(itemstack, user)
arena_lib.give_settings_tools(user)
end
})
@ -87,7 +86,6 @@ minetest.register_tool("arena_lib:editor_info", {
arena_lib.print_arena_info(user:get_player_name(), mod, arena_name)
end
})
@ -103,7 +101,6 @@ minetest.register_tool("arena_lib:editor_return", {
on_use = function(itemstack, user)
arena_lib.show_main_editor(user)
end
})
@ -122,7 +119,6 @@ minetest.register_tool("arena_lib:editor_enable", {
arena_lib.enable_arena(user:get_player_name(), mod, arena_name, true)
end
})
@ -138,5 +134,4 @@ minetest.register_tool("arena_lib:editor_quit", {
on_use = function(itemstack, user)
arena_lib.quit_editor(user)
end
})

View File

@ -1,17 +1,18 @@
local S = minetest.get_translator("arena_lib")
local FS = minetest.formspec_escape
local function get_region_formspec() end
local function get_rename_author_thumbnail_formspec() end
local function get_properties_formspec() end
local function get_timer_formspec() end
local function get_delete_formspec() end
local settings_tools = {
"arena_lib:settings_rename_author",
"arena_lib:settings_region",
"arena_lib:settings_returnpoint",
"arena_lib:settings_rename_author",
"arena_lib:settings_properties",
"", -- timer_off/_on
"",
"arena_lib:settings_delete",
"",
"arena_lib:editor_return",
@ -22,6 +23,85 @@ local sel_property_attr = {} --KEY: p_name; VALUE: {id = idx, name = propert
minetest.register_tool("arena_lib:settings_region", {
description = S("Arena region (LMB pos1, RMB pos2, Q removes)"),
inventory_image = "arenalib_tool_settings_region.png",
groups = {not_in_creative_inventory = 1},
on_drop = function(itemstack, dropper, pos)
local arena_name = dropper:get_meta():get_string("arena_lib_editor.arena")
minetest.show_formspec(dropper:get_player_name(), "arena_lib:settings_region", get_region_formspec(arena_name))
end,
on_use = function(itemstack, user, pointed_thing)
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
local _, arena = arena_lib.get_arena_by_name(mod, arena_name)
local p_pos = user:get_pos()
local pos2 = arena.pos2 or p_pos
-- copio perché arena.pos2 non è creato da vector.*, fallendo vector.check() in arena_lib.set_region()
arena_lib.set_region(user:get_player_name(), mod, arena_name, p_pos, vector.copy(pos2), in_editor)
end,
on_secondary_use = function(itemstack, user, pointed_thing)
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
local _, arena = arena_lib.get_arena_by_name(mod, arena_name)
local p_pos = user:get_pos()
local pos1 = arena.pos1 or p_pos
arena_lib.set_region(user:get_player_name(), mod, arena_name, vector.copy(pos1), p_pos, in_editor)
end,
on_place = function(itemstack, placer, pointed_thing)
local mod = placer:get_meta():get_string("arena_lib_editor.mod")
local arena_name = placer:get_meta():get_string("arena_lib_editor.arena")
local _, arena = arena_lib.get_arena_by_name(mod, arena_name)
local p_pos = placer:get_pos()
local pos1 = arena.pos1 or p_pos
arena_lib.set_region(placer:get_player_name(), mod, arena_name, vector.copy(pos1), p_pos, in_editor)
end
})
minetest.register_tool("arena_lib:settings_returnpoint", {
description = S("Custom return point (LMB sets, RMB removes)"),
inventory_image = "arenalib_tool_settings_returnpoint.png",
groups = {not_in_creative_inventory = 1},
on_drop = function() end,
on_use = function(itemstack, user, pointed_thing)
local p_name = user:get_player_name()
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, vector.round(user:get_pos()), true)
end,
on_secondary_use = function(itemstack, user, pointed_thing)
local p_name = user:get_player_name()
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, nil, true)
end,
on_place = function(itemstack, placer, pointed_thing)
local p_name = placer:get_player_name()
local mod = placer:get_meta():get_string("arena_lib_editor.mod")
local arena_name = placer:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, nil, true)
end
})
minetest.register_tool("arena_lib:settings_rename_author", {
description = S("Arena name, author and thumbnail"),
@ -61,40 +141,6 @@ minetest.register_tool("arena_lib:settings_properties", {
minetest.register_tool("arena_lib:settings_returnpoint", {
description = S("Custom return point (LMB sets, RMB removes)"),
inventory_image = "arenalib_tool_settings_returnpoint.png", -- TODO: immagine
groups = {not_in_creative_inventory = 1},
on_drop = function() end,
on_use = function(itemstack, user, pointed_thing)
local p_name = user:get_player_name()
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, vector.round(user:get_pos()), true)
end,
on_secondary_use = function(itemstack, placer, pointed_thing)
local p_name = placer:get_player_name()
local mod = placer:get_meta():get_string("arena_lib_editor.mod")
local arena_name = placer:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, nil, true)
end,
on_place = function(itemstack, user, pointed_thing)
local p_name = user:get_player_name()
local mod = user:get_meta():get_string("arena_lib_editor.mod")
local arena_name = user:get_meta():get_string("arena_lib_editor.arena")
arena_lib.set_custom_return_point(p_name, mod, arena_name, nil, true)
end
})
minetest.register_craftitem("arena_lib:timer", {
description = S("Timer: on"),
@ -139,7 +185,7 @@ function arena_lib.give_settings_tools(user)
local mod_ref = arena_lib.mods[mod]
if mod_ref.time_mode == "decremental" then
inv:set_stack("main", 4, "arena_lib:timer")
inv:set_stack("main", 5, "arena_lib:timer")
end
end
@ -151,6 +197,21 @@ end
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function get_region_formspec(arena_name)
local formspec = {
"size[5,1.3]",
"style[region_delete_confirm;bgcolor=red]",
"hypertext[0.25,-0.1;5,1;delete_msg;<global halign=center>" .. S("Are you sure you want to delete the region of the arena?") .. "]",
"button[3,0.7;1.5,0.5;region_delete_confirm;" .. S("Yes") .. "]",
"button[0.5,0.7;1.5,0.5;region_delete_cancel;" .. S("Cancel") .. "]",
"field_close_on_enter[;false]"
}
return table.concat(formspec, "")
end
function get_rename_author_thumbnail_formspec(arena)
local formspec = {
"formspec_version[4]",
@ -253,7 +314,7 @@ end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "arena_lib:settings_timer" and formname ~= "arena_lib:settings_rename_author_thumbnail"
if formname ~= "arena_lib:settings_timer" and formname ~= "arena_lib:settings_region" and formname ~= "arena_lib:settings_rename_author_thumbnail"
and formname ~= "arena_lib:settings_properties" and formname ~= "arena_lib:settings_delete" then
return end
@ -263,7 +324,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- GUI per rinominare arena e cambiare autore e miniatura
if formname == "arena_lib:settings_rename_author_thumbnail" then
if fields.key_enter then
if fields.key_enter_field == "rename" then
if not arena_lib.rename_arena(p_name, mod, arena_name, fields.rename, true) then return end
@ -295,9 +355,18 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
arena_lib.set_thumbnail(p_name, mod, arena_name, fields.thumbnail, true)
end
-- GUI per cancellare regione
elseif formname == "arena_lib:settings_region" then
if fields.region_delete_confirm then
minetest.close_formspec(p_name, formname)
arena_lib.set_region(p_name, mod, arena_name, nil, nil, true)
elseif fields.region_delete_cancel then
minetest.close_formspec(p_name, formname)
end
-- GUI per modificare proprietà
elseif formname == "arena_lib:settings_properties" then
local id, arena = arena_lib.get_arena_by_name(mod, arena_name)
-- se clicco sulla lista
@ -317,7 +386,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- GUI per timer
elseif formname == "arena_lib:settings_timer" then
if fields.timer_confirm or fields.key_enter then
local timer = tonumber(fields.set_timer)
@ -332,7 +400,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- GUI per cancellare arena
else
if fields.delete_confirm then
arena_lib.quit_editor(player)
minetest.close_formspec(p_name, formname)

View File

@ -50,6 +50,34 @@ function arena_lib.show_waypoints(p_name, mod, arena)
})
table.insert(waypoints[p_name], HUD_ID)
-- eventuale regione
-- TODO: si potrebbe usare https://github.com/minetest/minetest/pull/13020 in
-- futuro per renderizzare i bordi della regione. Questo renderebbe tuttavia
-- impossibile fare catture senza avere i bordi renderizzati; per ovviare,
-- si è ipotizzato di nascondere la regione al premere E su qualsiasi casella,
-- anche se sarebbe un po' un'esagerazione dato che non penso ci sarebbero altri
-- elementi grafici da nascondere (i marcatori già spariscono con F2). Un'altra
-- opzione è aggiungere /arenas tp <arena>, ma questo non appplicherebbe le
-- personalizzazioni grafiche dell'arena (quindi prob anche peggio)
if arena.pos1 then
local pos1 = player:hud_add({
name = "Pos1",
hud_elem_type = "waypoint",
precision = 0,
world_pos = arena.pos1
})
local pos2 = player:hud_add({
name = "Pos2",
hud_elem_type = "waypoint",
precision = 0,
world_pos = arena.pos2
})
table.insert(waypoints[p_name], pos1)
table.insert(waypoints[p_name], pos2)
end
end)
end

View File

@ -23,6 +23,7 @@ function arena_lib.print_minigames(sender)
end
function arena_lib.print_arenas(sender, mod)
local mod_ref = arena_lib.mods[mod]
@ -174,13 +175,18 @@ function arena_lib.print_arena_info(sender, mod, arena_name)
status = S("waiting")
end
-- calcolo entrata
if arena.entrance == nil then
entrance = "---"
else
-- calcolo eventuale entrata
local entrance = "---"
if arena.entrance ~= nil then
entrance = arena_lib.entrances[arena.entrance_type].print(arena.entrance)
end
-- calcolo eventuale regione
local region = "---"
if arena.pos1 then
region = "Pos1 " .. minetest.pos_to_string(arena.pos1) .. " Pos2 " .. minetest.pos_to_string(arena.pos2) .. ""
end
-- calcolo eventuale punto di ritorno personalizzato
local custom_return_point = not arena.custom_return_point and "---" or minetest.pos_to_string(arena.custom_return_point)
@ -222,11 +228,9 @@ function arena_lib.print_arena_info(sender, mod, arena_name)
end
-- calcolo eventuale illuminazione personalizzata
local lighting = ""
local lighting = "---"
if arena.lighting then
lighting = table_to_string(arena.lighting)
else
lighting = "---"
end
--calcolo proprietà
@ -277,7 +281,6 @@ function arena_lib.print_arena_info(sender, mod, arena_name)
end
end
minetest.chat_send_player(sender,
minetest.colorize("#cfc6b8", "====================================") .. "\n" ..
minetest.colorize("#eea160", S("Name: ")) .. minetest.colorize("#cfc6b8", arena_name ) .. "\n" ..
@ -306,6 +309,7 @@ function arena_lib.print_arena_info(sender, mod, arena_name)
minetest.colorize("#eea160", S("Enabled: ")) .. minetest.colorize("#cfc6b8", tostring(arena.enabled)) .. "\n" ..
minetest.colorize("#eea160", S("Status: ")) .. minetest.colorize("#cfc6b8", status) .. "\n" ..
minetest.colorize("#eea160", S("Entrance: ")) .. minetest.colorize("#cfc6b8", "(" .. arena.entrance_type .. ") " .. entrance) .. "\n" ..
minetest.colorize("#eea160", S("Region: ")) .. minetest.colorize("#cfc6b8", region) .. "\n" ..
minetest.colorize("#eea160", S("Custom return point: ")) .. minetest.colorize("#cfc6b8", custom_return_point) .. "\n" ..
minetest.colorize("#eea160", S("Spawn points: ")) .. minetest.colorize("#cfc6b8", arena_lib.get_arena_spawners_count(arena) .. " ( " .. spawners_pos .. ")") .. "\n\n" ..

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B