14 Commits

Author SHA1 Message Date
4f5260da5f Corrige la commande /awards.
Corrige l'affige des awards d'un joueur donné.
Empêche le retour de l'inventaire sfinv quand on active ou desactive
les awards d'un joueur.
2019-03-03 22:40:11 +01:00
89d4a93f3b Ajoute le privilège awards_admin
Modifie la commande /awards en conséquence
2019-03-03 13:24:28 +01:00
cae2c1ee3b Tente la correction d'un crash 2019-03-02 21:08:02 +01:00
54db6ce0c0 Suppression de minetest.register_on_craft
Cette fonction a été réécrite dans nalc_awards
2019-03-02 19:49:08 +01:00
Max
1ffa8f10ac Add missing german translations 2019-01-26 15:26:53 +00:00
fb1670abc6 Fix typo in documentation for craft trigger 2018-09-14 10:59:59 +01:00
38b7d9aa91 Fix progress exceeding target 2018-09-14 10:55:55 +01:00
805720b4af Fix sfinv page not updating on award unlock 2018-09-13 17:39:52 +01:00
29a1b97b38 Improve code structure and awards formspec size 2018-09-13 17:33:04 +01:00
b856aea54d Fix typo in custom trigger type example 2018-08-22 15:26:24 +01:00
570fd3a206 Fix incorrect description documentation 2018-08-22 15:19:38 +01:00
417ac0fe46 Fix mistakes in award definition documentation 2018-08-22 15:17:14 +01:00
1ab08d68c9 Add portuguese translations 2018-08-03 12:35:18 +01:00
32150bdd66 Fix crash for invalid award index selection 2018-07-15 13:17:06 +01:00
14 changed files with 1523 additions and 690 deletions

View File

@ -7,25 +7,6 @@ With thanks to Wuzzy, kaeza, and MrIbby.
Majority of awards are back ported from Calinou's old fork in Carbone, under same license. Majority of awards are back ported from Calinou's old fork in Carbone, under same license.
# Introduction # Introduction
@ -141,7 +122,7 @@ Here's an example.
```lua ```lua
awards.register_trigger("foo", { awards.register_trigger("foo", {
type = "counted", type = "custom",
progress = "@1/@2 foos", progress = "@1/@2 foos",
auto_description = { "Do a foo", "Foo @1 times" }, auto_description = { "Do a foo", "Foo @1 times" },
}) })
@ -188,13 +169,16 @@ end
# API # API
* awards.register_award(name, def), the def table has the following fields: * awards.register_award(name, def), the def table has the following fields:
* `description` - the title of the award. Required. * `title` - title of the award (defaults to name)
* `description` - longer description of the award, displayed in Awards tab
* `difficulty` - see [Award Difficulty](#award-difficulty). * `difficulty` - see [Award Difficulty](#award-difficulty).
* `requires` - list of awards that need to be unlocked before this one * `requires` - list of awards that need to be unlocked before this one
is visible. is visible.
* `prizes` - list of items to give when you earn the award
* `secret` - boolean if this award is secret (i.e. showed on awards list)
* `sound` - `SimpleSoundSpec` table to play on unlock. * `sound` - `SimpleSoundSpec` table to play on unlock.
`false` to disable unlock sound. `false` to disable unlock sound.
* `image` - the icon image, use default otherwise. * `icon` - the icon image, use default otherwise.
* `background` - the background image, use default otherwise. * `background` - the background image, use default otherwise.
* `trigger` - trigger definition, see [Builtin Trigger Types](#builtin-trigger-types). * `trigger` - trigger definition, see [Builtin Trigger Types](#builtin-trigger-types).
* `on_unlock(name, def)` - callback on unlock. * `on_unlock(name, def)` - callback on unlock.
@ -267,7 +251,7 @@ trigger = {
```lua ```lua
trigger = { trigger = {
type = "craft", type = "craft",
node = "default:dirt", -- item, alias, or group item = "default:dirt", -- item, alias, or group
target = 50, target = 50,
} }
``` ```

529
api.lua
View File

@ -1,529 +0,0 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
local S, NS = awards.gettext, awards.ngettext
awards.registered_awards = {}
awards.on = {}
awards.on_unlock = {}
local storage = minetest.get_mod_storage()
-- Table Save Load Functions
function awards.save()
storage:set_string("player_data", minetest.write_json(awards.players))
end
local function convert_data()
minetest.log("warning", "Importing awards data from previous version")
local old_players = awards.players
awards.players = {}
for name, data in pairs(old_players) do
while name.name do
name = name.name
end
data.name = name
print("Converting data for " .. name)
-- Just rename counted
local counted = {
chats = "chat",
deaths = "death",
joins = "join",
}
for from, to in pairs(counted) do
data[to] = data[from]
data[from] = nil
end
data.death = {
unknown = data.death,
__total = data.death,
}
-- Convert item db to new format
local counted_items = {
count = "dig",
place = "place",
craft = "craft",
}
for from, to in pairs(counted_items) do
local ret = {}
local count = 0
if data[from] then
for modname, items in pairs(data[from]) do
for itemname, value in pairs(items) do
itemname = modname .. ":" .. itemname
local key = minetest.registered_aliases[itemname] or itemname
ret[key] = value
count = count + value
end
end
end
ret.__total = count
data[from] = nil
data[to] = ret
end
awards.players[name] = data
end
end
function awards.load()
local old_save_path = minetest.get_worldpath().."/awards.txt"
local file = io.open(old_save_path, "r")
if file then
local table = minetest.deserialize(file:read("*all"))
if type(table) == "table" then
awards.players = table
convert_data()
else
awards.players = {}
end
file:close()
os.rename(old_save_path, minetest.get_worldpath().."/awards.bk.txt")
awards.save()
else
awards.players = minetest.parse_json(storage:get_string("player_data")) or {}
end
end
function awards.player(name)
assert(type(name) == "string")
local data = awards.players[name] or {}
awards.players[name] = data
data.name = data.name or name
data.unlocked = data.unlocked or {}
return data
end
function awards.player_or_nil(name)
return awards.players[name]
end
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
function awards.register_award(name, def)
def.name = name
-- Add Triggers
if def.trigger and def.trigger.type then
local tdef = awards.registered_triggers[def.trigger.type]
assert(tdef, "Trigger not found: " .. def.trigger.type)
tdef:on_register(def)
end
function def:can_unlock(data)
if not self.requires then
return true
end
for i=1, #self.requires do
if not data.unlocked[self.requires[i]] then
return false
end
end
return true
end
-- Add Award
awards.registered_awards[name] = def
local tdef = awards.registered_awards[name]
if def.description == nil and tdef.getDefaultDescription then
def.description = tdef:getDefaultDescription()
end
end
function awards.enable(name)
local data = awards.player(name)
if data then
data.disabled = nil
end
end
function awards.disable(name)
local data = awards.player(name)
if data then
data.disabled = true
end
end
function awards.clear_player(name)
awards.players[name] = {}
end
-- This function is called whenever a target condition is met.
-- It checks if a player already has that award, and if they do not,
-- it gives it to them
----------------------------------------------
--awards.unlock(name, award)
-- name - the name of the player
-- award - the name of the award to give
function awards.unlock(name, award)
-- Access Player Data
local data = awards.player(name)
local awdef = awards.registered_awards[award]
assert(awdef, "Unable to unlock an award which doesn't exist!")
if data.disabled or
(data.unlocked[award] and data.unlocked[award] == award) then
return
end
if not awdef:can_unlock(data) then
minetest.log("warning", "can_unlock returned false in unlock of " ..
award .. " for " .. name)
return
end
-- Unlock Award
minetest.log("action", name.." has unlocked award "..name)
data.unlocked[award] = award
awards.save()
-- Give Prizes
if awdef and awdef.prizes then
for i = 1, #awdef.prizes do
local itemstack = ItemStack(awdef.prizes[i])
if not itemstack:is_empty() then
local receiverref = minetest.get_player_by_name(name)
if receiverref then
receiverref:get_inventory():add_item("main", itemstack)
end
end
end
end
-- Run callbacks
if awdef.on_unlock and awdef.on_unlock(name, awdef) then
return
end
for _, callback in pairs(awards.on_unlock) do
if callback(name, awdef) then
return
end
end
-- Get Notification Settings
local title = awdef.title or award
local desc = awdef.description or ""
local background = awdef.background or "awards_bg_default.png"
local icon = awdef.icon or "awards_unknown.png"
local sound = awdef.sound
if sound == nil then
-- Explicit check for nil because sound could be `false` to disable it
sound = {name="awards_got_generic", gain=0.25}
end
-- Do Notification
if sound then
-- Enforce sound delay to prevent sound spamming
local lastsound = data.lastsound
if lastsound == nil or os.difftime(os.time(), lastsound) >= 1 then
minetest.sound_play(sound, {to_player=name})
data.lastsound = os.time()
end
end
if awards.show_mode == "chat" then
local chat_announce
if awdef.secret then
chat_announce = S("Secret Award Unlocked: %s")
else
chat_announce = S("Award Unlocked: %s")
end
-- use the chat console to send it
minetest.chat_send_player(name, string.format(chat_announce, title))
if desc~="" then
minetest.chat_send_player(name, desc)
end
else
local player = minetest.get_player_by_name(name)
local one = player:hud_add({
hud_elem_type = "image",
name = "award_bg",
scale = {x = 2, y = 1},
text = background,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 138},
alignment = {x = 0, y = -1}
})
local hud_announce
if awdef.secret then
hud_announce = S("Secret Award Unlocked!")
else
hud_announce = S("Award Unlocked!")
end
local two = player:hud_add({
hud_elem_type = "text",
name = "award_au",
number = 0xFFFFFF,
scale = {x = 100, y = 20},
text = hud_announce,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 45},
alignment = {x = 0, y = -1}
})
local three = player:hud_add({
hud_elem_type = "text",
name = "award_title",
number = 0xFFFFFF,
scale = {x = 100, y = 20},
text = title,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 100},
alignment = {x = 0, y = -1}
})
local four = player:hud_add({
hud_elem_type = "image",
name = "award_icon",
scale = {x = 4, y = 4},
text = icon,
position = {x = 0.5, y = 0.05},
offset = {x = -200.5, y = 126},
alignment = {x = 0, y = -1}
})
minetest.after(4, function()
local player2 = minetest.get_player_by_name(name)
if player2 then
player2:hud_remove(one)
player2:hud_remove(two)
player2:hud_remove(three)
player2:hud_remove(four)
end
end)
end
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "awards:awards" then
return false
end
if fields.quit then
return true
end
local name = player:get_player_name()
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
awards.show_to(name, name, event.index, false)
end
end
return true
end)
awards.load()
minetest.register_on_shutdown(function()
awards.save()
end)

