Compare commits
No commits in common. "development" and "bukkit1.2" have entirely different histories.
developmen
...
bukkit1.2
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="lib" path="/Users/tobi/Code/Vault.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="/Users/tobi/Code/craftbukkit-1.5.1-R0.1.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="lib" path="/Volumes/Data HD/Users/tobi/Code/bukkit-1.1-R5-20120224.051137-12.jar" sourcepath="/Users/tobi/Desktop/Bukkit">
|
||||
<attributes>
|
||||
<attribute name="javadoc_location" value="http://jd.bukkit.org/apidocs/"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
11
.gitignore
vendored
11
.gitignore
vendored
@ -6,13 +6,6 @@
|
||||
# netbeans
|
||||
/nbproject
|
||||
|
||||
# intelliJ
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# maven
|
||||
target/
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
||||
@ -28,7 +21,3 @@ profile
|
||||
|
||||
# bukkit
|
||||
bukkit/
|
||||
|
||||
# bukkit test-server
|
||||
bukkit-testserver/
|
||||
dependency-reduced-pom.xml
|
||||
|
2
.project
2
.project
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>craftinc-gates</name>
|
||||
<name>AncientGates</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
12
.settings/org.eclipse.jdt.core.prefs
Normal file
12
.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,12 @@
|
||||
#Wed Apr 06 16:59:25 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
13
AUTHORS.txt
13
AUTHORS.txt
@ -1,13 +0,0 @@
|
||||
The following persons contributed to Craft Inc. Gates (previously named Ancient Gates):
|
||||
|
||||
CURRENT MAINTAINERS
|
||||
|
||||
Tobias Ottenweller <mail@ottenweller.net>
|
||||
Paul Schulze <info@paul-schulze.de>
|
||||
|
||||
|
||||
FORMER CONTRIBUTORS (alphabetical order)
|
||||
|
||||
Jacob Brunson <jacob@dimensionsmachine.com>
|
||||
locutus <bladedpenguin@gmail.com>
|
||||
Olof Larsson <olof@sylt.nu>
|
674
LICENCE.txt
Normal file
674
LICENCE.txt
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
101
README.md
101
README.md
@ -1,85 +1,50 @@
|
||||
# Craft Inc. Gates #
|
||||
#AncientGates - Easily create portals with custom design#
|
||||
|
||||
This awesome plugin lets you _travel_ to far away places and worlds _faster than light_! Just create a gate at any location and set an exit somewhere else.
|
||||
Read the full userguide here: TODO
|
||||
|
||||
This has been made available by the hard work of the research and development department of the _Craft Inc. Corporation_. Under the lead of Professor Ddidderr Craftman scientists worked years to find a way to bend time and space inside the Minecraft universe to enable _ultra fast transportation_.
|
||||
With this plugin the server operators (OPs) can create gates that will teleport anyone who enter to a location specific to that gate. The hightlights are: __It is so darn easy to use!__ :D and __The gates can look any way you like__ \o/
|
||||
|
||||
Now it is time for _you_ to try out this wonderful plugin. Simply install, create a gate and feel the funny tickle inside your brain while traveling.*
|
||||
Try the ingame command: __/gate__
|
||||
Thought first you should take a look at the demonstration oloflarsson and karibu6 created:
|
||||
__[http://www.youtube.com/watch?v=L4hyqTpeEaA](http://www.youtube.com/watch?v=L4hyqTpeEaA)__
|
||||
|
||||
The key features of this are:
|
||||
##Commands##
|
||||
|
||||
* Dynmap integration
|
||||
* Gates with and without frames
|
||||
* Gates consisting of portal blocks and gates made of air (so called hidden gates)
|
||||
* Gates with destinations in different worlds
|
||||
* Gates with custom shapes (gates can look any way you want)
|
||||
* Riding through gates
|
||||
|
||||
|
||||
*The Craft Inc. Corporation won't take any responsibility for seasickness, memory loss and sudden suffocation in walls while traveling with one of our gates!
|
||||
* __/gate help,h,? *[page]__ Display a help page
|
||||
* __/gate create,new [id]__ Create a gate
|
||||
* __/gate createsetfrom,newsetfrom,csf,nsf [id]__ Create a gate and set "from"
|
||||
* __/gate delete,del,remove,rm [id]__ Delete a gate
|
||||
* __/gate setfrom [id]__ Set "from" to your location.
|
||||
* __/gate setto [id]__ Set "to" to your location.
|
||||
* __/gate open [id]__ Open that gate
|
||||
* __/gate close [id]__ Close that gate
|
||||
* __/gate list,ls [page]__ Display a list of the gates
|
||||
* __/gate info,details [id]__ Display information about a gate
|
||||
|
||||
##FAQ##
|
||||
|
||||
__Why the name AncientGates?__
|
||||
|
||||
Because the purpose of this plugin that I envision is that players should not be able to create gates to other worlds themselves. The server operators build gates with cool ruins around them and in order to get to another world the players need to find one of those ruins.
|
||||
|
||||
__Who can create a gate?__
|
||||
|
||||
Have a look at the [_Permissions_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/permissions/) page.
|
||||
Only server operators! Not normal players. There is no suport for any permissions plugin.
|
||||
|
||||
__Who can destroy a gate?__
|
||||
|
||||
Anyone if you do not use a third-party protection plugin like Grief Prevention.
|
||||
Anyone if you do not use a third-party protection plugin like Factions.
|
||||
|
||||
__Is there a IConnomy integration? Features for user to dial other gates etc?__
|
||||
__Are there IConnomy integration, Features for user to dial other gates etc?__
|
||||
|
||||
Nope. We currently don't plan to integrate such features. If you really need such an integration please inform us. If there are a lot of people requesting such features we might change our mind.
|
||||
Nope. This plugin is very minimalistic and plain. Server operators manage the portals players use them any time they are open.
|
||||
|
||||
__Is there a list of all commands?__
|
||||
Installing
|
||||
----------
|
||||
1. Download the latest release: __[https://github.com/tomco/minecraft-ancient-gates/downloads](https://github.com/tomco/minecraft-ancient-gates/downloads)__
|
||||
1. Put AncientGates.jar in the plugins folder.
|
||||
|
||||
Sure, type _/gate help_ in-game or have a look at the [_Commands_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/commands/) page.
|
||||
|
||||
__When I destroy the frame of a gate it stops working. Shouldn't it still work?__
|
||||
|
||||
Yes and no. To make gates work without a frame you need to tweak the _checkForBrokenGateFrames_ setting. Have a look at the [_Configuration_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/configuration/) page for more information.
|
||||
|
||||
|
||||
## Usage ##
|
||||
With this plugin you can create gates which will teleport players anywhere you want. The gates can look any way you like.
|
||||
|
||||
To make the gate work place yourself inside a newly created gate frame and type __/gate new [id]__. Afterwards walk to the destination of your gate and type __/gate exit [id]__ to set the destination. With __/gate open [id]__ you can get your newly created gate to work.
|
||||
|
||||
To hide a gate simply call __/gate hide [id]__. Now that gate won’t be made of purple portal blocks while open.
|
||||
|
||||
Have a look at the [_Commands_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/commands/) page to find out how to modify gates even further.
|
||||
|
||||
|
||||
## Installing ##
|
||||
|
||||
1. Download the latest release _[here](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/files/)_
|
||||
2. Delete any old versions of _Craft Inc. Gates_ (only the .jar files) including the extra dynmap-plugin of this plugin.
|
||||
3. Extract the content of the zip file into the plugins folder of your Bukkit server.
|
||||
4. Start or reload the server.
|
||||
|
||||
## Craft Inc. ##
|
||||
Check out our __[Craft Inc. Minecraft Server](http://www.craftinc.de)__. Everyone is welcome!
|
||||
|
||||
Also check out our other great plugins:
|
||||
|
||||
* [__Craft Inc. BorderProtection__](http://dev.bukkit.org/bukkit-mods/craftinc-borderprotection/)
|
||||
protect your worlds with a border players cannot cross.
|
||||
|
||||
* [__Craft Inc. Replicator__](http://dev.bukkit.org/bukkit-mods/craftinc-replicator/)
|
||||
allows players to build a replicator to replicate blocks and other items. (still experimental)
|
||||
|
||||
* __Craft Inc. Scarecrow__
|
||||
coming soon!
|
||||
|
||||
## Roadmap ##
|
||||
* Per player permissions for using and managing gates.
|
||||
* Horizontal gates.
|
||||
|
||||
## Bugs and other Problems ##
|
||||
Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issues?state=open) on GitHub.
|
||||
|
||||
## Legal Information ##
|
||||
This project is a fork of the original [_Ancient Gates_](https://github.com/bladedpenguin/minecraft-ancient-gates). It is licensed under the [_LGPL_](http://www.gnu.org/licenses/lgpl-3.0.txt) just like the Bukkit project. Thanks to all current and previous [_contributors_](https://github.com/craftinc/craftinc-gates/blob/development/AUTHORS.txt).
|
||||
The font used for the Craft Inc. Gates logo is called [_MineCrafter 3_](http://www.minecraftforum.net/topic/892789-minecrafter-3-font-simply-easy/) and has been made available under the creative commons license. Thanks to Asherz08, MadPixel and Ashley Denham for this great font.
|
||||
This plugin utilizes [_Hidendra's plugin metrics system_](http://mcstats.org), which means that the following information is collected and sent to mcstats.org: a unique identifier, the server's version of Java, whether the server is in offline or online mode, the plugin's version, the server's version, the OS version/name and architecture, the core count for the CPU, the number of players online, the Metrics version. __You can disable the stat collection via /plugins/PluginMetrics/config.yml if you wish.__
|
||||
License
|
||||
----------
|
||||
This project has a LGPL license just like the Bukkit project.<br>
|
||||
This project uses [GSON](http://code.google.com/p/google-gson/) which has a [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0 ).
|
||||
|
74
build.xml
Normal file
74
build.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="AncientGates" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project AncientGates.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="AncientGates-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
51
changelog.md
51
changelog.md
@ -1,51 +0,0 @@
|
||||
## 2.4.0 ##
|
||||
* Resolved issues with closing gates (special thanks to THCFrosD)
|
||||
* Added support for riding through gates (with horses, mine carts, pigs and boats)
|
||||
* Dynmap integration (extra plugin)
|
||||
|
||||
## 2.3.0 ##
|
||||
* Added a command for setting the exit and opening a gate at once.
|
||||
* Enabled the ability to change the gate block material.
|
||||
* Added a command printing all nearby gates while highlighting them.
|
||||
* Changed the info command to highlight gates.
|
||||
* Updated the info command to print information about the nearest gate if no gate name got supplied.
|
||||
|
||||
## 2.2.1 ##
|
||||
* Changed priority of some event listeners to solve problems with WorldGuard and other protection plugins.
|
||||
|
||||
## 2.2.0 ##
|
||||
* Improved gate commands and shortcuts (have a look at the bukkit-dev page for more information).
|
||||
* Improved overall performance.
|
||||
* Added a configuration file (have a look at the bukkit-dev page for more information).
|
||||
* Resolved issues with (random) teleports to the nether.
|
||||
* Made it possible to create non hidden gates without a frame. (Turned off by default!)
|
||||
* Changed the behavior regarding portal blocks. Starting with this version no blocks will be set by the plugin. All portal blocks will only be visible on client side.
|
||||
* Added checks preventing the plugin from overwriting the gate storage file on error.
|
||||
* Added the ability to change and disable messages on teleport and insufficient permissions via a config file.
|
||||
|
||||
## 2.1.2 ##
|
||||
* Fixed a bug where players got teleported one block beside the real portal.
|
||||
* Fixed a bug where gates with no location caused multiple exceptions.
|
||||
|
||||
## 2.1.1 ##
|
||||
* Made the list command more reliable.
|
||||
* Error messages will be displayed less frequent.
|
||||
|
||||
## 2.1.0 ##
|
||||
* Command outputs are now colored.
|
||||
* Fixed a bug where players in creative mode would not be teleported correctly.
|
||||
* Made various commands available via the server console.
|
||||
* Simplified command names.
|
||||
* Improved permissions handling. (Added soft dependency for Vault.)
|
||||
* A message will be displayed after a player has been teleported. There is also a message displayed if a player is not allowed to use a gate.
|
||||
|
||||
## 2.0.1a
|
||||
* Fixed broken import for gates created with version 2.0.0
|
||||
|
||||
## 2.0.1
|
||||
* Updated permissions to allow everyone to use gates by default.
|
||||
* Fixed a bug where yaw had not been taken correctly into account while teleporting.
|
||||
* Re-added persistence of yaw and pitch of gate locations and exits.
|
||||
|
||||
## 2.0.0
|
||||
Initial release under new name
|
@ -1,47 +0,0 @@
|
||||
* __/gate allowRiding, ar [id]__
|
||||
Update a gate so players can travel through it while riding.
|
||||
|
||||
* __/gate close, c [id]__
|
||||
Closes a gate to prevent players from using it.
|
||||
|
||||
* __/gate denyRiding, dr [id]__
|
||||
Update a gate so players can NOT travel through it while riding.
|
||||
|
||||
* __/gate delete, del, remove [id]__
|
||||
Removes the gate from the game.
|
||||
|
||||
* __/gate exit, e [id]__
|
||||
Changes the location where the gate will teleport players to your current location.
|
||||
|
||||
* __/gate exitopen, eo [id]__
|
||||
Changes the location where the gate will teleport players to your current location. Also tries to open that gate afterwards.
|
||||
|
||||
* __/gate help, ? [page]__
|
||||
Prints help pages.
|
||||
|
||||
* __/gate hide, h [id]__
|
||||
Makes a gate NOT consist of gate blocks while open.
|
||||
|
||||
* __/gate info, i [id]__
|
||||
Prints details about a certain gate. Will print information about the nearest gate if no _id_ is supplied. Also highlights the gate you're requesting information about.
|
||||
|
||||
* __/gate list, ls [page]__
|
||||
Prints all available gates.
|
||||
|
||||
* __/gate location, lo [id]__
|
||||
Sets the entrance of the gate to your current location.
|
||||
|
||||
* __/gate nearby, nb__
|
||||
Prints the name of nearby gates. Also highlights them.
|
||||
|
||||
* __/gate new, n [id]__
|
||||
Creates a gate at your current location.
|
||||
|
||||
* __/gate open, o [id]__
|
||||
Open a gate so players can use it.
|
||||
|
||||
* __/gate rename, rn [current name] [new name]__
|
||||
Changes the name/id of the gate.
|
||||
|
||||
* __/gate unhide,uh [id]__
|
||||
Makes that gate visible.
|
@ -1,57 +0,0 @@
|
||||
Starting with version 2.2.0 some features are customizable via a configuration file.
|
||||
|
||||
The configuration file will be automatically created on the the first startup after
|
||||
installing or updating the plugin.
|
||||
|
||||
|
||||
The following keys and values are available:
|
||||
|
||||
|
||||
* __maxGateBlocks__
|
||||
A positive integer defining the maximum number of blocks a gate can consist of.
|
||||
Note that increasing this value might slow down your server!
|
||||
|
||||
|
||||
* __playerGateBlockUpdateRadius__
|
||||
Defines the radius around a player where portal blocks are visible to that player.
|
||||
Adjust this value when increasing or decreasing the view-distance on the server.
|
||||
Only positive integer values are allowed.
|
||||
|
||||
|
||||
* __checkForBrokenGateFrames__
|
||||
Allowed values are _true_ and _false_ only. Setting this value to _false_ will disable
|
||||
all checks for broken frames for non-hidden gates. Disabling frame block checks
|
||||
might increase you server performance.
|
||||
|
||||
|
||||
* __saveOnChanges__
|
||||
Allowed values are _true_ and _false_ only. Disabling _save on changes_ might
|
||||
increase server performance but gates will only be saved to disk when the plugin
|
||||
gets disabled! This might lead to data loss on error.
|
||||
|
||||
|
||||
* __gateTeleportMessage__
|
||||
A string value going to displayed every time when a player travels using a gate. Will
|
||||
only be displayed if _showTeleportMessage_ is set to _true_.
|
||||
|
||||
|
||||
* __showTeleportMessage__
|
||||
A boolean (_true_ or _false_) determining wether the _teleport message_ will
|
||||
be displayed.
|
||||
|
||||
|
||||
* __gateTeleportNoPermissionMessage__
|
||||
A string value going to displayed every time when a player enters a gate and is not allowed to use that gate. Will only be displayed if _showTeleportNoPermissionMessage_
|
||||
is set to _true_.
|
||||
|
||||
|
||||
* __gateTeleportVehicleNotAllowedMessage__
|
||||
A string value being displayed when a player tries to go through a gate while riding when riding through this gate is disabled. Will only be displayed if _showTeleportNoPermissionMessage_ is set to _true_.
|
||||
|
||||
* __showTeleportNoPermissionMessage__
|
||||
A boolean (_true_ or _false_) determining wether the _no permission message_ will
|
||||
be displayed.
|
||||
|
||||
|
||||
* __gateMaterial__
|
||||
A String representing the material all gates will consist of. Have a look at our [_Gate Material Page_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/gate-materials/) for all possible values.
|
@ -1,27 +0,0 @@
|
||||
Starting with version 2.3.0 different gate materials can be used. You can set them via the configuration file. The following Materials are currently defined:
|
||||
|
||||
* sapling
|
||||
* water
|
||||
* lava
|
||||
* cobweb
|
||||
* grass
|
||||
* dead bush
|
||||
* dandelion
|
||||
* poppy
|
||||
* brown mushroom
|
||||
* red mushroom
|
||||
* torch
|
||||
* redstone torch (off)
|
||||
* redstone torch (on)
|
||||
* fence
|
||||
* nether portal
|
||||
* iron bars
|
||||
* glass pane
|
||||
* fence gate
|
||||
* nether brick fence
|
||||
* nether wart
|
||||
* end portal
|
||||
* cobblestone wall
|
||||
|
||||
|
||||
Your favorite material is missing? Please contact us and we will see if we can add it.
|
@ -1,12 +0,0 @@
|
||||
The following permissions are available: (Also have a look at the [Commands Page](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/commands/) to see if which commands can be executed with which permission set.)
|
||||
|
||||
* __craftincgates.info__
|
||||
Gives access to info and list commands.
|
||||
|
||||
* __craftincgates.use__
|
||||
Allows you to travel via gates.
|
||||
|
||||
* __craftincgates.manage__
|
||||
Gives access to commands manipulating gates.
|
||||
|
||||
Craft Inc. Gates will use __[Vault](http://dev.bukkit.org/bukkit-mods/vault/)__'s permission system if Vault is installed on your server.
|
13
gson-license.txt
Normal file
13
gson-license.txt
Normal file
@ -0,0 +1,13 @@
|
||||
Copyright (c) 2008-2009 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
33
plugin.yml
33
plugin.yml
@ -1,30 +1,7 @@
|
||||
name: ${project.name}
|
||||
version: ${project.version}
|
||||
description: A plugin to create gates for fast traveling.
|
||||
softdepend: [Vault, Multiverse-Core, MultiWorld, RoyalCommands]
|
||||
author: tomco, s1m0ne
|
||||
authors: [oloflarsson, locutus, DrAgonmoray, s1m0ne, tomco]
|
||||
website: http://dev.bukkit.org/bukkit-plugins/craftinc-gates/
|
||||
|
||||
main: de.craftinc.gates.Plugin
|
||||
database: false
|
||||
|
||||
name: AncientGates
|
||||
version: 1.1
|
||||
main: org.mcteam.ancientgates.Plugin
|
||||
commands:
|
||||
gate:
|
||||
description: All of the Craft Inc. Gates commands
|
||||
usage: See documentation or type '/gate help' while playing.
|
||||
|
||||
permissions:
|
||||
craftincgates.*:
|
||||
description: Gives access to all Craft Inc. Gates commands.
|
||||
children:
|
||||
craftincgates.info: true
|
||||
craftincgates.use: true
|
||||
craftincgates.manage: true
|
||||
craftincgates.info:
|
||||
description: Gives access to info and list commands.
|
||||
craftincgates.use:
|
||||
default: true
|
||||
description: Allows you to use open gates.
|
||||
craftincgates.manage:
|
||||
description: Gives access to commands manipulating gates.
|
||||
description: All of the AncientGates commands
|
||||
usage: See documentation.
|
149
pom.xml
149
pom.xml
@ -1,149 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.craftinc</groupId>
|
||||
<artifactId>CraftIncGates</artifactId>
|
||||
<name>Craft Inc. Gates</name>
|
||||
<url>http://dev.bukkit.org/bukkit-plugins/craftinc-gates/</url>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.4.1</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<!-- License -->
|
||||
<licenses>
|
||||
|
||||
<license>
|
||||
<name>GNU Lesser General Public License Version 3</name>
|
||||
<url>https://www.gnu.org/licenses/lgpl-3.0-standalone.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
|
||||
</licenses>
|
||||
|
||||
<build>
|
||||
<finalName>${project.name} ${project.version}</finalName>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<version>1.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>Run Test Bukkit Server</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>${basedir}/scripts/test-deployment.sh</executable>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>1.7.1</version>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.mcstats.bukkit:metrics</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--Spigot API-->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.11-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Bukkit API-->
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.11-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Vault-->
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
<artifactId>Vault</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Metrics-->
|
||||
<dependency>
|
||||
<groupId>org.mcstats.bukkit</groupId>
|
||||
<artifactId>metrics</artifactId>
|
||||
<version>R8-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>Plugin Metrics</id>
|
||||
<url>http://repo.mcstats.org/content/repositories/public</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
@ -1,11 +0,0 @@
|
||||
maxGateBlocks: 50
|
||||
playerGateBlockUpdateRadius: 64
|
||||
highlightDuration: 5
|
||||
saveOnChanges: true
|
||||
checkForBrokenGateFrames: true
|
||||
gateTeleportMessage: "Thank you for traveling with Craft Inc. Gates."
|
||||
showTeleportMessage: true
|
||||
gateTeleportNoPermissionMessage: "You are not allowed to use this gate!"
|
||||
showTeleportNoPermissionMessage: true
|
||||
gateTeleportVehicleNotAllowedMessage: "You must not use that gate while riding!"
|
||||
gateMaterial: "nether portal"
|
@ -1 +0,0 @@
|
||||
../plugin.yml
|
@ -1,160 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
SERVICE='craftbukkit*.jar'
|
||||
#USERNAME="minecraft"
|
||||
CPU_COUNT=2
|
||||
BUKKIT="$SCRIPT_DIR/../target/lib/$SERVICE"
|
||||
INVOCATION="java -Xmx1000M -Xms300M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=$CPU_COUNT -XX:+AggressiveOpts -jar $BUKKIT nogui"
|
||||
MCPATH="$SCRIPT_DIR/../bukkit-testserver"
|
||||
|
||||
if [ ! -d "$MCPATH" ]; then
|
||||
mkdir -p "$MCPATH"
|
||||
fi
|
||||
|
||||
ME=$(whoami)
|
||||
as_user() {
|
||||
#if [ $ME == $USERNAME ] ; then
|
||||
bash -c "$1"
|
||||
#else
|
||||
#su - $USERNAME -c "$1"
|
||||
#fi
|
||||
}
|
||||
|
||||
mc_start() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "Tried to start but $SERVICE was already running!"
|
||||
else
|
||||
echo "$SERVICE was not running... starting."
|
||||
cd "$MCPATH"
|
||||
as_user "cd "$MCPATH" && screen -dmS minecraft $INVOCATION"
|
||||
sleep 7
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is now running."
|
||||
else
|
||||
echo "Could not start $SERVICE."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
mc_stop() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is running... stopping."
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"save-all\"\015'"
|
||||
sleep 2
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"stop\"\015'"
|
||||
sleep 6
|
||||
else
|
||||
echo "$SERVICE was not running."
|
||||
fi
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE could not be shut down... still running."
|
||||
else
|
||||
echo "$SERVICE is shut down."
|
||||
fi
|
||||
}
|
||||
|
||||
mc_save() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is running... saving."
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"save-all\"\015'"
|
||||
else
|
||||
echo "$SERVICE was not running."
|
||||
fi
|
||||
}
|
||||
|
||||
mc_reload() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is running... reloading."
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"reload\"\015'"
|
||||
else
|
||||
echo "$SERVICE was not running."
|
||||
fi
|
||||
}
|
||||
|
||||
mc_reload_or_start() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE was already running! Doing a reload now!"
|
||||
mc_reload
|
||||
else
|
||||
echo "$SERVICE was not running... starting."
|
||||
cd "$MCPATH"
|
||||
as_user "cd \"$MCPATH\" && screen -dmS minecraft $INVOCATION"
|
||||
sleep 7
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is now running."
|
||||
else
|
||||
echo "Could not start $SERVICE."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
mc_ddidderr_admin() {
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is running... making ddidder to admin and reloading permissions."
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"pex user ddidderr group set admin\"\015'"
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"pex reload\"\015'"
|
||||
else
|
||||
echo "$SERVICE was not running."
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "Starting Minecraft..."
|
||||
mc_start
|
||||
echo "DONE"
|
||||
;;
|
||||
stop)
|
||||
echo "Stopping Minecraft..."
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"say SERVER SHUTTING DOWN!\"\015'"
|
||||
mc_stop
|
||||
echo "DONE"
|
||||
;;
|
||||
restart)
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"say SERVER REBOOT IN 10 SECONDS.\"\015'"
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
reload)
|
||||
mc_reload
|
||||
;;
|
||||
reload_or_start)
|
||||
echo "Starting or reloading Minecraft..."
|
||||
mc_reload_or_start
|
||||
echo "DONE"
|
||||
;;
|
||||
ddidderr_admin)
|
||||
mc_ddidderr_admin
|
||||
;;
|
||||
connected)
|
||||
as_user "screen -p 0 -S minecraft -X eval 'stuff \"who\"\015'"
|
||||
sleep 2s
|
||||
tac "$MCPATH"/server.log | grep -m 1 "Connected"
|
||||
;;
|
||||
status)
|
||||
if ps ax | grep -v grep | grep -v -i SCREEN | grep "craftbukkit" > /dev/null
|
||||
then
|
||||
echo "$SERVICE is running."
|
||||
else
|
||||
echo "$SERVICE is not running."
|
||||
fi
|
||||
;;
|
||||
save)
|
||||
mc_save
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/minecraft {start|stop|restart|connected|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$(dirname "$0")"
|
||||
|
||||
DEVELOPER=$(whoami)
|
||||
|
||||
if [ $DEVELOPER = "tobi" ]; then
|
||||
BUKKIT_DIR="$HOME/minecraft/testbuk"
|
||||
PLUGIN_DIR="$HOME/minecraft/testbuk/plugins"
|
||||
START_STOP_SCRIPT="$BUKKIT_DIR/../minecraft.sh"
|
||||
else
|
||||
BUKKIT_DIR="$SCRIPT_DIR/../bukkit-testserver"
|
||||
PLUGIN_DIR="$SCRIPT_DIR/../bukkit-testserver/plugins"
|
||||
START_STOP_SCRIPT="$SCRIPT_DIR/minecraft.sh"
|
||||
fi
|
||||
|
||||
# TODO: This is a bad solution! Maven should write necessary information into an extra file.
|
||||
ARTIFACT_ID="$(grep -C5 '<groupId>de.craftinc' "$SCRIPT_DIR/../pom.xml" | grep '<name>' | sed 's/[ \t]*<name>//g' | sed 's/<\/name>[ \t]*//g')"
|
||||
|
||||
# TODO: This is a bad solution! Maven should write necessary information into an extra file.
|
||||
VERSION="$(grep -C5 '<groupId>de.craftinc' "$SCRIPT_DIR/../pom.xml" | grep '<version>' | sed 's/[ \t]*<version>//g' | sed 's/<\/version>[ \t]*//g')"
|
||||
|
||||
mkdir -p "$PLUGIN_DIR"
|
||||
|
||||
cp "$SCRIPT_DIR/../target/$ARTIFACT_ID $VERSION".jar "$PLUGIN_DIR/"
|
||||
|
||||
echo -e "ddidderr\nmice_on_drugs\nMochaccino\nbeuth_el_max" > "$BUKKIT_DIR/ops.txt"
|
||||
|
||||
$START_STOP_SCRIPT reload_or_start
|
@ -1,217 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import de.craftinc.gates.controllers.GatesManager;
|
||||
import de.craftinc.gates.listeners.*;
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.ConfigurationUtil;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import de.craftinc.gates.commands.*;
|
||||
import org.mcstats.Metrics;
|
||||
|
||||
public class Plugin extends JavaPlugin {
|
||||
private static Plugin instance;
|
||||
|
||||
private String baseCommand;
|
||||
protected List<BaseCommand> commands = new ArrayList<>();
|
||||
|
||||
private GatesManager gatesManager = new GatesManager();
|
||||
|
||||
private PermissionController permissionController = new PermissionController();
|
||||
|
||||
private PlayerMoveListener moveListener;
|
||||
private VehicleMoveListener vehicleListener;
|
||||
private PlayerTeleportListener teleportListener = new PlayerTeleportListener();
|
||||
private PlayerRespawnListener respawnListener = new PlayerRespawnListener();
|
||||
private PlayerChangedWorldListener worldChangeListener = new PlayerChangedWorldListener();
|
||||
private PlayerJoinListener joinListener = new PlayerJoinListener();
|
||||
private BlockBreakListener blockBreakListener = new BlockBreakListener();
|
||||
|
||||
public Plugin() {
|
||||
instance = this;
|
||||
moveListener = new PlayerMoveListener(this);
|
||||
vehicleListener = new VehicleMoveListener(this);
|
||||
}
|
||||
|
||||
public static Plugin getPlugin() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public GatesManager getGatesManager() {
|
||||
return gatesManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
ConfigurationSerialization.registerClass(Gate.class);
|
||||
}
|
||||
|
||||
private void setupPermissions() {
|
||||
if (getServer().getPluginManager().getPlugin("Vault") == null) {
|
||||
log("Not using setup permission provider provided by Vault.");
|
||||
return;
|
||||
}
|
||||
|
||||
RegisteredServiceProvider<Permission> rsp = getServer().getServicesManager().getRegistration(Permission.class);
|
||||
|
||||
if (rsp != null) {
|
||||
log("Using permission provider provided by Vault.");
|
||||
permissionController.setPermission(rsp.getProvider());
|
||||
} else {
|
||||
log("Not using setup permission provider provided by Vault.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
gatesManager.saveGatesToDisk();
|
||||
log("Disabled");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Setup Metrics
|
||||
try {
|
||||
Metrics metrics = new Metrics(this);
|
||||
metrics.start();
|
||||
} catch (IOException e) {
|
||||
log("Failed to start metrics!");
|
||||
}
|
||||
|
||||
// Setup configuration
|
||||
this.saveDefaultConfig();
|
||||
|
||||
// Setup permissions
|
||||
setupPermissions();
|
||||
|
||||
// Add the commands
|
||||
commands.add(new CommandHelp());
|
||||
commands.add(new CommandNew());
|
||||
commands.add(new CommandRemove());
|
||||
commands.add(new CommandLocation());
|
||||
commands.add(new CommandExit());
|
||||
commands.add(new CommandTriggerOpen());
|
||||
commands.add(new CommandRename());
|
||||
commands.add(new CommandList());
|
||||
commands.add(new CommandInfo());
|
||||
commands.add(new CommandNearby());
|
||||
commands.add(new CommandTriggerVehicles());
|
||||
commands.add(new CommandMaterial());
|
||||
commands.add(new CommandTeleport());
|
||||
|
||||
// Register events
|
||||
this.registerEventListeners();
|
||||
|
||||
// Load gates
|
||||
boolean success = gatesManager.loadGatesFromDisk();
|
||||
|
||||
if (success) {
|
||||
log("Enabled");
|
||||
} else {
|
||||
PluginManager pm = this.getServer().getPluginManager();
|
||||
pm.disablePlugin(this);
|
||||
}
|
||||
}
|
||||
|
||||
public PermissionController getPermissionController() {
|
||||
return permissionController;
|
||||
}
|
||||
|
||||
private void registerEventListeners() {
|
||||
PluginManager pm = this.getServer().getPluginManager();
|
||||
|
||||
pm.registerEvents(this.moveListener, this);
|
||||
pm.registerEvents(this.teleportListener, this);
|
||||
pm.registerEvents(this.respawnListener, this);
|
||||
pm.registerEvents(this.worldChangeListener, this);
|
||||
pm.registerEvents(this.joinListener, this);
|
||||
pm.registerEvents(this.vehicleListener, this);
|
||||
|
||||
if (getConfig().getBoolean(ConfigurationUtil.confCheckForBrokenGateFramesKey)) {
|
||||
pm.registerEvents(this.blockBreakListener, this);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Commands
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String getBaseCommand() {
|
||||
if (this.baseCommand != null)
|
||||
return this.baseCommand;
|
||||
|
||||
Map<String, Map<String, Object>> Commands = this.getDescription().getCommands();
|
||||
|
||||
this.baseCommand = Commands.keySet().iterator().next();
|
||||
|
||||
return this.baseCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
List<String> parameters = new ArrayList<>(Arrays.asList(args));
|
||||
this.handleCommand(sender, parameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleCommand(CommandSender sender, List<String> parameters) {
|
||||
if (parameters.size() == 0) {
|
||||
this.commands.get(0).execute(sender, parameters);
|
||||
return;
|
||||
}
|
||||
|
||||
String commandName = parameters.get(0).toLowerCase();
|
||||
parameters.remove(0);
|
||||
|
||||
for (BaseCommand command : this.commands) {
|
||||
if (command.getAliases().contains(commandName)) {
|
||||
command.execute(sender, parameters);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatColor.RED + "Unknown gate-command \"" + commandName + "\"." +
|
||||
ChatColor.GREEN + " Try " + "/" + getBaseCommand() + " help");
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging
|
||||
*/
|
||||
public static void log(String msg) {
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public static void log(Level level, String msg) {
|
||||
Logger.getLogger("Minecraft").log(level, "[" + instance.getDescription().getFullName() + "] " + msg);
|
||||
}
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.ConfigurationUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.controllers.GatesManager;
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.util.TextUtil;
|
||||
|
||||
public abstract class BaseCommand {
|
||||
PermissionController permissionController;
|
||||
GatesManager gatesManager;
|
||||
|
||||
List<String> aliases = new ArrayList<>();
|
||||
List<String> requiredParameters = new ArrayList<>();
|
||||
List<String> optionalParameters = new ArrayList<>();
|
||||
|
||||
String helpDescription = "no description";
|
||||
|
||||
List<String> parameters;
|
||||
CommandSender sender;
|
||||
Player player;
|
||||
Gate gate;
|
||||
|
||||
boolean senderMustBePlayer = true;
|
||||
boolean hasGateParam = true;
|
||||
|
||||
String requiredPermission;
|
||||
boolean needsPermissionAtCurrentLocation;
|
||||
|
||||
boolean shouldPersistToDisk;
|
||||
|
||||
public List<String> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public BaseCommand() {
|
||||
gatesManager = Plugin.getPlugin().getGatesManager();
|
||||
permissionController = Plugin.getPlugin().getPermissionController();
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, List<String> parameters) {
|
||||
this.sender = sender;
|
||||
this.parameters = parameters;
|
||||
|
||||
if (!this.validateCall()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender instanceof Player) {
|
||||
this.player = (Player)sender;
|
||||
}
|
||||
|
||||
this.perform();
|
||||
|
||||
if (this.shouldPersistToDisk && getSaveOnChanges()) {
|
||||
gatesManager.saveGatesToDisk();
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void perform();
|
||||
|
||||
void sendMessage(String message) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
|
||||
void sendMessage(List<String> messages) {
|
||||
for (String message : messages) {
|
||||
this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
boolean setGateUsingParameter(String param) {
|
||||
if (!gatesManager.gateExists(param)) {
|
||||
return false;
|
||||
} else {
|
||||
gate = gatesManager.getGateWithId(param);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return false if a gate is required for this command but this.gate == null.
|
||||
*/
|
||||
boolean hasPermission() {
|
||||
if (needsPermissionAtCurrentLocation) {
|
||||
return permissionController.hasPermission(sender, requiredPermission);
|
||||
} else {
|
||||
return permissionController.hasPermission(sender, gate, requiredPermission);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Help and usage description
|
||||
*/
|
||||
|
||||
String getUsageTemplate(boolean withDescription) {
|
||||
String ret = "";
|
||||
|
||||
ret += ChatColor.AQUA;
|
||||
ret += "/" + Plugin.getPlugin().getBaseCommand() + " " + TextUtil.implode(getAliases(), ",") + " ";
|
||||
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
for (String requiredParameter : requiredParameters) {
|
||||
parts.add("[" + requiredParameter + "]");
|
||||
}
|
||||
|
||||
for (String optionalParameter : optionalParameters) {
|
||||
parts.add("*[" + optionalParameter + "]");
|
||||
}
|
||||
|
||||
|
||||
ret += ChatColor.DARK_AQUA;
|
||||
ret += TextUtil.implode(parts, " ");
|
||||
|
||||
if (withDescription) {
|
||||
ret += " ";
|
||||
ret += ChatColor.YELLOW;
|
||||
ret += helpDescription;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean validateCall() {
|
||||
boolean allParametersThere = parameters.size() >= requiredParameters.size();
|
||||
boolean senderIsPlayer = this.sender instanceof Player;
|
||||
boolean hasGateParameter = false;
|
||||
|
||||
if (this.hasGateParam && this.parameters.size() > 0 && this.setGateUsingParameter(this.parameters.get(0))) {
|
||||
hasGateParameter = true;
|
||||
}
|
||||
|
||||
boolean senderHasPermission = this.hasPermission();
|
||||
boolean valid;
|
||||
|
||||
if (this.senderMustBePlayer && !senderIsPlayer) {
|
||||
sendMessage(ChatColor.RED + "This command can only be used by in-game players.");
|
||||
valid = false;
|
||||
} else {
|
||||
if (!allParametersThere) {
|
||||
sendMessage(ChatColor.RED + "Some parameters are missing! " +
|
||||
ChatColor.AQUA + "Usage: " +
|
||||
getUsageTemplate(false)
|
||||
);
|
||||
valid = false;
|
||||
} else if ((!senderHasPermission && this.hasGateParam) ||
|
||||
(!senderHasPermission) ||
|
||||
(this.hasGateParam && !hasGateParameter)) {
|
||||
|
||||
sendMessage(ChatColor.RED +
|
||||
"You either provided a invalid gate or do not have permission to " +
|
||||
this.helpDescription.toLowerCase()
|
||||
);
|
||||
valid = false;
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
private boolean getSaveOnChanges() {
|
||||
FileConfiguration config = Plugin.getPlugin().getConfig();
|
||||
return config.getBoolean(ConfigurationUtil.confSaveOnChangesKey);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
abstract class BaseLocationCommand extends BaseCommand {
|
||||
|
||||
Location getValidPlayerLocation() {
|
||||
// The player might stand in a half block or a sign or whatever
|
||||
// Therefore we load some extra locations and blocks
|
||||
Location location = player.getLocation().clone();
|
||||
Block playerBlock = location.getBlock();
|
||||
Block upBlock = playerBlock.getRelative(BlockFace.UP);
|
||||
|
||||
if (playerBlock.getType() == Material.AIR) {
|
||||
return location;
|
||||
} else if (upBlock.getType() == Material.AIR) {
|
||||
return location.add(0, 1, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class CommandExit extends BaseCommand {
|
||||
|
||||
public CommandExit() {
|
||||
aliases.add("exit");
|
||||
aliases.add("e");
|
||||
requiredParameters.add("id");
|
||||
helpDescription = "Change exit of location.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = true;
|
||||
shouldPersistToDisk = true;
|
||||
senderMustBePlayer = true;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
try {
|
||||
Location oldExit = gate.getExit();
|
||||
gate.setExit(player.getLocation());
|
||||
sendMessage(ChatColor.GREEN + "The exit of gate '" + gate.getId() + "' is now where you stand.");
|
||||
gatesManager.handleGateExitChange(gate, oldExit);
|
||||
} catch (Exception e) {
|
||||
GateBlockChangeSender.updateGateBlocks(gate);
|
||||
sendMessage(ChatColor.RED + "Setting the exit for the gate failed! See server log for more information");
|
||||
Plugin.log(Level.WARNING, e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.TextUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandHelp extends BaseCommand {
|
||||
|
||||
private static List<String> help;
|
||||
|
||||
public CommandHelp() {
|
||||
aliases.add("help");
|
||||
aliases.add("?");
|
||||
helpDescription = "prints this help page";
|
||||
requiredPermission = PermissionController.permissionInfo;
|
||||
hasGateParam = false;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = false;
|
||||
senderMustBePlayer = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
sendMessage(TextUtil.titleSize("Craft Inc. Gates Help"));
|
||||
sendMessage(getHelp());
|
||||
}
|
||||
|
||||
private List<String> getHelp() {
|
||||
if (help == null) {
|
||||
help = Arrays.asList(
|
||||
new CommandHelp().getUsageTemplate(true),
|
||||
new CommandNew().getUsageTemplate(true),
|
||||
new CommandRemove().getUsageTemplate(true),
|
||||
new CommandLocation().getUsageTemplate(true),
|
||||
new CommandExit().getUsageTemplate(true),
|
||||
new CommandTriggerOpen().getUsageTemplate(true),
|
||||
new CommandRename().getUsageTemplate(true),
|
||||
new CommandList().getUsageTemplate(true),
|
||||
new CommandInfo().getUsageTemplate(true),
|
||||
new CommandNearby().getUsageTemplate(true),
|
||||
new CommandTriggerVehicles().getUsageTemplate(true),
|
||||
new CommandTeleport().getUsageTemplate(true),
|
||||
new CommandMaterial().getUsageTemplate(true)
|
||||
);
|
||||
Collections.sort(help);
|
||||
}
|
||||
|
||||
return help;
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.util.TextUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class CommandInfo extends BaseCommand {
|
||||
|
||||
public CommandInfo() {
|
||||
aliases.add("info");
|
||||
aliases.add("i");
|
||||
optionalParameters.add("id");
|
||||
helpDescription = "Print detailed information about a certain or the closest gate.";
|
||||
requiredPermission = PermissionController.permissionInfo;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = false;
|
||||
senderMustBePlayer = false;
|
||||
hasGateParam = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
if (this.parameters.size() > 0) {
|
||||
|
||||
if (!this.setGateUsingParameter(this.parameters.get(0))) {
|
||||
sendMessage(ChatColor.RED + "You either provided a invalid gate or do not have permission to " + this.helpDescription.toLowerCase());
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage(TextUtil.titleSize("Information about: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
|
||||
} else {
|
||||
boolean senderIsPlayer = this.sender instanceof Player;
|
||||
|
||||
if (!senderIsPlayer) {
|
||||
sendMessage(ChatColor.RED + "Only ingame players can perform this command without a supplied gate id!");
|
||||
return;
|
||||
}
|
||||
|
||||
Player p = (Player) this.sender;
|
||||
this.gate = gatesManager.getNearestGate(p.getLocation());
|
||||
|
||||
if (!this.hasPermission() || this.gate == null) {
|
||||
sendMessage(ChatColor.RED + "There is either no gate nearby or you do not have permission to " + this.helpDescription.toLowerCase());
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin.log(this.gate.toString());
|
||||
|
||||
sendMessage(TextUtil.titleSize("Information about closest gate: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
|
||||
}
|
||||
|
||||
String openMessage = ChatColor.DARK_AQUA + "This gate is";
|
||||
|
||||
if (gate.isOpen())
|
||||
openMessage += ChatColor.AQUA + " open";
|
||||
else
|
||||
openMessage += ChatColor.AQUA + " closed";
|
||||
|
||||
openMessage += ".\n";
|
||||
|
||||
sendMessage(openMessage);
|
||||
|
||||
if (gate.getLocation() != null)
|
||||
sendMessage(ChatColor.DARK_AQUA + "location: " + ChatColor.AQUA + "( " + (int) gate.getLocation().getX() +
|
||||
" | " + (int) gate.getLocation().getY() + " | " + (int) gate.getLocation().getZ() + " ) in " +
|
||||
gate.getLocation().getWorld().getName());
|
||||
else
|
||||
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no location");
|
||||
|
||||
if (gate.getExit() != null)
|
||||
sendMessage(ChatColor.DARK_AQUA + "exit: " + ChatColor.AQUA + "( " + (int) gate.getExit().getX() + " | "
|
||||
+ (int) gate.getExit().getY() + " | " + (int) gate.getExit().getZ() + " ) in " +
|
||||
gate.getExit().getWorld().getName());
|
||||
else
|
||||
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no exit");
|
||||
|
||||
|
||||
if (gate.getAllowsVehicles())
|
||||
sendMessage(ChatColor.DARK_AQUA + "You can ride through this gate.");
|
||||
|
||||
sendMessage(ChatColor.DARK_AQUA + "This gate is made of "
|
||||
+ ChatColor.AQUA + gate.getMaterial() + ChatColor.DARK_AQUA + ".");
|
||||
|
||||
if (this.sender instanceof Player) {
|
||||
HashSet<Gate> set = new HashSet<>();
|
||||
set.add(this.gate);
|
||||
|
||||
GateBlockChangeSender.temporaryHighlightGatesFrames((Player)this.sender, set);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,296 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.util.TextUtil;
|
||||
|
||||
public class CommandList extends BaseCommand {
|
||||
|
||||
private static final int linesPerPage = 15;
|
||||
|
||||
/* this is actually not true. the font used by Minecraft is not
|
||||
monospaced. but there seems to be no (easy) way to calculate
|
||||
the drawing-size of a string.
|
||||
*/
|
||||
private static final int charactersPerLine = 52;
|
||||
|
||||
public CommandList() {
|
||||
aliases.add("list");
|
||||
aliases.add("ls");
|
||||
|
||||
optionalParameters.add("page");
|
||||
hasGateParam = false;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
|
||||
helpDescription = "lists all availible gates.";
|
||||
|
||||
requiredPermission = PermissionController.permissionInfo;
|
||||
shouldPersistToDisk = false;
|
||||
senderMustBePlayer = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
int page = this.getPageParameter();
|
||||
List<String> allPages = this.pagedGateIds();
|
||||
|
||||
if (allPages == null) { // no gates exist
|
||||
sendMessage(ChatColor.RED + "There are no gates yet. " + ChatColor.RESET +
|
||||
"(Note that you might not be allowed to get information about certain gates)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (page > allPages.size() || page < 1) {
|
||||
sendMessage(ChatColor.RED + "The requested page is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
String message = TextUtil.titleSize("List of all gates (" + page + "/" + allPages.size() + ")") + "\n";
|
||||
message += allPages.get(page - 1);
|
||||
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
private static List<String> linesOfGateIds(List<String> gates) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
List<String> gateIdsForCurrentLine = new ArrayList<>();
|
||||
int numCharactersInCurrentLine = 0;
|
||||
|
||||
while (index < gates.size()) {
|
||||
String gateId = gates.get(index);
|
||||
int gateIdLength = gateId.length() + 2; // actual length + comma + whitespace
|
||||
|
||||
if (gateIdLength > charactersPerLine && numCharactersInCurrentLine == 0) { // special case: very long gate id
|
||||
gateIdsForCurrentLine = new ArrayList<>();
|
||||
numCharactersInCurrentLine = 0;
|
||||
|
||||
while ((gateId.length() + 2) > charactersPerLine) {
|
||||
int cutPos = charactersPerLine;
|
||||
|
||||
// is the id too long to add comma and whitespace but not longer than the line?
|
||||
if (gateId.length() <= charactersPerLine) {
|
||||
cutPos -= 2;
|
||||
}
|
||||
|
||||
lines.add(gateId.substring(0, cutPos));
|
||||
gateId = gateId.substring(cutPos, gateId.length());
|
||||
}
|
||||
|
||||
gateIdsForCurrentLine.add(gateId);
|
||||
|
||||
numCharactersInCurrentLine += gateId.length();
|
||||
index++;
|
||||
} else if ((numCharactersInCurrentLine + gateIdLength) <= charactersPerLine) { // gate fits into current line
|
||||
gateIdsForCurrentLine.add(gateId);
|
||||
numCharactersInCurrentLine += gateIdLength;
|
||||
|
||||
index++;
|
||||
} else { // the current gate does not fit on the
|
||||
lines.add(TextUtil.implode(gateIdsForCurrentLine, ", ") + ", ");
|
||||
|
||||
gateIdsForCurrentLine = new ArrayList<>();
|
||||
numCharactersInCurrentLine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lines.add(TextUtil.implode(gateIdsForCurrentLine, ", "));
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static String intToTitleString(int i, boolean addPreviousPageNote, boolean addNextPageNote) {
|
||||
String retVal = ChatColor.DARK_AQUA + "";
|
||||
|
||||
if (i < 26) {
|
||||
retVal += (char) (i + 65);
|
||||
} else if (i == 26) {
|
||||
retVal += "0-9";
|
||||
} else {
|
||||
retVal += "!@#$";
|
||||
}
|
||||
|
||||
if (addPreviousPageNote && addNextPageNote) {
|
||||
retVal += " (more on previous and next page)";
|
||||
} else if (addPreviousPageNote) {
|
||||
retVal += " (more on previous page)";
|
||||
} else if (addNextPageNote) {
|
||||
retVal += " (more on next page)";
|
||||
}
|
||||
|
||||
return retVal + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for getting a collection of gates the player is allowed to see.
|
||||
*/
|
||||
private Collection<Gate> getAllGates() {
|
||||
Collection<Gate> gates = gatesManager.allGates();
|
||||
// create a copy since we cannot iterate over a collection while modifying it!
|
||||
Collection<Gate> gatesCopy = new ArrayList<>(gates);
|
||||
|
||||
for (Gate gate : gatesCopy) {
|
||||
if (!this.permissionController.hasPermission(this.sender, gate, this.requiredPermission)) {
|
||||
gates.remove(gate);
|
||||
}
|
||||
}
|
||||
return gates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts all gates by there first character.
|
||||
* Puts gates in corresponding Lists: (all returned lists will be sorted alphabetically)
|
||||
* list 0-25: a,b,c,..,z
|
||||
* list 26: 0-9
|
||||
* list 27: other
|
||||
*/
|
||||
private static List<List<String>> gatesSortedByName(Collection<Gate> allGates) {
|
||||
// create the lists
|
||||
List<List<String>> ids = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 28; i++) {
|
||||
ids.add(new ArrayList<String>());
|
||||
}
|
||||
|
||||
// put all gates into correct lists
|
||||
for (Gate gate : allGates) {
|
||||
String id = gate.getId();
|
||||
int first = id.charAt(0);
|
||||
|
||||
if (first > 96 && first < 123) { // convert lower case chars
|
||||
first -= 97;
|
||||
} else if (first > 64 && first < 91) { // convert upper case chars
|
||||
first -= 65;
|
||||
} else if (first > 47 && first < 58) { // convert numbers
|
||||
first = 26;
|
||||
} else { // everything else
|
||||
first = 27;
|
||||
}
|
||||
|
||||
ids.get(first).add(id);
|
||||
}
|
||||
|
||||
// sort everything
|
||||
for (int i = 0; i < 28; i++) {
|
||||
Collections.sort(ids.get(i));
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of strings.
|
||||
* Each string is the text for a page.
|
||||
* The maximum number of lines per page is 'linesPerPage' minus 1.
|
||||
* Will return an empty list if no gates are availible.
|
||||
*/
|
||||
private List<String> pagedGateIds() {
|
||||
Collection<Gate> gates = this.getAllGates();
|
||||
|
||||
if (gates.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<List<String>> gatesSortedByName = gatesSortedByName(gates);
|
||||
List<String> allPages = new ArrayList<>();
|
||||
int linesLeftOnPage = linesPerPage - 1;
|
||||
String currentPageString = "";
|
||||
|
||||
for (int i = 0; i < gatesSortedByName.size(); i++) {
|
||||
|
||||
List<String> currentGates = gatesSortedByName.get(i);
|
||||
|
||||
if (currentGates.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> currentGatesAsLines = linesOfGateIds(currentGates);
|
||||
boolean moreGatesOnLastPage = false;
|
||||
|
||||
while (!currentGatesAsLines.isEmpty()) {
|
||||
|
||||
if (linesLeftOnPage < 2) {
|
||||
currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
|
||||
allPages.add(currentPageString);
|
||||
currentPageString = "";
|
||||
|
||||
linesLeftOnPage = linesPerPage - 1;
|
||||
}
|
||||
|
||||
// calculate number of lines to add to current page
|
||||
int linesNecessaryForCurrentGates = currentGatesAsLines.size();
|
||||
int linesToFill;
|
||||
boolean moreGatesOnNextPage;
|
||||
|
||||
if (linesNecessaryForCurrentGates < linesLeftOnPage) {
|
||||
linesToFill = linesNecessaryForCurrentGates;
|
||||
moreGatesOnNextPage = false;
|
||||
} else {
|
||||
linesToFill = linesLeftOnPage - 1;
|
||||
moreGatesOnNextPage = true;
|
||||
}
|
||||
|
||||
// add title
|
||||
currentPageString += intToTitleString(i, moreGatesOnLastPage, moreGatesOnNextPage);
|
||||
currentPageString += ChatColor.AQUA;
|
||||
linesLeftOnPage--;
|
||||
|
||||
// add gate lines
|
||||
for (int j = 0; j < linesToFill; j++) {
|
||||
currentPageString += currentGatesAsLines.get(j) + "\n";
|
||||
}
|
||||
|
||||
// remove lines added
|
||||
for (int j = 0; j < linesToFill; j++) {
|
||||
currentGatesAsLines.remove(0);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
moreGatesOnLastPage = linesNecessaryForCurrentGates >= linesLeftOnPage;
|
||||
linesLeftOnPage -= linesToFill;
|
||||
}
|
||||
}
|
||||
|
||||
// add the last page
|
||||
if (!currentPageString.isEmpty()) {
|
||||
currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
|
||||
allPages.add(currentPageString);
|
||||
}
|
||||
|
||||
return allPages;
|
||||
}
|
||||
|
||||
|
||||
private int getPageParameter() {
|
||||
int page = 1;
|
||||
|
||||
try {
|
||||
page = new Integer(parameters.get(0));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class CommandLocation extends BaseLocationCommand {
|
||||
|
||||
public CommandLocation() {
|
||||
aliases.add("location");
|
||||
aliases.add("lo");
|
||||
|
||||
requiredParameters.add("id");
|
||||
helpDescription = "Set the entrance of the gate to your current location.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
|
||||
needsPermissionAtCurrentLocation = true;
|
||||
shouldPersistToDisk = true;
|
||||
senderMustBePlayer = true;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
Location playerLocation = getValidPlayerLocation();
|
||||
|
||||
if (playerLocation == null) {
|
||||
sendMessage("There is not enough room for a gate to open here");
|
||||
return;
|
||||
}
|
||||
|
||||
Location oldLocation = gate.getLocation();
|
||||
Set<Location> oldGateBlockLocations = gate.getGateBlockLocations();
|
||||
Set<Block> oldFrameBlocks = gate.getGateFrameBlocks();
|
||||
|
||||
try {
|
||||
if (gate.isOpen()) {
|
||||
GateBlockChangeSender.updateGateBlocks(gate, true);
|
||||
}
|
||||
|
||||
gate.setLocation(playerLocation);
|
||||
sendMessage(ChatColor.GREEN + "The location of '" + gate.getId() + "' is now at your current location.");
|
||||
} catch (Exception e) {
|
||||
sendMessage(ChatColor.RED + "There seems to be no frame at your new location! The gate got closed!" + ChatColor.AQUA + " You should build a frame now and execute:");
|
||||
sendMessage(new CommandTriggerOpen().getUsageTemplate(true));
|
||||
} finally {
|
||||
gatesManager.handleGateLocationChange(gate, oldLocation, oldGateBlockLocations, oldFrameBlocks);
|
||||
GateBlockChangeSender.updateGateBlocks(gate);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.models.GateMaterial;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
public class CommandMaterial extends BaseCommand {
|
||||
|
||||
public CommandMaterial() {
|
||||
aliases.add("material");
|
||||
aliases.add("m");
|
||||
|
||||
requiredParameters.add("id");
|
||||
requiredParameters.add("material");
|
||||
|
||||
senderMustBePlayer = false;
|
||||
hasGateParam = true;
|
||||
helpDescription = "Change the material of a gate";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = true;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
GateMaterial material;
|
||||
try {
|
||||
material = new GateMaterial(parameters.get(1));
|
||||
} catch (InvalidParameterException e) {
|
||||
sendMessage(ChatColor.RED + "Invalid material!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
gate.setMaterial(material);
|
||||
} catch (Exception e) {
|
||||
sendMessage(ChatColor.RED + "Frame invalid. Gate is now closed!");
|
||||
}
|
||||
|
||||
GateBlockChangeSender.updateGateBlocks(gate);
|
||||
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " uses now " + material.toString() + " as material.");
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import de.craftinc.gates.util.TextUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandNearby extends BaseLocationCommand {
|
||||
|
||||
public CommandNearby() {
|
||||
aliases.add("nearby");
|
||||
aliases.add("nb");
|
||||
|
||||
helpDescription = "Highlight nearby gates";
|
||||
requiredPermission = PermissionController.permissionInfo;
|
||||
needsPermissionAtCurrentLocation = true;
|
||||
shouldPersistToDisk = false;
|
||||
senderMustBePlayer = true;
|
||||
hasGateParam = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
Set<Gate> nearbyGates = gatesManager.getNearbyGates(player.getLocation().getChunk());
|
||||
|
||||
if (nearbyGates == null) {
|
||||
player.sendMessage("There are no gates near you!");
|
||||
} else {
|
||||
GateBlockChangeSender.temporaryHighlightGatesFrames(player, nearbyGates);
|
||||
|
||||
ArrayList<String> gateNames = new ArrayList<>();
|
||||
|
||||
for (Gate g : nearbyGates) {
|
||||
gateNames.add(g.getId());
|
||||
}
|
||||
player.sendMessage("Nearby gates: " + TextUtil.implode(gateNames, ", "));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
|
||||
public class CommandNew extends BaseLocationCommand {
|
||||
|
||||
public CommandNew() {
|
||||
aliases.add("new");
|
||||
aliases.add("create");
|
||||
aliases.add("n");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
senderMustBePlayer = true;
|
||||
hasGateParam = false;
|
||||
helpDescription = "Create a gate at your current location.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = true;
|
||||
shouldPersistToDisk = true;
|
||||
senderMustBePlayer = true;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
String id = parameters.get(0);
|
||||
|
||||
if (gatesManager.gateExists(id)) {
|
||||
sendMessage(ChatColor.RED + "Creating the gate failed! " + "A gate with the supplied id already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
gate = new Gate(id);
|
||||
sendMessage(ChatColor.GREEN + "Gate with id '" + id + "' was created.");
|
||||
|
||||
Location playerLocation = getValidPlayerLocation();
|
||||
|
||||
if (playerLocation != null) {
|
||||
try {
|
||||
gate.setLocation(playerLocation);
|
||||
sendMessage(ChatColor.AQUA + "The gates location has been set to your current location.");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} else {
|
||||
sendMessage(ChatColor.RED + "Your location is invalid!" + ChatColor.AQUA + "Go somewhere else and execute:");
|
||||
sendMessage(new CommandLocation().getUsageTemplate(true));
|
||||
}
|
||||
|
||||
gatesManager.handleNewGate(gate);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CommandRemove extends BaseCommand {
|
||||
|
||||
public CommandRemove() {
|
||||
aliases.add("delete");
|
||||
aliases.add("del");
|
||||
aliases.add("remove");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
senderMustBePlayer = false;
|
||||
helpDescription = "Removes the gate from the game.";
|
||||
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
gatesManager.handleDeletion(gate);
|
||||
GateBlockChangeSender.updateGateBlocks(gate, true);
|
||||
sendMessage(ChatColor.GREEN + "Gate with id '" + gate.getId() + "' was deleted.");
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CommandRename extends BaseCommand {
|
||||
|
||||
public CommandRename() {
|
||||
aliases.add("rename");
|
||||
aliases.add("rn");
|
||||
|
||||
hasGateParam = true;
|
||||
senderMustBePlayer = false;
|
||||
requiredParameters.add("current name");
|
||||
requiredParameters.add("new name");
|
||||
helpDescription = "Changes the id of a gate.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = true;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
String newId = parameters.get(1);
|
||||
|
||||
if (gatesManager.gateExists(newId)) {
|
||||
sendMessage(ChatColor.RED + "Cannot rename " + gate.getId() + ". There is already a gate named " + newId + ".");
|
||||
} else {
|
||||
String oldId = gate.getId();
|
||||
|
||||
gate.setId(newId);
|
||||
gatesManager.handleGateIdChange(gate, oldId);
|
||||
|
||||
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " is now known as " + newId + ".");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
|
||||
public class CommandTeleport extends BaseCommand {
|
||||
|
||||
public CommandTeleport() {
|
||||
aliases.add("teleport");
|
||||
aliases.add("t");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
senderMustBePlayer = true;
|
||||
hasGateParam = true;
|
||||
helpDescription = "Teleport to the location of a gate";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CommandTriggerOpen extends BaseCommand {
|
||||
|
||||
public CommandTriggerOpen() {
|
||||
aliases.add("triggerOpen");
|
||||
aliases.add("o");
|
||||
|
||||
requiredParameters.add("id");
|
||||
helpDescription = "Open/close a gate.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = true;
|
||||
senderMustBePlayer = false;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
try {
|
||||
if (!gate.isOpen() && gate.getExit() == null && player != null) {
|
||||
gate.setExit(player.getLocation());
|
||||
sendMessage(ChatColor.GREEN + "The exit of gate '" + gate.getId() + "' is now where you stand.");
|
||||
}
|
||||
|
||||
gate.setOpen(!gate.isOpen());
|
||||
|
||||
GateBlockChangeSender.updateGateBlocks(gate);
|
||||
gatesManager.handleGateLocationChange(gate, null, null, null);
|
||||
sendMessage(ChatColor.GREEN + "The gate is now " + (gate.isOpen() ? "open." : "closed."));
|
||||
} catch (Exception e) {
|
||||
sendMessage(ChatColor.RED + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.commands;
|
||||
|
||||
import de.craftinc.gates.controllers.PermissionController;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CommandTriggerVehicles extends BaseCommand {
|
||||
|
||||
public CommandTriggerVehicles() {
|
||||
aliases.add("vehicles");
|
||||
aliases.add("v");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Allow/deny players to travel while riding.";
|
||||
requiredPermission = PermissionController.permissionManage;
|
||||
needsPermissionAtCurrentLocation = false;
|
||||
shouldPersistToDisk = true;
|
||||
senderMustBePlayer = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform() {
|
||||
gate.setAllowsVehicles(gate.getAllowsVehicles());
|
||||
|
||||
if (gate.getAllowsVehicles()) {
|
||||
sendMessage(ChatColor.GREEN + "Traveling while riding is now enabled for this gate.");
|
||||
} else {
|
||||
sendMessage(ChatColor.GREEN + "Traveling while riding is now disabled for this gate.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,477 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.controllers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.persistence.MigrationUtil;
|
||||
import de.craftinc.gates.util.ConfigurationUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import de.craftinc.gates.models.SimpleChunk;
|
||||
import de.craftinc.gates.models.SimpleLocation;
|
||||
|
||||
public class GatesManager {
|
||||
protected List<Gate> gates;
|
||||
|
||||
private static final String gatesPath = "gates"; // path to gates inside the yaml file
|
||||
private static final String storageVersionPath = "version";
|
||||
private static final int storageVersion = 3;
|
||||
|
||||
private File gatesConfigFile;
|
||||
private FileConfiguration gatesConfig;
|
||||
private int chunkRadius;
|
||||
private Map<String, Gate> gatesById;
|
||||
private Map<SimpleChunk, Set<Gate>> gatesByChunk;
|
||||
private Map<SimpleLocation, Gate> gatesByLocation;
|
||||
private Map<SimpleLocation, Gate> gatesByFrameLocation;
|
||||
private boolean storageFileIsInvalid = false;
|
||||
|
||||
public Gate getGateWithId(final String id) {
|
||||
return gatesById.get(id.toLowerCase());
|
||||
}
|
||||
|
||||
public Set<Gate> getNearbyGates(final Chunk chunk) {
|
||||
SimpleChunk simpleChunk = new SimpleChunk(chunk);
|
||||
return gatesByChunk.get(simpleChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest gate.
|
||||
*
|
||||
* @param location The location at which to look for a gate.
|
||||
* @return Might return null if there are no nearby gates.
|
||||
*/
|
||||
public Gate getNearestGate(final Location location) {
|
||||
Set<Gate> nearbyGates = getNearbyGates(location.getChunk());
|
||||
|
||||
if (nearbyGates == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double minDist = Double.MAX_VALUE;
|
||||
Gate nearestGate = null;
|
||||
|
||||
for (Gate g : nearbyGates) {
|
||||
double dist = location.distance(g.getLocation());
|
||||
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
nearestGate = g;
|
||||
}
|
||||
}
|
||||
|
||||
return nearestGate;
|
||||
}
|
||||
|
||||
Gate getGateAtLocation(final Location location) {
|
||||
SimpleLocation simpleLocation = new SimpleLocation(location);
|
||||
return gatesByLocation.get(simpleLocation);
|
||||
}
|
||||
|
||||
public Gate getGateAtFrameLocation(final Location location) {
|
||||
SimpleLocation simpleLocation = new SimpleLocation(location);
|
||||
return gatesByFrameLocation.get(simpleLocation);
|
||||
}
|
||||
|
||||
public void saveGatesToDisk() {
|
||||
if (storageFileIsInvalid) {
|
||||
Plugin.log(Level.SEVERE, "ERROR: Not saving gates to disk. Storage file is invalid or corrupted!");
|
||||
return;
|
||||
}
|
||||
|
||||
gatesConfig.set(gatesPath, gates);
|
||||
gatesConfig.set(storageVersionPath, storageVersion);
|
||||
|
||||
try {
|
||||
gatesConfig.save(gatesConfigFile);
|
||||
Plugin.log("Saved gates to disk.");
|
||||
} catch (IOException e) {
|
||||
Plugin.log(Level.SEVERE, "ERROR: Could not save gates to disk.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean loadGatesFromDisk() {
|
||||
// TODO: refactor: move loading/saving logic into persistence package
|
||||
|
||||
this.gatesConfigFile = new File(Plugin.getPlugin().getDataFolder(), "gates.yml");
|
||||
|
||||
if (!this.gatesConfigFile.exists()) {
|
||||
try {
|
||||
boolean isNew = this.gatesConfigFile.createNewFile();
|
||||
|
||||
if (isNew) {
|
||||
Plugin.log(Level.FINEST, "Created gate storage file.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.storageFileIsInvalid = true;
|
||||
Plugin.log(Level.SEVERE, "Cannot create gate storage file! No gates will be persisted.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.gatesConfig = new YamlConfiguration();
|
||||
|
||||
try {
|
||||
this.gatesConfig.load(this.gatesConfigFile);
|
||||
} catch (Exception e) {
|
||||
this.storageFileIsInvalid = true;
|
||||
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (" + Arrays.toString(e.getStackTrace()) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.gates = (List<Gate>) gatesConfig.getList(gatesPath);
|
||||
|
||||
if (this.gates == null) {
|
||||
this.gates = new ArrayList<>();
|
||||
}
|
||||
|
||||
for (Object o : this.gates) {
|
||||
|
||||
if (!(o instanceof Gate)) {
|
||||
this.storageFileIsInvalid = true;
|
||||
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (Invalid gate class detected)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Gate g : this.gates) {
|
||||
try {
|
||||
g.validate();
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
g.setOpen(false);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
Plugin.log(Level.FINER, "closed gate '" + g.getId() + "' reason: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
fillGatesById();
|
||||
fillGatesByChunk();
|
||||
fillGatesByLocation();
|
||||
fillGatesByFrameLocation();
|
||||
|
||||
Plugin.log("Loaded " + this.gates.size() + " gates.");
|
||||
|
||||
// migration
|
||||
int fileStorageVersion = gatesConfig.getInt(storageVersionPath);
|
||||
|
||||
if (fileStorageVersion > storageVersion) {
|
||||
this.storageFileIsInvalid = true;
|
||||
Plugin.log(Level.SEVERE, "Unsupported storage version detected! Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileStorageVersion < storageVersion && !this.gates.isEmpty()) {
|
||||
Plugin.log("Outdated storage version detected. Performing data migration...");
|
||||
boolean success = MigrationUtil.performMigration(fileStorageVersion, storageVersion, this.gates);
|
||||
|
||||
this.storageFileIsInvalid = !success;
|
||||
return success;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getChunkRadius() {
|
||||
if (this.chunkRadius == 0) {
|
||||
this.chunkRadius = Plugin.getPlugin().getConfig().getInt(ConfigurationUtil.confPlayerGateBlockUpdateRadiusKey);
|
||||
this.chunkRadius = this.chunkRadius >> 4;
|
||||
}
|
||||
|
||||
return this.chunkRadius;
|
||||
}
|
||||
|
||||
private void fillGatesById() {
|
||||
gatesById = new HashMap<>((int) (gates.size() * 1.25));
|
||||
|
||||
for (Gate g : gates) {
|
||||
this.addGateWithId(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillGatesByChunk() {
|
||||
HashSet<SimpleChunk> chunksUsedByGates = new HashSet<>();
|
||||
|
||||
for (Gate g : gates) {
|
||||
if (g.getLocation() != null) {
|
||||
Chunk c = g.getLocation().getChunk();
|
||||
|
||||
int x = c.getX();
|
||||
int z = c.getZ();
|
||||
|
||||
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
|
||||
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
|
||||
chunksUsedByGates.add(new SimpleChunk(i, j, c.getWorld()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gatesByChunk = new HashMap<>((int) (chunksUsedByGates.size() * 1.25));
|
||||
|
||||
for (Gate g : gates) {
|
||||
this.addGateByChunk(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillGatesByLocation() {
|
||||
Set<Location> gateBlocks = new HashSet<>();
|
||||
|
||||
for (Gate g : gates) {
|
||||
for (Location l : g.getGateBlockLocations()) {
|
||||
gateBlocks.add(l);
|
||||
Location headLocation = l.clone().add(0, 1, 0);
|
||||
gateBlocks.add(headLocation);
|
||||
}
|
||||
}
|
||||
|
||||
gatesByLocation = new HashMap<>((int) (gateBlocks.size() * 1.25));
|
||||
|
||||
for (Gate g : gates) {
|
||||
this.addGateByLocations(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillGatesByFrameLocation() {
|
||||
int numFrameBlocks = 0;
|
||||
|
||||
for (Gate g : gates) {
|
||||
numFrameBlocks += g.getGateFrameBlocks().size();
|
||||
}
|
||||
|
||||
gatesByFrameLocation = new HashMap<>((int) (numFrameBlocks * 1.25));
|
||||
|
||||
for (Gate g : gates) {
|
||||
this.addGateByFrameLocations(g);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeGateById(final String id) {
|
||||
gatesById.remove(id);
|
||||
}
|
||||
|
||||
private void addGateWithId(final Gate g) {
|
||||
gatesById.put(g.getId(), g);
|
||||
}
|
||||
|
||||
private void removeGateByLocation(final Set<Location> gateBlocks) {
|
||||
if (gateBlocks != null) {
|
||||
|
||||
for (Location l : gateBlocks) {
|
||||
SimpleLocation sl = new SimpleLocation(l);
|
||||
gatesByLocation.remove(sl);
|
||||
|
||||
SimpleLocation headLocation = new SimpleLocation(l, true);
|
||||
gatesByLocation.remove(headLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeGateByFrameLocation(final Set<Block> gateFrameBlocks) {
|
||||
if (gateFrameBlocks != null) {
|
||||
|
||||
for (Block block : gateFrameBlocks) {
|
||||
SimpleLocation sl = new SimpleLocation(block.getLocation());
|
||||
gatesByFrameLocation.remove(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addGateByLocations(final Gate g) {
|
||||
for (Location l : g.getGateBlockLocations()) {
|
||||
SimpleLocation sl = new SimpleLocation(l);
|
||||
gatesByLocation.put(sl, g);
|
||||
|
||||
SimpleLocation headLocation = new SimpleLocation(l, true);
|
||||
gatesByLocation.put(headLocation, g);
|
||||
}
|
||||
}
|
||||
|
||||
private void addGateByFrameLocations(final Gate g) {
|
||||
for (Block block : g.getGateFrameBlocks()) {
|
||||
SimpleLocation sl = new SimpleLocation(block.getLocation());
|
||||
gatesByFrameLocation.put(sl, g);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeGateFromChunk(final Gate g, final Location l) {
|
||||
if (l != null) {
|
||||
|
||||
Chunk c = l.getChunk();
|
||||
int x = c.getX();
|
||||
int z = c.getZ();
|
||||
|
||||
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
|
||||
|
||||
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
|
||||
|
||||
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
|
||||
Set<Gate> gatesInChunk = gatesByChunk.get(sc);
|
||||
|
||||
if (gatesInChunk != null) {
|
||||
gatesInChunk.remove(g);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addGateByChunk(final Gate g) {
|
||||
Location gateLocation = g.getLocation();
|
||||
|
||||
if (gateLocation != null) {
|
||||
|
||||
Chunk c = g.getLocation().getChunk();
|
||||
int x = c.getX();
|
||||
int z = c.getZ();
|
||||
|
||||
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
|
||||
|
||||
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
|
||||
|
||||
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
|
||||
|
||||
Set<Gate> gatesForC = gatesByChunk.get(sc);
|
||||
|
||||
if (gatesForC == null) {
|
||||
gatesForC = new HashSet<>(); // NOTE: not optimizing size here
|
||||
gatesByChunk.put(sc, gatesForC);
|
||||
}
|
||||
|
||||
gatesForC.add(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void storeInvalidGate(Map<String, Object> map) {
|
||||
File invalidGatesFile = new File(Plugin.getPlugin().getDataFolder(), "invalid_gates.yml");
|
||||
Boolean invalidGatesFileExists = invalidGatesFile.exists();
|
||||
|
||||
try {
|
||||
FileWriter fileWriter = new FileWriter(invalidGatesFile, true);
|
||||
|
||||
if (!invalidGatesFileExists) {
|
||||
fileWriter.write("gates:\n");
|
||||
}
|
||||
|
||||
fileWriter.write("- ==: ");
|
||||
fileWriter.write(map.get("==").toString() + "\n");
|
||||
map.remove("==");
|
||||
|
||||
fileWriter.write("\topen: false\n");
|
||||
map.remove("open");
|
||||
|
||||
fileWriter.write("\tgateBlocks: []\n");
|
||||
map.remove("gateBlocks");
|
||||
|
||||
|
||||
for (String key : map.keySet()) {
|
||||
Object value = map.get(key);
|
||||
|
||||
fileWriter.write("\t" + key + ": ");
|
||||
|
||||
if (value instanceof Map) {
|
||||
fileWriter.write("\n");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> valueMap = (Map<String, Object>) value;
|
||||
|
||||
for (String k : valueMap.keySet()) {
|
||||
Object v = valueMap.get(k);
|
||||
|
||||
fileWriter.write("\t\t" + k + ": " + v.toString() + "\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
fileWriter.write(value.toString() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
fileWriter.close();
|
||||
} catch (IOException e) {
|
||||
Plugin.log("ERROR: Could not save invalid gates to disk. Reason: \n" + Arrays.toString(e.getStackTrace()));
|
||||
}
|
||||
}
|
||||
|
||||
public void handleGateIdChange(final Gate g, final String oldId) {
|
||||
this.removeGateById(oldId);
|
||||
this.addGateWithId(g);
|
||||
}
|
||||
|
||||
public void handleGateLocationChange(final Gate g,
|
||||
final Location oldLocation,
|
||||
final Set<Location> oldGateBlockLocations,
|
||||
final Set<Block> oldGateFrameBlocks) {
|
||||
this.removeGateFromChunk(g, oldLocation);
|
||||
this.addGateByChunk(g);
|
||||
|
||||
this.removeGateByLocation(oldGateBlockLocations);
|
||||
this.addGateByLocations(g);
|
||||
|
||||
this.removeGateByFrameLocation(oldGateFrameBlocks);
|
||||
this.addGateByFrameLocations(g);
|
||||
}
|
||||
|
||||
public void handleGateExitChange(final Gate g, final Location oldExit) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public void handleNewGate(final Gate g) {
|
||||
this.gates.add(g);
|
||||
|
||||
this.addGateByChunk(g);
|
||||
this.addGateByLocations(g);
|
||||
this.addGateWithId(g);
|
||||
this.addGateByFrameLocations(g);
|
||||
}
|
||||
|
||||
public void handleDeletion(final Gate g) {
|
||||
this.gates.remove(g);
|
||||
|
||||
this.removeGateById(g.getId());
|
||||
this.removeGateFromChunk(g, g.getLocation());
|
||||
this.removeGateByLocation(g.getGateBlockLocations());
|
||||
this.removeGateByFrameLocation(g.getGateFrameBlocks());
|
||||
}
|
||||
|
||||
public boolean gateExists(final String id) {
|
||||
return gatesById.containsKey(id.toLowerCase());
|
||||
}
|
||||
|
||||
public List<Gate> allGates() {
|
||||
return gates;
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package de.craftinc.gates.controllers;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class PermissionController {
|
||||
public static final String permissionInfo = "craftincgates.info";
|
||||
public static final String permissionManage = "craftincgates.manage";
|
||||
public static final String permissionUse = "craftincgates.use";
|
||||
|
||||
private Permission permission;
|
||||
|
||||
public void setPermission(Permission permission) {
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender, Gate gate, String permission) {
|
||||
assert(sender != null);
|
||||
assert(permission != null);
|
||||
|
||||
if (gate == null) {
|
||||
return hasPermission(sender, permission);
|
||||
}
|
||||
|
||||
final Location location = gate.getLocation();
|
||||
final Location exit = gate.getExit();
|
||||
|
||||
boolean permAtLocation = location == null || hasPermission(sender, location.getWorld(), permission);
|
||||
boolean permAtExit = exit == null || hasPermission(sender, exit.getWorld(), permission);
|
||||
|
||||
return permAtLocation && permAtExit;
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender, String permission) {
|
||||
return hasPermission(sender, (World)null, permission);
|
||||
}
|
||||
|
||||
private boolean hasPermission(CommandSender sender, World world, String permission) {
|
||||
assert(sender != null);
|
||||
assert(permission != null);
|
||||
|
||||
if (this.permission == null) {
|
||||
// fallback - use the standard bukkit permission system
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
|
||||
if (!(sender instanceof OfflinePlayer)) {
|
||||
return this.permission.has(sender, permission);
|
||||
}
|
||||
|
||||
String worldName = world != null ? world.getName() : null;
|
||||
return this.permission.playerHas(worldName, (OfflinePlayer)sender, permission);
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package de.craftinc.gates.controllers;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.util.ConfigurationUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TeleportController {
|
||||
private TeleportMessageUtil messageUtil;
|
||||
private GatesManager gatesManager;
|
||||
private PermissionController permissionController;
|
||||
|
||||
public TeleportController(Plugin plugin) {
|
||||
this.gatesManager = plugin.getGatesManager();
|
||||
this.messageUtil = new TeleportMessageUtil(plugin.getConfig());
|
||||
this.permissionController = plugin.getPermissionController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try teleporting a player at given location.
|
||||
*/
|
||||
public void teleport(final Player player, Location toLocation) {
|
||||
final Gate gateAtLocation = gatesManager.getGateAtLocation(toLocation);
|
||||
|
||||
if ((gateAtLocation == null) || !gateAtLocation.isOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!permissionController.hasPermission(player, gateAtLocation, PermissionController.permissionUse)) {
|
||||
messageUtil.sendNoPermissionMessage(player);
|
||||
return;
|
||||
}
|
||||
|
||||
this.teleportPlayer(player, gateAtLocation);
|
||||
}
|
||||
|
||||
private void teleportPlayer(final Player player, final Gate gate) {
|
||||
final Entity vehicle = player.getVehicle();
|
||||
|
||||
if (vehicle != null && !gate.getAllowsVehicles()) {
|
||||
messageUtil.sendVehicleForbiddenMessage(player);
|
||||
Plugin.log("no vehicle transport");
|
||||
return;
|
||||
}
|
||||
|
||||
final Location destination = calculateDestination(player, gate);
|
||||
player.teleport(destination);
|
||||
|
||||
if (vehicle != null) {
|
||||
vehicle.teleport(destination, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
vehicle.setPassenger(player);
|
||||
}
|
||||
|
||||
messageUtil.sendTeleportMessage(player);
|
||||
}
|
||||
|
||||
private Location calculateDestination(Player player, Gate gate) {
|
||||
final Location exit = gate.getExit();
|
||||
final Location pLocation = player.getLocation();
|
||||
final Float newYaw = exit.getYaw() - gate.getLocation().getYaw() + pLocation.getYaw();
|
||||
|
||||
return new Location(exit.getWorld(),
|
||||
exit.getX(),
|
||||
exit.getY(),
|
||||
exit.getZ(),
|
||||
newYaw,
|
||||
pLocation.getPitch()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TeleportMessageUtil {
|
||||
private HashMap<String, Long> lastNoPermissionMessages = new HashMap<>();
|
||||
private FileConfiguration config;
|
||||
|
||||
TeleportMessageUtil(FileConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
void sendVehicleForbiddenMessage(Player player) {
|
||||
if (!config.getBoolean(ConfigurationUtil.confShowTeleportNoPermissionMessageKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String notAllowedMessage = config.getString(ConfigurationUtil.confGateTeleportVehicleNotAllowedMessageKey);
|
||||
player.sendMessage(ChatColor.DARK_AQUA + notAllowedMessage);
|
||||
}
|
||||
|
||||
void sendNoPermissionMessage(Player player) {
|
||||
if (!config.getBoolean(ConfigurationUtil.confShowTeleportNoPermissionMessageKey)) {
|
||||
return;
|
||||
}
|
||||
final String playerName = player.getPlayer().getName();
|
||||
|
||||
if (playerName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Long now = Calendar.getInstance().getTimeInMillis();
|
||||
|
||||
// do not display messages more often than once per second
|
||||
if (!this.lastNoPermissionMessages.containsKey(playerName)
|
||||
|| this.lastNoPermissionMessages.get(playerName) < now - 10000L) {
|
||||
|
||||
final String noPermissionString = config.getString(ConfigurationUtil.confGateTeleportNoPermissionMessageKey);
|
||||
player.sendMessage(ChatColor.RED + noPermissionString);
|
||||
this.lastNoPermissionMessages.put(playerName, now);
|
||||
}
|
||||
}
|
||||
|
||||
void sendTeleportMessage(Player player) {
|
||||
if (!config.getBoolean(ConfigurationUtil.confShowTeleportMessageKey)) {
|
||||
return;
|
||||
}
|
||||
final String teleportMessage = config.getString(ConfigurationUtil.confGateTeleportMessageKey);
|
||||
player.sendMessage(ChatColor.DARK_AQUA + teleportMessage);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
|
||||
public class BlockBreakListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gate gate = Plugin.getPlugin().getGatesManager().getGateAtFrameLocation(event.getBlock().getLocation());
|
||||
|
||||
if (gate != null && gate.getMaterial().getMaterial() != Material.AIR) {
|
||||
try {
|
||||
gate.setOpen(false);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
GateBlockChangeSender.updateGateBlocks(gate);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
|
||||
public class PlayerChangedWorldListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerChangeWorld(PlayerChangedWorldEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
GateBlockChangeSender.updateGateBlocks(p, p.getLocation());
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
public class PlayerJoinListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
GateBlockChangeSender.updateGateBlocks(p, p.getLocation());
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.controllers.TeleportController;
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public class PlayerMoveListener implements Listener {
|
||||
private TeleportController teleportController;
|
||||
|
||||
public PlayerMoveListener(Plugin plugin) {
|
||||
this.teleportController = new TeleportController(plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getFrom().getChunk() != event.getTo().getChunk()) {
|
||||
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getTo());
|
||||
}
|
||||
|
||||
teleportController.teleport(event.getPlayer(), event.getTo());
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
|
||||
public class PlayerRespawnListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getRespawnLocation(), true);
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.util.GateBlockChangeSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
public class PlayerTeleportListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getTo(), true);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package de.craftinc.gates.listeners;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.controllers.TeleportController;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.vehicle.VehicleMoveEvent;
|
||||
|
||||
public class VehicleMoveListener implements Listener {
|
||||
private TeleportController teleportController;
|
||||
|
||||
public VehicleMoveListener(Plugin plugin) {
|
||||
this.teleportController = new TeleportController(plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onVehicleMove(VehicleMoveEvent event) {
|
||||
Entity passenger = event.getVehicle().getPassenger();
|
||||
|
||||
if (passenger instanceof Player) {
|
||||
teleportController.teleport((Player)passenger, event.getTo());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,298 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.models;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.util.ConfigurationUtil;
|
||||
import de.craftinc.gates.util.FloodUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class Gate implements ConfigurationSerializable {
|
||||
private Location location; /* saving both location and gateBlockLocations is redundant but makes it easy to allow players to reshape gates */
|
||||
private Set<Location> gateBlockLocations = new HashSet<>(); /* Locations of the blocks inside the gate */
|
||||
private Set<Block> gateFrameBlocks = new HashSet<>();
|
||||
private Location exit;
|
||||
private boolean isOpen = false;
|
||||
private boolean allowsVehicles = true;
|
||||
private String id;
|
||||
private GateMaterial material = new GateMaterial(Material.PORTAL);
|
||||
|
||||
/**
|
||||
* You should never create two gates with the same 'id'. Also see 'setId(String id)'.
|
||||
*
|
||||
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
|
||||
*/
|
||||
public Gate(final String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + " " + this.getId();
|
||||
}
|
||||
|
||||
public GateDirection getDirection() {
|
||||
if (gateBlockLocations.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
Block some = ((Location)gateBlockLocations.toArray()[0]).getBlock();
|
||||
boolean east = gateBlockLocations.contains(some.getRelative(BlockFace.EAST).getLocation());
|
||||
boolean west = gateBlockLocations.contains(some.getRelative(BlockFace.WEST).getLocation());
|
||||
|
||||
return east || west ? GateDirection.EastWest : GateDirection.NorthSouth;
|
||||
}
|
||||
}
|
||||
|
||||
public GateMaterial getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
public void setMaterial(GateMaterial material) throws Exception {
|
||||
this.material = material;
|
||||
validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This method might return a 'null' data.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param location Supplying 'null' is permitted.
|
||||
* @throws Exception Will throw an exception if the gate is open and an invalid (no gate frame) location is
|
||||
* supplied. Note that the supplied 'location' will be set even if an exception is thrown. Note that this
|
||||
* gate will be closed if an exception is thrown.
|
||||
*/
|
||||
public void setLocation(final Location location) throws Exception {
|
||||
this.location = location;
|
||||
|
||||
if (isOpen) {
|
||||
findPortalBlocks();
|
||||
validate();
|
||||
} else {
|
||||
this.gateBlockLocations = new HashSet<>();
|
||||
this.gateFrameBlocks = new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This method might return a 'null' value.
|
||||
*/
|
||||
public Location getExit() {
|
||||
return exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exit Supplying 'null' is permitted.
|
||||
* @throws Exception An exception will be thrown if 'null' data is supplied and this gate is open. Note that the
|
||||
* supplied 'exit' will be set even if an exception is thrown. Note that this gate will be closed if an
|
||||
* exception is thrown.
|
||||
*/
|
||||
public void setExit(final Location exit) throws Exception {
|
||||
this.exit = exit;
|
||||
validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This method will never return 'null'.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every gate should have an unique 'id'. You should therefore check if another gate with the same 'id' exists.
|
||||
* Note that this method will not check if another gate with the same 'id' exists!
|
||||
*
|
||||
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
|
||||
*/
|
||||
public void setId(final String id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("gate 'id' cannot be 'null'");
|
||||
}
|
||||
|
||||
this.id = id.toLowerCase();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public void setOpen(boolean isOpen) throws Exception {
|
||||
if (isOpen && !this.isOpen) {
|
||||
findPortalBlocks();
|
||||
}
|
||||
|
||||
this.isOpen = isOpen;
|
||||
validate();
|
||||
}
|
||||
|
||||
public void setAllowsVehicles(boolean allowsVehicles) {
|
||||
this.allowsVehicles = allowsVehicles;
|
||||
}
|
||||
|
||||
public boolean getAllowsVehicles() {
|
||||
return this.allowsVehicles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Will never return 'null' but might return an empty Set.
|
||||
*/
|
||||
public Set<Location> getGateBlockLocations() {
|
||||
return gateBlockLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Will never return 'null' but might return an empty Set.
|
||||
*/
|
||||
public Set<Block> getGateFrameBlocks() {
|
||||
return gateFrameBlocks;
|
||||
}
|
||||
|
||||
private void findPortalBlocks() {
|
||||
gateBlockLocations = new HashSet<>();
|
||||
Set<Block> gateBlocks = FloodUtil.getGatePortalBlocks(location.getBlock());
|
||||
|
||||
if (gateBlocks != null) {
|
||||
for (Block b : gateBlocks) {
|
||||
gateBlockLocations.add(b.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
gateFrameBlocks = FloodUtil.getFrame(gateBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if values attributes do add up; will close gate on wrong values.
|
||||
*/
|
||||
public void validate() throws Exception {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (location == null) {
|
||||
isOpen = false;
|
||||
this.gateBlockLocations = new HashSet<>();
|
||||
this.gateFrameBlocks = new HashSet<>();
|
||||
|
||||
throw new Exception("Gate got closed. It has no location.");
|
||||
}
|
||||
|
||||
if (exit == null) {
|
||||
isOpen = false;
|
||||
this.gateBlockLocations = new HashSet<>();
|
||||
this.gateFrameBlocks = new HashSet<>();
|
||||
|
||||
throw new Exception("Gate got closed. It has no exit.");
|
||||
}
|
||||
|
||||
if (gateBlockLocations.size() == 0) {
|
||||
isOpen = false;
|
||||
this.gateBlockLocations = new HashSet<>();
|
||||
this.gateFrameBlocks = new HashSet<>();
|
||||
|
||||
throw new Exception("Gate got closed. The frame is missing or broken. (no gate blocks)");
|
||||
}
|
||||
|
||||
validateFrame();
|
||||
}
|
||||
|
||||
private void validateFrame() throws Exception {
|
||||
boolean isAir = material.getMaterial() == Material.AIR;
|
||||
boolean ignore = !Plugin.getPlugin().getConfig().getBoolean(ConfigurationUtil.confCheckForBrokenGateFramesKey);
|
||||
|
||||
if (isAir || ignore) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Block b : gateFrameBlocks) {
|
||||
|
||||
if (b.getType() == Material.AIR) {
|
||||
isOpen = false;
|
||||
this.gateBlockLocations = new HashSet<>();
|
||||
this.gateFrameBlocks = new HashSet<>();
|
||||
|
||||
throw new Exception("Gate got closed. The frame is missing or broken. (missing frame block(s))");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERFACE: ConfigurationSerializable
|
||||
*/
|
||||
static private String idKey = "id";
|
||||
static private String locationKey = "location";
|
||||
static private String gateBlocksKey = "gateBlocks";
|
||||
static private String exitKey = "exit";
|
||||
static private String materialKey = "material";
|
||||
static private String isOpenKey = "open";
|
||||
static private String allowsVehiclesKey = "allowsVehiclesKey";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Gate(Map<String, Object> map) {
|
||||
try {
|
||||
id = map.get(idKey).toString().toLowerCase();
|
||||
location = (Location) map.get(locationKey);
|
||||
exit = (Location) map.get(exitKey);
|
||||
material = new GateMaterial((String)map.get(materialKey));
|
||||
isOpen = (Boolean) map.get(isOpenKey);
|
||||
allowsVehicles = (Boolean) map.get(allowsVehiclesKey);
|
||||
gateBlockLocations = (Set<Location>) map.get(gateBlocksKey);
|
||||
|
||||
gateFrameBlocks = FloodUtil.getFrameWithLocations(gateBlockLocations);
|
||||
} catch (Exception e) {
|
||||
Plugin.log("ERROR: Failed to load gate '" + id + "'! (" + e.getMessage() + ")");
|
||||
Plugin.log("NOTE: This gate will be removed from 'gates.yml' and added to 'invalid_gates.yml'!");
|
||||
|
||||
Plugin.getPlugin().getGatesManager().storeInvalidGate(map);
|
||||
}
|
||||
|
||||
try {
|
||||
validate(); // make sure to not write invalid stuff to disk
|
||||
} catch (Exception e) {
|
||||
Plugin.log("The loaded gate " + this.getId() + " seems to be not valid: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> retVal = new HashMap<>();
|
||||
|
||||
retVal.put(idKey, id);
|
||||
retVal.put(isOpenKey, isOpen);
|
||||
retVal.put(allowsVehiclesKey, allowsVehicles);
|
||||
retVal.put(gateBlocksKey, gateBlockLocations);
|
||||
retVal.put(materialKey, material.toString());
|
||||
|
||||
if (exit != null) {
|
||||
retVal.put(exitKey, exit);
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
retVal.put(locationKey, location);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package de.craftinc.gates.models;
|
||||
|
||||
public enum GateDirection {
|
||||
EastWest,
|
||||
NorthSouth
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
package de.craftinc.gates.models;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
public class GateMaterial {
|
||||
private Material material;
|
||||
|
||||
GateMaterial(Material material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
public GateMaterial(String materialString) throws InvalidParameterException {
|
||||
Material material;
|
||||
|
||||
switch (materialString) {
|
||||
case "air":
|
||||
material = Material.AIR;
|
||||
break;
|
||||
case "sapling":
|
||||
material = Material.SAPLING;
|
||||
break;
|
||||
case "water":
|
||||
material = Material.STATIONARY_WATER;
|
||||
break;
|
||||
case "lava":
|
||||
material = Material.STATIONARY_LAVA;
|
||||
break;
|
||||
case "cobweb":
|
||||
material = Material.WEB;
|
||||
break;
|
||||
case "grass":
|
||||
material = Material.LONG_GRASS;
|
||||
break;
|
||||
case "dead bush":
|
||||
material = Material.DEAD_BUSH;
|
||||
break;
|
||||
case "dandelion":
|
||||
material = Material.YELLOW_FLOWER;
|
||||
break;
|
||||
case "poppy":
|
||||
material = Material.RED_ROSE;
|
||||
break;
|
||||
case "brown mushroom":
|
||||
material = Material.BROWN_MUSHROOM;
|
||||
break;
|
||||
case "red mushroom":
|
||||
material = Material.RED_MUSHROOM;
|
||||
break;
|
||||
case "torch":
|
||||
material = Material.TORCH;
|
||||
break;
|
||||
case "redstone torch (off)":
|
||||
material = Material.REDSTONE_TORCH_OFF;
|
||||
break;
|
||||
case "redstone torch (on)":
|
||||
material = Material.REDSTONE_TORCH_ON;
|
||||
break;
|
||||
case "fence":
|
||||
material = Material.FENCE;
|
||||
break;
|
||||
case "nether portal":
|
||||
material = Material.PORTAL;
|
||||
break;
|
||||
case "iron bars":
|
||||
material = Material.IRON_FENCE;
|
||||
break;
|
||||
case "glass pane":
|
||||
material = Material.THIN_GLASS;
|
||||
break;
|
||||
case "fence gate":
|
||||
material = Material.FENCE_GATE;
|
||||
break;
|
||||
case "nether brick fence":
|
||||
material = Material.NETHER_FENCE;
|
||||
break;
|
||||
case "nether wart":
|
||||
material = Material.NETHER_WARTS;
|
||||
break;
|
||||
case "end portal":
|
||||
material = Material.ENDER_PORTAL;
|
||||
break;
|
||||
case "cobblestone wall":
|
||||
material = Material.COBBLE_WALL;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidParameterException();
|
||||
}
|
||||
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (material) {
|
||||
case AIR:
|
||||
return "air";
|
||||
case SAPLING:
|
||||
return "sapling";
|
||||
case STATIONARY_WATER:
|
||||
return "water";
|
||||
case STATIONARY_LAVA:
|
||||
return "lava";
|
||||
case WEB:
|
||||
return "cobweb";
|
||||
case LONG_GRASS:
|
||||
return "grass";
|
||||
case DEAD_BUSH:
|
||||
return "dead bush";
|
||||
case YELLOW_FLOWER:
|
||||
return "dandelion";
|
||||
case RED_ROSE:
|
||||
return "poppy";
|
||||
case BROWN_MUSHROOM:
|
||||
return "brown mushroom";
|
||||
case RED_MUSHROOM:
|
||||
return "red mushroom";
|
||||
case TORCH:
|
||||
return "torch";
|
||||
case REDSTONE_TORCH_OFF:
|
||||
return "redstone torch (off)";
|
||||
case REDSTONE_TORCH_ON:
|
||||
return "redstone torch (on)";
|
||||
case FENCE:
|
||||
return "fence";
|
||||
case PORTAL:
|
||||
return "nether portal";
|
||||
case IRON_FENCE:
|
||||
return "iron bars";
|
||||
case THIN_GLASS:
|
||||
return "glass pane";
|
||||
case FENCE_GATE:
|
||||
return "fence gate";
|
||||
case NETHER_FENCE:
|
||||
return "nether brick fence";
|
||||
case NETHER_WARTS:
|
||||
return "nether wart";
|
||||
case ENDER_PORTAL:
|
||||
return "end portal";
|
||||
case COBBLE_WALL:
|
||||
return "cobblestone wall";
|
||||
default:
|
||||
return "nether portal";
|
||||
}
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
public byte getData(GateDirection direction) {
|
||||
switch (material) {
|
||||
case PORTAL:
|
||||
return direction == GateDirection.EastWest ? (byte)0b0 : (byte)0b10;
|
||||
case GRASS:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.models;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class SimpleChunk {
|
||||
private int x;
|
||||
private int z;
|
||||
private String world;
|
||||
|
||||
public SimpleChunk(Chunk c) {
|
||||
this.x = c.getX();
|
||||
this.z = c.getZ();
|
||||
this.world = c.getWorld().getName();
|
||||
}
|
||||
|
||||
|
||||
public SimpleChunk(int x, int z, World w) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.world = w.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof SimpleChunk) {
|
||||
SimpleChunk otherLocation = (SimpleChunk) o;
|
||||
|
||||
if (otherLocation.x == this.x
|
||||
&& otherLocation.z == this.z
|
||||
&& otherLocation.world.equals(this.world)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 11;
|
||||
hash = 29 * hash + x;
|
||||
hash = 37 * hash + z;
|
||||
hash = 29 * hash + world.hashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().toString() + " (x=" + this.x + " z=" + this.z + " world='" + this.world + "')";
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.models;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class SimpleLocation {
|
||||
private String world;
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
|
||||
public SimpleLocation(Location l) {
|
||||
this.world = l.getWorld().getName();
|
||||
|
||||
// Using Block coordinates makes it possible to compare block locations with player locations.
|
||||
// There might be an offset of 1 otherwise.
|
||||
this.x = l.getBlockX();
|
||||
this.y = l.getBlockY();
|
||||
this.z = l.getBlockZ();
|
||||
}
|
||||
|
||||
public SimpleLocation(Location l, boolean isHeadPosition) {
|
||||
this.world = l.getWorld().getName();
|
||||
|
||||
// Using Block coordinates makes it possible to compare block locations with player locations.
|
||||
// There might be an offset of 1 otherwise.
|
||||
this.x = l.getBlockX();
|
||||
this.y = l.getBlockY();
|
||||
this.z = l.getBlockZ();
|
||||
|
||||
if (isHeadPosition) {
|
||||
this.y--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " x: " + x + " y: " + y + " z: " + z + " world: " + world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o instanceof SimpleLocation) {
|
||||
SimpleLocation otherLocation = (SimpleLocation) o;
|
||||
|
||||
if (otherLocation.x == this.x
|
||||
&& otherLocation.y == this.y
|
||||
&& otherLocation.z == this.z
|
||||
&& otherLocation.world.equals(this.world)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 13;
|
||||
hash = 37 * hash + x;
|
||||
hash = 31 * hash + y;
|
||||
hash = 37 * hash + z;
|
||||
hash = 31 * hash + world.hashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.persistence;
|
||||
|
||||
import de.craftinc.gates.models.Gate;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class MigrationUtil {
|
||||
|
||||
public static boolean performMigration(int storageVersion, int currentVersion, List<Gate> gates) {
|
||||
if (storageVersion != currentVersion) {
|
||||
Plugin.log(Level.SEVERE, "Supplied storage version is currently not supported!" +
|
||||
"Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.util;
|
||||
|
||||
public class ConfigurationUtil {
|
||||
public static final String confMaxGateBlocksKey = "maxGateBlocks";
|
||||
public static final String confPlayerGateBlockUpdateRadiusKey = "playerGateBlockUpdateRadius";
|
||||
public static final String confCheckForBrokenGateFramesKey = "checkForBrokenGateFrames";
|
||||
public static final String confGateTeleportMessageKey = "gateTeleportMessage";
|
||||
public static final String confGateTeleportVehicleNotAllowedMessageKey = "gateTeleportVehicleNotAllowedMessage";
|
||||
public static final String confShowTeleportMessageKey = "showTeleportMessage";
|
||||
public static final String confGateTeleportNoPermissionMessageKey = "gateTeleportNoPermissionMessage";
|
||||
public static final String confShowTeleportNoPermissionMessageKey = "showTeleportNoPermissionMessage";
|
||||
public static final String confSaveOnChangesKey = "saveOnChanges";
|
||||
public static final String confHighlightDurationKey = "highlightDuration";
|
||||
}
|
@ -1,197 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
|
||||
|
||||
public class FloodUtil {
|
||||
private static final Set<BlockFace> exp1 = new HashSet<>();
|
||||
private static final Set<BlockFace> exp2 = new HashSet<>();
|
||||
|
||||
static {
|
||||
exp1.add(BlockFace.UP);
|
||||
exp1.add(BlockFace.DOWN);
|
||||
exp1.add(BlockFace.EAST);
|
||||
exp1.add(BlockFace.WEST);
|
||||
|
||||
exp2.add(BlockFace.UP);
|
||||
exp2.add(BlockFace.DOWN);
|
||||
exp2.add(BlockFace.NORTH);
|
||||
exp2.add(BlockFace.SOUTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the all frame blocks of an gate.
|
||||
*
|
||||
* @param blocks All blocks inside the gate.
|
||||
* @return A Set containing all frame block. Will never return 'null'.
|
||||
*/
|
||||
public static Set<Block> getFrame(final Set<Block> blocks) {
|
||||
if (blocks == null || blocks.isEmpty()) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
// try to find gate's direction (north-south or east-west)
|
||||
Set<BlockFace> gateFrameSearchFaces = null;
|
||||
|
||||
for (Block b : blocks) {
|
||||
|
||||
if (blocks.contains(b.getRelative(BlockFace.EAST)) ||
|
||||
blocks.contains(b.getRelative(BlockFace.WEST))) {
|
||||
|
||||
gateFrameSearchFaces = exp1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (blocks.contains(b.getRelative(BlockFace.NORTH)) ||
|
||||
blocks.contains(b.getRelative(BlockFace.SOUTH))) {
|
||||
|
||||
gateFrameSearchFaces = exp2;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (gateFrameSearchFaces != null) {
|
||||
return _getFrame(blocks, gateFrameSearchFaces);
|
||||
} else { // no direction found (the gate might only consist of blocks one over another)
|
||||
|
||||
// Try one direction and check if the found blocks are not air.
|
||||
// If air is found (frame broken or wrong direction) return the other direction
|
||||
Set<Block> frameBlocks = _getFrame(blocks, exp1);
|
||||
|
||||
for (Block b : frameBlocks) {
|
||||
|
||||
if (b.getType() == Material.AIR) {
|
||||
return _getFrame(blocks, exp2);
|
||||
}
|
||||
}
|
||||
|
||||
return frameBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Set<Block> _getFrame(final Set<Block> blocks, final Set<BlockFace> searchDirections) {
|
||||
Set<Block> frameBlocks = new HashSet<>();
|
||||
|
||||
for (Block b : blocks) {
|
||||
|
||||
for (BlockFace bf : searchDirections) {
|
||||
Block bb = b.getRelative(bf);
|
||||
|
||||
if (!blocks.contains(bb)) {
|
||||
frameBlocks.add(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frameBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the all frame blocks of an gate.
|
||||
*
|
||||
* @param locations All locations inside the gate.
|
||||
* @return A Set containing all frame block. Will never return 'null'.
|
||||
*/
|
||||
public static Set<Block> getFrameWithLocations(final Set<Location> locations) {
|
||||
if (locations == null) {
|
||||
throw new IllegalArgumentException("'locations' must not be 'null'");
|
||||
}
|
||||
|
||||
Set<Block> blocks = new HashSet<>();
|
||||
|
||||
for (Location l : locations) {
|
||||
blocks.add(l.getBlock());
|
||||
}
|
||||
|
||||
return getFrame(blocks);
|
||||
}
|
||||
|
||||
|
||||
// For the same frame and location this set of blocks is deterministic
|
||||
public static Set<Block> getGatePortalBlocks(final Block block) {
|
||||
if (block == null) {
|
||||
throw new IllegalArgumentException("'block' must not be 'null'");
|
||||
}
|
||||
|
||||
int frameBlockSearchLimit = Plugin.getPlugin().getConfig().getInt(ConfigurationUtil.confMaxGateBlocksKey);
|
||||
|
||||
Set<Block> blocks1 = getAirFloodBlocks(block, new HashSet<Block>(), exp1, frameBlockSearchLimit);
|
||||
Set<Block> blocks2 = getAirFloodBlocks(block, new HashSet<Block>(), exp2, frameBlockSearchLimit);
|
||||
|
||||
if (blocks1 == null && blocks2 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (blocks1 == null) {
|
||||
return blocks2;
|
||||
}
|
||||
|
||||
if (blocks2 == null) {
|
||||
return blocks1;
|
||||
}
|
||||
|
||||
if (blocks1.size() > blocks2.size()) {
|
||||
return blocks2;
|
||||
}
|
||||
|
||||
return blocks1;
|
||||
}
|
||||
|
||||
|
||||
private static Set<Block> getAirFloodBlocks(final Block startBlock,
|
||||
Set<Block> foundBlocks,
|
||||
final Set<BlockFace> expandFaces,
|
||||
int limit) {
|
||||
if (foundBlocks == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (foundBlocks.size() > limit) {
|
||||
Plugin.log(Level.ALL, "exceeding gate size limit.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (foundBlocks.contains(startBlock)) {
|
||||
return foundBlocks;
|
||||
}
|
||||
|
||||
if (startBlock.getType() == Material.AIR) {
|
||||
foundBlocks.add(startBlock);
|
||||
|
||||
for (BlockFace face : expandFaces) {
|
||||
Block potentialBlock = startBlock.getRelative(face);
|
||||
foundBlocks = getAirFloodBlocks(potentialBlock, foundBlocks, expandFaces, limit);
|
||||
}
|
||||
}
|
||||
|
||||
return foundBlocks;
|
||||
}
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.util;
|
||||
|
||||
import de.craftinc.gates.Plugin;
|
||||
import de.craftinc.gates.models.Gate;
|
||||
|
||||
import de.craftinc.gates.models.GateMaterial;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import static de.craftinc.gates.util.ConfigurationUtil.*;
|
||||
|
||||
public class GateBlockChangeSender {
|
||||
/**
|
||||
* Replaces gate frame blocks with glowstone for a short period of time.
|
||||
* Uses the data stored in 'highlightDuration' inside the config file
|
||||
* for determining when to de-highlight the frames.
|
||||
*
|
||||
* @param player The player for whom the frame should be highlighted.
|
||||
* Must not be null!
|
||||
*
|
||||
* @param gates The gates to highlighting
|
||||
*/
|
||||
public static void temporaryHighlightGatesFrames(final Player player, final Set<Gate> gates) {
|
||||
assert(player != null);
|
||||
assert(gates != null);
|
||||
|
||||
for (Gate g : gates) {
|
||||
Set<Block> frameBlocks = g.getGateFrameBlocks();
|
||||
|
||||
for (Block b : frameBlocks) {
|
||||
player.sendBlockChange(b.getLocation(), Material.GLOWSTONE, (byte) 0);
|
||||
}
|
||||
}
|
||||
scheduleDelighting(player, gates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends gate blocks to player at a given location. Will send the updates either immediately or
|
||||
* immediately and after a short delay.
|
||||
*
|
||||
* @param player A player to send block changes to. Must not be null!
|
||||
* @param location The location to look for gates nearby. Must not be null!
|
||||
* @param sendDelayed Set to 'true' if the block changes shall be send a second time after a one
|
||||
* second delay.
|
||||
*/
|
||||
public static void updateGateBlocks(final Player player, final Location location, boolean sendDelayed) {
|
||||
assert(player != null);
|
||||
assert(location != null);
|
||||
|
||||
Set<Gate> gatesNearby = Plugin.getPlugin().getGatesManager().getNearbyGates(location.getChunk());
|
||||
|
||||
if (gatesNearby == null) {
|
||||
return; // no gates nearby
|
||||
}
|
||||
|
||||
for (Gate g : gatesNearby) {
|
||||
if (!g.isOpen()) {
|
||||
continue;
|
||||
}
|
||||
sendGateBlockChanges(g, true, player);
|
||||
}
|
||||
|
||||
if (sendDelayed) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Plugin.getPlugin(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateGateBlocks(player, location, false);
|
||||
}
|
||||
}, 20L);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateGateBlocks(final Player player, final Location location) {
|
||||
updateGateBlocks(player, location, false);
|
||||
}
|
||||
|
||||
|
||||
public static void updateGateBlocks(final Gate gate) {
|
||||
updateGateBlocks(gate, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends block changes to players near a given gate.
|
||||
*
|
||||
* @param gate Must not be 'null'!
|
||||
* @param remove Set to true if all visible gate blocks shall be removed.
|
||||
*/
|
||||
public static void updateGateBlocks(final Gate gate, boolean remove) {
|
||||
assert(gate != null);
|
||||
|
||||
Location gateLocation = gate.getLocation();
|
||||
if (gate.getGateBlockLocations().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<Player> playersNearby = new ArrayList<>();
|
||||
int searchRadius = Plugin.getPlugin().getConfig().getInt(confPlayerGateBlockUpdateRadiusKey);
|
||||
|
||||
for (Player p : Plugin.getPlugin().getServer().getOnlinePlayers()) {
|
||||
if (p.getWorld() == gateLocation.getWorld() && p.getLocation().distance(gateLocation) < searchRadius) {
|
||||
playersNearby.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isVisible = gate.isOpen() && !remove;
|
||||
for (Player p : playersNearby) {
|
||||
sendGateBlockChanges(gate, isVisible, p);
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleDelighting(final Player player, final Set<Gate> gates) {
|
||||
Plugin plugin = Plugin.getPlugin();
|
||||
long highlightDuration = 20 * plugin.getConfig().getLong(confHighlightDurationKey);
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dehighlightGatesFrames(player, gates);
|
||||
}
|
||||
}, highlightDuration);
|
||||
}
|
||||
|
||||
private static void dehighlightGatesFrames(final Player player, final Set<Gate> gates) {
|
||||
for (Gate g : gates) {
|
||||
Set<Block> frameBlocks = g.getGateFrameBlocks();
|
||||
|
||||
for (Block b : frameBlocks) {
|
||||
player.sendBlockChange(b.getLocation(), b.getType(), (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendGateBlockChanges(final Gate gate, boolean isVisible, final Player p) {
|
||||
byte data;
|
||||
Material material;
|
||||
|
||||
if (isVisible) {
|
||||
GateMaterial gm = gate.getMaterial();
|
||||
data = gm.getData(gate.getDirection());
|
||||
material = gm.getMaterial();
|
||||
} else {
|
||||
data = 0b0;
|
||||
material = Material.AIR;
|
||||
}
|
||||
|
||||
for (Location l : gate.getGateBlockLocations()) {
|
||||
if (l.getBlock().getType() == Material.AIR) {
|
||||
p.sendBlockChange(l, material, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* Craft Inc. Gates
|
||||
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
|
||||
|
||||
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 3 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 (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.craftinc.gates.util;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TextUtil {
|
||||
|
||||
public static String titleSize(String str) {
|
||||
String center = ".[ " + ChatColor.YELLOW + str + ChatColor.GOLD + " ].";
|
||||
|
||||
if (center.length() >= 60) {
|
||||
return ChatColor.GOLD + center;
|
||||
} else {
|
||||
String line = ChatColor.GOLD + repeat("_", 60);
|
||||
|
||||
int pivot = line.length() / 2;
|
||||
int eatLeft = center.length() / 2;
|
||||
int eatRight = center.length() - eatLeft;
|
||||
|
||||
return line.substring(0, pivot - eatLeft) + center + line.substring(pivot + eatRight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String repeat(String s, int times) {
|
||||
if (times <= 0)
|
||||
return "";
|
||||
|
||||
return s + repeat(s, times - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins all elements of list into a single string, separating the original strings with glue.
|
||||
*/
|
||||
public static String implode(List<String> list, String glue) {
|
||||
if (list.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String ret = list.get(0);
|
||||
|
||||
for (int i = 1; i < list.size(); i++) {
|
||||
ret += glue + list.get(i);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
75
src/org/mcteam/ancientgates/Conf.java
Normal file
75
src/org/mcteam/ancientgates/Conf.java
Normal file
@ -0,0 +1,75 @@
|
||||
package org.mcteam.ancientgates;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.mcteam.ancientgates.util.DiscUtil;
|
||||
|
||||
|
||||
public class Conf {
|
||||
public static transient File file = new File(Plugin.instance.getDataFolder(), "conf.json");
|
||||
|
||||
// Colors
|
||||
public static ChatColor colorMember = ChatColor.GREEN;
|
||||
public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE;
|
||||
public static ChatColor colorNeutral = ChatColor.WHITE;
|
||||
public static ChatColor colorEnemy = ChatColor.RED;
|
||||
|
||||
public static ChatColor colorSystem = ChatColor.YELLOW;
|
||||
public static ChatColor colorChrome = ChatColor.GOLD;
|
||||
public static ChatColor colorCommand = ChatColor.AQUA;
|
||||
public static ChatColor colorParameter = ChatColor.DARK_AQUA;
|
||||
|
||||
private static double gateSearchRadius = 10.0;
|
||||
|
||||
static {
|
||||
|
||||
}
|
||||
|
||||
public static double getGateSearchRadius() {
|
||||
return gateSearchRadius;
|
||||
}
|
||||
|
||||
public static int getGateMaxArea() {
|
||||
return (int)gateSearchRadius * 7;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Persistance
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static boolean save() {
|
||||
//Factions.log("Saving config to disk.");
|
||||
|
||||
try {
|
||||
DiscUtil.write(file, Plugin.gson.toJson(new Conf()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Plugin.log("Failed to save the config to disk.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean load() {
|
||||
Plugin.log("Loading conf from disk");
|
||||
|
||||
if ( ! file.exists()) {
|
||||
Plugin.log("No conf to load from disk. Creating new file.");
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
Plugin.gson.fromJson(DiscUtil.read(file), Conf.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Plugin.log("Failed to load the config from disk.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
251
src/org/mcteam/ancientgates/Gate.java
Normal file
251
src/org/mcteam/ancientgates/Gate.java
Normal file
@ -0,0 +1,251 @@
|
||||
package org.mcteam.ancientgates;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import org.mcteam.ancientgates.gson.reflect.TypeToken;
|
||||
import org.mcteam.ancientgates.util.DiscUtil;
|
||||
import org.mcteam.ancientgates.util.FloodUtil;
|
||||
|
||||
|
||||
public class Gate
|
||||
{
|
||||
private static transient TreeMap<String, Gate> instances = new TreeMap<String, Gate>(String.CASE_INSENSITIVE_ORDER);
|
||||
private static transient File file = new File(Plugin.instance.getDataFolder(), "gates.json");
|
||||
|
||||
private transient String id;
|
||||
private Location from;
|
||||
private Location to;
|
||||
|
||||
private Integer[][] gateBlocks;
|
||||
|
||||
|
||||
public Gate()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Getters And Setters
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public void setFrom(Location from)
|
||||
{
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
|
||||
public Location getFrom()
|
||||
{
|
||||
return from;
|
||||
}
|
||||
|
||||
public void setTo(Location to)
|
||||
{
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
|
||||
public Location getTo()
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
public Integer[][] getGateBlocks()
|
||||
{
|
||||
return gateBlocks;
|
||||
}
|
||||
|
||||
|
||||
public void setGateBlocks(Set<Block> gateBlocks)
|
||||
{
|
||||
if (gateBlocks == null)
|
||||
return;
|
||||
|
||||
this.gateBlocks = new Integer[gateBlocks.size()][3];
|
||||
|
||||
int blockcount = 0;
|
||||
for (Block b : gateBlocks)
|
||||
{
|
||||
if (b != null)
|
||||
{
|
||||
this.gateBlocks[blockcount][0] = b.getX();
|
||||
this.gateBlocks[blockcount][1] = b.getY();
|
||||
this.gateBlocks[blockcount][2] = b.getZ();
|
||||
}
|
||||
blockcount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// The Open And Close Methods
|
||||
//----------------------------------------------//
|
||||
|
||||
public boolean open()
|
||||
{
|
||||
Set<Block> blocks = FloodUtil.getGateFrameBlocks(from.getBlock());
|
||||
|
||||
if (blocks == null)
|
||||
return false;
|
||||
|
||||
// Uncomment lines below to have the old Portal open functionality back.
|
||||
|
||||
// This is not to do an effect
|
||||
// It is to stop portal blocks from destroying themself as they cant rely on non created blocks :P
|
||||
for (Block block : blocks)
|
||||
block.setType(Material.GLOWSTONE);
|
||||
|
||||
for (Block block : blocks)
|
||||
block.setType(Material.PORTAL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void close()
|
||||
{
|
||||
if (from != null)
|
||||
{
|
||||
Set<Block> blocks = FloodUtil.getGateFrameBlocks(from.getBlock());
|
||||
|
||||
if (blocks != null)
|
||||
{
|
||||
for (Block block : blocks)
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// Persistance and entity management
|
||||
//----------------------------------------------//
|
||||
|
||||
public static Gate get(String id)
|
||||
{
|
||||
return instances.get(id);
|
||||
}
|
||||
|
||||
|
||||
public static boolean exists(String id)
|
||||
{
|
||||
return instances.containsKey(id);
|
||||
}
|
||||
|
||||
|
||||
public static Gate create(String id)
|
||||
{
|
||||
Gate gate = new Gate();
|
||||
gate.id = id;
|
||||
instances.put(gate.id, gate);
|
||||
Plugin.log("created new gate " + gate.id);
|
||||
//faction.save();
|
||||
return gate;
|
||||
}
|
||||
|
||||
|
||||
public static void rename(Gate gate, String newId)
|
||||
{
|
||||
delete(gate.id);
|
||||
|
||||
gate.setId(newId);
|
||||
instances.put(gate.id, gate);
|
||||
}
|
||||
|
||||
|
||||
public static void delete(String id)
|
||||
{
|
||||
// Remove the faction
|
||||
instances.remove(id);
|
||||
}
|
||||
|
||||
|
||||
public static boolean save()
|
||||
{
|
||||
try
|
||||
{
|
||||
DiscUtil.write(file, Plugin.gson.toJson(instances));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Plugin.log("Failed to save the gates to disk due to I/O exception.");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
Plugin.log("Failed to save the gates to disk due to NPE.");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static boolean load()
|
||||
{
|
||||
Plugin.log("Loading gates from disk");
|
||||
if ( ! file.exists()) {
|
||||
Plugin.log("No gates to load from disk. Creating new file.");
|
||||
save();
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Type type = new TypeToken<Map<String, Gate>>(){}.getType();
|
||||
Map<String, Gate> instancesFromFile = Plugin.gson.fromJson(DiscUtil.read(file), type);
|
||||
instances.clear();
|
||||
instances.putAll(instancesFromFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
fillIds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static Collection<Gate> getAll()
|
||||
{
|
||||
return instances.values();
|
||||
}
|
||||
|
||||
|
||||
public static void fillIds()
|
||||
{
|
||||
for(Entry<String, Gate> entry : instances.entrySet())
|
||||
entry.getValue().setId(entry.getKey());
|
||||
}
|
||||
}
|
71
src/org/mcteam/ancientgates/MyLocationTypeAdapter.java
Normal file
71
src/org/mcteam/ancientgates/MyLocationTypeAdapter.java
Normal file
@ -0,0 +1,71 @@
|
||||
package org.mcteam.ancientgates;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.mcteam.ancientgates.gson.JsonDeserializationContext;
|
||||
import org.mcteam.ancientgates.gson.JsonDeserializer;
|
||||
import org.mcteam.ancientgates.gson.JsonElement;
|
||||
import org.mcteam.ancientgates.gson.JsonObject;
|
||||
import org.mcteam.ancientgates.gson.JsonParseException;
|
||||
import org.mcteam.ancientgates.gson.JsonSerializationContext;
|
||||
import org.mcteam.ancientgates.gson.JsonSerializer;
|
||||
|
||||
public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSerializer<Location> {
|
||||
private static final String WORLD = "world";
|
||||
private static final String X = "x";
|
||||
private static final String Y = "y";
|
||||
private static final String Z = "z";
|
||||
private static final String YAW = "yaw";
|
||||
private static final String PITCH = "pitch";
|
||||
|
||||
@Override
|
||||
public Location deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
JsonObject obj = json.getAsJsonObject();
|
||||
|
||||
World world = this.getWorld(obj.get(WORLD).getAsString());
|
||||
double x = obj.get(X).getAsDouble();
|
||||
double y = obj.get(Y).getAsDouble();
|
||||
double z = obj.get(Z).getAsDouble();
|
||||
float yaw = obj.get(YAW).getAsFloat();
|
||||
float pitch = obj.get(PITCH).getAsFloat();
|
||||
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonObject obj = new JsonObject();
|
||||
|
||||
if (src == null)
|
||||
{
|
||||
Plugin.log("Passed location is null in MyLocationTypeAdapter.");
|
||||
return obj;
|
||||
}
|
||||
else if (src.getWorld() == null)
|
||||
{
|
||||
Plugin.log("Passed location's world is null in MyLocationTypeAdapter.");
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj.addProperty(WORLD, src.getWorld().getName());
|
||||
obj.addProperty(X, src.getX());
|
||||
obj.addProperty(Y, src.getY());
|
||||
obj.addProperty(Z, src.getZ());
|
||||
obj.addProperty(YAW, src.getYaw());
|
||||
obj.addProperty(PITCH, src.getPitch());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private World getWorld(String name) {
|
||||
World world = Plugin.instance.getServer().getWorld(name);
|
||||
if (world == null) {
|
||||
world = Plugin.instance.getServer().createWorld(new WorldCreator(name).environment(Environment.NORMAL));
|
||||
}
|
||||
return world;
|
||||
}
|
||||
}
|
140
src/org/mcteam/ancientgates/Plugin.java
Normal file
140
src/org/mcteam/ancientgates/Plugin.java
Normal file
@ -0,0 +1,140 @@
|
||||
package org.mcteam.ancientgates;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.mcteam.ancientgates.commands.*;
|
||||
import org.mcteam.ancientgates.gson.Gson;
|
||||
import org.mcteam.ancientgates.gson.GsonBuilder;
|
||||
|
||||
import org.mcteam.ancientgates.listeners.PluginBlockListener;
|
||||
import org.mcteam.ancientgates.listeners.PluginPlayerListener;
|
||||
|
||||
|
||||
public class Plugin extends JavaPlugin
|
||||
{
|
||||
public static Plugin instance;
|
||||
|
||||
public PluginPlayerListener playerListener = new PluginPlayerListener();
|
||||
public PluginBlockListener blockListener = new PluginBlockListener();
|
||||
|
||||
private String baseCommand;
|
||||
|
||||
public final static Gson gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
|
||||
.registerTypeAdapter(Location.class, new MyLocationTypeAdapter())
|
||||
.create();
|
||||
|
||||
// Commands
|
||||
public List<BaseCommand> commands = new ArrayList<BaseCommand>();
|
||||
|
||||
public Plugin()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
log("Disabled");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
// Add the commands
|
||||
commands.add(new CommandHelp());
|
||||
commands.add(new CommandCreate());
|
||||
commands.add(new CommandCreateSetFrom());
|
||||
commands.add(new CommandDelete());
|
||||
commands.add(new CommandSetFrom());
|
||||
commands.add(new CommandSetTo());
|
||||
commands.add(new CommandOpen());
|
||||
commands.add(new CommandRename());
|
||||
commands.add(new CommandClose());
|
||||
commands.add(new CommandList());
|
||||
commands.add(new CommandInfo());
|
||||
|
||||
// Ensure basefolder exists!
|
||||
this.getDataFolder().mkdirs();
|
||||
|
||||
// Load from disc
|
||||
Conf.load();
|
||||
Gate.load();
|
||||
|
||||
// Register events
|
||||
getServer().getPluginManager().registerEvents(this.playerListener, this);
|
||||
getServer().getPluginManager().registerEvents(this.blockListener, this);
|
||||
|
||||
log("Enabled");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Test rights
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static boolean hasPermManage(CommandSender sender) {
|
||||
return sender.isOp();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Commands
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String getBaseCommand() {
|
||||
if (this.baseCommand != null) {
|
||||
return this.baseCommand;
|
||||
}
|
||||
Map<String, Map<String, Object>> Commands = (Map<String, Map<String, Object>>) this.getDescription().getCommands();
|
||||
this.baseCommand = Commands.keySet().iterator().next();
|
||||
return this.baseCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
List<String> parameters = new ArrayList<String>(Arrays.asList(args));
|
||||
this.handleCommand(sender, parameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void handleCommand(CommandSender sender, List<String> parameters) {
|
||||
if (parameters.size() == 0) {
|
||||
this.commands.get(0).execute(sender, parameters);
|
||||
return;
|
||||
}
|
||||
|
||||
String commandName = parameters.get(0).toLowerCase();
|
||||
parameters.remove(0);
|
||||
|
||||
for (BaseCommand fcommand : this.commands) {
|
||||
if (fcommand.getAliases().contains(commandName)) {
|
||||
fcommand.execute(sender, parameters);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(Conf.colorSystem+"Unknown gate-command \""+commandName+"\". Try "+Conf.colorCommand+"/"+getBaseCommand()+" help");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Logging
|
||||
// -------------------------------------------- //
|
||||
public static void log(String msg) {
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public static void log(Level level, String msg) {
|
||||
Logger.getLogger("Minecraft").log(level, "["+instance.getDescription().getFullName()+"] "+msg);
|
||||
}
|
||||
|
||||
}
|
160
src/org/mcteam/ancientgates/commands/BaseCommand.java
Normal file
160
src/org/mcteam/ancientgates/commands/BaseCommand.java
Normal file
@ -0,0 +1,160 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
import org.mcteam.ancientgates.Plugin;
|
||||
import org.mcteam.ancientgates.Conf;
|
||||
import org.mcteam.ancientgates.util.TextUtil;
|
||||
|
||||
public class BaseCommand
|
||||
{
|
||||
public List<String> aliases;
|
||||
public List<String> requiredParameters;
|
||||
public List<String> optionalParameters;
|
||||
|
||||
public String helpDescription;
|
||||
|
||||
public CommandSender sender;
|
||||
public boolean senderMustBePlayer;
|
||||
public boolean hasGateParam;
|
||||
public Player player;
|
||||
public Gate gate;
|
||||
|
||||
public List<String> parameters;
|
||||
|
||||
|
||||
public BaseCommand()
|
||||
{
|
||||
aliases = new ArrayList<String>();
|
||||
requiredParameters = new ArrayList<String>();
|
||||
optionalParameters = new ArrayList<String>();
|
||||
|
||||
senderMustBePlayer = true;
|
||||
hasGateParam = true;
|
||||
|
||||
helpDescription = "no description";
|
||||
}
|
||||
|
||||
public List<String> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, List<String> parameters) {
|
||||
this.sender = sender;
|
||||
this.parameters = parameters;
|
||||
|
||||
if ( ! validateCall()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.senderMustBePlayer) {
|
||||
this.player = (Player)sender;
|
||||
}
|
||||
|
||||
perform();
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
|
||||
}
|
||||
|
||||
public void sendMessage(String message) {
|
||||
sender.sendMessage(Conf.colorSystem+message);
|
||||
}
|
||||
|
||||
public void sendMessage(List<String> messages) {
|
||||
for(String message : messages) {
|
||||
this.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateCall()
|
||||
{
|
||||
// validate player
|
||||
if ( this.senderMustBePlayer && ! (sender instanceof Player))
|
||||
{
|
||||
sendMessage("This command can only be used by ingame players.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate permission
|
||||
if( ! hasPermission(sender))
|
||||
{
|
||||
sendMessage("You lack the permissions to "+this.helpDescription.toLowerCase()+".");
|
||||
return false;
|
||||
}
|
||||
|
||||
// valide parameter count
|
||||
if (parameters.size() < requiredParameters.size())
|
||||
{
|
||||
sendMessage("Usage: "+this.getUseageTemplate(true));
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate gate parameter
|
||||
if (this.hasGateParam)
|
||||
{
|
||||
String id = parameters.get(0);
|
||||
|
||||
if ( ! Gate.exists(id))
|
||||
{
|
||||
sendMessage("There exists no gate with id "+id);
|
||||
return false;
|
||||
}
|
||||
gate = Gate.get(id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender) {
|
||||
return Plugin.hasPermManage(sender);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Help and usage description
|
||||
// -------------------------------------------- //
|
||||
public String getUseageTemplate(boolean withColor, boolean withDescription) {
|
||||
String ret = "";
|
||||
|
||||
if (withColor) {
|
||||
ret += Conf.colorCommand;
|
||||
}
|
||||
|
||||
ret += "/" + Plugin.instance.getBaseCommand()+ " " +TextUtil.implode(this.getAliases(), ",")+" ";
|
||||
|
||||
List<String> parts = new ArrayList<String>();
|
||||
|
||||
for (String requiredParameter : this.requiredParameters) {
|
||||
parts.add("["+requiredParameter+"]");
|
||||
}
|
||||
|
||||
for (String optionalParameter : this.optionalParameters) {
|
||||
parts.add("*["+optionalParameter+"]");
|
||||
}
|
||||
|
||||
if (withColor) {
|
||||
ret += Conf.colorParameter;
|
||||
}
|
||||
|
||||
ret += TextUtil.implode(parts, " ");
|
||||
|
||||
if (withDescription) {
|
||||
ret += " "+Conf.colorSystem + this.helpDescription;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String getUseageTemplate(boolean withColor) {
|
||||
return getUseageTemplate(withColor, false);
|
||||
}
|
||||
|
||||
public String getUseageTemplate() {
|
||||
return getUseageTemplate(true);
|
||||
}
|
||||
}
|
18
src/org/mcteam/ancientgates/commands/CommandClose.java
Normal file
18
src/org/mcteam/ancientgates/commands/CommandClose.java
Normal file
@ -0,0 +1,18 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
public class CommandClose extends BaseCommand {
|
||||
|
||||
public CommandClose() {
|
||||
aliases.add("close");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Close that gate";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
gate.close();
|
||||
sendMessage("The gate was closed.");
|
||||
}
|
||||
}
|
||||
|
32
src/org/mcteam/ancientgates/commands/CommandCreate.java
Normal file
32
src/org/mcteam/ancientgates/commands/CommandCreate.java
Normal file
@ -0,0 +1,32 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
|
||||
public class CommandCreate extends BaseCommand {
|
||||
public CommandCreate() {
|
||||
aliases.add("create");
|
||||
aliases.add("new");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
senderMustBePlayer = false;
|
||||
hasGateParam = false;
|
||||
|
||||
helpDescription = "Create a gate";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
String id = parameters.get(0);
|
||||
if (Gate.exists(id)) {
|
||||
sendMessage("There gate \"" + id + "\" already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
Gate.create(id);
|
||||
sendMessage("Gate with id \"" + id + "\" was created. Now you should:");
|
||||
sendMessage(new CommandSetFrom().getUseageTemplate(true, true));
|
||||
|
||||
Gate.save();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.mcteam.ancientgates.Conf;
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
import org.mcteam.ancientgates.util.FloodUtil;
|
||||
|
||||
public class CommandCreateSetFrom extends BaseCommand
|
||||
{
|
||||
public CommandCreateSetFrom()
|
||||
{
|
||||
aliases.add("createsetfrom");
|
||||
aliases.add("newsetfrom");
|
||||
aliases.add("csf");
|
||||
aliases.add("nsf");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
hasGateParam = false;
|
||||
|
||||
helpDescription = "Create a gate and set \"from\" to your location.";
|
||||
}
|
||||
|
||||
public void perform()
|
||||
{
|
||||
String id = parameters.get(0);
|
||||
|
||||
if (Gate.exists(id)) {
|
||||
sendMessage("There gate \"" + id + "\" already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
Gate.create(id);
|
||||
Gate.save();
|
||||
sendMessage("Gate with id \"" + id + "\" was created.");
|
||||
|
||||
gate = Gate.get(id);
|
||||
|
||||
// The player might stand in a halfblock or a sign or whatever
|
||||
// Therefore we load som extra locations and blocks
|
||||
Block playerBlock = player.getLocation().getBlock();
|
||||
Block upBlock = playerBlock.getRelative(BlockFace.UP);
|
||||
Location playerUpLocation = new Location(player.getLocation().getWorld(),
|
||||
player.getLocation().getX(),
|
||||
player.getLocation().getY() + 1,
|
||||
player.getLocation().getZ(),
|
||||
player.getLocation().getYaw(),
|
||||
player.getLocation().getPitch());
|
||||
|
||||
Set<Block> gateBlocks = FloodUtil.getGateFrameBlocks(player.getLocation().getBlock());
|
||||
|
||||
if (gateBlocks == null)
|
||||
{
|
||||
sendMessage("Could not set from! Your portal is too large.\nMax size is: " + Conf.getGateMaxArea() + " Blocks.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerBlock.getType() == Material.AIR)
|
||||
{
|
||||
gate.setFrom(player.getLocation());
|
||||
gate.setGateBlocks(gateBlocks);
|
||||
}
|
||||
else if (upBlock.getType() == Material.AIR)
|
||||
{
|
||||
gate.setFrom(playerUpLocation);
|
||||
gate.setGateBlocks(gateBlocks);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendMessage("Could not set from! There is not enough room for a gate to open here");
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage("From location for gate \""+gate.getId()+"\" is now where you stand.");
|
||||
sendMessage("Your gate includes " + gateBlocks.size() + " Blocks.");
|
||||
}
|
||||
}
|
25
src/org/mcteam/ancientgates/commands/CommandDelete.java
Normal file
25
src/org/mcteam/ancientgates/commands/CommandDelete.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
|
||||
public class CommandDelete extends BaseCommand {
|
||||
public CommandDelete() {
|
||||
aliases.add("delete");
|
||||
aliases.add("del");
|
||||
aliases.add("remove");
|
||||
aliases.add("rm");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
senderMustBePlayer = false;
|
||||
helpDescription = "Delete a gate";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
gate.close();
|
||||
sendMessage("Gate with id \"" + gate.getId() + "\" was deleted.");
|
||||
Gate.delete(gate.getId());
|
||||
Gate.save();
|
||||
}
|
||||
}
|
||||
|
83
src/org/mcteam/ancientgates/commands/CommandHelp.java
Normal file
83
src/org/mcteam/ancientgates/commands/CommandHelp.java
Normal file
@ -0,0 +1,83 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.mcteam.ancientgates.util.TextUtil;
|
||||
|
||||
public class CommandHelp extends BaseCommand {
|
||||
|
||||
public CommandHelp() {
|
||||
aliases.add("help");
|
||||
aliases.add("h");
|
||||
aliases.add("?");
|
||||
|
||||
optionalParameters.add("page");
|
||||
hasGateParam = false;
|
||||
|
||||
helpDescription = "Display a help page";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(CommandSender sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void perform()
|
||||
{
|
||||
int page = 1;
|
||||
|
||||
if (parameters.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
page = Integer.parseInt(parameters.get(0));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
// wasn't an integer
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(TextUtil.titleize("AncientGates Help ("+page+"/"+helpPages.size()+")"));
|
||||
|
||||
page -= 1;
|
||||
if (page < 0 || page >= helpPages.size())
|
||||
{
|
||||
sendMessage("This page does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage(helpPages.get(page));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// Build the help pages
|
||||
//----------------------------------------------//
|
||||
|
||||
public static ArrayList<ArrayList<String>> helpPages;
|
||||
|
||||
static
|
||||
{
|
||||
helpPages = new ArrayList<ArrayList<String>>();
|
||||
ArrayList<String> pageLines;
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add( new CommandHelp().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandCreate().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandCreateSetFrom().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandDelete().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandSetFrom().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandSetTo().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandOpen().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandRename().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandClose().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandList().getUseageTemplate(true, true) );
|
||||
pageLines.add( new CommandInfo().getUseageTemplate(true, true) );
|
||||
helpPages.add(pageLines);
|
||||
}
|
||||
|
||||
}
|
||||
|
34
src/org/mcteam/ancientgates/commands/CommandInfo.java
Normal file
34
src/org/mcteam/ancientgates/commands/CommandInfo.java
Normal file
@ -0,0 +1,34 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
|
||||
public class CommandInfo extends BaseCommand
|
||||
{
|
||||
public CommandInfo()
|
||||
{
|
||||
aliases.add("info");
|
||||
aliases.add("details");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Prints information about a gate";
|
||||
}
|
||||
|
||||
|
||||
public void perform()
|
||||
{
|
||||
sendMessage(ChatColor.LIGHT_PURPLE + "Information about " + ChatColor.WHITE + gate.getId() + ChatColor.LIGHT_PURPLE + ":");
|
||||
|
||||
if (gate.getFrom() != null)
|
||||
sendMessage(ChatColor.GREEN + "'from' location: " + ChatColor.YELLOW + "( " + gate.getFrom().getBlockX() + " | " + gate.getFrom().getBlockY() + " | " + gate.getFrom().getBlockZ() + " )");
|
||||
else
|
||||
sendMessage(ChatColor.GREEN + "this gate has no 'from' location");
|
||||
|
||||
if (gate.getTo() != null)
|
||||
sendMessage(ChatColor.GREEN + "'to' location: " + ChatColor.YELLOW + "( " + gate.getTo().getBlockX() + " | " + gate.getTo().getBlockY() + " | " + gate.getTo().getBlockZ() + " )");
|
||||
else
|
||||
sendMessage(ChatColor.GREEN + "this gate has no 'to' location");
|
||||
|
||||
}
|
||||
}
|
215
src/org/mcteam/ancientgates/commands/CommandList.java
Normal file
215
src/org/mcteam/ancientgates/commands/CommandList.java
Normal file
@ -0,0 +1,215 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.mcteam.ancientgates.Conf;
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
import org.mcteam.ancientgates.util.TextUtil;
|
||||
|
||||
public class CommandList extends BaseCommand
|
||||
{
|
||||
public CommandList()
|
||||
{
|
||||
aliases.add("list");
|
||||
aliases.add("ls");
|
||||
|
||||
optionalParameters.add("page");
|
||||
hasGateParam = false;
|
||||
|
||||
helpDescription = "Display a list of the gates";
|
||||
}
|
||||
|
||||
|
||||
protected String intToTitleString(int i)
|
||||
{
|
||||
if ( i < 26 )
|
||||
return Conf.colorMember + "" + (char)(i+65) + ":";
|
||||
else if ( i == 26 )
|
||||
return Conf.colorMember + "0 - 9:";
|
||||
else
|
||||
return Conf.colorMember + "!@#$:";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// pages start at 1
|
||||
// will return null if requested page not availible
|
||||
protected List<String> message(int page)
|
||||
{
|
||||
Collection<Gate> gates = Gate.getAll();
|
||||
|
||||
if (gates.size() == 0)
|
||||
return null;
|
||||
|
||||
/* sort all gates by there first character
|
||||
* put gates in corresponding Lists
|
||||
* list 0-25: a,b,c, ... ,z
|
||||
* list 26: 0-9
|
||||
* list 27: other
|
||||
*/
|
||||
List<List<String>> ids = new ArrayList<List<String>>();
|
||||
|
||||
for (int i=0; i<28; i++)
|
||||
ids.add(new ArrayList<String>());
|
||||
|
||||
for (Gate gate : gates)
|
||||
{
|
||||
String id = gate.getId();
|
||||
int first = id.charAt(0);
|
||||
|
||||
if (first > 96 && first < 123) // convert lower case chars
|
||||
first -= 97;
|
||||
else if (first > 64 && first < 91) // convert upper case chars
|
||||
first -= 65;
|
||||
else if (first > 47 && first < 58) // convert numbers
|
||||
first = 26;
|
||||
else // everything else
|
||||
first = 27;
|
||||
|
||||
ids.get(first).add(id);
|
||||
}
|
||||
|
||||
|
||||
/* calculating which gates will be displayed on which page.
|
||||
* this is a little bit fuzzy. but hopefully it will look
|
||||
* great. (tell me if there is a better way!)
|
||||
*/
|
||||
|
||||
// list<string>: a list from ids
|
||||
// Integer: the number of lines neccessary for displaying the corresponding list
|
||||
HashMap<List<String>, Integer> lines = new HashMap<List<String>, Integer>(27);
|
||||
|
||||
for (List<String> currentIds : ids)
|
||||
{
|
||||
if (currentIds.size() == 0)
|
||||
continue;
|
||||
|
||||
int characters = TextUtil.implode(currentIds, ", ").length();
|
||||
lines.put(currentIds, characters / 52 + 2);
|
||||
}
|
||||
|
||||
|
||||
int currentPage = 1;
|
||||
int currentStartingCharList = 0;
|
||||
boolean finishedCurrentIds = true;
|
||||
|
||||
List<String> pageMessages = new ArrayList<String>();
|
||||
|
||||
while (currentStartingCharList < ids.size())
|
||||
{
|
||||
int linesLeftOnCurrentPage = 9;
|
||||
|
||||
while (linesLeftOnCurrentPage > 1 && currentStartingCharList < ids.size())
|
||||
{
|
||||
List<String> currentIds = ids.get(currentStartingCharList);
|
||||
|
||||
if (currentIds.size() > 0)
|
||||
{
|
||||
// add header line
|
||||
if (currentPage == page)
|
||||
pageMessages.add(intToTitleString(currentStartingCharList));
|
||||
|
||||
//sort
|
||||
Collections.sort(currentIds);
|
||||
|
||||
// add ids
|
||||
if (lines.get(currentIds) <= linesLeftOnCurrentPage) // all ids fit on current page
|
||||
{
|
||||
linesLeftOnCurrentPage -= lines.get(currentIds);
|
||||
|
||||
|
||||
if (currentPage == page)
|
||||
{
|
||||
pageMessages.add(TextUtil.implode(currentIds, ", "));
|
||||
if (finishedCurrentIds == false)
|
||||
pageMessages.set(pageMessages.size() -2, pageMessages.get(pageMessages.size() -2) + " (more on previous page)");
|
||||
}
|
||||
|
||||
finishedCurrentIds = true;
|
||||
}
|
||||
else // NOT all ids fit on current page
|
||||
{
|
||||
int charsAvailible = (linesLeftOnCurrentPage - 1) * 52;
|
||||
int idsPos = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
charsAvailible -= currentIds.get(idsPos).length() + 2;
|
||||
|
||||
if (charsAvailible <= 0)
|
||||
break;
|
||||
|
||||
idsPos++;
|
||||
}
|
||||
|
||||
List<String> idsToPutOnCurrentPage = currentIds.subList(0, idsPos);
|
||||
currentIds.remove(idsToPutOnCurrentPage);
|
||||
|
||||
String stringToPutOnCurrentPage = TextUtil.implode(idsToPutOnCurrentPage, ", ");
|
||||
|
||||
if (currentPage == page)
|
||||
{
|
||||
pageMessages.add(stringToPutOnCurrentPage);
|
||||
pageMessages.set(pageMessages.size() -2, pageMessages.get(pageMessages.size() -2) + " (more on next page)");
|
||||
}
|
||||
|
||||
lines.put(currentIds, TextUtil.implode(currentIds, ", ").length() / 52 + 2);
|
||||
linesLeftOnCurrentPage -= stringToPutOnCurrentPage.length() / 52 + 2;
|
||||
|
||||
finishedCurrentIds = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (finishedCurrentIds)
|
||||
currentStartingCharList++;
|
||||
}
|
||||
|
||||
currentPage++;
|
||||
}
|
||||
|
||||
if (pageMessages.isEmpty())
|
||||
return null;
|
||||
else
|
||||
{
|
||||
ArrayList<String> retVal = new ArrayList<String>();
|
||||
retVal.add(ChatColor.LIGHT_PURPLE + "This is page " + ChatColor.WHITE + page + ChatColor.LIGHT_PURPLE + "/" + ChatColor.WHITE + --currentPage + ChatColor.LIGHT_PURPLE + ". There are " + gates.size() + " gates on this server: ");
|
||||
retVal.addAll(pageMessages);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void perform()
|
||||
{
|
||||
Collection<Gate> gates = Gate.getAll();
|
||||
|
||||
if (gates.size() == 0)
|
||||
sendMessage("There are no gates yet.");
|
||||
else
|
||||
{
|
||||
int page = 1;
|
||||
|
||||
try
|
||||
{
|
||||
page = new Integer(parameters.get(0));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
List<String> messages = message(page);
|
||||
|
||||
if (messages == null)
|
||||
sendMessage("The requested page is not availible");
|
||||
else
|
||||
sendMessage(messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
src/org/mcteam/ancientgates/commands/CommandOpen.java
Normal file
40
src/org/mcteam/ancientgates/commands/CommandOpen.java
Normal file
@ -0,0 +1,40 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class CommandOpen extends BaseCommand {
|
||||
|
||||
public CommandOpen() {
|
||||
aliases.add("open");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Open that gate";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
if (gate.getFrom() == null) {
|
||||
sendMessage("You must set the from location first. To fix that:");
|
||||
sendMessage(new CommandSetFrom().getUseageTemplate(true, true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (gate.getTo() == null) {
|
||||
sendMessage("Sure, but note that this gate does not point anywhere :P");
|
||||
sendMessage("To fix that: " + new CommandSetTo().getUseageTemplate(true, true));
|
||||
}
|
||||
|
||||
if (gate.getFrom().getBlock().getType() != Material.AIR) {
|
||||
sendMessage("The gate could not open. The from location is not air.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gate.open()) {
|
||||
sendMessage("The gate was opened.");
|
||||
} else {
|
||||
sendMessage("Failed to open the gate. Have you built a frame?");
|
||||
sendMessage("More info here: " + new CommandHelp().getUseageTemplate(true, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
src/org/mcteam/ancientgates/commands/CommandRename.java
Normal file
40
src/org/mcteam/ancientgates/commands/CommandRename.java
Normal file
@ -0,0 +1,40 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
|
||||
|
||||
|
||||
public class CommandRename extends BaseCommand
|
||||
{
|
||||
public CommandRename()
|
||||
{
|
||||
aliases.add("rename");
|
||||
aliases.add("changename");
|
||||
aliases.add("cn");
|
||||
|
||||
hasGateParam = true;
|
||||
senderMustBePlayer = false;
|
||||
|
||||
requiredParameters.add("current name");
|
||||
requiredParameters.add("new name");
|
||||
|
||||
helpDescription = "Change the name of a gate";
|
||||
}
|
||||
|
||||
|
||||
public void perform()
|
||||
{
|
||||
String newId = parameters.get(1);
|
||||
String oldId = gate.getId();
|
||||
|
||||
if (Gate.exists(newId))
|
||||
{
|
||||
sendMessage("Cannot rename " + oldId + ". There is already a gate named " + newId + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
Gate.rename(gate, newId);
|
||||
|
||||
sendMessage("Gate " + oldId + " is now known as " + newId + ".");
|
||||
}
|
||||
}
|
61
src/org/mcteam/ancientgates/commands/CommandSetFrom.java
Normal file
61
src/org/mcteam/ancientgates/commands/CommandSetFrom.java
Normal file
@ -0,0 +1,61 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import java.util.Set;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.mcteam.ancientgates.Conf;
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
import org.mcteam.ancientgates.util.FloodUtil;
|
||||
|
||||
public class CommandSetFrom extends BaseCommand {
|
||||
|
||||
public CommandSetFrom() {
|
||||
aliases.add("setfrom");
|
||||
aliases.add("sf");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Set \"from\" to your location.";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
// The player might stand in a halfblock or a sign or whatever
|
||||
// Therefore we load som extra locations and blocks
|
||||
Block playerBlock = player.getLocation().getBlock();
|
||||
Block upBlock = playerBlock.getRelative(BlockFace.UP);
|
||||
Location playerUpLocation = new Location(player.getLocation().getWorld(),
|
||||
player.getLocation().getX(),
|
||||
player.getLocation().getY() + 1,
|
||||
player.getLocation().getZ(),
|
||||
player.getLocation().getYaw(),
|
||||
player.getLocation().getPitch());
|
||||
|
||||
Set<Block> gateBlocks = FloodUtil.getGateFrameBlocks(player.getLocation().getBlock());
|
||||
if (gateBlocks == null) {
|
||||
sendMessage("There is no portal here, or your portal is too large.\nMax size is: " + Conf.getGateMaxArea() + " Blocks.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerBlock.getType() == Material.AIR) {
|
||||
gate.setFrom(player.getLocation());
|
||||
gate.setGateBlocks(gateBlocks);
|
||||
} else if (upBlock.getType() == Material.AIR) {
|
||||
gate.setFrom(playerUpLocation);
|
||||
gate.setGateBlocks(gateBlocks);
|
||||
} else {
|
||||
sendMessage("There is not enough room for a gate to open here");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sendMessage("From location for gate \""+gate.getId()+"\" is now where you stand.");
|
||||
sendMessage("Your gate includes " + gateBlocks.size() + " Blocks.");
|
||||
|
||||
Gate.save();
|
||||
}
|
||||
|
||||
}
|
||||
|
23
src/org/mcteam/ancientgates/commands/CommandSetTo.java
Normal file
23
src/org/mcteam/ancientgates/commands/CommandSetTo.java
Normal file
@ -0,0 +1,23 @@
|
||||
package org.mcteam.ancientgates.commands;
|
||||
|
||||
import org.mcteam.ancientgates.Gate;
|
||||
|
||||
public class CommandSetTo extends BaseCommand {
|
||||
|
||||
public CommandSetTo() {
|
||||
aliases.add("setto");
|
||||
|
||||
requiredParameters.add("id");
|
||||
|
||||
helpDescription = "Set \"to\" to your location.";
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
gate.setTo(player.getLocation());
|
||||
sendMessage("To location for gate \""+gate.getId()+"\" is now where you stand.");
|
||||
|
||||
Gate.save();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
|
||||
/**
|
||||
* Strategy for excluding anonymous and local classes.
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return isAnonymousOrLocal(f.getDeclaredClass());
|
||||
}
|
||||
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return isAnonymousOrLocal(clazz);
|
||||
}
|
||||
|
||||
private boolean isAnonymousOrLocal(Class<?> clazz) {
|
||||
return !Enum.class.isAssignableFrom(clazz)
|
||||
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
|
||||
}
|
||||
}
|
61
src/org/mcteam/ancientgates/gson/Cache.java
Normal file
61
src/org/mcteam/ancientgates/gson/Cache.java
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* Defines generic cache interface.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
interface Cache<K, V> {
|
||||
|
||||
/**
|
||||
* Adds the new value object into the cache for the given key. If the key already
|
||||
* exists, then this method will override the value for the key.
|
||||
*
|
||||
* @param key the key identifier for the {@code value} object
|
||||
* @param value the value object to store in the cache
|
||||
*/
|
||||
void addElement(K key, V value);
|
||||
|
||||
/**
|
||||
* Retrieve the cached value for the given {@code key}.
|
||||
*
|
||||
* @param key the key identifying the value
|
||||
* @return the cached value for the given {@code key}
|
||||
*/
|
||||
V getElement(K key);
|
||||
|
||||
/**
|
||||
* Removes the value from the cache for the given key.
|
||||
*
|
||||
* @param key the key identifying the value to remove
|
||||
* @return the value for the given {@code key}
|
||||
*/
|
||||
V removeElement(K key);
|
||||
|
||||
/**
|
||||
* Removes everything from this cache.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @return the number of objects in this cache
|
||||
*/
|
||||
int size();
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Converts the field name that uses camel-case define word separation into separate words that
|
||||
* are separated by the provided {@code separatorString}.
|
||||
*
|
||||
* <p>The following is an example:</p>
|
||||
* <pre>
|
||||
* class IntWrapper {
|
||||
* public int integerField = 0;
|
||||
* }
|
||||
*
|
||||
* CamelCaseSeparatorNamingPolicy policy = new CamelCaseSeparatorNamingPolicy("_");
|
||||
* String translatedFieldName =
|
||||
* policy.translateName(IntWrapper.class.getField("integerField"));
|
||||
*
|
||||
* assert("integer_Field".equals(translatedFieldName));
|
||||
* </pre>
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class CamelCaseSeparatorNamingPolicy extends RecursiveFieldNamingPolicy {
|
||||
private final String separatorString;
|
||||
|
||||
/**
|
||||
* Constructs a new CamelCaseSeparatorNamingPolicy object that will add the
|
||||
* {@code separatorString} between each of the words separated by camel case.
|
||||
*
|
||||
* @param separatorString the string value to place between words
|
||||
* @throws IllegalArgumentException thrown if the {@code separatorString} parameter
|
||||
* is null or empty.
|
||||
*/
|
||||
public CamelCaseSeparatorNamingPolicy(String separatorString) {
|
||||
Preconditions.checkNotNull(separatorString);
|
||||
Preconditions.checkArgument(!"".equals(separatorString));
|
||||
this.separatorString = separatorString;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String translateName(String target, Type fieldType,
|
||||
Collection<Annotation> annnotations) {
|
||||
StringBuilder translation = new StringBuilder();
|
||||
for (int i = 0; i < target.length(); i++) {
|
||||
char character = target.charAt(i);
|
||||
if (Character.isUpperCase(character) && translation.length() != 0) {
|
||||
translation.append(separatorString);
|
||||
}
|
||||
translation.append(character);
|
||||
}
|
||||
|
||||
return translation.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* Exception class to indicate a circular reference error.
|
||||
* This class is not part of the public API and hence is not public.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class CircularReferenceException extends RuntimeException {
|
||||
private static final long serialVersionUID = 7444343294106513081L;
|
||||
private final Object offendingNode;
|
||||
|
||||
CircularReferenceException(Object offendingNode) {
|
||||
super("circular reference error");
|
||||
this.offendingNode = offendingNode;
|
||||
}
|
||||
|
||||
public IllegalStateException createDetailedException(FieldAttributes offendingField) {
|
||||
StringBuilder msg = new StringBuilder(getMessage());
|
||||
if (offendingField != null) {
|
||||
msg.append("\n ").append("Offending field: ").append(offendingField.getName() + "\n");
|
||||
}
|
||||
if (offendingNode != null) {
|
||||
msg.append("\n ").append("Offending object: ").append(offendingNode);
|
||||
}
|
||||
return new IllegalStateException(msg.toString(), this);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Performs numerous field naming translations wrapped up as one object.
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
abstract class CompositionFieldNamingPolicy extends RecursiveFieldNamingPolicy {
|
||||
|
||||
private final RecursiveFieldNamingPolicy[] fieldPolicies;
|
||||
|
||||
public CompositionFieldNamingPolicy(RecursiveFieldNamingPolicy... fieldNamingPolicies) {
|
||||
if (fieldNamingPolicies == null) {
|
||||
throw new NullPointerException("naming policies can not be null.");
|
||||
}
|
||||
this.fieldPolicies = fieldNamingPolicies;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
|
||||
for (RecursiveFieldNamingPolicy policy : fieldPolicies) {
|
||||
target = policy.translateName(target, fieldType, annotations);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
893
src/org/mcteam/ancientgates/gson/DefaultTypeAdapters.java
Normal file
893
src/org/mcteam/ancientgates/gson/DefaultTypeAdapters.java
Normal file
@ -0,0 +1,893 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* List of all the default type adapters ({@link JsonSerializer}s, {@link JsonDeserializer}s,
|
||||
* and {@link InstanceCreator}s.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class DefaultTypeAdapters {
|
||||
|
||||
private static final DefaultDateTypeAdapter DATE_TYPE_ADAPTER = new DefaultDateTypeAdapter();
|
||||
private static final DefaultJavaSqlDateTypeAdapter JAVA_SQL_DATE_TYPE_ADAPTER =
|
||||
new DefaultJavaSqlDateTypeAdapter();
|
||||
private static final DefaultTimeTypeAdapter TIME_TYPE_ADAPTER =
|
||||
new DefaultTimeTypeAdapter();
|
||||
private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER =
|
||||
new DefaultTimestampDeserializer();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
|
||||
private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter();
|
||||
private static final UriTypeAdapter URI_TYPE_ADAPTER = new UriTypeAdapter();
|
||||
private static final UuidTypeAdapter UUUID_TYPE_ADAPTER = new UuidTypeAdapter();
|
||||
private static final LocaleTypeAdapter LOCALE_TYPE_ADAPTER = new LocaleTypeAdapter();
|
||||
private static final CollectionTypeAdapter COLLECTION_TYPE_ADAPTER = new CollectionTypeAdapter();
|
||||
private static final MapTypeAdapter MAP_TYPE_ADAPTER = new MapTypeAdapter();
|
||||
private static final BigDecimalTypeAdapter BIG_DECIMAL_TYPE_ADAPTER = new BigDecimalTypeAdapter();
|
||||
private static final BigIntegerTypeAdapter BIG_INTEGER_TYPE_ADAPTER = new BigIntegerTypeAdapter();
|
||||
|
||||
private static final BooleanTypeAdapter BOOLEAN_TYPE_ADAPTER = new BooleanTypeAdapter();
|
||||
private static final ByteTypeAdapter BYTE_TYPE_ADAPTER = new ByteTypeAdapter();
|
||||
private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter();
|
||||
private static final DoubleDeserializer DOUBLE_TYPE_ADAPTER = new DoubleDeserializer();
|
||||
private static final FloatDeserializer FLOAT_TYPE_ADAPTER = new FloatDeserializer();
|
||||
private static final IntegerTypeAdapter INTEGER_TYPE_ADAPTER = new IntegerTypeAdapter();
|
||||
private static final LongDeserializer LONG_DESERIALIZER = new LongDeserializer();
|
||||
private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
|
||||
private static final ShortTypeAdapter SHORT_TYPE_ADAPTER = new ShortTypeAdapter();
|
||||
private static final StringTypeAdapter STRING_TYPE_ADAPTER = new StringTypeAdapter();
|
||||
|
||||
private static final PropertiesCreator PROPERTIES_CREATOR = new PropertiesCreator();
|
||||
private static final TreeSetCreator TREE_SET_CREATOR = new TreeSetCreator();
|
||||
private static final HashSetCreator HASH_SET_CREATOR = new HashSetCreator();
|
||||
private static final GregorianCalendarTypeAdapter GREGORIAN_CALENDAR_TYPE_ADAPTER =
|
||||
new GregorianCalendarTypeAdapter();
|
||||
|
||||
// The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS
|
||||
// must be defined after the constants for the type adapters. Otherwise, the type adapter
|
||||
// constants will appear as nulls.
|
||||
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
|
||||
createDefaultSerializers();
|
||||
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
|
||||
createDefaultDeserializers();
|
||||
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
|
||||
createDefaultInstanceCreators();
|
||||
|
||||
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
||||
|
||||
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER);
|
||||
map.register(URL.class, URL_TYPE_ADAPTER);
|
||||
map.register(URI.class, URI_TYPE_ADAPTER);
|
||||
map.register(UUID.class, UUUID_TYPE_ADAPTER);
|
||||
map.register(Locale.class, LOCALE_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
|
||||
map.register(Date.class, DATE_TYPE_ADAPTER);
|
||||
map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER);
|
||||
map.register(Timestamp.class, DATE_TYPE_ADAPTER);
|
||||
map.register(Time.class, TIME_TYPE_ADAPTER);
|
||||
map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
|
||||
map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
|
||||
map.register(BigDecimal.class, BIG_DECIMAL_TYPE_ADAPTER);
|
||||
map.register(BigInteger.class, BIG_INTEGER_TYPE_ADAPTER);
|
||||
|
||||
// Add primitive serializers
|
||||
map.register(Boolean.class, BOOLEAN_TYPE_ADAPTER);
|
||||
map.register(boolean.class, BOOLEAN_TYPE_ADAPTER);
|
||||
map.register(Byte.class, BYTE_TYPE_ADAPTER);
|
||||
map.register(byte.class, BYTE_TYPE_ADAPTER);
|
||||
map.register(Character.class, CHARACTER_TYPE_ADAPTER);
|
||||
map.register(char.class, CHARACTER_TYPE_ADAPTER);
|
||||
map.register(Integer.class, INTEGER_TYPE_ADAPTER);
|
||||
map.register(int.class, INTEGER_TYPE_ADAPTER);
|
||||
map.register(Number.class, NUMBER_TYPE_ADAPTER);
|
||||
map.register(Short.class, SHORT_TYPE_ADAPTER);
|
||||
map.register(short.class, SHORT_TYPE_ADAPTER);
|
||||
map.register(String.class, STRING_TYPE_ADAPTER);
|
||||
|
||||
map.makeUnmodifiable();
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
|
||||
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER));
|
||||
map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER));
|
||||
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
|
||||
map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER));
|
||||
map.register(Locale.class, wrapDeserializer(LOCALE_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER));
|
||||
map.register(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER));
|
||||
map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER));
|
||||
map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER));
|
||||
map.register(Time.class, wrapDeserializer(TIME_TYPE_ADAPTER));
|
||||
map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
|
||||
map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER);
|
||||
map.register(BigDecimal.class, wrapDeserializer(BIG_DECIMAL_TYPE_ADAPTER));
|
||||
map.register(BigInteger.class, wrapDeserializer(BIG_INTEGER_TYPE_ADAPTER));
|
||||
|
||||
// Add primitive deserializers
|
||||
map.register(Boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER));
|
||||
map.register(boolean.class, wrapDeserializer(BOOLEAN_TYPE_ADAPTER));
|
||||
map.register(Byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER));
|
||||
map.register(byte.class, wrapDeserializer(BYTE_TYPE_ADAPTER));
|
||||
map.register(Character.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER));
|
||||
map.register(char.class, wrapDeserializer(CHARACTER_TYPE_ADAPTER));
|
||||
map.register(Double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER));
|
||||
map.register(double.class, wrapDeserializer(DOUBLE_TYPE_ADAPTER));
|
||||
map.register(Float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER));
|
||||
map.register(float.class, wrapDeserializer(FLOAT_TYPE_ADAPTER));
|
||||
map.register(Integer.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
|
||||
map.register(int.class, wrapDeserializer(INTEGER_TYPE_ADAPTER));
|
||||
map.register(Long.class, wrapDeserializer(LONG_DESERIALIZER));
|
||||
map.register(long.class, wrapDeserializer(LONG_DESERIALIZER));
|
||||
map.register(Number.class, wrapDeserializer(NUMBER_TYPE_ADAPTER));
|
||||
map.register(Short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
|
||||
map.register(short.class, wrapDeserializer(SHORT_TYPE_ADAPTER));
|
||||
map.register(String.class, wrapDeserializer(STRING_TYPE_ADAPTER));
|
||||
|
||||
map.makeUnmodifiable();
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
|
||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> map =
|
||||
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
|
||||
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
|
||||
|
||||
// Add Collection type instance creators
|
||||
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
|
||||
|
||||
map.registerForTypeHierarchy(Set.class, HASH_SET_CREATOR);
|
||||
map.registerForTypeHierarchy(SortedSet.class, TREE_SET_CREATOR);
|
||||
map.register(Properties.class, PROPERTIES_CREATOR);
|
||||
map.makeUnmodifiable();
|
||||
return map;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static JsonDeserializer<?> wrapDeserializer(JsonDeserializer<?> deserializer) {
|
||||
return new JsonDeserializerExceptionWrapper(deserializer);
|
||||
}
|
||||
|
||||
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() {
|
||||
return getDefaultSerializers(false, LongSerializationPolicy.DEFAULT);
|
||||
}
|
||||
|
||||
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers(
|
||||
boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
|
||||
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
||||
|
||||
// Double primitive
|
||||
DefaultTypeAdapters.DoubleSerializer doubleSerializer =
|
||||
new DefaultTypeAdapters.DoubleSerializer(serializeSpecialFloatingPointValues);
|
||||
serializers.registerIfAbsent(Double.class, doubleSerializer);
|
||||
serializers.registerIfAbsent(double.class, doubleSerializer);
|
||||
|
||||
// Float primitive
|
||||
DefaultTypeAdapters.FloatSerializer floatSerializer =
|
||||
new DefaultTypeAdapters.FloatSerializer(serializeSpecialFloatingPointValues);
|
||||
serializers.registerIfAbsent(Float.class, floatSerializer);
|
||||
serializers.registerIfAbsent(float.class, floatSerializer);
|
||||
|
||||
// Long primitive
|
||||
DefaultTypeAdapters.LongSerializer longSerializer =
|
||||
new DefaultTypeAdapters.LongSerializer(longSerializationPolicy);
|
||||
serializers.registerIfAbsent(Long.class, longSerializer);
|
||||
serializers.registerIfAbsent(long.class, longSerializer);
|
||||
|
||||
serializers.registerIfAbsent(DEFAULT_SERIALIZERS);
|
||||
return serializers;
|
||||
}
|
||||
|
||||
static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getDefaultDeserializers() {
|
||||
return DEFAULT_DESERIALIZERS;
|
||||
}
|
||||
|
||||
static ParameterizedTypeHandlerMap<InstanceCreator<?>> getDefaultInstanceCreators() {
|
||||
return DEFAULT_INSTANCE_CREATORS;
|
||||
}
|
||||
|
||||
static class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
|
||||
private final DateFormat format;
|
||||
|
||||
DefaultDateTypeAdapter() {
|
||||
this.format = DateFormat.getDateTimeInstance();
|
||||
}
|
||||
|
||||
DefaultDateTypeAdapter(final String datePattern) {
|
||||
this.format = new SimpleDateFormat(datePattern);
|
||||
}
|
||||
|
||||
DefaultDateTypeAdapter(final int style) {
|
||||
this.format = DateFormat.getDateInstance(style);
|
||||
}
|
||||
|
||||
public DefaultDateTypeAdapter(final int dateStyle, final int timeStyle) {
|
||||
this.format = DateFormat.getDateTimeInstance(dateStyle, timeStyle);
|
||||
}
|
||||
|
||||
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
|
||||
// See issue 162
|
||||
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
synchronized (format) {
|
||||
String dateFormatAsString = format.format(src);
|
||||
return new JsonPrimitive(dateFormatAsString);
|
||||
}
|
||||
}
|
||||
|
||||
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
if (!(json instanceof JsonPrimitive)) {
|
||||
throw new JsonParseException("The date should be a string value");
|
||||
}
|
||||
try {
|
||||
synchronized (format) {
|
||||
return format.parse(json.getAsString());
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(DefaultDateTypeAdapter.class.getSimpleName());
|
||||
sb.append('(').append(format.getClass().getSimpleName()).append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultJavaSqlDateTypeAdapter implements JsonSerializer<java.sql.Date>,
|
||||
JsonDeserializer<java.sql.Date> {
|
||||
private final DateFormat format;
|
||||
DefaultJavaSqlDateTypeAdapter() {
|
||||
this.format = new SimpleDateFormat("MMM d, yyyy");
|
||||
}
|
||||
|
||||
public JsonElement serialize(java.sql.Date src, Type typeOfSrc,
|
||||
JsonSerializationContext context) {
|
||||
synchronized (format) {
|
||||
String dateFormatAsString = format.format(src);
|
||||
return new JsonPrimitive(dateFormatAsString);
|
||||
}
|
||||
}
|
||||
|
||||
public java.sql.Date deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
if (!(json instanceof JsonPrimitive)) {
|
||||
throw new JsonParseException("The date should be a string value");
|
||||
}
|
||||
try {
|
||||
synchronized (format) {
|
||||
Date date = format.parse(json.getAsString());
|
||||
return new java.sql.Date(date.getTime());
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultTimestampDeserializer implements JsonDeserializer<Timestamp> {
|
||||
public Timestamp deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
Date date = context.deserialize(json, Date.class);
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultTimeTypeAdapter implements JsonSerializer<Time>, JsonDeserializer<Time> {
|
||||
private final DateFormat format;
|
||||
DefaultTimeTypeAdapter() {
|
||||
this.format = new SimpleDateFormat("hh:mm:ss a");
|
||||
}
|
||||
public JsonElement serialize(Time src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
synchronized (format) {
|
||||
String dateFormatAsString = format.format(src);
|
||||
return new JsonPrimitive(dateFormatAsString);
|
||||
}
|
||||
}
|
||||
public Time deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
if (!(json instanceof JsonPrimitive)) {
|
||||
throw new JsonParseException("The date should be a string value");
|
||||
}
|
||||
try {
|
||||
synchronized (format) {
|
||||
Date date = format.parse(json.getAsString());
|
||||
return new Time(date.getTime());
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GregorianCalendarTypeAdapter
|
||||
implements JsonSerializer<GregorianCalendar>, JsonDeserializer<GregorianCalendar> {
|
||||
|
||||
private static final String YEAR = "year";
|
||||
private static final String MONTH = "month";
|
||||
private static final String DAY_OF_MONTH = "dayOfMonth";
|
||||
private static final String HOUR_OF_DAY = "hourOfDay";
|
||||
private static final String MINUTE = "minute";
|
||||
private static final String SECOND = "second";
|
||||
|
||||
public JsonElement serialize(GregorianCalendar src, Type typeOfSrc,
|
||||
JsonSerializationContext context) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty(YEAR, src.get(Calendar.YEAR));
|
||||
obj.addProperty(MONTH, src.get(Calendar.MONTH));
|
||||
obj.addProperty(DAY_OF_MONTH, src.get(Calendar.DAY_OF_MONTH));
|
||||
obj.addProperty(HOUR_OF_DAY, src.get(Calendar.HOUR_OF_DAY));
|
||||
obj.addProperty(MINUTE, src.get(Calendar.MINUTE));
|
||||
obj.addProperty(SECOND, src.get(Calendar.SECOND));
|
||||
return obj;
|
||||
}
|
||||
|
||||
public GregorianCalendar deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
JsonObject obj = json.getAsJsonObject();
|
||||
int year = obj.get(YEAR).getAsInt();
|
||||
int month = obj.get(MONTH).getAsInt();
|
||||
int dayOfMonth = obj.get(DAY_OF_MONTH).getAsInt();
|
||||
int hourOfDay = obj.get(HOUR_OF_DAY).getAsInt();
|
||||
int minute = obj.get(MINUTE).getAsInt();
|
||||
int second = obj.get(SECOND).getAsInt();
|
||||
return new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute, second);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GregorianCalendarTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static class EnumTypeAdapter<T extends Enum<T>>
|
||||
implements JsonSerializer<T>, JsonDeserializer<T> {
|
||||
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.name());
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
public T deserialize(JsonElement json, Type classOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return (T) Enum.valueOf((Class<T>) classOfT, json.getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return EnumTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UrlTypeAdapter implements JsonSerializer<URL>, JsonDeserializer<URL> {
|
||||
public JsonElement serialize(URL src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.toExternalForm());
|
||||
}
|
||||
|
||||
public URL deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
try {
|
||||
return new URL(json.getAsString());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return UrlTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UriTypeAdapter implements JsonSerializer<URI>, JsonDeserializer<URI> {
|
||||
public JsonElement serialize(URI src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.toASCIIString());
|
||||
}
|
||||
public URI deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
try {
|
||||
return new URI(json.getAsString());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return UriTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UuidTypeAdapter implements JsonSerializer<UUID>, JsonDeserializer<UUID> {
|
||||
public JsonElement serialize(UUID src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.toString());
|
||||
}
|
||||
|
||||
public UUID deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return UUID.fromString(json.getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return UuidTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class LocaleTypeAdapter
|
||||
implements JsonSerializer<Locale>, JsonDeserializer<Locale> {
|
||||
public JsonElement serialize(Locale src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.toString());
|
||||
}
|
||||
|
||||
public Locale deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
String locale = json.getAsString();
|
||||
StringTokenizer tokenizer = new StringTokenizer(locale, "_");
|
||||
String language = null;
|
||||
String country = null;
|
||||
String variant = null;
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
language = tokenizer.nextToken();
|
||||
}
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
country = tokenizer.nextToken();
|
||||
}
|
||||
if (tokenizer.hasMoreElements()) {
|
||||
variant = tokenizer.nextToken();
|
||||
}
|
||||
if (country == null && variant == null) {
|
||||
return new Locale(language);
|
||||
} else if (variant == null) {
|
||||
return new Locale(language, country);
|
||||
} else {
|
||||
return new Locale(language, country, variant);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return LocaleTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static class CollectionTypeAdapter implements JsonSerializer<Collection>,
|
||||
JsonDeserializer<Collection>, InstanceCreator<Collection> {
|
||||
public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
if (src == null) {
|
||||
return JsonNull.createJsonNull();
|
||||
}
|
||||
JsonArray array = new JsonArray();
|
||||
Type childGenericType = null;
|
||||
if (typeOfSrc instanceof ParameterizedType) {
|
||||
childGenericType = new TypeInfoCollection(typeOfSrc).getElementType();
|
||||
}
|
||||
for (Object child : src) {
|
||||
if (child == null) {
|
||||
array.add(JsonNull.createJsonNull());
|
||||
} else {
|
||||
Type childType = (childGenericType == null || childGenericType == Object.class)
|
||||
? child.getClass() : childGenericType;
|
||||
JsonElement element = context.serialize(child, childType);
|
||||
array.add(element);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Collection deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
if (json.isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
|
||||
// This handles cases where users are using their own subclass of Collection.
|
||||
Collection collection = constructCollectionType(typeOfT, context);
|
||||
Type childType = new TypeInfoCollection(typeOfT).getElementType();
|
||||
for (JsonElement childElement : json.getAsJsonArray()) {
|
||||
if (childElement == null || childElement.isJsonNull()) {
|
||||
collection.add(null);
|
||||
} else {
|
||||
Object value = context.deserialize(childElement, childType);
|
||||
collection.add(value);
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
private Collection constructCollectionType(Type collectionType,
|
||||
JsonDeserializationContext context) {
|
||||
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
|
||||
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
|
||||
return (Collection) objectConstructor.construct(collectionType);
|
||||
}
|
||||
|
||||
public Collection createInstance(Type type) {
|
||||
return new LinkedList();
|
||||
}
|
||||
}
|
||||
|
||||
private static class PropertiesCreator implements InstanceCreator<Properties> {
|
||||
public Properties createInstance(Type type) {
|
||||
return new Properties();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
static class MapTypeAdapter implements JsonSerializer<Map>, JsonDeserializer<Map>,
|
||||
InstanceCreator<Map> {
|
||||
|
||||
public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonObject map = new JsonObject();
|
||||
Type childGenericType = null;
|
||||
if (typeOfSrc instanceof ParameterizedType) {
|
||||
childGenericType = new TypeInfoMap(typeOfSrc).getValueType();
|
||||
}
|
||||
|
||||
for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
|
||||
JsonElement valueElement;
|
||||
if (value == null) {
|
||||
valueElement = JsonNull.createJsonNull();
|
||||
} else {
|
||||
Type childType = (childGenericType == null)
|
||||
? value.getClass() : childGenericType;
|
||||
valueElement = context.serialize(value, childType);
|
||||
}
|
||||
map.add(String.valueOf(entry.getKey()), valueElement);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
|
||||
// This handles cases where users are using their own subclass of Map.
|
||||
Map<Object, Object> map = constructMapType(typeOfT, context);
|
||||
TypeInfoMap mapTypeInfo = new TypeInfoMap(typeOfT);
|
||||
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
|
||||
Object key = context.deserialize(new JsonPrimitive(entry.getKey()), mapTypeInfo.getKeyType());
|
||||
Object value = context.deserialize(entry.getValue(), mapTypeInfo.getValueType());
|
||||
map.put(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private Map constructMapType(Type mapType, JsonDeserializationContext context) {
|
||||
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
|
||||
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
|
||||
return (Map) objectConstructor.construct(mapType);
|
||||
}
|
||||
|
||||
public Map createInstance(Type type) {
|
||||
return new LinkedHashMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MapTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class BigDecimalTypeAdapter
|
||||
implements JsonSerializer<BigDecimal>, JsonDeserializer<BigDecimal> {
|
||||
public JsonElement serialize(BigDecimal src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public BigDecimal deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
return json.getAsBigDecimal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return BigDecimalTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class BigIntegerTypeAdapter
|
||||
implements JsonSerializer<BigInteger>, JsonDeserializer<BigInteger> {
|
||||
|
||||
public JsonElement serialize(BigInteger src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public BigInteger deserialize(JsonElement json, Type typeOfT,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
return json.getAsBigInteger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return BigIntegerTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class NumberTypeAdapter
|
||||
implements JsonSerializer<Number>, JsonDeserializer<Number> {
|
||||
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Number deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return NumberTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class LongSerializer implements JsonSerializer<Long> {
|
||||
private final LongSerializationPolicy longSerializationPolicy;
|
||||
|
||||
private LongSerializer(LongSerializationPolicy longSerializationPolicy) {
|
||||
this.longSerializationPolicy = longSerializationPolicy;
|
||||
}
|
||||
|
||||
public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return longSerializationPolicy.serialize(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return LongSerializer.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class LongDeserializer implements JsonDeserializer<Long> {
|
||||
public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return LongDeserializer.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class IntegerTypeAdapter
|
||||
implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
|
||||
public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return IntegerTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ShortTypeAdapter
|
||||
implements JsonSerializer<Short>, JsonDeserializer<Short> {
|
||||
public JsonElement serialize(Short src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Short deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ShortTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ByteTypeAdapter implements JsonSerializer<Byte>, JsonDeserializer<Byte> {
|
||||
public JsonElement serialize(Byte src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Byte deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ByteTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
static class FloatSerializer implements JsonSerializer<Float> {
|
||||
private final boolean serializeSpecialFloatingPointValues;
|
||||
|
||||
FloatSerializer(boolean serializeSpecialDoubleValues) {
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialDoubleValues;
|
||||
}
|
||||
|
||||
public JsonElement serialize(Float src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
if (!serializeSpecialFloatingPointValues) {
|
||||
if (Float.isNaN(src) || Float.isInfinite(src)) {
|
||||
throw new IllegalArgumentException(src
|
||||
+ " is not a valid float value as per JSON specification. To override this"
|
||||
+ " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.");
|
||||
}
|
||||
}
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FloatDeserializer implements JsonDeserializer<Float> {
|
||||
public Float deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return FloatDeserializer.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
static class DoubleSerializer implements JsonSerializer<Double> {
|
||||
private final boolean serializeSpecialFloatingPointValues;
|
||||
|
||||
DoubleSerializer(boolean serializeSpecialDoubleValues) {
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialDoubleValues;
|
||||
}
|
||||
|
||||
public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
if (!serializeSpecialFloatingPointValues) {
|
||||
if (Double.isNaN(src) || Double.isInfinite(src)) {
|
||||
throw new IllegalArgumentException(src
|
||||
+ " is not a valid double value as per JSON specification. To override this"
|
||||
+ " behavior, use GsonBuilder.serializeSpecialDoubleValues() method.");
|
||||
}
|
||||
}
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DoubleDeserializer implements JsonDeserializer<Double> {
|
||||
public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return DoubleDeserializer.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class CharacterTypeAdapter
|
||||
implements JsonSerializer<Character>, JsonDeserializer<Character> {
|
||||
public JsonElement serialize(Character src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Character deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsCharacter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return CharacterTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class StringTypeAdapter
|
||||
implements JsonSerializer<String>, JsonDeserializer<String> {
|
||||
public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class BooleanTypeAdapter
|
||||
implements JsonSerializer<Boolean>, JsonDeserializer<Boolean> {
|
||||
public JsonElement serialize(Boolean src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
|
||||
public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return json.getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return BooleanTypeAdapter.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class TreeSetCreator implements InstanceCreator<TreeSet<?>> {
|
||||
public TreeSet<?> createInstance(Type type) {
|
||||
return new TreeSet<Object>();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return TreeSetCreator.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HashSetCreator implements InstanceCreator<HashSet<?>> {
|
||||
public HashSet<?> createInstance(Type type) {
|
||||
return new HashSet<Object>();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return HashSetCreator.class.getSimpleName();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A simple implementation of the {@link JsonElementVisitor} that simply delegates the method
|
||||
* invocation onto a {@code delegate} instance of the {@link JsonElementVisitor}. This object
|
||||
* can be used to build a chain of visitors such that each Visitor instance can perform some
|
||||
* operation on the {@link JsonElement} and then pass on the input to the delegate. This kind
|
||||
* of pattern is sometimes referred as a "Chain of Responsibility".
|
||||
*
|
||||
* <p>The following is an example use case:
|
||||
*
|
||||
* <pre>
|
||||
* class JsonEscapingVisitor extends DelegatingJsonElementVisitor {
|
||||
* public JsonEscapingVisitor(JsonElementVisitor) {
|
||||
* super(visitor);
|
||||
* }
|
||||
*
|
||||
* public void visitPrimitive(JsonPrimitive primitive) {
|
||||
* JsonPrimitive escapedPrimitive = escapePrimitiveObject(primitive);
|
||||
* super.visitPrimitive(escapedPrimitive);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* JsonElementVisitor visitor = new JsonEscapingVisitor(new FormattingVisitor());
|
||||
* </pre></p>
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
class DelegatingJsonElementVisitor implements JsonElementVisitor {
|
||||
private final JsonElementVisitor delegate;
|
||||
|
||||
protected DelegatingJsonElementVisitor(JsonElementVisitor delegate) {
|
||||
Preconditions.checkNotNull(delegate);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public void endArray(JsonArray array) throws IOException {
|
||||
delegate.endArray(array);
|
||||
}
|
||||
|
||||
public void endObject(JsonObject object) throws IOException {
|
||||
delegate.endObject(object);
|
||||
}
|
||||
|
||||
public void startArray(JsonArray array) throws IOException {
|
||||
delegate.startArray(array);
|
||||
}
|
||||
|
||||
public void startObject(JsonObject object) throws IOException {
|
||||
delegate.startObject(object);
|
||||
}
|
||||
|
||||
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitArrayMember(parent, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitArrayMember(JsonArray parent, JsonArray member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitArrayMember(parent, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitArrayMember(JsonArray parent, JsonObject member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitArrayMember(parent, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitObjectMember(parent, memberName, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitObjectMember(parent, memberName, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitObjectMember(parent, memberName, member, isFirst);
|
||||
}
|
||||
|
||||
public void visitNullObjectMember(JsonObject parent, String memberName,
|
||||
boolean isFirst) throws IOException {
|
||||
delegate.visitNullObjectMember(parent, memberName, isFirst);
|
||||
}
|
||||
|
||||
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
|
||||
delegate.visitPrimitive(primitive);
|
||||
}
|
||||
|
||||
public void visitNull() throws IOException {
|
||||
delegate.visitNull();
|
||||
}
|
||||
|
||||
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
|
||||
delegate.visitNullArrayMember(parent, isFirst);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A wrapper class used to collect numerous {@link ExclusionStrategy} objects
|
||||
* and perform a short-circuited OR operation.
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class DisjunctionExclusionStrategy implements ExclusionStrategy {
|
||||
private final Collection<ExclusionStrategy> strategies;
|
||||
|
||||
public DisjunctionExclusionStrategy(Collection<ExclusionStrategy> strategies) {
|
||||
Preconditions.checkNotNull(strategies);
|
||||
this.strategies = strategies;
|
||||
}
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
for (ExclusionStrategy strategy : strategies) {
|
||||
if (strategy.shouldSkipField(f)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
for (ExclusionStrategy strategy : strategies) {
|
||||
if (strategy.shouldSkipClass(clazz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
160
src/org/mcteam/ancientgates/gson/Escaper.java
Normal file
160
src/org/mcteam/ancientgates/gson/Escaper.java
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A utility class that is used to perform JSON escaping so that ", <, >, etc. characters are
|
||||
* properly encoded in the JSON string representation before returning to the client code.
|
||||
*
|
||||
* <p>This class contains a single method to escape a passed in string value:
|
||||
* <pre>
|
||||
* String jsonStringValue = "beforeQuote\"afterQuote";
|
||||
* String escapedValue = Escaper.escapeJsonString(jsonStringValue);
|
||||
* </pre></p>
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class Escaper {
|
||||
|
||||
private static final char[] HEX_CHARS = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
||||
};
|
||||
|
||||
private static final Set<Character> JS_ESCAPE_CHARS;
|
||||
private static final Set<Character> HTML_ESCAPE_CHARS;
|
||||
|
||||
static {
|
||||
Set<Character> mandatoryEscapeSet = new HashSet<Character>();
|
||||
mandatoryEscapeSet.add('"');
|
||||
mandatoryEscapeSet.add('\\');
|
||||
JS_ESCAPE_CHARS = Collections.unmodifiableSet(mandatoryEscapeSet);
|
||||
|
||||
Set<Character> htmlEscapeSet = new HashSet<Character>();
|
||||
htmlEscapeSet.add('<');
|
||||
htmlEscapeSet.add('>');
|
||||
htmlEscapeSet.add('&');
|
||||
htmlEscapeSet.add('=');
|
||||
htmlEscapeSet.add('\'');
|
||||
// htmlEscapeSet.add('/'); -- Removing slash for now since it causes some incompatibilities
|
||||
HTML_ESCAPE_CHARS = Collections.unmodifiableSet(htmlEscapeSet);
|
||||
}
|
||||
|
||||
private final boolean escapeHtmlCharacters;
|
||||
|
||||
Escaper(boolean escapeHtmlCharacters) {
|
||||
this.escapeHtmlCharacters = escapeHtmlCharacters;
|
||||
}
|
||||
|
||||
public String escapeJsonString(CharSequence plainText) {
|
||||
StringBuffer escapedString = new StringBuffer(plainText.length() + 20);
|
||||
try {
|
||||
escapeJsonString(plainText, escapedString);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return escapedString.toString();
|
||||
}
|
||||
|
||||
private void escapeJsonString(CharSequence plainText, StringBuffer out) throws IOException {
|
||||
int pos = 0; // Index just past the last char in plainText written to out.
|
||||
int len = plainText.length();
|
||||
|
||||
for (int charCount, i = 0; i < len; i += charCount) {
|
||||
int codePoint = Character.codePointAt(plainText, i);
|
||||
charCount = Character.charCount(codePoint);
|
||||
|
||||
if (!isControlCharacter(codePoint) && !mustEscapeCharInJsString(codePoint)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out.append(plainText, pos, i);
|
||||
pos = i + charCount;
|
||||
switch (codePoint) {
|
||||
case '\b':
|
||||
out.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
out.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
out.append("\\n");
|
||||
break;
|
||||
case '\f':
|
||||
out.append("\\f");
|
||||
break;
|
||||
case '\r':
|
||||
out.append("\\r");
|
||||
break;
|
||||
case '\\':
|
||||
out.append("\\\\");
|
||||
break;
|
||||
case '/':
|
||||
out.append("\\/");
|
||||
break;
|
||||
case '"':
|
||||
out.append("\\\"");
|
||||
break;
|
||||
default:
|
||||
appendHexJavaScriptRepresentation(codePoint, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.append(plainText, pos, len);
|
||||
}
|
||||
|
||||
private boolean mustEscapeCharInJsString(int codepoint) {
|
||||
if (!Character.isSupplementaryCodePoint(codepoint)) {
|
||||
char c = (char) codepoint;
|
||||
return JS_ESCAPE_CHARS.contains(c)
|
||||
|| (escapeHtmlCharacters && HTML_ESCAPE_CHARS.contains(c));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isControlCharacter(int codePoint) {
|
||||
// JSON spec defines these code points as control characters, so they must be escaped
|
||||
return codePoint < 0x20
|
||||
|| codePoint == 0x2028 // Line separator
|
||||
|| codePoint == 0x2029 // Paragraph separator
|
||||
|| (codePoint >= 0x7f && codePoint <= 0x9f);
|
||||
}
|
||||
|
||||
private static void appendHexJavaScriptRepresentation(int codePoint, Appendable out)
|
||||
throws IOException {
|
||||
if (Character.isSupplementaryCodePoint(codePoint)) {
|
||||
// Handle supplementary unicode values which are not representable in
|
||||
// javascript. We deal with these by escaping them as two 4B sequences
|
||||
// so that they will round-trip properly when sent from java to javascript
|
||||
// and back.
|
||||
char[] surrogates = Character.toChars(codePoint);
|
||||
appendHexJavaScriptRepresentation(surrogates[0], out);
|
||||
appendHexJavaScriptRepresentation(surrogates[1], out);
|
||||
return;
|
||||
}
|
||||
out.append("\\u")
|
||||
.append(HEX_CHARS[(codePoint >>> 12) & 0xf])
|
||||
.append(HEX_CHARS[(codePoint >>> 8) & 0xf])
|
||||
.append(HEX_CHARS[(codePoint >>> 4) & 0xf])
|
||||
.append(HEX_CHARS[codePoint & 0xf]);
|
||||
}
|
||||
}
|
95
src/org/mcteam/ancientgates/gson/ExclusionStrategy.java
Normal file
95
src/org/mcteam/ancientgates/gson/ExclusionStrategy.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
|
||||
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
|
||||
* if the {@link #shouldSkipClass(Class)} method returns false then that class or field type
|
||||
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
|
||||
* returns false, then it will not be set as part of the Java object structure.
|
||||
*
|
||||
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
||||
*
|
||||
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
|
||||
* <pre class="code">
|
||||
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
||||
* private final Class<?> excludedThisClass;
|
||||
*
|
||||
* public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
||||
* this.excludedThisClass = excludedThisClass;
|
||||
* }
|
||||
*
|
||||
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||
* return excludedThisClass.equals(clazz);
|
||||
* }
|
||||
*
|
||||
* public boolean shouldSkipField(FieldAttributes f) {
|
||||
* return excludedThisClass.equals(f.getDeclaredClass());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
|
||||
* <pre class="code">
|
||||
* public @interface FooAnnotation {
|
||||
* // some implementation here
|
||||
* }
|
||||
*
|
||||
* // Excludes any field (or class) that is tagged with an "@FooAnnotation"
|
||||
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
|
||||
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||
* return clazz.getAnnotation(FooAnnotation.class) != null;
|
||||
* }
|
||||
*
|
||||
* public boolean shouldSkipField(FieldAttributes f) {
|
||||
* return f.getAnnotation(FooAnnotation.class) != null;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
|
||||
* the {@code GsonBuilder} is required. The following is an example of how you can use the
|
||||
* {@code GsonBuilder} to configure Gson to use one of the above sample:
|
||||
* <pre class="code">
|
||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .setExclusionStrategies(excludeStrings)
|
||||
* .create();
|
||||
* </pre>
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*
|
||||
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public interface ExclusionStrategy {
|
||||
|
||||
/**
|
||||
* @param f the field object that is under test
|
||||
* @return true if the field should be ignored; otherwise false
|
||||
*/
|
||||
public boolean shouldSkipField(FieldAttributes f);
|
||||
|
||||
/**
|
||||
* @param clazz the class object that is under test
|
||||
* @return true if the class should be ignored; otherwise false
|
||||
*/
|
||||
public boolean shouldSkipClass(Class<?> clazz);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import org.mcteam.ancientgates.gson.annotations.Expose;
|
||||
|
||||
/**
|
||||
* Excludes fields that do not have the {@link Expose} annotation
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class ExposeAnnotationDeserializationExclusionStrategy implements ExclusionStrategy {
|
||||
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
Expose annotation = f.getAnnotation(Expose.class);
|
||||
if (annotation == null) {
|
||||
return true;
|
||||
}
|
||||
return !annotation.deserialize();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import org.mcteam.ancientgates.gson.annotations.Expose;
|
||||
|
||||
/**
|
||||
* Excludes fields that do not have the {@link Expose} annotation
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class ExposeAnnotationSerializationExclusionStrategy implements ExclusionStrategy {
|
||||
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
Expose annotation = f.getAnnotation(Expose.class);
|
||||
if (annotation == null) {
|
||||
return true;
|
||||
}
|
||||
return !annotation.serialize();
|
||||
}
|
||||
}
|
229
src/org/mcteam/ancientgates/gson/FieldAttributes.java
Normal file
229
src/org/mcteam/ancientgates/gson/FieldAttributes.java
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* A data object that stores attributes of a field.
|
||||
*
|
||||
* <p>This class is immutable; therefore, it can be safely shared across threads.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public final class FieldAttributes {
|
||||
private static final String MAX_CACHE_PROPERTY_NAME =
|
||||
"com.bukkit.mcteam.gson.annotation_cache_size_hint";
|
||||
|
||||
private static final Cache<Pair<Class<?>, String>, Collection<Annotation>> ANNOTATION_CACHE =
|
||||
new LruCache<Pair<Class<?>,String>, Collection<Annotation>>(getMaxCacheSize());
|
||||
|
||||
private final Class<?> declaringClazz;
|
||||
private final Field field;
|
||||
private final Class<?> declaredType;
|
||||
private final boolean isSynthetic;
|
||||
private final int modifiers;
|
||||
private final String name;
|
||||
|
||||
// Fields used for lazy initialization
|
||||
private Type genericType;
|
||||
private Collection<Annotation> annotations;
|
||||
|
||||
/**
|
||||
* Constructs a Field Attributes object from the {@code f}.
|
||||
*
|
||||
* @param f the field to pull attributes from
|
||||
*/
|
||||
FieldAttributes(final Class<?> declaringClazz, final Field f) {
|
||||
Preconditions.checkNotNull(declaringClazz);
|
||||
this.declaringClazz = declaringClazz;
|
||||
name = f.getName();
|
||||
declaredType = f.getType();
|
||||
isSynthetic = f.isSynthetic();
|
||||
modifiers = f.getModifiers();
|
||||
field = f;
|
||||
}
|
||||
|
||||
private static int getMaxCacheSize() {
|
||||
final int defaultMaxCacheSize = 2000;
|
||||
try {
|
||||
String propertyValue = System.getProperty(
|
||||
MAX_CACHE_PROPERTY_NAME, String.valueOf(defaultMaxCacheSize));
|
||||
return Integer.parseInt(propertyValue);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultMaxCacheSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the declaring class that contains this field
|
||||
*/
|
||||
public Class<?> getDeclaringClass() {
|
||||
return declaringClazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the field
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>For example, assume the following class definition:
|
||||
* <pre class="code">
|
||||
* public class Foo {
|
||||
* private String bar;
|
||||
* private List<String> red;
|
||||
* }
|
||||
*
|
||||
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
|
||||
* </pre>
|
||||
*
|
||||
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||
* {@code listParameterizedType} for the {@code red} field.
|
||||
*
|
||||
* @return the specific type declared for this field
|
||||
*/
|
||||
public Type getDeclaredType() {
|
||||
if (genericType == null) {
|
||||
genericType = field.getGenericType();
|
||||
}
|
||||
return genericType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code Class<?>} object that was declared for this field.
|
||||
*
|
||||
* <p>For example, assume the following class definition:
|
||||
* <pre class="code">
|
||||
* public class Foo {
|
||||
* private String bar;
|
||||
* private List<String> red;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||
* {@code List.class} for the {@code red} field.
|
||||
*
|
||||
* @return the specific class object that was declared for the field
|
||||
*/
|
||||
public Class<?> getDeclaredClass() {
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@code T} annotation object from this field if it exist; otherwise returns
|
||||
* {@code null}.
|
||||
*
|
||||
* @param annotation the class of the annotation that will be retrieved
|
||||
* @return the annotation instance if it is bound to the field; otherwise {@code null}
|
||||
*/
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
|
||||
return getAnnotationFromArray(getAnnotations(), annotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the annotations that are present on this field.
|
||||
*
|
||||
* @return an array of all the annotations set on the field
|
||||
* @since 1.4
|
||||
*/
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
if (annotations == null) {
|
||||
Pair<Class<?>, String> key = new Pair<Class<?>, String>(declaringClazz, name);
|
||||
annotations = ANNOTATION_CACHE.getElement(key);
|
||||
if (annotations == null) {
|
||||
annotations = Collections.unmodifiableCollection(
|
||||
Arrays.asList(field.getAnnotations()));
|
||||
ANNOTATION_CACHE.addElement(key, annotations);
|
||||
}
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the field is defined with the {@code modifier}.
|
||||
*
|
||||
* <p>This method is meant to be called as:
|
||||
* <pre class="code">
|
||||
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
|
||||
* </pre>
|
||||
*
|
||||
* @see java.lang.reflect.Modifier
|
||||
*/
|
||||
public boolean hasModifier(int modifier) {
|
||||
return (modifiers & modifier) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||
*
|
||||
* @throws IllegalAccessException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
void set(Object instance, Object value) throws IllegalAccessException {
|
||||
field.set(instance, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||
*
|
||||
* @return true if the field is synthetic; otherwise false
|
||||
* @throws IllegalAccessException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
Object get(Object instance) throws IllegalAccessException {
|
||||
return field.get(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||
*
|
||||
* @return true if the field is synthetic; otherwise false
|
||||
*/
|
||||
boolean isSynthetic() {
|
||||
return isSynthetic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated remove this when {@link FieldNamingStrategy} is deleted.
|
||||
*/
|
||||
@Deprecated
|
||||
Field getFieldObject() {
|
||||
return field;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Annotation> T getAnnotationFromArray(
|
||||
Collection<Annotation> annotations, Class<T> annotation) {
|
||||
for (Annotation a : annotations) {
|
||||
if (a.annotationType() == annotation) {
|
||||
return (T) a;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
99
src/org/mcteam/ancientgates/gson/FieldNamingPolicy.java
Normal file
99
src/org/mcteam/ancientgates/gson/FieldNamingPolicy.java
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* An enumeration that defines a few standard naming conventions for JSON field names.
|
||||
* This enumeration should be used in conjunction with {@link org.mcteam.ancientgates.gson.GsonBuilder}
|
||||
* to configure a {@link org.mcteam.ancientgates.gson.Gson} instance to properly translate Java field
|
||||
* names into the desired JSON field names.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public enum FieldNamingPolicy {
|
||||
/**
|
||||
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
||||
* field name is capitalized when serialized to its JSON form.
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> SomeFieldName</li>
|
||||
* <li>_someFieldName ---> _SomeFieldName</li>
|
||||
* </ul>
|
||||
*/
|
||||
UPPER_CAMEL_CASE(new ModifyFirstLetterNamingPolicy(
|
||||
ModifyFirstLetterNamingPolicy.LetterModifier.UPPER)),
|
||||
|
||||
/**
|
||||
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
||||
* field name is capitalized when serialized to its JSON form and the words will be
|
||||
* separated by a space.
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> Some Field Name</li>
|
||||
* <li>_someFieldName ---> _Some Field Name</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
UPPER_CAMEL_CASE_WITH_SPACES(new UpperCamelCaseSeparatorNamingPolicy(" ")),
|
||||
|
||||
/**
|
||||
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
||||
* form to a lower case field name where each word is separated by an underscore (_).
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> some_field_name</li>
|
||||
* <li>_someFieldName ---> _some_field_name</li>
|
||||
* <li>aStringField ---> a_string_field</li>
|
||||
* <li>aURL ---> a_u_r_l</li>
|
||||
* </ul>
|
||||
*/
|
||||
LOWER_CASE_WITH_UNDERSCORES(new LowerCamelCaseSeparatorNamingPolicy("_")),
|
||||
|
||||
/**
|
||||
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
||||
* form to a lower case field name where each word is separated by a dash (-).
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> some-field-name</li>
|
||||
* <li>_someFieldName ---> _some-field-name</li>
|
||||
* <li>aStringField ---> a-string-field</li>
|
||||
* <li>aURL ---> a-u-r-l</li>
|
||||
* </ul>
|
||||
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
|
||||
* expressions. This requires that a field named with dashes is always accessed as a quoted
|
||||
* property like {@code myobject['my-field']}. Accessing it as an object field
|
||||
* {@code myobject.my-field} will result in an unintended javascript expression.
|
||||
* @since 1.4
|
||||
*/
|
||||
LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
|
||||
|
||||
private final FieldNamingStrategy2 namingPolicy;
|
||||
|
||||
private FieldNamingPolicy(FieldNamingStrategy2 namingPolicy) {
|
||||
this.namingPolicy = namingPolicy;
|
||||
}
|
||||
|
||||
FieldNamingStrategy2 getFieldNamingPolicy() {
|
||||
return namingPolicy;
|
||||
}
|
||||
}
|
40
src/org/mcteam/ancientgates/gson/FieldNamingStrategy.java
Normal file
40
src/org/mcteam/ancientgates/gson/FieldNamingStrategy.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
|
||||
* field names into a particular convention that is not supported as a normal Java field
|
||||
* declaration rules. For example, Java does not support "-" characters in a field name.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
* @since 1.3
|
||||
*/
|
||||
public interface FieldNamingStrategy {
|
||||
|
||||
/**
|
||||
* Translates the field name into its JSON field name representation.
|
||||
*
|
||||
* @param f the field object that we are translating
|
||||
* @return the translated field name.
|
||||
* @since 1.3
|
||||
*/
|
||||
public String translateName(Field f);
|
||||
}
|
38
src/org/mcteam/ancientgates/gson/FieldNamingStrategy2.java
Normal file
38
src/org/mcteam/ancientgates/gson/FieldNamingStrategy2.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* The new mechanism for providing custom field naming in Gson. This allows the client code
|
||||
* to translate field names into a particular convention that is not supported as a normal
|
||||
* Java field declaration rules. For example, Java does not support "-" characters in a
|
||||
* field name.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
interface FieldNamingStrategy2 {
|
||||
|
||||
/**
|
||||
* Translates the field name into its JSON field name representation.
|
||||
*
|
||||
* @param f the field that is being translated
|
||||
* @return the translated field name.
|
||||
* @since 1.3
|
||||
*/
|
||||
public String translateName(FieldAttributes f);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
/**
|
||||
* Adapts the old "deprecated" {@link FieldNamingStrategy} to the new {@link FieldNamingStrategy2}
|
||||
* type.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class FieldNamingStrategy2Adapter implements FieldNamingStrategy2 {
|
||||
private final FieldNamingStrategy adaptee;
|
||||
|
||||
public FieldNamingStrategy2Adapter(FieldNamingStrategy adaptee) {
|
||||
Preconditions.checkNotNull(adaptee);
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public String translateName(FieldAttributes f) {
|
||||
return adaptee.translateName(f.getFieldObject());
|
||||
}
|
||||
}
|
70
src/org/mcteam/ancientgates/gson/GenericArrayTypeImpl.java
Normal file
70
src/org/mcteam/ancientgates/gson/GenericArrayTypeImpl.java
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* An simple pojo-like immutable instance of the {@link GenericArrayType}. This object provides
|
||||
* us the ability to create reflective types on demand. This object is required for support
|
||||
* object similar to the one defined below:
|
||||
* <pre>
|
||||
* class Foo<T> {
|
||||
* private final List<T>[] arrayOfListT;
|
||||
*
|
||||
* Foo(List<T>[] arrayList) {
|
||||
* this.arrayOfListT = arrayList;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>During parsing or serialization, we know the real variable type parameter {@code T},
|
||||
* so we can build a new {@code GenericTypeArray} with the "real" type parameters and
|
||||
* pass that object along instead.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class GenericArrayTypeImpl implements GenericArrayType {
|
||||
|
||||
private final Type genericComponentType;
|
||||
|
||||
public GenericArrayTypeImpl(Type genericComponentType) {
|
||||
this.genericComponentType = genericComponentType;
|
||||
}
|
||||
|
||||
public Type getGenericComponentType() {
|
||||
return genericComponentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof GenericArrayType)) {
|
||||
return false;
|
||||
}
|
||||
GenericArrayType that = (GenericArrayType) o;
|
||||
Type thatComponentType = that.getGenericComponentType();
|
||||
return genericComponentType == null ?
|
||||
thatComponentType == null : genericComponentType.equals(thatComponentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (genericComponentType == null) ? 0 : genericComponentType.hashCode();
|
||||
}
|
||||
}
|
597
src/org/mcteam/ancientgates/gson/Gson.java
Normal file
597
src/org/mcteam/ancientgates/gson/Gson.java
Normal file
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mcteam.ancientgates.gson.JsonSerializationContextDefault;
|
||||
import org.mcteam.ancientgates.gson.stream.JsonReader;
|
||||
import org.mcteam.ancientgates.gson.stream.JsonToken;
|
||||
import org.mcteam.ancientgates.gson.stream.JsonWriter;
|
||||
import org.mcteam.ancientgates.gson.stream.MalformedJsonException;
|
||||
|
||||
/**
|
||||
* This is the main class for using Gson. Gson is typically used by first constructing a
|
||||
* Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
|
||||
* methods on it.
|
||||
*
|
||||
* <p>You can create a Gson instance by invoking {@code new Gson()} if the default configuration
|
||||
* is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various
|
||||
* configuration options such as versioning support, pretty printing, custom
|
||||
* {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.</p>
|
||||
*
|
||||
* <p>Here is an example of how Gson is used for a simple Class:
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new Gson(); // Or use new GsonBuilder().create();
|
||||
* MyType target = new MyType();
|
||||
* String json = gson.toJson(target); // serializes target to Json
|
||||
* MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>If the object that your are serializing/deserializing is a {@code ParameterizedType}
|
||||
* (i.e. contains at least one type parameter and may be an array) then you must use the
|
||||
* {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
|
||||
* example for serializing and deserialing a {@code ParameterizedType}:
|
||||
*
|
||||
* <pre>
|
||||
* Type listType = new TypeToken<List<String>>() {}.getType();
|
||||
* List<String> target = new LinkedList<String>();
|
||||
* target.add("blah");
|
||||
*
|
||||
* Gson gson = new Gson();
|
||||
* String json = gson.toJson(target, listType);
|
||||
* List<String> target2 = gson.fromJson(json, listType);
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson User Guide</a>
|
||||
* for a more complete set of examples.</p>
|
||||
*
|
||||
* @see org.mcteam.ancientgates.gson.reflect.TypeToken
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public final class Gson {
|
||||
|
||||
//TODO(inder): get rid of all the registerXXX methods and take all such parameters in the
|
||||
// constructor instead. At the minimum, mark those methods private.
|
||||
|
||||
private static final String NULL_STRING = "null";
|
||||
|
||||
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
|
||||
// Default instances of plug-ins
|
||||
static final AnonymousAndLocalClassExclusionStrategy DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY =
|
||||
new AnonymousAndLocalClassExclusionStrategy();
|
||||
static final SyntheticFieldExclusionStrategy DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY =
|
||||
new SyntheticFieldExclusionStrategy(true);
|
||||
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
|
||||
new ModifierBasedExclusionStrategy(new int[] { Modifier.TRANSIENT, Modifier.STATIC });
|
||||
static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY =
|
||||
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
|
||||
|
||||
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY =
|
||||
createExclusionStrategy(VersionConstants.IGNORE_VERSIONS);
|
||||
|
||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
|
||||
private final ExclusionStrategy serializationStrategy;
|
||||
|
||||
private final ExclusionStrategy deserializationStrategy;
|
||||
|
||||
private final FieldNamingStrategy2 fieldNamingPolicy;
|
||||
private final MappedObjectConstructor objectConstructor;
|
||||
|
||||
/** Map containing Type or Class objects as keys */
|
||||
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
|
||||
|
||||
/** Map containing Type or Class objects as keys */
|
||||
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
|
||||
|
||||
private final boolean serializeNulls;
|
||||
private final boolean htmlSafe;
|
||||
private final boolean generateNonExecutableJson;
|
||||
private final boolean prettyPrinting;
|
||||
|
||||
/**
|
||||
* Constructs a Gson object with default configuration. The default configuration has the
|
||||
* following settings:
|
||||
* <ul>
|
||||
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
|
||||
* means that all the unneeded white-space is removed. You can change this behavior with
|
||||
* {@link GsonBuilder#setPrettyPrinting()}. </li>
|
||||
* <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are
|
||||
* kept as is since an array is an ordered list. Moreover, if a field is not null, but its
|
||||
* generated JSON is empty, the field is kept. You can configure Gson to serialize null values
|
||||
* by setting {@link GsonBuilder#serializeNulls()}.</li>
|
||||
* <li>Gson provides default serialization and deserialization for Enums, {@link Map},
|
||||
* {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date},
|
||||
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
|
||||
* to change the default representation, you can do so by registering a type adapter through
|
||||
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
|
||||
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
|
||||
* ignores the millisecond portion of the date during serialization. You can change
|
||||
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
|
||||
* {@link GsonBuilder#setDateFormat(String)}. </li>
|
||||
* <li>By default, Gson ignores the {@link org.mcteam.ancientgates.gson.annotations.Expose} annotation.
|
||||
* You can enable Gson to serialize/deserialize only those fields marked with this annotation
|
||||
* through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}. </li>
|
||||
* <li>By default, Gson ignores the {@link org.mcteam.ancientgates.gson.annotations.Since} annotation. You
|
||||
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.</li>
|
||||
* <li>The default field naming policy for the output Json is same as in Java. So, a Java class
|
||||
* field <code>versionNumber</code> will be output as <code>"versionNumber@quot;</code> in
|
||||
* Json. The same rules are applied for mapping incoming Json to the Java classes. You can
|
||||
* change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.</li>
|
||||
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
|
||||
* consideration for serialization and deserialization. You can change this behavior through
|
||||
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Gson() {
|
||||
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
|
||||
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
||||
false, DefaultTypeAdapters.getDefaultSerializers(),
|
||||
DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
|
||||
}
|
||||
|
||||
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
||||
FieldNamingStrategy2 fieldNamingPolicy, MappedObjectConstructor objectConstructor,
|
||||
boolean serializeNulls, ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||
boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) {
|
||||
this.serializationStrategy = serializationStrategy;
|
||||
this.deserializationStrategy = deserializationStrategy;
|
||||
this.fieldNamingPolicy = fieldNamingPolicy;
|
||||
this.objectConstructor = objectConstructor;
|
||||
this.serializeNulls = serializeNulls;
|
||||
this.serializers = serializers;
|
||||
this.deserializers = deserializers;
|
||||
this.generateNonExecutableJson = generateNonExecutableGson;
|
||||
this.htmlSafe = htmlSafe;
|
||||
this.prettyPrinting = prettyPrinting;
|
||||
}
|
||||
|
||||
private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy strategy) {
|
||||
return new ObjectNavigatorFactory(strategy, fieldNamingPolicy);
|
||||
}
|
||||
|
||||
private static ExclusionStrategy createExclusionStrategy(double version) {
|
||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||
strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
|
||||
strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
|
||||
strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
|
||||
if (version != VersionConstants.IGNORE_VERSIONS) {
|
||||
strategies.add(new VersionExclusionStrategy(version));
|
||||
}
|
||||
return new DisjunctionExclusionStrategy(strategies);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object into its equivalent representation as a tree of
|
||||
* {@link JsonElement}s. This method should be used when the specified object is not a generic
|
||||
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
|
||||
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
|
||||
* of Java. Note that this method works fine if the any of the object fields are of generic type,
|
||||
* just the object itself should not be of a generic type. If the object is of generic type, use
|
||||
* {@link #toJsonTree(Object, Type)} instead.
|
||||
*
|
||||
* @param src the object for which Json representation is to be created setting for Gson
|
||||
* @return Json representation of {@code src}.
|
||||
* @since 1.4
|
||||
*/
|
||||
public JsonElement toJsonTree(Object src) {
|
||||
if (src == null) {
|
||||
return JsonNull.createJsonNull();
|
||||
}
|
||||
return toJsonTree(src, src.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object, including those of generic types, into its
|
||||
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
|
||||
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
|
||||
* instead.
|
||||
*
|
||||
* @param src the object for which JSON representation is to be created
|
||||
* @param typeOfSrc The specific genericized type of src. You can obtain
|
||||
* this type by using the {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return Json representation of {@code src}
|
||||
* @since 1.4
|
||||
*/
|
||||
public JsonElement toJsonTree(Object src, Type typeOfSrc) {
|
||||
if (src == null) {
|
||||
return JsonNull.createJsonNull();
|
||||
}
|
||||
JsonSerializationContextDefault context = new JsonSerializationContextDefault(
|
||||
createDefaultObjectNavigatorFactory(serializationStrategy), serializeNulls, serializers);
|
||||
return context.serialize(src, typeOfSrc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object into its equivalent Json representation.
|
||||
* This method should be used when the specified object is not a generic type. This method uses
|
||||
* {@link Class#getClass()} to get the type for the specified object, but the
|
||||
* {@code getClass()} loses the generic type information because of the Type Erasure feature
|
||||
* of Java. Note that this method works fine if the any of the object fields are of generic type,
|
||||
* just the object itself should not be of a generic type. If the object is of generic type, use
|
||||
* {@link #toJson(Object, Type)} instead. If you want to write out the object to a
|
||||
* {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
|
||||
*
|
||||
* @param src the object for which Json representation is to be created setting for Gson
|
||||
* @return Json representation of {@code src}.
|
||||
*/
|
||||
public String toJson(Object src) {
|
||||
if (src == null) {
|
||||
return serializeNulls ? NULL_STRING : "";
|
||||
}
|
||||
return toJson(src, src.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object, including those of generic types, into its
|
||||
* equivalent Json representation. This method must be used if the specified object is a generic
|
||||
* type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
|
||||
* the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
|
||||
*
|
||||
* @param src the object for which JSON representation is to be created
|
||||
* @param typeOfSrc The specific genericized type of src. You can obtain
|
||||
* this type by using the {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return Json representation of {@code src}
|
||||
*/
|
||||
public String toJson(Object src, Type typeOfSrc) {
|
||||
StringWriter writer = new StringWriter();
|
||||
toJson(toJsonTree(src, typeOfSrc), writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object into its equivalent Json representation.
|
||||
* This method should be used when the specified object is not a generic type. This method uses
|
||||
* {@link Class#getClass()} to get the type for the specified object, but the
|
||||
* {@code getClass()} loses the generic type information because of the Type Erasure feature
|
||||
* of Java. Note that this method works fine if the any of the object fields are of generic type,
|
||||
* just the object itself should not be of a generic type. If the object is of generic type, use
|
||||
* {@link #toJson(Object, Type, Appendable)} instead.
|
||||
*
|
||||
* @param src the object for which Json representation is to be created setting for Gson
|
||||
* @param writer Writer to which the Json representation needs to be written
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
* @since 1.2
|
||||
*/
|
||||
public void toJson(Object src, Appendable writer) throws JsonIOException {
|
||||
try {
|
||||
if (src != null) {
|
||||
toJson(src, src.getClass(), writer);
|
||||
} else if (serializeNulls) {
|
||||
writeOutNullString(writer);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the specified object, including those of generic types, into its
|
||||
* equivalent Json representation. This method must be used if the specified object is a generic
|
||||
* type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
|
||||
*
|
||||
* @param src the object for which JSON representation is to be created
|
||||
* @param typeOfSrc The specific genericized type of src. You can obtain
|
||||
* this type by using the {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @param writer Writer to which the Json representation of src needs to be written.
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
* @since 1.2
|
||||
*/
|
||||
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
|
||||
JsonElement jsonElement = toJsonTree(src, typeOfSrc);
|
||||
toJson(jsonElement, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
|
||||
* {@code writer}.
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
*/
|
||||
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
|
||||
toJson(toJsonTree(src, typeOfSrc), writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
||||
*
|
||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||
* @return JSON String representation of the tree
|
||||
* @since 1.4
|
||||
*/
|
||||
public String toJson(JsonElement jsonElement) {
|
||||
StringWriter writer = new StringWriter();
|
||||
toJson(jsonElement, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
|
||||
*
|
||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||
* @param writer Writer to which the Json representation needs to be written
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
* @since 1.4
|
||||
*/
|
||||
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
|
||||
try {
|
||||
if (generateNonExecutableJson) {
|
||||
writer.append(JSON_NON_EXECUTABLE_PREFIX);
|
||||
}
|
||||
JsonWriter jsonWriter = new JsonWriter(Streams.writerForAppendable(writer));
|
||||
if (prettyPrinting) {
|
||||
jsonWriter.setIndent(" ");
|
||||
}
|
||||
toJson(jsonElement, jsonWriter);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the JSON for {@code jsonElement} to {@code writer}.
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
*/
|
||||
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
try {
|
||||
Streams.write(jsonElement, serializeNulls, writer);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the specified Json into an object of the specified class. It is not
|
||||
* suitable to use if the specified class is a generic type since it will not have the generic
|
||||
* type information because of the Type Erasure feature of Java. Therefore, this method should not
|
||||
* be used if the desired type is a generic type. Note that this method works fine if the any of
|
||||
* the fields of the specified object are generics, just the object itself should not be a
|
||||
* generic type. For the cases when the object is of generic type, invoke
|
||||
* {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
|
||||
* a String, use {@link #fromJson(Reader, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the string from which the object is to be deserialized
|
||||
* @param classOfT the class of T
|
||||
* @return an object of type T from the string
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* classOfT
|
||||
*/
|
||||
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
|
||||
Object object = fromJson(json, (Type) classOfT);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the specified Json into an object of the specified type. This method
|
||||
* is useful if the specified object is a generic type. For non-generic objects, use
|
||||
* {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
|
||||
* a String, use {@link #fromJson(Reader, Type)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the string from which the object is to be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the string
|
||||
* @throws JsonParseException if json is not a valid representation for an object of type typeOfT
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
StringReader reader = new StringReader(json);
|
||||
T target = (T) fromJson(reader, typeOfT);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified reader into an object of the
|
||||
* specified class. It is not suitable to use if the specified class is a generic type since it
|
||||
* will not have the generic type information because of the Type Erasure feature of Java.
|
||||
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
||||
* this method works fine if the any of the fields of the specified object are generics, just the
|
||||
* object itself should not be a generic type. For the cases when the object is of generic type,
|
||||
* invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
|
||||
* {@link Reader}, use {@link #fromJson(String, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the reader producing the Json from which the object is to be deserialized.
|
||||
* @param classOfT the class of T
|
||||
* @return an object of type T from the string
|
||||
* @throws JsonIOException if there was a problem reading from the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* @since 1.2
|
||||
*/
|
||||
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
|
||||
JsonReader jsonReader = new JsonReader(json);
|
||||
Object object = fromJson(jsonReader, classOfT);
|
||||
assertFullConsumption(object, jsonReader);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified reader into an object of the
|
||||
* specified type. This method is useful if the specified object is a generic type. For
|
||||
* non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
|
||||
* String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the reader producing Json from which the object is to be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the json
|
||||
* @throws JsonIOException if there was a problem reading from the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* @since 1.2
|
||||
*/
|
||||
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
JsonReader jsonReader = new JsonReader(json);
|
||||
T object = this.<T>fromJson(jsonReader, typeOfT);
|
||||
assertFullConsumption(object, jsonReader);
|
||||
return object;
|
||||
}
|
||||
|
||||
private static void assertFullConsumption(Object obj, JsonReader reader) {
|
||||
try {
|
||||
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
|
||||
throw new JsonIOException("JSON document was not fully consumed.");
|
||||
}
|
||||
} catch (MalformedJsonException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next JSON value from {@code reader} and convert it to an object
|
||||
* of type {@code typeOfT}.
|
||||
* Since Type is not parameterized by T, this method is type unsafe and should be used carefully
|
||||
*
|
||||
* @throws JsonIOException if there was a problem writing to the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
boolean oldLenient = reader.isLenient();
|
||||
reader.setLenient(true);
|
||||
try {
|
||||
JsonElement root = Streams.parse(reader);
|
||||
return (T) fromJson(root, typeOfT);
|
||||
} finally {
|
||||
reader.setLenient(oldLenient);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified parse tree into an object of the
|
||||
* specified type. It is not suitable to use if the specified class is a generic type since it
|
||||
* will not have the generic type information because of the Type Erasure feature of Java.
|
||||
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
||||
* this method works fine if the any of the fields of the specified object are generics, just the
|
||||
* object itself should not be a generic type. For the cases when the object is of generic type,
|
||||
* invoke {@link #fromJson(JsonElement, Type)}.
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||
* be deserialized
|
||||
* @param classOfT The class of T
|
||||
* @return an object of type T from the json
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
|
||||
* @since 1.3
|
||||
*/
|
||||
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
|
||||
Object object = fromJson(json, (Type) classOfT);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified parse tree into an object of the
|
||||
* specified type. This method is useful if the specified object is a generic type. For
|
||||
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||
* be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link org.mcteam.ancientgates.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the json
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
|
||||
* @since 1.3
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
JsonDeserializationContext context = new JsonDeserializationContextDefault(
|
||||
createDefaultObjectNavigatorFactory(deserializationStrategy), deserializers,
|
||||
objectConstructor);
|
||||
T target = (T) context.deserialize(json, typeOfT);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the {@link #NULL_STRING} to the {@code writer} object.
|
||||
*
|
||||
* @param writer the object to append the null value to
|
||||
*/
|
||||
private void writeOutNullString(Appendable writer) throws IOException {
|
||||
writer.append(NULL_STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("{")
|
||||
.append("serializeNulls:").append(serializeNulls)
|
||||
.append(",serializers:").append(serializers)
|
||||
.append(",deserializers:").append(deserializers)
|
||||
|
||||
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
|
||||
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
|
||||
// just a utility class around instance creators, and its toString() only displays them.
|
||||
.append(",instanceCreators:").append(objectConstructor)
|
||||
.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
571
src/org/mcteam/ancientgates/gson/GsonBuilder.java
Normal file
571
src/org/mcteam/ancientgates/gson/GsonBuilder.java
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mcteam.ancientgates.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
|
||||
* options other than the default. For {@link Gson} with default configuration, it is simpler to
|
||||
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
|
||||
* various configuration methods, and finally calling create.</p>
|
||||
*
|
||||
* <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
|
||||
* instance:
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
|
||||
* .serializeNulls()
|
||||
* .setDateFormat(DateFormat.LONG)
|
||||
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
|
||||
* .setPrettyPrinting()
|
||||
* .setVersion(1.0)
|
||||
* .create();
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>NOTE: the order of invocation of configuration methods does not matter.</p>
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public final class GsonBuilder {
|
||||
private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
|
||||
new InnerClassExclusionStrategy();
|
||||
private static final ExposeAnnotationSerializationExclusionStrategy
|
||||
exposeAnnotationSerializationExclusionStrategy =
|
||||
new ExposeAnnotationSerializationExclusionStrategy();
|
||||
private static final ExposeAnnotationDeserializationExclusionStrategy
|
||||
exposeAnnotationDeserializationExclusionStrategy =
|
||||
new ExposeAnnotationDeserializationExclusionStrategy();
|
||||
|
||||
private final Collection<ExclusionStrategy> exclusionStrategies =
|
||||
new HashSet<ExclusionStrategy>();
|
||||
|
||||
private double ignoreVersionsAfter;
|
||||
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
|
||||
private boolean serializeInnerClasses;
|
||||
private boolean excludeFieldsWithoutExposeAnnotation;
|
||||
private LongSerializationPolicy longSerializationPolicy;
|
||||
private FieldNamingStrategy2 fieldNamingPolicy;
|
||||
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators;
|
||||
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
|
||||
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
|
||||
private boolean serializeNulls;
|
||||
private String datePattern;
|
||||
private int dateStyle;
|
||||
private int timeStyle;
|
||||
private boolean serializeSpecialFloatingPointValues;
|
||||
private boolean escapeHtmlChars;
|
||||
private boolean prettyPrinting;
|
||||
private boolean generateNonExecutableJson;
|
||||
|
||||
/**
|
||||
* Creates a GsonBuilder instance that can be used to build Gson with various configuration
|
||||
* settings. GsonBuilder follows the builder pattern, and it is typically used by first
|
||||
* invoking various configuration methods to set desired options, and finally calling
|
||||
* {@link #create()}.
|
||||
*/
|
||||
public GsonBuilder() {
|
||||
// add default exclusion strategies
|
||||
exclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
|
||||
exclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
|
||||
|
||||
// setup default values
|
||||
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
|
||||
serializeInnerClasses = true;
|
||||
prettyPrinting = false;
|
||||
escapeHtmlChars = true;
|
||||
modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY;
|
||||
excludeFieldsWithoutExposeAnnotation = false;
|
||||
longSerializationPolicy = LongSerializationPolicy.DEFAULT;
|
||||
fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY;
|
||||
instanceCreators = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
|
||||
serializers = new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
||||
deserializers = new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
|
||||
serializeNulls = false;
|
||||
dateStyle = DateFormat.DEFAULT;
|
||||
timeStyle = DateFormat.DEFAULT;
|
||||
serializeSpecialFloatingPointValues = false;
|
||||
generateNonExecutableJson = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to enable versioning support.
|
||||
*
|
||||
* @param ignoreVersionsAfter any field or type marked with a version higher than this value
|
||||
* are ignored during serialization or deserialization.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder setVersion(double ignoreVersionsAfter) {
|
||||
this.ignoreVersionsAfter = ignoreVersionsAfter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
|
||||
* Gson will exclude all fields marked transient or static. This method will override that
|
||||
* behavior.
|
||||
*
|
||||
* @param modifiers the field modifiers. You must use the modifiers specified in the
|
||||
* {@link java.lang.reflect.Modifier} class. For example,
|
||||
* {@link java.lang.reflect.Modifier#TRANSIENT},
|
||||
* {@link java.lang.reflect.Modifier#STATIC}.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
|
||||
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
|
||||
* special text. This prevents attacks from third-party sites through script sourcing. See
|
||||
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
|
||||
* for details.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder generateNonExecutableJson() {
|
||||
this.generateNonExecutableJson = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to exclude all fields from consideration for serialization or deserialization
|
||||
* that do not have the {@link org.mcteam.ancientgates.gson.annotations.Expose} annotation.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
|
||||
excludeFieldsWithoutExposeAnnotation = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null
|
||||
* during serialization.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.2
|
||||
*/
|
||||
public GsonBuilder serializeNulls() {
|
||||
this.serializeNulls = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to exclude inner classes during serialization.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder disableInnerClassSerialization() {
|
||||
serializeInnerClasses = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
|
||||
* objects.
|
||||
*
|
||||
* @param serializationPolicy the particular policy to use for serializing longs.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
|
||||
this.longSerializationPolicy = serializationPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to apply a specific naming policy to an object's field during serialization
|
||||
* and deserialization.
|
||||
*
|
||||
* @param namingConvention the JSON field naming convention to use for serialization and
|
||||
* deserialization.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
|
||||
return setFieldNamingStrategy(namingConvention.getFieldNamingPolicy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to apply a specific naming policy strategy to an object's field during
|
||||
* serialization and deserialization.
|
||||
*
|
||||
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
|
||||
return setFieldNamingStrategy(new FieldNamingStrategy2Adapter(fieldNamingStrategy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to apply a specific naming policy strategy to an object's field during
|
||||
* serialization and deserialization.
|
||||
*
|
||||
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
GsonBuilder setFieldNamingStrategy(FieldNamingStrategy2 fieldNamingStrategy) {
|
||||
this.fieldNamingPolicy =
|
||||
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to apply a set of exclusion strategies during both serialization and
|
||||
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
|
||||
* This means that if one of the {@code strategies} suggests that a field (or class) should be
|
||||
* skipped then that field (or object) is skipped during serializaiton/deserialization.
|
||||
*
|
||||
* @param strategies the set of strategy object to apply during object (de)serialization.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.4
|
||||
*/
|
||||
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
|
||||
for (ExclusionStrategy strategy : strategies) {
|
||||
exclusionStrategies.add(strategy);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to output Json that fits in a page for pretty printing. This option only
|
||||
* affects Json serialization.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder setPrettyPrinting() {
|
||||
prettyPrinting = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Gson escapes HTML characters such as < > etc. Use this option to configure
|
||||
* Gson to pass-through HTML characters as is.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder disableHtmlEscaping() {
|
||||
this.escapeHtmlChars = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
|
||||
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
|
||||
* will be used to decide the serialization format.
|
||||
*
|
||||
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
|
||||
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
|
||||
* valid date and time patterns.</p>
|
||||
*
|
||||
* @param pattern the pattern that dates will be serialized/deserialized to/from
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.2
|
||||
*/
|
||||
public GsonBuilder setDateFormat(String pattern) {
|
||||
// TODO(Joel): Make this fail fast if it is an invalid date format
|
||||
this.datePattern = pattern;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
|
||||
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
|
||||
* invocation will be used to decide the serialization format.
|
||||
*
|
||||
* <p>Note that this style value should be one of the predefined constants in the
|
||||
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
|
||||
* information on the valid style constants.</p>
|
||||
*
|
||||
* @param style the predefined date style that date objects will be serialized/deserialized
|
||||
* to/from
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.2
|
||||
*/
|
||||
public GsonBuilder setDateFormat(int style) {
|
||||
this.dateStyle = style;
|
||||
this.datePattern = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
|
||||
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
|
||||
* invocation will be used to decide the serialization format.
|
||||
*
|
||||
* <p>Note that this style value should be one of the predefined constants in the
|
||||
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
|
||||
* information on the valid style constants.</p>
|
||||
*
|
||||
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
|
||||
* to/from
|
||||
* @param timeStyle the predefined style for the time portion of the date objects
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.2
|
||||
*/
|
||||
public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
|
||||
this.dateStyle = dateStyle;
|
||||
this.timeStyle = timeStyle;
|
||||
this.datePattern = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson for custom serialization or deserialization. This method combines the
|
||||
* registration of an {@link InstanceCreator}, {@link JsonSerializer}, and a
|
||||
* {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
|
||||
* all the required interfaces for custom serialization with Gson. If an instance creator,
|
||||
* serializer or deserializer was previously registered for the specified {@code type}, it is
|
||||
* overwritten.
|
||||
*
|
||||
* @param type the type definition for the type adapter being registered
|
||||
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
|
||||
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
|
||||
Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|
||||
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
|
||||
if (typeAdapter instanceof InstanceCreator<?>) {
|
||||
registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonSerializer<?>) {
|
||||
registerSerializer(type, (JsonSerializer<?>) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonDeserializer<?>) {
|
||||
registerDeserializer(type, (JsonDeserializer<?>) typeAdapter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to use a custom {@link InstanceCreator} for the specified type. If an instance
|
||||
* creator was previously registered for the specified class, it is overwritten. Since this method
|
||||
* takes a type instead of a Class object, it can be used to register a specific handler for a
|
||||
* generic type corresponding to a raw type.
|
||||
*
|
||||
* @param <T> the type for which instance creator is being registered
|
||||
* @param typeOfT The Type definition for T
|
||||
* @param instanceCreator the instance creator for T
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
private <T> GsonBuilder registerInstanceCreator(Type typeOfT,
|
||||
InstanceCreator<? extends T> instanceCreator) {
|
||||
instanceCreators.register(typeOfT, instanceCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to use a custom JSON serializer for the specified type. You should use this
|
||||
* method if you want to register different serializers for different generic types corresponding
|
||||
* to a raw type.
|
||||
*
|
||||
* @param <T> the type for which the serializer is being registered
|
||||
* @param typeOfT The type definition for T
|
||||
* @param serializer the custom serializer
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
private <T> GsonBuilder registerSerializer(Type typeOfT, final JsonSerializer<T> serializer) {
|
||||
serializers.register(typeOfT, serializer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to use a custom JSON deserializer for the specified type. You should use this
|
||||
* method if you want to register different deserializers for different generic types
|
||||
* corresponding to a raw type.
|
||||
*
|
||||
* @param <T> the type for which the deserializer is being registered
|
||||
* @param typeOfT The type definition for T
|
||||
* @param deserializer the custom deserializer
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
private <T> GsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer<T> deserializer) {
|
||||
deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper<T>(deserializer));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
|
||||
* This method combines the registration of an {@link InstanceCreator}, {@link JsonSerializer},
|
||||
* and a {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter}
|
||||
* implements all the required interfaces for custom serialization with Gson.
|
||||
* If an instance creator, serializer or deserializer was previously registered for the specified
|
||||
* type hierarchy, it is overwritten. If an instance creator, serializer or deserializer is
|
||||
* registered for a specific type in the type hierarchy, it will be invoked instead of the one
|
||||
* registered for the type hierarchy.
|
||||
*
|
||||
* @param baseType the class definition for the type adapter being registered for the base class
|
||||
* or interface
|
||||
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
|
||||
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.7
|
||||
*/
|
||||
GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
|
||||
Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|
||||
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
|
||||
if (typeAdapter instanceof InstanceCreator<?>) {
|
||||
registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator<?>) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonSerializer<?>) {
|
||||
registerSerializerForTypeHierarchy(baseType, (JsonSerializer<?>) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonDeserializer<?>) {
|
||||
registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer<?>) typeAdapter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private <T> GsonBuilder registerInstanceCreatorForTypeHierarchy(Class<?> classOfT,
|
||||
InstanceCreator<? extends T> instanceCreator) {
|
||||
instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
private <T> GsonBuilder registerSerializerForTypeHierarchy(Class<?> classOfT,
|
||||
final JsonSerializer<T> serializer) {
|
||||
serializers.registerForTypeHierarchy(classOfT, serializer);
|
||||
return this;
|
||||
}
|
||||
|
||||
private <T> GsonBuilder registerDeserializerForTypeHierarchy(Class<?> classOfT,
|
||||
JsonDeserializer<T> deserializer) {
|
||||
deserializers.registerForTypeHierarchy(classOfT,
|
||||
new JsonDeserializerExceptionWrapper<T>(deserializer));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
|
||||
* special double values (NaN, Infinity, -Infinity). However,
|
||||
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
|
||||
* specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
|
||||
* values. Moreover, most JavaScript engines will accept these special values in JSON without
|
||||
* problem. So, at a practical level, it makes sense to accept these values as valid JSON even
|
||||
* though JSON specification disallows them.
|
||||
*
|
||||
* <p>Gson always accepts these special values during deserialization. However, it outputs
|
||||
* strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
|
||||
* {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
|
||||
* {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
|
||||
* will throw an {@link IllegalArgumentException}. This method provides a way to override the
|
||||
* default behavior when you know that the JSON receiver will be able to handle these special
|
||||
* values.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.3
|
||||
*/
|
||||
public GsonBuilder serializeSpecialFloatingPointValues() {
|
||||
this.serializeSpecialFloatingPointValues = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Gson} instance based on the current configuration. This method is free of
|
||||
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
|
||||
*
|
||||
* @return an instance of Gson configured with the options currently set in this builder
|
||||
*/
|
||||
public Gson create() {
|
||||
List<ExclusionStrategy> serializationStrategies =
|
||||
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||
List<ExclusionStrategy> deserializationStrategies =
|
||||
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||
|
||||
serializationStrategies.add(modifierBasedExclusionStrategy);
|
||||
deserializationStrategies.add(modifierBasedExclusionStrategy);
|
||||
|
||||
if (!serializeInnerClasses) {
|
||||
serializationStrategies.add(innerClassExclusionStrategy);
|
||||
deserializationStrategies.add(innerClassExclusionStrategy);
|
||||
}
|
||||
if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) {
|
||||
serializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter));
|
||||
deserializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter));
|
||||
}
|
||||
if (excludeFieldsWithoutExposeAnnotation) {
|
||||
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
|
||||
deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
|
||||
}
|
||||
ExclusionStrategy serializationExclusionStrategy =
|
||||
new DisjunctionExclusionStrategy(serializationStrategies);
|
||||
ExclusionStrategy deserializationExclusionStrategy =
|
||||
new DisjunctionExclusionStrategy(deserializationStrategies);
|
||||
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
|
||||
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
|
||||
customDeserializers);
|
||||
|
||||
customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers(
|
||||
serializeSpecialFloatingPointValues, longSerializationPolicy));
|
||||
|
||||
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers());
|
||||
|
||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
|
||||
instanceCreators.copyOf();
|
||||
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
|
||||
|
||||
customSerializers.makeUnmodifiable();
|
||||
customDeserializers.makeUnmodifiable();
|
||||
instanceCreators.makeUnmodifiable();
|
||||
|
||||
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
|
||||
|
||||
Gson gson = new Gson(serializationExclusionStrategy, deserializationExclusionStrategy,
|
||||
fieldNamingPolicy, objConstructor, serializeNulls, customSerializers,
|
||||
customDeserializers, generateNonExecutableJson, escapeHtmlChars, prettyPrinting);
|
||||
return gson;
|
||||
}
|
||||
|
||||
private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) {
|
||||
DefaultDateTypeAdapter dateTypeAdapter = null;
|
||||
if (datePattern != null && !"".equals(datePattern.trim())) {
|
||||
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
|
||||
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
|
||||
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
|
||||
}
|
||||
|
||||
if (dateTypeAdapter != null) {
|
||||
if (!serializers.hasSpecificHandlerFor(Date.class)) {
|
||||
serializers.register(Date.class, dateTypeAdapter);
|
||||
}
|
||||
if (!deserializers.hasSpecificHandlerFor(Date.class)) {
|
||||
deserializers.register(Date.class, dateTypeAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Strategy for excluding inner classes.
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
class InnerClassExclusionStrategy implements ExclusionStrategy {
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return isInnerClass(f.getDeclaredClass());
|
||||
}
|
||||
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return isInnerClass(clazz);
|
||||
}
|
||||
|
||||
private boolean isInnerClass(Class<?> clazz) {
|
||||
return clazz.isMemberClass() && !isStatic(clazz);
|
||||
}
|
||||
|
||||
private boolean isStatic(Class<?> clazz) {
|
||||
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
||||
}
|
||||
}
|
92
src/org/mcteam/ancientgates/gson/InstanceCreator.java
Normal file
92
src/org/mcteam/ancientgates/gson/InstanceCreator.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* This interface is implemented to create instances of a class that does not define a no-args
|
||||
* constructor. If you can modify the class, you should instead add a private, or public
|
||||
* no-args constructor. However, that is not possible for library classes, such as JDK classes, or
|
||||
* a third-party library that you do not have source-code of. In such cases, you should define an
|
||||
* instance creator for the class. Implementations of this interface should be registered with
|
||||
* {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
|
||||
* them.
|
||||
* <p>Let us look at an example where defining an InstanceCreator might be useful. The
|
||||
* {@code Id} class defined below does not have a default no-args constructor.</p>
|
||||
*
|
||||
* <pre>
|
||||
* public class Id<T> {
|
||||
* private final Class<T> clazz;
|
||||
* private final long value;
|
||||
* public Id(Class<T> clazz, long value) {
|
||||
* this.clazz = clazz;
|
||||
* this.value = value;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>If Gson encounters an object of type {@code Id} during deserialization, it will throw an
|
||||
* exception. The easiest way to solve this problem will be to add a (public or private) no-args
|
||||
* constructor as follows:</p>
|
||||
*
|
||||
* <pre>
|
||||
* private Id() {
|
||||
* this(Object.class, 0L);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>However, let us assume that the developer does not have access to the source-code of the
|
||||
* {@code Id} class, or does not want to define a no-args constructor for it. The developer
|
||||
* can solve this problem by defining an {@code InstanceCreator} for {@code Id}:</p>
|
||||
*
|
||||
* <pre>
|
||||
* class IdInstanceCreator implements InstanceCreator<Id> {
|
||||
* public Id createInstance(Type type) {
|
||||
* return new Id(Object.class, 0L);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Note that it does not matter what the fields of the created instance contain since Gson will
|
||||
* overwrite them with the deserialized values specified in Json. You should also ensure that a
|
||||
* <i>new</i> object is returned, not a common object since its fields will be overwritten.
|
||||
* The developer will need to register {@code IdInstanceCreator} with Gson as follows:</p>
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> the type of object that will be created by this implementation.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public interface InstanceCreator<T> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during deserialization to create an instance of the
|
||||
* specified type. The fields of the returned instance are overwritten with the data present
|
||||
* in the Json. Since the prior contents of the object are destroyed and overwritten, do not
|
||||
* return an instance that is useful elsewhere. In particular, do not return a common instance,
|
||||
* always use {@code new} to create a new instance.
|
||||
*
|
||||
* @param type the parameterized T represented as a {@link Type}.
|
||||
* @return a default object instance of type T.
|
||||
*/
|
||||
public T createInstance(Type type);
|
||||
}
|
51
src/org/mcteam/ancientgates/gson/JavaFieldNamingPolicy.java
Normal file
51
src/org/mcteam/ancientgates/gson/JavaFieldNamingPolicy.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A simple implementation of the {@link FieldNamingStrategy2} interface such that it does not
|
||||
* perform any string translation of the incoming field name.
|
||||
*
|
||||
* <p>The following is an example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* class IntWrapper {
|
||||
* public int integerField = 0;
|
||||
* }
|
||||
*
|
||||
* JavaFieldNamingPolicy policy = new JavaFieldNamingPolicy();
|
||||
* String translatedFieldName =
|
||||
* policy.translateName(IntWrapper.class.getField("integerField"));
|
||||
*
|
||||
* assert("integerField".equals(translatedFieldName));
|
||||
* </pre>
|
||||
*
|
||||
* <p>This is the default {@link FieldNamingStrategy2} used by Gson.</p>
|
||||
*
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class JavaFieldNamingPolicy extends RecursiveFieldNamingPolicy {
|
||||
|
||||
@Override
|
||||
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
|
||||
return target;
|
||||
}
|
||||
}
|
312
src/org/mcteam/ancientgates/gson/JsonArray.java
Normal file
312
src/org/mcteam/ancientgates/gson/JsonArray.java
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
|
||||
* which can be of a different type. This is an ordered list, meaning that the order in which
|
||||
* elements are added is preserved.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
|
||||
private final List<JsonElement> elements;
|
||||
|
||||
/**
|
||||
* Creates an empty JsonArray.
|
||||
*/
|
||||
public JsonArray() {
|
||||
elements = new ArrayList<JsonElement>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to self.
|
||||
*
|
||||
* @param element the element that needs to be added to the array.
|
||||
*/
|
||||
public void add(JsonElement element) {
|
||||
if (element == null) {
|
||||
element = JsonNull.createJsonNull();
|
||||
}
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all the elements of the specified array to self.
|
||||
*
|
||||
* @param array the array whose elements need to be added to the array.
|
||||
*/
|
||||
public void addAll(JsonArray array) {
|
||||
elements.addAll(array.elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the elements of the array.
|
||||
*/
|
||||
void reverse() {
|
||||
Collections.reverse(elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the array.
|
||||
*
|
||||
* @return the number of elements in the array.
|
||||
*/
|
||||
public int size() {
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to navigate the elemetns of the array. Since the array is an ordered list,
|
||||
* the iterator navigates the elements in the order they were inserted.
|
||||
*
|
||||
* @return an iterator to navigate the elements of the array.
|
||||
*/
|
||||
public Iterator<JsonElement> iterator() {
|
||||
return elements.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ith element of the array.
|
||||
*
|
||||
* @param i the index of the element that is being sought.
|
||||
* @return the element present at the ith index.
|
||||
* @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
|
||||
* {@link #size()} of the array.
|
||||
*/
|
||||
public JsonElement get(int i) {
|
||||
return elements.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a {@link Number} if it contains a single element.
|
||||
*
|
||||
* @return get this element as a number if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid Number.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public Number getAsNumber() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsNumber();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a {@link String} if it contains a single element.
|
||||
*
|
||||
* @return get this element as a String if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid String.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public String getAsString() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsString();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a double if it contains a single element.
|
||||
*
|
||||
* @return get this element as a double if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid double.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public double getAsDouble() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsDouble();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a {@link BigDecimal} if it contains a single element.
|
||||
*
|
||||
* @return get this element as a {@link BigDecimal} if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
||||
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
* @since 1.2
|
||||
*/
|
||||
@Override
|
||||
public BigDecimal getAsBigDecimal() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsBigDecimal();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a {@link BigInteger} if it contains a single element.
|
||||
*
|
||||
* @return get this element as a {@link BigInteger} if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
||||
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
* @since 1.2
|
||||
*/
|
||||
@Override
|
||||
public BigInteger getAsBigInteger() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsBigInteger();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a float if it contains a single element.
|
||||
*
|
||||
* @return get this element as a float if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid float.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public float getAsFloat() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsFloat();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a long if it contains a single element.
|
||||
*
|
||||
* @return get this element as a long if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid long.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public long getAsLong() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsLong();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as an integer if it contains a single element.
|
||||
*
|
||||
* @return get this element as an integer if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid integer.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsInt();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getAsByte() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsByte();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getAsCharacter() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsCharacter();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a primitive short if it contains a single element.
|
||||
*
|
||||
* @return get this element as a primitive short if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid short.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public short getAsShort() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsShort();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as a boolean if it contains a single element.
|
||||
*
|
||||
* @return get this element as a boolean if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid boolean.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsBoolean();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* convenience method to get this array as an Object if it contains a single element.
|
||||
*
|
||||
* @return get this element as an Object if it is single element array.
|
||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||
* is not a valid Object.
|
||||
* @throws IllegalStateException if the array has more than one element.
|
||||
*/
|
||||
@Override
|
||||
Object getAsObject() {
|
||||
if (elements.size() == 1) {
|
||||
return elements.get(0).getAsObject();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toString(Appendable sb, Escaper escaper) throws IOException {
|
||||
sb.append('[');
|
||||
boolean first = true;
|
||||
for (JsonElement element : elements) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(',');
|
||||
}
|
||||
element.toString(sb, escaper);
|
||||
}
|
||||
sb.append(']');
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* A visitor that populates fields of an object with data from its equivalent
|
||||
* JSON representation
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class JsonArrayDeserializationVisitor<T> extends JsonDeserializationVisitor<T> {
|
||||
|
||||
JsonArrayDeserializationVisitor(JsonArray jsonArray, Type arrayType,
|
||||
ObjectNavigatorFactory factory, ObjectConstructor objectConstructor,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||
JsonDeserializationContext context) {
|
||||
super(jsonArray, arrayType, factory, objectConstructor, deserializers, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T constructTarget() {
|
||||
|
||||
TypeInfo typeInfo = new TypeInfo(targetType);
|
||||
|
||||
if (!json.isJsonArray()) {
|
||||
throw new JsonParseException("Expecting array found: " + json);
|
||||
}
|
||||
JsonArray jsonArray = json.getAsJsonArray();
|
||||
if (typeInfo.isArray()) {
|
||||
TypeInfoArray arrayTypeInfo = TypeInfoFactory.getTypeInfoForArray(targetType);
|
||||
// We know that we are getting back an array of the required type, so
|
||||
// this typecasting is safe.
|
||||
return (T) objectConstructor.constructArray(arrayTypeInfo.getSecondLevelType(),
|
||||
jsonArray.size());
|
||||
}
|
||||
// is a collection
|
||||
return (T) objectConstructor.construct(typeInfo.getRawClass());
|
||||
}
|
||||
|
||||
public void visitArray(Object array, Type arrayType) {
|
||||
if (!json.isJsonArray()) {
|
||||
throw new JsonParseException("Expecting array found: " + json);
|
||||
}
|
||||
JsonArray jsonArray = json.getAsJsonArray();
|
||||
TypeInfoArray arrayTypeInfo = TypeInfoFactory.getTypeInfoForArray(arrayType);
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JsonElement jsonChild = jsonArray.get(i);
|
||||
Object child;
|
||||
|
||||
if (jsonChild == null || jsonChild.isJsonNull()) {
|
||||
child = null;
|
||||
} else if (jsonChild instanceof JsonObject) {
|
||||
child = visitChildAsObject(arrayTypeInfo.getComponentRawType(), jsonChild);
|
||||
} else if (jsonChild instanceof JsonArray) {
|
||||
child = visitChildAsArray(arrayTypeInfo.getSecondLevelType(), jsonChild.getAsJsonArray());
|
||||
} else if (jsonChild instanceof JsonPrimitive) {
|
||||
child = visitChildAsObject(arrayTypeInfo.getComponentRawType(),
|
||||
jsonChild.getAsJsonPrimitive());
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
Array.set(array, i, child);
|
||||
}
|
||||
}
|
||||
|
||||
// We should not implement any other method from Visitor interface since
|
||||
// all other methods should be invoked on JsonObjectDeserializationVisitor
|
||||
// instead.
|
||||
|
||||
public void startVisitingObject(Object node) {
|
||||
throw new JsonParseException("Expecting array but found object: " + node);
|
||||
}
|
||||
|
||||
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
|
||||
throw new JsonParseException("Expecting array but found array field " + f.getName() + ": "
|
||||
+ obj);
|
||||
}
|
||||
|
||||
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
|
||||
throw new JsonParseException("Expecting array but found object field " + f.getName() + ": "
|
||||
+ obj);
|
||||
}
|
||||
|
||||
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField, Object parent) {
|
||||
throw new JsonParseException("Expecting array but found field " + f.getName() + ": "
|
||||
+ parent);
|
||||
}
|
||||
|
||||
public void visitPrimitive(Object primitive) {
|
||||
throw new JsonParseException(
|
||||
"Type information is unavailable, and the target is not a primitive: " + json);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Context for deserialization that is passed to a custom deserializer during invocation of its
|
||||
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
|
||||
* method.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public interface JsonDeserializationContext {
|
||||
|
||||
/**
|
||||
* Invokes default deserialization on the specified object. It should never be invoked on
|
||||
* the element received as a parameter of the
|
||||
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
|
||||
* so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
|
||||
|
||||
* @param json the parse tree.
|
||||
* @param typeOfT type of the expected return value.
|
||||
* @param <T> The type of the deserialized object.
|
||||
* @return An object of type typeOfT.
|
||||
* @throws JsonParseException if the parse tree does not contain expected data.
|
||||
*/
|
||||
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* implementation of a deserialization context for Gson
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
final class JsonDeserializationContextDefault implements JsonDeserializationContext {
|
||||
|
||||
private final ObjectNavigatorFactory navigatorFactory;
|
||||
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
|
||||
private final MappedObjectConstructor objectConstructor;
|
||||
|
||||
JsonDeserializationContextDefault(ObjectNavigatorFactory navigatorFactory,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||
MappedObjectConstructor objectConstructor) {
|
||||
this.navigatorFactory = navigatorFactory;
|
||||
this.deserializers = deserializers;
|
||||
this.objectConstructor = objectConstructor;
|
||||
}
|
||||
|
||||
ObjectConstructor getObjectConstructor() {
|
||||
return objectConstructor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
|
||||
if (json == null || json.isJsonNull()) {
|
||||
return null;
|
||||
} else if (json.isJsonArray()) {
|
||||
return (T) fromJsonArray(typeOfT, json.getAsJsonArray(), this);
|
||||
} else if (json.isJsonObject()) {
|
||||
return (T) fromJsonObject(typeOfT, json.getAsJsonObject(), this);
|
||||
} else if (json.isJsonPrimitive()) {
|
||||
return (T) fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this);
|
||||
} else {
|
||||
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>(
|
||||
jsonArray, arrayType, navigatorFactory, objectConstructor, deserializers, context);
|
||||
ObjectNavigator on = navigatorFactory.create(new ObjectTypePair(null, arrayType, true));
|
||||
on.accept(visitor);
|
||||
return visitor.getTarget();
|
||||
}
|
||||
|
||||
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
|
||||
jsonObject, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
|
||||
ObjectNavigator on = navigatorFactory.create(new ObjectTypePair(null, typeOfT, true));
|
||||
on.accept(visitor);
|
||||
return visitor.getTarget();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
|
||||
json, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
|
||||
ObjectNavigator on =
|
||||
navigatorFactory.create(new ObjectTypePair(json.getAsObject(), typeOfT, true));
|
||||
on.accept(visitor);
|
||||
Object target = visitor.getTarget();
|
||||
return (T) target;
|
||||
}
|
||||
}
|
112
src/org/mcteam/ancientgates/gson/JsonDeserializationVisitor.java
Normal file
112
src/org/mcteam/ancientgates/gson/JsonDeserializationVisitor.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mcteam.ancientgates.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Abstract data value container for the {@link ObjectNavigator.Visitor}
|
||||
* implementations. This class exposes the {@link #getTarget()} method
|
||||
* which returns the class that was visited by this object.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor {
|
||||
|
||||
protected final ObjectNavigatorFactory factory;
|
||||
protected final ObjectConstructor objectConstructor;
|
||||
protected final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
|
||||
protected T target;
|
||||
protected final JsonElement json;
|
||||
protected final Type targetType;
|
||||
protected final JsonDeserializationContext context;
|
||||
protected boolean constructed;
|
||||
|
||||
public JsonDeserializationVisitor(JsonElement json, Type targetType,
|
||||
ObjectNavigatorFactory factory, ObjectConstructor objectConstructor,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||
JsonDeserializationContext context) {
|
||||
Preconditions.checkNotNull(json);
|
||||
this.targetType = targetType;
|
||||
this.factory = factory;
|
||||
this.objectConstructor = objectConstructor;
|
||||
this.deserializers = deserializers;
|
||||
this.json = json;
|
||||
this.context = context;
|
||||
this.constructed = false;
|
||||
}
|
||||
|
||||
public T getTarget() {
|
||||
if (!constructed) {
|
||||
target = constructTarget();
|
||||
constructed = true;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
protected abstract T constructTarget();
|
||||
|
||||
public void start(ObjectTypePair node) {
|
||||
}
|
||||
|
||||
public void end(ObjectTypePair node) {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
|
||||
Pair<JsonDeserializer<?>, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
|
||||
if (pair == null) {
|
||||
return false;
|
||||
}
|
||||
Object value = invokeCustomDeserializer(json, pair);
|
||||
target = (T) value;
|
||||
constructed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Object invokeCustomDeserializer(JsonElement element,
|
||||
Pair<JsonDeserializer<?>, ObjectTypePair> pair) {
|
||||
if (element == null || element.isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
Type objType = pair.second.type;
|
||||
return (pair.first).deserialize(element, objType, context);
|
||||
}
|
||||
|
||||
final Object visitChildAsObject(Type childType, JsonElement jsonChild) {
|
||||
JsonDeserializationVisitor<?> childVisitor =
|
||||
new JsonObjectDeserializationVisitor<Object>(jsonChild, childType,
|
||||
factory, objectConstructor, deserializers, context);
|
||||
return visitChild(childType, childVisitor);
|
||||
}
|
||||
|
||||
final Object visitChildAsArray(Type childType, JsonArray jsonChild) {
|
||||
JsonDeserializationVisitor<?> childVisitor =
|
||||
new JsonArrayDeserializationVisitor<Object>(jsonChild.getAsJsonArray(), childType,
|
||||
factory, objectConstructor, deserializers, context);
|
||||
return visitChild(childType, childVisitor);
|
||||
}
|
||||
|
||||
private Object visitChild(Type type, JsonDeserializationVisitor<?> childVisitor) {
|
||||
ObjectNavigator on = factory.create(new ObjectTypePair(null, type, false));
|
||||
on.accept(childVisitor);
|
||||
// the underlying object may have changed during the construction phase
|
||||
// This happens primarily because of custom deserializers
|
||||
return childVisitor.getTarget();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user