From 29a1b97b3849daaf07e2d3789b54817101e9061c Mon Sep 17 00:00:00 2001
From: rubenwardy <rw@rubenwardy.com>
Date: Thu, 13 Sep 2018 17:31:58 +0100
Subject: Improve code structure and awards formspec size

---
 src/api_triggers.lua | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)
 create mode 100644 src/api_triggers.lua

(limited to 'src/api_triggers.lua')

diff --git a/src/api_triggers.lua b/src/api_triggers.lua
new file mode 100644
index 0000000..9311bcf
--- /dev/null
+++ b/src/api_triggers.lua
@@ -0,0 +1,215 @@
+-- Copyright (c) 2013-18 rubenwardy. MIT.
+
+local S, NS = awards.gettext, awards.ngettext
+
+awards.registered_awards = {}
+awards.on = {}
+awards.on_unlock = {}
+
+local default_def = {}
+
+function default_def:run_callbacks(player, data, table_func)
+	for i = 1, #self.on do
+		local res = nil
+		local entry = self.on[i]
+		if type(entry) == "function" then
+			res = entry(player, data)
+		elseif type(entry) == "table" and entry.award then
+			res = table_func(entry)
+		end
+
+		if res then
+			awards.unlock(player:get_player_name(), res)
+		end
+	end
+end
+
+function awards.register_trigger(tname, tdef)
+	assert(type(tdef) == "table",
+			"Passing a callback to register_trigger is not supported in 3.0")
+
+	tdef.name = tname
+	for key, value in pairs(default_def) do
+		tdef[key] = value
+	end
+
+	if tdef.type == "counted" then
+		local old_reg = tdef.on_register
+
+		function tdef:on_register(def)
+			local tmp = {
+				award  = def.name,
+				target = def.trigger.target,
+			}
+			tdef.register(tmp)
+
+			function def.getProgress(_, data)
+				local done = data[tname] or 0
+				return {
+					perc = done / tmp.target,
+					label = S(tdef.progress, done, tmp.target),
+				}
+			end
+
+			function def.getDefaultDescription(_)
+				local n = def.trigger.target
+				return NS(tdef.auto_description[1], tdef.auto_description[2], n, n)
+			end
+
+			if old_reg then
+				return old_reg(tdef, def)
+			end
+		end
+
+		function tdef.notify(player)
+			assert(player and player.is_player and player:is_player())
+			local name = player:get_player_name()
+			local data = awards.player(name)
+
+			-- Increment counter
+			local currentVal = (data[tname] or 0) + 1
+			data[tname] = currentVal
+
+			tdef:run_callbacks(player, data, function(entry)
+				if entry.target and entry.award and currentVal and
+						currentVal >= entry.target then
+					return entry.award
+				end
+			end)
+		end
+
+		awards["notify_" .. tname] = tdef.notify
+
+	elseif tdef.type == "counted_key" then
+		if tdef.key_is_item then
+			tdef.watched_groups = {}
+		end
+
+		-- On award register
+		local old_reg = tdef.on_register
+		function tdef:on_register(def)
+			-- Register trigger
+			local tmp = {
+				award  = def.name,
+				key    = tdef:get_key(def),
+				target = def.trigger.target,
+			}
+			tdef.register(tmp)
+
+			-- If group, add it to watch list
+			if tdef.key_is_item and tmp.key and tmp.key:sub(1, 6) == "group:" then
+				tdef.watched_groups[tmp.key:sub(7, #tmp.key)] = true
+			end
+
+			-- Called to get progress values and labels
+			function def.getProgress(_, data)
+				local done
+				data[tname] = data[tname] or {}
+				if tmp.key then
+					done = data[tname][tmp.key] or 0
+				else
+					done = data[tname].__total or 0
+				end
+				return {
+					perc = done / tmp.target,
+					label = S(tdef.progress, done, tmp.target),
+				}
+			end
+
+			-- Build description if none is specificed by the award
+			function def.getDefaultDescription(_)
+				local n = def.trigger.target
+				if tmp.key then
+					local nname = tmp.key
+					return NS(tdef.auto_description[1],
+							tdef.auto_description[2], n, n, nname)
+				else
+					return NS(tdef.auto_description_total[1],
+							tdef.auto_description_total[2], n, n)
+				end
+			end
+
+			-- Call on_register in trigger type definition
+			if old_reg then
+				return old_reg(tdef, def)
+			end
+		end
+
+		function tdef.notify(player, key, n)
+			n = n or 1
+
+			if tdef.key_is_item and key:sub(1, 6) ~= "group:" then
+				local itemdef = minetest.registered_items[key]
+				if itemdef then
+					for groupname, _ in pairs(itemdef.groups or {}) do
+						if tdef.watched_groups[groupname] then
+							tdef.notify(player, "group:" .. groupname, n)
+						end
+					end
+				end
+			end
+
+			assert(player and player.is_player and player:is_player() and key)
+			local name = player:get_player_name()
+			local data = awards.player(name)
+
+			-- Increment counter
+			data[tname] = data[tname] or {}
+			local currentVal = (data[tname][key] or 0) + n
+			data[tname][key] = currentVal
+			if key:sub(1, 6) ~= "group:" then
+				data[tname].__total = (data[tname].__total or 0) + n
+			end
+
+			tdef:run_callbacks(player, data, function(entry)
+				local current
+				if entry.key == key then
+					current = currentVal
+				elseif entry.key == nil then
+					current = data[tname].__total
+				else
+					return
+				end
+
+				if current >= entry.target then
+					return entry.award
+				end
+			end)
+		end
+
+		awards["notify_" .. tname] = tdef.notify
+
+	elseif tdef.type and tdef.type ~= "custom" then
+		error("Unrecognised trigger type " .. tdef.type)
+	end
+
+	awards.registered_triggers[tname] = tdef
+
+	tdef.on = {}
+	tdef.register = function(func)
+		table.insert(tdef.on, func)
+	end
+
+	-- Backwards compat
+	awards.on[tname] = tdef.on
+	awards['register_on_' .. tname] = tdef.register
+	return tdef
+end
+
+function awards.increment_item_counter(data, field, itemname, count)
+	itemname = minetest.registered_aliases[itemname] or itemname
+	data[field][itemname] = (data[field][itemname] or 0) + 1
+end
+
+function awards.get_item_count(data, field, itemname)
+	itemname = minetest.registered_aliases[itemname] or itemname
+	return data[field][itemname] or 0
+end
+
+function awards.get_total_keyed_count(data, field)
+	return data[field].__total or 0
+end
+
+function awards.register_on_unlock(func)
+	table.insert(awards.on_unlock, func)
+end
-- 
cgit v1.2.3