View File

@ -1,61 +0,0 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
local S = awards.gettext
minetest.register_chatcommand("awards", {
params = S("[c|clear|disable|enable]"),
description = S("Show, clear, disable or enable your awards"),
func = function(name, param)
if param == "clear" then
awards.clear_player(name)
minetest.chat_send_player(name,
S("All your awards and statistics have been cleared. You can now start again."))
elseif param == "disable" then
awards.disable(name)
minetest.chat_send_player(name, S("You have disabled awards."))
elseif param == "enable" then
awards.enable(name)
minetest.chat_send_player(name, S("You have enabled awards."))
elseif param == "c" then
awards.show_to(name, name, nil, true)
else
awards.show_to(name, name, nil, false)
end
if (param == "disable" or param == "enable") and minetest.global_exists("sfinv") then
local player = minetest.get_player_by_name(name)
if player then
sfinv.set_player_inventory_formspec(player)
end
end
end
})
minetest.register_chatcommand("awd", {
params = S("<award ID>"),
description = S("Show details of an award"),
func = function(name, param)
local def = awards.registered_awards[param]
if def then
minetest.chat_send_player(name, string.format(S("%s: %s"), def.title, def.description))
else
minetest.chat_send_player(name, S("Award not found."))
end
end
})
minetest.register_chatcommand("awpl", {
privs = {
server = true
},
params = S("<name>"),
description = S("Get the awards statistics for the given player or yourself"),
func = function(name, param)
if not param or param == "" then
param = name
end
minetest.chat_send_player(name, param)
local player = awards.player(param)
minetest.chat_send_player(name, dump(player))
end
})

View File

@ -7,14 +7,20 @@ awards = {
} }
-- Internationalization support. -- Internationalization support.
awards.gettext, awards.ngettext = dofile(minetest.get_modpath("awards").."/intllib.lua") awards.gettext, awards.ngettext = dofile(minetest.get_modpath("awards").."/src/intllib.lua")
-- Load files -- Load files
dofile(minetest.get_modpath("awards").."/api.lua") dofile(minetest.get_modpath("awards").."/src/data.lua")
dofile(minetest.get_modpath("awards").."/chat_commands.lua") dofile(minetest.get_modpath("awards").."/src/api_awards.lua")
dofile(minetest.get_modpath("awards").."/gui.lua") dofile(minetest.get_modpath("awards").."/src/api_triggers.lua")
dofile(minetest.get_modpath("awards").."/triggers.lua") dofile(minetest.get_modpath("awards").."/src/chat_commands.lua")
dofile(minetest.get_modpath("awards").."/awards.lua") dofile(minetest.get_modpath("awards").."/src/gui.lua")
dofile(minetest.get_modpath("awards").."/src/triggers.lua")
dofile(minetest.get_modpath("awards").."/src/awards.lua")
awards.load()
minetest.register_on_shutdown(awards.save)
-- Backwards compatibility -- Backwards compatibility
awards.give_achievement = awards.unlock awards.give_achievement = awards.unlock

