initial upload

master
NathanSalapat 2020-06-14 18:29:10 -05:00
commit fb98659b03
4530 changed files with 305760 additions and 0 deletions

1
.stignore Normal file
View File

@ -0,0 +1 @@
.git

519
LICENSE.txt Normal file
View File

@ -0,0 +1,519 @@
License of media (textures and sounds)
--------------------------------------
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
See README.txt in each mod directory for information about other authors.
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
License of menu/header.png
Copyright (C) 2015 paramat CC BY-SA 3.0
License of source code
----------------------
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
See README.txt in each mod directory for information about other authors.
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

3
game.conf Normal file
View File

@ -0,0 +1,3 @@
name = Epic
author = Nathan Salapat
description = Based off of MTG with a bunch of custom mods.

1076
game_api.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
menu/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,2 @@
dofile(minetest.get_modpath('arctic_life')..'/penguin.lua')
dofile(minetest.get_modpath('arctic_life')..'/walrus.lua')

View File

@ -0,0 +1,21 @@
Graphics by Nathan(CC-BY-SA 4.0)
mobs_penguin
mobs_walrus1
mobs_walrus2
Graphics by DuCake (CC-BY-SA 4.0)
mobs_penguin_tux
Sound:
Penguin_chirrup.ogg
Tai "DuCake" Kedzierski CC-BY-SA 4.0
Walrus sounds
AlexTriceratops123 CCA
Code is licensed MIT,
Copyright 2020 Nathan Salapat
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,5 @@
name = arctic_life
title = Artic Life
author = Nathan Salapat
description = Simple mod that adds penguins and walrus to snowy biomes.
depends = default, mobs

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,58 @@
mobs:register_mob("arctic_life:penguin", {
type = "animal",
passive = false,
attack_type = "dogfight",
group_attack = true,
reach = 1,
damage = 1,
hp_min = 5,
hp_max = 15,
armor = 200,
fly_in = "default:water_source",
collisionbox = {-0.25, -0.4, -0.25, 0.25, 0.3, 0.25},
visual = "mesh",
mesh = "arctic_life_penguin.b3d",
drawtype = "front",
textures = {
{"arctic_life_penguin.png"},
{"arctic_life_penguin_tux.png"},
},
blood_texture = "mobs_blood.png",
visual_size = {x=8,y=8},
makes_footstep_sound = true,
sounds = {
random = "penguin_chirrup",
},
-- speed and jump
walk_velocity = 1,
run_velocity = 2,
jump = true,
jump_height = 1,
stepheight = 1.1,
floats = 0,
-- drops raw meat when dead
drops = {
{name = "mobs:meat_raw", chance = 1, min = 1, max = 4},
{name = 'bonemeal:bone', chance = 2, min = 1, max = 2},
},
-- damaged by
water_damage = 0,
lava_damage = 5,
light_damage = 0,
-- model animation
animation = {
speed_normal = 15, speed_run = 15,
stand_start = 0, stand_end = 60, -- head down/up
walk_start = 150, walk_end = 170, -- walk
run_start = 150, run_end = 170, -- walk
punch_start = 70, punch_end = 140, -- attack
fly_start = 171, fly_end = 201, -- swimming
},
follow = "fishing:fish_raw", view_range = 7,
replace_rate = 50,
replace_what = {"group:flora"},
replace_with = "air",
})
mobs:register_spawn("arctic_life:penguin", {"default:dirt_with_snow", "default:snowblock"}, 20, 0, 20000, 1, 600)
mobs:register_egg("arctic_life:penguin", "Penguin", "default_grass.png", 1)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,55 @@
mobs:register_mob("arctic_life:walrus", {
type = "animal",
passive = false,
attack_type = "dogfight",
reach = 1,
damage = 5,
hp_min = 15,
hp_max = 45,
armor = 200,
collisionbox = {-0.35, -0.5, -0.35, 0.35, 0.4, 0.35},
visual = "mesh",
mesh = "arctic_life_walrus.b3d",
drawtype = "front",
textures = {
{"arctic_life_walrus1.png"},
{"arctic_life_walrus2.png"},
},
blood_texture = "mobs_blood.png",
visual_size = {x=10,y=10},
makes_footstep_sound = false,
sounds = {
random = "walrus_random.ogg",
war_cry = 'walrus_war_cry.ogg',
attack = 'walrus_attack.ogg'
},
-- speed and jump
walk_velocity = 1,
run_velocity = 2,
jump = true,
jump_height = 1,
stepheight = 1.1,
floats = 1,
-- drops raw meat when dead
drops = {
{name = "mobs:meat_raw", chance = 1, min = 2, max = 5},
{name = 'bonemeal:bone', chance = 2, min = 1, max = 3},
},
-- damaged by
water_damage = 1,
lava_damage = 5,
light_damage = 0,
-- model animation
animation = {
speed_normal = 15, speed_run = 15,
stand_start = 0, stand_end = 50, -- head down/up
walk_start = 55, walk_end = 95, -- walk
run_start = 55, run_end = 95, -- walk
punch_start = 100, punch_end = 145, -- attack
},
follow = {"fishing:fish_raw", "mobs_fish:clownfish", "fishing:pike"},
view_range = 7,
})
mobs:register_spawn("arctic_life:walrus", {"default:dirt_with_snow", "default:snowblock"}, 20, 0, 20000, 1, 600)
mobs:register_egg("arctic_life:walrus", "Walrus", "default_grass.png", 1)

502
mods/areas/LICENSE.txt Normal file
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

103
mods/areas/README.md Normal file
View File

@ -0,0 +1,103 @@
Areas mod for Minetest
======================
Dependencies
------------
Minetest 5.0.0+ is recommended, but 0.4.16+ should work as well.
Configuration
-------------
Open the tab `Settings -> All Settings -> Mods -> areas` to get a list of all
possible settings.
For server owners: Check `settingtypes.txt` and modify your `minetest.conf`
according to the wanted setting changes.
Tutorial
--------
1) Specify the corner positions of the area you would like to protect.
Use one of the following commands:
* `/area_pos set` and punch the two corner nodes to set them.
* `/area_pos set1/set2` and punch only the first or second corner node to
set them one at a time.
* `/area_pos1/2` to set one of the positions to your current position.
* `/area_pos1/2 X Y Z` to set one of the positions to the specified
coordinates.
2) Protect the selected area by running one of the following commands:
* `/set_owner <OwnerName> <AreaName>` -- If you have the `areas` privilege.
* `/protect <AreaName>` -- If you have the `areas` privilege or the server
administrator has enabled area self-protection.
The area name is used only for informational purposes and has no functional
importance.
For example: `/set_owner SomePlayer Mese city`
3) You now own an area. You may now add sub-owners to it if you want to (see command `/add_owner`). Before using the `/add_owner` command you have to
select the corners of the sub-area as you did in step 1.
If your markers are still around your original area and you want to grant
access to your entire area you will not have to re-set them. Use `/select_area` to place the markers at the corners of an existing area if you've reset your
markers and want to grant access to a full area.
The `/add_owner` command expects three arguments:
1. The ID number of the parent area (the area that you want to add a
sub-area to).
2. The name of the player that will own the sub-area.
3. The name of the sub-area. (can contain spaces)
For example: `/add_owner 123 BobTheBuilder Diamond lighthouse`
Commands
--------
* `/protect <AreaName>` -- Protects an area for yourself. (if
self-protection is enabled)
* `/set_owner <OwnerName> <AreaName>` -- Protects an area for a specified
player. (requires the `areas` privilege)
* `/add_owner <ParentID> <OwnerName> <ChildName>` -- Grants another player
control over part (or all) of an area.
* `/rename_area <ID> <NewName>` -- Renames an existing area.
* `/list_areas` -- Lists all of the areas that you own, or all areas if you
have the `areas` privilege.
* `/find_areas <Regex>` -- Finds areas using a Lua regular expresion.
For example, to find castles:
/find_areas [Cc]astle
* `/remove_area <ID>` -- Removes an area that you own. Any sub-areas of that
area are made sub-areas of the removed area's parent, if it exists.
If the removed area has no parent it's sub-areas will have no parent.
* `/recursive_remove_areas <ID>` -- Removes an area and all sub-areas of it.
* `/change_owner <ID> <NewOwner>` -- Change the owner of an area.
* `/area_info` -- Returns information about area configuration and usage.
* `/select_area <ID>` -- Sets the area positions to those of an existing
area.
* `/area_pos {set,set1,set2,get}` -- Sets the area positions by punching
nodes or shows the current area positions.
* `/area_pos1 [X,Y,Z|X Y Z]` -- Sets area position one to your position or
the one supplied.
* `/area_pos2 [X,Y,Z|X Y Z]` -- Sets area position two to your position or
the one supplied.

165
mods/areas/api.lua Normal file
View File

@ -0,0 +1,165 @@
local hudHandlers = {}
areas.registered_on_adds = {}
areas.registered_on_removes = {}
areas.registered_on_moves = {}
function areas:registerOnAdd(func)
table.insert(areas.registered_on_adds, func)
end
function areas:registerOnRemove(func)
table.insert(areas.registered_on_removes, func)
end
function areas:registerOnMove(func)
table.insert(areas.registered_on_moves, func)
end
--- Adds a function as a HUD handler, it will be able to add items to the Areas HUD element.
function areas:registerHudHandler(handler)
table.insert(hudHandlers, handler)
end
function areas:getExternalHudEntries(pos)
local areas = {}
for _, func in pairs(hudHandlers) do
func(pos, areas)
end
return areas
end
--- Returns a list of areas that include the provided position.
function areas:getAreasAtPos(pos)
local res = {}
if self.store then
local a = self.store:get_areas_for_pos(pos, false, true)
for store_id, store_area in pairs(a) do
local id = tonumber(store_area.data)
res[id] = self.areas[id]
end
else
local px, py, pz = pos.x, pos.y, pos.z
for id, area in pairs(self.areas) do
local ap1, ap2 = area.pos1, area.pos2
if
(px >= ap1.x and px <= ap2.x) and
(py >= ap1.y and py <= ap2.y) and
(pz >= ap1.z and pz <= ap2.z) then
res[id] = area
end
end
end
return res
end
--- Returns areas that intersect with the passed area.
function areas:getAreasIntersectingArea(pos1, pos2)
local res = {}
if self.store then
local a = self.store:get_areas_in_area(pos1, pos2,
true, false, true)
for store_id, store_area in pairs(a) do
local id = tonumber(store_area.data)
res[id] = self.areas[id]
end
else
self:sortPos(pos1, pos2)
local p1x, p1y, p1z = pos1.x, pos1.y, pos1.z
local p2x, p2y, p2z = pos2.x, pos2.y, pos2.z
for id, area in pairs(self.areas) do
local ap1, ap2 = area.pos1, area.pos2
if
(ap1.x <= p2x and ap2.x >= p1x) and
(ap1.y <= p2y and ap2.y >= p1y) and
(ap1.z <= p2z and ap2.z >= p1z) then
-- Found an intersecting area.
res[id] = area
end
end
end
return res
end
-- Checks if the area is unprotected or owned by you
function areas:canInteract(pos, name)
if minetest.check_player_privs(name, self.adminPrivs) then
return true
end
local owned = false
for _, area in pairs(self:getAreasAtPos(pos)) do
if area.owner == name or area.open then
return true
elseif areas.factions_available and area.faction_open then
local faction_name = factions.get_player_faction(area.owner)
if faction_name ~= nil and faction_name == factions.get_player_faction(name) then
return true
end
end
owned = true
end
return not owned
end
-- Returns a table (list) of all players that own an area
function areas:getNodeOwners(pos)
local owners = {}
for _, area in pairs(self:getAreasAtPos(pos)) do
table.insert(owners, area.owner)
end
return owners
end
--- Checks if the area intersects with an area that the player can't interact in.
-- Note that this fails and returns false when the specified area is fully
-- owned by the player, but with multiple protection zones, none of which
-- cover the entire checked area.
-- @param name (optional) Player name. If not specified checks for any intersecting areas.
-- @param allow_open Whether open areas should be counted as if they didn't exist.
-- @return Boolean indicating whether the player can interact in that area.
-- @return Un-owned intersecting area ID, if found.
function areas:canInteractInArea(pos1, pos2, name, allow_open)
if name and minetest.check_player_privs(name, self.adminPrivs) then
return true
end
self:sortPos(pos1, pos2)
-- Intersecting non-owned area ID, if found.
local blocking_area = nil
local areas = self:getAreasIntersectingArea(pos1, pos2)
for id, area in pairs(areas) do
-- First check for a fully enclosing owned area.
-- A little optimization: isAreaOwner isn't necessary
-- here since we're iterating over all relevant areas.
if area.owner == name and
self:isSubarea(pos1, pos2, id) then
return true
end
-- Then check for intersecting non-owned (blocking) areas.
-- We don't bother with this check if we've already found a
-- blocking area, as the check is somewhat expensive.
-- The area blocks if the area is closed or open areas aren't
-- acceptable to the caller, and the area isn't owned.
-- Note: We can't return directly here, because there might be
-- an exclosing owned area that we haven't gotten to yet.
if not blocking_area and
(not allow_open or not area.open) and
(not name or not self:isAreaOwner(id, name)) then
blocking_area = id
end
end
if blocking_area then
return false, blocking_area
end
-- There are no intersecting areas or they are only partially
-- intersecting areas and they are all owned by the player.
return true
end

48
mods/areas/api.md Normal file
View File

