Stats can be viewed in a formspec, via a chat command.

master
Nathan Salapat 2022-02-12 12:57:57 -06:00
parent 118a5f52eb
commit 50ae7fb10d
6 changed files with 79 additions and 49 deletions

View File

@ -1,4 +1,7 @@
!!!Important bits and bobs you need to know!!!
2-12-22:
Also Important!!! Uncomment line 7 the first run after updating your code. This will create another new table that is required for the stats stuff to work.
2-11-22:
IMPORTANT!!! After updating you'll need to uncomment line 6 in lobby/functions.lua to create the table that the stats are saved in. Remove or comment out the line after the first run, or you'll clear the stats every restart. This will be removed in the near future. Check git history if you need to add the line in to update your database. Any newly created worlds do not need this step.

View File

@ -61,6 +61,9 @@ minetest.register_node('furniture:news_stand', {
})
local news = [[
2/12/22
Stats on levels is now visible with the /stats command.
2/7/22
Level buttons have an option to disallow solo playing, edit your buttons accordingly.

View File

@ -26,8 +26,7 @@ local function button_create(id, name, player_count, xp, pos_string, desc, build
local formspec =
'formspec_version[3]'..
'size[12,8.5]'..
'field[0.5,.5;3.25,.5;ID;ID;'..esc(id)..']'..
'tooltip[ID;Must not contain spaces or special characters.]'..
'label[.5,.75;Map ID: '..esc(id)..']'..
'field[4.375,.5;3.25,.5;name;Map Name;'..esc(name)..']'..
'tooltip[name;Will be used in chat messages and as the infotext]'..
'checkbox[8.25,.75;solo;Allow Singleplayer;'..solo..']'..
@ -50,11 +49,12 @@ local function button_display(id, name, owner, player_count, xp, pos, desc)
local formspec =
'formspec_version[3]'..
'size[12,8]'..
'textarea[0.5,1;5,2;;Map Name;'..esc(name)..' (by '..owner..')]'..
'textarea[0.5,2;5,2;;Required # of Players;'..esc(player_count)..']'..
'textarea[0.5,3;5,2;;Required XP;'..esc(xp)..']'..
'textarea[0.5,4;11,3.5;;Description of map:;'..esc(desc)..']'..
'textarea[5,1;6,4;;;Sneak punch to visit without starting a game. Return with /lobby.\n'..
'textarea[0.5,.75;4,.5;;Map Name:;'..esc(name)..' (by '..owner..')]'..
'textarea[0.5,1.5;4,.5;;Map ID:;'..esc(id)..']'..
'textarea[0.5,2.25;4,.5;;Required # of Players:;'..esc(player_count)..']'..
'textarea[0.5,3;4,.5;;Required XP:;'..esc(xp)..']'..
'textarea[0.5,3.75;11,4;;Description of map:;'..esc(desc)..']'..
'textarea[5,.5;6.5,3;;;Sneak punch to visit without starting a game. Return with /lobby.\n'..
'Be sure all interested parties are standing within three nodes of the button before punching.]'
return formspec
end
@ -73,7 +73,6 @@ minetest.register_node('lobby:button_0', {
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string('infotext', 'Unconfigured/Claimed button')
meta:set_string('id', '')
meta:set_string('name', '')
meta:set_string('player_count', '')
meta:set_string('xp', '')
@ -86,18 +85,20 @@ minetest.register_node('lobby:button_0', {
local player_name = clicker:get_player_name()
local meta = minetest.get_meta(pos)
local owner = meta:get_string('owner')
local id = meta:get_string('id')
local name = meta:get_string('name')
local player_count = meta:get_string('player_count')
local xp = meta:get_string('xp')
local pos = meta:get_string('pos')
local desc = meta:get_string('desc')
local builders = meta:get_string('builders')
local solo = meta:get_string('solo')
if owner == '' then
meta:set_string('formspec', button_claim)
elseif owner == player_name or minetest.check_player_privs(clicker, {server = true}) then
local id = meta:get_string('id')
local name = meta:get_string('name')
local player_count = meta:get_string('player_count')
local xp = meta:get_string('xp')
local pos = meta:get_string('pos')
local desc = meta:get_string('desc')
local builders = meta:get_string('builders')
local solo = meta:get_string('solo')
meta:set_string('formspec', button_create(id, name, player_count, xp, pos, desc, builders, solo))
else
minetest.show_formspec(player_name, 'lobby:button_display', button_display(id, name, owner, player_count, xp, pos, desc))
end
end,
on_punch = function(pos, node, puncher, pointed_thing)
@ -129,6 +130,14 @@ minetest.register_node('lobby:button_0', {
if lobby.take_xp(sender, 15) then
minetest.show_formspec(player_name, 'lobby:get_started', lobby.getting_started)
meta:set_string('owner', player_name)
local i = 1
local map_id = player_name..'_'..i
while lobby.savedata.IDs[map_id] do
i = i + 1
map_id = player_name..'_'..i
end
lobby.savedata.IDs[map_id] = true
meta:set_string('id', map_id)
local pos_string = random_pos()
local pos = minetest.string_to_pos(pos_string)
local run = true
@ -146,11 +155,11 @@ minetest.register_node('lobby:button_0', {
end
end
if owner == player_name or minetest.check_player_privs(sender, {server = true}) then
local map_id = meta:get_string('id')
if fields.solo then
meta:set_string('solo', fields.solo)
elseif fields ['save'] then
meta:set_string('infotext', fields.name)
meta:set_string('id', fields.ID)
meta:set_string('name', fields.name)
meta:set_string('player_count', fields.player_count)
meta:set_string('xp', fields.xp)
@ -159,14 +168,12 @@ minetest.register_node('lobby:button_0', {
meta:set_string('builders', fields.builders)
elseif fields ['submit'] then
meta:set_string('infotext', fields.name)
meta:set_string('id', fields.ID)
meta:set_string('name', fields.name)
meta:set_string('player_count', fields.player_count)
meta:set_string('xp', fields.xp)
meta:set_string('pos', fields.pos)
meta:set_string('desc', fields.desc)
meta:set_string('builders', fields.builders)
local map_id = fields.ID
local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000)
local x, y, z = string.match(fields.pos, "^(-?%d+),(-?%d+),(-?%d+)$")
local pos_x = tonumber(x)
@ -177,10 +184,6 @@ minetest.register_node('lobby:button_0', {
minetest.chat_send_player(player_name, 'Double check your spawn pos, values seem to be invalid.')
saveable = 1
end
if lobby.savedata.IDs[map_id] then
minetest.chat_send_player(player_name, 'That ID is already in use, you MUST change the ID.')
saveable = 1
end
if not lobby.is_integer(fields.player_count ) then
minetest.chat_send_player(player_name, 'An Integer is a whole number, your required player count is not.')
saveable = 1
@ -198,8 +201,9 @@ minetest.register_node('lobby:button_0', {
data.owner_name = owner
data.required_players = fields.player_count
data.xp = tonumber(fields.xp)
lobby.savedata.IDs[map_id] = true
lobby.savedata.data[map_id] = data
lobby.savedata.name_2_id[fields.name] = map_id
lobby.savedata.IDs[map_id] = true
minetest.swap_node(pos, {name = 'lobby:button_1'})
end
elseif fields ['discard'] then
@ -234,7 +238,6 @@ minetest.register_node('lobby:button_1', {
if item == 'creative:tool_breaking' or item == 'tasks:configurator' then
if owner == player_name or minetest.check_player_privs(clicker, {server = true}) then
minetest.swap_node(pos, {name = 'lobby:button_0'})
lobby.savedata.IDs[id] = false
end
else
local name = meta:get_string('name')
@ -243,7 +246,7 @@ minetest.register_node('lobby:button_1', {
local pos = meta:get_string('pos')
local desc = meta:get_string('desc')
local owner = meta:get_string('owner')
meta:set_string('formspec', button_display(id, name, owner, player_count, xp, pos, desc))
minetest.show_formspec(player_name, 'lobby:button_display', button_display(id, name, owner, player_count, xp, pos, desc))
end
end,
on_punch = function(pos, node, puncher, pointed_thing)
@ -276,7 +279,6 @@ minetest.register_node('lobby:button_1', {
minetest.chat_send_player(name, 'you can start the game!')
lobby.map[map_id] = player_count
lobby.update_stats(map_id, 'player', '', player_count)
print ('updating stats')
local traitor = math.random(1,player_count)
lobby.xp[map_id] = 0
lobby.votes[map_id] = 0
@ -316,7 +318,6 @@ minetest.register_node('lobby:button_1', {
local solo = meta:get_string('solo')
if solo == 'true' then
lobby.update_stats(map_id, 'solo')
print ('updating stats')
local name = puncher:get_player_name()
gamer.player_set_textures(puncher,{'lobby_ghost.png'})
puncher:set_nametag_attributes({

View File

@ -23,7 +23,7 @@ minetest.register_node('lobby:corpse', {
local voting = player_attributes:get_string('voting')
local map_id = lobby.game[name]
if voting == 'false' then
if map_id ~= 'lobby' and mode == 'solo' then
if map_id ~= 'lobby' and mode == 'player' then
minetest.remove_node(pos)
local game_data = lobby.savedata.data[map_id]
local game_pos = game_data['level_pos']

View File

@ -1,14 +1,16 @@
function lobby.load()
local file = io.open(minetest.get_worldpath() .. '/levels', 'r')
if file then
lobby.savedata = minetest.deserialize(file:read())
lobby.savedata = minetest.deserialize(file:read('*a'))
file:close()
--lobby.savedata.stats = {}
--lobby.savedata.name_2_id = {}
else
lobby.savedata = {}
lobby.savedata.IDs = {}
lobby.savedata.data = {}
lobby.savedata.stats = {}
lobby.savedata.name_2_id = {}
end
end
@ -93,7 +95,6 @@ function lobby.update_maps(map_id)
player:set_pos(lobby.spawn_pos)
player_attributes:set_string('mode', 'solo')
minetest.chat_send_player(rname, 'Kicking you to the lobby')
print 'kicked to lobby from updated maps'
player:set_physics_override({speed=1})
local player_inv = player:get_inventory()
player_inv:set_list('main', {})
@ -135,10 +136,14 @@ function lobby.vote(map_id, force)
elseif kick ~= '' then
lobby.message_to_level(map_id, 'The votes are in, '..kick..' will be kicked.')
local player = minetest.get_player_by_name(kick)
player:set_pos(lobby.spawn_pos)
local player_inv = player:get_inventory()
player_inv:set_list('main', {})
lobby.game[kick] = 'lobby'
gamer.player_set_textures(player,{'lobby_ghost.png'})
player:set_nametag_attributes({
color = {a = 0, r = 255, g = 255, b = 255}
})
player:set_properties({visual_size = {x = 0, y = 0}, collisionbox = {-0.3, 0.0, -0.3, 0.3, .2, 0.3}})
player_attributes:set_string('mode', 'ghost')
minetest.chat_send_player(kick, 'You were kicked, and are now a ghost. Return to the lobby with the /lobby chat command.')
lobby.game[kick] = map_id..'_ghost'
lobby.update_maps(map_id)
else
lobby.message_to_level(map_id, 'Nobody was kicked this round.')
@ -166,7 +171,6 @@ function lobby.team_win(map_id)
})
player:set_properties({visual_size = {x = 1, y = 1}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}})
player:set_pos(lobby.spawn_pos)
print 'teleporting to spawn as traitor was killed.'
player_attributes:set_string('mode', 'solo')
minetest.chat_send_player(rname, 'The traitor was defeated.')
player:set_physics_override({speed=1})
@ -188,7 +192,6 @@ function lobby.traitor_win(traitor, map_id)
lobby.give_xp(player, 25)
minetest.chat_send_player(traitor, 'CONGRATULATIONS!!! You killed all the crew!')
lobby.game[traitor] = 'lobby'
print 'killed all the crew, teleporting to spawn.'
player:set_pos(lobby.spawn_pos)
player:set_physics_override({speed=1})
local player_inv = player:get_inventory()

View File

@ -26,29 +26,49 @@ function lobby.update_stats(map_id, mode, win, player_count)
end
function lobby.retrieve_stats(map_id)
local formspec = ''
if lobby.savedata.stats[map_id] then
local data = lobby.savedata.data[map_id]
local map_name = data['map_name'] or map_id
local stats = lobby.savedata.stats[map_id]
local solo = stats.solo_play
local player = stats.multi_play
local traitor = stats.winner_traitor
local team = stats.winner_team
local avg_players = stats.player_count
print ('solo count is '..solo)
print ('multiplayer count is '..player)
print ('traitor won '..traitor)
print ('team won '..team)
print ('average player count is '..avg_players)
local count = solo + player
formspec =
'formspec_version[3]'..
'size[16,9]'..
'label[.5,.5;Viewing stats for '..map_name..', ('..map_id..')]'..
'textarea[.5,1;7.5,5;;; This level has been played '..player..' times.'..
' The average number of players in a session is '..avg_players..'.\n'..
' The traitor has won '..traitor..' games, whereas '..team..' have been team wins.\n'..
' This level has been visited by single players '..solo..' times.]'..
'textarea[8.5,.5;7,5;;; What does this all mean and why should you care?\n'..
' If you find that your level\'s wins strongly favor one party you might want to tweak the number of tasks,'..
' the granted XP, or the required XP. People are more likely to play your level when the chances of winning are fairly even.]'..
'label[.5,5.5;This space reserved for eventual charts and tables.]'
else
formspec =
'formspec_version[3]'..
'size[16,9]'..
'label[.5,2;No data on this level yet! Get some friends and play a round.]'..
'label[.5,5.5;This space reserved for eventual charts and tables.]'
end
return formspec
end
minetest.register_chatcommand('stats', {
description = 'View stats on a level, valid level ID required.',
func = function(name, map_id)
if lobby.savedata.IDs[map_id] then
local data = lobby.savedata.data[map_id]
print (data.owner_name)
if data.owner_name == name or minetest.check_player_privs(name, {server = true}) then
lobby.retrieve_stats(map_id)
description = 'View stats on a level, valid map name required.',
func = function(name, map_name)
if lobby.savedata.name_2_id[map_name] then
local map_id = lobby.savedata.name_2_id[map_name]
if lobby.savedata.IDs[map_id] then
local data = lobby.savedata.data[map_id]
if data.owner_name == name or minetest.check_player_privs(name, {server = true}) then
minetest.show_formspec(name, 'lobby:stats', lobby.retrieve_stats(map_id))
end
end
end
end