View File

@ -102,8 +102,8 @@ msgstr[1] "Bauen Sie Blöcke ab: @1×@2"
#: triggers.lua #: triggers.lua
msgid "Mine @1 block." msgid "Mine @1 block."
msgid_plural "Mine @1 blocks." msgid_plural "Mine @1 blocks."
msgstr[0] "" msgstr[0] "Bauen Sie einen @1 Block ab."
msgstr[1] "" msgstr[1] "Bauen Sie @1 Blöcke ab."
#: triggers.lua #: triggers.lua
msgid "@1/@2 placed" msgid "@1/@2 placed"
@ -119,8 +119,8 @@ msgstr[1] "Platzieren Sie Blöcke: @1×@2"
#: triggers.lua #: triggers.lua
msgid "Place a block." msgid "Place a block."
msgid_plural "Place @1 blocks." msgid_plural "Place @1 blocks."
msgstr[0] "" msgstr[0] "Platzieren Sie einen Block."
msgstr[1] "" msgstr[1] "Platzieren Sie @1 Blöcke."
#: triggers.lua #: triggers.lua
msgid "@1/@2 eaten" msgid "@1/@2 eaten"
@ -151,13 +151,13 @@ msgstr[1] "Sterben Sie @1 mal."
#: triggers.lua #: triggers.lua
msgid "@1/@2 chat messages" msgid "@1/@2 chat messages"
msgstr "" msgstr "@1/@2 Chatnachrichten"
#: triggers.lua #: triggers.lua
msgid "Write something in chat." msgid "Write something in chat."
msgid_plural "Write @1 chat messages." msgid_plural "Write @1 chat messages."
msgstr[0] "" msgstr[0] "Schreiben Sie etwas im Chat."
msgstr[1] "" msgstr[1] "Schreiben Sie @1 Chatnachrichten."
#: triggers.lua #: triggers.lua
msgid "@1/@2 game joins" msgid "@1/@2 game joins"

819
locale/pt.po Normal file
View File