@ -0,0 +1,48 @@
Areas mod API
===
API list
---
* `areas:registerHudHandler(handler)` - Registers a handler to add items to the Areas HUD. See [HUD](#hud).
* `areas:registerOnAdd(func(id, area))`
* `areas:registerOnRemove(func(id))`
* `areas:registerOnMove(func(id, area, pos1, pos2))`
HUD
---
If you are making a protection mod or a similar mod that adds invisible regions
to the world, and you would like then to show up in the areas HUD element, you
can register a callback to show your areas.
HUD handler specification:
* `handler(pos, list)`
* `pos` - The position to check.
* `list` - The list of area HUD elements, this should be modified in-place.
The area list item is a table containing a list of tables with the following fields:
* `id` - An identifier for the area. This should be a unique string in the format `mod:id`.
* `name` - The name of the area.
* `owner` - The player name of the region owner, if any.
All of the fields are optional but at least one of them must be set.
### Example
local function areas_hud_handler(pos, areas)
local val = find_my_protection(pos)
if val then
table.insert(areas, {
id = "mod:"..val.id,
name = val.name,
owner = val.owner,
})
end
end
areas:registerHudHandler(areas_hud_handler)

434
mods/areas/chatcommands.lua Normal file
View File

@ -0,0 +1,434 @@
minetest.register_chatcommand("protect", {
params = "<AreaName>",
description = "Protect your own area",
privs = {[areas.config.self_protection_privilege]=true},
func = function(name, param)
if param == "" then
return false, "Invalid usage, see /help protect."
end
local player = minetest.get_player_by_name(name)
if not player:get_inventory():contains_item('main', 'epic:deed') then
minetest.chat_send_player(name, 'You need a land deed.')
return
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
end
minetest.log("action", "/protect invoked, owner="..name..
" AreaName="..param..
" StartPos="..minetest.pos_to_string(pos1)..
" EndPos=" ..minetest.pos_to_string(pos2))
local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, name)
if not canAdd then
return false, "You can't protect that area: "..errMsg
end
local id = areas:add(name, param, pos1, pos2, nil)
areas:save()
player:get_inventory():remove_item('main', 'epic:deed')
return true, "Area protected. ID: "..id
end
})
minetest.register_chatcommand("set_owner", {
params = "<PlayerName> <AreaName>",
description = "Protect an area beetween two positions and give"
.." a player access to it without setting the parent of the"
.." area to any existing area",
privs = areas.adminPrivs,
func = function(name, param)
local ownerName, areaName = param:match('^(%S+)%s(.+)$')
if not ownerName then
return false, "Incorrect usage, see /help set_owner."
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
end
if not areas:player_exists(ownerName) then
return false, "The player \""
..ownerName.."\" does not exist."
end
minetest.log("action", name.." runs /set_owner. Owner = "..ownerName..
" AreaName = "..areaName..
" StartPos = "..minetest.pos_to_string(pos1)..
" EndPos = " ..minetest.pos_to_string(pos2))
local id = areas:add(ownerName, areaName, pos1, pos2, nil)
areas:save()
minetest.chat_send_player(ownerName,
"You have been granted control over area #"..
id..". Type /list_areas to show your areas.")
return true, "Area protected. ID: "..id
end
})
minetest.register_chatcommand("add_owner", {
params = "<ParentID> <Player> <AreaName>",
description = "Give a player access to a sub-area beetween two"
.." positions that have already been protected,"
.." Use set_owner if you don't want the parent to be set.",
func = function(name, param)
local pid, ownerName, areaName
= param:match('^(%d+) ([^ ]+) (.+)$')
if not pid then
minetest.chat_send_player(name, "Incorrect usage, see /help add_owner")
return
end
local pos1, pos2 = areas:getPos(name)
if not (pos1 and pos2) then
return false, "You need to select an area first."
end
if not areas:player_exists(ownerName) then
return false, "The player \""..ownerName.."\" does not exist."
end
minetest.log("action", name.." runs /add_owner. Owner = "..ownerName..
" AreaName = "..areaName.." ParentID = "..pid..
" StartPos = "..pos1.x..","..pos1.y..","..pos1.z..
" EndPos = " ..pos2.x..","..pos2.y..","..pos2.z)
-- Check if this new area is inside an area owned by the player
pid = tonumber(pid)
if (not areas:isAreaOwner(pid, name)) or
(not areas:isSubarea(pos1, pos2, pid)) then
return false, "You can't protect that area."
end
local id = areas:add(ownerName, areaName, pos1, pos2, pid)
areas:save()
minetest.chat_send_player(ownerName,
"You have been granted control over area #"..
id..". Type /list_areas to show your areas.")
return true, "Area protected. ID: "..id
end
})
minetest.register_chatcommand("rename_area", {
params = "<ID> <newName>",
description = "Rename a area that you own",
func = function(name, param)
local id, newName = param:match("^(%d+)%s(.+)$")
if not id then
return false, "Invalid usage, see /help rename_area."
end
id = tonumber(id)
if not id then
return false, "That area doesn't exist."
end
if not areas:isAreaOwner(id, name) then
return true, "You don't own that area."
end
areas.areas[id].name = newName
areas:save()
return true, "Area renamed."
end
})
minetest.register_chatcommand("find_areas", {
params = "<regexp>",
description = "Find areas using a Lua regular expression",
privs = areas.adminPrivs,
func = function(name, param)
if param == "" then
return false, "A regular expression is required."
end
-- Check expression for validity
local function testRegExp()
("Test [1]: Player (0,0,0) (0,0,0)"):find(param)
end
if not pcall(testRegExp) then
return false, "Invalid regular expression."
end
local matches = {}
for id, area in pairs(areas.areas) do
local str = areas:toString(id)
if str:find(param) then
table.insert(matches, str)
end
end
if #matches > 0 then
return true, table.concat(matches, "\n")
else
return true, "No matches found."
end
end
})
minetest.register_chatcommand("list_areas", {
description = "List your areas, or all areas if you are an admin.",
func = function(name, param)
local admin = minetest.check_player_privs(name, areas.adminPrivs)
local areaStrings = {}
for id, area in pairs(areas.areas) do
if admin or areas:isAreaOwner(id, name) then
table.insert(areaStrings, areas:toString(id))
end
end
if #areaStrings == 0 then
return true, "No visible areas."
end
return true, table.concat(areaStrings, "\n")
end
})
minetest.register_chatcommand("recursive_remove_areas", {
params = "<id>",
description = "Recursively remove areas using an id",
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see"
.." /help recursive_remove_areas"
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist or is"
.." not owned by you."
end
areas:remove(id, true)
areas:save()
return true, "Removed area "..id.." and it's sub areas."
end
})
minetest.register_chatcommand("remove_area", {
params = "<id>",
description = "Remove an area using an id",
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help remove_area"
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist or"
.." is not owned by you."
end
areas:remove(id)
areas:save()
return true, "Removed area "..id
end
})
minetest.register_chatcommand("change_owner", {
params = "<ID> <NewOwner>",
description = "Change the owner of an area using it's ID",
func = function(name, param)
local id, newOwner = param:match("^(%d+)%s(%S+)$")
if not id then
return false, "Invalid usage, see"
.." /help change_owner."
end
if not areas:player_exists(newOwner) then
return false, "The player \""..newOwner
.."\" does not exist."
end
id = tonumber(id)
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
end
areas.areas[id].owner = newOwner
areas:save()
minetest.chat_send_player(newOwner,
("%s has given you control over the area %q (ID %d).")
:format(name, areas.areas[id].name, id))
return true, "Owner changed."
end
})
minetest.register_chatcommand("area_open", {
params = "<ID>",
description = "Toggle an area open (anyone can interact) or closed",
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help area_open."
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
end
local open = not areas.areas[id].open
-- Save false as nil to avoid inflating the DB.
areas.areas[id].open = open or nil
areas:save()
return true, ("Area %s."):format(open and "opened" or "closed")
end
})
if areas.factions_available then
minetest.register_chatcommand("area_faction_open", {
params = "<ID>",
description = "Toggle an area open/closed for members in your faction.",
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help area_faction_open."
end
if not areas:isAreaOwner(id, name) then
return false, "Area "..id.." does not exist"
.." or is not owned by you."
end
local open = not areas.areas[id].faction_open
-- Save false as nil to avoid inflating the DB.
areas.areas[id].faction_open = open or nil
areas:save()
return true, ("Area %s for faction members."):format(open and "opened" or "closed")
end
})
end
minetest.register_chatcommand("move_area", {
params = "<ID>",
description = "Move (or resize) an area to the current positions.",
privs = areas.adminPrivs,
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help move_area."
end
local area = areas.areas[id]
if not area then
return false, "Area does not exist."
end
local pos1, pos2 = areas:getPos(name)
if not pos1 then
return false, "You need to select an area first."
end
areas:move(id, area, pos1, pos2)
areas:save()
return true, "Area successfully moved."
end,
})
minetest.register_chatcommand("area_info", {
description = "Get information about area configuration and usage.",
func = function(name, param)
local lines = {}
local privs = minetest.get_player_privs(name)
-- Short (and fast to access) names
local cfg = areas.config
local self_prot = cfg.self_protection
local prot_priv = cfg.self_protection_privilege
local limit = cfg.self_protection_max_areas
local limit_high = cfg.self_protection_max_areas_high
local size_limit = cfg.self_protection_max_size
local size_limit_high = cfg.self_protection_max_size_high
local has_high_limit = privs.areas_high_limit
local has_prot_priv = not prot_priv or privs[prot_priv]
local can_prot = privs.areas or (self_prot and has_prot_priv)
local max_count = can_prot and
(has_high_limit and limit_high or limit) or 0
local max_size = has_high_limit and
size_limit_high or size_limit
-- Privilege information
local self_prot_line = ("Self protection is %sabled"):format(
self_prot and "en" or "dis")
if self_prot and prot_priv then
self_prot_line = self_prot_line..
(" %s have the neccessary privilege (%q).")
:format(
has_prot_priv and "and you" or
"but you don't",
prot_priv)
else
self_prot_line = self_prot_line.."."
end
table.insert(lines, self_prot_line)
if privs.admin_areas then
table.insert(lines, "You are an area"..
" administrator (\"areas\" privilege).")
elseif has_high_limit then
table.insert(lines,
"You have extended area protection"..
" limits (\"areas_high_limit\" privilege).")
end
-- Area count
local area_num = 0
for id, area in pairs(areas.areas) do
if area.owner == name then
area_num = area_num + 1
end
end
local count_line = ("You have %d area%s"):format(
area_num, area_num == 1 and "" or "s")
if privs.admin_areas then
count_line = count_line..
" and have no area protection limits."
elseif can_prot then
count_line = count_line..(", out of a maximum of %d.")
:format(max_count)
end
table.insert(lines, count_line)
-- Area size limits
local function size_info(str, size)
table.insert(lines, ("%s spanning up to %dx%dx%d.")
:format(str, size.x, size.y, size.z))
end
local function priv_limit_info(lpriv, lmax_count, lmax_size)
size_info(("Players with the %q privilege"..
" can protect up to %d areas"):format(
lpriv, lmax_count), lmax_size)
end
if self_prot then
if privs.admin_areas then
priv_limit_info(prot_priv,
limit, size_limit)
priv_limit_info("areas_high_limit",
limit_high, size_limit_high)
elseif has_prot_priv then
size_info("You can protect areas", max_size)
end
end
return true, table.concat(lines, "\n")
end,
})

72
mods/areas/hud.lua Normal file
View File

@ -0,0 +1,72 @@
-- This is inspired by the landrush mod by Bremaweb
areas.hud = {}
areas.hud.refresh = 0
minetest.register_globalstep(function(dtime)
areas.hud.refresh = areas.hud.refresh + dtime
if areas.hud.refresh > areas.config["tick"] then
areas.hud.refresh = 0
else
return
end
for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local pos = vector.round(player:get_pos())
pos = vector.apply(pos, function(p)
return math.max(math.min(p, 2147483), -2147483)
end)
local areaStrings = {}
for id, area in pairs(areas:getAreasAtPos(pos)) do
local faction_info = area.faction_open and areas.factions_available and
factions.get_player_faction(area.owner)
area.faction_open = faction_info
table.insert(areaStrings, ("%s [%u] (%s%s%s)")
:format(area.name, id, area.owner,
area.open and ":open" or "",
faction_info and ":"..faction_info or ""))
end
for i, area in pairs(areas:getExternalHudEntries(pos)) do
local str = ""
if area.name then str = area.name .. " " end
if area.id then str = str.."["..area.id.."] " end
if area.owner then str = str.."("..area.owner..")" end
table.insert(areaStrings, str)
end
local areaString = "Areas:"
if #areaStrings > 0 then
areaString = areaString.."\n"..
table.concat(areaStrings, "\n")
end
local hud = areas.hud[name]
if not hud then
hud = {}
areas.hud[name] = hud
hud.areasId = player:hud_add({
hud_elem_type = "text",
name = "Areas",
number = 0xFFFFFF,
position = {x=0, y=1},
offset = {x=8, y=-8},
text = areaString,
scale = {x=200, y=60},
alignment = {x=1, y=-1},
})
hud.oldAreas = areaString
return
elseif hud.oldAreas ~= areaString then
player:hud_change(hud.areasId, "text", areaString)
hud.oldAreas = areaString
end
end
end)
minetest.register_on_leaveplayer(function(player)
areas.hud[player:get_player_name()] = nil
end)

41
mods/areas/init.lua Normal file
View File

@ -0,0 +1,41 @@
-- Areas mod by ShadowNinja
-- Based on node_ownership
-- License: LGPLv2+
areas = {}
areas.factions_available = minetest.global_exists("factions")
areas.adminPrivs = {admin_areas=true}
areas.startTime = os.clock()
areas.modpath = minetest.get_modpath("areas")
dofile(areas.modpath.."/settings.lua")
dofile(areas.modpath.."/api.lua")
dofile(areas.modpath.."/internal.lua")
dofile(areas.modpath.."/chatcommands.lua")
dofile(areas.modpath.."/pos.lua")
dofile(areas.modpath.."/interact.lua")
dofile(areas.modpath.."/legacy.lua")
dofile(areas.modpath.."/hud.lua")
areas:load()
minetest.register_privilege("admin_areas", {
description = "Can administer areas.",
give_to_singleplayer = false
})
minetest.register_privilege("areas_high_limit", {
description = "Can can more, bigger areas."
})
if not minetest.registered_privileges[areas.config.self_protection_privilege] then
minetest.register_privilege(areas.config.self_protection_privilege, {
description = "Can protect areas.",
})
end
if minetest.settings:get_bool("log_mods") then
local diffTime = os.clock() - areas.startTime
minetest.log("action", "areas loaded in "..diffTime.."s.")
end

25
mods/areas/interact.lua Normal file
View File

@ -0,0 +1,25 @@
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
if not areas:canInteract(pos, name) then
return true
end
return old_is_protected(pos, name)
end
minetest.register_on_protection_violation(function(pos, name)
if not areas:canInteract(pos, name) then
local player = minetest.get_player_by_name(name)
if player then
local yaw = player:get_look_horizontal() + math.pi
if yaw > 2 * math.pi then
yaw = yaw - 2 * math.pi
end
player:set_look_horizontal(yaw)
player:set_look_vertical(-player:get_look_vertical())
local owners = areas:getNodeOwners(pos)
minetest.chat_send_player(name,("%s is protected by %s."):format(
minetest.pos_to_string(pos), table.concat(owners, ", ")))
end
end
end)

305
mods/areas/internal.lua Normal file
View File

@ -0,0 +1,305 @@
function areas:player_exists(name)
return minetest.get_auth_handler().get_auth(name) ~= nil
end
local safe_file_write = minetest.safe_file_write
if safe_file_write == nil then
function safe_file_write(path, content)
local file, err = io.open(path, "w")
if err then
return err
end
file:write(content)
file:close()
end
end
-- Save the areas table to a file
function areas:save()
local datastr = minetest.serialize(self.areas)
if not datastr then
minetest.log("error", "[areas] Failed to serialize area data!")
return
end
return safe_file_write(self.config.filename, datastr)
end
-- Load the areas table from the save file
function areas:load()
local file, err = io.open(self.config.filename, "r")
if err then
self.areas = self.areas or {}
return err
end
self.areas = minetest.deserialize(file:read("*a"))
if type(self.areas) ~= "table" then
self.areas = {}
end
file:close()
self:populateStore()
end
--- Checks an AreaStore ID.
-- Deletes the AreaStore (falling back to the iterative method)
-- and prints an error message if the ID is invalid.
-- @return Whether the ID was valid.
function areas:checkAreaStoreId(sid)
if not sid then
minetest.log("error", "AreaStore failed to find an ID for an "
.."area! Falling back to iterative area checking.")
self.store = nil
self.store_ids = nil
end
return sid and true or false
end
-- Populates the AreaStore after loading, if needed.
function areas:populateStore()
if not rawget(_G, "AreaStore") then
return
end
local store = AreaStore()
local store_ids = {}
for id, area in pairs(areas.areas) do
local sid = store:insert_area(area.pos1,
area.pos2, tostring(id))
if not self:checkAreaStoreId(sid) then
return
end
store_ids[id] = sid
end
self.store = store
self.store_ids = store_ids
end
-- Finds the first usable index in a table
-- Eg: {[1]=false,[4]=true} -> 2
local function findFirstUnusedIndex(t)
local i = 0
repeat i = i + 1
until t[i] == nil
return i
end
--- Add a area.
-- @return The new area's ID.
function areas:add(owner, name, pos1, pos2, parent)
local id = findFirstUnusedIndex(self.areas)
self.areas[id] = {
name = name,
pos1 = pos1,
pos2 = pos2,
owner = owner,
parent = parent
}
for i=1, #areas.registered_on_adds do
areas.registered_on_adds[i](id, self.areas[id])
end
-- Add to AreaStore
if self.store then
local sid = self.store:insert_area(pos1, pos2, tostring(id))
if self:checkAreaStoreId(sid) then
self.store_ids[id] = sid
end
end
return id
end
--- Remove a area, and optionally it's children recursively.
-- If a area is deleted non-recursively the children will
-- have the removed area's parent as their new parent.
function areas:remove(id, recurse)
if recurse then
-- Recursively find child entries and remove them
local cids = self:getChildren(id)
for _, cid in pairs(cids) do
self:remove(cid, true)
end
else
-- Update parents
local parent = self.areas[id].parent
local children = self:getChildren(id)
for _, cid in pairs(children) do
-- The subarea parent will be niled out if the
-- removed area does not have a parent
self.areas[cid].parent = parent
end
end
for i=1, #areas.registered_on_removes do
areas.registered_on_removes[i](id)
end
-- Remove main entry
self.areas[id] = nil
-- Remove from AreaStore
if self.store then
self.store:remove_area(self.store_ids[id])
self.store_ids[id] = nil
end
end
--- Move an area.
function areas:move(id, area, pos1, pos2)
area.pos1 = pos1
area.pos2 = pos2
for i=1, #areas.registered_on_moves do
areas.registered_on_moves[i](id, area, pos1, pos2)
end
if self.store then
self.store:remove_area(areas.store_ids[id])
local sid = self.store:insert_area(pos1, pos2, tostring(id))
if self:checkAreaStoreId(sid) then
self.store_ids[id] = sid
end
end
end
-- Checks if a area between two points is entirely contained by another area.
-- Positions must be sorted.
function areas:isSubarea(pos1, pos2, id)
local area = self.areas[id]
if not area then
return false
end
local ap1, ap2 = area.pos1, area.pos2
local ap1x, ap1y, ap1z = ap1.x, ap1.y, ap1.z
local ap2x, ap2y, ap2z = ap2.x, ap2.y, ap2.z
local p1x, p1y, p1z = pos1.x, pos1.y, pos1.z
local p2x, p2y, p2z = pos2.x, pos2.y, pos2.z
if
(p1x >= ap1x and p1x <= ap2x) and
(p2x >= ap1x and p2x <= ap2x) and
(p1y >= ap1y and p1y <= ap2y) and
(p2y >= ap1y and p2y <= ap2y) and
(p1z >= ap1z and p1z <= ap2z) and
(p2z >= ap1z and p2z <= ap2z) then
return true
end
end
-- Returns a table (list) of children of an area given it's identifier
function areas:getChildren(id)
local children = {}
for cid, area in pairs(self.areas) do
if area.parent and area.parent == id then
table.insert(children, cid)
end
end
return children
end
-- Checks if the user has sufficient privileges.
-- If the player is not a administrator it also checks
-- if the area intersects other areas that they do not own.
-- Also checks the size of the area and if the user already
-- has more than max_areas.
function areas:canPlayerAddArea(pos1, pos2, name)
local privs = minetest.get_player_privs(name)
if privs.areas then
return true
end
-- Check self protection privilege, if it is enabled,
-- and if the area is too big.
if not self.config.self_protection or
not privs[areas.config.self_protection_privilege] then
return false, "Self protection is disabled or you do not have"
.." the necessary privilege."
end
local max_size = privs.areas_high_limit and
self.config.self_protection_max_size_high or
self.config.self_protection_max_size
if
(pos2.x - pos1.x) > max_size.x or
(pos2.y - pos1.y) > max_size.y or
(pos2.z - pos1.z) > max_size.z then
return false, "Area is too big."
end
-- Check number of areas the user has and make sure it not above the max
local count = 0
for _, area in pairs(self.areas) do
if area.owner == name then
count = count + 1
end
end
local max_areas = privs.areas_high_limit and
self.config.self_protection_max_areas_high or
self.config.self_protection_max_areas
if count >= max_areas then
return false, "You have reached the maximum amount of"
.." areas that you are allowed to protect."
end
-- Check intersecting areas
local can, id = self:canInteractInArea(pos1, pos2, name)
if not can then
local area = self.areas[id]
return false, ("The area intersects with %s [%u] (%s).")
:format(area.name, id, area.owner)
end
return true
end
-- Given a id returns a string in the format:
-- "name [id]: owner (x1, y1, z1) (x2, y2, z2) -> children"
function areas:toString(id)
local area = self.areas[id]
local message = ("%s [%d]: %s %s %s"):format(
area.name, id, area.owner,
minetest.pos_to_string(area.pos1),
minetest.pos_to_string(area.pos2))
local children = areas:getChildren(id)
if #children > 0 then
message = message.." -> "..table.concat(children, ", ")
end
return message
end
-- Re-order areas in table by their identifiers
function areas:sort()
local sa = {}
for k, area in pairs(self.areas) do
if not area.parent then
table.insert(sa, area)
local newid = #sa
for _, subarea in pairs(self.areas) do
if subarea.parent == k then
subarea.parent = newid
table.insert(sa, subarea)
end
end
end
end
self.areas = sa
end
-- Checks if a player owns an area or a parent of it
function areas:isAreaOwner(id, name)
local cur = self.areas[id]
if cur and minetest.check_player_privs(name, self.adminPrivs) then
return true
end
while cur do
if cur.owner == name then
return true
elseif cur.parent then
cur = self.areas[cur.parent]
else
return false
end
end
return false
end

