Initial commit
This commit is contained in:
commit
e55d0cfd5e
2
.checkstyle
Normal file
2
.checkstyle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<fileset-config file-format-version="1.0.0"/>
|
25
.classpath
Normal file
25
.classpath
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-collections-3.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-logging.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-pool-1.2.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/nanocontainer-1.0-beta-3.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/picocontainer-1.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/javax.servlet.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/ant.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jasper-runtime.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jasper-compiler.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-el.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/ant-launcher.jar"/>
|
||||||
|
<classpathentry kind="lib" path="conf"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-codec-1.3.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-configuration-1.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/org.mortbay.jetty.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-httpclient-3.0-rc3.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/commons-lang-2.1.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/log4j-1.2.12.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/xstream-1.1.2.jar"/>
|
||||||
|
<classpathentry kind="output" path="build"/>
|
||||||
|
</classpath>
|
2
.cvsignore
Normal file
2
.cvsignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build
|
||||||
|
.settings
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
33
.project
Normal file
33
.project
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>EmuLinker</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.ibm.sse.model.structuredbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.ibm.etools.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
12
.settings/org.eclipse.jdt.core.prefs
Normal file
12
.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#Sun Oct 02 20:49:44 EDT 2005
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||||
|
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.5
|
4
.settings/org.eclipse.jdt.ui.prefs
Normal file
4
.settings/org.eclipse.jdt.ui.prefs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#Sat Jan 21 23:22:08 EST 2006
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
internal.default.compliance=default
|
||||||
|
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
|
339
LICENSE
Normal file
339
LICENSE
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) 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
|
||||||
|
this service 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 make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. 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.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the 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 a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE 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.
|
||||||
|
|
||||||
|
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
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the 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 2 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, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision 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, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This 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.
|
40
build.xml
Normal file
40
build.xml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project name="EmuLinker" default="build" basedir=".">
|
||||||
|
|
||||||
|
<path id="project.class.path">
|
||||||
|
<pathelement path="${java.class.path}/" />
|
||||||
|
<fileset dir="./lib">
|
||||||
|
<include name="**/*.jar" />
|
||||||
|
<include name="**/*.zip" />
|
||||||
|
</fileset>
|
||||||
|
<!--
|
||||||
|
<fileset dir="C:\eclipse\plugins\com.cloudgarden.jigloo_3.8.9.2">
|
||||||
|
<include name="**/*.jar" />
|
||||||
|
</fileset>
|
||||||
|
-->
|
||||||
|
<pathelement path="./conf" />
|
||||||
|
<pathelement path="./src" />
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<target name="compile">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="./build" includes="**/*.class" />
|
||||||
|
</delete>
|
||||||
|
<javac srcdir="./src" destdir="./build" includes="**/*.java" failonerror="true" debug="on">
|
||||||
|
<classpath refid="project.class.path" />
|
||||||
|
</javac>
|
||||||
|
<echo message="Compiling complete." />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="build" depends="compile">
|
||||||
|
<delete file="build/emulinker.jar" />
|
||||||
|
<jar jarfile="build/emulinker.jar" update="false">
|
||||||
|
<fileset dir="./build">
|
||||||
|
<include name="**/*.class" />
|
||||||
|
</fileset>
|
||||||
|
</jar>
|
||||||
|
<echo message="Build Complete." />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
82
conf/access.cfg
Normal file
82
conf/access.cfg
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# This is the EmuLinker Kaillera Server user access and filter configuration.
|
||||||
|
# This file is constantly monitored for modifications, so any changes you make
|
||||||
|
# will get picked up immediately without restarting the server.
|
||||||
|
|
||||||
|
# Any line that starts with # is considered a comment and will not be processed.
|
||||||
|
# Lines are evaluated in order from top to bottom for the first match.
|
||||||
|
# Processing stops after finding the first match, so redundant ALLOW/DENY
|
||||||
|
# lines will have no effect.
|
||||||
|
|
||||||
|
# The ip address, game name, and emulator name filters are NOT case sensitive,
|
||||||
|
# and use a * character as a wildcard, and a | character as an OR, similar to
|
||||||
|
# DOS file name matching.
|
||||||
|
# Matching example:
|
||||||
|
# The following will match the name Moosehead:
|
||||||
|
# Moosehead moose* M* *head *oose* Moose*|Admin
|
||||||
|
# The following will NOT match the name Moosehead:
|
||||||
|
# Moose moose *asdf*
|
||||||
|
|
||||||
|
# USER PRIVILEGES
|
||||||
|
# ===============
|
||||||
|
# Syntax: user,<NORMAL|ELEVATED|ADMIN>,<ip address filter>,[login announcement]
|
||||||
|
# Examples:
|
||||||
|
# - Grant admin access to anyone on the local network with login announcement:
|
||||||
|
# user,ADMIN,192.168.*|10.0.0.*|127.0.0.1,Local Admin Logged In!
|
||||||
|
# - Silently grant admin access to a specific ip address:
|
||||||
|
# user,ADMIN,69.137.29.150,
|
||||||
|
# - Grant elevated access to a specific ip address with login announcement:
|
||||||
|
# user,ELEVATED,69.137.29.150,Welcome Moosehead!
|
||||||
|
# - Grant no special access but make a login announcement to users from Asia:
|
||||||
|
# user,NORMAL,2*,Welcome user from Asia!
|
||||||
|
|
||||||
|
#user,SUPERADMIN,dns:localhost,Server Owner Logged In!
|
||||||
|
|
||||||
|
|
||||||
|
# IP ADDRESS ACCESS
|
||||||
|
# =================
|
||||||
|
# Syntax: ipaddress,<ALLOW|DENY>,<ip address filter>
|
||||||
|
# Examples:
|
||||||
|
# - Allow only users on the private network:
|
||||||
|
# ipaddress,ALLOW,192.168.*|127.0.0.1|10.0.0.*
|
||||||
|
# ipaddress,DENY,*
|
||||||
|
# - Ban a specific ip address:
|
||||||
|
# ipaddress,DENY,69.137.29.150
|
||||||
|
# ipaddress,ALLOW,*
|
||||||
|
# - Ban all users from Asia
|
||||||
|
# ipaddress,DENY,2*
|
||||||
|
# ipaddress,ALLOW,*
|
||||||
|
# - Allow a specific user from Asia, ban the rest, allow everyone else
|
||||||
|
# ipaddress,ALLOW,200.201.202.203
|
||||||
|
# ipaddress,DENY,2*
|
||||||
|
# ipaddress,ALLOW,*
|
||||||
|
|
||||||
|
ipaddress,ALLOW,*
|
||||||
|
|
||||||
|
# GAME FILTERS
|
||||||
|
# ============
|
||||||
|
# Syntax: game,<ALLOW|DENY>,<game name filter>
|
||||||
|
# Examples:
|
||||||
|
# - Allow only 2 specific games:
|
||||||
|
# game,ALLOW,NBA Jam*
|
||||||
|
# game,ALLOW,NBA Maximum*
|
||||||
|
# game,DENY,*
|
||||||
|
# - Ban any game with a name containing Capcom and the Chat and Away games
|
||||||
|
# game,DENY,*Capcom*
|
||||||
|
# game,DENY,*Chat (not game)|*Away (leave messages)
|
||||||
|
# game,ALLOW,*
|
||||||
|
|
||||||
|
game,ALLOW,*
|
||||||
|
|
||||||
|
# EMULATOR FILTERS
|
||||||
|
# ================
|
||||||
|
# Syntax: emulator,<ALLOW|DENY>,<emulator name filter>
|
||||||
|
# Examples:
|
||||||
|
# - Allow only Kawaks users and nobody else:
|
||||||
|
# emulator,ALLOW,Kawaks*
|
||||||
|
# emulator,DENY,*
|
||||||
|
# - Allow any emulator except for Kawaks
|
||||||
|
# emulator,DENY,Kawaks*
|
||||||
|
# emulator,ALLOW,*
|
||||||
|
|
||||||
|
emulator,ALLOW,*
|
||||||
|
|
3
conf/commons-logging.properties
Normal file
3
conf/commons-logging.properties
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# You do not need to edit this file unless you want to use a logger other than Log4J
|
||||||
|
|
||||||
|
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
|
17
conf/components.xml
Normal file
17
conf/components.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- This file defines the core components used in EmuLinker. You do not need to edit this file
|
||||||
|
unless you want to replace a component with a different implementation. -->
|
||||||
|
|
||||||
|
<container>
|
||||||
|
<component class='org.emulinker.util.EmuLinkerPropertiesConfig'/>
|
||||||
|
<component class='org.emulinker.util.EmuLinkerExecutor'/>
|
||||||
|
<component class='org.emulinker.kaillera.release.KailleraServerReleaseInfo'/>
|
||||||
|
<component class='org.emulinker.kaillera.access.AccessManager2'/>
|
||||||
|
<component class='org.emulinker.kaillera.controller.connectcontroller.ConnectController'/>
|
||||||
|
<component class='org.emulinker.kaillera.controller.v086.V086Controller'/>
|
||||||
|
<component class='org.emulinker.kaillera.model.impl.KailleraServerImpl'/>
|
||||||
|
<component class='org.emulinker.kaillera.model.impl.AutoFireDetectorFactoryImpl'/>
|
||||||
|
<component class='org.emulinker.kaillera.master.MasterListStatsCollector'/>
|
||||||
|
<component class='org.emulinker.kaillera.master.client.MasterListUpdaterImpl'/>
|
||||||
|
</container>
|
114
conf/emulinker.cfg
Normal file
114
conf/emulinker.cfg
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# This is the main EmuLinker Kaillera Server configuration file.
|
||||||
|
# This file is read on startup of the server, so you must restart the server
|
||||||
|
# to pickup any changes. Don't forget to edit access.cfg also.
|
||||||
|
|
||||||
|
# Any line that starts with # is considered a comment and will not be processed
|
||||||
|
|
||||||
|
# NETWORKING CONFIGURATION
|
||||||
|
# ========================
|
||||||
|
# This is the main port your server will listen on for new connections
|
||||||
|
controllers.connect.port=27888
|
||||||
|
# Buffer size for messages to the connect port.
|
||||||
|
# Should not need adjustment.
|
||||||
|
controllers.connect.bufferSize=4096
|
||||||
|
# This is the first port in the range of port your server will assign to
|
||||||
|
# individual users. Each user gets a private port while connected. The
|
||||||
|
# server will use ports between this number and this number + maxUsers + extraPorts.
|
||||||
|
controllers.v086.portRangeStart=27889
|
||||||
|
# The number of extra ports to allocate for admin and elevated users to join
|
||||||
|
# the server even when it's full.
|
||||||
|
controllers.v086.extraPorts=10
|
||||||
|
# Buffer size for all private port messages including game data packets.
|
||||||
|
# Should not need adjustment.
|
||||||
|
controllers.v086.bufferSize=2048
|
||||||
|
# Do not change; for future use only.
|
||||||
|
controllers.v086.clientTypes.clientType=0.83
|
||||||
|
|
||||||
|
# GAME PERFORMANCE CONFIGURATION
|
||||||
|
# ==============================
|
||||||
|
# Buffer size for the game data queue. Increasing this will not improve
|
||||||
|
# performance. Should be equal to at least the largest single game packet.
|
||||||
|
game.bufferSize=1024
|
||||||
|
# Maximum number of milliseconds to wait for other player's data before a
|
||||||
|
# timeout retry is generated.
|
||||||
|
game.timeoutMillis=1000
|
||||||
|
# Number of consecutive timeouts before a player is considered desynched.
|
||||||
|
game.desynchTimeouts=8
|
||||||
|
|
||||||
|
# AUTOFIRE DETECTION CONFIGURATION
|
||||||
|
# ================================
|
||||||
|
# Autofire detection is a cheat protection feature that will scan player's data
|
||||||
|
# during the game for button presses so fast they're humanly impossible, also
|
||||||
|
# known as turbo button or rapid fire. Most people consider this cheating.
|
||||||
|
# If the server detects autofire, it will print a message in the game and the
|
||||||
|
# emulinker.log file so all players know who's using autofire.
|
||||||
|
# Autofire detection sensitivity controls the threshold of how rapid a button
|
||||||
|
# press is considered true autofire. Sensitivity values [1-5], 0 to disable.
|
||||||
|
#
|
||||||
|
# game.defaultAutoFireSensitivity=0 : AUTOFIRE DETECTION DISABLED
|
||||||
|
#
|
||||||
|
# game.defaultAutoFireSensitivity=1 : MINIMUM SENSITIVITY; no chance of a false
|
||||||
|
# alert but may miss some autofire users
|
||||||
|
#
|
||||||
|
# game.defaultAutoFireSensitivity=5 : MAXIMUM SENSITIVITY; should alert on most
|
||||||
|
# autofire users but could produce false
|
||||||
|
# alerts for people with very fast fingers
|
||||||
|
#
|
||||||
|
game.defaultAutoFireSensitivity=1
|
||||||
|
|
||||||
|
# MASTER LIST CONFIGURATION
|
||||||
|
# =========================
|
||||||
|
# Server name to display in the master lists
|
||||||
|
masterList.serverName=Test Server
|
||||||
|
# Location of the server to display in the master lists
|
||||||
|
masterList.serverLocation=
|
||||||
|
# Website of the server to display in the master lists
|
||||||
|
masterList.serverWebsite=
|
||||||
|
# Explicit connect address in cases where your server uses NAT. Leave this
|
||||||
|
# blank unless required by your firewall.
|
||||||
|
masterList.serverConnectAddress=
|
||||||
|
# Set to true to list your server on the original kaillera.com master.
|
||||||
|
masterList.touchKaillera=false
|
||||||
|
# Set to true to list your server on the emulinker.org/anti3d.com master
|
||||||
|
masterList.touchEmulinker=false
|
||||||
|
# Set both of the above to false to run a private server!
|
||||||
|
|
||||||
|
# GENERAL SERVER CHECKS AND CONTROL CONFIGURATION
|
||||||
|
# ===============================================
|
||||||
|
# Maximum user ping time allowed to login to your server, must be set > 0
|
||||||
|
server.maxPing=250
|
||||||
|
# Comma delimited list of allowed user connection types
|
||||||
|
# 1 = LAN, 2 = Excellent, 3 = Good, 4 = Average, 5 = Low, 6 = Bad
|
||||||
|
server.allowedConnectionTypes=1,2,3,4,5,6
|
||||||
|
# Max number of users allowed to connect at a time, 0 to disable
|
||||||
|
server.maxUsers=140
|
||||||
|
# Max number of games allowed on the server at a time, 0 to disable
|
||||||
|
server.maxGames=0
|
||||||
|
# Set to false to prevent users from playing single player
|
||||||
|
server.allowSinglePlayer=true
|
||||||
|
# Set to false to prevent users from logging in mutiple times using different names
|
||||||
|
server.allowMultipleConnections=true
|
||||||
|
# Seconds of no activity before a user is removed for a Ping Timeout
|
||||||
|
# Should not need adjustment
|
||||||
|
server.keepAliveTimeout=70
|
||||||
|
# Seconds of inactivity before a user is removed for a Idle Timeout
|
||||||
|
# 900 = 15 minutes of idling before being removed, 0 to disable
|
||||||
|
server.idleTimeout=0
|
||||||
|
|
||||||
|
# FLOOD CONTROL AND HACKER PREVENTION CONFIGURATION
|
||||||
|
# =================================================
|
||||||
|
# Minimum number of seconds between chat messages, 0 to disable
|
||||||
|
server.chatFloodTime=3
|
||||||
|
# Minimum number of seconds between created games, 0 to disable
|
||||||
|
server.createGameFloodTime=2
|
||||||
|
# Maximum user name length, 0 to disable
|
||||||
|
server.maxUserNameLength=31
|
||||||
|
# Maximum emulator (client) name length, 0 to disable
|
||||||
|
server.maxClientNameLength=128
|
||||||
|
# Maximum chat message length, 0 to disable
|
||||||
|
server.maxChatLength=150
|
||||||
|
# Maximum game (ROM) name length, 0 to disable
|
||||||
|
server.maxGameNameLength=128
|
||||||
|
# Maximum quit message length, 0 to disable
|
||||||
|
server.maxQuitMessageLength=75
|
||||||
|
|
171
conf/language.properties
Normal file
171
conf/language.properties
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
# This is the EmuLinker Kaillera Server language configuration file. EmuLinker
|
||||||
|
# supports multiple languages using standard Java resource bundle format. To
|
||||||
|
# use a different language you should create a new file named for your locale
|
||||||
|
# such as language_fr.properties, language_de.properties, language_es.properties, etc
|
||||||
|
# Please submit any translations to http://www.emulinker.org.
|
||||||
|
#
|
||||||
|
# Values enclosed in { } are variables and will be replaced with the appropriate
|
||||||
|
# data when displayed.
|
||||||
|
#
|
||||||
|
# Some special characters must be prefixed with the \ character.
|
||||||
|
#
|
||||||
|
# For more information see: http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles
|
||||||
|
|
||||||
|
# Login Announcements
|
||||||
|
KailleraServerImpl.LoginMessage.1=Test Server
|
||||||
|
|
||||||
|
|
||||||
|
# Other Announcements
|
||||||
|
KailleraServerImpl.UserCreatedGameAnnouncement={0} created game: {1}
|
||||||
|
|
||||||
|
# Server Denied Messages
|
||||||
|
KailleraServerImpl.LoginDeniedPingTooHigh=Ping Too High: {0}
|
||||||
|
KailleraServerImpl.LoginDeniedServerFull=Server is full\!
|
||||||
|
KailleraServerImpl.LoginDeniedAccessDenied=Access Denied\!
|
||||||
|
KailleraServerImpl.LoginDeniedAddressMatchError=Login address does not match connect address\!
|
||||||
|
KailleraServerImpl.LoginDeniedAlreadyLoggedIn=You are already logged in\!
|
||||||
|
KailleraServerImpl.LoginDeniedAlreadyLoggedInAs=Already logged in as: {0}
|
||||||
|
KailleraServerImpl.LoginDeniedConnectionTimedOut=Connection timed out\!
|
||||||
|
KailleraServerImpl.LoginDeniedConnectionTypeDenied=Connection Type Denied: {0}
|
||||||
|
KailleraServerImpl.LoginDeniedEmulatorNameTooLong=Emulator Name Too Long
|
||||||
|
KailleraServerImpl.LoginDeniedEmulatorRestricted=Emulator Restricted: {0}
|
||||||
|
KailleraServerImpl.LoginDeniedIllegalCharactersInUserName=Illegal characters in User Name
|
||||||
|
KailleraServerImpl.LoginDeniedUserNameEmpty=Empty UserName\!
|
||||||
|
KailleraServerImpl.LoginDeniedUserNameTooLong=User Name Too Long
|
||||||
|
KailleraServerImpl.ChatDeniedFloodControl=Flood Control
|
||||||
|
KailleraServerImpl.ChatDeniedIllegalCharacters=Illegal characters in message
|
||||||
|
KailleraServerImpl.ChatDeniedMessageTooLong=Message Too Long
|
||||||
|
KailleraServerImpl.ChatDeniedSilenced=Silenced
|
||||||
|
KailleraServerImpl.CreateGameDeniedGameBanned=Server does not allow playing this game\!
|
||||||
|
KailleraServerImpl.CreateGameDeniedFloodControl=Flood Control
|
||||||
|
KailleraServerImpl.CreateGameDeniedIllegalCharacters=Illegal characters in ROM name
|
||||||
|
KailleraServerImpl.CreateGameDeniedMaxGames=Server maximum games reached: {0,number,integer}
|
||||||
|
KailleraServerImpl.CreateGameDeniedNameTooLong=Rom Name Too Long
|
||||||
|
ChatAction.ChatDenied=Denied: {0}
|
||||||
|
|
||||||
|
# Server Error Messages
|
||||||
|
KailleraServerImpl.LoginErrorInvalidStatus=Invalid Login Status: {0}
|
||||||
|
KailleraServerImpl.LoginErrorInvalidPing=Invalid Ping: {0,number}
|
||||||
|
KailleraServerImpl.CreateGameErrorAlreadyInGame=You are already in a game\!
|
||||||
|
KailleraServerImpl.CreateGameErrorEmptyName=Rom Name Empty
|
||||||
|
KailleraServerImpl.NotLoggedIn=Not logged in
|
||||||
|
|
||||||
|
# Forced Quit Messages
|
||||||
|
KailleraServerImpl.StandardQuitMessage=
|
||||||
|
KailleraServerImpl.ForcedQuitReconnected=Reconnected
|
||||||
|
KailleraServerImpl.ForcedQuitInactivityTimeout=Inactivity Timeout
|
||||||
|
KailleraServerImpl.ForcedQuitPingTimeout=Ping Timeout
|
||||||
|
KailleraServerImpl.ForcedQuitBanned=Banned until the Messiah comes!
|
||||||
|
KailleraServerImpl.ForcedQuitEmulatorRestricted=Emulator Restricted\!
|
||||||
|
|
||||||
|
# Admin Messages
|
||||||
|
KailleraServerImpl.AdminWelcomeMessage=Welcome admin. Type /help for commands.
|
||||||
|
AdminCommandAction.AdminCommands=Available Admin Commands:
|
||||||
|
AdminCommandAction.HelpAnnounce=/announce to make an announcement
|
||||||
|
AdminCommandAction.HelpAnnounceAll=/announceall to make an announcement including all games
|
||||||
|
AdminCommandAction.HelpAnnounceGame=/announcegame to make an announcement to a single game
|
||||||
|
AdminCommandAction.HelpCloseGame=/closegame close a game
|
||||||
|
AdminCommandAction.HelpBan=/ban to temporarily ban a user
|
||||||
|
AdminCommandAction.HelpFindGame=/findgame to get a game's number
|
||||||
|
AdminCommandAction.HelpFindUser=/finduser to get a user's number
|
||||||
|
AdminCommandAction.HelpKick=/kick to eject a user
|
||||||
|
AdminCommandAction.HelpSilence=/silence to temporarily silence a user
|
||||||
|
AdminCommandAction.HelpTempAdmin=/tempadmin to grant a user temporary admin access
|
||||||
|
AdminCommandAction.HelpVersion=/version to print server version information
|
||||||
|
AdminCommandAction.AnnounceError=/announce <msg> or /announceall <msg> (includes games)
|
||||||
|
AdminCommandAction.AnnounceGameError=/announcegame <game number> <message>
|
||||||
|
AdminCommandAction.BanError=/ban <user number> <minutes>
|
||||||
|
AdminCommandAction.CloseGameError=/closegame <game number>
|
||||||
|
AdminCommandAction.FindGameError=/findgame <name search string> (name*, *name, * to list all)>
|
||||||
|
AdminCommandAction.FindUserError=/finduser <name search string> (name*, *name, * to list all)>
|
||||||
|
AdminCommandAction.KickError=/kick <user number>
|
||||||
|
AdminCommandAction.SilenceError=/silence <user number> <minutes>
|
||||||
|
AdminCommandAction.TempAdminError=/tempadmin <user number> <minutes>
|
||||||
|
AdminCommandAction.VersionError=/version
|
||||||
|
AdminCommandAction.AlreadyAdmin=You are already an admin\!
|
||||||
|
AdminCommandAction.Banned=Banned ({0,number,integer} minutes): {1}
|
||||||
|
AdminCommandAction.CanNotBanAdmin=You can not ban another admin\!
|
||||||
|
AdminCommandAction.CanNotBanSelf=You can not ban yourself\!
|
||||||
|
AdminCommandAction.CanNotCloseAdminGame=You can not close another admin's game\!
|
||||||
|
AdminCommandAction.CanNotKickAdmin=You can not kick another admin\!
|
||||||
|
AdminCommandAction.CanNotKickSelf=You can not kick yourself\!
|
||||||
|
AdminCommandAction.CanNotSilenceAdmin=You can not silence another admin\!
|
||||||
|
AdminCommandAction.CanNotSilenceSelf=You can not silence yourself\!
|
||||||
|
AdminCommandAction.Failed=Failed: {0}
|
||||||
|
AdminCommandAction.GameNotFound=Game not found: {0}
|
||||||
|
AdminCommandAction.NoGamesFound=No games match search\!
|
||||||
|
AdminCommandAction.NoUsersFound=No users match search\!
|
||||||
|
AdminCommandAction.QuitBanned=Banned until the Messiah returns!
|
||||||
|
AdminCommandAction.QuitKicked=Kicked...Go that way >>
|
||||||
|
AdminCommandAction.Silenced=Shhh!!! ({0,number,integer} minutes): {1}
|
||||||
|
AdminCommandAction.TempAdminGranted=Admin access granted ({0,number,integer} minutes): {1}
|
||||||
|
AdminCommandAction.UserAlreadyAdmin=User is already an admin\!
|
||||||
|
AdminCommandAction.UserNotFound=User not found: {0}
|
||||||
|
AdminCommandAction.HelpClear=/clear to remove any temp ban, silence, or admin
|
||||||
|
AdminCommandAction.ClearError=/clear <ip address>
|
||||||
|
AdminCommandAction.ClearAddressFormatError=Invalid ip address\!
|
||||||
|
AdminCommandAction.ClearSuccess=Address cleared\!
|
||||||
|
AdminCommandAction.ClearNotFound=Address not found\!
|
||||||
|
|
||||||
|
# In-Game Messages
|
||||||
|
KailleraGameImpl.DesynchDetectedDroppedPacket=Player dropped a packet: {0}
|
||||||
|
KailleraGameImpl.DesynchDetectedPlayerLagged=Player is lagged: {0}
|
||||||
|
KailleraGameImpl.DesynchedWarning=Game is desynched\!
|
||||||
|
GameDesynchAction.DesynchDetected=Desynch Detected\!
|
||||||
|
PlayerDesynchAction.DesynchDetected=Desynch Detected\!
|
||||||
|
KailleraGameImpl.StartGameConnectionTypeMismatchInfo=To prevent desynch, all players must use the same connection type as the game owner
|
||||||
|
KailleraGameImpl.StartGameEmulatorMismatchInfo=To prevent desynch, all players must use the same emulator as the game owner
|
||||||
|
|
||||||
|
# Game Denied Messages
|
||||||
|
KailleraGameImpl.CloseGameDeniedNotGameOwner=You are not the owner of this game\!
|
||||||
|
KailleraGameImpl.GameKickDeniedCannotKickSelf=You can not kick yourself\!
|
||||||
|
KailleraGameImpl.GameKickDeniedNotGameOwner=Only the game owner may kick players\!
|
||||||
|
KailleraGameImpl.JoinGameDeniedGameIsInProgress=You may not join a game in-progress\!
|
||||||
|
KailleraGameImpl.JoinGameDeniedPreviouslyKicked=Previously kicked from this game\!
|
||||||
|
KailleraGameImpl.StartGameDeniedConnectionTypeMismatch=All players must use the same connection type\!
|
||||||
|
KailleraGameImpl.StartGameDeniedEmulatorMismatch=All players must use the same emulator\!
|
||||||
|
KailleraGameImpl.StartGameDeniedOnlyOwnerMayStart=Only the game owner may start the game\!
|
||||||
|
KailleraGameImpl.StartGameDeniedSinglePlayerNotAllowed=Server does not allow single player\!
|
||||||
|
JoinGameAction.JoinGameDenied=Denied: {0}
|
||||||
|
CreateGameAction.CreateGameDenied=Denied: {0}
|
||||||
|
CreateGameAction.CreateGameDeniedFloodControl=Denied: Flood control
|
||||||
|
|
||||||
|
# Game Error Messages
|
||||||
|
KailleraGameImpl.DropGameErrorInternalError=Internal Error\!
|
||||||
|
KailleraGameImpl.DropGameErrorNotInGame=You are not in this game\!
|
||||||
|
KailleraGameImpl.GameChatErrorNotInGame=You are not in this game
|
||||||
|
KailleraGameImpl.GameKickErrorUserNotFound=User is not in this game
|
||||||
|
KailleraGameImpl.JoinGameErrorAlreadyInGame=You are already in this game\!
|
||||||
|
KailleraGameImpl.QuitGameErrorNotInGame=You are not in this game\!
|
||||||
|
KailleraGameImpl.ReadyGameErrorIncorrectState=Game is waiting or still playing\!
|
||||||
|
KailleraGameImpl.ReadyGameErrorInternalError=Internal Error\!
|
||||||
|
KailleraGameImpl.ReadyGameErrorNotInGame=You are not in this game\!
|
||||||
|
KailleraGameImpl.StartGameErrorStatusIsPlaying=Please Wait: Not all players have dropped\!
|
||||||
|
KailleraGameImpl.StartGameErrorSynchronizing=Please Wait: Game is synchronizing\!
|
||||||
|
KailleraUserImpl.CreateGameErrorAlreadyInGame=You have another game running\!
|
||||||
|
KailleraUserImpl.CreateGameErrorNotFullyConnected=You are not fully connected\!
|
||||||
|
KailleraUserImpl.GameChatErrorNotInGame=You are not in a game\!
|
||||||
|
KailleraUserImpl.GameDataErrorNotInGame=Your are not in a game\!
|
||||||
|
KailleraUserImpl.JoinGameErrorAlreadyInGame=You are already in a game\!
|
||||||
|
KailleraUserImpl.JoinGameErrorAnotherGameRunning=You have another game running\!
|
||||||
|
KailleraUserImpl.JoinGameErrorDoesNotExist=Game does not exist\!
|
||||||
|
KailleraUserImpl.JoinGameErrorNotFullyConnected=You are not fully connected\!
|
||||||
|
KailleraUserImpl.KickErrorNotInGame=You are not in a game\!
|
||||||
|
KailleraUserImpl.PlayerReadyErrorNotInGame=You are not in a game\!
|
||||||
|
KailleraUserImpl.StartGameErrorNotInGame=You are not in a game\!
|
||||||
|
|
||||||
|
# Game Setting Commands
|
||||||
|
AutoFireScanner2.AutoFireDetected=AutoFire Detected: {0}
|
||||||
|
KailleraGameImpl.AutofireDetectionOn=AutoFire Detection is ON
|
||||||
|
KailleraGameImpl.AutofireCurrentSensitivity=Current AutoFire Sensitivity: {0,number,integer}
|
||||||
|
KailleraGameImpl.AutofireDetectionOff=AutoFire Detection is OFF
|
||||||
|
KailleraGameImpl.GameHelp=Type /help to adjust game settings
|
||||||
|
GameOwnerCommandAction.CommandFailed=Failed: {0}
|
||||||
|
GameOwnerCommandAction.AvailableCommands=Available Game Setting Commands:
|
||||||
|
GameOwnerCommandAction.SetAutofireDetection=/detectautofire to set AutoFire detection
|
||||||
|
GameOwnerCommandAction.HelpSensitivity=/detectautofire 1-5 (low-high sensitivity)
|
||||||
|
GameOwnerCommandAction.HelpDisable=/detectautofire 0 to disable detection
|
||||||
|
GameOwnerCommandAction.HelpCurrentSensitivity=Current AutoFire sensitivity: {0,number,integer}
|
||||||
|
GameOwnerCommandAction.HelpDisabled=\ (disabled)
|
||||||
|
GameOwnerCommandAction.AutoFireChangeDeniedInGame=All players must drop the game to change settings!
|
||||||
|
|
20
conf/log4j.properties
Normal file
20
conf/log4j.properties
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# This file defines what, where, and how your server writes logs using Log4J
|
||||||
|
# For Log4J instructions see: http://logging.apache.org/log4j/docs/manual.html
|
||||||
|
|
||||||
|
# Log levels are: DEBUG, INFO, WARN, ERROR, FATAL
|
||||||
|
log4j.rootLogger=DEBUG, console
|
||||||
|
log4j.logger.org.apache.commons.httpclient=WARN
|
||||||
|
log4j.logger.httpclient=WARN
|
||||||
|
log4j.appender.logFile=org.apache.log4j.RollingFileAppender
|
||||||
|
|
||||||
|
# This causes the server to write all logs to server.log, rotate the file every
|
||||||
|
# 10 megabytes, and keep the last 5 rotations.
|
||||||
|
log4j.appender.logFile.File=emulinker.log
|
||||||
|
log4j.appender.logFile.MaxFileSize=10MB
|
||||||
|
log4j.appender.logFile.MaxBackupIndex=5
|
||||||
|
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.logFile.layout.ConversionPattern=%d{MM-dd-yy HH:mm:ss.SSS} %5p %c{1}: %m%n
|
||||||
|
|
||||||
|
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.console.layout.ConversionPattern=%d{MM-dd-yy HH:mm:ss.SSS} %5p %c{1}: %m%n
|
1
conf/user.properties
Normal file
1
conf/user.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
emuadmin: playgame
|
43
doc/master_analysis.txt
Normal file
43
doc/master_analysis.txt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
GET
|
||||||
|
/touch_server.php?
|
||||||
|
servername=Anti%33D%2Ecom+%23%31+General+Public+Server
|
||||||
|
&port=27888
|
||||||
|
&nbusers=0
|
||||||
|
&maxconn=35
|
||||||
|
&version=0.86
|
||||||
|
&nbgames=0
|
||||||
|
&location=East+Coast%2C+USA
|
||||||
|
&ip=
|
||||||
|
&url=http%3A%2F%2Fwww%2Eanti%33d%2Ecom
|
||||||
|
HTTP/1.0..
|
||||||
|
Host:www.kaillera.com..
|
||||||
|
Kaillera-games: ..
|
||||||
|
Kaillera-wgames: ....
|
||||||
|
|
||||||
|
|
||||||
|
3 D % 2 E c o m + % 2 3 % 3 1 + G e n e r a l + P u b l i c + S e r v e r & p o r t = 2 7 8 8 8 & n b u s e r s = 2 8 & m a x c o n n = 3 5 & v e r s i o n = 0 . 8 6 & n b g a m e s = 9 & l o c a t i o n = E a s t + C o a s t % 2 C + U S A & i p = & u r l = h t t p % 3 A % 2 F % 2 F w w w % 2 E a n t i % 3 3 d % 2 E c o m
|
||||||
|
|
||||||
|
3 D % 2 E c o m + % 2 3 % 3 1 + G e n e r a l + P u b l i c + S e r v e r & p o r t = 2 7 8 8 8 & n b u s e r s = 2 8 & m a x c o n n = 3 5 & v e r s i o n = 0 . 8 6 & n b g a m e s = 9 & l o c a t i o n = E a s t + C o a s t % 2 C + U S A & i p = & u r l = h t t p % 3 A % 2 F % 2 F w w w % 2 E a n t i % 3 3 d % 2 E c o m H T T P / 1 . 0 . . H o s t : w w w . k a i l l e r a . c o m . .
|
||||||
|
|
||||||
|
G E T / t o u c h _ s e r v e r . p h p ? s e
|
||||||
|
r v e r n a m e = A n t i % 3 3 D % 2 E c o m + % 2 3 % 3 1 + G e n e r a l
|
||||||
|
+ P u b l i c + S e r v e r & p o r t = 2 7 8 8 8 & n b u s e r s = 3 4 & m
|
||||||
|
a x c o n n = 3 5 & v e r s i o n = 0 . 8 6 & n b g a m e s = 1 2 & l o c a
|
||||||
|
t i o n = E a s t + C o a s t % 2 C + U S A & i p = & u r l = h t t p % 3 A
|
||||||
|
% 2 F % 2 F w w w % 2 E a n t i % 3 3 d % 2 E c o m H T T P / 1 . 0 . . H
|
||||||
|
o s t : w w w . k a i l l e r a . c o m . .
|
||||||
|
|
||||||
|
K a i l l e r a - g a m e s :
|
||||||
|
M a r v e l V s . C a p c o m : C l a s h o f S u p e r H e r o
|
||||||
|
e s ( U S 9 8 0 1 2 3 ) | K i n g o f F i g h t e r s 2 0 0 2 ,
|
||||||
|
T h e ( b o o t l e g ) | S u p e r S m a s h B r o s . ( U ) [ !
|
||||||
|
] | K i n g o f F i g h t e r s 2 0 0 2 , T h e ( b o o t l e g )
|
||||||
|
| . .
|
||||||
|
|
||||||
|
Kaillera-wgames:
|
||||||
|
1072|Vampire Savior: The Lord of Vampire (US 970519)|ChibiPotPie|MAME32k 0.64 (Feb 3 2003)|1|
|
||||||
|
1077|*Away (leave messages)|.Alice|MAME32k 0.64 (Feb 3 2003)|1|
|
||||||
|
1093|*Chat (ot game)|Moosehead4|asdf|MAME32k 0.64 (Feb 3 2003)|1|1094|Darius Gaiden - ilver Hawk (World)|Mystery person.|MAE32k 0.64 (Feb 3 2003)|1|....
|
||||||
|
|
||||||
|
Kaillera-games: [<game name>|]..
|
||||||
|
Kaillera-wgames: <gameid>|<game name>|<owner name>|<emu name>|<num players>|
|
483
doc/raw_server_list2.orig
Normal file
483
doc/raw_server_list2.orig
Normal file
File diff suppressed because one or more lines are too long
483
doc/raw_server_list2.txt
Normal file
483
doc/raw_server_list2.txt
Normal file
File diff suppressed because one or more lines are too long
215
doc/scratch.txt
Normal file
215
doc/scratch.txt
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
x way to choose excellent only
|
||||||
|
x make kick from a game permanent
|
||||||
|
x access levels
|
||||||
|
x verify wildcard parsing
|
||||||
|
x / commands for admins
|
||||||
|
x temporary ban ~10 minute ban
|
||||||
|
- temp ban for repetedly spamming
|
||||||
|
x join playing games w/ access
|
||||||
|
x don't force everyone to drop in > 2 player games if one person drops
|
||||||
|
x don't lock if other player closes game
|
||||||
|
|
||||||
|
- Finish I18N
|
||||||
|
x Join game when in game vulnerability
|
||||||
|
- Game status update when drop during netsynch bug
|
||||||
|
x Version admin command
|
||||||
|
x Thread deadlock issue
|
||||||
|
x Finish & test better autofire detector
|
||||||
|
x Add better autofire controls
|
||||||
|
- Login flood protection
|
||||||
|
- Admin "game" with client controls
|
||||||
|
x Fix announcegame
|
||||||
|
x Fix message count = 3 when < 3 messages
|
||||||
|
x Fix Rejecting packet received from wrong address
|
||||||
|
x Check for correct class types in Action classes before casting
|
||||||
|
|
||||||
|
Sensitivity
|
||||||
|
----------
|
||||||
|
|
||||||
|
Repetitions Max Delay
|
||||||
|
----------- ---------
|
||||||
|
5 2
|
||||||
|
8 4
|
||||||
|
10 6
|
||||||
|
12 8
|
||||||
|
14 10
|
||||||
|
16 12
|
||||||
|
|
||||||
|
0 OFF
|
||||||
|
|
||||||
|
LEAST SENSITIVE
|
||||||
|
|
||||||
|
MAX DELAY MIN REPETITIONS
|
||||||
|
1 2 25
|
||||||
|
2 4 20
|
||||||
|
3 6 15
|
||||||
|
4 8 10
|
||||||
|
5 10 5
|
||||||
|
|
||||||
|
MOST SENSITIVE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Connection Type Actions Per Frame Frames Per Second
|
||||||
|
--------------- ----------------- -----------------
|
||||||
|
LAN 1 60
|
||||||
|
Excellent 2 30
|
||||||
|
Good 3 20
|
||||||
|
Average 4 15
|
||||||
|
Low 5 12
|
||||||
|
Bad 6 10
|
||||||
|
|
||||||
|
Bytes Per Frame (IN)
|
||||||
|
Emulator Bytes Per Action LAN Excellent Good Average Low Bad
|
||||||
|
-------- ---------------- --- --------- ---- ------- --- ---
|
||||||
|
Mame32k 0.64 2 2 4 6 8 10 12
|
||||||
|
|
||||||
|
Bytes Per Action = (Bytes Per Frame (IN))/
|
||||||
|
Bytes Per Frame (IN) = (Connection Type Actions Per Frame) * (Emulator Bytes Per Action)
|
||||||
|
Bytes Per Frame (OUT) = (Connection Type Actions Per Frame) * (Emulator Bytes Per Action) * (Number of Players)
|
||||||
|
|
||||||
|
112233 112233 112233
|
||||||
|
|
||||||
|
numPlayers
|
||||||
|
playerCounter
|
||||||
|
numActions
|
||||||
|
actionCounter
|
||||||
|
connectionType=actionsPerMessage
|
||||||
|
bytesPerAction=(inboundMessage.length/actionsPerMessage)
|
||||||
|
inboundMessage.length=(actionsPerMessage*bytesPerAction)
|
||||||
|
outboutMessageLength = (numPlayers*actionsPerMessage*bytesPerAction)
|
||||||
|
|
||||||
|
pos=(actionCounter*(numPlayers*bytesPerAction))+(playerCounter*bytesPerAction)
|
||||||
|
0*(3*2)+(0*2) = 0
|
||||||
|
0*(3*2)+(1*2) = 2
|
||||||
|
0*(3*2)+(2*2) = 4
|
||||||
|
1*(3*2)+(0*2) = 6
|
||||||
|
|
||||||
|
|
||||||
|
10-01-05 16:48:48.445 DEBUG: send (03,B3,03,03,00,13,00,00,B2,03,03,00,13,00,00,B1,03,03,00,13,00,00,B0,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.495 DEBUG: receive(03,AB,03,03,00,13,00,00,AA,03,03,00,13,00,00,A9,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.495 DEBUG: send (03,B4,03,03,00,13,00,00,B3,03,03,00,13,00,00,B2,03,03,00,13,00,00,B1,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.565 DEBUG: receive(03,AC,03,03,00,13,00,00,AB,03,03,00,13,00,00,AA,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.565 DEBUG: send (03,B5,03,03,00,13,00,00,B4,03,03,00,13,00,00,B3,03,03,00,13,00,00,B2,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.595 DEBUG: receive(03,AD,03,0A,00,12,00,06,00,00,00,00,00,08,00,AC,03,03,00,13,00,00,AB,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.595 DEBUG: send (03,B6,03,0A,00,12,00,06,00,00,00,00,00,08,00,B5,03,03,00,13,00,00,B4,03,03,00,13,00,00,B3,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.645 DEBUG: receive(03,AE,03,0A,00,12,00,06,00,08,00,08,00,08,00,AD,03,0A,00,12,00,06,00,00,00,00,00,08,00,AC,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.645 DEBUG: send (03,B7,03,0A,00,12,00,06,00,08,00,08,00,08,00,B6,03,0A,00,12,00,06,00,00,00,00,00,08,00,B5,03,03,00,13,00,00,B4,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.696 DEBUG: receive(03,AF,03,03,00,13,00,00,AE,03,0A,00,12,00,06,00,08,00,08,00,08,00,AD,03,0A,00,12,00,06,00,00,00,00,00,08,00)
|
||||||
|
10-01-05 16:48:48.696 DEBUG: send (03,B8,03,03,00,13,00,00,B7,03,0A,00,12,00,06,00,08,00,08,00,08,00,B6,03,0A,00,12,00,06,00,00,00,00,00,08,00,B5,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.746 DEBUG: receive(03,B0,03,03,00,13,00,00,AF,03,03,00,13,00,00,AE,03,0A,00,12,00,06,00,08,00,08,00,08,00)
|
||||||
|
10-01-05 16:48:48.746 DEBUG: send (03,B9,03,03,00,13,00,00,B8,03,03,00,13,00,00,B7,03,0A,00,12,00,06,00,08,00,08,00,08,00,B6,03,0A,00,12,00,06,00,00,00,00,00,08,00)
|
||||||
|
10-01-05 16:48:48.816 DEBUG: receive(03,B1,03,03,00,13,00,00,B0,03,03,00,13,00,00,AF,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.816 DEBUG: send (03,BA,03,03,00,13,00,00,B9,03,03,00,13,00,00,B8,03,03,00,13,00,00,B7,03,0A,00,12,00,06,00,08,00,08,00,08,00)
|
||||||
|
10-01-05 16:48:48.846 DEBUG: receive(03,B2,03,03,00,13,00,00,B1,03,03,00,13,00,00,B0,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.846 DEBUG: send (03,BB,03,03,00,13,00,00,BA,03,03,00,13,00,00,B9,03,03,00,13,00,00,B8,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.936 DEBUG: receive(03,B3,03,03,00,13,00,00,B2,03,03,00,13,00,00,B1,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.936 DEBUG: send (03,BC,03,03,00,13,00,00,BB,03,03,00,13,00,00,BA,03,03,00,13,00,00,B9,03,03,00,13,00,00)
|
||||||
|
10-01-05 16:48:48.976 DEBUG: receive(03,B4,03,03,00,13,00,00,B3,03,03,00,13,00,00,B2,03,03,00,13,00,00)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
10-01-05 19:55:28.505 WARN: Unexpected exception: 05,04,00,z,00,04,00,03,00,00,00,01,00,00,00,J,a,c,k,20,B,a,u,e,r,00,27,00,00,00,01,0F,00,03,?,?,00,H,00,00,00,00,0C,00,03,k,e,n,00,T,00,00,00,00,0B,00,03,S,a,m,u,r,a,i,20,S,h,o,d,o,w,n,20,I,V,3A,20,A,m,a,k,u,s,a,27,s,20,R,e,v,e,n,g,e,00,03,00,00,00,K,a,w,a,k,s,20,1,2E,4,5,20,N,e,t,p,l,a,y,00,?,?,00,2,2F,2,00,01,03,00,12,00,05,00,00,00,00,00,01,00,00,00,02,00,00,00,03,00,00,00,02,00,12,00,05,00,00,00,00,00,01,00,00,00,02,00,00,00,03,00,00,00,01,00,12,00,05,00,00,00,00,00,01,00,00,00,02,00,00,00,03,00,00,00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
03, bundle message count
|
||||||
|
18,01, message number 280
|
||||||
|
03,00, message length 3
|
||||||
|
13, message type 19
|
||||||
|
00, unused
|
||||||
|
0C, cache key 12
|
||||||
|
17,01, message number 279
|
||||||
|
03,00,
|
||||||
|
13,
|
||||||
|
00,
|
||||||
|
00,
|
||||||
|
16,01, message number 278
|
||||||
|
03,00,
|
||||||
|
13,
|
||||||
|
00,
|
||||||
|
00
|
||||||
|
XX XX XX
|
||||||
|
client sent: 03,18,01,03,00,13,00,0C,17,01,03,00,13,00,00,16,01,03,00,13,00,00
|
||||||
|
server sent: 03,24,01,03,00,13,00,0C,23,01,03,00,13,00,00,22,01,03,00,13,00,00
|
||||||
|
client sent: 03,19,01,03,00,13,00,00,18,01,03,00,13,00,0C,17,01,03,00,13,00,00
|
||||||
|
server sent: 03,25,01,03,00,13,00,00,24,01,03,00,13,00,0C,23,01,03,00,13,00,00
|
||||||
|
client sent: 03,1A,01,03,00,13,00,00,19,01,03,00,13,00,00,18,01,03,00,13,00,0C
|
||||||
|
server sent: 03,26,01,03,00,13,00,00,25,01,03,00,13,00,00,24,01,03,00,13,00,0C
|
||||||
|
client sent: 03,1B,01,03,00,13,00,00,1A,01,03,00,13,00,00,19,01,03,00,13,00,00
|
||||||
|
server sent: 03,27,01,03,00,13,00,00,26,01,03,00,13,00,00,25,01,03,00,13,00,00
|
||||||
|
client sent: 03,1C,01,03,00,13,00,00,1B,01,03,00,13,00,00,1A,01,03,00,13,00,00
|
||||||
|
server sent: 03,28,01,03,00,13,00,00,27,01,03,00,13,00,00,26,01,03,00,13,00,00
|
||||||
|
client sent: 03,1D,01,03,00,13,00,00,1C,01,03,00,13,00,00,1B,01,03,00,13,00,00
|
||||||
|
server sent: 03,29,01,03,00,13,00,00,28,01,03,00,13,00,00,27,01,03,00,13,00,00
|
||||||
|
client sent: 03,1E,01,03,00,13,00,00,1D,01,03,00,13,00,00,1C,01,03,00,13,00,00
|
||||||
|
server sent: 03,2A,01,03,00,13,00,00,29,01,03,00,13,00,00,28,01,03,00,13,00,00
|
||||||
|
client sent: 03,1F,01,03,00,13,00,00,1E,01,03,00,13,00,00,1D,01,03,00,13,00,00
|
||||||
|
server sent: 03,2B,01,03,00,13,00,00,2A,01,03,00,13,00,00,29,01,03,00,13,00,00
|
||||||
|
client sent: 03,20,01,03,00,13,00,00,1F,01,03,00,13,00,00,1E,01,03,00,13,00,00
|
||||||
|
server sent: 03,2C,01,03,00,13,00,00,2B,01,03,00,13,00,00,2A,01,03,00,13,00,00
|
||||||
|
client sent: 03,21,01,03,00,13,00,00,20,01,03,00,13,00,00,1F,01,03,00,13,00,00
|
||||||
|
server sent: 03,2D,01,03,00,13,00,00,2C,01,03,00,13,00,00,2B,01,03,00,13,00,00
|
||||||
|
client sent: 03,22,01,03,00,13,00,00,21,01,03,00,13,00,00,20,01,03,00,13,00,00
|
||||||
|
server sent: 03,2E,01,03,00,13,00,00,2D,01,03,00,13,00,00,2C,01,03,00,13,00,00
|
||||||
|
client sent: 03,23,01,03,00,13,00,00,22,01,03,00,13,00,00,21,01,03,00,13,00,00
|
||||||
|
server sent: 03,2F,01,03,00,13,00,00,2E,01,03,00,13,00,00,2D,01,03,00,13,00,00
|
||||||
|
client sent: 03,24,01,03,00,13,00,00,23,01,03,00,13,00,00,22,01,03,00,13,00,00
|
||||||
|
server sent: 03,30,01,03,00,13,00,00,2F,01,03,00,13,00,00,2E,01,03,00,13,00,00
|
||||||
|
client sent: 03,25,01,03,00,13,00,00,24,01,03,00,13,00,00,23,01,03,00,13,00,00
|
||||||
|
server sent: 03,31,01,03,00,13,00,00,30,01,03,00,13,00,00,2F,01,03,00,13,00,00
|
||||||
|
client sent: 03,26,01,03,00,13,00,00,25,01,03,00,13,00,00,24,01,03,00,13,00,00
|
||||||
|
server sent: 03,32,01,03,00,13,00,00,31,01,03,00,13,00,00,30,01,03,00,13,00,00
|
||||||
|
client sent: 03,27,01,03,00,13,00,00,26,01,03,00,13,00,00,25,01,03,00,13,00,00
|
||||||
|
server sent: 03,33,01,03,00,13,00,00,32,01,03,00,13,00,00,31,01,03,00,13,00,00
|
||||||
|
client sent: 03,28,01,03,00,13,00,00,27,01,03,00,13,00,00,26,01,03,00,13,00,00
|
||||||
|
server sent: 03,34,01,03,00,13,00,00,33,01,03,00,13,00,00,32,01,03,00,13,00,00
|
||||||
|
client sent: 03,29,01,03,00,13,00,00,28,01,03,00,13,00,00,27,01,03,00,13,00,00
|
||||||
|
server sent: 03,35,01,03,00,13,00,00,34,01,03,00,13,00,00,33,01,03,00,13,00,00
|
||||||
|
client sent: 03,2A,01,03,00,13,00,00,29,01,03,00,13,00,00,28,01,03,00,13,00,00
|
||||||
|
server sent: 03,36,01,03,00,13,00,00,35,01,03,00,13,00,00,34,01,03,00,13,00,00
|
||||||
|
client sent: 03,2B,01,03,00,13,00,00,2A,01,03,00,13,00,00,29,01,03,00,13,00,00
|
||||||
|
server sent: 03,37,01,03,00,13,00,00,36,01,03,00,13,00,00,35,01,03,00,13,00,00
|
||||||
|
client sent: 03,2C,01,03,00,13,00,00,2B,01,03,00,13,00,00,2A,01,03,00,13,00,00
|
||||||
|
server sent: 03,38,01,03,00,13,00,00,37,01,03,00,13,00,00,36,01,03,00,13,00,00
|
||||||
|
client sent: 03,2D,01,03,00,13,00,00,2C,01,03,00,13,00,00,2B,01,03,00,13,00,00
|
||||||
|
server sent: 03,39,01,03,00,13,00,00,38,01,03,00,13,00,00,37,01,03,00,13,00,00
|
||||||
|
client sent: 03,2E,01,03,00,13,00,00,2D,01,03,00,13,00,00,2C,01,03,00,13,00,00
|
||||||
|
server sent: 03,3A,01,03,00,13,00,00,39,01,03,00,13,00,00,38,01,03,00,13,00,00
|
||||||
|
client sent: 03,2F,01,03,00,13,00,00,2E,01,03,00,13,00,00,2D,01,03,00,13,00,00
|
||||||
|
server sent: 03,3B,01,03,00,13,00,00,3A,01,03,00,13,00,00,39,01,03,00,13,00,00
|
||||||
|
client sent: 03,30,01,03,00,13,00,00,2F,01,03,00,13,00,00,2E,01,03,00,13,00,00
|
||||||
|
server sent: 03,3C,01,03,00,13,00,00,3B,01,03,00,13,00,00,3A,01,03,00,13,00,00
|
||||||
|
client sent: 03,31,01,03,00,13,00,00,30,01,03,00,13,00,00,2F,01,03,00,13,00,00
|
||||||
|
server sent: 03,3D,01,03,00,13,00,00,3C,01,03,00,13,00,00,3B,01,03,00,13,00,00
|
||||||
|
client sent: 03,32,01,03,00,13,00,00,31,01,03,00,13,00,00,30,01,03,00,13,00,00
|
||||||
|
server sent: 03,3E,01,03,00,13,00,00,3D,01,03,00,13,00,00,3C,01,03,00,13,00,00
|
||||||
|
client sent: 03,33,01,03,00,13,00,00,32,01,03,00,13,00,00,31,01,03,00,13,00,00
|
||||||
|
server sent: 03,3F,01,03,00,13,00,00,3E,01,03,00,13,00,00,3D,01,03,00,13,00,00
|
||||||
|
client sent: 03,34,01,03,00,13,00,03,33,01,03,00,13,00,00,32,01,03,00,13,00,00
|
||||||
|
server sent: 03,40,01,03,00,13,00,03,3F,01,03,00,13,00,00,3E,01,03,00,13,00,00
|
||||||
|
client sent: 03,35,01,03,00,13,00,00,34,01,03,00,13,00,03,33,01,03,00,13,00,00
|
||||||
|
server sent: 03,41,01,03,00,13,00,00,40,01,03,00,13,00,03,3F,01,03,00,13,00,00
|
||||||
|
client sent: 03,36,01,03,00,13,00,00,35,01,03,00,13,00,00,34,01,03,00,13,00,03
|
||||||
|
server sent: 03,42,01,03,00,13,00,00,41,01,03,00,13,00,00,40,01,03,00,13,00,03
|
||||||
|
client sent: 03,37,01,03,00,13,00,00,36,01,03,00,13,00,00,35,01,03,00,13,00,00
|
||||||
|
server sent: 03,43,01,03,00,13,00,00,42,01,03,00,13,00,00,41,01,03,00,13,00,00
|
||||||
|
client sent: 03,38,01,03,00,13,00,00,37,01,03,00,13,00,00,36,01,03,00,13,00,00
|
||||||
|
server sent: 03,44,01,03,00,13,00,00,43,01,03,00,13,00,00,42,01,03,00,13,00,00
|
||||||
|
client sent: 03,39,01,03,00,13,00,00,38,01,03,00,13,00,00,37,01,03,00,13,00,00
|
||||||
|
server sent: 03,45,01,03,00,13,00,00,44,01,03,00,13,00,00,43,01,03,00,13,00,00
|
||||||
|
client sent: 03,3A,01,03,00,13,00,00,39,01,03,00,13,00,00,38,01,03,00,13,00,00
|
||||||
|
server sent: 03,46,01,03,00,13,00,00,45,01,03,00,13,00,00,44,01,03,00,13,00,00
|
||||||
|
client sent: 03,3B,01,03,00,13,00,00,3A,01,03,00,13,00,00,39,01,03,00,13,00,00
|
||||||
|
server sent: 03,47,01,03,00,13,00,00,46,01,03,00,13,00,00,45,01,03,00,13,00,00
|
||||||
|
client sent: 03,3C,01,03,00,13,00,00,3B,01,03,00,13,00,00,3A,01,03,00,13,00,00
|
||||||
|
server sent: 03,48,01,03,00,13,00,00,47,01,03,00,13,00,00,46,01,03,00,13,00,00
|
||||||
|
client sent: 03,3D,01,03,00,13,00,00,3C,01,03,00,13,00,00,3B,01,03,00,13,00,00
|
||||||
|
server sent: 03,49,01,03,00,13,00,00,48,01,03,00,13,00,00,47,01,03,00,13,00,00
|
||||||
|
|
||||||
|
|
BIN
doc/screenshot1.gif
Normal file
BIN
doc/screenshot1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
doc/screenshot2.gif
Normal file
BIN
doc/screenshot2.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
246
eclipse_code_formatter.xml
Normal file
246
eclipse_code_formatter.xml
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<profiles version="8">
|
||||||
|
<profile name="EmuLinker" version="8">
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="999"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="500"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
5
questions.txt
Normal file
5
questions.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
q:How old are you on your first birthday?
|
||||||
|
a:1
|
||||||
|
|
||||||
|
q:How old are you on your second birthday?
|
||||||
|
a:two
|
8
scores.txt
Normal file
8
scores.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ip:/127.0.0.1
|
||||||
|
s:3
|
||||||
|
n:SupraFast
|
||||||
|
|
||||||
|
ip:/127.0.0.1
|
||||||
|
s:3
|
||||||
|
n:SupraFast
|
||||||
|
|
9
src/org/emulinker/kaillera/access/AccessException.java
Normal file
9
src/org/emulinker/kaillera/access/AccessException.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package org.emulinker.kaillera.access;
|
||||||
|
|
||||||
|
public class AccessException extends Exception
|
||||||
|
{
|
||||||
|
public AccessException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
108
src/org/emulinker/kaillera/access/AccessManager.java
Normal file
108
src/org/emulinker/kaillera/access/AccessManager.java
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package org.emulinker.kaillera.access;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An AccessManager is used retrieve, check, and store user access levels and permissions, and game and emulator
|
||||||
|
* filters. This interface defines the static access levels and methods that an AccessManager must implement. How the
|
||||||
|
* access permissions are stored, checked, and manipulated is left to the implementation class.<br>
|
||||||
|
* <br>
|
||||||
|
* Most of the main EmuLinker components are passed a handle to the current AccessManager and make calls to it upon
|
||||||
|
* user interactions.<br>
|
||||||
|
* <br>
|
||||||
|
* AccessManager is a top-level EmuLinker component; it's implementation class is loaded via PicoContainer upon startup.
|
||||||
|
*
|
||||||
|
* @author Paul Cowan
|
||||||
|
* @see www.emulinker.org
|
||||||
|
*/
|
||||||
|
public interface AccessManager
|
||||||
|
{
|
||||||
|
public static int ACCESS_BANNED = 0;
|
||||||
|
public static int ACCESS_NORMAL = 1;
|
||||||
|
public static int ACCESS_ELEVATED = 2;
|
||||||
|
public static int ACCESS_MODERATOR = 3;
|
||||||
|
public static int ACCESS_ADMIN = 4;
|
||||||
|
public static int ACCESS_SUPERADMIN = 5;
|
||||||
|
|
||||||
|
public static String[] ACCESS_NAMES = { "Banned", "Normal", "Elevated", "Moderator", "Admin", "SuperAdmin"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if address is allowed to connect.
|
||||||
|
*
|
||||||
|
* @param address IP Address of client
|
||||||
|
* @return true if address is allowed to connect
|
||||||
|
*/
|
||||||
|
public boolean isAddressAllowed(InetAddress address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if address is silenced
|
||||||
|
*
|
||||||
|
* @param address IP Address of client
|
||||||
|
* @return true if address is silenced
|
||||||
|
*/
|
||||||
|
public boolean isSilenced(InetAddress address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if client's emulator is allowed (not filtered)
|
||||||
|
*
|
||||||
|
* @param emulator Emulator name of client
|
||||||
|
* @return true if emulator is allowed
|
||||||
|
*/
|
||||||
|
public boolean isEmulatorAllowed(String emulator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if client's game (ROM) is allowed (not filtered)
|
||||||
|
*
|
||||||
|
* @param game Game name of client
|
||||||
|
* @return true if game is allowed
|
||||||
|
*/
|
||||||
|
public boolean isGameAllowed(String game);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the client's assigned access level
|
||||||
|
*
|
||||||
|
* @param address IP Address of client
|
||||||
|
* @return The access level or the default access level if not found
|
||||||
|
*/
|
||||||
|
public int getAccess(InetAddress address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a login announcement string
|
||||||
|
*
|
||||||
|
* @param address IP Address of client
|
||||||
|
* @return The login announcement, null if not defined
|
||||||
|
*/
|
||||||
|
public String getAnnouncement(InetAddress address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporairly adds a user to the nanned list using a pattern algorythm defined by the AccessManager implementation.
|
||||||
|
* While active, <code>isAddressAllowed</code> should return false, and <code>getAccess</code> should return
|
||||||
|
* <code>ACCESS_BANNED</code>.
|
||||||
|
*
|
||||||
|
* @param pattern A pattern to match to an address
|
||||||
|
* @param minutes Number of minutes this ban is valid from the time of addition
|
||||||
|
*/
|
||||||
|
public void addTempBan(String pattern, int minutes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporairly adds a user to the admin list using a pattern algorythm defined by the AccessManager implementation.
|
||||||
|
* While active, <code>getAccess</code> should return <code>ACCESS_ADMIN</code>.
|
||||||
|
*
|
||||||
|
* @param pattern A pattern to match to an address
|
||||||
|
* @param minutes Number of minutes this grant is valid from the time of addition
|
||||||
|
*/
|
||||||
|
public void addTempAdmin(String pattern, int minutes);
|
||||||
|
|
||||||
|
public void addTempElevated(String pattern, int minutes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporairly adds a user to the silenced list using a pattern algorythm defined by the AccessManager
|
||||||
|
* implementation. While active, <code>isSilenced</code> should return <code>true</code>.
|
||||||
|
*
|
||||||
|
* @param pattern A pattern to match to an address
|
||||||
|
* @param minutes Number of minutes this grant is valid from the time of addition
|
||||||
|
*/
|
||||||
|
public void addSilenced(String pattern, int minutes);
|
||||||
|
|
||||||
|
public boolean clearTemp(InetAddress address);
|
||||||
|
}
|
924
src/org/emulinker/kaillera/access/AccessManager2.java
Normal file
924
src/org/emulinker/kaillera/access/AccessManager2.java
Normal file
@ -0,0 +1,924 @@
|
|||||||
|
package org.emulinker.kaillera.access;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.util.WildcardStringPattern;
|
||||||
|
import org.picocontainer.Startable;
|
||||||
|
|
||||||
|
public class AccessManager2 implements AccessManager, Startable, Runnable
|
||||||
|
{
|
||||||
|
static
|
||||||
|
{
|
||||||
|
java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
|
||||||
|
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "60");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(AccessManager2.class);
|
||||||
|
|
||||||
|
private ThreadPoolExecutor threadPool;
|
||||||
|
private boolean isRunning = false;
|
||||||
|
private boolean stopFlag = false;
|
||||||
|
|
||||||
|
private File accessFile;
|
||||||
|
private long lastLoadModifiedTime = -1;
|
||||||
|
|
||||||
|
private List<UserAccess> userList = new CopyOnWriteArrayList<UserAccess>();
|
||||||
|
private List<GameAccess> gameList = new CopyOnWriteArrayList<GameAccess>();
|
||||||
|
private List<EmulatorAccess> emulatorList = new CopyOnWriteArrayList<EmulatorAccess>();
|
||||||
|
private List<AddressAccess> addressList = new CopyOnWriteArrayList<AddressAccess>();
|
||||||
|
private List<TempBan> tempBanList = new CopyOnWriteArrayList<TempBan>();
|
||||||
|
private List<TempAdmin> tempAdminList = new CopyOnWriteArrayList<TempAdmin>();
|
||||||
|
private List<TempElevated> tempElevatedList = new CopyOnWriteArrayList<TempElevated>();
|
||||||
|
private List<Silence> silenceList = new CopyOnWriteArrayList<Silence>();
|
||||||
|
|
||||||
|
public AccessManager2(ThreadPoolExecutor threadPool) throws NoSuchElementException, FileNotFoundException
|
||||||
|
{
|
||||||
|
this.threadPool = threadPool;
|
||||||
|
|
||||||
|
URL url = AccessManager2.class.getResource("/access.cfg");
|
||||||
|
if (url == null)
|
||||||
|
throw new FileNotFoundException("Resource not found: /access.conf");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
accessFile = new File(url.toURI());
|
||||||
|
}
|
||||||
|
catch (URISyntaxException e)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accessFile.exists())
|
||||||
|
throw new FileNotFoundException("Resource not found: /access.conf");
|
||||||
|
|
||||||
|
if (!accessFile.canRead())
|
||||||
|
throw new FileNotFoundException("Can not read: /access.conf");
|
||||||
|
|
||||||
|
loadAccess();
|
||||||
|
|
||||||
|
threadPool.execute(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void start()
|
||||||
|
{
|
||||||
|
log.debug("AccessManager2 thread received start request!");
|
||||||
|
log.debug("AccessManager2 thread starting (ThreadPool:" + threadPool.getActiveCount() + "/" + threadPool.getPoolSize() + ")");
|
||||||
|
threadPool.execute(this);
|
||||||
|
Thread.yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRunning()
|
||||||
|
{
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stop()
|
||||||
|
{
|
||||||
|
log.debug("AccessManager2 thread received stop request!");
|
||||||
|
|
||||||
|
if (!isRunning())
|
||||||
|
{
|
||||||
|
log.debug("KailleraServer thread stop request ignored: not running!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopFlag = true;
|
||||||
|
|
||||||
|
userList.clear();
|
||||||
|
gameList.clear();
|
||||||
|
emulatorList.clear();
|
||||||
|
addressList.clear();
|
||||||
|
tempBanList.clear();
|
||||||
|
tempElevatedList.clear();
|
||||||
|
tempAdminList.clear();
|
||||||
|
silenceList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
isRunning = true;
|
||||||
|
log.debug("AccessManager2 thread running...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!stopFlag)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(60 * 1000);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
log.error("Sleep Interrupted!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopFlag)
|
||||||
|
break;
|
||||||
|
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
for (TempBan tempBan : tempBanList)
|
||||||
|
{
|
||||||
|
if (tempBan.isExpired())
|
||||||
|
tempBanList.remove(tempBan);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempAdmin tempAdmin : tempAdminList)
|
||||||
|
{
|
||||||
|
if (tempAdmin.isExpired())
|
||||||
|
tempAdminList.remove(tempAdmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempElevated tempElevated : tempElevatedList)
|
||||||
|
{
|
||||||
|
if (tempElevated .isExpired())
|
||||||
|
tempElevatedList.remove(tempElevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Silence silence : silenceList)
|
||||||
|
{
|
||||||
|
if (silence.isExpired())
|
||||||
|
silenceList.remove(silence);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(UserAccess userAccess : userList)
|
||||||
|
{
|
||||||
|
userAccess.refreshDNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(AddressAccess addressAccess : addressList)
|
||||||
|
{
|
||||||
|
addressAccess.refreshDNS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
if (!stopFlag)
|
||||||
|
log.fatal("AccessManager2 thread caught unexpected exception: " + e, e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
log.debug("AccessManager2 thread exiting...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void checkReload()
|
||||||
|
{
|
||||||
|
if (accessFile != null && accessFile.lastModified() > lastLoadModifiedTime)
|
||||||
|
loadAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void loadAccess()
|
||||||
|
{
|
||||||
|
if (accessFile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log.info("Reloading permissions...");
|
||||||
|
|
||||||
|
lastLoadModifiedTime = accessFile.lastModified();
|
||||||
|
|
||||||
|
userList.clear();
|
||||||
|
gameList.clear();
|
||||||
|
emulatorList.clear();
|
||||||
|
addressList.clear();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(accessFile));
|
||||||
|
String line = null;
|
||||||
|
while ((line = reader.readLine()) != null)
|
||||||
|
{
|
||||||
|
if (line.length() == 0 || line.startsWith("#") || line.startsWith("//"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
StringTokenizer st = new StringTokenizer(line, ",");
|
||||||
|
if (st.countTokens() < 3)
|
||||||
|
{
|
||||||
|
log.error("Failed to load access line, too few tokens: " + line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = st.nextToken();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (type.equalsIgnoreCase("user"))
|
||||||
|
userList.add(new UserAccess(st));
|
||||||
|
else if (type.equalsIgnoreCase("game"))
|
||||||
|
gameList.add(new GameAccess(st));
|
||||||
|
else if (type.equalsIgnoreCase("emulator"))
|
||||||
|
emulatorList.add(new EmulatorAccess(st));
|
||||||
|
else if (type.equalsIgnoreCase("ipaddress"))
|
||||||
|
addressList.add(new AddressAccess(st));
|
||||||
|
else
|
||||||
|
throw new Exception("Unrecognized access type: " + type);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Failed to load access line: " + e.getMessage() + ": " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to load access file: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTempBan(String addressPattern, int minutes)
|
||||||
|
{
|
||||||
|
tempBanList.add(new TempBan(addressPattern, minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTempAdmin(String addressPattern, int minutes)
|
||||||
|
{
|
||||||
|
tempAdminList.add(new TempAdmin(addressPattern, minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTempElevated(String addressPattern, int minutes)
|
||||||
|
{
|
||||||
|
tempElevatedList.add(new TempElevated(addressPattern, minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSilenced(String addressPattern, int minutes)
|
||||||
|
{
|
||||||
|
silenceList.add(new Silence(addressPattern, minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String getAnnouncement(InetAddress address)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
String userAddress = address.getHostAddress();
|
||||||
|
for (UserAccess userAccess : userList)
|
||||||
|
{
|
||||||
|
if (userAccess.matches(userAddress))
|
||||||
|
return userAccess.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getAccess(InetAddress address)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
|
||||||
|
String userAddress = address.getHostAddress();
|
||||||
|
|
||||||
|
for (TempAdmin tempAdmin : tempAdminList)
|
||||||
|
{
|
||||||
|
if (tempAdmin.matches(userAddress) && !tempAdmin.isExpired())
|
||||||
|
return ACCESS_ADMIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempElevated tempElevated : tempElevatedList)
|
||||||
|
{
|
||||||
|
if (tempElevated.matches(userAddress) && !tempElevated.isExpired())
|
||||||
|
return ACCESS_ELEVATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UserAccess userAccess : userList)
|
||||||
|
{
|
||||||
|
if (userAccess.matches(userAddress))
|
||||||
|
return userAccess.getAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ACCESS_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean clearTemp(InetAddress address)
|
||||||
|
{
|
||||||
|
String userAddress = address.getHostAddress();
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (Silence silence : silenceList)
|
||||||
|
{
|
||||||
|
if (silence.matches(userAddress))
|
||||||
|
{
|
||||||
|
silenceList.remove(silence);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempBan tempBan : tempBanList)
|
||||||
|
{
|
||||||
|
if (tempBan.matches(userAddress) && !tempBan.isExpired())
|
||||||
|
{
|
||||||
|
tempBanList.remove(tempBan);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempElevated tempElevated : tempElevatedList)
|
||||||
|
{
|
||||||
|
if (tempElevated.matches(userAddress))
|
||||||
|
{
|
||||||
|
tempElevatedList.remove(tempElevated);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TempAdmin tempAdmin : tempAdminList)
|
||||||
|
{
|
||||||
|
if (tempAdmin.matches(userAddress))
|
||||||
|
{
|
||||||
|
tempAdminList.remove(tempAdmin);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isSilenced(InetAddress address)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
|
||||||
|
String userAddress = address.getHostAddress();
|
||||||
|
|
||||||
|
for (Silence silence : silenceList)
|
||||||
|
{
|
||||||
|
if (silence.matches(userAddress) && !silence.isExpired())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isAddressAllowed(InetAddress address)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
|
||||||
|
String userAddress = address.getHostAddress();
|
||||||
|
|
||||||
|
for (TempBan tempBan : tempBanList)
|
||||||
|
{
|
||||||
|
if (tempBan.matches(userAddress) && !tempBan.isExpired())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AddressAccess addressAccess : addressList)
|
||||||
|
{
|
||||||
|
if (addressAccess.matches(userAddress))
|
||||||
|
return addressAccess.getAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isEmulatorAllowed(String emulator)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
|
||||||
|
for (EmulatorAccess emulatorAccess : emulatorList)
|
||||||
|
{
|
||||||
|
if (emulatorAccess.matches(emulator))
|
||||||
|
return emulatorAccess.getAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isGameAllowed(String game)
|
||||||
|
{
|
||||||
|
checkReload();
|
||||||
|
|
||||||
|
for (GameAccess gameAccess : gameList)
|
||||||
|
{
|
||||||
|
if (gameAccess.matches(game))
|
||||||
|
return gameAccess.getAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class UserAccess
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected List<String> hostNames;
|
||||||
|
protected List<String> resolvedAddresses;
|
||||||
|
protected int access;
|
||||||
|
protected String message;
|
||||||
|
|
||||||
|
protected UserAccess(StringTokenizer st) throws Exception
|
||||||
|
{
|
||||||
|
if (st.countTokens() < 2 || st.countTokens() > 3)
|
||||||
|
throw new Exception("Wrong number of tokens: " + st.countTokens());
|
||||||
|
|
||||||
|
String accessStr = st.nextToken().toLowerCase();
|
||||||
|
if (accessStr.equals("normal"))
|
||||||
|
access = ACCESS_NORMAL;
|
||||||
|
else if (accessStr.equals("elevated"))
|
||||||
|
access = ACCESS_ELEVATED;
|
||||||
|
else if (accessStr.equals("moderator"))
|
||||||
|
access = ACCESS_MODERATOR;
|
||||||
|
else if (accessStr.equals("admin"))
|
||||||
|
access = ACCESS_ADMIN;
|
||||||
|
else if (accessStr.equals("superadmin"))
|
||||||
|
access = ACCESS_SUPERADMIN;
|
||||||
|
else
|
||||||
|
throw new AccessException("Unrecognized access token: " + accessStr);
|
||||||
|
|
||||||
|
hostNames = new ArrayList<String>();
|
||||||
|
resolvedAddresses = new ArrayList<String>();
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
|
||||||
|
String s = st.nextToken().toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String pat = pt.nextToken().toLowerCase();
|
||||||
|
if(pat.startsWith("dns:"))
|
||||||
|
{
|
||||||
|
if(pat.length() <= 5)
|
||||||
|
throw new AccessException("Malformatted DNS entry: " + s);
|
||||||
|
String hostName = pat.substring(4);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InetAddress a = InetAddress.getByName(hostName);
|
||||||
|
log.debug("Resolved " + hostName + " to " + a.getHostAddress());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
log.warn("Failed to resolve DNS entry to an address: " + hostName + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
hostNames.add(pat.substring(4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDNS();
|
||||||
|
|
||||||
|
if (st.hasMoreTokens())
|
||||||
|
message = st.nextToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void refreshDNS()
|
||||||
|
{
|
||||||
|
resolvedAddresses.clear();
|
||||||
|
for(String hostName: hostNames)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InetAddress address = InetAddress.getByName(hostName);
|
||||||
|
resolvedAddresses.add(address.getHostAddress());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to resolve DNS entry to an address: " + hostName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getAccess()
|
||||||
|
{
|
||||||
|
return access;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String resolvedAddress : resolvedAddresses)
|
||||||
|
{
|
||||||
|
if (resolvedAddress.equals(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class AddressAccess
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected List<String> hostNames;
|
||||||
|
protected List<String> resolvedAddresses;
|
||||||
|
protected boolean access;
|
||||||
|
|
||||||
|
protected AddressAccess(StringTokenizer st) throws Exception
|
||||||
|
{
|
||||||
|
if (st.countTokens() != 2)
|
||||||
|
throw new Exception("Wrong number of tokens: " + st.countTokens());
|
||||||
|
|
||||||
|
String accessStr = st.nextToken().toLowerCase();
|
||||||
|
if (accessStr.equals("allow"))
|
||||||
|
access = true;
|
||||||
|
else if (accessStr.equals("deny"))
|
||||||
|
access = false;
|
||||||
|
else
|
||||||
|
throw new AccessException("Unrecognized access token: " + accessStr);
|
||||||
|
|
||||||
|
hostNames = new ArrayList<String>();
|
||||||
|
resolvedAddresses = new ArrayList<String>();
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
|
||||||
|
String s = st.nextToken().toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String pat = pt.nextToken().toLowerCase();
|
||||||
|
if(pat.startsWith("dns:"))
|
||||||
|
{
|
||||||
|
if(pat.length() <= 5)
|
||||||
|
throw new AccessException("Malformatted DNS entry: " + s);
|
||||||
|
String hostName = pat.substring(4);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InetAddress a = InetAddress.getByName(hostName);
|
||||||
|
log.debug("Resolved " + hostName + " to " + a.getHostAddress());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
log.warn("Failed to resolve DNS entry to an address: " + hostName + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
hostNames.add(pat.substring(4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void refreshDNS()
|
||||||
|
{
|
||||||
|
resolvedAddresses.clear();
|
||||||
|
for(String hostName: hostNames)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InetAddress address = InetAddress.getByName(hostName);
|
||||||
|
resolvedAddresses.add(address.getHostAddress());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to resolve DNS entry to an address: " + hostName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean getAccess()
|
||||||
|
{
|
||||||
|
return access;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String resolvedAddress : resolvedAddresses)
|
||||||
|
{
|
||||||
|
if (resolvedAddress.equals(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class EmulatorAccess
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected boolean access;
|
||||||
|
|
||||||
|
protected EmulatorAccess(StringTokenizer st) throws Exception
|
||||||
|
{
|
||||||
|
if (st.countTokens() != 2)
|
||||||
|
throw new Exception("Wrong number of tokens: " + st.countTokens());
|
||||||
|
|
||||||
|
String accessStr = st.nextToken().toLowerCase();
|
||||||
|
if (accessStr.equals("allow"))
|
||||||
|
access = true;
|
||||||
|
else if (accessStr.equals("deny"))
|
||||||
|
access = false;
|
||||||
|
else
|
||||||
|
throw new AccessException("Unrecognized access token: " + accessStr);
|
||||||
|
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = st.nextToken().toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean getAccess()
|
||||||
|
{
|
||||||
|
return access;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String emulator)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(emulator.toLowerCase()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class GameAccess
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected boolean access;
|
||||||
|
|
||||||
|
protected GameAccess(StringTokenizer st) throws Exception
|
||||||
|
{
|
||||||
|
if (st.countTokens() != 2)
|
||||||
|
throw new Exception("Wrong number of tokens: " + st.countTokens());
|
||||||
|
|
||||||
|
String accessStr = st.nextToken().toLowerCase();
|
||||||
|
if (accessStr.equals("allow"))
|
||||||
|
access = true;
|
||||||
|
else if (accessStr.equals("deny"))
|
||||||
|
access = false;
|
||||||
|
else
|
||||||
|
throw new AccessException("Unrecognized access token: " + accessStr);
|
||||||
|
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = st.nextToken().toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean getAccess()
|
||||||
|
{
|
||||||
|
return access;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String game)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(game.toLowerCase()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TempBan
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected long startTime;
|
||||||
|
protected int minutes;
|
||||||
|
|
||||||
|
protected TempBan(String accessStr, int minutes)
|
||||||
|
{
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = accessStr.toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minutes = minutes;
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMinutes()
|
||||||
|
{
|
||||||
|
return minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isExpired()
|
||||||
|
{
|
||||||
|
if (System.currentTimeMillis() > (startTime + (minutes * 60000)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TempAdmin
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected long startTime;
|
||||||
|
protected int minutes;
|
||||||
|
|
||||||
|
protected TempAdmin(String accessStr, int minutes)
|
||||||
|
{
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = accessStr.toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minutes = minutes;
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMinutes()
|
||||||
|
{
|
||||||
|
return minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isExpired()
|
||||||
|
{
|
||||||
|
if (System.currentTimeMillis() > (startTime + (minutes * 60000)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TempElevated
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected long startTime;
|
||||||
|
protected int minutes;
|
||||||
|
|
||||||
|
protected TempElevated(String accessStr, int minutes)
|
||||||
|
{
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = accessStr.toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minutes = minutes;
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMinutes()
|
||||||
|
{
|
||||||
|
return minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isExpired()
|
||||||
|
{
|
||||||
|
if (System.currentTimeMillis() > (startTime + (minutes * 60000)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected class Silence
|
||||||
|
{
|
||||||
|
protected List<WildcardStringPattern> patterns;
|
||||||
|
protected long startTime;
|
||||||
|
protected int minutes;
|
||||||
|
|
||||||
|
protected Silence(String accessStr, int minutes)
|
||||||
|
{
|
||||||
|
patterns = new ArrayList<WildcardStringPattern>();
|
||||||
|
String s = accessStr.toLowerCase();
|
||||||
|
StringTokenizer pt = new StringTokenizer(s, "|");
|
||||||
|
while (pt.hasMoreTokens())
|
||||||
|
{
|
||||||
|
patterns.add(new WildcardStringPattern(pt.nextToken().toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minutes = minutes;
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<WildcardStringPattern> getPatterns()
|
||||||
|
{
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMinutes()
|
||||||
|
{
|
||||||
|
return minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isExpired()
|
||||||
|
{
|
||||||
|
if (System.currentTimeMillis() > (startTime + (minutes * 60000)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean matches(String address)
|
||||||
|
{
|
||||||
|
for (WildcardStringPattern pattern : patterns)
|
||||||
|
{
|
||||||
|
if (pattern.match(address))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
251
src/org/emulinker/kaillera/access/BasicAccessManager.java
Normal file
251
src/org/emulinker/kaillera/access/BasicAccessManager.java
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
package org.emulinker.kaillera.access;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.configuration.*;
|
||||||
|
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.util.EmuLinkerXMLConfig;
|
||||||
|
|
||||||
|
public class BasicAccessManager implements AccessManager
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(BasicAccessManager.class);
|
||||||
|
|
||||||
|
private String accessFileName;
|
||||||
|
private XMLConfiguration config;
|
||||||
|
private Map<String, Admin> admins = new HashMap<String, Admin>();
|
||||||
|
private List<String> bannedAddresses = new ArrayList<String>();
|
||||||
|
private List<String> bannedNames = new ArrayList<String>();
|
||||||
|
|
||||||
|
public BasicAccessManager(Configuration config) throws NoSuchElementException
|
||||||
|
{
|
||||||
|
accessFileName = config.getString("accessManager.basic.fileName");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.config = new XMLConfiguration(EmuLinkerXMLConfig.class.getResource("/" + accessFileName));
|
||||||
|
this.config.setReloadingStrategy(new AccessManagerReloader());
|
||||||
|
}
|
||||||
|
catch (ConfigurationException e)
|
||||||
|
{
|
||||||
|
log.error("AccessManager failed to load " + accessFileName + ": " + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void loadAccess()
|
||||||
|
{
|
||||||
|
if (config == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log.info("BasicAccessManager reloading permissions...");
|
||||||
|
|
||||||
|
bannedNames = config.getList("banned.names.name");
|
||||||
|
for (String name : bannedNames)
|
||||||
|
log.info("The name \"" + name + "\" will be banned");
|
||||||
|
|
||||||
|
bannedAddresses = config.getList("banned.addresses.address");
|
||||||
|
for (String address : bannedAddresses)
|
||||||
|
log.info("The address \"" + address + "\" will be banned");
|
||||||
|
|
||||||
|
admins.clear();
|
||||||
|
|
||||||
|
Iterator iter = config.getKeys("admins");
|
||||||
|
while (iter.hasNext())
|
||||||
|
{
|
||||||
|
String entry = (String) iter.next();
|
||||||
|
Scanner scanner = new Scanner(entry);
|
||||||
|
scanner.useDelimiter("\\.");
|
||||||
|
|
||||||
|
scanner.next();
|
||||||
|
String adminName = scanner.next();
|
||||||
|
|
||||||
|
if (admins.containsKey(adminName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<String> names = config.getList("admins." + adminName + ".names.name");
|
||||||
|
List<String> addresses = config.getList("admins." + adminName + ".addresses.address");
|
||||||
|
|
||||||
|
Admin admin = new Admin(adminName, names, addresses);
|
||||||
|
log.info("Loading admin access: " + admin);
|
||||||
|
admins.put(adminName, admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isBanned(InetAddress remoteAddress)
|
||||||
|
{
|
||||||
|
// this won't actually reload the config unless it's been changed... this will trigger our loadAccess if there's a change
|
||||||
|
if (config != null)
|
||||||
|
config.reload();
|
||||||
|
|
||||||
|
String hostAddress = remoteAddress.getHostAddress();
|
||||||
|
for (String banned : bannedAddresses)
|
||||||
|
{
|
||||||
|
if (hostAddress.startsWith(banned))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isBanned(String userName)
|
||||||
|
{
|
||||||
|
// this won't actually reload the config unless it's been changed... this will trigger our loadAccess if there's a change
|
||||||
|
if (config != null)
|
||||||
|
config.reload();
|
||||||
|
|
||||||
|
String nameLower = userName.toLowerCase();
|
||||||
|
for (String banned : bannedNames)
|
||||||
|
{
|
||||||
|
if (nameLower.startsWith(banned.toLowerCase()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isBanned(KailleraUser user)
|
||||||
|
{
|
||||||
|
return isBanned(user.getConnectSocketAddress().getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isAdmin(InetAddress remoteAddress)
|
||||||
|
{
|
||||||
|
// this won't actually reload the config unless it's been changed... this will trigger our loadAccess if there's a change
|
||||||
|
if (config != null)
|
||||||
|
config.reload();
|
||||||
|
|
||||||
|
for (Admin admin : admins.values())
|
||||||
|
{
|
||||||
|
if (admin.checkAddress(remoteAddress))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isAdmin(KailleraUser user)
|
||||||
|
{
|
||||||
|
return isAdmin(user.getConnectSocketAddress().getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getAccess(InetAddress remoteAddress, String userName) throws AccessException
|
||||||
|
{
|
||||||
|
// this won't actually reload the config unless it's been changed... this will trigger our loadAccess if there's a change
|
||||||
|
if (config != null)
|
||||||
|
config.reload();
|
||||||
|
|
||||||
|
if (isBanned(remoteAddress))
|
||||||
|
return AccessManager.DENIED;
|
||||||
|
|
||||||
|
if (isBanned(userName))
|
||||||
|
return AccessManager.DENIED;
|
||||||
|
|
||||||
|
for (Admin admin : admins.values())
|
||||||
|
{
|
||||||
|
int access = admin.checkMatch(remoteAddress, userName);
|
||||||
|
if (access == AccessManager.ADMIN)
|
||||||
|
return AccessManager.ADMIN;
|
||||||
|
else if (access == AccessManager.DENIED)
|
||||||
|
return AccessManager.DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AccessManager.USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Admin
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private List<String> names;
|
||||||
|
private List<String> addresses;
|
||||||
|
|
||||||
|
private Admin(String name, List<String> names, List<String> addresses)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.names = names;
|
||||||
|
this.addresses = addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
// this is very inefficient
|
||||||
|
// return "BasicAccessManager.Admin[name=" + name + " loginNames=" + Arrays.toString(names.toArray()) + " addresses=" + Arrays.toString(addresses.toArray()) + "]";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkName(String userName)
|
||||||
|
{
|
||||||
|
String nameLower = userName.toLowerCase();
|
||||||
|
for (String adminName : names)
|
||||||
|
{
|
||||||
|
if (nameLower.startsWith(adminName.toLowerCase()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAddress(InetAddress remoteAddress)
|
||||||
|
{
|
||||||
|
String hostAddress = remoteAddress.getHostAddress();
|
||||||
|
for (String adminAddress : addresses)
|
||||||
|
{
|
||||||
|
if (hostAddress.startsWith(adminAddress))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int checkMatch(InetAddress remoteAddress, String userName) throws AccessException
|
||||||
|
{
|
||||||
|
boolean nameMatches = checkName(userName);
|
||||||
|
boolean addressMatches = checkAddress(remoteAddress);
|
||||||
|
|
||||||
|
if (addressMatches)
|
||||||
|
return AccessManager.ADMIN;
|
||||||
|
else if (nameMatches && !addressMatches)
|
||||||
|
throw new AccessException("Restricted UserName: " + userName);
|
||||||
|
else
|
||||||
|
return AccessManager.USER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AccessManagerReloader extends FileChangedReloadingStrategy
|
||||||
|
{
|
||||||
|
private AccessManagerReloader()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
super.init();
|
||||||
|
loadAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadingPerformed()
|
||||||
|
{
|
||||||
|
super.reloadingPerformed();
|
||||||
|
loadAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean reloadingRequired()
|
||||||
|
{
|
||||||
|
boolean reloadingRequired = super.reloadingRequired();
|
||||||
|
if (reloadingRequired)
|
||||||
|
config.clear();
|
||||||
|
return reloadingRequired;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
8
src/org/emulinker/kaillera/admin/AdminServer.java
Normal file
8
src/org/emulinker/kaillera/admin/AdminServer.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package org.emulinker.kaillera.admin;
|
||||||
|
|
||||||
|
import org.picocontainer.Startable;
|
||||||
|
|
||||||
|
public interface AdminServer extends Startable
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
135
src/org/emulinker/kaillera/admin/KailleraAdminHttpServer.java
Normal file
135
src/org/emulinker/kaillera/admin/KailleraAdminHttpServer.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package org.emulinker.kaillera.admin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import org.apache.commons.configuration.Configuration;
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.connectcontroller.ConnectController;
|
||||||
|
import org.emulinker.kaillera.model.KailleraServer;
|
||||||
|
import org.mortbay.http.*;
|
||||||
|
import org.mortbay.http.handler.*;
|
||||||
|
import org.mortbay.jetty.Server;
|
||||||
|
import org.mortbay.jetty.servlet.*;
|
||||||
|
import org.mortbay.util.InetAddrPort;
|
||||||
|
import org.picocontainer.Startable;
|
||||||
|
|
||||||
|
public class KailleraAdminHttpServer implements Startable
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(KailleraAdminHttpServer.class);
|
||||||
|
|
||||||
|
protected Server appServer = new Server();
|
||||||
|
|
||||||
|
public KailleraAdminHttpServer(Configuration config, ThreadPoolExecutor threadPool, ConnectController connectController, KailleraServer kailleraServer) throws Exception
|
||||||
|
{
|
||||||
|
int port = config.getInt("adminserver.httpport");
|
||||||
|
String jspDir = config.getString("adminserver.jspdir");
|
||||||
|
|
||||||
|
appServer = new Server();
|
||||||
|
appServer.addListener(new InetAddrPort(port));
|
||||||
|
|
||||||
|
ServletHttpContext context = (ServletHttpContext) appServer.getContext(jspDir);
|
||||||
|
context.setAttribute("threadPool", threadPool);
|
||||||
|
context.setAttribute("connectController", connectController);
|
||||||
|
context.setAttribute("kailleraServer", kailleraServer);
|
||||||
|
|
||||||
|
setupSecurity(context, config);
|
||||||
|
|
||||||
|
context.addHandler(new ServletHandler());
|
||||||
|
context.addHandler(new ResourceHandler());
|
||||||
|
context.addHandler(new NotFoundHandler());
|
||||||
|
|
||||||
|
context.setResourceBase(jspDir);
|
||||||
|
context.addServlet("JSP", "*.jsp", "org.apache.jasper.servlet.JspServlet");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Basic authentication for the admin server.
|
||||||
|
*
|
||||||
|
* @param context the context object that is to be configured
|
||||||
|
* @param config the configuration file data from emulinker.xml
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void setupSecurity(ServletHttpContext context, Configuration config) throws IOException
|
||||||
|
{
|
||||||
|
boolean isSecurity = config.getBoolean("adminserver.authenticate", false);
|
||||||
|
|
||||||
|
if (isSecurity)
|
||||||
|
{
|
||||||
|
log.info("Configuring admin server security.");
|
||||||
|
|
||||||
|
String realmName = config.getString("adminserver.realmname");
|
||||||
|
if (realmName == null || realmName.trim().length() == 0)
|
||||||
|
{
|
||||||
|
realmName = "Emulinker";
|
||||||
|
}
|
||||||
|
|
||||||
|
String userFile = config.getString("adminserver.userfile");
|
||||||
|
if (userFile == null || userFile.trim().length() == 0)
|
||||||
|
{
|
||||||
|
userFile = "conf/user.properties";
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Establishing realm " + realmName);
|
||||||
|
log.info("Loading usernames and passwords from " + userFile);
|
||||||
|
|
||||||
|
SecurityHandler sh = new SecurityHandler();
|
||||||
|
sh.setAuthMethod("BASIC");
|
||||||
|
sh.setName(realmName);
|
||||||
|
|
||||||
|
context.addHandler(sh);
|
||||||
|
SecurityConstraint sc = new SecurityConstraint();
|
||||||
|
sc.setAuthenticate(true);
|
||||||
|
sc.setName(SecurityConstraint.__BASIC_AUTH);
|
||||||
|
sc.addRole("*");
|
||||||
|
context.addSecurityConstraint("/*", sc);
|
||||||
|
|
||||||
|
//load the usernames and passwords from a file of the
|
||||||
|
//following form, where password is in plain text
|
||||||
|
//user: password
|
||||||
|
HashUserRealm hur = new HashUserRealm();
|
||||||
|
hur.setName(realmName);
|
||||||
|
hur.load(userFile);
|
||||||
|
context.setRealm(hur);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.info("Admin server security is disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
log.info("Starting Web-based Admin Interface.");
|
||||||
|
|
||||||
|
if (!appServer.isStarted())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
appServer.start();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Failed to start admin server: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
log.info("Stoping!");
|
||||||
|
|
||||||
|
if (appServer.isStarted())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
appServer.stop();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Failed to stop admin server: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.emulinker.kaillera.controller;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.model.KailleraServer;
|
||||||
|
import org.emulinker.kaillera.model.exception.*;
|
||||||
|
import org.picocontainer.Startable;
|
||||||
|
|
||||||
|
public interface KailleraServerController extends Startable
|
||||||
|
{
|
||||||
|
public int newConnection(InetSocketAddress clientSocketAddress, String protocol) throws ServerFullException, NewConnectionException;
|
||||||
|
|
||||||
|
public KailleraServer getServer();
|
||||||
|
|
||||||
|
public int getBufferSize();
|
||||||
|
|
||||||
|
public String getVersion();
|
||||||
|
|
||||||
|
public int getNumClients();
|
||||||
|
|
||||||
|
public String[] getClientTypes();
|
||||||
|
}
|
@ -0,0 +1,279 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import org.apache.commons.configuration.*;
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.KailleraServerController;
|
||||||
|
import org.emulinker.kaillera.controller.connectcontroller.protocol.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.*;
|
||||||
|
import org.emulinker.net.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class ConnectController extends UDPServer
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(ConnectController.class);
|
||||||
|
|
||||||
|
private ThreadPoolExecutor threadPool;
|
||||||
|
private AccessManager accessManager;
|
||||||
|
private Map<String, KailleraServerController> controllersMap;
|
||||||
|
|
||||||
|
private int bufferSize = 0;
|
||||||
|
|
||||||
|
private long startTime;
|
||||||
|
private int requestCount = 0;
|
||||||
|
private int messageFormatErrorCount = 0;
|
||||||
|
private int protocolErrorCount = 0;
|
||||||
|
private int deniedServerFullCount = 0;
|
||||||
|
private int deniedOtherCount = 0;
|
||||||
|
private String lastAddress = null;
|
||||||
|
private int lastAddressCount = 0;
|
||||||
|
private int failedToStartCount = 0;
|
||||||
|
private int connectedCount = 0;
|
||||||
|
private int pingCount = 0;
|
||||||
|
|
||||||
|
public ConnectController(ThreadPoolExecutor threadPool, KailleraServerController[] controllersArray, AccessManager accessManager, Configuration config) throws NoSuchElementException, ConfigurationException, BindException
|
||||||
|
{
|
||||||
|
super(true);
|
||||||
|
|
||||||
|
this.threadPool = threadPool;
|
||||||
|
this.accessManager = accessManager;
|
||||||
|
|
||||||
|
int port = config.getInt("controllers.connect.port");
|
||||||
|
bufferSize = config.getInt("controllers.connect.bufferSize");
|
||||||
|
if (bufferSize <= 0)
|
||||||
|
throw new ConfigurationException("controllers.connect.bufferSize must be > 0");
|
||||||
|
|
||||||
|
controllersMap = new HashMap<String, KailleraServerController>();
|
||||||
|
for (KailleraServerController controller : controllersArray)
|
||||||
|
{
|
||||||
|
String[] clientTypes = controller.getClientTypes();
|
||||||
|
for (int j = 0; j < clientTypes.length; j++)
|
||||||
|
{
|
||||||
|
log.debug("Mapping client type " + clientTypes[j] + " to " + controller);
|
||||||
|
controllersMap.put(clientTypes[j], controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.bind(port);
|
||||||
|
|
||||||
|
System.out.println("Ready to accept connections on port " + port);
|
||||||
|
log.info("Ready to accept connections on port " + port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KailleraServerController getController(String clientType)
|
||||||
|
{
|
||||||
|
return controllersMap.get(clientType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<KailleraServerController> getControllers()
|
||||||
|
{
|
||||||
|
return controllersMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartTime()
|
||||||
|
{
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferSize()
|
||||||
|
{
|
||||||
|
return bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRequestCount()
|
||||||
|
{
|
||||||
|
return requestCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMessageFormatErrorCount()
|
||||||
|
{
|
||||||
|
return messageFormatErrorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getProtocolErrorCount()
|
||||||
|
{
|
||||||
|
return protocolErrorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeniedServerFullCount()
|
||||||
|
{
|
||||||
|
return deniedServerFullCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeniedOtherCount()
|
||||||
|
{
|
||||||
|
return deniedOtherCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFailedToStartCount()
|
||||||
|
{
|
||||||
|
return failedToStartCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnectCount()
|
||||||
|
{
|
||||||
|
return connectedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPingCount()
|
||||||
|
{
|
||||||
|
return pingCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ByteBuffer getBuffer()
|
||||||
|
{
|
||||||
|
return ByteBufferMessage.getBuffer(bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void releaseBuffer(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
ByteBufferMessage.releaseBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
//return "ConnectController[port=" + getBindPort() + " isRunning=" + isRunning() + "]";
|
||||||
|
//return "ConnectController[port=" + getBindPort() + "]";
|
||||||
|
if (getBindPort() > 0)
|
||||||
|
return "ConnectController(" + getBindPort() + ")";
|
||||||
|
else
|
||||||
|
return "ConnectController(unbound)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void start()
|
||||||
|
{
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
log.debug(toString() + " Thread starting (ThreadPool:" + threadPool.getActiveCount() + "/" + threadPool.getPoolSize() + ")");
|
||||||
|
threadPool.execute(this);
|
||||||
|
Thread.yield();
|
||||||
|
log.debug(toString() + " Thread started (ThreadPool:" + threadPool.getActiveCount() + "/" + threadPool.getPoolSize() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stop()
|
||||||
|
{
|
||||||
|
super.stop();
|
||||||
|
for (KailleraServerController controller : controllersMap.values())
|
||||||
|
controller.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void handleReceived(ByteBuffer buffer, InetSocketAddress fromSocketAddress)
|
||||||
|
{
|
||||||
|
requestCount++;
|
||||||
|
|
||||||
|
ConnectMessage inMessage = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inMessage = ConnectMessage.parse(buffer);
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
messageFormatErrorCount++;
|
||||||
|
buffer.rewind();
|
||||||
|
log.warn("Received invalid message from " + EmuUtil.formatSocketAddress(fromSocketAddress) + ": " + EmuUtil.dumpBuffer(buffer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the message set of the ConnectController isn't really complex enough to warrant a complicated request/action class
|
||||||
|
// structure, so I'm going to handle it all in this class alone
|
||||||
|
|
||||||
|
if (inMessage instanceof ConnectMessage_PING)
|
||||||
|
{
|
||||||
|
pingCount++;
|
||||||
|
log.debug("Ping from: " + EmuUtil.formatSocketAddress(fromSocketAddress));
|
||||||
|
send(new ConnectMessage_PONG(), fromSocketAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(inMessage instanceof ConnectMessage_HELLO))
|
||||||
|
{
|
||||||
|
messageFormatErrorCount++;
|
||||||
|
log.warn("Received unexpected message type from " + EmuUtil.formatSocketAddress(fromSocketAddress) + ": " + inMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectMessage_HELLO connectMessage = (ConnectMessage_HELLO) inMessage;
|
||||||
|
|
||||||
|
// now we need to find the specific server this client is request to
|
||||||
|
// connect to using the client type
|
||||||
|
KailleraServerController protocolController = getController(connectMessage.getProtocol());
|
||||||
|
if (protocolController == null)
|
||||||
|
{
|
||||||
|
protocolErrorCount++;
|
||||||
|
log.error("Client requested an unhandled protocol " + EmuUtil.formatSocketAddress(fromSocketAddress) + ": " + connectMessage.getProtocol());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accessManager.isAddressAllowed(fromSocketAddress.getAddress()))
|
||||||
|
{
|
||||||
|
deniedOtherCount++;
|
||||||
|
log.warn("AccessManager denied connection from " + EmuUtil.formatSocketAddress(fromSocketAddress));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int privatePort = -1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//SF MOD - Hammer Protection
|
||||||
|
if(connectedCount > 0){
|
||||||
|
if(lastAddress.equals(fromSocketAddress.getAddress().getHostAddress())){
|
||||||
|
lastAddressCount++;
|
||||||
|
if(lastAddressCount >= 4){
|
||||||
|
lastAddressCount = 0;
|
||||||
|
failedToStartCount++;
|
||||||
|
log.debug("SF MOD: HAMMER PROTECTION (2 Min Ban): " + EmuUtil.formatSocketAddress(fromSocketAddress));
|
||||||
|
accessManager.addTempBan(fromSocketAddress.getAddress().getHostAddress(), 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lastAddress = fromSocketAddress.getAddress().getHostAddress();
|
||||||
|
lastAddressCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lastAddress = fromSocketAddress.getAddress().getHostAddress();
|
||||||
|
|
||||||
|
privatePort = protocolController.newConnection(fromSocketAddress, connectMessage.getProtocol());
|
||||||
|
|
||||||
|
if (privatePort <= 0)
|
||||||
|
{
|
||||||
|
failedToStartCount++;
|
||||||
|
log.error(protocolController + " failed to start for " + EmuUtil.formatSocketAddress(fromSocketAddress));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCount++;
|
||||||
|
log.debug(protocolController + " allocated port " + privatePort + " to client from " + fromSocketAddress.getAddress().getHostAddress());
|
||||||
|
send(new ConnectMessage_HELLOD00D(privatePort), fromSocketAddress);
|
||||||
|
}
|
||||||
|
catch (ServerFullException e)
|
||||||
|
{
|
||||||
|
deniedServerFullCount++;
|
||||||
|
log.debug("Sending server full response to " + EmuUtil.formatSocketAddress(fromSocketAddress));
|
||||||
|
send(new ConnectMessage_TOO(), fromSocketAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (NewConnectionException e)
|
||||||
|
{
|
||||||
|
deniedOtherCount++;
|
||||||
|
log.warn(protocolController + " denied connection from " + EmuUtil.formatSocketAddress(fromSocketAddress) + ": " + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void send(ConnectMessage outMessage, InetSocketAddress toSocketAddress)
|
||||||
|
{
|
||||||
|
send(outMessage.toBuffer(), toSocketAddress);
|
||||||
|
outMessage.releaseBuffer();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.*;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public abstract class ConnectMessage extends ByteBufferMessage
|
||||||
|
{
|
||||||
|
public static Charset charset = Charset.forName("ISO-8859-1");
|
||||||
|
|
||||||
|
protected abstract String getID();
|
||||||
|
|
||||||
|
public static ConnectMessage parse(ByteBuffer buffer) throws MessageFormatException
|
||||||
|
{
|
||||||
|
String messageStr = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CharsetDecoder stringDecoder = charset.newDecoder();
|
||||||
|
messageStr = stringDecoder.decode(buffer).toString();
|
||||||
|
}
|
||||||
|
catch (CharacterCodingException e)
|
||||||
|
{
|
||||||
|
throw new MessageFormatException("Invalid bytes received: failed to decode to a string!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageStr.startsWith(ConnectMessage_TOO.ID))
|
||||||
|
{
|
||||||
|
return ConnectMessage_TOO.parse(messageStr);
|
||||||
|
}
|
||||||
|
else if (messageStr.startsWith(ConnectMessage_HELLOD00D.ID))
|
||||||
|
{
|
||||||
|
return ConnectMessage_HELLOD00D.parse(messageStr);
|
||||||
|
}
|
||||||
|
else if (messageStr.startsWith(ConnectMessage_HELLO.ID))
|
||||||
|
{
|
||||||
|
return ConnectMessage_HELLO.parse(messageStr);
|
||||||
|
}
|
||||||
|
else if (messageStr.startsWith(ConnectMessage_PING.ID))
|
||||||
|
{
|
||||||
|
return ConnectMessage_PING.parse(messageStr);
|
||||||
|
}
|
||||||
|
else if (messageStr.startsWith(ConnectMessage_PONG.ID))
|
||||||
|
{
|
||||||
|
return ConnectMessage_PONG.parse(messageStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.rewind();
|
||||||
|
throw new MessageFormatException("Unrecognized connect message: " + EmuUtil.dumpBuffer(buffer));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class ConnectMessage_HELLO extends ConnectMessage
|
||||||
|
{
|
||||||
|
public static final String ID = "HELLO";
|
||||||
|
public static final String DESC = "Client Connection Request";
|
||||||
|
|
||||||
|
private String protocol;
|
||||||
|
private InetSocketAddress clientSocketAddress;
|
||||||
|
|
||||||
|
public ConnectMessage_HELLO(String protocol)
|
||||||
|
{
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProtocol()
|
||||||
|
{
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSocketAddress(InetSocketAddress clientSocketAddress)
|
||||||
|
{
|
||||||
|
this.clientSocketAddress = clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetSocketAddress getClientSocketAddress()
|
||||||
|
{
|
||||||
|
return clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return DESC + ": protocol: " + protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength()
|
||||||
|
{
|
||||||
|
return (ID.length() + protocol.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put(charset.encode(ID));
|
||||||
|
EmuUtil.writeString(buffer, protocol, 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectMessage parse(String msg) throws MessageFormatException
|
||||||
|
{
|
||||||
|
if (msg.length() < (ID.length() + 2))
|
||||||
|
throw new MessageFormatException("Invalid message length!");
|
||||||
|
|
||||||
|
if (!msg.startsWith(ID))
|
||||||
|
throw new MessageFormatException("Invalid message identifier!");
|
||||||
|
|
||||||
|
if (msg.charAt(msg.length() - 1) != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid message stop byte!");
|
||||||
|
|
||||||
|
return new ConnectMessage_HELLO(msg.substring(ID.length(), (msg.length() - 1)));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class ConnectMessage_HELLOD00D extends ConnectMessage
|
||||||
|
{
|
||||||
|
public static final String ID = "HELLOD00D";
|
||||||
|
public static final String DESC = "Server Connection Response";
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
public ConnectMessage_HELLOD00D(int port)
|
||||||
|
{
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort()
|
||||||
|
{
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return DESC + ": port: " + getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength()
|
||||||
|
{
|
||||||
|
return (ID.length() + Integer.toString(port).length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put(charset.encode(ID));
|
||||||
|
EmuUtil.writeString(buffer, Integer.toString(port), 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectMessage parse(String msg) throws MessageFormatException
|
||||||
|
{
|
||||||
|
if (msg.length() < (ID.length() + 2))
|
||||||
|
throw new MessageFormatException("Invalid message length!");
|
||||||
|
|
||||||
|
if (!msg.startsWith(ID))
|
||||||
|
throw new MessageFormatException("Invalid message identifier!");
|
||||||
|
|
||||||
|
if (msg.charAt(msg.length() - 1) != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid message stop byte!");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int port = Integer.parseInt(msg.substring(ID.length(), (msg.length() - 1)));
|
||||||
|
return new ConnectMessage_HELLOD00D(port);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
throw new MessageFormatException("Invalid port number!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class ConnectMessage_PING extends ConnectMessage
|
||||||
|
{
|
||||||
|
public static final String ID = "PING";
|
||||||
|
public static final String DESC = "Client Ping";
|
||||||
|
|
||||||
|
private InetSocketAddress clientSocketAddress;
|
||||||
|
|
||||||
|
public ConnectMessage_PING()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSocketAddress(InetSocketAddress clientSocketAddress)
|
||||||
|
{
|
||||||
|
this.clientSocketAddress = clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetSocketAddress getClientSocketAddress()
|
||||||
|
{
|
||||||
|
return clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength()
|
||||||
|
{
|
||||||
|
return (ID.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put(charset.encode(ID));
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectMessage parse(String msg) throws MessageFormatException
|
||||||
|
{
|
||||||
|
if (msg.length() != 5)
|
||||||
|
throw new MessageFormatException("Invalid message length!");
|
||||||
|
|
||||||
|
if (!msg.startsWith(ID))
|
||||||
|
throw new MessageFormatException("Invalid message identifier!");
|
||||||
|
|
||||||
|
if (msg.charAt(msg.length() - 1) != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid message stop byte!");
|
||||||
|
|
||||||
|
return new ConnectMessage_PING();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class ConnectMessage_PONG extends ConnectMessage
|
||||||
|
{
|
||||||
|
public static final String ID = "PONG";
|
||||||
|
public static final String DESC = "Server Pong";
|
||||||
|
|
||||||
|
private InetSocketAddress clientSocketAddress;
|
||||||
|
|
||||||
|
public ConnectMessage_PONG()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSocketAddress(InetSocketAddress clientSocketAddress)
|
||||||
|
{
|
||||||
|
this.clientSocketAddress = clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetSocketAddress getClientSocketAddress()
|
||||||
|
{
|
||||||
|
return clientSocketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength()
|
||||||
|
{
|
||||||
|
return (ID.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put(charset.encode(ID));
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectMessage parse(String msg) throws MessageFormatException
|
||||||
|
{
|
||||||
|
if (msg.length() != 5)
|
||||||
|
throw new MessageFormatException("Invalid message length!");
|
||||||
|
|
||||||
|
if (!msg.startsWith(ID))
|
||||||
|
throw new MessageFormatException("Invalid message identifier!");
|
||||||
|
|
||||||
|
if (msg.charAt(msg.length() - 1) != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid message stop byte!");
|
||||||
|
|
||||||
|
return new ConnectMessage_PONG();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.emulinker.kaillera.controller.connectcontroller.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class ConnectMessage_TOO extends ConnectMessage
|
||||||
|
{
|
||||||
|
public static final String ID = "TOO";
|
||||||
|
public static final String DESC = "Server Full Response";
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength()
|
||||||
|
{
|
||||||
|
return (ID.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put(charset.encode(ID));
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectMessage parse(String msg) throws MessageFormatException
|
||||||
|
{
|
||||||
|
if (msg.length() != ID.length() + 1)
|
||||||
|
throw new MessageFormatException("Invalid message length!");
|
||||||
|
|
||||||
|
if (!msg.startsWith(ID))
|
||||||
|
throw new MessageFormatException("Invalid message identifier!");
|
||||||
|
|
||||||
|
if (msg.charAt(msg.length() - 1) != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid message stop byte!");
|
||||||
|
|
||||||
|
return new ConnectMessage_TOO();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package org.emulinker.kaillera.controller.messaging;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
|
||||||
|
public abstract class ByteBufferMessage
|
||||||
|
{
|
||||||
|
protected static Log log = LogFactory.getLog(ByteBufferMessage.class);
|
||||||
|
// public static Charset charset = Charset.forName("US-ASCII");
|
||||||
|
// public static Charset charset = Charset.forName("ISO-8859-1");
|
||||||
|
// public static Charset charset = Charset.forName("UTF-8");
|
||||||
|
public static Charset charset = Charset.defaultCharset();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
String charsetName = System.getProperty("emulinker.charset");
|
||||||
|
if (charsetName != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Charset.isSupported(charsetName))
|
||||||
|
charset = Charset.forName(charsetName);
|
||||||
|
else
|
||||||
|
log.fatal("Charset " + charsetName + " is not supported!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.fatal("Failed to load charset " + charsetName + ": " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Using character set: " + charset.displayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer buffer;
|
||||||
|
|
||||||
|
public abstract int getLength();
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
protected void initBuffer()
|
||||||
|
{
|
||||||
|
initBuffer(getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBuffer(int size)
|
||||||
|
{
|
||||||
|
buffer = getBuffer(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseBuffer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer toBuffer()
|
||||||
|
{
|
||||||
|
initBuffer();
|
||||||
|
writeTo(buffer);
|
||||||
|
buffer.flip();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void writeTo(ByteBuffer buffer);
|
||||||
|
|
||||||
|
public static ByteBuffer getBuffer(int size)
|
||||||
|
{
|
||||||
|
return ByteBuffer.allocateDirect(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void releaseBuffer(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
// nothing to do since we aren't caching buffers anymore
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.emulinker.kaillera.controller.messaging;
|
||||||
|
|
||||||
|
public class MessageFormatException extends Exception
|
||||||
|
{
|
||||||
|
public MessageFormatException()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFormatException(String msg)
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFormatException(String msg, Throwable cause)
|
||||||
|
{
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.emulinker.kaillera.controller.messaging;
|
||||||
|
|
||||||
|
public class ParseException extends Exception
|
||||||
|
{
|
||||||
|
public ParseException()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseException(String msg)
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseException(String msg, Throwable cause)
|
||||||
|
{
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.V086Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a specialized data structure designed to efficiently store and retrieve the last outbound messages sent to a
|
||||||
|
* client. It would be much easier to use a simple LinkedList, but that means we have to use iterators and create node
|
||||||
|
* objects, which causes large amounts of garbage collection considering the rate at which messages flow through the
|
||||||
|
* server.<br>
|
||||||
|
* <br>
|
||||||
|
* This class operates like a circular buffer, but adds messages from back to front. By doing this, we can use
|
||||||
|
* System.aray copy to efficiently copy messages out, start with the newest first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LastMessageBuffer
|
||||||
|
{
|
||||||
|
private int max;
|
||||||
|
private int next;
|
||||||
|
private int size;
|
||||||
|
private V086Message[] array;
|
||||||
|
|
||||||
|
public LastMessageBuffer(int max)
|
||||||
|
{
|
||||||
|
array = new V086Message[max];
|
||||||
|
this.max = max;
|
||||||
|
next = (max-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(V086Message o)
|
||||||
|
{
|
||||||
|
array[next] = o;
|
||||||
|
if (--next < 0)
|
||||||
|
next = (max-1);
|
||||||
|
if(size < max)
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int fill(V086Message[] o, int num)
|
||||||
|
{
|
||||||
|
//int startRead = (next+1);
|
||||||
|
//int endRead = ((next+1)+size);
|
||||||
|
if(size < num)
|
||||||
|
{
|
||||||
|
System.arraycopy(array, (next + 1), o, 0, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else if (((next + 1) + num) <= max)
|
||||||
|
{
|
||||||
|
System.arraycopy(array, (next + 1), o, 0, num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//int firstPartSize = (max-(next+1));
|
||||||
|
//int secondPartSize = (size-(max-(next+1)));
|
||||||
|
System.arraycopy(array, (next + 1), o, 0, (max - (next + 1)));
|
||||||
|
System.arraycopy(array, 0, o, (max - (next + 1)), (num - (max - (next + 1))));
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
}
|
633
src/org/emulinker/kaillera/controller/v086/V086Controller.java
Normal file
633
src/org/emulinker/kaillera/controller/v086/V086Controller.java
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import org.apache.commons.configuration.*;
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.KailleraServerController;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.kaillera.controller.v086.action.*;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.*;
|
||||||
|
import org.emulinker.net.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class V086Controller implements KailleraServerController
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(V086Controller.class);
|
||||||
|
|
||||||
|
private int MAX_BUNDLE_SIZE = 9;
|
||||||
|
|
||||||
|
private int bufferSize = 4096;
|
||||||
|
private boolean isRunning = false;
|
||||||
|
|
||||||
|
private ThreadPoolExecutor threadPool;
|
||||||
|
private KailleraServer server;
|
||||||
|
private AccessManager accessManager;
|
||||||
|
private String[] clientTypes;
|
||||||
|
private Map<Integer, V086ClientHandler> clientHandlers = new ConcurrentHashMap<Integer, V086ClientHandler>();
|
||||||
|
|
||||||
|
private int portRangeStart;
|
||||||
|
private int extraPorts;
|
||||||
|
private Queue<Integer> portRangeQueue = new ConcurrentLinkedQueue<Integer>();
|
||||||
|
|
||||||
|
// shouldn't need to use a synchronized or concurrent map since all thread access will be read only
|
||||||
|
private Map<Class, V086ServerEventHandler> serverEventHandlers = new HashMap<Class, V086ServerEventHandler>();
|
||||||
|
private Map<Class, V086GameEventHandler> gameEventHandlers = new HashMap<Class, V086GameEventHandler>();
|
||||||
|
private Map<Class, V086UserEventHandler> userEventHandlers = new HashMap<Class, V086UserEventHandler>();
|
||||||
|
|
||||||
|
private V086Action[] actions = new V086Action[25];
|
||||||
|
|
||||||
|
public V086Controller(KailleraServer server, ThreadPoolExecutor threadPool, AccessManager accessManager, Configuration config) throws NoSuchElementException, ConfigurationException
|
||||||
|
{
|
||||||
|
this.threadPool = threadPool;
|
||||||
|
this.server = server;
|
||||||
|
this.accessManager = accessManager;
|
||||||
|
|
||||||
|
this.bufferSize = config.getInt("controllers.v086.bufferSize");
|
||||||
|
this.clientTypes = config.getStringArray("controllers.v086.clientTypes.clientType");
|
||||||
|
|
||||||
|
this.portRangeStart = config.getInt("controllers.v086.portRangeStart");
|
||||||
|
this.extraPorts = config.getInt("controllers.v086.extraPorts", 0);
|
||||||
|
int maxPort = 0;
|
||||||
|
for (int i = portRangeStart; i <= (portRangeStart + server.getMaxUsers() + extraPorts); i++)
|
||||||
|
{
|
||||||
|
portRangeQueue.add(i);
|
||||||
|
maxPort = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn("Listening on UDP ports: " + portRangeStart + " to " + maxPort + ". Make sure these ports are open in your firewall!");
|
||||||
|
|
||||||
|
if (bufferSize <= 0)
|
||||||
|
throw new ConfigurationException("controllers.v086.bufferSize must be > 0");
|
||||||
|
|
||||||
|
// array access should be faster than a hash and we won't have to create
|
||||||
|
// a new Integer each time
|
||||||
|
actions[UserInformation.ID] = LoginAction.getInstance();
|
||||||
|
actions[ClientACK.ID] = ACKAction.getInstance();
|
||||||
|
actions[Chat.ID] = ChatAction.getInstance();
|
||||||
|
actions[CreateGame.ID] = CreateGameAction.getInstance();
|
||||||
|
actions[JoinGame.ID] = JoinGameAction.getInstance();
|
||||||
|
actions[KeepAlive.ID] = KeepAliveAction.getInstance();
|
||||||
|
actions[QuitGame.ID] = QuitGameAction.getInstance();
|
||||||
|
actions[Quit.ID] = QuitAction.getInstance();
|
||||||
|
actions[StartGame.ID] = StartGameAction.getInstance();
|
||||||
|
actions[GameChat.ID] = GameChatAction.getInstance();
|
||||||
|
actions[GameKick.ID] = GameKickAction.getInstance();
|
||||||
|
actions[AllReady.ID] = UserReadyAction.getInstance();
|
||||||
|
actions[CachedGameData.ID] = CachedGameDataAction.getInstance();
|
||||||
|
actions[GameData.ID] = GameDataAction.getInstance();
|
||||||
|
actions[PlayerDrop.ID] = DropGameAction.getInstance();
|
||||||
|
|
||||||
|
// setup the server event handlers
|
||||||
|
serverEventHandlers.put(ChatEvent.class, ChatAction.getInstance());
|
||||||
|
serverEventHandlers.put(GameCreatedEvent.class, CreateGameAction.getInstance());
|
||||||
|
serverEventHandlers.put(UserJoinedEvent.class, LoginAction.getInstance());
|
||||||
|
serverEventHandlers.put(GameClosedEvent.class, CloseGameAction.getInstance());
|
||||||
|
serverEventHandlers.put(UserQuitEvent.class, QuitAction.getInstance());
|
||||||
|
serverEventHandlers.put(GameStatusChangedEvent.class, GameStatusAction.getInstance());
|
||||||
|
|
||||||
|
// setup the game event handlers
|
||||||
|
gameEventHandlers.put(UserJoinedGameEvent.class, JoinGameAction.getInstance());
|
||||||
|
gameEventHandlers.put(UserQuitGameEvent.class, QuitGameAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameStartedEvent.class, StartGameAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameChatEvent.class, GameChatAction.getInstance());
|
||||||
|
gameEventHandlers.put(AllReadyEvent.class, UserReadyAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameDataEvent.class, GameDataAction.getInstance());
|
||||||
|
gameEventHandlers.put(UserDroppedGameEvent.class, DropGameAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameDesynchEvent.class, GameDesynchAction.getInstance());
|
||||||
|
gameEventHandlers.put(PlayerDesynchEvent.class, PlayerDesynchAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameInfoEvent.class, GameInfoAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameTimeoutEvent.class, GameTimeoutAction.getInstance());
|
||||||
|
gameEventHandlers.put(GameTimeoutEvent.class, GameTimeoutAction.getInstance());
|
||||||
|
|
||||||
|
// setup the user event handlers
|
||||||
|
userEventHandlers.put(ConnectedEvent.class, ACKAction.getInstance());
|
||||||
|
userEventHandlers.put(InfoMessageEvent.class, InfoMessageAction.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion()
|
||||||
|
{
|
||||||
|
return "v086";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getClientTypes()
|
||||||
|
{
|
||||||
|
return clientTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KailleraServer getServer()
|
||||||
|
{
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumClients()
|
||||||
|
{
|
||||||
|
return clientHandlers.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferSize()
|
||||||
|
{
|
||||||
|
return bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Map<Class, V086ServerEventHandler> getServerEventHandlers()
|
||||||
|
{
|
||||||
|
return serverEventHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Map<Class, V086GameEventHandler> getGameEventHandlers()
|
||||||
|
{
|
||||||
|
return gameEventHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Map<Class, V086UserEventHandler> getUserEventHandlers()
|
||||||
|
{
|
||||||
|
return userEventHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final V086Action[] getActions()
|
||||||
|
{
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Map<Integer, V086ClientHandler> getClientHandlers()
|
||||||
|
{
|
||||||
|
return clientHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRunning()
|
||||||
|
{
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "V086Controller[clients=" + clientHandlers.size() + " isRunning=" + isRunning + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int newConnection(InetSocketAddress clientSocketAddress, String protocol) throws ServerFullException, NewConnectionException
|
||||||
|
{
|
||||||
|
if (!isRunning)
|
||||||
|
throw new NewConnectionException("Controller is not running");
|
||||||
|
|
||||||
|
V086ClientHandler clientHandler = new V086ClientHandler(clientSocketAddress);
|
||||||
|
KailleraUser user = server.newConnection(clientSocketAddress, protocol, clientHandler);
|
||||||
|
|
||||||
|
int boundPort = -1;
|
||||||
|
int bindAttempts = 0;
|
||||||
|
while (bindAttempts++ < 5)
|
||||||
|
{
|
||||||
|
Integer portInteger = portRangeQueue.poll();
|
||||||
|
if (portInteger == null)
|
||||||
|
{
|
||||||
|
log.error("No ports are available to bind for: " + user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int port = portInteger.intValue();
|
||||||
|
log.info("Private port " + port + " allocated to: " + user);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.bind(port);
|
||||||
|
boundPort = port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (BindException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to bind to port " + port + " for: " + user + ": " + e.getMessage(), e);
|
||||||
|
log.debug(toString() + " returning port " + port + " to available port queue: " + (portRangeQueue.size() + 1) + " available");
|
||||||
|
portRangeQueue.add(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// pause very briefly to give the OS a chance to free a port
|
||||||
|
Thread.sleep(5);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boundPort < 0)
|
||||||
|
{
|
||||||
|
clientHandler.stop();
|
||||||
|
throw new NewConnectionException("Failed to bind!");
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.start(user);
|
||||||
|
return boundPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void start()
|
||||||
|
{
|
||||||
|
isRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stop()
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
|
||||||
|
for (V086ClientHandler clientHandler : clientHandlers.values())
|
||||||
|
clientHandler.stop();
|
||||||
|
|
||||||
|
clientHandlers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class V086ClientHandler extends PrivateUDPServer implements KailleraEventListener
|
||||||
|
{
|
||||||
|
private KailleraUser user;
|
||||||
|
private int messageNumberCounter = 0;
|
||||||
|
private int prevMessageNumber = -1;
|
||||||
|
private int lastMessageNumber = -1;
|
||||||
|
private GameDataCache clientCache = null;
|
||||||
|
private GameDataCache serverCache = null;
|
||||||
|
|
||||||
|
//private LinkedList<V086Message> lastMessages = new LinkedList<V086Message>();
|
||||||
|
private LastMessageBuffer lastMessageBuffer = new LastMessageBuffer(MAX_BUNDLE_SIZE);
|
||||||
|
|
||||||
|
private V086Message[] outMessages = new V086Message[MAX_BUNDLE_SIZE];
|
||||||
|
|
||||||
|
private ByteBuffer inBuffer = ByteBuffer.allocateDirect(bufferSize);
|
||||||
|
private ByteBuffer outBuffer = ByteBuffer.allocateDirect(bufferSize);
|
||||||
|
|
||||||
|
private Object inSynch = new Object();
|
||||||
|
private Object outSynch = new Object();
|
||||||
|
|
||||||
|
private long testStart;
|
||||||
|
private long lastMeasurement;
|
||||||
|
private int measurementCount = 0;
|
||||||
|
private int bestTime = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private int clientRetryCount = 0;
|
||||||
|
private long lastResend = 0;
|
||||||
|
|
||||||
|
private V086ClientHandler(InetSocketAddress remoteSocketAddress)
|
||||||
|
{
|
||||||
|
super(false, remoteSocketAddress.getAddress());
|
||||||
|
|
||||||
|
inBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
outBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
resetGameDataCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
if (getBindPort() > 0)
|
||||||
|
return "V086Controller(" + getBindPort() + ")";
|
||||||
|
else
|
||||||
|
return "V086Controller(unbound)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public V086Controller getController()
|
||||||
|
{
|
||||||
|
return V086Controller.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KailleraUser getUser()
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getNextMessageNumber()
|
||||||
|
{
|
||||||
|
if (messageNumberCounter > 0xFFFF)
|
||||||
|
messageNumberCounter = 0;
|
||||||
|
|
||||||
|
return messageNumberCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public List<V086Message> getLastMessage()
|
||||||
|
{
|
||||||
|
return lastMessages;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public int getPrevMessageNumber()
|
||||||
|
{
|
||||||
|
return prevMessageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastMessageNumber()
|
||||||
|
{
|
||||||
|
return lastMessageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameDataCache getClientGameDataCache()
|
||||||
|
{
|
||||||
|
return clientCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameDataCache getServerGameDataCache()
|
||||||
|
{
|
||||||
|
return serverCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetGameDataCache()
|
||||||
|
{
|
||||||
|
clientCache = new ClientGameDataCache(256);
|
||||||
|
/*SF MOD - Button Ghosting Patch
|
||||||
|
serverCache = new ServerGameDataCache(256);
|
||||||
|
*/
|
||||||
|
serverCache = new ClientGameDataCache(256);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSpeedTest()
|
||||||
|
{
|
||||||
|
testStart = lastMeasurement = System.currentTimeMillis();
|
||||||
|
measurementCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSpeedMeasurement()
|
||||||
|
{
|
||||||
|
int et = (int) (System.currentTimeMillis() - lastMeasurement);
|
||||||
|
if (et < bestTime)
|
||||||
|
bestTime = et;
|
||||||
|
measurementCount++;
|
||||||
|
lastMeasurement = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpeedMeasurementCount()
|
||||||
|
{
|
||||||
|
return measurementCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBestNetworkSpeed()
|
||||||
|
{
|
||||||
|
return bestTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAverageNetworkSpeed()
|
||||||
|
{
|
||||||
|
return (int) ((lastMeasurement - testStart) / measurementCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(int port) throws BindException
|
||||||
|
{
|
||||||
|
super.bind(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(KailleraUser user)
|
||||||
|
{
|
||||||
|
this.user = user;
|
||||||
|
log.debug(toString() + " thread starting (ThreadPool:" + threadPool.getActiveCount() + "/" + threadPool.getPoolSize() + ")");
|
||||||
|
threadPool.execute(this);
|
||||||
|
Thread.yield();
|
||||||
|
|
||||||
|
/*
|
||||||
|
long s = System.currentTimeMillis();
|
||||||
|
while (!isBound() && (System.currentTimeMillis() - s) < 1000)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Sleep Interrupted!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBound())
|
||||||
|
{
|
||||||
|
log.error("V086ClientHandler failed to start for client from " + getRemoteInetAddress().getHostAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
log.debug(toString() + " thread started (ThreadPool:" + threadPool.getActiveCount() + "/" + threadPool.getPoolSize() + ")");
|
||||||
|
clientHandlers.put(user.getID(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
synchronized(this)
|
||||||
|
{
|
||||||
|
if (getStopFlag())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int port = -1;
|
||||||
|
if (isBound())
|
||||||
|
port = getBindPort();
|
||||||
|
log.debug(this.toString() + " Stopping!");
|
||||||
|
super.stop();
|
||||||
|
|
||||||
|
if (port > 0)
|
||||||
|
{
|
||||||
|
log.debug(toString() + " returning port " + port + " to available port queue: " + (portRangeQueue.size() + 1) + " available");
|
||||||
|
portRangeQueue.add(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
clientHandlers.remove(user.getID());
|
||||||
|
user.stop();
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ByteBuffer getBuffer()
|
||||||
|
{
|
||||||
|
//return ByteBufferMessage.getBuffer(bufferSize);
|
||||||
|
inBuffer.clear();
|
||||||
|
return inBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void releaseBuffer(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
//ByteBufferMessage.releaseBuffer(buffer);
|
||||||
|
//buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleReceived(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
V086Bundle inBundle = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inBundle = V086Bundle.parse(buffer, lastMessageNumber);
|
||||||
|
//inBundle = V086Bundle.parse(buffer, -1);
|
||||||
|
}
|
||||||
|
catch (ParseException e)
|
||||||
|
{
|
||||||
|
buffer.rewind();
|
||||||
|
log.warn(toString() + " failed to parse: " + EmuUtil.dumpBuffer(buffer), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (V086BundleFormatException e)
|
||||||
|
{
|
||||||
|
buffer.rewind();
|
||||||
|
log.warn(toString() + " received invalid message bundle: " + EmuUtil.dumpBuffer(buffer), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
buffer.rewind();
|
||||||
|
log.warn(toString() + " received invalid message: " + EmuUtil.dumpBuffer(buffer), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.debug("-> " + inBundle.getNumMessages());
|
||||||
|
|
||||||
|
if (inBundle.getNumMessages() == 0)
|
||||||
|
{
|
||||||
|
log.debug(toString() + " received bundle of " + inBundle.getNumMessages() + " messages from " + user);
|
||||||
|
clientRetryCount++;
|
||||||
|
resend(clientRetryCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientRetryCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (inSynch)
|
||||||
|
{
|
||||||
|
|
||||||
|
V086Message[] messages = inBundle.getMessages();
|
||||||
|
if(inBundle.getNumMessages() == 1){
|
||||||
|
lastMessageNumber = messages[0].getNumber();
|
||||||
|
|
||||||
|
V086Action action = actions[messages[0].getID()];
|
||||||
|
if(action == null){
|
||||||
|
log.error("No action defined to handle client message: " + messages[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
action.performAction(messages[0], this);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// read the bundle from back to front to process the oldest messages first
|
||||||
|
for(int i = (inBundle.getNumMessages() - 1); i >= 0; i--){
|
||||||
|
if (messages[i].getNumber() > lastMessageNumber)
|
||||||
|
{
|
||||||
|
prevMessageNumber = lastMessageNumber;
|
||||||
|
lastMessageNumber = messages[i].getNumber();
|
||||||
|
|
||||||
|
if ((prevMessageNumber + 1) != lastMessageNumber)
|
||||||
|
{
|
||||||
|
log.warn(user + " dropped a packet! (" + prevMessageNumber + " to " + lastMessageNumber + ")");
|
||||||
|
user.droppedPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
V086Action action = actions[messages[i].getID()];
|
||||||
|
if (action == null)
|
||||||
|
{
|
||||||
|
log.error("No action defined to handle client message: " + messages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.debug(user + " -> " + message);
|
||||||
|
action.performAction(messages[i], this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FatalActionException e)
|
||||||
|
{
|
||||||
|
log.warn(toString() + " fatal action, closing connection: " + e.getMessage());
|
||||||
|
Thread.yield();
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(KailleraEvent event)
|
||||||
|
{
|
||||||
|
if (event instanceof GameEvent)
|
||||||
|
{
|
||||||
|
V086GameEventHandler eventHandler = gameEventHandlers.get(event.getClass());
|
||||||
|
if (eventHandler == null)
|
||||||
|
{
|
||||||
|
log.error(toString() + " found no GameEventHandler registered to handle game event: " + event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandler.handleEvent((GameEvent) event, this);
|
||||||
|
}
|
||||||
|
else if (event instanceof ServerEvent)
|
||||||
|
{
|
||||||
|
V086ServerEventHandler eventHandler = serverEventHandlers.get(event.getClass());
|
||||||
|
if (eventHandler == null)
|
||||||
|
{
|
||||||
|
log.error(toString() + " found no ServerEventHandler registered to handle server event: " + event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandler.handleEvent((ServerEvent) event, this);
|
||||||
|
}
|
||||||
|
else if (event instanceof UserEvent)
|
||||||
|
{
|
||||||
|
V086UserEventHandler eventHandler = userEventHandlers.get(event.getClass());
|
||||||
|
if (eventHandler == null)
|
||||||
|
{
|
||||||
|
log.error(toString() + " found no UserEventHandler registered to handle user event: " + event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandler.handleEvent((UserEvent) event, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resend(int timeoutCounter)
|
||||||
|
{
|
||||||
|
|
||||||
|
synchronized (outSynch)
|
||||||
|
{
|
||||||
|
//if ((System.currentTimeMillis() - lastResend) > (user.getPing()*3))
|
||||||
|
if ((System.currentTimeMillis() - lastResend) > server.getMaxPing())
|
||||||
|
{
|
||||||
|
//int numToSend = (3+timeoutCounter);
|
||||||
|
int numToSend = (3 * timeoutCounter);
|
||||||
|
if (numToSend > MAX_BUNDLE_SIZE)
|
||||||
|
numToSend = MAX_BUNDLE_SIZE;
|
||||||
|
|
||||||
|
log.debug(this + ": resending last " + numToSend + " messages");
|
||||||
|
send(null, numToSend);
|
||||||
|
lastResend = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.debug("Skipping resend...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(V086Message outMessage)
|
||||||
|
{
|
||||||
|
send(outMessage, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(V086Message outMessage, int numToSend)
|
||||||
|
{
|
||||||
|
synchronized (outSynch)
|
||||||
|
{
|
||||||
|
if(outMessage != null){
|
||||||
|
lastMessageBuffer.add(outMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
numToSend = lastMessageBuffer.fill(outMessages, numToSend);
|
||||||
|
//System.out.println("Server -> " + numToSend);
|
||||||
|
V086Bundle outBundle = new V086Bundle(outMessages, numToSend);
|
||||||
|
// log.debug("<- " + outBundle);
|
||||||
|
outBundle.writeTo(outBuffer);
|
||||||
|
outBuffer.flip();
|
||||||
|
super.send(outBuffer);
|
||||||
|
outBuffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
214
src/org/emulinker/kaillera/controller/v086/action/ACKAction.java
Normal file
214
src/org/emulinker/kaillera/controller/v086/action/ACKAction.java
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.LoginException;
|
||||||
|
|
||||||
|
public class ACKAction implements V086Action, V086UserEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(ACKAction.class);
|
||||||
|
private static final String desc = "ACKAction";
|
||||||
|
private static ACKAction singleton = new ACKAction();
|
||||||
|
private static int numAcksForSpeedTest = 3;
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
public static ACKAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ACKAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
KailleraUser user = clientHandler.getUser();
|
||||||
|
if(user.isLoggedIn())
|
||||||
|
return;
|
||||||
|
|
||||||
|
clientHandler.addSpeedMeasurement();
|
||||||
|
|
||||||
|
if (clientHandler.getSpeedMeasurementCount() > numAcksForSpeedTest)
|
||||||
|
{
|
||||||
|
|
||||||
|
user.setPing(clientHandler.getAverageNetworkSpeed());
|
||||||
|
|
||||||
|
log.debug("Calculated " + user + " ping time: average=" + clientHandler.getAverageNetworkSpeed() + ", best=" + clientHandler.getBestNetworkSpeed());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
user.login();
|
||||||
|
}
|
||||||
|
catch (LoginException e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new ConnectionRejected(clientHandler.getNextMessageNumber(), user.getName(), user.getID(), e.getMessage()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new ConnectionRejected", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FatalActionException("Login failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new ServerACK(clientHandler.getNextMessageNumber()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new ServerACK", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(UserEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
ConnectedEvent connectedEvent = (ConnectedEvent) event;
|
||||||
|
|
||||||
|
KailleraServer server = connectedEvent.getServer();
|
||||||
|
KailleraUser thisUser = connectedEvent.getUser();
|
||||||
|
|
||||||
|
List<ServerStatus.User> users = new ArrayList<ServerStatus.User>();
|
||||||
|
List<ServerStatus.Game> games = new ArrayList<ServerStatus.Game>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (KailleraUser user : server.getUsers())
|
||||||
|
{
|
||||||
|
if (user.getStatus() != KailleraUser.STATUS_CONNECTING && !user.equals(thisUser))
|
||||||
|
users.add(new ServerStatus.User(user.getName(), user.getPing(), (byte) user.getStatus(), user.getID(), user.getConnectionType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new ServerStatus.User", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (KailleraGame game : server.getGames()){
|
||||||
|
int num = 0;
|
||||||
|
for(KailleraUser user : game.getPlayers()){
|
||||||
|
if(!user.getStealth())
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
games.add(new ServerStatus.Game(game.getRomName(), game.getID(), game.getClientType(), game.getOwner().getName(), (num + "/" + game.getMaxUsers()), (byte) game.getStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new ServerStatus.User", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here I am attempting to fix the inherent Kaillera protocol bug that occurs when there are a large number of users
|
||||||
|
// and/or games on the server. The size of the ServerStatus packet can be very large, and depending on the router
|
||||||
|
// settings or os config, the packet size exceeds a UDP/IP limit and gets dropped. This results in the user getting
|
||||||
|
// half logged-in, in a weird state.
|
||||||
|
|
||||||
|
// I am attempting to fix this by breaking the ServerStatus message up into multiple packets. I'm shooting for a max
|
||||||
|
// packet size of 1500 bytes, but since kaillera sends 3 messages per packet, the max size for a single message should be 500
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
boolean sent = false;
|
||||||
|
|
||||||
|
List<ServerStatus.User> usersSubList = new ArrayList<ServerStatus.User>();
|
||||||
|
List<ServerStatus.Game> gamesSubList = new ArrayList<ServerStatus.Game>();
|
||||||
|
|
||||||
|
while(!users.isEmpty())
|
||||||
|
{
|
||||||
|
ServerStatus.User user = users.get(0);
|
||||||
|
users.remove(0);
|
||||||
|
|
||||||
|
if((counter + user.getLength()) >= 300)
|
||||||
|
{
|
||||||
|
sendServerStatus(clientHandler, usersSubList, gamesSubList, counter);
|
||||||
|
usersSubList = new ArrayList<ServerStatus.User>();
|
||||||
|
gamesSubList = new ArrayList<ServerStatus.Game>();
|
||||||
|
counter = 0;
|
||||||
|
sent = true;
|
||||||
|
try { Thread.sleep(100); } catch(Exception e) {}//SF MOD
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += user.getLength();
|
||||||
|
usersSubList.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!games.isEmpty())
|
||||||
|
{
|
||||||
|
ServerStatus.Game game = games.get(0);
|
||||||
|
games.remove(0);
|
||||||
|
|
||||||
|
if((counter + game.getLength()) >= 300)
|
||||||
|
{
|
||||||
|
sendServerStatus(clientHandler, usersSubList, gamesSubList, counter);
|
||||||
|
usersSubList = new ArrayList<ServerStatus.User>();
|
||||||
|
gamesSubList = new ArrayList<ServerStatus.Game>();
|
||||||
|
counter = 0;
|
||||||
|
sent = true;
|
||||||
|
try { Thread.sleep(100); } catch(Exception e) {}//SF MOD
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += game.getLength();
|
||||||
|
gamesSubList.add(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((usersSubList.size() > 0 || gamesSubList.size() > 0) || !sent)
|
||||||
|
sendServerStatus(clientHandler, usersSubList, gamesSubList, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendServerStatus(V086Controller.V086ClientHandler clientHandler, List<ServerStatus.User> users, List<ServerStatus.Game> games, int counter)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for(ServerStatus.Game game : games)
|
||||||
|
{
|
||||||
|
sb.append(game.getGameID());
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
log.debug("Sending ServerStatus to " + clientHandler.getUser() + ": " + users.size() + " users, " + games.size() + " games in " + counter + " bytes, games: " + sb.toString());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new ServerStatus(clientHandler.getNextMessageNumber(), users, games));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new ServerStatus for users", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,786 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
|
||||||
|
import org.emulinker.release.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.ActionException;
|
||||||
|
import org.emulinker.kaillera.model.impl.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class AdminCommandAction implements V086Action
|
||||||
|
{
|
||||||
|
public static final String COMMAND_ANNOUNCE = "/announce"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_ANNOUNCEALL = "/announceall"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_ANNOUNCEGAME = "/announcegame"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_BAN = "/ban"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_CLEAR = "/clear"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_CLOSEGAME = "/closegame"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_FINDGAME = "/findgame"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_FINDUSER = "/finduser"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_HELP = "/help"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_KICK = "/kick"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_SILENCE = "/silence"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_TEMPADMIN = "/tempadmin"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_VERSION = "/version"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_TRIVIA = "/trivia";
|
||||||
|
|
||||||
|
//SF MOD
|
||||||
|
public static final String COMMAND_STEALTH = "/stealth"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_TEMPELEVATED = "/tempelevated"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(AdminCommandAction.class);
|
||||||
|
private static final String desc = "AdminCommandAction"; //$NON-NLS-1$
|
||||||
|
private static AdminCommandAction singleton = new AdminCommandAction();
|
||||||
|
|
||||||
|
public static AdminCommandAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private AdminCommandAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidCommand(String chat){
|
||||||
|
if (chat.startsWith(COMMAND_HELP))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_FINDUSER))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_FINDGAME))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_CLOSEGAME))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_KICK))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_BAN))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TEMPELEVATED))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SILENCE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_ANNOUNCEGAME))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_ANNOUNCE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TEMPADMIN))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_VERSION))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_CLEAR))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_STEALTH))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TRIVIA))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
Chat chatMessage = (Chat) message;
|
||||||
|
String chat = chatMessage.getMessage();
|
||||||
|
KailleraServerImpl server = (KailleraServerImpl) clientHandler.getController().getServer();
|
||||||
|
AccessManager accessManager = server.getAccessManager();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
|
||||||
|
if (accessManager.getAccess(clientHandler.getRemoteInetAddress()) < AccessManager.ACCESS_ADMIN){
|
||||||
|
if (chat.startsWith(COMMAND_SILENCE) || chat.startsWith(COMMAND_KICK) || chat.startsWith(COMMAND_HELP) || chat.startsWith(COMMAND_FINDUSER) && accessManager.getAccess(clientHandler.getRemoteInetAddress()) > AccessManager.ACCESS_ELEVATED)
|
||||||
|
{
|
||||||
|
//SF MOD - Moderators can silence and Kick
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Admin Command Error: You are not an admin!"));} catch (MessageFormatException e){} //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
throw new FatalActionException("Admin Command Denied: " + user + " does not have Admin access: " + chat); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(user + ": Admin Command: " + chat); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (chat.startsWith(COMMAND_HELP))
|
||||||
|
{
|
||||||
|
processHelp(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_FINDUSER))
|
||||||
|
{
|
||||||
|
processFindUser(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_FINDGAME))
|
||||||
|
{
|
||||||
|
processFindGame(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_CLOSEGAME))
|
||||||
|
{
|
||||||
|
processCloseGame(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_KICK))
|
||||||
|
{
|
||||||
|
processKick(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_BAN))
|
||||||
|
{
|
||||||
|
processBan(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TEMPELEVATED))
|
||||||
|
{
|
||||||
|
processTempElevated(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SILENCE))
|
||||||
|
{
|
||||||
|
processSilence(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_ANNOUNCEGAME))
|
||||||
|
{
|
||||||
|
processGameAnnounce(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_ANNOUNCE))
|
||||||
|
{
|
||||||
|
processAnnounce(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TEMPADMIN))
|
||||||
|
{
|
||||||
|
processTempAdmin(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_VERSION))
|
||||||
|
{
|
||||||
|
processVersion(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_CLEAR))
|
||||||
|
{
|
||||||
|
processClear(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_STEALTH))
|
||||||
|
{
|
||||||
|
processStealth(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_TRIVIA))
|
||||||
|
{
|
||||||
|
processTrivia(chat, server, user, clientHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ActionException("Invalid Command: " + chat); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
catch (ActionException e)
|
||||||
|
{
|
||||||
|
log.info("Admin Command Failed: " + user + ": " + chat); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.Failed", e.getMessage()))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct InformationMessage message: " + e.getMessage(), e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct message: " + e.getMessage(), e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processHelp(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
//clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.AdminCommands"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
//try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpVersion"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
|
||||||
|
if(admin.getAccess() == AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpTempAdmin"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpKick"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpSilence"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
|
||||||
|
if(admin.getAccess() == AccessManager.ACCESS_MODERATOR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpBan"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpClear"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpCloseGame"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpAnnounce"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpAnnounceAll"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpAnnounceGame"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpFindUser"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.HelpFindGame"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/stealthon /stealthoff_ join room unnoticed")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
if(admin.getAccess() == AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/tempelevated <UserID> <min> gives elevation.")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processFindUser(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
int space = message.indexOf(' ');
|
||||||
|
if (space < 0)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.FindUserError")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int foundCount = 0;
|
||||||
|
String str = (message.substring(space + 1));
|
||||||
|
//WildcardStringPattern pattern = new WildcardStringPattern
|
||||||
|
|
||||||
|
for (KailleraUserImpl user : server.getUsers())
|
||||||
|
{
|
||||||
|
if (!user.isLoggedIn())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (user.getName().toLowerCase().contains(str.toLowerCase()))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("UserID: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getID());
|
||||||
|
sb.append(", IP: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getConnectSocketAddress().getAddress().getHostAddress());
|
||||||
|
sb.append(", Nick: <"); //$NON-NLS-1$
|
||||||
|
sb.append(user.getName());
|
||||||
|
sb.append(">, Access: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getAccessStr());
|
||||||
|
if(user.getGame() != null){
|
||||||
|
sb.append(", GameID: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getGame().getID());
|
||||||
|
sb.append(", Game: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getGame().getRomName());
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", sb.toString())); //$NON-NLS-1$
|
||||||
|
foundCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundCount == 0)
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.NoUsersFound"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFindGame(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
int space = message.indexOf(' ');
|
||||||
|
if (space < 0)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.FindGameError")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int foundCount = 0;
|
||||||
|
WildcardStringPattern pattern = new WildcardStringPattern(message.substring(space + 1));
|
||||||
|
for (KailleraGameImpl game : server.getGames())
|
||||||
|
{
|
||||||
|
if (pattern.match(game.getRomName()))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(game.getID());
|
||||||
|
sb.append(": "); //$NON-NLS-1$
|
||||||
|
sb.append(game.getOwner().getName());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
sb.append(game.getRomName());
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", sb.toString())); //$NON-NLS-1$
|
||||||
|
foundCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundCount == 0)
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.NoGamesFound"))); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSilence(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
int minutes = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) server.getUser(userID);
|
||||||
|
if (user == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserNotFound") + userID); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (user.getID() == admin.getID())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotSilenceSelf")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = server.getAccessManager().getAccess(user.getConnectSocketAddress().getAddress());
|
||||||
|
if (access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotSilenceAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (access == AccessManager.ACCESS_MODERATOR && admin.getStatus() == AccessManager.ACCESS_MODERATOR)
|
||||||
|
throw new ActionException("You cannot silence an elevated user if you're not an admin!"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if(admin.getAccess() == AccessManager.ACCESS_MODERATOR){
|
||||||
|
if(server.getAccessManager().isSilenced(user.getSocketAddress().getAddress()))
|
||||||
|
throw new ActionException("This User has already been Silenced. Please wait until his time expires."); //$NON-NLS-1$
|
||||||
|
if(minutes > 15)
|
||||||
|
throw new ActionException("Moderators can only silence up to 15 minutes!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
server.getAccessManager().addSilenced(user.getConnectSocketAddress().getAddress().getHostAddress(), minutes);
|
||||||
|
server.announce(EmuLang.getString("AdminCommandAction.Silenced", minutes, user.getName()), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.SilenceError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processKick(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) server.getUser(userID);
|
||||||
|
if (user == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserNotFound", userID)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (user.getID() == admin.getID())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotKickSelf")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = server.getAccessManager().getAccess(user.getConnectSocketAddress().getAddress());
|
||||||
|
|
||||||
|
if (access == AccessManager.ACCESS_MODERATOR && admin.getStatus() == AccessManager.ACCESS_MODERATOR)
|
||||||
|
throw new ActionException("You cannot kick a moderator if you're not an admin!"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotKickAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
user.quit(EmuLang.getString("AdminCommandAction.QuitKicked")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.KickError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCloseGame(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int gameID = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraGameImpl game = (KailleraGameImpl) server.getGame(gameID);
|
||||||
|
if (game == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.GameNotFound", gameID)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
KailleraUserImpl owner = (KailleraUserImpl) game.getOwner();
|
||||||
|
int access = server.getAccessManager().getAccess(owner.getConnectSocketAddress().getAddress());
|
||||||
|
|
||||||
|
if(access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN && owner.isLoggedIn())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotCloseAdminGame")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
owner.quitGame();
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CloseGameError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processBan(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
int minutes = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) server.getUser(userID);
|
||||||
|
if (user == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserNotFound", userID)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (user.getID() == admin.getID())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotBanSelf")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = server.getAccessManager().getAccess(user.getConnectSocketAddress().getAddress());
|
||||||
|
if (access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.CanNotBanAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
server.announce(EmuLang.getString("AdminCommandAction.Banned", minutes, user.getName()), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
user.quit(EmuLang.getString("AdminCommandAction.QuitBanned")); //$NON-NLS-1$
|
||||||
|
server.getAccessManager().addTempBan(user.getConnectSocketAddress().getAddress().getHostAddress(), minutes);
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.BanError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processTempElevated(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(admin.getAccess()!= AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
throw new ActionException("Only SUPER ADMIN's can give Temp Elevated Status!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
int minutes = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) server.getUser(userID);
|
||||||
|
if (user == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserNotFound", userID)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (user.getID() == admin.getID())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.AlreadyAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = server.getAccessManager().getAccess(user.getConnectSocketAddress().getAddress());
|
||||||
|
if (access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserAlreadyAdmin")); //$NON-NLS-1$
|
||||||
|
else if (access == AccessManager.ACCESS_ELEVATED)
|
||||||
|
throw new ActionException("User is already elevated."); //$NON-NLS-1$
|
||||||
|
|
||||||
|
server.getAccessManager().addTempElevated(user.getConnectSocketAddress().getAddress().getHostAddress(), minutes);
|
||||||
|
server.announce("Temp Elevated Granted: " + user.getName() + " for " + minutes + "min", false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("Temp Elevated Error.")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processTempAdmin(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(admin.getAccess()!= AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
throw new ActionException("Only SUPER ADMIN's can give Temp Admin Status!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
int minutes = scanner.nextInt();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) server.getUser(userID);
|
||||||
|
if (user == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserNotFound", userID)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (user.getID() == admin.getID())
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.AlreadyAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = server.getAccessManager().getAccess(user.getConnectSocketAddress().getAddress());
|
||||||
|
if (access >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.UserAlreadyAdmin")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
server.getAccessManager().addTempAdmin(user.getConnectSocketAddress().getAddress().getHostAddress(), minutes);
|
||||||
|
server.announce(EmuLang.getString("AdminCommandAction.TempAdminGranted", minutes, user.getName()), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.TempAdminError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processStealth(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(admin.getGame() != null)
|
||||||
|
throw new ActionException("Can't use /stealth while in a gameroom."); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if(message.equals("/stealthon")){
|
||||||
|
admin.setStealth(true);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Stealth Mode is on.")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
else if(message.equals("/stealthoff")){
|
||||||
|
admin.setStealth(false);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Stealth Mode is off.")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ActionException("Stealth Mode Error: /stealthon /stealthoff"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processTrivia(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(message.equals("/triviareset")){
|
||||||
|
if(server.getSwitchTrivia()){
|
||||||
|
server.getTrivia().saveScores(true);
|
||||||
|
server.getTriviaThread().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
server.announce("<Trivia> " + "SupraTrivia has been reset!", false, null);
|
||||||
|
Trivia trivia = new Trivia(server);
|
||||||
|
Thread triviaThread = new Thread(trivia);
|
||||||
|
triviaThread.start();
|
||||||
|
|
||||||
|
server.setTriviaThread(triviaThread);
|
||||||
|
server.setTrivia(trivia);
|
||||||
|
server.setSwitchTrivia(true);
|
||||||
|
trivia.setTriviaPaused(false);
|
||||||
|
}
|
||||||
|
else if(message.equals("/triviapause")){
|
||||||
|
if(server.getTrivia() == null){
|
||||||
|
throw new ActionException("Trivia needs to be started first!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
server.getTrivia().setTriviaPaused(true);
|
||||||
|
server.announce("<Trivia> " + "SupraTrivia will be paused after this question!", false, null);
|
||||||
|
}
|
||||||
|
else if(message.equals("/triviaresume")){
|
||||||
|
if(server.getTrivia() == null){
|
||||||
|
throw new ActionException("Trivia needs to be started first!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
server.getTrivia().setTriviaPaused(false);
|
||||||
|
server.announce("<Trivia> " + "SupraTrivia has been resumed!", false, null);
|
||||||
|
}
|
||||||
|
else if(message.equals("/triviasave")){
|
||||||
|
if(server.getTrivia() == null){
|
||||||
|
throw new ActionException("Trivia needs to be started first!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
server.getTrivia().saveScores(true);
|
||||||
|
}
|
||||||
|
else if(message.startsWith("/triviaupdate")){
|
||||||
|
if(server.getTrivia() == null){
|
||||||
|
throw new ActionException("Trivia needs to be started first!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try{
|
||||||
|
scanner.next();
|
||||||
|
String ip = scanner.next();
|
||||||
|
String ip_update = scanner.next();
|
||||||
|
|
||||||
|
if(server.getTrivia().updateIP(ip, ip_update)){
|
||||||
|
server.announce("<Trivia> " + ip_update.subSequence(0, 4) + ".... Trivia IP was updated!", false, admin);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
server.announce("<Trivia> " + ip.subSequence(0, 4) + " was not found! Error updating score!", false, admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
throw new ActionException("Invalid Trivia Score Update!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(message.startsWith("/triviatime")){
|
||||||
|
if(server.getTrivia() == null){
|
||||||
|
throw new ActionException("Trivia needs to be started first!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try{
|
||||||
|
scanner.next();
|
||||||
|
int questionTime = scanner.nextInt();
|
||||||
|
server.getTrivia().setQuestionTime(questionTime * 1000);
|
||||||
|
server.announce("<Trivia> " + "SupraTrivia's question delay has been changed to " + questionTime + "s!", false, admin);
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
throw new ActionException("Invalid Trivia Time!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void processAnnounce(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
int space = message.indexOf(' ');
|
||||||
|
if (space < 0)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.AnnounceError")); //$NON-NLS-1$
|
||||||
|
|
||||||
|
boolean all = false;
|
||||||
|
if (message.startsWith(COMMAND_ANNOUNCEALL)){
|
||||||
|
all = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String announcement = message.substring(space + 1);
|
||||||
|
if(announcement.startsWith(":"))
|
||||||
|
announcement = announcement.substring(1); // this protects against people screwing up the emulinker supraclient
|
||||||
|
|
||||||
|
server.announce(announcement, all, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processGameAnnounce(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int gameID = scanner.nextInt();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (scanner.hasNext())
|
||||||
|
{
|
||||||
|
sb.append(scanner.next());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
KailleraGameImpl game = (KailleraGameImpl) server.getGame(gameID);
|
||||||
|
if (game == null)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.GameNoutFound") + gameID); //$NON-NLS-1$
|
||||||
|
|
||||||
|
game.announce(sb.toString(), null);
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.AnnounceGameError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processClear(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
int space = message.indexOf(' ');
|
||||||
|
if (space < 0)
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.ClearError"));
|
||||||
|
|
||||||
|
String addressStr = message.substring(space + 1);
|
||||||
|
InetAddress inetAddr = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inetAddr = InetAddress.getByName(addressStr);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.ClearAddressFormatError"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(server.getAccessManager().clearTemp(inetAddr))
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.ClearSuccess")));
|
||||||
|
else
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("AdminCommandAction.ClearNotFound")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processVersion(String message, KailleraServerImpl server, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ReleaseInfo releaseInfo = server.getReleaseInfo();
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "VERSION: " + releaseInfo.getProductName())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
sleep(20);
|
||||||
|
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "JAVAVER: " + props.getProperty("java.version"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "JAVAVEND: " + props.getProperty("java.vendor"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "OSNAME: " + props.getProperty("os.name"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "OSARCH: " + props.getProperty("os.arch"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "OSVER: " + props.getProperty("os.version"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "NUMPROCS: " + runtime.availableProcessors())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "FREEMEM: " + runtime.freeMemory())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "MAXMEM: " + runtime.maxMemory())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "TOTMEM: " + runtime.totalMemory())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
sleep(20);
|
||||||
|
|
||||||
|
Map<String, String> env = System.getenv();
|
||||||
|
|
||||||
|
if(EmuUtil.systemIsWindows())
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "COMPNAME: " + env.get("COMPUTERNAME"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "USER: " + env.get("USERNAME"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "COMPNAME: " + env.get("HOSTNAME"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "USER: " + env.get("USERNAME"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
sleep(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
throw new ActionException(EmuLang.getString("AdminCommandAction.VersionError")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sleep(int ms)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(ms);
|
||||||
|
}
|
||||||
|
catch(Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.exception.GameDataException;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class CachedGameDataAction implements V086Action
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(CachedGameDataAction.class);
|
||||||
|
private static final String desc = "CachedGameDataAction";
|
||||||
|
private static CachedGameDataAction singleton = new CachedGameDataAction();
|
||||||
|
|
||||||
|
private static Log keyLog = LogFactory.getLog("KEYLOG");
|
||||||
|
|
||||||
|
public static CachedGameDataAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private CachedGameDataAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUser user = clientHandler.getUser();
|
||||||
|
|
||||||
|
int key = ((CachedGameData) message).getKey();
|
||||||
|
byte[] data = clientHandler.getClientGameDataCache().get(key);
|
||||||
|
|
||||||
|
if(data == null){
|
||||||
|
log.debug("Game Cache Error: null data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.addGameData(data);
|
||||||
|
}
|
||||||
|
catch (GameDataException e)
|
||||||
|
{
|
||||||
|
log.debug("Game data error: " + e.getMessage());
|
||||||
|
|
||||||
|
if(e.hasResponse())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameData(clientHandler.getNextMessageNumber(), e.getResponse()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameData message: " + e2.getMessage(), e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IndexOutOfBoundsException e)
|
||||||
|
{
|
||||||
|
log.error("Game data error! The client cached key " + ((CachedGameData) message).getKey() + " was not found in the cache!", e);
|
||||||
|
|
||||||
|
// This may not always be the best thing to do...
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), "Error", "Game Data Error! Game state will be inconsistent!"));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new GameChat_Notification", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,452 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.ActionException;
|
||||||
|
import org.emulinker.kaillera.model.exception.FloodException;
|
||||||
|
import org.emulinker.kaillera.model.impl.KailleraUserImpl;
|
||||||
|
import org.emulinker.release.ReleaseInfo;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
import org.emulinker.util.WildcardStringPattern;
|
||||||
|
|
||||||
|
public class ChatAction implements V086Action, V086ServerEventHandler
|
||||||
|
{
|
||||||
|
public static final String ADMIN_COMMAND_ESCAPE_STRING = "/";
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(ChatAction.class);
|
||||||
|
private static final String desc = "ChatAction";
|
||||||
|
private static ChatAction singleton = new ChatAction();
|
||||||
|
|
||||||
|
public static ChatAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private ChatAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!(message instanceof Chat_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of Chat: " + message);
|
||||||
|
|
||||||
|
if (((Chat) message).getMessage().startsWith(ADMIN_COMMAND_ESCAPE_STRING)){
|
||||||
|
if(clientHandler.getUser().getAccess() > AccessManager.ACCESS_ELEVATED){
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(AdminCommandAction.getInstance().isValidCommand(((Chat) message).getMessage())){
|
||||||
|
AdminCommandAction.getInstance().performAction(message, clientHandler);
|
||||||
|
if(((Chat) message).getMessage().equals("/help"))
|
||||||
|
checkCommands(message, clientHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
checkCommands(message, clientHandler);
|
||||||
|
}
|
||||||
|
catch (FatalActionException e)
|
||||||
|
{
|
||||||
|
log.warn("Admin command failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkCommands(message, clientHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().chat(((Chat) message).getMessage());
|
||||||
|
}
|
||||||
|
catch (ActionException e)
|
||||||
|
{
|
||||||
|
log.info("Chat Denied: " + clientHandler.getUser() + ": " + ((Chat) message).getMessage());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("ChatAction.ChatDenied", e.getMessage())));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct InformationMessage message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCommands(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException{
|
||||||
|
boolean doCommand = true;
|
||||||
|
KailleraUserImpl userN = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
|
||||||
|
if(userN.getAccess() < AccessManager.ACCESS_ELEVATED){
|
||||||
|
try{
|
||||||
|
clientHandler.getUser().chat(":USER_COMMAND");
|
||||||
|
}catch (ActionException e){
|
||||||
|
doCommand = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doCommand){
|
||||||
|
//SF MOD - User Commands
|
||||||
|
if(((Chat) message).getMessage().equals("/alivecheck")){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", ":ALIVECHECK=EmulinkerSF Alive Check: You are still logged in."));} catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/version") && clientHandler.getUser().getAccess() < AccessManager.ACCESS_ADMIN){
|
||||||
|
ReleaseInfo releaseInfo = clientHandler.getUser().getServer().getReleaseInfo();
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "VERSION: " + releaseInfo.getProductName() + ": " + releaseInfo.getVersionString() + ": " + releaseInfo.getReleaseDate()));} catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/myip")){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Your IP Address is: " + clientHandler.getUser().getConnectSocketAddress().getAddress().getHostAddress()));} catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/msgon")){
|
||||||
|
clientHandler.getUser().setMsg(true);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Private messages are now on."));} catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/msgoff")){
|
||||||
|
clientHandler.getUser().setMsg(false);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Private messages are now off."));} catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().startsWith("/me")){
|
||||||
|
int space = ((Chat) message).getMessage().indexOf(' ');
|
||||||
|
if (space < 0){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","Invalid # of Fields!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String announcement = ((Chat) message).getMessage().substring(space + 1);
|
||||||
|
if(announcement.startsWith(":"))
|
||||||
|
announcement = announcement.substring(1); // this protects against people screwing up the emulinker supraclient
|
||||||
|
|
||||||
|
|
||||||
|
int access = clientHandler.getUser().getServer().getAccessManager().getAccess(clientHandler.getUser().getSocketAddress().getAddress());
|
||||||
|
if (access < AccessManager.ACCESS_SUPERADMIN && clientHandler.getUser().getServer().getAccessManager().isSilenced(clientHandler.getUser().getSocketAddress().getAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "You are silenced!"));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clientHandler.getUser().getServer().checkMe(clientHandler.getUser(), announcement)){
|
||||||
|
String m = announcement;
|
||||||
|
|
||||||
|
announcement = "*" + clientHandler.getUser().getName() + " " + m;
|
||||||
|
KailleraUserImpl user1 = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
clientHandler.getUser().getServer().announce(announcement, true, user1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().startsWith("/msg")){
|
||||||
|
KailleraUserImpl user1 = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
Scanner scanner = new Scanner(((Chat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = clientHandler.getUser().getServer().getAccessManager().getAccess(clientHandler.getUser().getSocketAddress().getAddress());
|
||||||
|
if (access < AccessManager.ACCESS_SUPERADMIN && clientHandler.getUser().getServer().getAccessManager().isSilenced(clientHandler.getUser().getSocketAddress().getAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "You are silenced!"));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (scanner.hasNext())
|
||||||
|
{
|
||||||
|
sb.append(scanner.next());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't private message yourself!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getMsg() == false || user.searchIgnoredUsers(clientHandler.getUser().getConnectSocketAddress().getAddress().getHostAddress()) == true){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","<" + user.getName() + "> Is not accepting private messages!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = sb.toString();
|
||||||
|
|
||||||
|
|
||||||
|
user1.setLastMsgID(user.getID());
|
||||||
|
user.setLastMsgID(user1.getID());
|
||||||
|
|
||||||
|
user1.getServer().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user1);
|
||||||
|
user.getServer().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user);
|
||||||
|
|
||||||
|
if(user1.getGame() != null){
|
||||||
|
user1.getGame().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getGame() != null){
|
||||||
|
user.getGame().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
if(user1.getLastMsgID() != -1){
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(user1.getLastMsgID());
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (scanner.hasNext())
|
||||||
|
{
|
||||||
|
sb.append(scanner.next());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't private message yourself!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getMsg() == false){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","<" + user.getName() + "> Is not accepting private messages!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = sb.toString();
|
||||||
|
|
||||||
|
user1.getServer().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user1);
|
||||||
|
user.getServer().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user);
|
||||||
|
if(user1.getGame() != null){
|
||||||
|
user1.getGame().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getGame() != null){
|
||||||
|
user.getGame().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e1){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","Private Message Error: /msg <UserID> <message>")); } catch(Exception e2) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","Private Message Error: /msg <UserID> <message>")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/ignoreall")){
|
||||||
|
clientHandler.getUser().setIgnoreAll(true);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server",clientHandler.getUser().getName() + " is now ignoring everyone!")); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/unignoreall")){
|
||||||
|
clientHandler.getUser().setIgnoreAll(false);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server",clientHandler.getUser().getName() + " is now unignoring everyone!")); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().startsWith("/ignore")){
|
||||||
|
Scanner scanner = new Scanner(((Chat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user.getAccess() >= AccessManager.ACCESS_MODERATOR){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You cannot ignore an admin!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't ignore yourself!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(clientHandler.getUser().findIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't ignore a user that is already ignored!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.getUser().addIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress());
|
||||||
|
user.getServer().announce(clientHandler.getUser().getName() + " is now ignoring <" + user.getName() + "> ID: " + user.getID(), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getServer().announce("Ignore User Error: /ignore <UserID>", false, user); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
log.info("IGNORE USER ERROR: " + user.getName() + ": " + clientHandler.getRemoteSocketAddress().getHostName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().startsWith("/unignore")){
|
||||||
|
Scanner scanner = new Scanner(((Chat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!clientHandler.getUser().findIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't unignore a user that isn't ignored!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clientHandler.getUser().removeIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress(), false) == true)
|
||||||
|
user.getServer().announce(clientHandler.getUser().getName() + " is now unignoring <" + user.getName() + "> ID: " + user.getID(), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
else
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getServer().announce("Unignore User Error: /ignore <UserID>", false, user); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
log.info("UNIGNORE USER ERROR: " + user.getName() + ": " + clientHandler.getRemoteSocketAddress().getHostName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().equals("/help")){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/me <message> to make personal message eg. /me is bored ...SupraFast is bored.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/ignore <UserID> or /unignore <UserID> or /ignoreall or /unignoreall to ignore users.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/msg <UserID> <msg> to PM somebody. /msgon or /msgoff to turn on | off.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/myip to get your IP Address.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/version to get server version.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
if(clientHandler.getUser().getAccess() == AccessManager.ACCESS_MODERATOR){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/silence <UserID> <Min> to silence a user. 15min max.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/kick <UserID> to kick a user.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clientHandler.getUser().getAccess() < AccessManager.ACCESS_ADMIN){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "/finduser <Nick> to get a user's info. eg. /finduser sup ...will return SupraFast info.")); } catch(Exception e) {}
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((Chat) message).getMessage().startsWith("/finduser") && clientHandler.getUser().getAccess() < AccessManager.ACCESS_ADMIN){
|
||||||
|
int space = ((Chat) message).getMessage().indexOf(' ');
|
||||||
|
if (space < 0){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Finduser Error: /finduser <nick> eg. /finduser sup ...will return SupraFast info.")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int foundCount = 0;
|
||||||
|
String str =(((Chat) message).getMessage().substring(space + 1));
|
||||||
|
//WildcardStringPattern pattern = new WildcardStringPattern
|
||||||
|
for (KailleraUserImpl user : clientHandler.getUser().getUsers())
|
||||||
|
{
|
||||||
|
if (!user.isLoggedIn())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (user.getName().toLowerCase().contains(str.toLowerCase()))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("UserID: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getID());
|
||||||
|
sb.append(", Nick: < "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getName());
|
||||||
|
sb.append(">"); //$NON-NLS-1$
|
||||||
|
sb.append(", Access: ");
|
||||||
|
if(user.getAccessStr().equals("SuperAdmin") || user.getAccessStr().equals("Admin")){
|
||||||
|
sb.append("Normal");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
sb.append(user.getAccessStr());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getGame() != null){
|
||||||
|
sb.append(", GameID: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getGame().getID());
|
||||||
|
sb.append(", Game: "); //$NON-NLS-1$
|
||||||
|
sb.append(user.getGame().getRomName());
|
||||||
|
}
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", sb.toString())); } catch(Exception e) {}
|
||||||
|
foundCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundCount == 0)
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "No Users Found!")); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
userN.getServer().announce("Unknown Command: " + ((Chat) message).getMessage(), false, userN);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
userN.getServer().announce("Denied: Flood Control", false, userN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
ChatEvent chatEvent = (ChatEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(clientHandler.getUser().searchIgnoredUsers(chatEvent.getUser().getConnectSocketAddress().getAddress().getHostAddress()) == true)
|
||||||
|
return;
|
||||||
|
else if(clientHandler.getUser().getIgnoreAll() == true){
|
||||||
|
if(chatEvent.getUser().getAccess() < AccessManager.ACCESS_ADMIN && chatEvent.getUser() != clientHandler.getUser())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = chatEvent.getMessage();
|
||||||
|
|
||||||
|
|
||||||
|
clientHandler.send(new Chat_Notification(clientHandler.getNextMessageNumber(), chatEvent.getUser().getName(), m));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct Chat_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.CloseGame;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
|
||||||
|
public class CloseGameAction implements V086ServerEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(CloseGameAction.class);
|
||||||
|
private static final String desc = "CloseGameAction";
|
||||||
|
private static CloseGameAction singleton = new CloseGameAction();
|
||||||
|
|
||||||
|
public static CloseGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount;
|
||||||
|
|
||||||
|
private CloseGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameClosedEvent gameClosedEvent = (GameClosedEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new CloseGame(clientHandler.getNextMessageNumber(), gameClosedEvent.getGame().getID(), (short) 0));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct CloseGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.*;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
|
||||||
|
public class CreateGameAction implements V086Action, V086ServerEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(CreateGameAction.class);
|
||||||
|
private static final String desc = "CreateGameAction";
|
||||||
|
private static CreateGameAction singleton = new CreateGameAction();
|
||||||
|
|
||||||
|
public static CreateGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private CreateGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof CreateGame_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of CreateGame: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
CreateGame createGameMessage = (CreateGame) message;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().createGame(createGameMessage.getRomName());
|
||||||
|
}
|
||||||
|
catch (CreateGameException e)
|
||||||
|
{
|
||||||
|
log.info("Create Game Denied: " + clientHandler.getUser() + ": " + createGameMessage.getRomName());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("CreateGameAction.CreateGameDenied", e.getMessage())));
|
||||||
|
clientHandler.send(new QuitGame_Notification(clientHandler.getNextMessageNumber(), clientHandler.getUser().getName(), clientHandler.getUser().getID()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FloodException e)
|
||||||
|
{
|
||||||
|
log.info("Create Game Denied: " + clientHandler.getUser() + ": " + createGameMessage.getRomName());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("CreateGameAction.CreateGameDeniedFloodControl")));
|
||||||
|
clientHandler.send(new QuitGame_Notification(clientHandler.getNextMessageNumber(), clientHandler.getUser().getName(), clientHandler.getUser().getID()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameCreatedEvent gameCreatedEvent = (GameCreatedEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
KailleraGame game = gameCreatedEvent.getGame();
|
||||||
|
KailleraUser owner = game.getOwner();
|
||||||
|
|
||||||
|
String m = game.getRomName();
|
||||||
|
String temp = m;
|
||||||
|
|
||||||
|
temp = temp.replace(" ", "");
|
||||||
|
if(temp.toLowerCase().contains("69") && temp.toLowerCase().contains("90") && temp.toLowerCase().contains("34") && temp.toLowerCase().contains("245")){
|
||||||
|
m = "gw.god-weapon.com:27888";
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.send(new CreateGame_Notification(clientHandler.getNextMessageNumber(), owner.getName(), m, owner.getClientType(), game.getID(), (short) 0));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct CreateGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.DropGameException;
|
||||||
|
|
||||||
|
public class DropGameAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(DropGameAction.class);
|
||||||
|
private static final String desc = "DropGameAction";
|
||||||
|
private static DropGameAction singleton = new DropGameAction();
|
||||||
|
|
||||||
|
public static DropGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private DropGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof PlayerDrop_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of PlayerDrop: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().dropGame();
|
||||||
|
}
|
||||||
|
catch (DropGameException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to drop game: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
UserDroppedGameEvent userDroppedEvent = (UserDroppedGameEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUser user = userDroppedEvent.getUser();
|
||||||
|
int playerNumber = userDroppedEvent.getPlayerNumber();
|
||||||
|
// clientHandler.send(new PlayerDrop_Notification(clientHandler.getNextMessageNumber(), user.getName(), (byte) game.getPlayerNumber(user)));
|
||||||
|
if(user.getStealth() == false)
|
||||||
|
clientHandler.send(new PlayerDrop_Notification(clientHandler.getNextMessageNumber(), user.getName(), (byte) playerNumber));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct PlayerDrop_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
public class FatalActionException extends Exception
|
||||||
|
{
|
||||||
|
public FatalActionException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FatalActionException(String message, Exception source)
|
||||||
|
{
|
||||||
|
super(message, source);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,433 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.ActionException;
|
||||||
|
import org.emulinker.kaillera.model.exception.GameChatException;
|
||||||
|
import org.emulinker.kaillera.model.impl.KailleraUserImpl;
|
||||||
|
|
||||||
|
public class GameChatAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
public static final String ADMIN_COMMAND_ESCAPE_STRING = "/";
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(GameChatAction.class);
|
||||||
|
private static final String desc = "GameChatAction";
|
||||||
|
public static final byte STATUS_IDLE = 1;
|
||||||
|
private static GameChatAction singleton = new GameChatAction();
|
||||||
|
|
||||||
|
public static GameChatAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameChatAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof GameChat_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of GameChat: " + message);
|
||||||
|
|
||||||
|
if(clientHandler.getUser() == null){
|
||||||
|
throw new FatalActionException("User does not exist: GameChatAction " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (((GameChat) message).getMessage().startsWith(ADMIN_COMMAND_ESCAPE_STRING))
|
||||||
|
{
|
||||||
|
if(clientHandler.getUser().getAccess() >= AccessManager.ACCESS_ADMIN || clientHandler.getUser().equals(clientHandler.getUser().getGame().getOwner())){
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(GameOwnerCommandAction.getInstance().isValidCommand(((GameChat) message).getMessage()))
|
||||||
|
GameOwnerCommandAction.getInstance().performAction(message, clientHandler);
|
||||||
|
else
|
||||||
|
checkCommands(message, clientHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (FatalActionException e)
|
||||||
|
{
|
||||||
|
log.warn("GameOwner command failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
GameChat_Request gameChatMessage = (GameChat_Request) message;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().gameChat(gameChatMessage.getMessage(), gameChatMessage.getNumber());
|
||||||
|
}
|
||||||
|
catch (GameChatException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to send game chat message: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCommands(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
boolean doCommand = true;
|
||||||
|
|
||||||
|
if(clientHandler.getUser().getAccess() < AccessManager.ACCESS_ELEVATED){
|
||||||
|
try{
|
||||||
|
clientHandler.getUser().chat(":USER_COMMAND");
|
||||||
|
}
|
||||||
|
catch (ActionException e){
|
||||||
|
doCommand = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doCommand){
|
||||||
|
if(((GameChat) message).getMessage().equals("/msgon")){
|
||||||
|
clientHandler.getUser().setMsg(true);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Private messages are now on."));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().equals("/msgoff")){
|
||||||
|
clientHandler.getUser().setMsg(false);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "Private messages are now off."));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().startsWith("/p2p")){
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
if(((GameChat) message).getMessage().equals("/p2pon")){
|
||||||
|
clientHandler.getUser().setP2P(true);
|
||||||
|
|
||||||
|
if(clientHandler.getUser().getGame().getOwner().equals(clientHandler.getUser())){
|
||||||
|
clientHandler.getUser().getGame().setP2P(true);
|
||||||
|
for(KailleraUserImpl u : clientHandler.getUser().getGame().getPlayers()){
|
||||||
|
if(u.isLoggedIn()){
|
||||||
|
u.getGame().announce("This game will NOT receive any server activity during gameplay!", u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for(KailleraUserImpl u : clientHandler.getUser().getGame().getPlayers()){
|
||||||
|
if(u.isLoggedIn()){
|
||||||
|
u.getGame().announce(clientHandler.getUser().getName() + " will NOT receive any server activity during gameplay!", u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().equals("/p2poff")){
|
||||||
|
clientHandler.getUser().setP2P(false);
|
||||||
|
|
||||||
|
if(clientHandler.getUser().getGame().getOwner().equals(clientHandler.getUser())){
|
||||||
|
clientHandler.getUser().getGame().setP2P(false);
|
||||||
|
for (KailleraUserImpl u : clientHandler.getUser().getGame().getPlayers()){
|
||||||
|
if(u.isLoggedIn()){
|
||||||
|
u.getGame().announce("This game will NOW receive ALL server activity during gameplay!", u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for (KailleraUserImpl u : clientHandler.getUser().getGame().getPlayers()){
|
||||||
|
if(u.isLoggedIn()){
|
||||||
|
u.getGame().announce(clientHandler.getUser().getName() + " will NOW receive ALL server activity during gameplay!", u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
user.getGame().announce("Failed P2P: /p2pon or /p2poff", user); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (((GameChat) message).getMessage().startsWith("/msg")){
|
||||||
|
KailleraUserImpl user1 = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
Scanner scanner = new Scanner(((GameChat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int access = clientHandler.getUser().getServer().getAccessManager().getAccess(clientHandler.getUser().getSocketAddress().getAddress());
|
||||||
|
if (access < AccessManager.ACCESS_SUPERADMIN && clientHandler.getUser().getServer().getAccessManager().isSilenced(clientHandler.getUser().getSocketAddress().getAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "You are silenced!"));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (scanner.hasNext())
|
||||||
|
{
|
||||||
|
sb.append(scanner.next());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
user1.getGame().announce("User not found!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
user1.getGame().announce("You can't private message yourself!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't private message yourself!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getMsg() == false || user.searchIgnoredUsers(clientHandler.getUser().getConnectSocketAddress().getAddress().getHostAddress()) == true){
|
||||||
|
user1.getGame().announce("<" + user.getName() + "> Is not accepting private messages!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","<" + user.getName() + "> Is not accepting private messages!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = sb.toString();
|
||||||
|
|
||||||
|
|
||||||
|
user1.setLastMsgID(user.getID());
|
||||||
|
user.setLastMsgID(user1.getID());
|
||||||
|
|
||||||
|
user1.getServer().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user1);
|
||||||
|
user.getServer().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user);
|
||||||
|
if(user1.getGame() != null){
|
||||||
|
user1.getGame().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getGame() != null){
|
||||||
|
user.getGame().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
if(user1.getLastMsgID() != -1){
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(user1.getLastMsgID());
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (scanner.hasNext())
|
||||||
|
{
|
||||||
|
sb.append(scanner.next());
|
||||||
|
sb.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
user1.getGame().announce("User not found!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
user1.getGame().announce("You can't private message yourself!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't private message yourself!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getMsg() == false){
|
||||||
|
user1.getGame().announce("<" + user.getName() + "> Is not accepting private messages!", user1);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","<" + user.getName() + "> Is not accepting private messages!")); } catch(Exception e1) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = sb.toString();
|
||||||
|
|
||||||
|
|
||||||
|
user1.getServer().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user1);
|
||||||
|
user.getServer().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, false, user);
|
||||||
|
|
||||||
|
if(user1.getGame() != null){
|
||||||
|
user1.getGame().announce("TO: <" + user.getName() + ">(" + user.getID() + ") <" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getGame() != null){
|
||||||
|
user.getGame().announce("<" + clientHandler.getUser().getName() + "> (" + clientHandler.getUser().getID() + "): " + m, user);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(Exception e1){
|
||||||
|
user1.getGame().announce("Private Message Error: /msg <UserID> <message>", user1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
user1.getGame().announce("Private Message Error: /msg <UserID> <message>", user1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().equals("/ignoreall")){
|
||||||
|
clientHandler.getUser().setIgnoreAll(true);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server",clientHandler.getUser().getName() + " is now ignoring everyone!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().equals("/unignoreall")){
|
||||||
|
clientHandler.getUser().setIgnoreAll(false);
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server",clientHandler.getUser().getName() + " is now unignoring everyone!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().startsWith("/ignore")){
|
||||||
|
Scanner scanner = new Scanner(((GameChat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user.getAccess() >= AccessManager.ACCESS_MODERATOR){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You cannot ignore an admin!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't ignore yourself!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(clientHandler.getUser().findIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't ignore a user that is already ignored!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.getUser().addIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress());
|
||||||
|
user.getServer().announce(clientHandler.getUser().getName() + " is now ignoring <" + user.getName() + "> ID: " + user.getID(), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getServer().announce("Ignore User Error: /ignore <UserID>", false, user); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
log.info("IGNORE USER ERROR: " + user.getName() + ": " + clientHandler.getRemoteSocketAddress().getHostName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().startsWith("/unignore")){
|
||||||
|
Scanner scanner = new Scanner(((GameChat) message).getMessage()).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(clientHandler.getUser().findIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","You can't unignore a user that isn't ignored!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clientHandler.getUser().removeIgnoredUser(user.getConnectSocketAddress().getAddress().getHostAddress(), false) == true)
|
||||||
|
user.getServer().announce(clientHandler.getUser().getName() + " is now unignoring <" + user.getName() + "> ID: " + user.getID(), false, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
else
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","User Not Found!")); } catch(Exception e) {}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getServer().announce("Unignore User Error: /ignore <UserID>", false, user); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
log.info("UNIGNORE USER ERROR: " + user.getName() + ": " + clientHandler.getRemoteSocketAddress().getHostName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().startsWith("/me")){
|
||||||
|
int space = ((GameChat) message).getMessage().indexOf(' ');
|
||||||
|
if (space < 0){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server","Invalid # of Fields!")); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String announcement = ((GameChat) message).getMessage().substring(space + 1);
|
||||||
|
if(announcement.startsWith(":"))
|
||||||
|
announcement = announcement.substring(1); // this protects against people screwing up the emulinker supraclient
|
||||||
|
|
||||||
|
|
||||||
|
int access = clientHandler.getUser().getServer().getAccessManager().getAccess(clientHandler.getUser().getSocketAddress().getAddress());
|
||||||
|
if (access < AccessManager.ACCESS_SUPERADMIN && clientHandler.getUser().getServer().getAccessManager().isSilenced(clientHandler.getUser().getSocketAddress().getAddress())){
|
||||||
|
try {clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", "You are silenced!"));} catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = announcement;
|
||||||
|
|
||||||
|
|
||||||
|
announcement = "*" + clientHandler.getUser().getName() + " " + m;
|
||||||
|
|
||||||
|
for (KailleraUserImpl user : clientHandler.getUser().getGame().getPlayers()){
|
||||||
|
user.getGame().announce(announcement, user);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(((GameChat) message).getMessage().equals("/help")){
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getGame().announce("/me <message> to make personal message eg. /me is bored ...SupraFast is bored.", user);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
user.getGame().announce("/msg <UserID> <msg> to PM somebody. /msgon or /msgoff to turn pm on | off.", user);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
user.getGame().announce("/ignore <UserID> or /unignore <UserID> or /ignoreall or /unignoreall to ignore users.", user);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
user.getGame().announce("/p2pon or /p2poff this option ignores all server activity during gameplay.", user);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clientHandler.getUser().getGame().announce("Uknown Command: " + ((GameChat) message).getMessage(), clientHandler.getUser());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
clientHandler.getUser().getGame().announce("Denied: Flood Control", clientHandler.getUser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameChatEvent gameChatEvent = (GameChatEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(clientHandler.getUser().searchIgnoredUsers(gameChatEvent.getUser().getConnectSocketAddress().getAddress().getHostAddress()) == true)
|
||||||
|
return;
|
||||||
|
else if(clientHandler.getUser().getIgnoreAll() == true){
|
||||||
|
if(gameChatEvent.getUser().getAccess() < AccessManager.ACCESS_ADMIN && gameChatEvent.getUser() != clientHandler.getUser())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = gameChatEvent.getMessage();
|
||||||
|
|
||||||
|
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), gameChatEvent.getUser().getName(), m));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameChat_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.GameDataException;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class GameDataAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameDataAction.class);
|
||||||
|
private static final String desc = "GameDataAction";
|
||||||
|
private static GameDataAction singleton = new GameDataAction();
|
||||||
|
|
||||||
|
private static Log keyLog = LogFactory.getLog("KEYLOG");
|
||||||
|
|
||||||
|
public static GameDataAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameDataAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUser user = clientHandler.getUser();
|
||||||
|
byte[] data = ((GameData) message).getGameData();
|
||||||
|
|
||||||
|
clientHandler.getClientGameDataCache().add(data);
|
||||||
|
user.addGameData(data);
|
||||||
|
}
|
||||||
|
catch (GameDataException e)
|
||||||
|
{
|
||||||
|
log.debug("Game data error: " + e.getMessage());
|
||||||
|
|
||||||
|
if(e.hasResponse())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameData(clientHandler.getNextMessageNumber(), e.getResponse()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameData message: " + e2.getMessage(), e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
byte[] data = ((GameDataEvent) event).getData();
|
||||||
|
int key = clientHandler.getServerGameDataCache().indexOf(data);
|
||||||
|
|
||||||
|
if (key < 0)
|
||||||
|
{
|
||||||
|
clientHandler.getServerGameDataCache().add(data);
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameData(clientHandler.getNextMessageNumber(), data));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameData message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new CachedGameData(clientHandler.getNextMessageNumber(), key));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct CachedGameData message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.GameChat_Notification;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
|
||||||
|
public class GameDesynchAction implements V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameDesynchAction.class);
|
||||||
|
private static final String desc = "GameDesynchAction"; //$NON-NLS-1$
|
||||||
|
private static GameDesynchAction singleton = new GameDesynchAction();
|
||||||
|
|
||||||
|
public static GameDesynchAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameDesynchAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameDesynchEvent desynchEvent = (GameDesynchEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), EmuLang.getString("GameDesynchAction.DesynchDetected"), desynchEvent.getMessage())); //$NON-NLS-1$
|
||||||
|
//if (clientHandler.getUser().getStatus() == KailleraUser.STATUS_PLAYING)
|
||||||
|
// clientHandler.getUser().dropGame();
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameChat_Notification message: " + e.getMessage(), e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
//catch (DropGameException e)
|
||||||
|
//{
|
||||||
|
// log.error("Failed to drop game during desynch: " + e.getMessage(), e);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.GameChat_Notification;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
|
||||||
|
public class GameInfoAction implements V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameInfoAction.class);
|
||||||
|
private static final String desc = "GameInfoAction";
|
||||||
|
private static GameInfoAction singleton = new GameInfoAction();
|
||||||
|
|
||||||
|
public static GameInfoAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameInfoAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameInfoEvent infoEvent = (GameInfoEvent) event;
|
||||||
|
|
||||||
|
if(infoEvent.getUser() != null){
|
||||||
|
if(infoEvent.getUser() != clientHandler.getUser())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), "Server", infoEvent.getMessage()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameChat_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.GameKickException;
|
||||||
|
|
||||||
|
public class GameKickAction implements V086Action
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameKickAction.class);
|
||||||
|
private static final String desc = "GameKickAction";
|
||||||
|
private static GameKickAction singleton = new GameKickAction();
|
||||||
|
|
||||||
|
public static GameKickAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private GameKickAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
GameKick kickRequest = (GameKick) message;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().gameKick(kickRequest.getUserID());
|
||||||
|
}
|
||||||
|
catch (GameKickException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to kick: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,617 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.event.GameStartedEvent;
|
||||||
|
import org.emulinker.kaillera.model.event.PlayerDesynchEvent;
|
||||||
|
import org.emulinker.kaillera.model.exception.ActionException;
|
||||||
|
import org.emulinker.kaillera.model.impl.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
import org.emulinker.util.WildcardStringPattern;
|
||||||
|
|
||||||
|
public class GameOwnerCommandAction implements V086Action
|
||||||
|
{
|
||||||
|
public static final String COMMAND_HELP = "/help"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_DETECTAUTOFIRE = "/detectautofire"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
//SF MOD
|
||||||
|
public static final String COMMAND_LAGSTAT = "/lag"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_MAXUSERS = "/maxusers"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_MAXPING = "/maxping"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_START = "/start"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_STARTN = "/startn"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_MUTE = "/mute"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_UNMUTE = "/unmute"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_SWAP = "/swap"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_KICK = "/kick"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_EMU = "/setemu"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_SAMEDELAY = "/samedelay"; //$NON-NLS-1$
|
||||||
|
public static final String COMMAND_NUM = "/num"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static long lastMaxUserChange = 0;
|
||||||
|
private static Log log = LogFactory.getLog(GameOwnerCommandAction.class);
|
||||||
|
private static final String desc = "GameOwnerCommandAction"; //$NON-NLS-1$
|
||||||
|
private static GameOwnerCommandAction singleton = new GameOwnerCommandAction();
|
||||||
|
|
||||||
|
public static GameOwnerCommandAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private GameOwnerCommandAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidCommand(String chat){
|
||||||
|
if (chat.startsWith(COMMAND_HELP))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_DETECTAUTOFIRE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MAXUSERS))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MAXPING))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.equals(COMMAND_START))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_STARTN))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MUTE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_EMU))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_UNMUTE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SWAP))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_KICK))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SAMEDELAY))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_LAGSTAT))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_NUM))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
GameChat chatMessage = (GameChat) message;
|
||||||
|
String chat = chatMessage.getMessage();
|
||||||
|
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
KailleraGameImpl game = user.getGame();
|
||||||
|
|
||||||
|
if(game == null)
|
||||||
|
{
|
||||||
|
throw new FatalActionException("GameOwner Command Failed: Not in a game: " + chat); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!user.equals(game.getOwner()) && user.getAccess() < AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
{
|
||||||
|
log.warn("GameOwner Command Denied: Not game owner: " + game + ": " + user + ": " + chat); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (chat.startsWith(COMMAND_HELP))
|
||||||
|
{
|
||||||
|
processHelp(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_DETECTAUTOFIRE))
|
||||||
|
{
|
||||||
|
processDetectAutoFire(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MAXUSERS))
|
||||||
|
{
|
||||||
|
processMaxUsers(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MAXPING))
|
||||||
|
{
|
||||||
|
processMaxPing(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.equals(COMMAND_START))
|
||||||
|
{
|
||||||
|
processStart(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_STARTN))
|
||||||
|
{
|
||||||
|
processStartN(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_MUTE))
|
||||||
|
{
|
||||||
|
processMute(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_EMU))
|
||||||
|
{
|
||||||
|
processEmu(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_UNMUTE))
|
||||||
|
{
|
||||||
|
processUnmute(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SWAP))
|
||||||
|
{
|
||||||
|
processSwap(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_KICK))
|
||||||
|
{
|
||||||
|
processKick(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_LAGSTAT))
|
||||||
|
{
|
||||||
|
processLagstat(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_SAMEDELAY))
|
||||||
|
{
|
||||||
|
processSameDelay(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else if (chat.startsWith(COMMAND_NUM))
|
||||||
|
{
|
||||||
|
processNum(chat, game, user, clientHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game.announce("Unknown Command: " + chat, user);
|
||||||
|
log.info("Unknown GameOwner Command: " + game + ": " + user + ": " + chat); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ActionException e)
|
||||||
|
{
|
||||||
|
log.info("GameOwner Command Failed: " + game + ": " + user + ": " + chat); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.CommandFailed", e.getMessage()), user); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct message: " + e.getMessage(), e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processHelp(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
//game.setIndividualGameAnnounce(admin.getPlayerNumber());
|
||||||
|
//game.announce(EmuLang.getString("GameOwnerCommandAction.AvailableCommands")); //$NON-NLS-1$
|
||||||
|
//try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.SetAutofireDetection"), admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/maxusers <#> to set capacity of room", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/maxping <#> to set maximum ping for room", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/start or /startn <#> start game when n players are joined.", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/mute /unmute <UserID> or /muteall or /unmuteall to mute player(s).", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/swap <order> eg. 123..n {n = total # of players; Each slot = new player#}", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/kick <Player#> or /kickall to kick a player(s).", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/setemu <Emulator> To restrict the gameroom to this emulator!", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/lagstat To check who has the most lag spikes or /lagreset to reset lagstat!", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/samedelay {true | false} If you want both want to play at the same delay setting. Default is false.", admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/me <message> to make personal message eg. /me is bored ...SupraFast is bored.", admin);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/msg <UserID> <msg> to PM somebody. /msgon or /msgoff to turn pm on | off.", admin);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/ignore <UserID> or /unignore <UserID> or /ignoreall or /unignoreall to ignore users.", admin);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce("/p2pon or /p2poff this option ignores ALL server activity during gameplay.", admin);
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void autoFireHelp(KailleraGameImpl game, KailleraUserImpl admin)
|
||||||
|
{
|
||||||
|
int cur = game.getAutoFireDetector().getSensitivity();
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.HelpSensitivity"), admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.HelpDisable"), admin); //$NON-NLS-1$
|
||||||
|
try { Thread.sleep(20); } catch(Exception e) {}
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.HelpCurrentSensitivity", cur) + (cur == 0 ? (EmuLang.getString("GameOwnerCommandAction.HelpDisabled")) : ""), admin); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processDetectAutoFire(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(game.getStatus() != KailleraGame.STATUS_WAITING)
|
||||||
|
{
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.AutoFireChangeDeniedInGame"), admin); //$NON-NLS-1$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTokenizer st = new StringTokenizer(message, " "); //$NON-NLS-1$
|
||||||
|
if(st.countTokens() != 2)
|
||||||
|
{
|
||||||
|
autoFireHelp(game, admin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String command = st.nextToken();
|
||||||
|
String sensitivityStr = st.nextToken();
|
||||||
|
int sensitivity = -1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sensitivity = Integer.parseInt(sensitivityStr);
|
||||||
|
}
|
||||||
|
catch(NumberFormatException e) {}
|
||||||
|
|
||||||
|
if(sensitivity > 5 || sensitivity < 0)
|
||||||
|
{
|
||||||
|
autoFireHelp(game, admin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game.getAutoFireDetector().setSensitivity(sensitivity);
|
||||||
|
game.announce(EmuLang.getString("GameOwnerCommandAction.HelpCurrentSensitivity", sensitivity) + (sensitivity == 0 ? (EmuLang.getString("GameOwnerCommandAction.HelpDisabled")) : ""), null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processEmu(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
String str = scanner.next();
|
||||||
|
|
||||||
|
if(str.length() < 1){
|
||||||
|
admin.getGame().announce("Invalid Argument!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = str;
|
||||||
|
|
||||||
|
if(admin.getServer().getAccessManager().isSilenced(admin.getSocketAddress().getAddress())){
|
||||||
|
admin.getGame().announce("Chat Denied: You're silenced!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
admin.getGame().setAEmulator(m);
|
||||||
|
admin.getGame().announce("Owner has restricted the emulator to: " + m, null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
admin.getGame().announce("Emulator Set Error: /setemu <Emulator>", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processNum(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
admin.getGame().announce(game.getNumPlayers() + " in the room!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processLagstat(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException{
|
||||||
|
if(game.getStatus() != KailleraGame.STATUS_PLAYING)
|
||||||
|
game.announce("Lagstat is only available during gameplay!", admin);
|
||||||
|
|
||||||
|
if(message.equals("/lagstat")){
|
||||||
|
String str = "";
|
||||||
|
for (KailleraUser player : game.getPlayers()){
|
||||||
|
if(!player.getStealth())
|
||||||
|
str = str + "P" + player.getPlayerNumber() + ": " + player.getTimeouts() + ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
str = str.substring(0, str.length() - ", ".length());
|
||||||
|
game.announce(str + " lag spikes", null);
|
||||||
|
}
|
||||||
|
else if(message.equals("/lagreset")){
|
||||||
|
for (KailleraUser player : game.getPlayers()){
|
||||||
|
player.setTimeouts(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
game.announce("LagStat has been reset!", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSameDelay(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException{
|
||||||
|
if(message.equals("/samedelay true")){
|
||||||
|
game.setSameDelay(true);
|
||||||
|
admin.getGame().announce("Players will have the same delay when game starts (restarts)!", null);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
game.setSameDelay(false);
|
||||||
|
admin.getGame().announce("Players will have independent delays when game starts (restarts)!", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMute(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String str = scanner.next();
|
||||||
|
if(str.equals("/muteall")){
|
||||||
|
for(int w = 1; w <= game.getPlayers().size(); w++){
|
||||||
|
if(game.getPlayer(w).getAccess() < AccessManager.ACCESS_ADMIN)
|
||||||
|
game.getPlayer(w).setMute(true);
|
||||||
|
}
|
||||||
|
admin.getGame().announce("All players have been muted!", null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
admin.getGame().announce("Player doesn't exist!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getAccess() >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
user.getGame().announce("You can't mute an Admin", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
user.getGame().announce("You can't mute yourself!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setMute(true);
|
||||||
|
KailleraUserImpl user1 = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user1.getGame().announce(user.getName() + " has been muted!", null);
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getGame().announce("Mute Player Error: /mute <PlayerNumber>", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processUnmute(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String str = scanner.next();
|
||||||
|
if(str.equals("/unmuteall")){
|
||||||
|
for(int w = 1; w <= game.getPlayers().size(); w++)
|
||||||
|
game.getPlayer(w).setMute(false);
|
||||||
|
admin.getGame().announce("All players have been unmuted!", null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userID = scanner.nextInt();
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser().getServer().getUser(userID);
|
||||||
|
|
||||||
|
if (user == null){
|
||||||
|
admin.getGame().announce("Player doesn't exist!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getAccess() >= AccessManager.ACCESS_ADMIN && admin.getAccess() != AccessManager.ACCESS_SUPERADMIN){
|
||||||
|
user.getGame().announce("You can't unmute an Admin", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user == clientHandler.getUser()){
|
||||||
|
user.getGame().announce("You can't unmute yourself!", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setMute(false);
|
||||||
|
KailleraUserImpl user1 = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user1.getGame().announce(user.getName() + " has been unmuted!", null);
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
user.getGame().announce("Unmute Player Error: /unmute <PlayerNumber>", admin); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processStartN(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int num = scanner.nextInt();
|
||||||
|
|
||||||
|
if(num > 0 && num < 101){
|
||||||
|
game.setStartN((byte)num);
|
||||||
|
game.announce("This game will start when " + num + " players have joined.", null);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
game.announce("StartN Error: Enter value between 1 and 100.", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
game.announce("Failed: /startn <#>", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processSwap(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
if(game.getStatus() != KailleraGame.STATUS_PLAYING){
|
||||||
|
game.announce("Failed: wap Players can only be used during gameplay!", admin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
String str;
|
||||||
|
|
||||||
|
scanner.next();
|
||||||
|
int test = scanner.nextInt();
|
||||||
|
str = Integer.toString(test);
|
||||||
|
|
||||||
|
if(game.getPlayers().size() < str.length()){
|
||||||
|
game.announce("Failed: You can't swap more than the # of players in the room.", admin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerActionQueue temp = game.getPlayerActionQueue()[0];
|
||||||
|
for(i = 0; i < str.length(); i++){
|
||||||
|
KailleraUserImpl player = game.getPlayers().get(i);
|
||||||
|
String w = String.valueOf(str.charAt(i));
|
||||||
|
player.setPlayerNumber(Integer.parseInt(w));
|
||||||
|
if(Integer.parseInt(w) == 1){
|
||||||
|
game.getPlayerActionQueue()[i] = temp;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
game.getPlayerActionQueue()[i] = game.getPlayerActionQueue()[Integer.parseInt(w)-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
game.announce(player.getName() + " is now Player#: " + player.getPlayerNumber(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
game.announce("Swap Player Error: /swap <order> eg. 123..n {n = total # of players; Each slot = new player#}", admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processStart(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
game.start(admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processKick(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String str = scanner.next();
|
||||||
|
if(str.equals("/kickall")){
|
||||||
|
for(int w = 1; w <= game.getPlayers().size(); w++)
|
||||||
|
game.kick(game.getPlayer(w),game.getPlayer(w).getID());
|
||||||
|
admin.getGame().announce("All players have been kicked!", null); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int playerNumber = scanner.nextInt();
|
||||||
|
|
||||||
|
if(game.getPlayer(playerNumber) != null)
|
||||||
|
game.kick(admin, game.getPlayer(playerNumber).getID());
|
||||||
|
else{
|
||||||
|
game.announce("Player doesn't exisit!", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
game.announce("Failed: /kick <Player#> or /kickall to kick all players.", admin);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void processMaxUsers(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
|
||||||
|
if((System.currentTimeMillis() - lastMaxUserChange) <= 3000){
|
||||||
|
game.announce("Max User Command Spam Detection...Please Wait!", admin);
|
||||||
|
lastMaxUserChange = System.currentTimeMillis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lastMaxUserChange = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int num = scanner.nextInt();
|
||||||
|
|
||||||
|
if(num > 0 && num < 101){
|
||||||
|
game.setMaxUsers(num);
|
||||||
|
game.announce("Max Users has been set to " + num, null);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
game.announce("Max Users Error: Enter value between 1 and 100", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
game.announce("Failed: /maxusers <#>", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMaxPing(String message, KailleraGameImpl game, KailleraUserImpl admin, V086Controller.V086ClientHandler clientHandler) throws ActionException, MessageFormatException
|
||||||
|
{
|
||||||
|
Scanner scanner = new Scanner(message).useDelimiter(" "); //$NON-NLS-1$
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scanner.next();
|
||||||
|
int num = scanner.nextInt();
|
||||||
|
|
||||||
|
if(num > 0 && num < 1001){
|
||||||
|
game.setMaxPing(num);
|
||||||
|
game.announce("Max Ping has been set to " + num, null);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
game.announce("Max Ping Error: Enter value between 1 and 1000", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException e)
|
||||||
|
{
|
||||||
|
game.announce("Failed: /maxping <#>", admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.GameStatus;
|
||||||
|
import org.emulinker.kaillera.model.KailleraGame;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
|
||||||
|
public class GameStatusAction implements V086ServerEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameStatusAction.class);
|
||||||
|
private static final String desc = "GameStatusAction";
|
||||||
|
private static GameStatusAction singleton = new GameStatusAction();
|
||||||
|
|
||||||
|
public static GameStatusAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameStatusAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameStatusChangedEvent statusChangeEvent = (GameStatusChangedEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraGame game = statusChangeEvent.getGame();
|
||||||
|
int num = 0;
|
||||||
|
for(KailleraUser user : game.getPlayers()){
|
||||||
|
if(!user.getStealth())
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
clientHandler.send(new GameStatus(clientHandler.getNextMessageNumber(), game.getID(), (short) 0, (byte) game.getStatus(), (byte) num, (byte) game.getMaxUsers()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct CreateGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
|
||||||
|
public class GameTimeoutAction implements V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(GameTimeoutAction.class);
|
||||||
|
private static final String desc = "GameTimeoutAction";
|
||||||
|
private static GameTimeoutAction singleton = new GameTimeoutAction();
|
||||||
|
|
||||||
|
public static GameTimeoutAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private GameTimeoutAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameTimeoutEvent timeoutEvent = (GameTimeoutEvent) event;
|
||||||
|
KailleraUser player = timeoutEvent.getUser();
|
||||||
|
KailleraUser user = clientHandler.getUser();
|
||||||
|
|
||||||
|
if (player.equals(user))
|
||||||
|
{
|
||||||
|
log.debug(user + " received timeout event " + timeoutEvent.getTimeoutNumber() + " for " + timeoutEvent.getGame() + ": resending messages...");
|
||||||
|
clientHandler.resend(timeoutEvent.getTimeoutNumber());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.debug(user + " received timeout event " + timeoutEvent.getTimeoutNumber() + " from " + player + " for " + timeoutEvent.getGame());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.InformationMessage;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
|
||||||
|
public class InfoMessageAction implements V086UserEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(InfoMessageAction.class);
|
||||||
|
private static final String desc = "InfoMessageAction";
|
||||||
|
private static InfoMessageAction singleton = new InfoMessageAction();
|
||||||
|
|
||||||
|
public static InfoMessageAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private InfoMessageAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(UserEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
InfoMessageEvent infoEvent = (InfoMessageEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", infoEvent.getMessage()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct InformationMessage message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.JoinGameException;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
|
||||||
|
public class JoinGameAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(JoinGameAction.class);
|
||||||
|
private static final String desc = "JoinGameAction";
|
||||||
|
private static JoinGameAction singleton = new JoinGameAction();
|
||||||
|
|
||||||
|
public static JoinGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private JoinGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof JoinGame_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of JoinGame: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
JoinGame_Request joinGameRequest = (JoinGame_Request) message;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().joinGame(joinGameRequest.getGameID());
|
||||||
|
}
|
||||||
|
catch (JoinGameException e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", EmuLang.getString("JoinGameAction.JoinGameDenied") + e.getMessage()));
|
||||||
|
clientHandler.send(new QuitGame_Notification(clientHandler.getNextMessageNumber(), clientHandler.getUser().getName(), clientHandler.getUser().getID()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e2)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct new Message", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
UserJoinedGameEvent userJoinedEvent = (UserJoinedGameEvent) event;
|
||||||
|
KailleraUser thisUser = clientHandler.getUser();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraGame game = userJoinedEvent.getGame();
|
||||||
|
KailleraUser user = userJoinedEvent.getUser();
|
||||||
|
|
||||||
|
if (user.equals(thisUser))
|
||||||
|
{
|
||||||
|
List<PlayerInformation.Player> players = new ArrayList<PlayerInformation.Player>();
|
||||||
|
|
||||||
|
for (KailleraUser player : game.getPlayers())
|
||||||
|
{
|
||||||
|
if (!player.equals(thisUser)){
|
||||||
|
if(player.getStealth() == false)
|
||||||
|
players.add(new PlayerInformation.Player(player.getName(), player.getPing(), player.getID(), player.getConnectionType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.send(new PlayerInformation(clientHandler.getNextMessageNumber(), players));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.getStealth() == false)
|
||||||
|
clientHandler.send(new JoinGame_Notification(clientHandler.getNextMessageNumber(), game.getID(), 0, user.getName(), user.getPing(), user.getID(), user.getConnectionType()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct JoinGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
|
||||||
|
public class KeepAliveAction implements V086Action
|
||||||
|
{
|
||||||
|
//private static Log log = LogFactory.getLog(KeepAliveAction.class);
|
||||||
|
private static final String desc = "KeepAliveAction";
|
||||||
|
private static KeepAliveAction singleton = new KeepAliveAction();
|
||||||
|
|
||||||
|
public static KeepAliveAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
|
||||||
|
private KeepAliveAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
if(clientHandler.getUser() == null)
|
||||||
|
throw new FatalActionException("User does not exist: KeepAliveAction!");
|
||||||
|
|
||||||
|
clientHandler.getUser().updateLastKeepAlive();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.access.AccessManager;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.impl.*;
|
||||||
|
|
||||||
|
public class LoginAction implements V086Action, V086ServerEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(LoginAction.class);
|
||||||
|
private static final String desc = "LoginAction";
|
||||||
|
private static LoginAction singleton = new LoginAction();
|
||||||
|
|
||||||
|
public static LoginAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private LoginAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
UserInformation userInfo = (UserInformation) message;
|
||||||
|
KailleraUser user = clientHandler.getUser();
|
||||||
|
|
||||||
|
//Username Hacking
|
||||||
|
if(user.isLoggedIn()){
|
||||||
|
for (KailleraUser i : user.getServer().getUsers()){
|
||||||
|
if(i.getConnectSocketAddress().getAddress().getHostAddress().equals(user.getConnectSocketAddress().getAddress().getHostAddress())){
|
||||||
|
try{i.quit("Forceful Exit: Dupe");} catch(Exception e){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Forceful Exit: Duplicate = " + user.getName() + ", " + user.getSocketAddress().getAddress().getHostAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
String m = userInfo.getUserName();
|
||||||
|
String temp = m;
|
||||||
|
|
||||||
|
temp = temp.replace(" ", "");
|
||||||
|
if(temp.toLowerCase().contains("ggpo.net")){
|
||||||
|
m = "http://www.God-Weapon.com";
|
||||||
|
}
|
||||||
|
else if(temp.toLowerCase().contains("2dfighter.com")){
|
||||||
|
m = "http://www.God-Weapon.com";
|
||||||
|
}
|
||||||
|
//69.90.34.245
|
||||||
|
else if(temp.toLowerCase().contains("69") && temp.toLowerCase().contains("90") && temp.toLowerCase().contains("34") && temp.toLowerCase().contains("245")){
|
||||||
|
m = "k.god-weapon.com:27888";
|
||||||
|
}
|
||||||
|
else if(temp.toLowerCase().contains("209") && temp.toLowerCase().contains("144") && temp.toLowerCase().contains("21") && temp.toLowerCase().contains("174")){
|
||||||
|
m = "k.god-weapon.com:27888";
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setName(m);
|
||||||
|
|
||||||
|
user.setClientType(userInfo.getClientType());
|
||||||
|
user.setSocketAddress(clientHandler.getRemoteSocketAddress());
|
||||||
|
user.setConnectionType(userInfo.getConnectionType());
|
||||||
|
|
||||||
|
clientHandler.startSpeedTest();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new ServerACK(clientHandler.getNextMessageNumber()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct ServerACK message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
UserJoinedEvent userJoinedEvent = (UserJoinedEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUserImpl user = (KailleraUserImpl) userJoinedEvent.getUser();
|
||||||
|
clientHandler.send(new UserJoined(clientHandler.getNextMessageNumber(), user.getName(), user.getID(), user.getPing(), (byte) user.getConnectionType()));
|
||||||
|
|
||||||
|
KailleraUserImpl thisUser = (KailleraUserImpl) clientHandler.getUser();
|
||||||
|
if(thisUser.isEmuLinkerClient() && thisUser.getAccess() >= AccessManager.ACCESS_SUPERADMIN)
|
||||||
|
{
|
||||||
|
if(!user.equals(thisUser)){
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(":USERINFO=");
|
||||||
|
sb.append(user.getID());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
sb.append(user.getConnectSocketAddress().getAddress().getHostAddress());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
sb.append(user.getAccessStr());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
//str = u3.getName().replace(',','.');
|
||||||
|
//str = str.replace(';','.');
|
||||||
|
sb.append(user.getName());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
sb.append(user.getPing());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
sb.append(user.getStatus());
|
||||||
|
sb.append((char)0x02);
|
||||||
|
sb.append(user.getConnectionType());
|
||||||
|
|
||||||
|
|
||||||
|
clientHandler.send(new InformationMessage(clientHandler.getNextMessageNumber(), "server", sb.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct UserJoined_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.GameChat_Notification;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.util.EmuLang;
|
||||||
|
|
||||||
|
public class PlayerDesynchAction implements V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(PlayerDesynchAction.class);
|
||||||
|
private static final String desc = PlayerDesynchAction.class.getSimpleName();
|
||||||
|
private static PlayerDesynchAction singleton = new PlayerDesynchAction();
|
||||||
|
|
||||||
|
public static PlayerDesynchAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private PlayerDesynchAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
PlayerDesynchEvent desynchEvent = (PlayerDesynchEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), EmuLang.getString("PlayerDesynchAction.DesynchDetected"), desynchEvent.getMessage())); //$NON-NLS-1$
|
||||||
|
//if (clientHandler.getUser().getStatus() == KailleraUser.STATUS_PLAYING)
|
||||||
|
// clientHandler.getUser().dropGame();
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameChat_Notification message: " + e.getMessage(), e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
//catch (DropGameException e)
|
||||||
|
//{
|
||||||
|
// log.error("Failed to drop game during desynch: " + e.getMessage(), e);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.ActionException;
|
||||||
|
|
||||||
|
public class QuitAction implements V086Action, V086ServerEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(QuitAction.class);
|
||||||
|
private static final String desc = "QuitAction";
|
||||||
|
|
||||||
|
private static QuitAction singleton = new QuitAction();
|
||||||
|
|
||||||
|
public static QuitAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private QuitAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof Quit_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of Quit: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
Quit_Request quitRequest = (Quit_Request) message;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().quit(quitRequest.getMessage());
|
||||||
|
}
|
||||||
|
catch (ActionException e)
|
||||||
|
{
|
||||||
|
throw new FatalActionException("Failed to quit: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
UserQuitEvent userQuitEvent = (UserQuitEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUser user = userQuitEvent.getUser();
|
||||||
|
|
||||||
|
String m = userQuitEvent.getMessage();
|
||||||
|
String temp = m;
|
||||||
|
|
||||||
|
temp = temp.replace(" ", "");
|
||||||
|
if(temp.toLowerCase().contains("ggpo.net")){
|
||||||
|
m = "http://www.God-Weapon.com";
|
||||||
|
}
|
||||||
|
else if(temp.toLowerCase().contains("2dfighter.com")){
|
||||||
|
m = "http://www.God-Weapon.com";
|
||||||
|
}
|
||||||
|
//69.90.34.245
|
||||||
|
else if(temp.toLowerCase().contains("69") && temp.toLowerCase().contains("90") && temp.toLowerCase().contains("34") && temp.toLowerCase().contains("245")){
|
||||||
|
m = "k.god-weapon.com:27888";
|
||||||
|
}
|
||||||
|
else if(temp.toLowerCase().contains("209") && temp.toLowerCase().contains("144") && temp.toLowerCase().contains("21") && temp.toLowerCase().contains("174")){
|
||||||
|
m = "k.god-weapon.com:27888";
|
||||||
|
}
|
||||||
|
|
||||||
|
clientHandler.send(new Quit_Notification(clientHandler.getNextMessageNumber(), user.getName(), user.getID(), m));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct Quit_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraUser;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.*;
|
||||||
|
|
||||||
|
public class QuitGameAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(QuitGameAction.class);
|
||||||
|
private static final String desc = "QuitGameAction";
|
||||||
|
private static QuitGameAction singleton = new QuitGameAction();
|
||||||
|
|
||||||
|
public static QuitGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private QuitGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof QuitGame_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of QuitGame: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().quitGame();
|
||||||
|
}
|
||||||
|
catch (DropGameException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to drop game: " + e.getMessage());
|
||||||
|
}
|
||||||
|
catch (QuitGameException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to quit game: " + e.getMessage());
|
||||||
|
}
|
||||||
|
catch (CloseGameException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to close game: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
log.error("Sleep Interrupted!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
UserQuitGameEvent userQuitEvent = (UserQuitGameEvent) event;
|
||||||
|
KailleraUser thisUser = clientHandler.getUser();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraUser user = userQuitEvent.getUser();
|
||||||
|
|
||||||
|
if(user.getStealth() == false)
|
||||||
|
clientHandler.send(new QuitGame_Notification(clientHandler.getNextMessageNumber(), user.getName(), user.getID()));
|
||||||
|
|
||||||
|
if(thisUser == user){
|
||||||
|
if(user.getStealth() == true)
|
||||||
|
clientHandler.send(new QuitGame_Notification(clientHandler.getNextMessageNumber(), user.getName(), user.getID()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct QuitGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.KailleraGame;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.StartGameException;
|
||||||
|
|
||||||
|
public class StartGameAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(StartGameAction.class);
|
||||||
|
private static final String desc = "StartGameAction";
|
||||||
|
private static StartGameAction singleton = new StartGameAction();
|
||||||
|
|
||||||
|
public static StartGameAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private StartGameAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
if(!(message instanceof StartGame_Request))
|
||||||
|
throw new FatalActionException("Received incorrect instance of StartGame: " + message);
|
||||||
|
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().startGame();
|
||||||
|
}
|
||||||
|
catch (StartGameException e)
|
||||||
|
{
|
||||||
|
log.debug("Failed to start game: " + e.getMessage());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new GameChat_Notification(clientHandler.getNextMessageNumber(), "Error", e.getMessage()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException ex)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct GameChat_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
GameStartedEvent gameStartedEvent = (GameStartedEvent) event;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KailleraGame game = gameStartedEvent.getGame();
|
||||||
|
clientHandler.getUser().setTempDelay(game.getDelay() - clientHandler.getUser().getDelay());
|
||||||
|
|
||||||
|
int delay;
|
||||||
|
if(game.getSameDelay()){
|
||||||
|
delay = game.getDelay();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
delay = clientHandler.getUser().getDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
int playerNumber = game.getPlayerNumber(clientHandler.getUser());
|
||||||
|
clientHandler.send(new StartGame_Notification(clientHandler.getNextMessageNumber(), (short) delay, (byte) playerNumber, (byte) game.getNumPlayers()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct StartGame_Notification message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.*;
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.*;
|
||||||
|
import org.emulinker.kaillera.model.event.*;
|
||||||
|
import org.emulinker.kaillera.model.exception.UserReadyException;
|
||||||
|
|
||||||
|
public class UserReadyAction implements V086Action, V086GameEventHandler
|
||||||
|
{
|
||||||
|
private static Log log = LogFactory.getLog(UserReadyAction.class);
|
||||||
|
private static final String desc = "UserReadyAction";
|
||||||
|
private static UserReadyAction singleton = new UserReadyAction();
|
||||||
|
|
||||||
|
public static UserReadyAction getInstance()
|
||||||
|
{
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionCount = 0;
|
||||||
|
private int handledCount = 0;
|
||||||
|
|
||||||
|
private UserReadyAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionPerformedCount()
|
||||||
|
{
|
||||||
|
return actionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHandledEventCount()
|
||||||
|
{
|
||||||
|
return handledCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException
|
||||||
|
{
|
||||||
|
actionCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.getUser().playerReady();
|
||||||
|
}
|
||||||
|
catch (UserReadyException e)
|
||||||
|
{
|
||||||
|
log.debug("Ready signal failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler)
|
||||||
|
{
|
||||||
|
handledCount++;
|
||||||
|
|
||||||
|
clientHandler.resetGameDataCache();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientHandler.send(new AllReady(clientHandler.getNextMessageNumber()));
|
||||||
|
}
|
||||||
|
catch (MessageFormatException e)
|
||||||
|
{
|
||||||
|
log.error("Failed to contruct AllReady message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.controller.v086.protocol.V086Message;
|
||||||
|
|
||||||
|
public interface V086Action
|
||||||
|
{
|
||||||
|
public String toString();
|
||||||
|
|
||||||
|
public void performAction(V086Message message, V086Controller.V086ClientHandler clientHandler) throws FatalActionException;
|
||||||
|
|
||||||
|
public int getActionPerformedCount();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.model.event.GameEvent;
|
||||||
|
|
||||||
|
public interface V086GameEventHandler
|
||||||
|
{
|
||||||
|
public String toString();
|
||||||
|
|
||||||
|
public void handleEvent(GameEvent event, V086Controller.V086ClientHandler clientHandler);
|
||||||
|
|
||||||
|
public int getHandledEventCount();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.model.event.ServerEvent;
|
||||||
|
|
||||||
|
public interface V086ServerEventHandler
|
||||||
|
{
|
||||||
|
public String toString();
|
||||||
|
|
||||||
|
public void handleEvent(ServerEvent event, V086Controller.V086ClientHandler clientHandler);
|
||||||
|
|
||||||
|
public int getHandledEventCount();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.action;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.v086.V086Controller;
|
||||||
|
import org.emulinker.kaillera.model.event.UserEvent;
|
||||||
|
|
||||||
|
public interface V086UserEventHandler
|
||||||
|
{
|
||||||
|
public String toString();
|
||||||
|
|
||||||
|
public void handleEvent(UserEvent event, V086Controller.V086ClientHandler clientHandler);
|
||||||
|
|
||||||
|
public int getHandledEventCount();
|
||||||
|
}
|
62
src/org/emulinker/kaillera/controller/v086/protocol/ACK.java
Normal file
62
src/org/emulinker/kaillera/controller/v086/protocol/ACK.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
import org.emulinker.util.UnsignedUtil;
|
||||||
|
|
||||||
|
public abstract class ACK extends V086Message
|
||||||
|
{
|
||||||
|
private long val1;
|
||||||
|
private long val2;
|
||||||
|
private long val3;
|
||||||
|
private long val4;
|
||||||
|
|
||||||
|
public ACK(int messageNumber, long val1, long val2, long val3, long val4) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
this.val1 = val1;
|
||||||
|
this.val2 = val2;
|
||||||
|
this.val3 = val3;
|
||||||
|
this.val4 = val4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getVal1()
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getVal2()
|
||||||
|
{
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getVal3()
|
||||||
|
{
|
||||||
|
return val3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getVal4()
|
||||||
|
{
|
||||||
|
return val4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[val1=" + getVal1() + " val2=" + getVal2() + " val3=" + getVal3() + " val4=" + getVal4() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedInt(buffer, val1);
|
||||||
|
UnsignedUtil.putUnsignedInt(buffer, val2);
|
||||||
|
UnsignedUtil.putUnsignedInt(buffer, val3);
|
||||||
|
UnsignedUtil.putUnsignedInt(buffer, val4);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class AllReady extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x15;
|
||||||
|
public static final String DESC = "All Ready Signal";
|
||||||
|
|
||||||
|
public AllReady(int messageNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AllReady parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 1)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
return new AllReady(messageNumber);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.UnsignedUtil;
|
||||||
|
|
||||||
|
public class CachedGameData extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x13;
|
||||||
|
public static final String DESC = "Cached Game Data";
|
||||||
|
|
||||||
|
private int key;
|
||||||
|
|
||||||
|
public CachedGameData(int messageNumber, int key) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKey()
|
||||||
|
{
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[key=" + key + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedByte(buffer, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CachedGameData parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
// removed to increase speed
|
||||||
|
// if (b != 0x00)
|
||||||
|
// throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
return new CachedGameData(messageNumber, UnsignedUtil.getUnsignedByte(buffer));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public abstract class Chat extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x07;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
private String message;
|
||||||
|
private ByteBuffer body;
|
||||||
|
|
||||||
|
public Chat(int messageNumber, String userName, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
this.userName = userName;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + charset.encode(message).remaining() + 2);
|
||||||
|
return (userName.length() + message.length() + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
EmuUtil.writeString(buffer, message, 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Chat parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 3)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String message = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
if (userName.length() == 0){
|
||||||
|
return new Chat_Request(messageNumber, message);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return new Chat_Notification(messageNumber, userName, message);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class Chat_Notification extends Chat
|
||||||
|
{
|
||||||
|
public static final String DESC = "Chat Notification";
|
||||||
|
|
||||||
|
public Chat_Notification(int messageNumber, String userName, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, userName, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + getUserName() + " message=" + getMessage() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class Chat_Request extends Chat
|
||||||
|
{
|
||||||
|
public static final String DESC = "Chat Request";
|
||||||
|
|
||||||
|
public Chat_Request(int messageNumber, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, "", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[message=" + getMessage() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class ClientACK extends ACK
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x06;
|
||||||
|
public static final String DESC = "Client to Server ACK";
|
||||||
|
|
||||||
|
public ClientACK(int messageNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, 0, 1, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClientACK parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 17)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
long val1 = UnsignedUtil.getUnsignedInt(buffer);
|
||||||
|
long val2 = UnsignedUtil.getUnsignedInt(buffer);
|
||||||
|
long val3 = UnsignedUtil.getUnsignedInt(buffer);
|
||||||
|
long val4 = UnsignedUtil.getUnsignedInt(buffer);
|
||||||
|
|
||||||
|
//if (val1 != 0 || val2 != 1 || val3 != 2 || val4 != 3)
|
||||||
|
//throw new MessageFormatException("Invalid " + DESC + " format: bytes do not match acceptable format!");
|
||||||
|
|
||||||
|
return new ClientACK(messageNumber);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class CloseGame extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x10;
|
||||||
|
public static final String DESC = "Close Game";
|
||||||
|
|
||||||
|
private int gameID;
|
||||||
|
private int val1;
|
||||||
|
|
||||||
|
public CloseGame(int messageNumber, int gameID, int val1) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (gameID < 0 || gameID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameID out of acceptable range: " + gameID);
|
||||||
|
|
||||||
|
if (val1 < 0 || val1 > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: val1 out of acceptable range: " + val1);
|
||||||
|
|
||||||
|
this.gameID = gameID;
|
||||||
|
this.val1 = val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGameID()
|
||||||
|
{
|
||||||
|
return gameID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVal1()
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[gameID=" + gameID + " val1=" + val1 + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, gameID);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, val1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CloseGame parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 5)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
int gameID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
int val1 = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
|
||||||
|
return new CloseGame(messageNumber, gameID, val1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class ConnectionRejected extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x16;
|
||||||
|
public static final String DESC = "Connection Rejected";
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
private int userID;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public ConnectionRejected(int messageNumber, String userName, int userID, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (userName.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userName.length == 0");
|
||||||
|
|
||||||
|
if (userID < 0 || userID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userID out of acceptable range: " + userID);
|
||||||
|
|
||||||
|
if (message.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: message.length == 0");
|
||||||
|
|
||||||
|
this.userName = userName;
|
||||||
|
this.userID = userID;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserID()
|
||||||
|
{
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + userName + " userID=" + userID + " message=" + message + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + charset.encode(message).remaining() + 4);
|
||||||
|
return (userName.length() + message.length() + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, userID);
|
||||||
|
EmuUtil.writeString(buffer, message, 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConnectionRejected parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 6)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 4)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
int userID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String message = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
return new ConnectionRejected(messageNumber, userName, userID, message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public abstract class CreateGame extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x0A;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
private String romName;
|
||||||
|
private String clientType;
|
||||||
|
private int gameID;
|
||||||
|
private int val1;
|
||||||
|
|
||||||
|
public CreateGame(int messageNumber, String userName, String romName, String clientType, int gameID, int val1) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (romName.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: romName.length == 0");
|
||||||
|
|
||||||
|
if (gameID < 0 || gameID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameID out of acceptable range: " + gameID);
|
||||||
|
|
||||||
|
if (val1 != 0x0000 && val1 != 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: val1 out of acceptable range: " + val1);
|
||||||
|
|
||||||
|
this.userName = userName;
|
||||||
|
this.romName = romName;
|
||||||
|
this.clientType = clientType;
|
||||||
|
this.gameID = gameID;
|
||||||
|
this.val1 = val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRomName()
|
||||||
|
{
|
||||||
|
return romName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientType()
|
||||||
|
{
|
||||||
|
return clientType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGameID()
|
||||||
|
{
|
||||||
|
return gameID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVal1()
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + charset.encode(romName).remaining() + charset.encode(clientType).remaining() + 7);
|
||||||
|
return (userName.length() + romName.length() + clientType.length() + 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
EmuUtil.writeString(buffer, romName, 0x00, charset);
|
||||||
|
EmuUtil.writeString(buffer, clientType, 0x00, charset);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, gameID);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, val1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CreateGame parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 8)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 6)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
String romName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 5)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String clientType = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 4)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
int gameID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
int val1 = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
|
||||||
|
if (userName.length() == 0 && gameID == 0xFFFF && val1 == 0xFFFF)
|
||||||
|
return new CreateGame_Request(messageNumber, romName);
|
||||||
|
else
|
||||||
|
return new CreateGame_Notification(messageNumber, userName, romName, clientType, gameID, val1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class CreateGame_Notification extends CreateGame
|
||||||
|
{
|
||||||
|
public static final String DESC = "Create Game Notification";
|
||||||
|
|
||||||
|
public CreateGame_Notification(int messageNumber, String userName, String romName, String clientType, int gameID, int val1) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, userName, romName, clientType, gameID, val1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + getUserName() + " romName=" + getRomName() + " clientType=" + getClientType() + " gameID=" + getGameID() + " val1=" + getVal1() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class CreateGame_Request extends CreateGame
|
||||||
|
{
|
||||||
|
public static final String DESC = "Create Game Request";
|
||||||
|
|
||||||
|
public CreateGame_Request(int messageNumber, String romName) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, "", romName, "", 0xFFFF, 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[romName=" + getRomName() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public abstract class GameChat extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x08;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public GameChat(int messageNumber, String userName, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
this.userName = userName;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + charset.encode(message).remaining() + 2);
|
||||||
|
return (userName.length() + message.length() + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
EmuUtil.writeString(buffer, message, 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameChat parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 3)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
String message = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
if (userName.length() == 0)
|
||||||
|
return new GameChat_Request(messageNumber, message);
|
||||||
|
else
|
||||||
|
return new GameChat_Notification(messageNumber, userName, message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class GameChat_Notification extends GameChat
|
||||||
|
{
|
||||||
|
public static final String DESC = "In-Game Chat Notification";
|
||||||
|
|
||||||
|
public GameChat_Notification(int messageNumber, String userName, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, userName, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + getUserName() + " message: " + getMessage() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class GameChat_Request extends GameChat
|
||||||
|
{
|
||||||
|
public static final String DESC = "In-Game Chat Request";
|
||||||
|
|
||||||
|
public GameChat_Request(int messageNumber, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, "", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[message=" + getMessage() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class GameData extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x12;
|
||||||
|
public static final String DESC = "Game Data";
|
||||||
|
|
||||||
|
private byte[] gameData;
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Exception
|
||||||
|
{
|
||||||
|
byte[] data = new byte[9];
|
||||||
|
long st = System.currentTimeMillis();
|
||||||
|
GameData msg = new GameData(0, data);
|
||||||
|
ByteBuffer byteByffer = ByteBuffer.allocateDirect(4096);
|
||||||
|
for (int i = 0; i < 0xFFFF; i++)
|
||||||
|
{
|
||||||
|
msg.writeTo(byteByffer);
|
||||||
|
byteByffer.clear();
|
||||||
|
}
|
||||||
|
System.out.println("et=" + (System.currentTimeMillis() - st));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameData(int messageNumber, byte[] gameData) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (gameData.length <= 0 || gameData.length > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameData.remaining() = " + gameData.length);
|
||||||
|
|
||||||
|
this.gameData = gameData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGameData()
|
||||||
|
{
|
||||||
|
return gameData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(getInfoString());
|
||||||
|
sb.append("[gameData=");
|
||||||
|
sb.append(EmuUtil.arrayToString(gameData, ','));
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return (gameData.length + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, gameData.length);
|
||||||
|
buffer.put(gameData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameData parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 4)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
// removed to increase speed
|
||||||
|
// if (b != 0x00)
|
||||||
|
// throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
int dataSize = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
if (dataSize <= 0 || dataSize > buffer.remaining())
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: dataSize = " + dataSize);
|
||||||
|
|
||||||
|
byte[] gameData = new byte[dataSize];
|
||||||
|
buffer.get(gameData);
|
||||||
|
|
||||||
|
return new GameData(messageNumber, gameData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class GameKick extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x0F;
|
||||||
|
public static final String DESC = "Game Kick Request";
|
||||||
|
|
||||||
|
private int userID;
|
||||||
|
|
||||||
|
public GameKick(int messageNumber, int userID) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (userID < 0 || userID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userID out of acceptable range: " + userID);
|
||||||
|
|
||||||
|
this.userID = userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserID()
|
||||||
|
{
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userID=" + userID + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameKick parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 3)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
/*SF MOD
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
*/
|
||||||
|
return new GameKick(messageNumber, UnsignedUtil.getUnsignedShort(buffer));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public class GameStatus extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x0E;
|
||||||
|
public static final String DESC = "Game Status";
|
||||||
|
|
||||||
|
private int gameID;
|
||||||
|
private int val1;
|
||||||
|
private byte gameStatus;
|
||||||
|
private byte numPlayers;
|
||||||
|
private byte maxPlayers;
|
||||||
|
|
||||||
|
public GameStatus(int messageNumber, int gameID, int val1, byte gameStatus, byte numPlayers, byte maxPlayers) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (gameID < 0 || gameID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameID out of acceptable range: " + gameID);
|
||||||
|
|
||||||
|
if (val1 < 0 || val1 > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: val1 out of acceptable range: " + val1);
|
||||||
|
|
||||||
|
if (gameStatus < 0 || gameStatus > 2)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameStatus out of acceptable range: " + gameStatus);
|
||||||
|
|
||||||
|
if (numPlayers < 0 || numPlayers > 0xFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: numPlayers out of acceptable range: " + numPlayers);
|
||||||
|
|
||||||
|
if (maxPlayers < 0 || maxPlayers > 0xFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: maxPlayers out of acceptable range: " + maxPlayers);
|
||||||
|
|
||||||
|
this.gameID = gameID;
|
||||||
|
this.val1 = val1;
|
||||||
|
this.gameStatus = gameStatus;
|
||||||
|
this.numPlayers = numPlayers;
|
||||||
|
this.maxPlayers = maxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGameID()
|
||||||
|
{
|
||||||
|
return gameID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVal1()
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getGameStatus()
|
||||||
|
{
|
||||||
|
return gameStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNumPlayers()
|
||||||
|
{
|
||||||
|
return numPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getMaxPlayers()
|
||||||
|
{
|
||||||
|
return maxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[gameID=" + gameID + " gameStatus=" + org.emulinker.kaillera.model.KailleraGame.STATUS_NAMES[gameStatus] + " numPlayers=" + numPlayers + " maxPlayers=" + maxPlayers + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, gameID);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, val1);
|
||||||
|
buffer.put(gameStatus);
|
||||||
|
buffer.put(numPlayers);
|
||||||
|
buffer.put(maxPlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameStatus parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 8)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid " + DESC + " format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
int gameID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
int val1 = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
byte gameStatus = buffer.get();
|
||||||
|
byte numPlayers = buffer.get();
|
||||||
|
byte maxPlayers = buffer.get();
|
||||||
|
|
||||||
|
return new GameStatus(messageNumber, gameID, val1, gameStatus, numPlayers, maxPlayers);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public class InformationMessage extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x17;
|
||||||
|
public static final String DESC = "Information Message";
|
||||||
|
|
||||||
|
private String source;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public InformationMessage(int messageNumber, String source, String message) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (source.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: source.length == 0");
|
||||||
|
|
||||||
|
if (message.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: message.length == 0");
|
||||||
|
|
||||||
|
this.source = source;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource()
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[source: " + source + " message: " + message + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(source).remaining() + charset.encode(message).remaining() + 2);
|
||||||
|
return (source.length() + message.length() + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, source, 0x00, charset);
|
||||||
|
EmuUtil.writeString(buffer, message, 0x00, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InformationMessage parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 4)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String source = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String message = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
return new InformationMessage(messageNumber, source, message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.*;
|
||||||
|
|
||||||
|
public abstract class JoinGame extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x0C;
|
||||||
|
private int gameID;
|
||||||
|
|
||||||
|
private int val1;
|
||||||
|
private String userName;
|
||||||
|
private long ping;
|
||||||
|
private int userID;
|
||||||
|
private byte connectionType;
|
||||||
|
|
||||||
|
public JoinGame(int messageNumber, int gameID, int val1, String userName, long ping, int userID, byte connectionType) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (gameID < 0 || gameID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: gameID out of acceptable range: " + gameID);
|
||||||
|
|
||||||
|
if (ping < 0 || ping > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: ping out of acceptable range: " + ping);
|
||||||
|
|
||||||
|
if (userID < 0 || userID > 0xFFFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userID out of acceptable range: " + userID);
|
||||||
|
|
||||||
|
if (connectionType < 1 || connectionType > 6)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: connectionType out of acceptable range: " + connectionType);
|
||||||
|
|
||||||
|
this.gameID = gameID;
|
||||||
|
this.val1 = val1;
|
||||||
|
this.userName = userName; // check userName length?
|
||||||
|
this.ping = ping;
|
||||||
|
this.userID = userID;
|
||||||
|
this.connectionType = connectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public int getGameID()
|
||||||
|
{
|
||||||
|
return gameID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVal1()
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPing()
|
||||||
|
{
|
||||||
|
return ping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserID()
|
||||||
|
{
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getConnectionType()
|
||||||
|
{
|
||||||
|
return connectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String toString();
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + 13);
|
||||||
|
return (userName.length() + 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
buffer.put((byte) 0x00);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, gameID);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, val1);
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
UnsignedUtil.putUnsignedInt(buffer, ping);
|
||||||
|
UnsignedUtil.putUnsignedShort(buffer, userID);
|
||||||
|
buffer.put(connectionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JoinGame parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 13)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
byte b = buffer.get();
|
||||||
|
|
||||||
|
if (b != 0x00)
|
||||||
|
throw new MessageFormatException("Invalid format: byte 0 = " + EmuUtil.byteToHex(b));
|
||||||
|
|
||||||
|
int gameID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
int val1 = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
|
||||||
|
|
||||||
|
if (buffer.remaining() < 7)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
|
||||||
|
long ping = UnsignedUtil.getUnsignedInt(buffer);
|
||||||
|
int userID = UnsignedUtil.getUnsignedShort(buffer);
|
||||||
|
byte connectionType = buffer.get();
|
||||||
|
|
||||||
|
if (userName.length() == 0 && ping == 0 && userID == 0xFFFF)
|
||||||
|
return new JoinGame_Request(messageNumber, gameID, connectionType);
|
||||||
|
else
|
||||||
|
return new JoinGame_Notification(messageNumber, gameID, val1, userName, ping, userID, connectionType);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class JoinGame_Notification extends JoinGame
|
||||||
|
{
|
||||||
|
public static final String DESC = "Join Game Notification";
|
||||||
|
|
||||||
|
public JoinGame_Notification(int messageNumber, int gameID, int val1, String userName, long ping, int userID, byte connectionType) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, gameID, val1, userName, ping, userID, connectionType);
|
||||||
|
|
||||||
|
if (userName.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userName.length() == 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[gameID=" + getGameID() + " val1=" + getVal1() + " userName=" + getUserName() + " ping=" + getPing() + " userID=" + getUserID() + " connectionType=" + getConnectionType() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class JoinGame_Request extends JoinGame
|
||||||
|
{
|
||||||
|
public static final String DESC = "Join Game Request";
|
||||||
|
|
||||||
|
public JoinGame_Request(int messageNumber, int gameID, byte connectionType) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, gameID, 0, "", 0, 0xFFFF, connectionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[gameID=" + getGameID() + " connectionType=" + getConnectionType() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.UnsignedUtil;
|
||||||
|
|
||||||
|
public class KeepAlive extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x09;
|
||||||
|
public static final String DESC = "KeepAlive";
|
||||||
|
|
||||||
|
private short val;
|
||||||
|
|
||||||
|
public KeepAlive(int messageNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
this(messageNumber, (short) 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeepAlive(int messageNumber, short val) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (val < 0 || val > 0xFF)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: val out of acceptable range: " + val);
|
||||||
|
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getVal()
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[val=" + val + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
UnsignedUtil.putUnsignedByte(buffer, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeepAlive parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 1)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
return new KeepAlive(messageNumber, UnsignedUtil.getUnsignedByte(buffer));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.*;
|
||||||
|
import org.emulinker.util.EmuUtil;
|
||||||
|
|
||||||
|
public abstract class PlayerDrop extends V086Message
|
||||||
|
{
|
||||||
|
public static final byte ID = 0x14;
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
private byte playerNumber;
|
||||||
|
|
||||||
|
public PlayerDrop(int messageNumber, String userName, byte playerNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber);
|
||||||
|
|
||||||
|
if (playerNumber < 0 || playerNumber > 255)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: playerNumber out of acceptable range: " + playerNumber);
|
||||||
|
|
||||||
|
this.userName = userName;
|
||||||
|
this.playerNumber = playerNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getID()
|
||||||
|
{
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getDescription();
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getPlayerNumber()
|
||||||
|
{
|
||||||
|
return playerNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + userName + " playerNumber=" + playerNumber + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBodyLength()
|
||||||
|
{
|
||||||
|
//return (charset.encode(userName).remaining() + 2);
|
||||||
|
return (userName.length() + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBodyTo(ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
EmuUtil.writeString(buffer, userName, 0x00, charset);
|
||||||
|
buffer.put(playerNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerDrop parse(int messageNumber, ByteBuffer buffer) throws ParseException, MessageFormatException
|
||||||
|
{
|
||||||
|
if (buffer.remaining() < 2)
|
||||||
|
throw new ParseException("Failed byte count validation!");
|
||||||
|
|
||||||
|
String userName = EmuUtil.readString(buffer, 0x00, charset);
|
||||||
|
byte playerNumber = buffer.get();
|
||||||
|
|
||||||
|
if (userName.length() == 0 && playerNumber == 0)
|
||||||
|
return new PlayerDrop_Request(messageNumber);
|
||||||
|
else
|
||||||
|
return new PlayerDrop_Notification(messageNumber, userName, playerNumber);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class PlayerDrop_Notification extends PlayerDrop
|
||||||
|
{
|
||||||
|
public static final String DESC = "Player Drop Notification";
|
||||||
|
|
||||||
|
public PlayerDrop_Notification(int messageNumber, String userName, byte playerNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, userName, playerNumber);
|
||||||
|
|
||||||
|
if (userName.length() == 0)
|
||||||
|
throw new MessageFormatException("Invalid " + getDescription() + " format: userName.length == 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString() + "[userName=" + getUserName() + " playerNumber=" + getPlayerNumber() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.emulinker.kaillera.controller.v086.protocol;
|
||||||
|
|
||||||
|
import org.emulinker.kaillera.controller.messaging.MessageFormatException;
|
||||||
|
|
||||||
|
public class PlayerDrop_Request extends PlayerDrop
|
||||||
|
{
|
||||||
|
public static final String DESC = "Player Drop Request";
|
||||||
|
|
||||||
|
public PlayerDrop_Request(int messageNumber) throws MessageFormatException
|
||||||
|
{
|
||||||
|
super(messageNumber, "", (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getInfoString();
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user