@ -0,0 +1,819 @@
# Portuguese translations for Awards package.
# Copyright (C) 2018
# This file is distributed under the same license as the Awards package.
# FIRST AUTHOR borgesdossantosbruno@gmail.com, 2018.
# BrunoMine, 2018
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-21 05:50-0300\n"
"PO-Revision-Date: 2018-08-01 16:16-0300\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.6\n"
"Last-Translator: BrunoMine\n"
"Language: pt\n"
#: api.lua
msgid "Secret Achievement Unlocked:"
msgstr "Conquista Secreta Desbloqueada:"
#: api.lua
msgid "Achievement Unlocked:"
msgstr "Conquista Desbloqueada:"
#: api.lua
#, lua-format
msgid "Secret Achievement Unlocked: %s"
msgstr "Conquista Secreta Desbloqueada: %s"
#: api.lua
#, lua-format
msgid "Achievement Unlocked: %s"
msgstr "Conquista Desbloqueada: %s"
#: api.lua
msgid "Secret Achievement Unlocked!"
msgstr "Conquista Secreta Desbloqueada!"
#: api.lua
msgid "Achievement Unlocked!"
msgstr "Conquista Desbloqueada!"
#: api.lua
msgid "Error: No awards available."
msgstr "Erro: Nenhuma conquista encontrada."
#: api.lua
msgid "OK"
msgstr "OK"
#: api.lua
msgid "(Secret Award)"
msgstr "(Conquista Secreta)"
#: api.lua
msgid "Unlock this award to find out what it is."
msgstr "Desbloqueie essa conquista para descobrir o que significa."
#: api.lua
#, lua-format
msgid "%s (got)"
msgstr "%s (obtido)"
#: api.lua
msgid "You've disabled awards. Type /awards enable to reenable."
msgstr "Desabilitaste as conquistas. Digite /awards enable para reabilitar."
#: api.lua
msgid "You have not unlocked any awards."
msgstr "Nenhuma conquista desbloqueada ainda."
#: api.lua
#, lua-format
msgid "%ss awards:"
msgstr "%s das conquistas:"
#: api.lua chat_commands.lua
#, lua-format
msgid "%s: %s"
msgstr "%s: %s"
#: sfinv.lua unified_inventory.lua
msgid "Awards"
msgstr "Conquistas"
#: triggers.lua
msgid "@1/@2 dug"
msgstr "@1 de @2 obtidos"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Mine: @2"
msgid_plural "Mine: @1×@2"
msgstr[0] "Cavar: @2"
msgstr[1] "Minar: @1×@2"
#: triggers.lua
msgid "Mine @1 block."
msgid_plural "Mine @1 blocks."
msgstr[0] "Cavar um bloco."
msgstr[1] "Cavar @1 blocos."
#: triggers.lua
msgid "@1/@2 placed"
msgstr "@1 de @2 colocados"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Place: @2"
msgid_plural "Place: @1×@2"
msgstr[0] "Colocar: @2"
msgstr[1] "Place: @1×@2"
#: triggers.lua
msgid "Place a block."
msgid_plural "Place @1 blocks."
msgstr[0] "Colocar um bloco."
msgstr[1] "Colocar @1 blocos."
#: triggers.lua
msgid "@1/@2 eaten"
msgstr "@1 de @2 consumidos"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Eat: @2"
msgid_plural "Eat: @1×@2"
msgstr[0] "Consumir: @2"
msgstr[1] "Consumir: @1×@2"
#: triggers.lua
msgid "Eat an item."
msgid_plural "Eat @1 items."
msgstr[0] "Consumir um item."
msgstr[1] "Consumir @1 itens."
#: triggers.lua
msgid "@1/@2 deaths"
msgstr "@1 de @2 mortes"
#: triggers.lua
msgid "Die."
msgid_plural "Die @1 times."
msgstr[0] "Morrer."
msgstr[1] "Morrer @1 vezes."
#: triggers.lua
msgid "@1/@2 chat messages"
msgstr "@1 de @2"
#: triggers.lua
msgid "Write something in chat."
msgid_plural "Write @1 chat messages."
msgstr[0] "Escrever algo no bate papo."
msgstr[1] "Escrever @1 mensagens no bate papo."
#: triggers.lua
msgid "@1/@2 game joins"
msgstr "@1 de @2"
#: triggers.lua
msgid "Join the game."
msgid_plural "Join the game @1 times."
msgstr[0] "Entre no jogo."
msgstr[1] "Entre no jogo @1 vezes."
#: triggers.lua
msgid "@1/@2 crafted"
msgstr "@1 de @2 feitos"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Craft: @2"
msgid_plural "Craft: @1×@2"
msgstr[0] "Fazer @2"
msgstr[1] "Montar @2 @1 vezes"
#: triggers.lua
msgid "Craft an item."
msgid_plural "Craft @1 items."
msgstr[0] "Fazer um item."
msgstr[1] "Fazer @1 itens."
#: init.lua
msgid "Saint-Maclou"
msgstr "Saint-Maclou"
#: init.lua
msgid "Place 20 coal checkers."
msgstr ""
#: init.lua
msgid "Castorama"
msgstr ""
#: init.lua
msgid "Place 20 iron checkers."
msgstr ""
#: init.lua
msgid "Sam the Trapper"
msgstr ""
#: init.lua
msgid "Place 2 trap stones."
msgstr ""
#: init.lua
msgid "Backpacker"
msgstr ""
#: init.lua
msgid "Craft 4 large bags."
msgstr ""
#: init.lua
msgid "Pyromaniac"
msgstr "Piromaníaco"
#: init.lua
msgid "Craft 8 times flint and steel."
msgstr "Montar acendedor de Ferro e Pederneira 8 vezes."
#: init.lua
msgid "Firefighter"
msgstr "Bombeiro"
#: init.lua
msgid "Put out 1000 fires."
msgstr "Apagar fogo 1000 vezes."
#: init.lua
msgid "Light It Up"
msgstr "Ilumine Isso"
#: init.lua
msgid "Place 100 torches."
msgstr "Colocar 100 tochas."
#: init.lua
msgid "Well Lit"
msgstr "Bem Iluminado"
#: init.lua
msgid "Place 1,000 torches."
msgstr "Colocar 1.000 tochas."
#: init.lua
msgid "Really Well Lit"
msgstr "Realmente Bem Iluminado"
#: init.lua
msgid "Craft 10 mese lamps."
msgstr "Fazer 10 lâmpadas de mese."
#: init.lua
msgid "Outpost"
msgstr "Posto Avançado"
#: init.lua
msgid "Craft 200 stone bricks."
msgstr "Fazer 200 tijolos de pedra."
#: init.lua
msgid "Watchtower"
msgstr "Sentinela"
#: init.lua
msgid "Craft 800 stone bricks."
msgstr "Fazer 800 tijolos de pedra."
#: init.lua
msgid "Fortress"
msgstr "Fortaleza"
#: init.lua
msgid "Craft 3,200 stone bricks."
msgstr "Fazer 3.200 tijolos de pedra."
#: init.lua
msgid "Desert Dweller"
msgstr "Morador do Deserto"
#: init.lua
msgid "Craft 400 desert stone bricks."
msgstr "Fazer 400 Tijolos de pedra do deserto."
#: init.lua
msgid "Pharaoh"
msgstr "Faraó"
#: init.lua
msgid "Craft 100 sandstone bricks."
msgstr "Fazer 100 tijolos de arenito."
#: init.lua
msgid "Little Library"
msgstr "Pequena Biblioteca"
#: init.lua
msgid "Craft 7 bookshelves."
msgstr "Fazer 7 estantes de livros."
#: init.lua
msgid "Lava and Water"
msgstr "Lava e Água"
#: init.lua
msgid "Mine your first obsidian."
msgstr "Cavar sua primeira obsidiana."
#: init.lua
msgid "Obsessed with Obsidian"
msgstr "Obcecado por Obsidiana"
#: init.lua
msgid "Mine 50 obsidian."
msgstr "Minerar 50 obsidianas."
#: init.lua
msgid "Lava Miner"
msgstr "Minerador de Lava"
#: init.lua
msgid "Mine any block while being very close to lava."
msgstr "Minerar qualquer bloco enquanto estiver mergulhado em lava."
#: init.lua
msgid "On The Way"
msgstr "No Caminho"
#: init.lua
msgid "Place 100 rails."
msgstr "Colocar 100 trilhos."
#: init.lua
msgid "First Day in the Woods"
msgstr "Primeiro dia na Floresta"
#: init.lua
msgid "Dig 6 tree blocks."
msgstr "Cortar 6 blocos de árvore."
#: init.lua
msgid "Lumberjack"
msgstr "Lenhador"
#: init.lua
msgid "Dig 36 tree blocks."
msgstr "Cortar 36 blocos de árvore."
#: init.lua
msgid "Semi-pro Lumberjack"
msgstr "Lenhador Semi-Profissional"
#: init.lua
msgid "Dig 216 tree blocks."
msgstr "Cortar 216 blocos de árvore."
#: init.lua
msgid "Professional Lumberjack"
msgstr "Lenhador Profissional"
#: init.lua
msgid "Dig 1,296 tree blocks."
msgstr "Cortar 1.296 blocos de árvore."
#: init.lua
msgid "Junglebaby"
msgstr "Bebê Selvagem"
#: init.lua
msgid "Dig 100 jungle tree blocks."
msgstr "Cortar 100 blocos de árvore selvagem."
#: init.lua
msgid "Jungleman"
msgstr "Homem Selvagem"
#: init.lua
msgid "Dig 1,000 jungle tree blocks."
msgstr "Cortar 1.000 blocos de árvore selvagem."
#: init.lua
msgid "First Mese Find"
msgstr "Primeiro Mese"
#: init.lua
msgid "Mine your first mese ore."
msgstr "Cavar seu primeiro mese."
#: init.lua
msgid "Mese Mastery"
msgstr "Mestre do Mese"
#: init.lua
msgid "Mine a mese block."
msgstr "Cavar um bloco de mese."
#: init.lua
msgid "Youre a copper"
msgstr "Sou um Cobre"
#: init.lua
msgid "Dig 1,000 copper ores."
msgstr "Minerar 1.000 cobres."
#: init.lua
msgid "A Cat in a Pop-Tart?!"
msgstr "Um Gato em um Pop-Tart?!"
#: init.lua
msgid "Mine a nyan cat."
msgstr "Capturar um gato nyan."
#: init.lua
msgid "Mini Miner"
msgstr "Mini Minerador"
#: init.lua
msgid "Dig 100 stone blocks."
msgstr "Minerar 100 blocos de pedra."
#: init.lua
msgid "Hardened Miner"
msgstr "Minerador Avançado"
#: init.lua
msgid "Dig 1,000 stone blocks."
msgstr "Minerar 1.000 blocos de pedra."
#: init.lua
msgid "Master Miner"
msgstr "Minerador Mestre"
#: init.lua
msgid "Dig 10,000 stone blocks."
msgstr "Minerar 10.000 blocos de pedra."
#: init.lua
msgid "Marchand De Sable"
msgstr "Vendedor de Areia"
#: init.lua
msgid "Dig 1,000 sand."
msgstr "Cavar 1.000 blocos de areia."
#: init.lua
msgid "Crafter of Sticks"
msgstr "Rachador de Lenha"
#: init.lua
msgid "Craft 100 sticks."
msgstr "Lenhar 100 gravetos."
#: init.lua
msgid "Jungle Discoverer"
msgstr "Desbravador Selvagem"
#: init.lua
msgid "Mine your first jungle grass."
msgstr "Cortar seu primeiro mato selvagem."
#: init.lua
msgid "Grasslands Discoverer"
msgstr "Descobridor do Gramado"
#: init.lua
msgid "Mine some grass."
msgstr "Minerar algum mato"
#: init.lua
msgid "Savannah Discoverer"
msgstr "Descobridor da Savana"
#: init.lua
msgid "Mine some dry grass."
msgstr "Minerar algum mato seco."
#: init.lua
msgid "Desert Discoverer"
msgstr "Descobridor do Deserto"
#: init.lua
msgid "Mine your first cactus."
msgstr "Cortar seu primeiro cacto."
#: init.lua
msgid "Far Lands"
msgstr "Terras Distantes"
#: init.lua
msgid "Mine your first dry shrub."
msgstr "Minerar seu primeiro arbusto seco."
#: init.lua
msgid "Glacier Discoverer"
msgstr "Descobridor Glacial"
#: init.lua
msgid "Mine your first ice."
msgstr "Quebrar seu primeiro bloco de gelo."
#: init.lua
msgid "Very Simple Snow Man"
msgstr "Homem de Neve Muito Simples"
#: init.lua
msgid "Place two snow blocks."
msgstr "Colocar 2 blocos de neve."
#: init.lua
msgid "First Gold Find"
msgstr "Achei Ouro"
#: init.lua
msgid "Mine your first gold ore."
msgstr "Minerar sua primeira de ouro."
#: init.lua
msgid "Gold Rush"
msgstr "Corriga do Ouro"
#: init.lua
msgid "Mine 45 gold ores."
msgstr "Minerar 45 de ouro."
#: init.lua
msgid "Wow, I am Diamonds!"
msgstr "Uau, Diamante!"
#: init.lua
msgid "Mine your first diamond ore."
msgstr "Minerar seu primeiro diamante."
#: init.lua
msgid "Girl's Best Friend"
msgstr "Melhor Amigo da Menina"
#: init.lua
msgid "Mine 18 diamond ores."
msgstr "Minere 18 diamantes."
#: init.lua
msgid "Hardest Block on Earth"
msgstr "O Bloco mais Duro da Terra"
#: init.lua
msgid "Craft a diamond block."
msgstr "Montar um bloco de diamante."
#: init.lua
msgid "In the Dungeon"
msgstr "Na Masmorra"
#: init.lua
msgid "Mine a mossy cobblestone."
msgstr "Minerar um pedregulho com musgo."
#: init.lua
msgid "Smelter"
msgstr "Fundidor"
#: init.lua
msgid "Craft 10 furnaces."
msgstr "Montar 10 fornos."
#: init.lua
msgid "Treasurer"
msgstr "Tesoureiro"
#: init.lua
msgid "Craft 15 chests."
msgstr "Montar 10 baús."
#: init.lua
msgid "Bankier"
msgstr "Banqueiro"
#: init.lua
msgid "Craft 30 locked chests."
msgstr "Montar 30 baús trancados."
#: init.lua
msgid "Bricker"
msgstr "Tijoleiro"
#: init.lua
msgid "Craft 200 brick blocks."
msgstr "Fazer 200 blocos de tijolo."
#: init.lua
msgid "House of Obsidian"
msgstr "Casa de Obsidiana"
#: init.lua
msgid "Craft 100 obsidian bricks."
msgstr "Montar 100 tijolos de obsidiana."
#: init.lua
msgid "Build a Cave"
msgstr "Montar uma Caverna"
#: init.lua
msgid "Place 100 stone."
msgstr "Colocar 100 pedras."
#: init.lua
msgid "Long Ladder"
msgstr "Longa Escadaria"
#: init.lua
msgid "Place 400 wooden ladders."
msgstr "Colocar 400 escadas de madeira."
#: init.lua
msgid "Industrial Age"
msgstr "Era Industrial"
#: init.lua
msgid "Place 40 steel ladders."
msgstr "Colocar 40 escadas de ferro."
#: init.lua
msgid "Yummy!"
msgstr "Humm!"
#: init.lua
msgid "Eat 80 apples."
msgstr "Comer 80 maçãs."
#: init.lua
msgid "Glasser"
msgstr "Vidraceiro"
#: init.lua
msgid "Craft 14 vessels shelves."
msgstr "Montar 14 estantes de frascos."
#: init.lua
msgid "Farming Skills Acquired"
msgstr "Conhecimento de Cultivo Adquirido"
#: init.lua
msgid "Harvest a fully grown wheat plant."
msgstr "Colher um trigo totalmente crescido."
#: init.lua
msgid "Field Worker"
msgstr "Trabalhador do Campo"
#: init.lua
msgid "Harvest 25 fully grown wheat plants."
msgstr "Colher 25 plantas trigos totalmente crescidos."
#: init.lua
msgid "Aspiring Farmer"
msgstr "Fazendeiro Aspirante"
#: init.lua
msgid "Harvest 125 fully grown wheat plants."
msgstr "Colher 125 plantas trigos totalmente crescidos."
#: init.lua
msgid "Wheat Magnate"
msgstr "Magnata do Trigo"
#: init.lua
msgid "Harvest 625 fully grown wheat plants."
msgstr "Colher 625 plantas trigos totalmente crescidos."
#: init.lua
msgid "Baker"
msgstr "Padeiro"
#: init.lua
msgid "Eat 10 loaves of bread."
msgstr "Comer 10 pães."
#: init.lua
msgid "Wool Over Your Eyes"
msgstr "Lã Sobre Meus Olhos"
#: init.lua
msgid "Craft 250 white wool."
msgstr "Tecer 250 lãs branca."
#: init.lua
msgid "Hotelier"
msgstr "Hoteleiro"
#: init.lua
msgid "Craft 15 fancy beds."
msgstr "Montar 15 camas chiques."
#: init.lua
msgid "Filthy Rich"
msgstr "Muito Rico"
#: init.lua
msgid "Craft 24 gold block stairs."
msgstr "Montar 24 escadas de bloco de ouro."
#: init.lua
msgid "Roses Are Red"
msgstr "Rosas São Vermelhas"
#: init.lua
msgid "Craft 400 red dyes."
msgstr "Fazer 400 tintas vermelhas."
#: init.lua
msgid "Dandelions are Yellow"
msgstr "Dentes-de-Leões são Amarelos"
#: init.lua
msgid "Craft 400 yellow dyes."
msgstr "Fazer 400 tintas amarelas."
#: init.lua
msgid "Geraniums are Blue"
msgstr "Gerânios são Azuis"
#: init.lua
msgid "Craft 400 blue dyes."
msgstr "Fazer 400 tintas azuis."
#: init.lua
msgid "White Color Stock"
msgstr "Estoque de Cor Branca"
#: init.lua
msgid "Craft 100 white dyes."
msgstr "Fazer 100 tintas brancas."
#: init.lua
msgid "Tasty Mushrooms"
msgstr "Cogumelos Deliciosos"
#: init.lua
msgid "Eat 3 brown mushrooms."
msgstr "Comer 3 cogumelos marrons."
#: init.lua
msgid "Mushroom Lover"
msgstr "Amante de Cogumelo"
#: init.lua
msgid "Eat 33 brown mushrooms."
msgstr "Comer 33 cogumelos marrons."
#: init.lua
msgid "Underground Mushroom Farmer"
msgstr "Fazendeiro Subterrâneo de Cogumelos"
#: init.lua
msgid "Eat 333 brown mushrooms."
msgstr "Comer 333 cogumelos marrons."
#: init.lua
msgid "Builder"
msgstr "Construtor"
#: init.lua
msgid "Constructor"
msgstr "Empreiteiro"
#: init.lua
msgid "Architect"
msgstr "Arquiteto"
#: init.lua
msgid "Master Architect"
msgstr "Arquiteto Mestre"
#: chat_commands.lua
msgid "[c|clear|disable|enable]"
msgstr "[c|clear|disable|enable]"
#: chat_commands.lua
msgid "Show, clear, disable or enable your achievements"
msgstr "Exibir, limpar, desabilitar ou habilitar suas conquistas"
#: chat_commands.lua
msgid "All your awards and statistics have been cleared. You can now start again."
msgstr "Todas as suas conquistas e estatísticas foram limpas. Agora podes iniciar novamente."
#: chat_commands.lua
msgid "You have disabled your achievements."
msgstr "Suas conquistas foram desabilitadas."
#: chat_commands.lua
msgid "You have enabled your achievements."
msgstr "Suas conquistas foram habilitadas."
#: chat_commands.lua
msgid "<achievement ID>"
msgstr "<ID da conquista>"
#: chat_commands.lua
msgid "Show details of an achievement"
msgstr "Mostra detalhes de uma conquista"
#: chat_commands.lua
msgid "Achievement not found."
msgstr "Conquista não encontrada."
#: chat_commands.lua
msgid "<name>"
msgstr "<jogador>"
#: chat_commands.lua
msgid "Get the achievements statistics for the given player or yourself"
msgstr "Ver as estatísticas de conquistas de um jogador ou suas próprias"