139
mods/areas/legacy.lua Normal file
View File

@ -0,0 +1,139 @@
-- This file contains functions to convert from
-- the old areas format and other compatability code.
minetest.register_chatcommand("legacy_load_areas", {
params = "<version>",
description = "Loads, converts, and saves the areas from"
.." a legacy save file.",
privs = {areas=true, server=true},
func = function(name, param)
minetest.chat_send_player(name, "Converting areas...")
local version = tonumber(param)
if version == 0 then
local err = areas:node_ownership_load()
if err then
minetest.chat_send_player(name, "Error loading legacy file: "..err)
return
end
else
minetest.chat_send_player(name, "Invalid version number. (0 allowed)")
return
end
minetest.chat_send_player(name, "Legacy file loaded.")
for k, area in pairs(areas.areas) do
-- New position format
area.pos1 = {x=area.x1, y=area.y1, z=area.z1}
area.pos2 = {x=area.x2, y=area.y2, z=area.z2}
area.x1, area.y1, area.z1,
area.x2, area.y2, area.z2 =
nil, nil, nil, nil, nil, nil
-- Area positions sorting
areas:sortPos(area.pos1, area.pos2)
-- Add name
area.name = "unnamed"
-- Remove ID
area.id = nil
end
minetest.chat_send_player(name, "Table format updated.")
areas:save()
minetest.chat_send_player(name, "Converted areas saved. Done.")
end
})
function areas:node_ownership_load()
local filename = minetest.get_worldpath().."/owners.tbl"
local tables, err
tables, err = loadfile(filename)
if err then
return err
end
tables = tables()
for idx = 1, #tables do
local tolinkv, tolinki = {}, {}
for i, v in pairs(tables[idx]) do
if type(v) == "table" and tables[v[1]] then
table.insert(tolinkv, {i, tables[v[1]]})
end
if type(i) == "table" and tables[i[1]] then
table.insert(tolinki, {i, tables[i[1]]})
end
end
-- link values, first due to possible changes of indices
for _, v in ipairs(tolinkv) do
tables[idx][v[1]] = v[2]
end
-- link indices
for _, v in ipairs(tolinki) do
tables[idx][v[2]], tables[idx][v[1]] = tables[idx][v[1]], nil
end
end
self.areas = tables[1]
end
-- Returns the name of the first player that owns an area
function areas.getNodeOwnerName(pos)
for id, area in pairs(areas:getAreasAtPos(pos)) do
return area.owner
end
return false
end
-- Checks if a node is owned by you
function areas.isNodeOwner(pos, name)
if minetest.check_player_privs(name, areas.adminPrivs) then
return true
end
for id, area in pairs(areas:getAreasAtPos(pos)) do
if name == area.owner then
return true
end
end
return false
end
-- Checks if an area has an owner
function areas.hasOwner(pos)
for id, area in pairs(areas:getAreasAtPos(pos)) do
return true
end
return false
end
IsPlayerNodeOwner = areas.isNodeOwner
GetNodeOwnerName = areas.getNodeOwnerName
HasOwner = areas.hasOwner
-- This is entirely untested and may break in strange and new ways.
if areas.config.legacy_table then
owner_defs = setmetatable({}, {
__index = function(table, key)
local a = rawget(areas.areas, key)
if not a then return a end
local b = {}
for k, v in pairs(a) do b[k] = v end
b.x1, b.y1, b.z1 = b.pos1.x, b.pos1.y, b.pos1.z
b.x2, b.y1, b.z2 = b.pos2.x, b.pos2.y, b.pos2.z
b.pos1, b.pos2 = nil, nil
b.id = key
return b
end,
__newindex = function(table, key, value)
local a = value
a.pos1, a.pos2 = {x=a.x1, y=a.y1, z=a.z1},
{x=a.x2, y=a.y2, z=a.z2}
a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 =
nil, nil, nil, nil, nil, nil
a.name = a.name or "unnamed"
a.id = nil
return rawset(areas.areas, key, a)
end
})
end

6
mods/areas/license.txt Normal file
View File

@ -0,0 +1,6 @@
Code requiring player to have a land deed to protect an area added by Nathan Salapat.
Copyright (C) 2013 ShadowNinja
Licensed under the GNU LGPL version 2.1 or later.
See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt

2
mods/areas/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = areas
optional_depends = playerfactions

265
mods/areas/pos.lua Normal file
View File

@ -0,0 +1,265 @@
-- I could depend on WorldEdit for this, but you need to have the 'worldedit'
-- permission to use those commands and you don't have
-- /area_pos{1,2} [X Y Z|X,Y,Z].
-- Since this is mostly copied from WorldEdit it is mostly
-- licensed under the AGPL. (select_area is a exception)
areas.marker1 = {}
areas.marker2 = {}
areas.set_pos = {}
areas.pos1 = {}
areas.pos2 = {}
local LIMIT = 30992 -- this is due to MAPBLOCK_SIZE=16!
local function posLimit(pos)
return {
x = math.max(math.min(pos.x, LIMIT), -LIMIT),
y = math.max(math.min(pos.y, LIMIT), -LIMIT),
z = math.max(math.min(pos.z, LIMIT), -LIMIT)
}
end
minetest.register_chatcommand("select_area", {
params = "<ID>",
description = "Select a area by id.",
func = function(name, param)
local id = tonumber(param)
if not id then
return false, "Invalid usage, see /help select_area."
end
if not areas.areas[id] then
return false, "The area "..id.." does not exist."
end
areas:setPos1(name, areas.areas[id].pos1)
areas:setPos2(name, areas.areas[id].pos2)
return true, "Area "..id.." selected."
end,
})
minetest.register_chatcommand("area_pos1", {
params = "[X Y Z|X,Y,Z]",
description = "Set area protection region position 1 to your"
.." location or the one specified",
privs = {},
func = function(name, param)
local pos
local found, _, x, y, z = param:find(
"^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
if found then
pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)}
elseif param == "" then
local player = minetest.get_player_by_name(name)
if player then
pos = player:get_pos()
else
return false, "Unable to get position."
end
else
return false, "Invalid usage, see /help area_pos1."
end
pos = posLimit(vector.round(pos))
areas:setPos1(name, pos)
return true, "Area position 1 set to "
..minetest.pos_to_string(pos)
end,
})
minetest.register_chatcommand("area_pos2", {
params = "[X Y Z|X,Y,Z]",
description = "Set area protection region position 2 to your"
.." location or the one specified",
func = function(name, param)
local pos
local found, _, x, y, z = param:find(
"^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
if found then
pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)}
elseif param == "" then
local player = minetest.get_player_by_name(name)
if player then
pos = player:get_pos()
else
return false, "Unable to get position."
end
else
return false, "Invalid usage, see /help area_pos2."
end
pos = posLimit(vector.round(pos))
areas:setPos2(name, pos)
return true, "Area position 2 set to "
..minetest.pos_to_string(pos)
end,
})
minetest.register_chatcommand("area_pos", {
params = "set/set1/set2/get",
description = "Set area protection region, position 1, or position 2"
.." by punching nodes, or display the region",
func = function(name, param)
if param == "set" then -- Set both area positions
areas.set_pos[name] = "pos1"
return true, "Select positions by punching two nodes."
elseif param == "set1" then -- Set area position 1
areas.set_pos[name] = "pos1only"
return true, "Select position 1 by punching a node."
elseif param == "set2" then -- Set area position 2
areas.set_pos[name] = "pos2"
return true, "Select position 2 by punching a node."
elseif param == "get" then -- Display current area positions
local pos1str, pos2str = "Position 1: ", "Position 2: "
if areas.pos1[name] then
pos1str = pos1str..minetest.pos_to_string(areas.pos1[name])
else
pos1str = pos1str.."<not set>"
end
if areas.pos2[name] then
pos2str = pos2str..minetest.pos_to_string(areas.pos2[name])
else
pos2str = pos2str.."<not set>"
end
return true, pos1str.."\n"..pos2str
else
return false, "Unknown subcommand: "..param
end
end,
})
function areas:getPos(playerName)
local pos1, pos2 = areas.pos1[playerName], areas.pos2[playerName]
if not (pos1 and pos2) then
return nil
end
-- Copy positions so that the area table doesn't contain multiple
-- references to the same position.
pos1, pos2 = vector.new(pos1), vector.new(pos2)
return areas:sortPos(pos1, pos2)
end
function areas:setPos1(playerName, pos)
areas.pos1[playerName] = posLimit(pos)
areas.markPos1(playerName)
end
function areas:setPos2(playerName, pos)
areas.pos2[playerName] = posLimit(pos)
areas.markPos2(playerName)
end
minetest.register_on_punchnode(function(pos, node, puncher)
local name = puncher:get_player_name()
-- Currently setting position
if name ~= "" and areas.set_pos[name] then
if areas.set_pos[name] == "pos1" then
areas.pos1[name] = pos
areas.markPos1(name)
areas.set_pos[name] = "pos2"
minetest.chat_send_player(name,
"Position 1 set to "
..minetest.pos_to_string(pos))
elseif areas.set_pos[name] == "pos1only" then
areas.pos1[name] = pos
areas.markPos1(name)
areas.set_pos[name] = nil
minetest.chat_send_player(name,
"Position 1 set to "
..minetest.pos_to_string(pos))
elseif areas.set_pos[name] == "pos2" then
areas.pos2[name] = pos
areas.markPos2(name)
areas.set_pos[name] = nil
minetest.chat_send_player(name,
"Position 2 set to "
..minetest.pos_to_string(pos))
end
end
end)
-- Modifies positions `pos1` and `pos2` so that each component of `pos1`
-- is less than or equal to its corresponding component of `pos2`,
-- returning the two positions.
function areas:sortPos(pos1, pos2)
if pos1.x > pos2.x then
pos2.x, pos1.x = pos1.x, pos2.x
end
if pos1.y > pos2.y then
pos2.y, pos1.y = pos1.y, pos2.y
end
if pos1.z > pos2.z then
pos2.z, pos1.z = pos1.z, pos2.z
end
return pos1, pos2
end
-- Marks area position 1
areas.markPos1 = function(name)
local pos = areas.pos1[name]
if areas.marker1[name] ~= nil then -- Marker already exists
areas.marker1[name]:remove() -- Remove marker
areas.marker1[name] = nil
end
if pos ~= nil then -- Add marker
areas.marker1[name] = minetest.add_entity(pos, "areas:pos1")
areas.marker1[name]:get_luaentity().active = true
end
end
-- Marks area position 2
areas.markPos2 = function(name)
local pos = areas.pos2[name]
if areas.marker2[name] ~= nil then -- Marker already exists
areas.marker2[name]:remove() -- Remove marker
areas.marker2[name] = nil
end
if pos ~= nil then -- Add marker
areas.marker2[name] = minetest.add_entity(pos, "areas:pos2")
areas.marker2[name]:get_luaentity().active = true
end
end
minetest.register_entity("areas:pos1", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"areas_pos1.png", "areas_pos1.png",
"areas_pos1.png", "areas_pos1.png",
"areas_pos1.png", "areas_pos1.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
},
on_step = function(self, dtime)
if self.active == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
local name = hitter:get_player_name()
areas.marker1[name] = nil
end,
})
minetest.register_entity("areas:pos2", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"areas_pos2.png", "areas_pos2.png",
"areas_pos2.png", "areas_pos2.png",
"areas_pos2.png", "areas_pos2.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
},
on_step = function(self, dtime)
if self.active == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
local name = hitter:get_player_name()
areas.marker2[name] = nil
end,
})

46
mods/areas/settings.lua Normal file
View File

@ -0,0 +1,46 @@
local world_path = minetest.get_worldpath()
areas.config = {}
local function setting(name, tp, default)
local full_name = "areas." .. name
local value
if tp == "bool" then
value = minetest.settings:get_bool(full_name)
default = value == nil and minetest.is_yes(default)
elseif tp == "string" then
value = minetest.settings:get(full_name)
elseif tp == "v3f" then
value = minetest.setting_get_pos(full_name)
default = value == nil and minetest.string_to_pos(default)
elseif tp == "float" or tp == "int" then
value = tonumber(minetest.settings:get(full_name))
local v, other = default:match("^(%S+) (.+)")
default = value == nil and tonumber(other and v or default)
else
error("Cannot parse setting type " .. tp)
end
if value == nil then
value = default
assert(default ~= nil, "Cannot parse default for " .. full_name)
end
--print("add", name, default, value)
areas.config[name] = value
end
local file = io.open(areas.modpath .. "/settingtypes.txt", "r")
for line in file:lines() do
local name, tp, value = line:match("^areas%.(%S+) %(.*%) (%S+) (.*)")
if value then
setting(name, tp, value)
end
end
file:close()
--------------
-- Settings --
--------------
setting("filename", "string", world_path.."/areas.dat")

View File

@ -0,0 +1,37 @@
# This file is parsed in "settings.lua". Check regex first.
# Static paths do not work well with settings
#areas.filename (Configuration file path) string (world_path)/areas.dat
# Allow players with a privilege create their own areas using /protect
# within the specified size and amount limits.
areas.self_protection (Self protection) bool true
# Self protection: Privilege required to protect an area
areas.self_protection_privilege (Self protection: Required privs) string areas
# Refresh delay for the name displays in the HUD in seconds
areas.tick (HUD update delay) float 0.5 0 100
# Enable the legacy owner_defs metatable mode. Untested and possibly unstable
areas.legacy_table (Legacy owner_defs metatable) bool false
[Self protection (normal)]
# Self protection (normal): Maximal size of the protectable area
# Only enter positive whole numbers for the coordinate values or you'll mess up stuff.
areas.self_protection_max_size (Maximal area size) v3f (64, 128, 64)
# Self protection (normal): Maximal amount of protected areas per player
areas.self_protection_max_areas (Maximal area count) int 4
[Self protection (high)]
# Self protection (normal): Maximal size of the protectable area
# This setting applies for plyaers with the privilege 'areas_high_limit'
areas.self_protection_max_size_high (Maximal area size) v3f (512, 512, 512)
# Self protection (normal): Maximal amount of protected areas per player
# Only enter positive whole numbers for the coordinate values or you'll mess up stuff.
# This setting applies for plyaers with the privilege 'areas_high_limit'
areas.self_protection_max_areas_high (Maximal area count) float 32

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

View File

