local ns = firefly local game_makers = {} minetest.register_entity(":firefly:map_preview", { initial_properties = { visual = "mesh", textures = {"[fill:1x1:0,0:#39f2"}, use_texture_alpha = true, static_save = false }, on_activate = function(e) e.object:set_armor_groups{immortal = 1} e._name = ""..math.random() end, on_punch = function(e, p) e.master:set_map(e.map) end, dismiss = function(e) e.object:remove() end }) minetest.register_entity(":firefly:game_maker_display", { initial_properties = { visual = "sprite", textures = {"blank.png"}, selectionbox = { -2.5, -0.5, 0.5, 2.5, 2.5, 6/16 } -- pointable = false, }, on_activate = function(e, data) local pos = e.object:get_pos():round() local node = minetest.get_node(pos) if not data or not node.name:find "game_maker_" then return end e.object:set_armor_groups{immortal = 1} e.mode = data e.rot = ns.facedir_to_rotation(node.param2) e.object:set_properties { selectionbox = ns.rotate_selectionbox({ -2.5, -0.5, 0.5, 2.5, 2.5, 6/16 }, e.rot) } e.label = minetest.add_entity(pos +vector.new(0, 1, 0.3):rotate(e.rot), "display") e.label:set_rotation(e.rot) e.players = {} e.players_list = {} game_makers[pos:to_string()] = e e.pos = pos e:show_status() end, on_step = function(e, dtime) if e.state == "choose_world" then elseif e.state == "starting" and e.timer then e.timer = e.timer -dtime if e.timer_display then local tx, w = ns.texture_from_number(math.round(e.timer)) e.timer_display:set_properties { textures = {tx}, visual_size = vector.new(w /16,1,1) *0.5 } else e.timer = nil return end local timer = math.round(e.timer) if timer ~= e._timer then for _, name in pairs(e.players_list) do ns.change_hud_bar(ns.players[name], "start_timer", { value = math.max(timer, 0), title = timer == 0 and "Starting..." or "Starting in "..timer.."..." }) end end e._timer = timer if e.timer <= 0 then e:start_game() -- e.timer = nil -- e.timer_display:remove() -- e.timer_display = nil -- e.label:set_pos(e.label:get_pos():offset(0, -0.25, 0)) -- e.label:set_properties { -- visual = "upright_sprite", -- textures = {"[combine:102x102:0,46=firefly_punch_to_start.png", "[combine:102x102:0,46=firefly_punch_to_start.png"}, -- } -- -- ns.start_game(e.mode, e.players_list) -- -- for name, obj in pairs(e.players) do -- obj:remove() -- ns.remove_hud_bar(ns.players[name], "start_timer") -- end -- e.players = {} -- e.players_list = {} end end end, add_player = function(e, name) table.insert(e.players_list, name) ns.add_hud_bar(ns.players[name], "start_timer", { max = 10, value = 0, title = "Waiting for players..." }) if e.state == "awaiting_players" then local pos = e.object:get_pos() +vector.new(-#e.players_list /2 +0.5, 1, 0.3):rotate(e.rot) local obj = minetest.add_entity(pos, "display") obj:set_properties { visual = "mesh", mesh = "firefly_head.gltf", visual_size = vector.new(1, 1, 1) *0.5, textures = {"firefly_character.png"} } obj:set_rotation(e.rot:offset(0, -math.pi, 0)) e.players[name] = obj for i, name in pairs(e.players_list) do e.players[name]:set_pos(pos +vector.new(0.5 *(i -1), 0, 0):rotate(e.rot)) end elseif e.state == "starting" then end end, remove_player = function(e, name) ns.remove_hud_bar(ns.players[name], "start_timer") table.remove(e.players_list, table.indexof(e.players_list, name)) if e.state == "choose_map" then e:dismiss_map_selector() e.state = nil e:show_status() elseif #e.players_list < 1 then if e.state == "awaiting_players" then e:dismiss_players() elseif e.state == "starting" then e:dismiss_countdown() end e.state = nil for i, name in pairs(e.players_list) do e.players[name]:set_pos(pos +vector.new(0.5 *(i -1), 0, 0):rotate(e.rot)) end e:show_status() else local pos = e.object:get_pos() +vector.new(-#e.players_list /2 +0.5, 1, 0):rotate(e.rot) end end, show_status = function(e) if e.map_image then e.map_image.object:remove() e.map_image = nil end e.label:set_pos(e.pos +vector.new(0, 1, 0.3):rotate(e.rot)) e.label:set_properties { visual = "upright_sprite", textures = {"[combine:102x102:0,46=firefly_punch_to_start.png", "[combine:102x102:0,46=firefly_punch_to_start.png"}, visual_size = vector.new(1, 1, 1) *3 } end, dismiss_status = function(e) end, show_map_selector = function(e) e.map = nil e.label:set_pos(e.pos +vector.new(0, 2, 0.3):rotate(e.rot)) e.label:set_properties { visual = "upright_sprite", textures = {"[combine:85x85:0,37.5=firefly_choose_map.png", "[combine:85x85:0,37.5=firefly_choose_map.png"}, visual_size = vector.new(1, 1, 1) *1 } e.map_previews = {} local pos = e.object:get_pos() for name, x in pairs(ns.modes[e.mode].maps) do local obj = minetest.add_entity(pos, "firefly:map_preview") obj:set_properties { mesh = x.preview } local le = obj:get_luaentity() le.master = e le.map = name e.map_previews[name] = le end end, set_map = function(e, map) if not e.map then e.confirm_map = minetest.add_entity(e.object:get_pos() +vector.new(2, 1, 0.3):rotate(e.rot), "display") e.confirm_map:set_properties { visual = "upright_sprite", textures = {"[combine:85x85:0,37.5=firefly_choose_map.png", "[combine:85x85:0,37.5=firefly_choose_map.png"}, visual_size = vector.new(1, 1, 1) *1, pointable = true } e.confirm_map = e.confirm_map:get_luaentity() e.confirm_map.on_punch = function() e:dismiss_map_selector() e.state = "awaiting_players" e:show_players() end end e.map_image = minetest.add_entity(e.object:get_pos() +vector.new(0, 1, 0.35):rotate(e.rot), "display") e.map_image:set_properties { visual = "upright_sprite", textures = {"firefly_battle_map_test.png"}, visual_size = vector.new(4.5, 2.5, 5) *0.98, pointable = true } e.map_image = e.map_image:get_luaentity() e.map = map end, dismiss_map_selector = function(e) for _, x in pairs(e.map_previews) do x:dismiss() end e.map_previews = nil if e.confirm_map then e.confirm_map.object:remove() e.confirm_map = nil end end, show_players = function(e) e.label:set_pos(e.pos +vector.new(0, 2, 0.3):rotate(e.rot)) e.label:set_properties { visual = "upright_sprite", textures = {"[combine:94x94:0,42=firefly_punch_to_join.png", "[combine:94x94:0,42=firefly_punch_to_join.png"}, visual_size = vector.new(1, 1, 1) *2 } local pos = e.object:get_pos() +vector.new(-#e.players_list /2 +0.5, 1, 0.3):rotate(e.rot) for i = 1, #e.players_list do local name = e.players_list[i] local obj = minetest.add_entity(pos +vector.new(0.5 *(i -1), 0, 0):rotate(e.rot), "display") obj:set_properties { visual = "mesh", mesh = "firefly_head.gltf", visual_size = vector.new(1, 1, 1) *0.5, textures = {"firefly_character.png"} } obj:set_rotation(e.rot:offset(0, -math.pi, 0)) e.players[name] = obj end e.begin_countdown = minetest.add_entity(pos +vector.new(2, 1, 0):rotate(e.rot), "display") e.begin_countdown:set_properties { visual = "upright_sprite", textures = {"[combine:85x85:0,37.5=firefly_choose_map.png", "[combine:85x85:0,37.5=firefly_choose_map.png"}, visual_size = vector.new(1, 1, 1) *1, pointable = true } e.begin_countdown = e.begin_countdown:get_luaentity() e.begin_countdown.on_punch = function() e:dismiss_players() e.state = "starting" e.timer = 10 e:show_countdown() end end, dismiss_players = function(e) for _, x in pairs(e.players) do x:remove() end e.begin_countdown.object:remove() e.begin_countdown = nil end, show_countdown = function(e) local pos = e.object:get_pos() e.timer_display = minetest.add_entity(pos +vector.new(0, 1, 0.3):rotate(e.rot), "display") e.timer_display:set_properties { visual = "upright_sprite", } e.timer_display:set_rotation(e.rot) end, dismiss_countdown = function(e) e.timer_display:remove() e.timer_display = nil end, start_game = function(e) e.timer = nil e.state = nil e:dismiss_countdown() for i = 1, #e.players_list do ns.remove_hud_bar(ns.players[e.players_list[i]], "start_timer") end ns.start_game(e.mode, e.map, e.players_list) e.players_list = {} e:show_status() end, on_punch = function(e, p) local name = p:get_player_name() local m = ns.players[name] if not e.state then m.hosting = e e:add_player(name) e.state = "choose_map" e:show_map_selector() elseif e.state == "awaiting_players" or e.state == "starting" then if e.players[name] then e:remove_player(name) else e:add_player(name) end end -- if e.players[name] then -- e.players[name]:remove() -- e.players[name] = nil -- table.remove(e.players_list, table.indexof(e.players_list, name)) -- ns.remove_hud_bar(ns.players[name], "start_timer") -- if not next(e.players_list) then -- e.label:set_pos(e.label:get_pos():offset(0, -0.25, 0)) -- e.label:set_properties { -- visual = "upright_sprite", -- textures = {"[combine:102x102:0,46=firefly_punch_to_start.png", "[combine:102x102:0,46=firefly_punch_to_start.png"}, -- } -- e.timer_display:remove() -- e.timer_display = nil -- end -- else -- if not next(e.players_list) then -- e.label:set_pos(e.label:get_pos():offset(0, 0.25, 0)) -- e.label:set_properties { -- visual = "upright_sprite", -- textures = {"[combine:94x94:0,42=firefly_punch_to_join.png", "[combine:94x94:0,42=firefly_punch_to_join.png"}, -- } -- e.timer_display = minetest.add_entity(e.object:get_pos():offset(0, 0.85, 0), "display") -- e.timer_display:set_properties { -- visual = "upright_sprite", -- } -- e.timer_display:set_rotation(e.rot) -- end -- local display = minetest.add_entity(e.object:get_pos():offset(0, 0, 0), "display") -- display:set_properties { -- visual = "mesh", -- mesh = "firefly_head.gltf", -- textures = ns.players[name].object:get_properties().textures, -- visual_size = vector.new(1,1,1) *0.5 -- } -- display:set_rotation(e.rot) -- e.players[name] = display -- table.insert(e.players_list, name) -- e.timer = math.max(5, 11 -(#e.players_list)^2) -- e._timer = e.timer -- ns.add_hud_bar(ns.players[name], "start_timer", { -- max = e.timer, -- value = e.timer, -- title = "Starting in "..e._timer.."..." -- }) -- end end, get_staticdata = function(e) return e.mode end, on_deactivate = function(e) local pos = e.object:get_pos():round() game_makers[pos:to_string()] = nil e.label:remove() if e.timer_display then e.timer_display:remove() end end }) Player:listen("deinit", function(m) if m.hosting then m.hosting:remove_player(m.name) elseif m.joining then m.joining:remove_player(m.name) end end) function ns.register_game_maker(name, def) local function onload(pos) minetest.add_entity(pos, "firefly:game_maker_display", def.mode) end ns.register_node("game_maker_"..name, { drawtype = "mesh", mesh = "firefly_screen.gltf", tiles = {"firefly_screen.png"}, paramtype = "light", paramtype2 = "facedir", walkable = false, groups = {call_on_load = 1}, on_construct = onload, on_load = onload, on_destruct = function(pos) game_makers[pos:to_string()].object:remove() end, }) end