182
src/api_awards.lua Normal file
View File

@ -0,0 +1,182 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
local S = awards.gettext
function awards.register_award(name, def)
def.name = name
-- Add Triggers
if def.trigger and def.trigger.type then
local tdef = awards.registered_triggers[def.trigger.type]
assert(tdef, "Trigger not found: " .. def.trigger.type)
tdef:on_register(def)
end
function def:can_unlock(data)
if not self.requires then
return true
end
for i=1, #self.requires do
if not data.unlocked[self.requires[i]] then
return false
end
end
return true
end
-- Add Award
awards.registered_awards[name] = def
local tdef = awards.registered_awards[name]
if def.description == nil and tdef.getDefaultDescription then
def.description = tdef:getDefaultDescription()
end
end
-- This function is called whenever a target condition is met.
-- It checks if a player already has that award, and if they do not,
-- it gives it to them
----------------------------------------------
--awards.unlock(name, award)
-- name - the name of the player
-- award - the name of the award to give
function awards.unlock(name, award)
-- Access Player Data
local data = awards.player(name)
local awdef = awards.registered_awards[award]
assert(awdef, "Unable to unlock an award which doesn't exist!")
if data.disabled or
(data.unlocked[award] and data.unlocked[award] == award) then
return
end
if not awdef:can_unlock(data) then
minetest.log("warning", "can_unlock returned false in unlock of " ..
award .. " for " .. name)
return
end
-- Unlock Award
minetest.log("action", name.." has unlocked award "..name)
data.unlocked[award] = award
awards.save()
-- Give Prizes
if awdef and awdef.prizes then
for i = 1, #awdef.prizes do
local itemstack = ItemStack(awdef.prizes[i])
if not itemstack:is_empty() then
local receiverref = minetest.get_player_by_name(name)
if receiverref then
receiverref:get_inventory():add_item("main", itemstack)
end
end
end
end
-- Run callbacks
if awdef.on_unlock and awdef.on_unlock(name, awdef) then
return
end
for _, callback in pairs(awards.on_unlock) do
if callback(name, awdef) then
return
end
end
-- Get Notification Settings
local title = awdef.title or award
local desc = awdef.description or ""
local background = awdef.background or "awards_bg_default.png"
local icon = awdef.icon or "awards_unknown.png"
local sound = awdef.sound
if sound == nil then
-- Explicit check for nil because sound could be `false` to disable it
sound = {name="awards_got_generic", gain=0.25}
end
-- Do Notification
if sound then
-- Enforce sound delay to prevent sound spamming
local lastsound = data.lastsound
if lastsound == nil or os.difftime(os.time(), lastsound) >= 1 then
minetest.sound_play(sound, {to_player=name})
data.lastsound = os.time()
end
end
if awards.show_mode == "chat" then
local chat_announce
if awdef.secret then
chat_announce = S("Secret Award Unlocked: %s")
else
chat_announce = S("Award Unlocked: %s")
end
-- use the chat console to send it
minetest.chat_send_player(name, string.format(chat_announce, title))
if desc~="" then
minetest.chat_send_player(name, desc)
end
else
local player = minetest.get_player_by_name(name)
if not (player and player.is_player and player:is_player()) then
return
end
local one = player:hud_add({
hud_elem_type = "image",
name = "award_bg",
scale = {x = 2, y = 1},
text = background,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 138},
alignment = {x = 0, y = -1}
})
local hud_announce
if awdef.secret then
hud_announce = S("Secret Award Unlocked!")
else
hud_announce = S("Award Unlocked!")
end
local two = player:hud_add({
hud_elem_type = "text",
name = "award_au",
number = 0xFFFFFF,
scale = {x = 100, y = 20},
text = hud_announce,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 45},
alignment = {x = 0, y = -1}
})
local three = player:hud_add({
hud_elem_type = "text",
name = "award_title",
number = 0xFFFFFF,
scale = {x = 100, y = 20},
text = title,
position = {x = 0.5, y = 0.05},
offset = {x = 0, y = 100},
alignment = {x = 0, y = -1}
})
local four = player:hud_add({
hud_elem_type = "image",
name = "award_icon",
scale = {x = 4, y = 4},
text = icon,
position = {x = 0.5, y = 0.05},
offset = {x = -200.5, y = 126},
alignment = {x = 0, y = -1}
})
minetest.after(4, function()
local player2 = minetest.get_player_by_name(name)
if player2 then
player2:hud_remove(one)
player2:hud_remove(two)
player2:hud_remove(three)
player2:hud_remove(four)
end
end)
end
end