@ -0,0 +1,57 @@
--[[
Copyright 2017 Auke Kok <sofar@foo-projects.org>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]--
local def = 300 -- server must be empty for this long
local int = 15 -- check interval in seconds
local to = def
local function do_shutdown()
local i, _ = next(minetest.get_connected_players())
if not i then
to = to - int
else
to = def
minetest.after(int, do_shutdown)
return
end
if to < 0 then
minetest.log("action", "autoshutdown")
minetest.request_shutdown()
else
minetest.after(int, do_shutdown)
end
end
minetest.register_chatcommand("autoshutdown", {
params = "autoshutdown server",
description = "shut the server down after the last player leaves",
privs = {server = true},
func = function(name, param)
do_shutdown()
return true, "autoshutdown issued"
end,
})

View File

View File

@ -0,0 +1,2 @@
name = autoshutdown
description = Shut down the server after the last player leaves.

View File

@ -0,0 +1,11 @@
## autoshutdown mod
Allows admins to schedule a shutdown when the last player leaves.
The server shuts down a little time after the last player leaves,
to make sure all areas are slowly unloaded.
To schedule an automatic shutdown, issue the `/autoshutdown` command
in chat. The shutdown will only happen once.

19
mods/awards/LICENSE.txt Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2013-8 rubenwardy
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

295
mods/awards/README.md Normal file
View File

@ -0,0 +1,295 @@
# Awards
Adds awards/achievements to Minetest (plus a very good API).
by [rubenwardy](https://rubenwardy.com), licensed under MIT.
With thanks to Wuzzy, kaeza, and MrIbby.
Majority of awards are back ported from Calinou's old fork in Carbone, under same license.
# Introduction
## Awards and Triggers
An award is a single unlockable unit, registered like so:
```lua
awards.register_award("mymod:award", {
description = "My Example Award",
})
```
Awards are unlocked either using `awards.unlock()` or by a trigger being
fullfilled. A trigger is a condition which unlocks an award. Triggers are
registered at the same time as an award is registered:
```lua
awards.register_award("mymod:award", {
description = "My Example Award",
trigger = {
type = "dig",
node = "default:stone",
target = 10,
},
})
```
The above trigger type is an example of a counted_key trigger:
rather than a single counter there's a counter per key - in this
case the key is the value of the `node` field. If you leave out
the key in a `counted_key` trigger, then the total will be used
instead. For example, here is an award which unlocks after you've
placed 10 nodes of any type:
```lua
awards.register_award("mymod:award", {
description = "Place 10 nodes!",
trigger = {
type = "place",
target = 10,
},
})
```
You can also register an *Unlock Function*, which can return the name of an
award to unlock it:
```lua
awards.register_award("mymod:award", {
title = "Lava Miner",
description = "Mine any block while being very close to lava.",
})
awards.register_on_dig(function(player, data)
local pos = player:get_pos()
if pos and (minetest.find_node_near(pos, 1, "default:lava_source") or
minetest.find_node_near(pos, 1, "default:lava_flowing")) then
return "mymod:award"
end
return nil
end)
```
The above is a bad example as you don't actually need the stats data given.
It would be better to register a `dignode` callback and call `awards.unlock()`
if the condition is met.
## Trigger Types
The trigger type is used to determine which event will cause the trigger will be
fulfilled. The awards mod comes with a number of predefined types, documented
in [Builtin Trigger Types](#builtin-trigger-types).
Trigger types are registered like so:
```lua
awards.register_trigger("chat", {
type = "counted",
progress = "@1/@2 chat messages",
auto_description = { "Send a chat message", "Chat @1 times" },
})
minetest.register_on_chat_message(function(name, message)
local player = minetest.get_player_by_name(name)
if not player or string.find(message, "/") then
return
end
awards.notify_chat(player)
end)
```
A trigger type has a type as well, which determines how the data is stored and
also how the trigger is fulfilled.
**Trigger Type Types:**
* **custom** requires you handle the calling of awards.unlock() yourself. You also
need to implement on_register() yourself. You'll also probably want to implement
`on_register()` to catch awards registered with your trigger type.
* **counted** stores a single counter for each player which is incremented by calling
`trigger:notify(player)`. Good for homogenous actions like number of chat messages,
joins, and the like.
* **counted_key** stores a table of counters each indexed by a key. There is also
a total field (`__total`) which stores the sum of all counters. A counter is
incremented by calling `trigger:notify(player, key)`. This is good for things like
placing nodes or crafting items, where the key will be the item or node name.
If `key` is an item, then you should also add `key_is_item = true` to the
trigger type definition.
As said, you could use a custom trigger if none of the other ones match your needs.
Here's an example.
```lua
awards.register_trigger("foo", {
type = "custom",
progress = "@1/@2 foos",
auto_description = { "Do a foo", "Foo @1 times" },
})
minetest.register_on_foo(function()
for _, trigger in pairs(awards.on.foo) do
-- trigger is either a trigger tables or
-- or an unlock function.
-- some complex logic
if condition then
awards.unlock(trigger)
end
end
end)
```
## Award Difficulty
Difficulty is used to determine how awards are sorted in awards lists.
If the award trigger is counted, ie: the trigger requires a `target` property,
then the difficulty multipler is timesd by `target` to get the overall difficulty.
If the award isn't a counted type then the difficulty multiplier is used as the
overal difficulty. Award difficulty affects how awards are sorted in a list -
more difficult awards are further down the list.
In real terms, `difficulty` is a relative difficulty to do one unit of the trigger
if its counted, otherwise it's the relative difficulty of completely doing the
award (if not-counted). For the `dig` trigger type, 1 unit would be 1 node dug.
Actual code used to calculate award difficulty:
```lua
local difficulty = def.difficulty or 1
if def.trigger and def.trigger.target then
difficulty = difficulty * def.trigger.target
end
```
# API
* awards.register_award(name, def), the def table has the following fields:
* `title` - title of the award (defaults to name)
* `description` - longer description of the award, displayed in Awards tab
* `difficulty` - see [Award Difficulty](#award-difficulty).
* `requires` - list of awards that need to be unlocked before this one
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.
`false` to disable unlock sound.
* `icon` - the icon image, use default otherwise.
* `background` - the background image, use default otherwise.
* `trigger` - trigger definition, see [Builtin Trigger Types](#builtin-trigger-types).
* `on_unlock(name, def)` - callback on unlock.
* awards.register_trigger(name, def), the def table has the following fields:
* `type` - see [Trigger Types](#trigger-types).
* `progress` - used to format progress, defaults to "%1/%2".
* `auto_description` - a table of two elements. Each element is a format string. Element 1 is singular, element 2 is plural. Used for the award description (not title) if none is given.
* `on_register(award_def)` - called when an award registers with this type.
* "counted_key" only:
* `auto_description_total` - Used if the trigger is for the total.
* `get_key(self, def)` - get key for particular award, return nil for a total.
* `key_is_item` - true if the key is an item name. On notify(),
any watched groups will also be notified as `group:groupname` keys.
* awards.register_on_unlock(func(name, def))
* name is the player name
* def is the award def.
* return true to cancel HUD
* awards.unlock(name, award)
* gives an award to a player
* name is the player name
## Builtin Trigger Types
Callbacks (register a function to be run)
* dig type: Dig a node.
* node: the dug node type. If nil, all dug nodes are counted
* place type: Place a node.
* node: the placed node type. If nil, all placed nodes are counted
* craft type: Craft something.
* item: the crafted item type. If nil, all crafted items are counted
* death type: Die.
* reason: the death reason, one of the types in PlayerHPChangeReason (see lua_api.txt)
or nil for total deaths.
* chat type: Write a chat message.
* join type: Join the server.
* eat type: Eat an item.
* item: the eaten item type. If nil, all eaten items are counted
(for all types) target - how many times to dig/place/craft/etc.
Each type has a register function like so:
* awards.register_on_TRIGGERTYPE(func(player, data))
* data is the player stats data
* return award name or null
### dig
```lua
trigger = {
type = "dig",
node = "default:dirt", -- item, alias, or group
target = 50,
}
```
### place
```lua
trigger = {
type = "place",
node = "default:dirt", -- item, alias, or group
target = 50,
}
```
### craft
```lua
trigger = {
type = "craft",
item = "default:dirt", -- item, alias, or group
target = 50,
}
```
### death
```lua
trigger = {
type = "death",
reason = "fall",
target = 5,
}
```
### chat
```lua
trigger = {
type = "chat",
target = 100,
}
```
### join
```lua
trigger = {
type = "join",
target = 100,
}
```
### eat
```lua
trigger = {
type = "eat",
item = "default:apple",
target = 100,
}
```

36
mods/awards/init.lua Normal file
View File

@ -0,0 +1,36 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
-- The global award namespace
awards = {
show_mode = "hud",
registered_triggers = {},
}
-- Internationalization support.
awards.gettext, awards.ngettext = dofile(minetest.get_modpath("awards").."/src/intllib.lua")
-- Load files
dofile(minetest.get_modpath("awards").."/src/data.lua")
dofile(minetest.get_modpath("awards").."/src/api_awards.lua")
dofile(minetest.get_modpath("awards").."/src/api_triggers.lua")
dofile(minetest.get_modpath("awards").."/src/chat_commands.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
awards.give_achievement = awards.unlock
awards.getFormspec = awards.get_formspec
awards.showto = awards.show_to
awards.register_onDig = awards.register_on_dig
awards.register_onPlace = awards.register_on_place
awards.register_onDeath = awards.register_on_death
awards.register_onChat = awards.register_on_chat
awards.register_onJoin = awards.register_on_join
awards.register_onCraft = awards.register_on_craft
awards.def = awards.registered_awards
awards.register_achievement = awards.register_award

824
mods/awards/locale/de.po Normal file
View File

@ -0,0 +1,824 @@
# German translations for PACKAGE package.
# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Wuzzy2, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-21 05:35-0300\n"
"PO-Revision-Date: 2017-02-21 04:19-0300\n"
"Last-Translator: Wuzzy2\n"
"Language-Team: German\n"
"Language: de\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"
#: api.lua
msgid "Secret Achievement Unlocked:"
msgstr "Geheime Auszeichnung erhalten:"
#: api.lua
msgid "Achievement Unlocked:"
msgstr "Auszeichnung erhalten:"
#: api.lua
#, lua-format
msgid "Secret Achievement Unlocked: %s"
msgstr "Geheime Auszeichnung erhalten: %s"
#: api.lua
#, lua-format
msgid "Achievement Unlocked: %s"
msgstr "Auszeichnung erhalten: %s"
#: api.lua
msgid "Secret Achievement Unlocked!"
msgstr "Geheime Auszeichnung erhalten!"
#: api.lua
msgid "Achievement Unlocked!"
msgstr "Auszeichnung erhalten:"
#: api.lua
msgid "Error: No awards available."
msgstr "Fehler: Keine Auszeichnungen vorhanden."
#: api.lua
msgid "OK"
msgstr "OK"
#: api.lua
msgid "(Secret Award)"
msgstr "(Geheime Auszeichnung)"
#: api.lua
msgid "Unlock this award to find out what it is."
msgstr "Verdienen Sie sich diese Auszeichnung, um herauszufinden, was sie ist."
#: api.lua
#, lua-format
msgid "%s (got)"
msgstr "%s (erhalten)"
#: api.lua
msgid "You've disabled awards. Type /awards enable to reenable."
msgstr ""
"Sie haben die Auszeichnungen deaktiviert. Geben Sie »/awards enable« ein, um "
"sie wieder zu aktivieren."
#: api.lua
msgid "You have not unlocked any awards."
msgstr "Sie haben noch keine Auszeichnungen."
#: api.lua
#, lua-format
msgid "%ss awards:"
msgstr "%ss Auszeichnungen:"
#: api.lua chat_commands.lua
#, lua-format
msgid "%s: %s"
msgstr "%s: %s"
#: sfinv.lua unified_inventory.lua
msgid "Awards"
msgstr "Auszeichnungen"
#: triggers.lua
msgid "@1/@2 dug"
msgstr "@1/@2 abgebaut"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Mine: @2"
msgid_plural "Mine: @1×@2"
msgstr[0] "Bauen Sie einen Block ab: @2"
msgstr[1] "Bauen Sie Blöcke ab: @1×@2"
#: triggers.lua
msgid "Mine @1 block."
msgid_plural "Mine @1 blocks."
msgstr[0] "Bauen Sie einen @1 Block ab."
msgstr[1] "Bauen Sie @1 Blöcke ab."
#: triggers.lua
msgid "@1/@2 placed"
msgstr "@1/@2 platziert"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Place: @2"
msgid_plural "Place: @1×@2"
msgstr[0] "Platzieren Sie einen Block: @2"
msgstr[1] "Platzieren Sie Blöcke: @1×@2"
#: triggers.lua
msgid "Place a block."
msgid_plural "Place @1 blocks."
msgstr[0] "Platzieren Sie einen Block."
msgstr[1] "Platzieren Sie @1 Blöcke."
#: triggers.lua
msgid "@1/@2 eaten"
msgstr "@1/@2 gegessen"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Eat: @2"
msgid_plural "Eat: @1×@2"
msgstr[0] "Essen Sie: @2"
msgstr[1] "Essen Sie: @1×@2"
#: triggers.lua
msgid "Eat an item."
msgid_plural "Eat @1 items."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 deaths"
msgstr "@1/@2 Tode"
#: triggers.lua
msgid "Die."
msgid_plural "Die @1 times."
msgstr[0] "Sterben Sie."
msgstr[1] "Sterben Sie @1 mal."
#: triggers.lua
msgid "@1/@2 chat messages"
msgstr "@1/@2 Chatnachrichten"
#: triggers.lua
msgid "Write something in chat."
msgid_plural "Write @1 chat messages."
msgstr[0] "Schreiben Sie etwas im Chat."
msgstr[1] "Schreiben Sie @1 Chatnachrichten."
#: triggers.lua
msgid "@1/@2 game joins"
msgstr "@1/@2 Spielen beigetreten"
#: triggers.lua
msgid "Join the game."
msgid_plural "Join the game @1 times."
msgstr[0] "Treten Sie dem Spiel bei."
msgstr[1] "Treten Sie dem Spiel @1 mal bei."
#: triggers.lua
msgid "@1/@2 crafted"
msgstr "@1/@2 gefertigt"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Craft: @2"
msgid_plural "Craft: @1×@2"
msgstr[0] "Fertigen Sie an: @2"
msgstr[1] "Fertigen Sie an: @1×@2"
#: triggers.lua
msgid "Craft an item."
msgid_plural "Craft @1 items."
msgstr[0] ""
msgstr[1] ""
#: init.lua
msgid "Saint-Maclou"
msgstr "Saint-Maclou"
#: init.lua
msgid "Place 20 coal checkers."
msgstr "Platzieren Sie 20 Kohlenschachbrettmuster."
#: init.lua
msgid "Castorama"
msgstr "Gießmeister"
#: init.lua
msgid "Place 20 iron checkers."
msgstr "Platzieren Sie 20 Eisenschachbrettmuster."
#: init.lua
msgid "Sam the Trapper"
msgstr "Sam der Fallensteller"
#: init.lua
msgid "Place 2 trap stones."
msgstr "Platzieren Sie 2 Fallensteine."
#: init.lua
msgid "Backpacker"
msgstr "Rucksacktourist"
#: init.lua
msgid "Craft 4 large bags."
msgstr "Fertigen Sie 4 große Taschen."
#: init.lua
msgid "Pyromaniac"
msgstr "Pyromane"
#: init.lua
msgid "Craft 8 times flint and steel."
msgstr "Fertigen Sie 8 mal einen Feuerstein und Stahl an."
#: init.lua
msgid "Firefighter"
msgstr "Feuerwehr"
#: init.lua
msgid "Put out 1000 fires."
msgstr "Löschen Sie 1000 Flammen."
#: init.lua
msgid "Light It Up"
msgstr "Licht an!"
#: init.lua
msgid "Place 100 torches."
msgstr "Platzieren Sie 100 Fackeln."
#: init.lua
msgid "Well Lit"
msgstr "Gut ausgeleuchtet"
#: init.lua
msgid "Place 1,000 torches."
msgstr "Platzieren Sie 1000 Fackeln."
#: init.lua
msgid "Really Well Lit"
msgstr "Sehr gute Beleuchtung"
#: init.lua
msgid "Craft 10 mese lamps."
msgstr "Fertigen Sie 10 Meselampen."
#: init.lua
msgid "Outpost"
msgstr "Außenposten"
#: init.lua
msgid "Craft 200 stone bricks."
msgstr "Fertigen Sie 200 Steinziegel."
#: init.lua
msgid "Watchtower"
msgstr "Wachturm"
#: init.lua
msgid "Craft 800 stone bricks."
msgstr "Fertigen Sie 800 Steinziegel an."
#: init.lua
msgid "Fortress"
msgstr "Burg"
#: init.lua
msgid "Craft 3,200 stone bricks."
msgstr "Fertigen Sie 3200 Steinziegel."
#: init.lua
msgid "Desert Dweller"
msgstr "Wüstenbewohner"
#: init.lua
msgid "Craft 400 desert stone bricks."
msgstr "Fertigen Sie 400 Wüstensteinziegel."
#: init.lua
msgid "Pharaoh"
msgstr "Pharao"
#: init.lua
msgid "Craft 100 sandstone bricks."
msgstr "Fertigen Sie 100 Sandsteinziegel."
#: init.lua
msgid "Little Library"
msgstr "Kleine Bücherei"
#: init.lua
msgid "Craft 7 bookshelves."
msgstr "Fertigen Sie 7 Bücherregale."
#: init.lua
msgid "Lava and Water"
msgstr "Lava und Wasser"
#: init.lua
msgid "Mine your first obsidian."
msgstr "Bauen Sie Ihr erstes Obsidian ab."
#: init.lua
msgid "Obsessed with Obsidian"
msgstr "Von Obsidian besessen"
#: init.lua
msgid "Mine 50 obsidian."
msgstr "Bauen Sie 50 Obsidian ab."
#: init.lua
msgid "Lava Miner"
msgstr "Lavagräber"
#: init.lua
msgid "Mine any block while being very close to lava."
msgstr ""
"Bauen Sie einen beliebigen Block ab, während Sie sehr nahe an der Lava "
"stehen."
#: init.lua
msgid "On The Way"
msgstr "Auf dem Weg"
#: init.lua
msgid "Place 100 rails."
msgstr "Platzieren Sie 100 Gleise."
#: init.lua
msgid "First Day in the Woods"
msgstr "Erster Tag im Wald"
#: init.lua
msgid "Dig 6 tree blocks."
msgstr "Bauen Sie 6 Baumblöcke ab."
#: init.lua
msgid "Lumberjack"
msgstr "Holzfäller"
#: init.lua
msgid "Dig 36 tree blocks."
msgstr "Bauen Sie 36 Baumblöcke ab."
#: init.lua
msgid "Semi-pro Lumberjack"
msgstr "Fortgeschrittener Holzfäller"
#: init.lua
msgid "Dig 216 tree blocks."
msgstr "Bauen Sie 216 Baumblöcke ab."
#: init.lua
msgid "Professional Lumberjack"
msgstr "Profiholzfäller"
#: init.lua
msgid "Dig 1,296 tree blocks."
msgstr "Bauen Sie 1296 Baumblöcke ab."
#: init.lua
msgid "Junglebaby"
msgstr "Dschungelbaby"
#: init.lua
msgid "Dig 100 jungle tree blocks."
msgstr "Bauen Sie 100 Dschungelbaumblöcke ab."
#: init.lua
msgid "Jungleman"
msgstr "Dschungelmann"
#: init.lua
msgid "Dig 1,000 jungle tree blocks."
msgstr "Bauen Sie 1000 Dschungelbaumblöcke ab."
#: init.lua
msgid "First Mese Find"
msgstr "Erster Mesefund"
#: init.lua
msgid "Mine your first mese ore."
msgstr "Bauen Sie Ihr erstes Meseerz ab."
#: init.lua
msgid "Mese Mastery"
msgstr "Mesemeister"
#: init.lua
msgid "Mine a mese block."
msgstr "Bauen Sie einen Meseblock ab."
#: init.lua
msgid "Youre a copper"
msgstr "Du Kupfer!"
#: init.lua
msgid "Dig 1,000 copper ores."
msgstr "Bauen Sie 1000 Kupfererze ab."
#: init.lua
msgid "A Cat in a Pop-Tart?!"
msgstr "Eine Katze im Pop-Tart?!"
#: init.lua
msgid "Mine a nyan cat."
msgstr "Bauen Sie eine Nyan Cat ab."
#: init.lua
msgid "Mini Miner"
msgstr "Berganfänger"
#: init.lua
msgid "Dig 100 stone blocks."
msgstr "Bauen Sie 100 Steinblöcke ab."
#: init.lua
msgid "Hardened Miner"
msgstr "Abhehärteter Bergarbeiter"
#: init.lua
msgid "Dig 1,000 stone blocks."
msgstr "Bauen Sie 1000 Steine ab."
#: init.lua
msgid "Master Miner"
msgstr "Profibergarbeiter"
#: init.lua
msgid "Dig 10,000 stone blocks."
msgstr "Bauen Sie 10000 Steine ab."
#: init.lua
msgid "Marchand De Sable"
msgstr ""
#: init.lua
msgid "Dig 1,000 sand."
msgstr "Bauen Sie 1000 Sand ab."
#: init.lua
msgid "Crafter of Sticks"
msgstr "Stockmacher"
#: init.lua
msgid "Craft 100 sticks."
msgstr "Fertigen Sie 100 Stöcke."
#: init.lua
msgid "Jungle Discoverer"
msgstr "Dschungelerkunder"
#: init.lua
msgid "Mine your first jungle grass."
msgstr "Bauen Sie Ihr erstes Dschungelgras ab."
#: init.lua
msgid "Grasslands Discoverer"
msgstr "Prärieerkunder"
#: init.lua
msgid "Mine some grass."
msgstr "Bauen Sie etwas Gras ab."
#: init.lua
msgid "Savannah Discoverer"
msgstr "Savannenerkunder"
#: init.lua
msgid "Mine some dry grass."
msgstr "Bauen Sie etwas trockenes Gras ab."
#: init.lua
msgid "Desert Discoverer"
msgstr "Wüstenerkunder"
#: init.lua
msgid "Mine your first cactus."
msgstr "Bauen Sie Ihren ersten Kaktus ab."
#: init.lua
msgid "Far Lands"
msgstr "Ferne Lande"
#: init.lua
msgid "Mine your first dry shrub."
msgstr "Bauen Sie Ihren ersten vertrockneten Strauch ab."
#: init.lua
msgid "Glacier Discoverer"
msgstr "Gletschererkunder"
#: init.lua
msgid "Mine your first ice."
msgstr "Bauen Sie Ihr erstes Eis ab."
#: init.lua
msgid "Very Simple Snow Man"
msgstr "Sehr simpler Schneemann"
#: init.lua
msgid "Place two snow blocks."
msgstr "Platzieren Sie zwei Schneeblöcke."
#: init.lua
msgid "First Gold Find"
msgstr "Erster Goldfund"
#: init.lua
msgid "Mine your first gold ore."
msgstr "Bauen Sie Ihr erstes Golderz ab."
#: init.lua
msgid "Gold Rush"
msgstr "Goldrausch"
#: init.lua
msgid "Mine 45 gold ores."
msgstr "Bauen Sie 18 Diamanterze ab."
#: init.lua
msgid "Wow, I am Diamonds!"
msgstr "Wow, ich bin Diamanten!"
#: init.lua
msgid "Mine your first diamond ore."
msgstr "Bauen Sie Ihr erstes Diamanterz ab."
#: init.lua
msgid "Girl's Best Friend"
msgstr "Bester Freund der Mädchen"
#: init.lua
msgid "Mine 18 diamond ores."
msgstr "Bauen Sie 18 Diamanterze ab."
#: init.lua
msgid "Hardest Block on Earth"
msgstr "Härtester Block der Welt"
#: init.lua
msgid "Craft a diamond block."
msgstr "Fertigen Sie einen Diamantblock an."
#: init.lua
msgid "In the Dungeon"
msgstr "Im Verlies"
#: init.lua
msgid "Mine a mossy cobblestone."
msgstr "Bauen Sie ein bemoostes Kopfsteinpflaster ab."
#: init.lua
msgid "Smelter"
msgstr "Schmelzer"
#: init.lua
msgid "Craft 10 furnaces."
msgstr "Fertigen Sie 10 Öfen."
#: init.lua
msgid "Treasurer"
msgstr "Schatzmeister"
#: init.lua
msgid "Craft 15 chests."
msgstr "Fertigen Sie 15 Truhen."
#: init.lua
msgid "Bankier"
msgstr "Bankier"
#: init.lua
msgid "Craft 30 locked chests."
msgstr "Fertigen Sie 30 abgeschlossene Truhen."
#: init.lua
msgid "Bricker"
msgstr "Ziegler"
#: init.lua
msgid "Craft 200 brick blocks."
msgstr "Fertigen Sie 200 Ziegelblöcke."
#: init.lua
msgid "House of Obsidian"
msgstr "Haus aus Obsidian"
#: init.lua
msgid "Craft 100 obsidian bricks."
msgstr "Fertigen Sie 100 Obsidianziegel."
#: init.lua
msgid "Build a Cave"
msgstr "Höhlenbauer"
#: init.lua
msgid "Place 100 stone."
msgstr "Platzieren Sie 100 Steine."
#: init.lua
msgid "Long Ladder"
msgstr "Lange Leiter"
#: init.lua
msgid "Place 400 wooden ladders."
msgstr "Platzieren Sie 400 Holzleitern."
#: init.lua
msgid "Industrial Age"
msgstr "Industriezeitalter"
#: init.lua
msgid "Place 40 steel ladders."
msgstr "Platzieren Sie 40 Stahlleitern."
#: init.lua
msgid "Yummy!"
msgstr "Lecker!"
#: init.lua
msgid "Eat 80 apples."
msgstr "Essen Sie 80 Äpfel."
#: init.lua
msgid "Glasser"
msgstr "Glasmacher"
#: init.lua
msgid "Craft 14 vessels shelves."
msgstr "Fertigen Sie 14 Gefäßregale."
#: init.lua
msgid "Farming Skills Acquired"
msgstr "Landwirtschaft erlernt"
#: init.lua
msgid "Harvest a fully grown wheat plant."
msgstr "Ernten Sie eine voll ausgewachsene Getreidepflanze."
#: init.lua
msgid "Field Worker"
msgstr "Feldarbeiter"
#: init.lua
msgid "Harvest 25 fully grown wheat plants."
msgstr "Ernten Sie 25 voll ausgewachsene Getreidepflanzen."
#: init.lua
msgid "Aspiring Farmer"
msgstr "Aufstrebender Bauer"
#: init.lua
msgid "Harvest 125 fully grown wheat plants."
msgstr "Ernten Sie 125 voll ausgewachsene Getreidepflanzen."
#: init.lua
msgid "Wheat Magnate"
msgstr "Getreidemagnat"
#: init.lua
msgid "Harvest 625 fully grown wheat plants."
msgstr "Ernten Sie 625 voll ausgewachsene Getreidepflanzen."
#: init.lua
msgid "Baker"
msgstr "Bäcker"
#: init.lua
msgid "Eat 10 loaves of bread."
msgstr "Essen Sie 10 Brote."
#: init.lua
msgid "Wool Over Your Eyes"
msgstr "Wollige Augen"
#: init.lua
msgid "Craft 250 white wool."
msgstr "Fertigen Sie 250 weiße Wolle."
#: init.lua
msgid "Hotelier"
msgstr "Hotelier"
#: init.lua
msgid "Craft 15 fancy beds."
msgstr "Fertigen Sie 15 schicke Betten."
#: init.lua
msgid "Filthy Rich"
msgstr "Stinkreich"
#: init.lua
msgid "Craft 24 gold block stairs."
msgstr "Fertigen Sie 24 Goldblockstufen."
#: init.lua
msgid "Roses Are Red"
msgstr "Rosen sind rot"
#: init.lua
msgid "Craft 400 red dyes."
msgstr "Fertigen Sie 400 rote Farbstoffe."
#: init.lua
msgid "Dandelions are Yellow"
msgstr "Löwenzahn ist gelb"
#: init.lua
msgid "Craft 400 yellow dyes."
msgstr "Fertigen Sie 400 gelbe Farbstoffe."
#: init.lua
msgid "Geraniums are Blue"
msgstr "Geranien sind blau"
#: init.lua
msgid "Craft 400 blue dyes."
msgstr "Fertigen Sie 400 blaue Farbstoffe."
#: init.lua
msgid "White Color Stock"
msgstr "Weißer Farbstoffvorrat"
#: init.lua
msgid "Craft 100 white dyes."
msgstr "Fertigen Sie 100 weiße Farbstoffe."
#: init.lua
msgid "Tasty Mushrooms"
msgstr "Leckere Pilze"
#: init.lua
msgid "Eat 3 brown mushrooms."
msgstr "Essen Sie 3 braune Pilze."
#: init.lua
msgid "Mushroom Lover"
msgstr "Pilzfreund"
#: init.lua
msgid "Eat 33 brown mushrooms."
msgstr "Essen Sie 33 braune Pilze."
#: init.lua
msgid "Underground Mushroom Farmer"
msgstr "Unterirdischer Pilzbauer"
#: init.lua
msgid "Eat 333 brown mushrooms."
msgstr "Essen Sie 333 braune Pilze."
#: init.lua
msgid "Builder"
msgstr "Bauarbeiter"
#: init.lua
msgid "Constructor"
msgstr "Konstrukteur"
#: init.lua
msgid "Architect"
msgstr "Architekt"
#: init.lua
msgid "Master Architect"
msgstr "Meisterarchitekt"
#: 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 "Zeigen, löschen, deaktivieren oder aktivieren Sie Ihre Auszeichnungen"
#: chat_commands.lua
msgid ""
"All your awards and statistics have been cleared. You can now start again."
msgstr ""
"All Ihre Auszeichnugen und Statistiken wurden zurückgesetzt. Sie können nun "
"von vorne anfangen."
#: chat_commands.lua
msgid "You have disabled your achievements."
msgstr "Sie haben Ihre Auszeichnungen deaktiviert."
#: chat_commands.lua
msgid "You have enabled your achievements."
msgstr "Sie haben Ihre Auszeichnungen aktiviert."
#: chat_commands.lua
msgid "<achievement ID>"
msgstr "<Auszeichnungs-ID>"
#: chat_commands.lua
msgid "Show details of an achievement"
msgstr "Details einer Auszeichnung anzeigen"
#: chat_commands.lua
msgid "Achievement not found."
msgstr "Auszeichnung nicht gefunden."
#: chat_commands.lua
msgid "<name>"
msgstr "<Name>"
#: chat_commands.lua
msgid "Get the achievements statistics for the given player or yourself"
msgstr "Die Statistik der Auszeichnungen eines Spielers zeigen"

825
mods/awards/locale/es.po Normal file
View File

@ -0,0 +1,825 @@
# Spanish translations for PACKAGE package
# Traducciones al español para el paquete PACKAGE.
# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Diego Martínez <kaeza@users.noreply.github.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-21 05:35-0300\n"
"PO-Revision-Date: 2017-02-20 22:17-0300\n"
"Last-Translator: Diego Martínez <kaeza@users.noreply.github.com>\n"
"Language-Team: Spanish\n"
"Language: es\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"
#: api.lua
msgid "Secret Achievement Unlocked:"
msgstr "Logro secreto desbloqueado:"
#: api.lua
msgid "Achievement Unlocked:"
msgstr "Logro desbloqueado:"
#: api.lua
#, lua-format
msgid "Secret Achievement Unlocked: %s"
msgstr "Logro secreto desbloqueado: %s"
#: api.lua
#, lua-format
msgid "Achievement Unlocked: %s"
msgstr "Logro desbloqueado: %s"
#: api.lua
msgid "Secret Achievement Unlocked!"
msgstr "Logro secreto desbloqueado!"
#: api.lua
msgid "Achievement Unlocked!"
msgstr "Logro desbloqueado!"
#: api.lua
msgid "Error: No awards available."
msgstr "Error: No hay logros disponibles."
#: api.lua
msgid "OK"
msgstr "Aceptar"
#: api.lua
msgid "(Secret Award)"
msgstr "(Logro secreto)"
#: api.lua
msgid "Unlock this award to find out what it is."
msgstr "Desbloquea éste logro para saber qué es."
#: api.lua
#, lua-format
msgid "%s (got)"
msgstr "%s (obtenido)"
#: api.lua
msgid "You've disabled awards. Type /awards enable to reenable."
msgstr ""
"Has deshabilitado los logros. Escribe \"/awards enable\" para reactivar."
#: api.lua
msgid "You have not unlocked any awards."
msgstr "No has desbloqueado ningún logro."
#: api.lua
#, lua-format
msgid "%ss awards:"
msgstr "Logros de %s:"
#: api.lua chat_commands.lua
#, lua-format
msgid "%s: %s"
msgstr "%s: %s"
#: sfinv.lua unified_inventory.lua
msgid "Awards"
msgstr "Logros"
#: triggers.lua
msgid "@1/@2 dug"
msgstr "@1/@2 excavados"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Mine: @2"
msgid_plural "Mine: @1×@2"
msgstr[0] "Excavar: @2"
msgstr[1] "Excavar: @1×@2"
#: triggers.lua
msgid "Mine @1 block."
msgid_plural "Mine @1 blocks."
msgstr[0] "Excavar un bloque."
msgstr[1] "Excavar @1 bloques."
#: triggers.lua
msgid "@1/@2 placed"
msgstr "@1/@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] "Colocar: @1×@2"
#: triggers.lua
msgid "Place a block."
msgid_plural "Place @1 blocks."
msgstr[0] "Colocar un bloque."
msgstr[1] "Colocar @1 bloques."
#: triggers.lua
msgid "@1/@2 eaten"
msgstr "@1/@2 comidos"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Eat: @2"
msgid_plural "Eat: @1×@2"
msgstr[0] "Comer: @2"
msgstr[1] "Comer: @1×@2"
#: triggers.lua
msgid "Eat an item."
msgid_plural "Eat @1 items."
msgstr[0] "Comer un objeto."
msgstr[1] "Comer @1 objetos."
#: triggers.lua
msgid "@1/@2 deaths"
msgstr "@1/@2 muertes"
#: triggers.lua
msgid "Die."
msgid_plural "Die @1 times."
msgstr[0] "Morir."
msgstr[1] "Morir @1 veces."
#: triggers.lua
msgid "@1/@2 chat messages"
msgstr "@1/@2 conversaciones"
#: triggers.lua
msgid "Write something in chat."
msgid_plural "Write @1 chat messages."
msgstr[0] "Escribir algo."
msgstr[1] "Escribir @1 mensajes."
#: triggers.lua
msgid "@1/@2 game joins"
msgstr "@1/@2 veces unido"
#: triggers.lua
msgid "Join the game."
msgid_plural "Join the game @1 times."
msgstr[0] "Unirse al juego."
msgstr[1] "Unirse al juego @1 veces."
#: triggers.lua
msgid "@1/@2 crafted"
msgstr "@1/@2 elaborado"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Craft: @2"
msgid_plural "Craft: @1×@2"
msgstr[0] "Elaborar: @2"
msgstr[1] "Elaborar: %1×@2"
#: triggers.lua
msgid "Craft an item."
msgid_plural "Craft @1 items."
msgstr[0] "Elaborar un objeto."
msgstr[1] "Elaborar @1 objetos."
#: init.lua
msgid "Saint-Maclou"
msgstr "Saint-Maclou"
#: init.lua
msgid "Place 20 coal checkers."
msgstr "Colocar 20 baldosas de ajedrez de carbón."
#: init.lua
msgid "Castorama"
msgstr "Castorama"
#: init.lua
msgid "Place 20 iron checkers."
msgstr "Colocar 20 baldosas de ajedrez de hierro."
#: init.lua
msgid "Sam the Trapper"
msgstr "Sam el Atrapador"
#: init.lua
msgid "Place 2 trap stones."
msgstr "Colocar 2 piedras trampa."
#: init.lua
msgid "Backpacker"
msgstr "Mochilero"
#: init.lua
msgid "Craft 4 large bags."
msgstr "Elaborar 4 bolsas grandes."
#: init.lua
msgid "Pyromaniac"
msgstr "Piromaníaco"
#: init.lua
msgid "Craft 8 times flint and steel."
msgstr "Elaborar pedernal y hierro 8 veces."
#: init.lua
msgid "Firefighter"
msgstr "Bombero"
#: init.lua
msgid "Put out 1000 fires."
msgstr "Apagar 1000 incendios."
#: init.lua
msgid "Light It Up"
msgstr "Ilumínalo"
#: init.lua
msgid "Place 100 torches."
msgstr "Colocar 100 antorchas."
#: init.lua
msgid "Well Lit"
msgstr "Bien Iluminado"
#: init.lua
msgid "Place 1,000 torches."
msgstr "Colocar 1.000 antorchas."
#: init.lua
msgid "Really Well Lit"
msgstr "Realmente Bien Iluminado"
#: init.lua
msgid "Craft 10 mese lamps."
msgstr "Elaborar 10 lámparas de MESE."
#: init.lua
msgid "Outpost"
msgstr "Puesto de avanzada"
#: init.lua
msgid "Craft 200 stone bricks."
msgstr "Elaborar 200 ladrillos de piedra."
#: init.lua
msgid "Watchtower"
msgstr "Torre del vigía"
#: init.lua
msgid "Craft 800 stone bricks."
msgstr "Elaborar 800 ladrillos de piedra."
#: init.lua
msgid "Fortress"
msgstr "Fortaleza"
#: init.lua
msgid "Craft 3,200 stone bricks."
msgstr "Elaborar 3.200 ladrillos de piedra."
#: init.lua
msgid "Desert Dweller"
msgstr "Morador Desértico"
#: init.lua
msgid "Craft 400 desert stone bricks."
msgstr "Elaborar 400 ladrillos de piedra desértica."
#: init.lua
msgid "Pharaoh"
msgstr "Faraón"
#: init.lua
msgid "Craft 100 sandstone bricks."
msgstr "Elaborar 200 ladrillos de arenisca."
#: init.lua
msgid "Little Library"
msgstr "Pequeña Biblioteca"
#: init.lua
msgid "Craft 7 bookshelves."
msgstr "Elaborar 7 libreros."
#: init.lua
msgid "Lava and Water"
msgstr "Lava y Agua"
#: init.lua
msgid "Mine your first obsidian."
msgstr "Excavar tu primera obsidiana."
#: init.lua
msgid "Obsessed with Obsidian"
msgstr "Obsesionado con la Obsidiana"
#: init.lua
msgid "Mine 50 obsidian."
msgstr "Excavar 50 obsidianas."
#: init.lua
msgid "Lava Miner"
msgstr "Minero de Lava"
#: init.lua
msgid "Mine any block while being very close to lava."
msgstr "Excavar un bloque cerca de lava."
#: init.lua
msgid "On The Way"
msgstr "En Camino"
#: init.lua
msgid "Place 100 rails."
msgstr "Colocar 100 rieles."
#: init.lua
msgid "First Day in the Woods"
msgstr "Primer Día en el Bosque"
#: init.lua
msgid "Dig 6 tree blocks."
msgstr "Cortar 6 árboles."
#: init.lua
msgid "Lumberjack"
msgstr "Leñador"
#: init.lua
msgid "Dig 36 tree blocks."
msgstr "Cortar 36 árboles."
#: init.lua
msgid "Semi-pro Lumberjack"
msgstr "Leñador semi-profesional"
#: init.lua
msgid "Dig 216 tree blocks."
msgstr "Cortar 216 árboles."
#: init.lua
msgid "Professional Lumberjack"
msgstr "Leñador profesional"
#: init.lua
msgid "Dig 1,296 tree blocks."
msgstr "Cortar 1.296 árboles."
#: init.lua
msgid "Junglebaby"
msgstr "Bebé de la Selva"
#: init.lua
msgid "Dig 100 jungle tree blocks."
msgstr "Cortar 100 árboles selváticos."
#: init.lua
msgid "Jungleman"
msgstr "Hombre de la Selva"
#: init.lua
msgid "Dig 1,000 jungle tree blocks."
msgstr "Cortar 1.000 árboles selváticos."
#: init.lua
msgid "First Mese Find"
msgstr "Primer Encuentro de MESE"
#: init.lua
msgid "Mine your first mese ore."
msgstr "Excava tu primer mineral de MESE."
#: init.lua
msgid "Mese Mastery"
msgstr "Maestría de MESE"
#: init.lua
msgid "Mine a mese block."
msgstr "Excava tu primer bloque de MESE."
#: init.lua
msgid "Youre a copper"
msgstr "Eres un cobre"
#: init.lua
msgid "Dig 1,000 copper ores."
msgstr "Excavar 1.000 minerales de cobre"
#: init.lua
msgid "A Cat in a Pop-Tart?!"
msgstr "¡¿Un Gato en un Pop-Tart?!"
#: init.lua
msgid "Mine a nyan cat."
msgstr "Excavar un Gato Nyan."
#: init.lua
msgid "Mini Miner"
msgstr "Mini Minero"
#: init.lua
msgid "Dig 100 stone blocks."
msgstr "Excavar 100 bloques de piedra."
#: init.lua
msgid "Hardened Miner"
msgstr "Minero Curtido"
#: init.lua
msgid "Dig 1,000 stone blocks."
msgstr "Excavar 1.000 bloques de piedra."
#: init.lua
msgid "Master Miner"
msgstr "Minero Maestro"
#: init.lua
msgid "Dig 10,000 stone blocks."
msgstr "Excavar 10.000 bloques de piedra."
#: init.lua
msgid "Marchand De Sable"
msgstr "Marchand De Sable"
#: init.lua
msgid "Dig 1,000 sand."
msgstr "Cavar 1.000 bloques de arena."
#: init.lua
msgid "Crafter of Sticks"
msgstr "Elaborador de Varitas"
#: init.lua
msgid "Craft 100 sticks."
msgstr "Elaborar 100 varitas."
#: init.lua
msgid "Jungle Discoverer"
msgstr "Descubridor de Selva"
#: init.lua
msgid "Mine your first jungle grass."
msgstr "Cortar tu primer pasto de selva."
#: init.lua
msgid "Grasslands Discoverer"
msgstr "Descubridor de Praderas"
#: init.lua
msgid "Mine some grass."
msgstr "Cortar un poco de pasto."
#: init.lua
msgid "Savannah Discoverer"
msgstr "Descubridor de Savana"
#: init.lua
msgid "Mine some dry grass."
msgstr "Cortar un poco de pasto seco."
#: init.lua
msgid "Desert Discoverer"
msgstr "Descubridor del Desierto"
#: init.lua
msgid "Mine your first cactus."
msgstr "Cortar tu primer cácto."
#: init.lua
msgid "Far Lands"
msgstr "Tierras Lejanas"
#: init.lua
msgid "Mine your first dry shrub."
msgstr "Cortar tu primer arbusto seco"
#: init.lua
msgid "Glacier Discoverer"
msgstr "Descubridor del Glaciar"
#: init.lua
msgid "Mine your first ice."
msgstr "Romper tu primer bloque de hielo."
#: init.lua
msgid "Very Simple Snow Man"
msgstr "Muñeco de Nieve Muy Simple"
#: init.lua
msgid "Place two snow blocks."
msgstr "Colocar dos bloques de nieve."
#: init.lua
msgid "First Gold Find"
msgstr "Primer Encuentro de Oro"
#: init.lua
msgid "Mine your first gold ore."
msgstr "Excavar tu primer pepita de oro."
#: init.lua
msgid "Gold Rush"
msgstr "Fiebre del Oro"
#: init.lua
msgid "Mine 45 gold ores."
msgstr "Excavar 45 pepitas de oro."
#: init.lua
msgid "Wow, I am Diamonds!"
msgstr "¡Guau, Soy Diamantes!"
#: init.lua
msgid "Mine your first diamond ore."
msgstr "Excava tu primer diamante."
#: init.lua
msgid "Girl's Best Friend"
msgstr "El Mejor Amigo de Las Mujeres"
#: init.lua
msgid "Mine 18 diamond ores."
msgstr "Excava 10 diamantes."
#: init.lua
msgid "Hardest Block on Earth"
msgstr "El Bloque Más Duro Sobre La Tierra"
#: init.lua
msgid "Craft a diamond block."
msgstr "Elaborar un bloque de diamante."
#: init.lua
msgid "In the Dungeon"
msgstr "En Las Mazmorras"
#: init.lua
msgid "Mine a mossy cobblestone."
msgstr "Excavar unos adoquines musgosos."
#: init.lua
msgid "Smelter"
msgstr "Fundidor"
#: init.lua
msgid "Craft 10 furnaces."
msgstr "Elaborar 10 hornos."
#: init.lua
msgid "Treasurer"
msgstr "Tesorero"
#: init.lua
msgid "Craft 15 chests."
msgstr "Elaborar 15 cofres."
#: init.lua
msgid "Bankier"
msgstr "Banquero"
#: init.lua
msgid "Craft 30 locked chests."
msgstr "Elaborar 30 bloques cerrados."
#: init.lua
msgid "Bricker"
msgstr "Ladrillero"
#: init.lua
msgid "Craft 200 brick blocks."
msgstr "Elaborar 200 bloques de ladrillo."
#: init.lua
msgid "House of Obsidian"
msgstr "Casa de Obsidiana"
#: init.lua
msgid "Craft 100 obsidian bricks."
msgstr "Elaborar 100 ladrillos de obsidiana."
#: init.lua
msgid "Build a Cave"
msgstr "Construye Una Cueva"
#: init.lua
msgid "Place 100 stone."
msgstr "Coloca 100 piedras."
#: init.lua
msgid "Long Ladder"
msgstr "Escalerilla Larga"
#: init.lua
msgid "Place 400 wooden ladders."
msgstr "Coloca 400 escalerillas de madera."
#: init.lua
msgid "Industrial Age"
msgstr "Era Industrial"
#: init.lua
msgid "Place 40 steel ladders."
msgstr "Coloca 40 escalerillas de acero."
#: init.lua
msgid "Yummy!"
msgstr "¡Qué Rico!"
#: init.lua
msgid "Eat 80 apples."
msgstr "Come 80 manzanas."
# Intentionally marked as fuzzy.
#: init.lua
#, fuzzy
msgid "Glasser"
msgstr "Vidriero"
#: init.lua
msgid "Craft 14 vessels shelves."
msgstr "Elabora 14 estanterías para botellas."
#: init.lua
msgid "Farming Skills Acquired"
msgstr "Habilidades de Granja Adquiridas"
#: init.lua
msgid "Harvest a fully grown wheat plant."
msgstr "Cosecha una plantas de trigo madura."
#: init.lua
msgid "Field Worker"
msgstr "Trabajador de Campo"
#: init.lua
msgid "Harvest 25 fully grown wheat plants."
msgstr "Cosecha 25 plantas de trigo maduras."
#: init.lua
msgid "Aspiring Farmer"
msgstr "Aspirante a Granjero"
#: init.lua
msgid "Harvest 125 fully grown wheat plants."
msgstr "Cosecha 125 plantas de trigo maduras."
#: init.lua
msgid "Wheat Magnate"
msgstr "Magnate del Maíz"
#: init.lua
msgid "Harvest 625 fully grown wheat plants."
msgstr "Cosecha 625 plantas de trigo maduras."
#: init.lua
msgid "Baker"
msgstr "Panadero"
#: init.lua
msgid "Eat 10 loaves of bread."
msgstr "Come 10 rebanadas de pan."
#: init.lua
msgid "Wool Over Your Eyes"
msgstr "Lana Sobre Tus Ojos"
#: init.lua
msgid "Craft 250 white wool."
msgstr "Elabora 250 bloques de lana blanca."
#: init.lua
msgid "Hotelier"
msgstr "Hotelero"
#: init.lua
msgid "Craft 15 fancy beds."
msgstr "Elabora 15 camas de lujo."
#: init.lua
msgid "Filthy Rich"
msgstr "Sucio Rico"
#: init.lua
msgid "Craft 24 gold block stairs."
msgstr "Elabora 24 escaleras de bloque de oro."
#: init.lua
msgid "Roses Are Red"
msgstr "Las Rosas Son Rojas"
#: init.lua
msgid "Craft 400 red dyes."
msgstr "Elabora 400 colorantes rojos."
#: init.lua
msgid "Dandelions are Yellow"
msgstr "Los Dientes de León Son Amarillos"
#: init.lua
msgid "Craft 400 yellow dyes."
msgstr "Elabora 400 colorantes amarillos."
#: init.lua
msgid "Geraniums are Blue"
msgstr "Los Geranios Son Azules"
#: init.lua
msgid "Craft 400 blue dyes."
msgstr "Elabora 400 colorantes azules."
#: init.lua
msgid "White Color Stock"
msgstr "Reserva de Color Blanco"
#: init.lua
msgid "Craft 100 white dyes."
msgstr "Elabora 100 colorantes blancos."
#: init.lua
msgid "Tasty Mushrooms"
msgstr "Ricos Hongos"
#: init.lua
msgid "Eat 3 brown mushrooms."
msgstr "Come 3 hongos marrones."
#: init.lua
msgid "Mushroom Lover"
msgstr "Amante de los Hongos"
#: init.lua
msgid "Eat 33 brown mushrooms."
msgstr "Come 33 hongos marrones."
#: init.lua
msgid "Underground Mushroom Farmer"
msgstr "Granjero de Hongos Subterráneo"
#: init.lua
msgid "Eat 333 brown mushrooms."
msgstr "Come 333 hongos marrones."
# Nota: "Builder" y "Constructor" se traducen a "Constructor",
# así que lo traduje de ésta manera para diferenciar.
#: init.lua
msgid "Builder"
msgstr "Hacedor"
#: init.lua
msgid "Constructor"
msgstr "Constructor"
#: init.lua
msgid "Architect"
msgstr "Arquitecto"
#: init.lua
msgid "Master Architect"
msgstr "Maestro Arquitecto"
#: 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 "Mostrar, limpiar, deshabilitar o habilitar tus logros"
#: chat_commands.lua
msgid ""
"All your awards and statistics have been cleared. You can now start again."
msgstr ""
"Todos tus logros y estadísticas han sido borrados. Puedes iniciar nuevamente."
#: chat_commands.lua
msgid "You have disabled your achievements."
msgstr "Has deshabilitado tus logros."
#: chat_commands.lua
msgid "You have enabled your achievements."
msgstr "Has habilitado tus logros."
#: chat_commands.lua
msgid "<achievement ID>"
msgstr "<ID logro>"
#: chat_commands.lua
msgid "Show details of an achievement"
msgstr "Muestra los detalles de un logro"
#: chat_commands.lua
msgid "Achievement not found."
msgstr "Logro no encontrado."
#: chat_commands.lua
msgid "<name>"
msgstr "<nombre>"
#: chat_commands.lua
msgid "Get the achievements statistics for the given player or yourself"
msgstr "Obtener las estadísticas y logros del jugador dado"

818
mods/awards/locale/fr.po Normal file
View File

@ -0,0 +1,818 @@
# French translations for PACKAGE package.
# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# xisd, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-21 05:50-0300\n"
"PO-Revision-Date: 2017-02-21 05:50-0300\n"
"Last-Translator: xisd\n"
"Language-Team: French\n"
"Language: fr\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"
#: api.lua
msgid "Secret Achievement Unlocked:"
msgstr "Réussite Secrète Débloquée :"
#: api.lua
msgid "Achievement Unlocked:"
msgstr "Réussite Débloquée :"
#: api.lua
#, lua-format
msgid "Secret Achievement Unlocked: %s"
msgstr "Réussite Secrète Débloquée : %s"
#: api.lua
#, lua-format
msgid "Achievement Unlocked: %s"
msgstr "Réussite Débloquée : %s"
#: api.lua
msgid "Secret Achievement Unlocked!"
msgstr "Réussite Secrète Débloquée !"
#: api.lua
msgid "Achievement Unlocked!"
msgstr "Réussite Débloquée !"
#: api.lua
msgid "Error: No awards available."
msgstr "Erreur : Aucun trophée disponible"
#: api.lua
msgid "OK"
msgstr "OK"
#: api.lua
msgid "(Secret Award)"
msgstr "(Trophée Secret)"
#: api.lua
msgid "Unlock this award to find out what it is."
msgstr "Débloque ce trophée pour découvrir ce que c'est."
#: api.lua
#, lua-format
msgid "%s (got)"
msgstr "%s (obtenu)"
#: api.lua
msgid "You've disabled awards. Type /awards enable to reenable."
msgstr "Vous avez désactivé les trophées. Tapez '/awards enable' pour les réactiver."
#: api.lua
msgid "You have not unlocked any awards."
msgstr "Vous n'avez encore débloqué aucun trophée."
#: api.lua
#, lua-format
msgid "%ss awards:"
msgstr "Les trophées de %s :"
#: api.lua chat_commands.lua
#, lua-format
msgid "%s: %s"
msgstr "%s : %s"
#: sfinv.lua unified_inventory.lua
msgid "Awards"
msgstr "Trophées"
#: triggers.lua
msgid "@1/@2 dug"
msgstr "@1/@2 creusés"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Mine: @2"
msgid_plural "Mine: @1×@2"
msgstr[0] "Mine : @2"
msgstr[1] "Mine : @1×@2"
#: triggers.lua
msgid "Mine @1 block."
msgid_plural "Mine @1 blocks."
msgstr[0] "Creuse @1 bloc."
msgstr[1] "Creuse @1 blocs."
#: triggers.lua
msgid "@1/@2 placed"
msgstr "@1/@2 placés"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Place: @2"
msgid_plural "Place: @1×@2"
msgstr[0] "Place : @2"
msgstr[1] "Place : @1×@2"
#: triggers.lua
msgid "Place a block."
msgid_plural "Place @1 blocks."
msgstr[0] "Place un bloc."
msgstr[1] "Place @1 blocs."
#: triggers.lua
msgid "@1/@2 eaten"
msgstr "@1/@2 Mangés"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Eat: @2"
msgid_plural "Eat: @1×@2"
msgstr[0] "Mange : @2"
msgstr[1] "Mange : @1×@2"
#: triggers.lua
msgid "Eat an item."
msgid_plural "Eat @1 items."
msgstr[0] "Mange quelque chose."
msgstr[1] "Mange @1 aliments."
#: triggers.lua
msgid "@1/@2 deaths"
msgstr "@1/@2 morts"
#: triggers.lua
msgid "Die."
msgid_plural "Die @1 times."
msgstr[0] "Mort·e."
msgstr[1] "Mort·e %d fois."
#: triggers.lua
msgid "@1/@2 chat messages"
msgstr "@1/@2 messages du chat"
#: triggers.lua
msgid "Write something in chat."
msgid_plural "Write @1 chat messages."
msgstr[0] "Écrit quelque chose dans le chat."
msgstr[1] "Écrit @1 messages dans le chat."
#: triggers.lua
msgid "@1/@2 game joins"
msgstr "@1/@2 connexions"
#: triggers.lua
msgid "Join the game."
msgid_plural "Join the game @1 times."
msgstr[0] "Connecte toi au jeu."
msgstr[1] "Connecte toi au jeu @1 fois."
#: triggers.lua
msgid "@1/@2 crafted"
msgstr "@1/@2 craftés"
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Craft: @2"
msgid_plural "Craft: @1×@2"
msgstr[0] "Fabrique : @2"
msgstr[1] "Fabrique : @1×@2"
#: triggers.lua
msgid "Craft an item."
msgid_plural "Craft @1 items."
msgstr[0] "Confectionne un objet."
msgstr[1] "Confectionne @1 objets."
#: init.lua
msgid "Saint-Maclou"
msgstr "Saint-Maclou"
#: init.lua
msgid "Place 20 coal checkers."
msgstr "Place 20 damiers de charbon."
#: init.lua
msgid "Castorama"
msgstr "Castorama"
#: init.lua
msgid "Place 20 iron checkers."
msgstr "Place 20 damiers de fer."
#: init.lua
msgid "Sam the Trapper"
msgstr "Sam le Trappeur"
#: init.lua
msgid "Place 2 trap stones."
msgstr "Place 2 pièges de pierre."
#: init.lua
msgid "Backpacker"
msgstr "Randonneu·r·se"
#: init.lua
msgid "Craft 4 large bags."
msgstr "Confectionne 4 grands sacs"
#: init.lua
msgid "Pyromaniac"
msgstr "Pyromane"
#: init.lua
msgid "Craft 8 times flint and steel."
msgstr "Fabrique 8 silex et aciers."
#: init.lua
msgid "Firefighter"
msgstr "Pompier"
#: init.lua
msgid "Put out 1000 fires."
msgstr "Éteint 1000 feux."
#: init.lua
msgid "Light It Up"
msgstr "Eclairé·e"
#: init.lua
msgid "Place 100 torches."
msgstr "Place 100 torches."
#: init.lua
msgid "Well Lit"
msgstr "Bien Éclairé"
#: init.lua
msgid "Place 1,000 torches."
msgstr "Place 1000 torches."
#: init.lua
msgid "Really Well Lit"
msgstr "Vraiment Bien Éclairé"
#: init.lua
msgid "Craft 10 mese lamps."
msgstr "Fabrique 10 lampes de mese."
#: init.lua
msgid "Outpost"
msgstr "Poste Avancé"
#: init.lua
msgid "Craft 200 stone bricks."
msgstr "Confectionne 200 briques de pierre."
#: init.lua
msgid "Watchtower"
msgstr "Tour de Garde"
#: init.lua
msgid "Craft 800 stone bricks."
msgstr "Confectionne 800 briques de pierre."
#: init.lua
msgid "Fortress"
msgstr "Forteresse"
#: init.lua
msgid "Craft 3,200 stone bricks."
msgstr "Confectionne 3200 briques de pierre."
#: init.lua
msgid "Desert Dweller"
msgstr "Habitant·e du Désert"
#: init.lua
msgid "Craft 400 desert stone bricks."
msgstr "Confectionne 400 briques de pierre du désert."
#: init.lua
msgid "Pharaoh"
msgstr "Pharaon"
#: init.lua
msgid "Craft 100 sandstone bricks."
msgstr "Confectionne 100 briques de roche de sable."
#: init.lua
msgid "Little Library"
msgstr "Petite Bibliothèque"
#: init.lua
msgid "Craft 7 bookshelves."
msgstr "Fabrique 7 bibliothèques."
#: init.lua
msgid "Lava and Water"
msgstr "La Lave et l'Eau"
#: init.lua
msgid "Mine your first obsidian."
msgstr "Mine ton premier bloc d'obsidienne."
#: init.lua
msgid "Obsessed with Obsidian"
msgstr "Obsédé·e par l'obsidienne"
#: init.lua
msgid "Mine 50 obsidian."
msgstr "Mine 50 pierres d'obsidienne."
#: init.lua
msgid "Lava Miner"
msgstr "Mineu·r·se de lave"
#: init.lua
msgid "Mine any block while being very close to lava."
msgstr "Mine n'importe quel bloc à proximité de la lave."
#: init.lua
msgid "On The Way"
msgstr "Sur La Voie"
#: init.lua
msgid "Place 100 rails."
msgstr "Place 100 rails."
#: init.lua
msgid "First Day in the Woods"
msgstr "Premier Jour dans les Bois"
#: init.lua
msgid "Dig 6 tree blocks."
msgstr "Creuse 6 blocs d'arbre."
#: init.lua
msgid "Lumberjack"
msgstr "Bûcheron·ne"
#: init.lua
msgid "Dig 36 tree blocks."
msgstr "Creuse 36 blocs d'arbre."
#: init.lua
msgid "Semi-pro Lumberjack"
msgstr "Bûcheron.ne. Semi-Professionnel.le."
#: init.lua
msgid "Dig 216 tree blocks."
msgstr "Creuse 216 blocs d'arbre."
#: init.lua
msgid "Professional Lumberjack"
msgstr "Bûcheron·ne Professionnel·le"
#: init.lua
msgid "Dig 1,296 tree blocks."
msgstr "Creuse 1296 blocs d'arbre."
#: init.lua
msgid "Junglebaby"
msgstr "Enfant de la Jungle"
#: init.lua
msgid "Dig 100 jungle tree blocks."
msgstr "Creuse 100 blocs d'arbres de jungle."
#: init.lua
msgid "Jungleman"
msgstr "Personne de la Jungle"
#: init.lua
msgid "Dig 1,000 jungle tree blocks."
msgstr "Creuse 1000 blocs d'arbre de jungle."
#: init.lua
msgid "First Mese Find"
msgstr "Première Pépite : Mese"
#: init.lua
msgid "Mine your first mese ore."
msgstr "Mine ton premier minerai de mese."
#: init.lua
msgid "Mese Mastery"
msgstr "Maîtrise de Mese"
#: init.lua
msgid "Mine a mese block."
msgstr "Mine un bloc de mese."
#: init.lua
msgid "Youre a copper"
msgstr "Faîtes Jouer les Cuivres"
#: init.lua
msgid "Dig 1,000 copper ores."
msgstr "Creuse 1000 minerais de cuivre."
#: init.lua
msgid "A Cat in a Pop-Tart?!"
msgstr "Un Chat dans un Pop-Tart ?!"
#: init.lua
msgid "Mine a nyan cat."
msgstr "Mine un nyan cat."
#: init.lua
msgid "Mini Miner"
msgstr "Mini Mineu·r·se"
#: init.lua
msgid "Dig 100 stone blocks."
msgstr "Creuse 100 blocs de pierre."
#: init.lua
msgid "Hardened Miner"
msgstr "Mineu·r·se Endurci·e"
#: init.lua
msgid "Dig 1,000 stone blocks."
msgstr "Creuse 1000 blocs de pierre."
#: init.lua
msgid "Master Miner"
msgstr "Maître·sse Mineu·r·se"
#: init.lua
msgid "Dig 10,000 stone blocks."
msgstr "Creuse 10000 blocs de pierre."
#: init.lua
msgid "Marchand De Sable"
msgstr "Marchand·e De Sable"
#: init.lua
msgid "Dig 1,000 sand."
msgstr "Creuse 1000 blocs de sable."
#: init.lua
msgid "Crafter of Sticks"
msgstr "Fabriquant·e de Bâtons."
#: init.lua
msgid "Craft 100 sticks."
msgstr "Confectionne 100 bâtons."
#: init.lua
msgid "Jungle Discoverer"
msgstr "Explorat·eur·rice de la Jungle"
#: init.lua
msgid "Mine your first jungle grass."
msgstr "Ramasse ta première herbe de jungle."
#: init.lua
msgid "Grasslands Discoverer"
msgstr "Découvreu·r·se de prairies"
#: init.lua
msgid "Mine some grass."
msgstr "Ramasse de l'herbe."
#: init.lua
msgid "Savannah Discoverer"
msgstr "Explorat·eur·rice de la Savanne"
#: init.lua
msgid "Mine some dry grass."
msgstr "Ramasse de l'herbe sèche."
#: init.lua
msgid "Desert Discoverer"
msgstr "Expolrat·eur·rice du Désert."
#: init.lua
msgid "Mine your first cactus."
msgstr "Mine ton premier catus."
#: init.lua
msgid "Far Lands"
msgstr "Terres Lointaines"
#: init.lua
msgid "Mine your first dry shrub."
msgstr "Coupe ton premier arbuste sec."
#: init.lua
msgid "Glacier Discoverer"
msgstr "Découvreu·r·se de glacier"
#: init.lua
msgid "Mine your first ice."
msgstr "Creuse ton premier bloc de glace."
#: init.lua
msgid "Very Simple Snow Man"
msgstr "Bonhomme de Neige Rudimentaire"
#: init.lua
msgid "Place two snow blocks."
msgstr "Place deux blocs de neige."
#: init.lua
msgid "First Gold Find"
msgstr "Première Pépite : Or"
#: init.lua
msgid "Mine your first gold ore."
msgstr "Mine ton premier minerai d'or."
#: init.lua
msgid "Gold Rush"
msgstr "Ruée vers l'Or"
#: init.lua
msgid "Mine 45 gold ores."
msgstr "Mine 45 minerais d'or."
#: init.lua
msgid "Wow, I am Diamonds!"
msgstr "Wow, Je suis Diamants!"
#: init.lua
msgid "Mine your first diamond ore."
msgstr "Mine ton premier diamant."
#: init.lua
#, fuzzy
msgid "Girl's Best Friend"
msgstr "Girl's Best Friend"
#: init.lua
msgid "Mine 18 diamond ores."
msgstr "Mine 18 diamants."
#: init.lua
msgid "Hardest Block on Earth"
msgstr "Le Bloc le Plus Dur du Monde"
#: init.lua
msgid "Craft a diamond block."
msgstr "Confectionne un bloc de diamant."
#: init.lua
msgid "In the Dungeon"
msgstr "Dans le Donjon"
#: init.lua
msgid "Mine a mossy cobblestone."
msgstr "Mine un bloc de pavés moussus."
#: init.lua
msgid "Smelter"
msgstr "Fondeu·r·se"
#: init.lua
msgid "Craft 10 furnaces."
msgstr "Construis 10 fours."
#: init.lua
msgid "Treasurer"
msgstr "Trésori·er·ère"
#: init.lua
msgid "Craft 15 chests."
msgstr "Fabrique 15 coffres."
#: init.lua
msgid "Bankier"
msgstr "Banqui·er·ère"
#: init.lua
msgid "Craft 30 locked chests."
msgstr "Fabrique 30 coffres Verrouillés."
#: init.lua
msgid "Bricker"
msgstr "Briqueu·r·se"
#: init.lua
msgid "Craft 200 brick blocks."
msgstr "Confectionne 200 blocs de brique."
#: init.lua
msgid "House of Obsidian"
msgstr "La Maison de L'Obsidienne"
#: init.lua
msgid "Craft 100 obsidian bricks."
msgstr "Confectionne 100 briques d'obsidienne."
#: init.lua
msgid "Build a Cave"
msgstr "Construis une grotte"
#: init.lua
msgid "Place 100 stone."
msgstr "Place 100 pierres."
#: init.lua
msgid "Long Ladder"
msgstr "Longue Echelle"
#: init.lua
msgid "Place 400 wooden ladders."
msgstr "Place 400 échelles en bois."
#: init.lua
msgid "Industrial Age"
msgstr "Âge Industriel"
#: init.lua
msgid "Place 40 steel ladders."
msgstr "Place 40 échelles métalliques."
#: init.lua
msgid "Yummy!"
msgstr "Miam !"
#: init.lua
msgid "Eat 80 apples."
msgstr "Mange 80 pommes."
#: init.lua
msgid "Glasser"
msgstr "Verri·er·ère"
#: init.lua
msgid "Craft 14 vessels shelves."
msgstr "Fabrique 14 vaisseliers."
#: init.lua
msgid "Farming Skills Acquired"
msgstr "Compétences Paysannes Acquises"
#: init.lua
msgid "Harvest a fully grown wheat plant."
msgstr "Récolte un plant de blé à maturité."
#: init.lua
msgid "Field Worker"
msgstr "Travailleu·r·se Agricole"
#: init.lua
msgid "Harvest 25 fully grown wheat plants."
msgstr "Récolte 25 plants de blé à maturité."
#: init.lua
msgid "Aspiring Farmer"
msgstr "Apprenti·e Fermi·er·ère"
#: init.lua
msgid "Harvest 125 fully grown wheat plants."
msgstr "Récolte 125 plants de blé à maturité."
#: init.lua
msgid "Wheat Magnate"
msgstr "Magnat·e du Blé"
#: init.lua
msgid "Harvest 625 fully grown wheat plants."
msgstr "Récolte 625 plants de blé à maturité."
#: init.lua
msgid "Baker"
msgstr "Boulang·er·ère"
#: init.lua
msgid "Eat 10 loaves of bread."
msgstr "Mange 10 miches de pain."
#: init.lua
msgid "Wool Over Your Eyes"
msgstr "De la Laines dans Tes Yeux"
#: init.lua
msgid "Craft 250 white wool."
msgstr "Confectionne 250 blocs de laine blanche."
#: init.lua
msgid "Hotelier"
msgstr "Hoteli·er·ère"
#: init.lua
msgid "Craft 15 fancy beds."
msgstr "Construis 15 lits chics."
#: init.lua
msgid "Filthy Rich"
msgstr "Richissime"
#: init.lua
msgid "Craft 24 gold block stairs."
msgstr "Construis 24 escaliers en or."
#: init.lua
msgid "Roses Are Red"
msgstr "Les Roses Sont Rouges"
#: init.lua
msgid "Craft 400 red dyes."
msgstr "Prépare 400 teintures rouges."
#: init.lua
msgid "Dandelions are Yellow"
msgstr "Les Pissenlits sont Jaunes."
#: init.lua
msgid "Craft 400 yellow dyes."
msgstr "Prépare 400 teintures jaunes."
#: init.lua
msgid "Geraniums are Blue"
msgstr "Les Geraniums Sont Bleus"
#: init.lua
msgid "Craft 400 blue dyes."
msgstr "Prépare 400 teintures bleues."
#: init.lua
msgid "White Color Stock"
msgstr "Chaussettes Blanches"
#: init.lua
msgid "Craft 100 white dyes."
msgstr "Prépare 100 teintures blanches."
#: init.lua
msgid "Tasty Mushrooms"
msgstr "Délicieux Champignons"
#: init.lua
msgid "Eat 3 brown mushrooms."
msgstr "Mange 3 champignons marrons."
#: init.lua
msgid "Mushroom Lover"
msgstr "Adorat·eur·rice de Champignons"
#: init.lua
msgid "Eat 33 brown mushrooms."
msgstr "Mange 33 champignons marrons."
#: init.lua
msgid "Underground Mushroom Farmer"
msgstr "Culture de Champignons en Cave"
#: init.lua
msgid "Eat 333 brown mushrooms."
msgstr "Mange 333 champignons marrons."
#: init.lua
msgid "Builder"
msgstr "Bâtisseu·r·se"
#: init.lua
msgid "Constructor"
msgstr "Construct·eur·rice"
#: init.lua
msgid "Architect"
msgstr "Architecte"
#: init.lua
msgid "Master Architect"
msgstr "Maître·sse Architecte"
#: 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 "Affiche, réinitialise, désactive ou active vos réussites."
#: chat_commands.lua
msgid "All your awards and statistics have been cleared. You can now start again."
msgstr "Tous vos trophées et statistiques ont été réinitialisés. Vous pouvez recommencer à nouveau."
#: chat_commands.lua
msgid "You have disabled your achievements."
msgstr "Vous avez désactivé vos réussites."
#: chat_commands.lua
msgid "You have enabled your achievements."
msgstr "Vous avez activé vos réussites."
#: chat_commands.lua
msgid "<achievement ID>"
msgstr "<réussite ID>"
#: chat_commands.lua
msgid "Show details of an achievement"
msgstr "Afficher les détails d'une réussite"
#: chat_commands.lua
msgid "Achievement not found."
msgstr "Réussite non trouvée."
#: chat_commands.lua
msgid "<name>"
msgstr "<nom>"
#: chat_commands.lua
msgid "Get the achievements statistics for the given player or yourself"
msgstr "Obtenez les statistiques des réussites d'un joueur donné ou de vous-même"

819
mods/awards/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"

View File

@ -0,0 +1,819 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-21 05:50-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: api.lua
msgid "Secret Achievement Unlocked:"
msgstr ""
#: api.lua
msgid "Achievement Unlocked:"
msgstr ""
#: api.lua
#, lua-format
msgid "Secret Achievement Unlocked: %s"
msgstr ""
#: api.lua
#, lua-format
msgid "Achievement Unlocked: %s"
msgstr ""
#: api.lua
msgid "Secret Achievement Unlocked!"
msgstr ""
#: api.lua
msgid "Achievement Unlocked!"
msgstr ""
#: api.lua
msgid "Error: No awards available."
msgstr ""
#: api.lua
msgid "OK"
msgstr ""
#: api.lua
msgid "(Secret Award)"
msgstr ""
#: api.lua
msgid "Unlock this award to find out what it is."
msgstr ""
#: api.lua
#, lua-format
msgid "%s (got)"
msgstr ""
#: api.lua
msgid "You've disabled awards. Type /awards enable to reenable."
msgstr ""
#: api.lua
msgid "You have not unlocked any awards."
msgstr ""
#: api.lua
#, lua-format
msgid "%ss awards:"
msgstr ""
#: api.lua chat_commands.lua
#, lua-format
msgid "%s: %s"
msgstr ""
#: sfinv.lua unified_inventory.lua
msgid "Awards"
msgstr ""
#: triggers.lua
msgid "@1/@2 dug"
msgstr ""
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Mine: @2"
msgid_plural "Mine: @1×@2"
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "Mine @1 block."
msgid_plural "Mine @1 blocks."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 placed"
msgstr ""
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Place: @2"
msgid_plural "Place: @1×@2"
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "Place a block."
msgid_plural "Place @1 blocks."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 eaten"
msgstr ""
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Eat: @2"
msgid_plural "Eat: @1×@2"
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "Eat an item."
msgid_plural "Eat @1 items."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 deaths"
msgstr ""
#: triggers.lua
msgid "Die."
msgid_plural "Die @1 times."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 chat messages"
msgstr ""
#: triggers.lua
msgid "Write something in chat."
msgid_plural "Write @1 chat messages."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 game joins"
msgstr ""
#: triggers.lua
msgid "Join the game."
msgid_plural "Join the game @1 times."
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "@1/@2 crafted"
msgstr ""
#. Translators: @1 is count, @2 is description.
#: triggers.lua
msgid "Craft: @2"
msgid_plural "Craft: @1×@2"
msgstr[0] ""
msgstr[1] ""
#: triggers.lua
msgid "Craft an item."
msgid_plural "Craft @1 items."
msgstr[0] ""
msgstr[1] ""
#: init.lua
msgid "Saint-Maclou"
msgstr ""
#: 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 ""
#: init.lua
msgid "Craft 8 times flint and steel."
msgstr ""
#: init.lua
msgid "Firefighter"
msgstr ""
#: init.lua
msgid "Put out 1000 fires."
msgstr ""
#: init.lua
msgid "Light It Up"
msgstr ""
#: init.lua
msgid "Place 100 torches."
msgstr ""
#: init.lua
msgid "Well Lit"
msgstr ""
#: init.lua
msgid "Place 1,000 torches."
msgstr ""
#: init.lua
msgid "Really Well Lit"
msgstr ""
#: init.lua
msgid "Craft 10 mese lamps."
msgstr ""
#: init.lua
msgid "Outpost"
msgstr ""
#: init.lua
msgid "Craft 200 stone bricks."
msgstr ""
#: init.lua
msgid "Watchtower"
msgstr ""
#: init.lua
msgid "Craft 800 stone bricks."
msgstr ""
#: init.lua
msgid "Fortress"
msgstr ""
#: init.lua
msgid "Craft 3,200 stone bricks."
msgstr ""
#: init.lua
msgid "Desert Dweller"
msgstr ""
#: init.lua
msgid "Craft 400 desert stone bricks."
msgstr ""
#: init.lua
msgid "Pharaoh"
msgstr ""
#: init.lua
msgid "Craft 100 sandstone bricks."
msgstr ""
#: init.lua
msgid "Little Library"
msgstr ""
#: init.lua
msgid "Craft 7 bookshelves."
msgstr ""
#: init.lua
msgid "Lava and Water"
msgstr ""
#: init.lua
msgid "Mine your first obsidian."
msgstr ""
#: init.lua
msgid "Obsessed with Obsidian"
msgstr ""
#: init.lua
msgid "Mine 50 obsidian."
msgstr ""
#: init.lua
msgid "Lava Miner"
msgstr ""
#: init.lua
msgid "Mine any block while being very close to lava."
msgstr ""
#: init.lua
msgid "On The Way"
msgstr ""
#: init.lua
msgid "Place 100 rails."
msgstr ""
#: init.lua
msgid "First Day in the Woods"
msgstr ""
#: init.lua
msgid "Dig 6 tree blocks."
msgstr ""
#: init.lua
msgid "Lumberjack"
msgstr ""
#: init.lua
msgid "Dig 36 tree blocks."
msgstr ""
#: init.lua
msgid "Semi-pro Lumberjack"
msgstr ""
#: init.lua
msgid "Dig 216 tree blocks."
msgstr ""
#: init.lua
msgid "Professional Lumberjack"
msgstr ""
#: init.lua
msgid "Dig 1,296 tree blocks."
msgstr ""
#: init.lua
msgid "Junglebaby"
msgstr ""
#: init.lua
msgid "Dig 100 jungle tree blocks."
msgstr ""
#: init.lua
msgid "Jungleman"
msgstr ""
#: init.lua
msgid "Dig 1,000 jungle tree blocks."
msgstr ""
#: init.lua
msgid "First Mese Find"
msgstr ""
#: init.lua
msgid "Mine your first mese ore."
msgstr ""
#: init.lua
msgid "Mese Mastery"
msgstr ""
#: init.lua
msgid "Mine a mese block."
msgstr ""
#: init.lua
msgid "Youre a copper"
msgstr ""
#: init.lua
msgid "Dig 1,000 copper ores."
msgstr ""
#: init.lua
msgid "A Cat in a Pop-Tart?!"
msgstr ""
#: init.lua
msgid "Mine a nyan cat."
msgstr ""
#: init.lua
msgid "Mini Miner"
msgstr ""
#: init.lua
msgid "Dig 100 stone blocks."
msgstr ""
#: init.lua
msgid "Hardened Miner"
msgstr ""
#: init.lua
msgid "Dig 1,000 stone blocks."
msgstr ""
#: init.lua
msgid "Master Miner"
msgstr ""
#: init.lua
msgid "Dig 10,000 stone blocks."
msgstr ""
#: init.lua
msgid "Marchand De Sable"
msgstr ""
#: init.lua
msgid "Dig 1,000 sand."
msgstr ""
#: init.lua
msgid "Crafter of Sticks"
msgstr ""
#: init.lua
msgid "Craft 100 sticks."
msgstr ""
#: init.lua
msgid "Jungle Discoverer"
msgstr ""
#: init.lua
msgid "Mine your first jungle grass."
msgstr ""
#: init.lua
msgid "Grasslands Discoverer"
msgstr ""
#: init.lua
msgid "Mine some grass."
msgstr ""
#: init.lua
msgid "Savannah Discoverer"
msgstr ""
#: init.lua
msgid "Mine some dry grass."
msgstr ""
#: init.lua
msgid "Desert Discoverer"
msgstr ""
#: init.lua
msgid "Mine your first cactus."
msgstr ""
#: init.lua
msgid "Far Lands"
msgstr ""
#: init.lua
msgid "Mine your first dry shrub."
msgstr ""
#: init.lua
msgid "Glacier Discoverer"
msgstr ""
#: init.lua
msgid "Mine your first ice."
msgstr ""
#: init.lua
msgid "Very Simple Snow Man"
msgstr ""
#: init.lua
msgid "Place two snow blocks."
msgstr ""
#: init.lua
msgid "First Gold Find"
msgstr ""
#: init.lua
msgid "Mine your first gold ore."
msgstr ""
#: init.lua
msgid "Gold Rush"
msgstr ""
#: init.lua
msgid "Mine 45 gold ores."
msgstr ""
#: init.lua
msgid "Wow, I am Diamonds!"
msgstr ""
#: init.lua
msgid "Mine your first diamond ore."
msgstr ""
#: init.lua
msgid "Girl's Best Friend"
msgstr ""
#: init.lua
msgid "Mine 18 diamond ores."
msgstr ""
#: init.lua
msgid "Hardest Block on Earth"
msgstr ""
#: init.lua
msgid "Craft a diamond block."
msgstr ""
#: init.lua
msgid "In the Dungeon"
msgstr ""
#: init.lua
msgid "Mine a mossy cobblestone."
msgstr ""
#: init.lua
msgid "Smelter"
msgstr ""
#: init.lua
msgid "Craft 10 furnaces."
msgstr ""
#: init.lua
msgid "Treasurer"
msgstr ""
#: init.lua
msgid "Craft 15 chests."
msgstr ""
#: init.lua
msgid "Bankier"
msgstr ""
#: init.lua
msgid "Craft 30 locked chests."
msgstr ""
#: init.lua
msgid "Bricker"
msgstr ""
#: init.lua
msgid "Craft 200 brick blocks."
msgstr ""
#: init.lua
msgid "House of Obsidian"
msgstr ""
#: init.lua
msgid "Craft 100 obsidian bricks."
msgstr ""
#: init.lua
msgid "Build a Cave"
msgstr ""
#: init.lua
msgid "Place 100 stone."
msgstr ""
#: init.lua
msgid "Long Ladder"
msgstr ""
#: init.lua
msgid "Place 400 wooden ladders."
msgstr ""
#: init.lua
msgid "Industrial Age"
msgstr ""
#: init.lua
msgid "Place 40 steel ladders."
msgstr ""
#: init.lua
msgid "Yummy!"
msgstr ""
#: init.lua
msgid "Eat 80 apples."
msgstr ""
#: init.lua
msgid "Glasser"
msgstr ""
#: init.lua
msgid "Craft 14 vessels shelves."
msgstr ""
#: init.lua
msgid "Farming Skills Acquired"
msgstr ""
#: init.lua
msgid "Harvest a fully grown wheat plant."
msgstr ""
#: init.lua
msgid "Field Worker"
msgstr ""
#: init.lua
msgid "Harvest 25 fully grown wheat plants."
msgstr ""
#: init.lua
msgid "Aspiring Farmer"
msgstr ""
#: init.lua
msgid "Harvest 125 fully grown wheat plants."
msgstr ""
#: init.lua
msgid "Wheat Magnate"
msgstr ""
#: init.lua
msgid "Harvest 625 fully grown wheat plants."
msgstr ""
#: init.lua
msgid "Baker"
msgstr ""
#: init.lua
msgid "Eat 10 loaves of bread."
msgstr ""
#: init.lua
msgid "Wool Over Your Eyes"
msgstr ""
#: init.lua
msgid "Craft 250 white wool."
msgstr ""
#: init.lua
msgid "Hotelier"
msgstr ""
#: init.lua
msgid "Craft 15 fancy beds."
msgstr ""
#: init.lua
msgid "Filthy Rich"
msgstr ""
#: init.lua
msgid "Craft 24 gold block stairs."
msgstr ""
#: init.lua
msgid "Roses Are Red"
msgstr ""
#: init.lua
msgid "Craft 400 red dyes."
msgstr ""
#: init.lua
msgid "Dandelions are Yellow"
msgstr ""
#: init.lua
msgid "Craft 400 yellow dyes."
msgstr ""
#: init.lua
msgid "Geraniums are Blue"
msgstr ""
#: init.lua
msgid "Craft 400 blue dyes."
msgstr ""
#: init.lua
msgid "White Color Stock"
msgstr ""
#: init.lua
msgid "Craft 100 white dyes."
msgstr ""
#: init.lua
msgid "Tasty Mushrooms"
msgstr ""
#: init.lua
msgid "Eat 3 brown mushrooms."
msgstr ""
#: init.lua
msgid "Mushroom Lover"
msgstr ""
#: init.lua
msgid "Eat 33 brown mushrooms."
msgstr ""
#: init.lua
msgid "Underground Mushroom Farmer"
msgstr ""
#: init.lua
msgid "Eat 333 brown mushrooms."
msgstr ""
#: init.lua
msgid "Builder"
msgstr ""
#: init.lua
msgid "Constructor"
msgstr ""
#: init.lua
msgid "Architect"
msgstr ""
#: init.lua
msgid "Master Architect"
msgstr ""
#: chat_commands.lua
msgid "[c|clear|disable|enable]"
msgstr ""
#: chat_commands.lua
msgid "Show, clear, disable or enable your achievements"
msgstr ""
#: chat_commands.lua
msgid ""
"All your awards and statistics have been cleared. You can now start again."
msgstr ""
#: chat_commands.lua
msgid "You have disabled your achievements."
msgstr ""
#: chat_commands.lua
msgid "You have enabled your achievements."
msgstr ""
#: chat_commands.lua
msgid "<achievement ID>"
msgstr ""
#: chat_commands.lua
msgid "Show details of an achievement"
msgstr ""
#: chat_commands.lua
msgid "Achievement not found."
msgstr ""
#: chat_commands.lua
msgid "<name>"
msgstr ""
#: chat_commands.lua
msgid "Get the achievements statistics for the given player or yourself"
msgstr ""

8
mods/awards/mod.conf Normal file
View File

@ -0,0 +1,8 @@
name = awards
title = Awards
author = rubenwardy
description = Adds awards to Minetest, and an API to register new ones.
optional_depends = intllib,sfinv,unified_inventory,default,stairs,farming,dye,beds,wool,vessels,moreblocks,fire,flowers,nyancat
license = MIT
forum = https://forum.minetest.net/viewtopic.php?t=4870
version = 3.0.0

BIN
mods/awards/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

View File

@ -0,0 +1,179 @@
-- 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)
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 = 2, y = 2}, -- adjusted for 32x32 from x/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

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

1110
mods/awards/src/awards.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
-- 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
})

111
mods/awards/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

285
mods/awards/src/gui.lua Normal file
View File

@ -0,0 +1,285 @@
-- Copyright (c) 2013-18 rubenwardy. MIT.
local S = awards.gettext
local function order_awards(name)
local hash_is_unlocked = {}
local retval = {}
local data = awards.player(name)
if data and data.unlocked then
for awardname, _ in pairs(data.unlocked) do
local def = awards.registered_awards[awardname]
if def then
hash_is_unlocked[awardname] = true
local score = -100000
local difficulty = def.difficulty or 1
if def.trigger and def.trigger.target then
difficulty = difficulty * def.trigger.target
end
score = score + difficulty
retval[#retval + 1] = {
name = awardname,
def = def,
unlocked = true,
started = true,
score = score,
}
end
end
end
for _, def in pairs(awards.registered_awards) do
if not hash_is_unlocked[def.name] and def:can_unlock(data) then
local started = false
local score = def.difficulty or 1
if def.secret then
score = 1000000
elseif def.trigger and def.trigger.target and def.getProgress then
local progress = def:getProgress(data).perc
score = score * (1 - progress) * def.trigger.target
if progress < 0.001 then
score = score + 100
else
started = true
end
else
score = 100
end
retval[#retval + 1] = {
name = def.name,
def = def,
unlocked = false,
started = started,
score = score,
}
end
end
table.sort(retval, function(a, b)
return a.score < b.score
end)
return retval
end
function awards.get_formspec(name, to, sid)
local formspec = ""
local awards_list = order_awards(name)
local data = awards.player(name)
if #awards_list == 0 then
formspec = formspec .. "label[3.9,1.5;"..minetest.formspec_escape(S("Error: No achivements available.")).."]"
formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]"
return formspec
end
sid = awards_list[sid] and sid or 1
-- Sidebar
local sitem = awards_list[sid]
local sdef = sitem.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
formspec = formspec .. "textarea[0.5,3.1;4.8,1.45;;" ..
string.format(status, minetest.formspec_escape(title)) ..
";]"
if sdef and sdef.icon then
formspec = formspec .. "image[0.45,0;3.5,3.5;" .. sdef.icon .. "]" -- adjusted values from 0.6,0;3,3
end
local barwidth = 3.95
local perc = nil
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
formspec = formspec .. "background[0,8.24;" .. barwidth ..",0.4;awards_progress_gray.png;false]"
formspec = formspec .. "background[0,8.24;" .. (barwidth * perc) ..",0.4;awards_progress_green.png;false]"
if label then
formspec = formspec .. "label[1.6,8.15;" .. minetest.formspec_escape(label) .. "]"
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
-- Create list box
formspec = formspec .. "textlist[4,0;3.8,8.6;awards;"
local first = true
for _, award in pairs(awards_list) do
local def = award.def
if def then
if not first then
formspec = formspec .. ","
end
first = false
if def.secret and not award.unlocked then
formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)"))
else
local title = award.name
if def and def.title then
title = def.title
end
-- title = title .. " [" .. award.score .. "]"
if award.unlocked then
formspec = formspec .. minetest.formspec_escape(title)
elseif award.started then
formspec = formspec .. "#c0c0c0".. minetest.formspec_escape(title)
else
formspec = formspec .. "#a0a0a0".. minetest.formspec_escape(title)
end
end
end
end
return formspec .. ";"..sid.."]"
end
function awards.show_to(name, to, sid, text)
if name == "" or name == nil then
name = to
end
local data = awards.player(to)
if name == to and data.disabled then
minetest.chat_send_player(name, S("You've disabled awards. Type /awards enable to reenable."))
return
end
if text then
local awards_list = order_awards(name)
if #awards_list == 0 then
minetest.chat_send_player(to, S("Error: No award available."))
return
elseif not data or not data.unlocked then
minetest.chat_send_player(to, S("You have not unlocked any awards."))
return
end
minetest.chat_send_player(to, string.format(S("%ss awards:"), name))
for str, _ in pairs(data.unlocked) do
local def = awards.registered_awards[str]
if def then
if def.title then
if def.description then
minetest.chat_send_player(to, string.format(S("%s: %s"), def.title, def.description))
else
minetest.chat_send_player(to, def.title)
end
else
minetest.chat_send_player(to, str)
end
end
end
else
local deco = ""
if minetest.global_exists("default") then
deco = default.gui_bg .. default.gui_bg_img
end
-- Show formspec to user
minetest.show_formspec(to,"awards:awards",
"size[8,8.6]" .. deco ..
awards.get_formspec(name, to, sid))
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
sfinv.register_page("awards:awards", {
title = S("Awards"),
on_enter = function(self, player, context)
context.awards_idx = 1
end,
is_in_nav = function(self, player, context)
local data = awards.player(player:get_player_name())
return not data.disabled
end,
get = function(self, player, context)
local name = player:get_player_name()
return sfinv.make_formspec(player, context,
awards.get_formspec(name, name, context.awards_idx),
false)
end,
on_player_receive_fields = function(self, player, context, fields)
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
context.awards_idx = event.index
sfinv.set_player_inventory_formspec(player, context)
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
if minetest.get_modpath("unified_inventory") ~= nil then
unified_inventory.register_button("awards", {
type = "image",
image = "awards_ui_icon.png",
tooltip = S("Awards"),
action = function(player)
local name = player:get_player_name()
awards.show_to(name, name, nil, false)
end,
})
end

View File

@ -0,0 +1,44 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View File

@ -0,0 +1,141 @@
-- AWARDS
--
-- Copyright (C) 2013-2015 rubenwardy
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation; either version 2.1 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License along
-- with this program; if not, write to the Free Software Foundation, Inc.,
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--
awards.register_trigger("chat", {
type = "counted",
progress = "@1/@2 chat messages",
auto_description = { "Send a chat message", "Chat @1 times" },
})
minetest.register_on_chat_message(function(name, message)
local player = minetest.get_player_by_name(name)
if not player or string.find(message, "/") then
return
end
awards.notify_chat(player)
end)
awards.register_trigger("join", {
type = "counted",
progress = "@1/@2 joins",
auto_description = { "Join once", "Join @1 times" },
})
minetest.register_on_joinplayer(awards.notify_join)
awards.register_trigger("death", {
type = "counted_key",
progress = "@1/@2 deaths",
auto_description = { "Die once of @2", "Die @1 times of @2" },
auto_description_total = { "Die @1 times.", "Mine @1 times" },
get_key = function(self, def)
return def.trigger.reason
end,
})
minetest.register_on_dieplayer(function(player, reason)
if reason then
reason = reason.type
else
reason = "unknown"
end
awards.notify_death(player, reason)
end)
awards.register_trigger("dig", {
type = "counted_key",
progress = "@1/@2 dug",
auto_description = { "Mine: @2", "Mine: @1×@2" },
auto_description_total = { "Mine @1 block.", "Mine @1 blocks." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.node] or def.trigger.node
end,
key_is_item = true,
})
minetest.register_on_dignode(function(pos, node, player)
if not player or not pos or not node then
return
end
local node_name = node.name
node_name = minetest.registered_aliases[node_name] or node_name
awards.notify_dig(player, node_name)
end)
awards.register_trigger("place", {
type = "counted_key",
progress = "@1/@2 placed",
auto_description = { "Place: @2", "Place: @1×@2" },
auto_description_total = { "Place @1 block.", "Place @1 blocks." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.node] or def.trigger.node
end,
key_is_item = true,
})
minetest.register_on_placenode(function(pos, node, player)
if not player or not pos or not node then
return
end
local node_name = node.name
node_name = minetest.registered_aliases[node_name] or node_name
awards.notify_place(player, node_name)
end)
awards.register_trigger("craft", {
type = "counted_key",
progress = "@1/@2 crafted",
auto_description = { "Craft: @2", "Craft: @1×@2" },
auto_description_total = { "Craft @1 item", "Craft @1 items." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.item] or def.trigger.item
end,
key_is_item = true,
})
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not player or itemstack:is_empty() then
return
end
local itemname = itemstack:get_name()
itemname = minetest.registered_aliases[itemname] or itemname
awards.notify_craft(player, itemname, itemstack:get_count())
end)
awards.register_trigger("eat", {
type = "counted_key",
progress = "@1/@2 eaten",
auto_description = { "Eat @2", "Eat @1×@2" },
auto_description_total = { "Eat @1 item", "Eat @1 items." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.item] or def.trigger.item
end,
key_is_item = true,
})
minetest.register_on_item_eat(function(_, _, itemstack, player, _)
if not player or itemstack:is_empty() then
return
end
local itemname = itemstack:get_name()
itemname = minetest.registered_aliases[itemname] or itemname
awards.notify_eat(player, itemname, itemstack:get_count())
end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More