Initial commit

This commit is contained in:
Jgunishka 2019-08-21 20:06:04 +03:00
commit e55d0cfd5e
212 changed files with 228673 additions and 0 deletions

2
.checkstyle Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.0.0"/>

25
.classpath Normal file
View 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
View File

@ -0,0 +1,2 @@
build
.settings

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

23
.gitignore vendored Normal file
View 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
View 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>

View 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

View 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
View 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
View 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
View 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,*

View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
emuadmin: playgame

43
doc/master_analysis.txt Normal file
View 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

File diff suppressed because one or more lines are too long

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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
doc/screenshot2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

246
eclipse_code_formatter.xml Normal file
View 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
View 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
View File

@ -0,0 +1,8 @@
ip:/127.0.0.1
s:3
n:SupraFast
ip:/127.0.0.1
s:3
n:SupraFast

View File

@ -0,0 +1,9 @@
package org.emulinker.kaillera.access;
public class AccessException extends Exception
{
public AccessException(String message)
{
super(message);
}
}

View 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);
}

View 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;
}
}
}

View 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;
}
}
}
*/

View File

@ -0,0 +1,8 @@
package org.emulinker.kaillera.admin;
import org.picocontainer.Startable;
public interface AdminServer extends Startable
{
}

View 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);
}
}
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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));
}
}

View File

@ -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)));
}
}

View File

@ -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!");
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View 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();
}
}
}
}

View 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);
}
}
}

View File

@ -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) {}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
//}
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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);
//}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View 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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
}

View File

@ -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() + "]";
}
}

View File

@ -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() + "]";
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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() + "]";
}
}

View File

@ -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() + "]";
}
}

View File

@ -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);
}
}

View File

@ -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() + "]";
}
}

View File

@ -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() + "]";
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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() + "]";
}
}

View File

@ -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() + "]";
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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() + "]";
}
}

View File

@ -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