218
src/api_triggers.lua Normal file
View File

@ -0,0 +1,218 @@
-- 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 = math.min(data[tname] or 0, tmp.target)
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)
data[tname] = data[tname] or {}
local done
if tmp.key then
done = data[tname][tmp.key] or 0
else
done = data[tname].__total or 0
end
done = math.min(done, tmp.target)
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

72
src/chat_commands.lua Normal file
View File

@ -0,0 +1,72 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
local S = awards.gettext
minetest.register_privilege("awards_admin", { description = "Can manage awards of given player" })
minetest.register_chatcommand("awards", {
params = "[c|clear|disable|enable] [player_name]",
description = "Show, clear, disable or enable player's awards",
func = function(name, param)
if not minetest.check_player_privs(name, { awards_admin = true }) then
return false, "You need awards_admin privilege!"
end
local action, playern = param:split(" ")[1], param:split(" ")[2] or name
if action == "clear" then
awards.clear_player(playern)
minetest.chat_send_player(playern,
S("All your awards and statistics have been cleared. You can now start again."))
minetest.chat_send_player(name, "All awards and statistics of "..playern.." have been cleared.")
elseif action == "disable" then
awards.disable(playern)
minetest.chat_send_player(playern, "Your awards are disabled.")
minetest.chat_send_player(name, "You have disabled awards of "..playern..".")
elseif action == "enable" then
awards.enable(playern)
minetest.chat_send_player(playern, "Your awards are enabled.")
minetest.chat_send_player(name, "You have enabled awards of "..playern..".")
elseif action == "c" then
awards.show_to(playern, name, nil, true)
elseif not action then
awards.show_to(name, name, nil, false)
else
awards.show_to(action, name, nil, true)
end
if (action == "disable" or action == "enable") and minetest.global_exists("sfinv") and not minetest.get_modpath("unified_inventory") then
local player = minetest.get_player_by_name(playern)
if player then
sfinv.set_player_inventory_formspec(player)
end
end
end
})
minetest.register_chatcommand("awd", {
params = S("<award ID>"),
description = S("Show details of an award"),
func = function(name, param)
local def = awards.registered_awards[param]
if def then
minetest.chat_send_player(name, string.format(S("%s: %s"), def.title, def.description))
else
minetest.chat_send_player(name, S("Award not found."))
end
end
})
minetest.register_chatcommand("awpl", {
privs = {
server = true
},
params = S("<name>"),
description = S("Get the awards statistics for the given player or yourself"),
func = function(name, param)
if not param or param == "" then
param = name
end
minetest.chat_send_player(name, param)
local player = awards.player(param)
minetest.chat_send_player(name, dump(player))
end
})

