function lobby.load() local file = io.open(minetest.get_worldpath() .. '/levels', 'r') if file then 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 function lobby.save() local file = io.open(minetest.get_worldpath() .. '/levels', 'w') file:write(minetest.serialize(lobby.savedata)) file:close() end function lobby.no_drop(itemstack, dropper, pos) return end function lobby.is_integer(input) local number = tonumber(input) if number then if math.floor(number) == number then return true end end end local storage = minetest.get_mod_storage() function lobby.queue_xp(name, xp) --Queues XP for offline players storage:set_int(name, xp) end function lobby.check_xp_queue(name) --Checks if a player was award xp whilst offline. local xp = storage:get_int(name) if xp > 0 then local player = minetest.get_player_by_name(name) lobby.give_xp(player, xp) storage:set_int(name, 0) minetest.chat_send_player(name, 'Hey, you just got '..xp..' xp!') end end function lobby.give_xp(player, amount) local player_attributes = player:get_meta() local xp = player_attributes:get_float('xp') or 0 xp = xp + amount player_attributes:set_float('xp', xp) sfinv.set_player_inventory_formspec(player) end function lobby.take_xp(player, amount) local player_attributes = player:get_meta() local xp = player_attributes:get_float('xp') if xp >= amount then local xp = xp - amount player_attributes:set_float('xp', xp) sfinv.set_player_inventory_formspec(player) return true else return false end end function lobby.corpse_entry(pos, map_id) local corpse_pos = lobby.corpses[map_id] table.insert(corpse_pos, pos) lobby.corpses[map_id] = corpse_pos end function lobby.corpse_removal(map_id) local corpse_pos = lobby.corpses[map_id] for key, value in pairs(corpse_pos) do minetest.set_node(value, {name='air'}) end end function lobby.players_on_level(map_id) local survivors = '' for _, player in pairs(minetest.get_connected_players()) do local rname = player:get_player_name() if lobby.game[rname] == map_id then survivors = survivors..rname..', ' end end return survivors end function lobby.update_maps(map_id) local count = lobby.map[map_id] - 1 or 10 if count <= 1 then lobby.map[map_id] = 0 lobby.corpse_removal(map_id) for _, player in pairs(minetest.get_connected_players()) do local rname = player:get_player_name() if lobby.game[rname] == map_id or lobby.game[rname] == map_id..'_ghost' then local player_attributes = player:get_meta() player:set_nametag_attributes({ color = {a = 255, r = 255, g = 255, b = 255} }) player:set_properties({visual_size = {x = 10, y = 10}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}}) player:set_pos(lobby.spawn_pos) player_attributes:set_string('mode', 'solo') minetest.chat_send_player(rname, 'Kicking you to the lobby') player:set_physics_override({speed=1}) local player_inv = player:get_inventory() player_inv:set_list('main', {}) lobby.game[rname] = 'lobby' end end else lobby.map[map_id] = count end end function lobby.vote(map_id, force) local needed_votes = lobby.map[map_id] - 1 local actual_votes = lobby.votes[map_id] if actual_votes >= needed_votes or force then lobby.vote_timer[map_id] = -1 --Reset vote status and kick player with the highest score. local high_score = 0 local kick = '' local traitor = lobby.traitors[map_id] for _, player in pairs(minetest.get_connected_players()) do local rname = player:get_player_name() if lobby.game[rname] == map_id then local score = lobby.suspect[rname] local player_attributes = player:get_meta() if score > high_score then high_score = score kick = rname end lobby.suspect[rname] = 0 player:set_physics_override({speed=1}) player_attributes:set_string('voting', 'false') end end if kick == traitor then lobby.team_win(map_id) elseif needed_votes == 1 and kick ~= traitor then lobby.traitor_win(traitor, map_id) 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) local player_attributes = player:get_meta() 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:set_physics_override({speed=1}) 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.') end end end function lobby.team_win(map_id) lobby.corpse_removal(map_id) for _, player in pairs(minetest.get_connected_players()) do local rname = player:get_player_name() if lobby.game[rname] == map_id then lobby.give_xp(player, 25) minetest.chat_send_player(rname, 'The traitor was defeated.') player:set_pos(lobby.spawn_pos) player:set_physics_override({speed=1}) local player_inv = player:get_inventory() player_inv:set_list('main', {}) lobby.game[rname] = 'lobby' elseif lobby.game[rname] == map_id..'_ghost' then local player_attributes = player:get_meta() player:set_nametag_attributes({ color = {a = 255, r = 255, g = 255, b = 255} }) player:set_properties({visual_size = {x = 10, y = 10}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}}) player:set_pos(lobby.spawn_pos) player_attributes:set_string('mode', 'solo') minetest.chat_send_player(rname, 'The traitor was defeated.') player:set_physics_override({speed=1}) local player_inv = player:get_inventory() player_inv:set_list('main', {}) lobby.game[rname] = 'lobby' end end lobby.map[map_id] = 0 lobby.update_stats(map_id, '', 'team') local game_data = lobby.savedata.data[map_id] local map_name = game_data['map_name'] or map_id minetest.chat_send_all('The traitor was defeated on this round in the '..map_name) end function lobby.traitor_win(traitor, map_id) local player = minetest.get_player_by_name(traitor) lobby.corpse_removal(map_id) lobby.give_xp(player, 25) minetest.chat_send_player(traitor, 'CONGRATULATIONS!!! You killed all the crew!') lobby.game[traitor] = 'lobby' player:set_pos(lobby.spawn_pos) player:set_physics_override({speed=1}) local player_inv = player:get_inventory() player_inv:set_list('main', {}) lobby.map[map_id] = 0 for _, player in pairs(minetest.get_connected_players()) do local rname = player:get_player_name() if lobby.game[rname] == map_id..'_ghost' or lobby.game[rname] == map_id then minetest.chat_send_player(rname, 'The traitor won.') local player_attributes = player:get_meta() player:set_nametag_attributes({ color = {a = 255, r = 255, g = 255, b = 255} }) player:set_properties({visual_size = {x = 10, y = 10}, collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}}) player:set_pos(lobby.spawn_pos) player_attributes:set_string('mode', 'solo') player:set_physics_override({speed=1}) local player_inv = player:get_inventory() player_inv:set_list('main', {}) lobby.game[rname] = 'lobby' end end lobby.map[map_id] = 0 lobby.update_stats(map_id, '', 'traitor') local game_data = lobby.savedata.data[map_id] local map_name = game_data['map_name'] or map_id minetest.chat_send_all('The traitor was victorious on this round in the '..map_name) end --[[ is_builder(player: ObjectRef): bool Return true if `player` has builder privs. --]] function lobby.is_builder(player) if player == nil then return nil end local name = player:get_player_name() return minetest.check_player_privs(name, {builder = true}) end --[[ builder_to_player(player: ObjectRef) Cast builder into regular player, including switching inventories, revoking privs, etc. --]] function lobby.builder_to_player(player) if player == nil then return end local pl_name = player:get_player_name() local pl_attr = player:get_meta() local pl_priv = minetest.get_player_privs(pl_name) local pl_mode = pl_attr:get_string('mode') or '' if pl_mode ~= 'builder' then return end pl_priv.creative = nil pl_priv.fly = nil pl_priv.fast = nil pl_priv.worldedit = nil pl_priv.areas = nil minetest.set_player_privs(pl_name, pl_priv) pl_attr:set_string('mode', 'solo') local inv = player:get_inventory() local old_inv = inv:get_list('main') inv:set_list('builder', old_inv) inv:set_size('main', 16) inv:set_list('main', {}) end --[[ player_to_builder(player: ObjectRef) Cast regular player into builder, including switching inventories, granting privs, etc. Does NOT check if the player has acquired the builder priv. Call lobby.is_builder() beforehand to make sure player is allowed to be lifted. --]] function lobby.player_to_builder(player) if player == nil then return end local pl_name = player:get_player_name() local pl_attr = player:get_meta() local pl_priv = minetest.get_player_privs(pl_name) local pl_mode = pl_attr:get_string('mode') or '' if pl_mode == 'builder' then return end pl_priv.creative = true pl_priv.fly = true pl_priv.fast = true minetest.set_player_privs(pl_name, pl_priv) pl_attr:set_string('mode', 'builder') local inv = player:get_inventory() local old_inv = inv:get_list('builder') inv:set_list('builder', {}) inv:set_size('main', 32) inv:set_list('main', old_inv) end