-- indiedev.games game events and leaderboards for Defold. -- -- Put this file in your project (for example as indiedev.lua), then use it from any script: -- -- local indiedev = require("indiedev") -- indiedev.event("level_complete") -- indiedev.event("level_time", 83.5) -- an optional number, such as a score or a time in seconds -- -- Leaderboards (beta). Set the board up first on your Game Analytics page, then: -- -- indiedev.submit_score("high_scores", "AVA", 1200, function(result) end) -- indiedev.load_leaderboard("high_scores", function(result) end, 10) -- -- result.ok, result.rank (after a submit), result.entries = { { rank = 1, name = "AVA", score = 1200 } } -- -- Answers arrive later, so call indiedev.update() from the update() function of any script that runs all the time: -- -- function update(self, dt) -- indiedev.update() -- end -- -- It talks to the indiedev.games page the game runs in, and does nothing outside an HTML5 build. -- Only the name and the number are sent. See https://indiedev.games/help/game-events-godot-defold -- and https://indiedev.games/help/game-leaderboards local M = {} local pending = {} local next_id = 1 local installed = false function M.event(name, value) if not html5 then return end local message = { indiedev = 1, type = "event", name = name } if type(value) == "number" and value == value and value ~= math.huge and value ~= -math.huge then message.value = value end html5.run("window.parent.postMessage(" .. json.encode(message) .. ", '*')") end local function install() if installed then return end installed = true html5.run("if (!window.indiedevResults) { window.indiedevResults = {}; window.addEventListener('message', function (e) { var d = e.data; if (d && d.indiedev === 1 && d.type === 'scores') { window.indiedevResults[d.id] = JSON.stringify(d); } }); }") end local function ask(message, callback) if not html5 then if callback then callback({ ok = false, error = "not_html5", entries = {} }) end return end install() message.indiedev = 1 message.id = next_id pending[next_id] = callback or function() end next_id = next_id + 1 html5.run("window.parent.postMessage(" .. json.encode(message) .. ", '*')") end -- The player's name is shown to everyone: 1 to 12 letters, digits, spaces, dashes or underscores. Never use a real name. function M.submit_score(board, player_name, score, callback) ask({ type = "score", board = board, name = player_name, score = score }, callback) end function M.load_leaderboard(board, callback, limit) ask({ type = "leaderboard", board = board, limit = limit or 10 }, callback) end -- Hands the answers that arrived to their callbacks. Call it from a script's update(). function M.update() if not html5 or next(pending) == nil then return end for id, callback in pairs(pending) do local text = html5.run("(function () { var r = window.indiedevResults['" .. id .. "']; if (r === undefined) { return ''; } delete window.indiedevResults['" .. id .. "']; return r; })()") if text and text ~= "" then pending[id] = nil callback(json.decode(text)) end end end return M