111
src/data.lua Normal file
View File

@ -0,0 +1,111 @@
local storage = minetest.get_mod_storage()
local __player_data
-- Table Save Load Functions
function awards.save()
storage:set_string("player_data", minetest.write_json(__player_data))
end
local function convert_data()
minetest.log("warning", "Importing awards data from previous version")
local old_players = __player_data
__player_data = {}
for name, data in pairs(old_players) do
while name.name do
name = name.name
end
data.name = name
print("Converting data for " .. name)
-- Just rename counted
local counted = {
chats = "chat",
deaths = "death",
joins = "join",
}
for from, to in pairs(counted) do
data[to] = data[from]
data[from] = nil
end
data.death = {
unknown = data.death,
__total = data.death,
}
-- Convert item db to new format
local counted_items = {
count = "dig",
place = "place",
craft = "craft",
}
for from, to in pairs(counted_items) do
local ret = {}
local count = 0
if data[from] then
for modname, items in pairs(data[from]) do
for itemname, value in pairs(items) do
itemname = modname .. ":" .. itemname
local key = minetest.registered_aliases[itemname] or itemname
ret[key] = value
count = count + value
end
end
end
ret.__total = count
data[from] = nil
data[to] = ret
end
__player_data[name] = data
end
end
function awards.load()
local old_save_path = minetest.get_worldpath().."/awards.txt"
local file = io.open(old_save_path, "r")
if file then
local table = minetest.deserialize(file:read("*all"))
if type(table) == "table" then
__player_data = table
convert_data()
else
__player_data = {}
end
file:close()
os.rename(old_save_path, minetest.get_worldpath().."/awards.bk.txt")
awards.save()
else
__player_data = minetest.parse_json(storage:get_string("player_data")) or {}
end
end
function awards.player(name)
assert(type(name) == "string")
local data = __player_data[name] or {}
__player_data[name] = data
data.name = data.name or name
data.unlocked = data.unlocked or {}
return data
end
function awards.player_or_nil(name)
return __player_data[name]
end
function awards.enable(name)
awards.player(name).disabled = nil
end
function awards.disable(name)
awards.player(name).disabled = true
end
function awards.clear_player(name)
__player_data[name] = {}
end

View File

@ -75,64 +75,64 @@ function awards.get_formspec(name, to, sid)
formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]" formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]"
return formspec return formspec
end end
sid = awards_list[sid] and sid or 1
-- Sidebar -- Sidebar
if sid then local sitem = awards_list[sid]
local item = awards_list[sid+0] local sdef = sitem.def
local def = item.def if sdef and sdef.secret and not sitem.unlocked then
formspec = formspec .. "label[1,2.75;"..
minetest.formspec_escape(S("(Secret Award)")).."]"..
"image[1,0;3,3;awards_unknown.png]"
if sdef and sdef.description then
formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..
minetest.formspec_escape(
S("Unlock this award to find out what it is."))..";]"
end
else
local title = sitem.name
if sdef and sdef.title then
title = sdef.title
end
local status = "%s"
if sitem.unlocked then
status = S("%s (unlocked)")
end
if def and def.secret and not item.unlocked then formspec = formspec .. "textarea[0.5,3.1;4.8,1.45;;" ..
formspec = formspec .. "label[1,2.75;".. string.format(status, minetest.formspec_escape(title)) ..
minetest.formspec_escape(S("(Secret Award)")).."]".. ";]"
"image[1,0;3,3;awards_unknown.png]"
if def and def.description then
formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..
minetest.formspec_escape(
S("Unlock this award to find out what it is."))..";]"
end
else
local title = item.name
if def and def.title then
title = def.title
end
local status = "%s"
if item.unlocked then
status = S("%s (unlocked)")
end
formspec = formspec .. "textarea[0.5,2.7;4.8,1.45;;" .. if sdef and sdef.icon then
string.format(status, minetest.formspec_escape(title)) .. formspec = formspec .. "image[0.6,0;3,3;" .. sdef.icon .. "]"
";]" end
local barwidth = 3.95
if def and def.icon then local perc = nil
formspec = formspec .. "image[1,0;3,3;" .. def.icon .. "]" local label = nil
if sdef.getProgress and data then
local res = sdef:getProgress(data)
perc = res.perc
label = res.label
end
if perc then
if perc > 1 then
perc = 1
end end
local barwidth = 4.6 formspec = formspec .. "background[0,8.24;" .. barwidth ..",0.4;awards_progress_gray.png;false]"
local perc = nil formspec = formspec .. "background[0,8.24;" .. (barwidth * perc) ..",0.4;awards_progress_green.png;false]"
local label = nil if label then
if def.getProgress and data then formspec = formspec .. "label[1.6,8.15;" .. minetest.formspec_escape(label) .. "]"
local res = def:getProgress(data)
perc = res.perc
label = res.label
end
if perc then
if perc > 1 then
perc = 1
end
formspec = formspec .. "background[0,4.80;" .. barwidth ..",0.25;awards_progress_gray.png;false]"
formspec = formspec .. "background[0,4.80;" .. (barwidth * perc) ..",0.25;awards_progress_green.png;false]"
if label then
formspec = formspec .. "label[1.75,4.63;" .. minetest.formspec_escape(label) .. "]"
end
end
if def and def.description then
formspec = formspec .. "textarea[0.25,3.75;4.8,1.7;;"..minetest.formspec_escape(def.description)..";]"
end end
end end
if sdef and sdef.description then
formspec = formspec .. "box[-0.05,3.75;3.9,4.2;#000]"
formspec = formspec .. "textarea[0.25,3.75;3.9,4.2;;" ..
minetest.formspec_escape(sdef.description) .. ";]"
end
end end
-- Create list box -- Create list box
formspec = formspec .. "textlist[4.75,0;6,5;awards;" formspec = formspec .. "textlist[4,0;3.8,8.6;awards;"
local first = true local first = true
for _, award in pairs(awards_list) do for _, award in pairs(awards_list) do
local def = award.def local def = award.def
@ -168,7 +168,7 @@ function awards.show_to(name, to, sid, text)
if name == "" or name == nil then if name == "" or name == nil then
name = to name = to
end end
local data = awards.player(to) local data = awards.player(name)
if name == to and data.disabled then if name == to and data.disabled then
minetest.chat_send_player(name, S("You've disabled awards. Type /awards enable to reenable.")) minetest.chat_send_player(name, S("You've disabled awards. Type /awards enable to reenable."))
return return
@ -199,20 +199,35 @@ function awards.show_to(name, to, sid, text)
end end
end end
else else
if sid == nil or sid < 1 then
sid = 1
end
local deco = "" local deco = ""
if minetest.global_exists("default") then if minetest.global_exists("default") then
deco = default.gui_bg .. default.gui_bg_img deco = default.gui_bg .. default.gui_bg_img
end end
-- Show formspec to user -- Show formspec to user
minetest.show_formspec(to,"awards:awards", minetest.show_formspec(to,"awards:awards",
"size[11,5]" .. deco .. "size[8,8.6]" .. deco ..
awards.get_formspec(name, to, sid)) awards.get_formspec(name, to, sid))
end end
end end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "awards:awards" then
return false
end
if fields.quit then
return true
end
local name = player:get_player_name()
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
awards.show_to(name, name, event.index, false)
end
end
return true
end)
if minetest.get_modpath("sfinv") then if minetest.get_modpath("sfinv") then
sfinv.register_page("awards:awards", { sfinv.register_page("awards:awards", {
title = S("Awards"), title = S("Awards"),
@ -226,8 +241,8 @@ if minetest.get_modpath("sfinv") then
get = function(self, player, context) get = function(self, player, context)
local name = player:get_player_name() local name = player:get_player_name()
return sfinv.make_formspec(player, context, return sfinv.make_formspec(player, context,
awards.get_formspec(name, name, context.awards_idx or 1), awards.get_formspec(name, name, context.awards_idx),
false, "size[11,5]") false)
end, end,
on_player_receive_fields = function(self, player, context, fields) on_player_receive_fields = function(self, player, context, fields)
if fields.awards then if fields.awards then
@ -239,6 +254,22 @@ if minetest.get_modpath("sfinv") then
end end
end end
}) })
local function check_and_reshow(name)
local player = minetest.get_player_by_name(name)
if not player then
return
end
local context = sfinv.get_or_create_context(player)
if context.page ~= "awards:awards" then
return
end
sfinv.set_player_inventory_formspec(player, context)
end
awards.register_on_unlock(check_and_reshow)
end end
if minetest.get_modpath("unified_inventory") ~= nil then if minetest.get_modpath("unified_inventory") ~= nil then

View File

@ -109,15 +109,15 @@ awards.register_trigger("craft", {
end, end,
key_is_item = true, key_is_item = true,
}) })
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) --minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not player or itemstack:is_empty() then -- if not player or itemstack:is_empty() then
return -- return
end -- end
--
local itemname = itemstack:get_name() -- local itemname = itemstack:get_name()
itemname = minetest.registered_aliases[itemname] or itemname -- itemname = minetest.registered_aliases[itemname] or itemname
awards.notify_craft(player, itemname, itemstack:get_count()) -- awards.notify_craft(player, itemname, itemstack:get_count())
end) --end)
awards.register_trigger("eat", { awards.register_trigger("eat", {