Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,458 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
The Vilya library
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The Vilya library provides various facilities for making networked multiplayer
|
||||||
|
games. It's various packages include:
|
||||||
|
|
||||||
|
* whirled - builds on the crowd framework and defines a scene graph with
|
||||||
|
portals to move between scenes and provides hooks for distributing and
|
||||||
|
updating scene data (for example isometric rendering information) over
|
||||||
|
the network
|
||||||
|
* parlor - builds upon the crowd framework to create the notion of a
|
||||||
|
game with players and provides tools for making turn based games
|
||||||
|
* puzzle - builds on the parlor and media frameworks to provide tools
|
||||||
|
for implementing puzzle games in a networked environment
|
||||||
|
* micasa - builds on the parlor framework to provide lobbies and
|
||||||
|
matchmaking for multiplayer games
|
||||||
|
|
||||||
|
Documentation is somewhat sparse at the moment, but inspection of the code in
|
||||||
|
the tests/ directory shows examples of use of many features of the library.
|
||||||
|
|
||||||
|
Building
|
||||||
|
--------
|
||||||
|
|
||||||
|
Building the library is very simple. First ensure that the necessary third
|
||||||
|
party jar files are available in the lib/ directory. See lib/README for a list
|
||||||
|
of the necessary third party jar files and how to get them.
|
||||||
|
|
||||||
|
The library is built using Ant, a modern build tool written in and for Java. If
|
||||||
|
you aren't already using Ant for other projects, it can be found here:
|
||||||
|
|
||||||
|
http://ant.apache.org/
|
||||||
|
|
||||||
|
Invoke ant with any of the following targets:
|
||||||
|
|
||||||
|
all: builds the distribution files and javadoc documentation
|
||||||
|
compile: builds only the class files (dist/classes)
|
||||||
|
javadoc: builds only the javadoc documentation (dist/docs)
|
||||||
|
dist: builds the distribution jar files (dist/*.jar)
|
||||||
|
|
||||||
|
Distribution
|
||||||
|
------------
|
||||||
|
|
||||||
|
The Vilya library is released under the LGPL. The most recent version of the
|
||||||
|
library is available here:
|
||||||
|
|
||||||
|
http://www.threerings.net/code/vilya/
|
||||||
|
|
||||||
|
Contribution
|
||||||
|
------------
|
||||||
|
|
||||||
|
Contributions to Vilya are welcome. Read-only access to the subversion
|
||||||
|
repository is available at:
|
||||||
|
|
||||||
|
svn://code.threerings.net/vilya/trunk
|
||||||
|
|
||||||
|
Patches can be mailed to Michael Bayne <mdb@threerings.net>.
|
||||||
|
|
||||||
|
Contact Information
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Vilya is actively developed by the scurvy dogs at Three Rings Design, Inc.
|
||||||
|
Contact Michael Bayne <mdb@threerings.net> with questions, comments and other
|
||||||
|
wordly endeavors.
|
||||||
|
|
||||||
|
$Id$
|
||||||
@@ -0,0 +1,294 @@
|
|||||||
|
<?xml version="1.0" standalone="yes"?>
|
||||||
|
<!-- build configuration -->
|
||||||
|
<project name="narya" default="compile" basedir=".">
|
||||||
|
|
||||||
|
<!-- import overriding properties -->
|
||||||
|
<property file="build.properties"/>
|
||||||
|
|
||||||
|
<!-- configuration parameters -->
|
||||||
|
<property name="app.name" value="narya"/>
|
||||||
|
<property name="deploy.dir" value="dist"/>
|
||||||
|
<property name="savedoc.dir" value="docs"/>
|
||||||
|
<property name="lib.version" value="1.0"/>
|
||||||
|
|
||||||
|
<!-- derived properties -->
|
||||||
|
<property name="javadoc.home" value="${deploy.dir}/docs"/>
|
||||||
|
<property name="classes.dir" value="${deploy.dir}/classes"/>
|
||||||
|
|
||||||
|
<!-- declare our classpath business -->
|
||||||
|
<path id="classpath">
|
||||||
|
<pathelement location="${classes.dir}"/>
|
||||||
|
<fileset dir="lib" includes="**/*.jar"/>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<!-- generates additional methods for distributed object classes -->
|
||||||
|
<target name="gendobj" depends="prepare">
|
||||||
|
<taskdef name="dobj" classpathref="classpath"
|
||||||
|
classname="com.threerings.presents.tools.GenDObjectTask"/>
|
||||||
|
<!-- make sure the dobject class files are all compiled -->
|
||||||
|
<javac srcdir="src/java" destdir="${classes.dir}"
|
||||||
|
debug="on" optimize="${build.optimize}" deprecation="on"
|
||||||
|
source="1.5" target="1.5">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<include name="**/*Object.java"/>
|
||||||
|
</javac>
|
||||||
|
<!-- now generate the associated files -->
|
||||||
|
<dobj classpathref="classpath">
|
||||||
|
<fileset dir="src/java" includes="**/*Object.java"/>
|
||||||
|
</dobj>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- generates marshaller and dispatcher classes for all invocation -->
|
||||||
|
<!-- service declarations -->
|
||||||
|
<target name="genservice">
|
||||||
|
<taskdef name="service" classpathref="classpath"
|
||||||
|
classname="com.threerings.presents.tools.GenServiceTask"/>
|
||||||
|
<!-- make sure the service class files are all compiled -->
|
||||||
|
<javac srcdir="src/java" destdir="${classes.dir}"
|
||||||
|
debug="on" optimize="${build.optimize}" deprecation="on"
|
||||||
|
source="1.5" target="1.5">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<include name="**/*Service.java"/>
|
||||||
|
<exclude name="**/InvocationService.java"/>
|
||||||
|
</javac>
|
||||||
|
<!-- now generate the associated files -->
|
||||||
|
<service header="lib/SOURCE_HEADER" classpathref="classpath">
|
||||||
|
<fileset dir="src/java" includes="**/*Service.java"
|
||||||
|
excludes="**/InvocationService.java"/>
|
||||||
|
<providerless service="SimulatorService"/>
|
||||||
|
<providerless service="ParlorService"/>
|
||||||
|
<providerless service="SpotService"/>
|
||||||
|
<providerless service="ZoneService"/>
|
||||||
|
<providerless service="SceneService"/>
|
||||||
|
</service>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- generates sender and decoder classes for all invocation -->
|
||||||
|
<!-- receiver declarations -->
|
||||||
|
<target name="genreceiver">
|
||||||
|
<taskdef name="receiver" classpathref="classpath"
|
||||||
|
classname="com.threerings.presents.tools.GenReceiverTask"/>
|
||||||
|
<!-- make sure the receiver class files are all compiled -->
|
||||||
|
<javac srcdir="src/java" destdir="${classes.dir}"
|
||||||
|
debug="on" optimize="${build.optimize}" deprecation="on"
|
||||||
|
source="1.5" target="1.5">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<include name="**/*Receiver.java"/>
|
||||||
|
<exclude name="**/InvocationReceiver.java"/>
|
||||||
|
</javac>
|
||||||
|
<!-- now generate the associated files -->
|
||||||
|
<receiver header="lib/SOURCE_HEADER" classpathref="classpath">
|
||||||
|
<fileset dir="src/java" includes="**/*Receiver.java"
|
||||||
|
excludes="**/InvocationReceiver.java"/>
|
||||||
|
</receiver>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- checks the availability of certain libraries -->
|
||||||
|
<target name="check-available">
|
||||||
|
<available property="lwjgl.present"
|
||||||
|
classname="org.lwjgl.LWJGLException" classpathref="classpath"/>
|
||||||
|
<available property="jme.present"
|
||||||
|
classname="com.jme.scene.Node" classpathref="classpath"/>
|
||||||
|
<available property="jme-bui.present"
|
||||||
|
classname="com.jmex.bui.BWindow" classpathref="classpath"/>
|
||||||
|
<available property="jme-sound.present"
|
||||||
|
classname="com.jmex.sound.openAL.SoundSystem" classpathref="classpath"/>
|
||||||
|
<condition property="build.jme">
|
||||||
|
<and>
|
||||||
|
<isset property="jme.present"/>
|
||||||
|
<isset property="jme-bui.present"/>
|
||||||
|
</and>
|
||||||
|
</condition>
|
||||||
|
<condition property="build.openal">
|
||||||
|
<and>
|
||||||
|
<isset property="lwjgl.present"/>
|
||||||
|
<isset property="jme-sound.present"/>
|
||||||
|
</and>
|
||||||
|
</condition>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- prepares the application directories -->
|
||||||
|
<target name="prepare">
|
||||||
|
<mkdir dir="${deploy.dir}"/>
|
||||||
|
<mkdir dir="${classes.dir}"/>
|
||||||
|
<mkdir dir="${classes.dir}/rsrc"/>
|
||||||
|
<mkdir dir="${javadoc.home}"/>
|
||||||
|
<copy todir="${classes.dir}">
|
||||||
|
<fileset dir="src/java" includes="**/*.properties"/>
|
||||||
|
<fileset dir="src/java" includes="**/*.tmpl"/>
|
||||||
|
</copy>
|
||||||
|
<copy todir="${classes.dir}/rsrc">
|
||||||
|
<fileset dir="rsrc" includes="**/*" excludes="**/bundles/**"/>
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- cleans out the installed application -->
|
||||||
|
<target name="clean">
|
||||||
|
<delete dir="${deploy.dir}"/>
|
||||||
|
<ant dir="tests" target="clean"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- build the java class files -->
|
||||||
|
<target name="compile" depends="check-available,prepare">
|
||||||
|
<javac srcdir="src/java" destdir="${classes.dir}"
|
||||||
|
debug="on" optimize="{$build.optimize}" deprecation="on"
|
||||||
|
source="1.5" target="1.5">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<exclude name="com/threerings/jme/**" unless="build.jme"/>
|
||||||
|
<exclude name="com/threerings/openal/**" unless="build.openal"/>
|
||||||
|
<exclude name="**/OggPlayer.java"/>
|
||||||
|
<exclude name="**/ModPlayer.java"/>
|
||||||
|
<exclude name="**/MidiPlayer.java"/>
|
||||||
|
<exclude name="**/Mp3Player.java"/>
|
||||||
|
<!--<compilerarg value="-Xlint:unchecked"/>-->
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- build the javadoc documentation -->
|
||||||
|
<target name="javadoc" depends="prepare">
|
||||||
|
<javadoc sourcepath="src/java" packagenames="com.threerings.*"
|
||||||
|
destdir="${javadoc.home}" stylesheetfile="docs/stylesheet.css"
|
||||||
|
additionalparam="-breakiterator"
|
||||||
|
link="http://www.threerings.net/code/narya/narya/docs/api">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<link href="http://java.sun.com/j2se/1.5/docs/api/"/>
|
||||||
|
<!-- ant documentation is not available online, sorry kids -->
|
||||||
|
<link href="file:///usr/share/doc/ant-doc/javadocs"/>
|
||||||
|
<link href="http://samskivert.com/code/samskivert/samskivert/docs/api"/>
|
||||||
|
<link href="http://www.jmonkeyengine.com/doc"/>
|
||||||
|
</javadoc>
|
||||||
|
<copy todir="${javadoc.home}">
|
||||||
|
<fileset dir="src/java" includes="**/*.png"/>
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- builds the javadocs and stuffs them in a directory where they won't
|
||||||
|
be blown away when we do "clean" next time -->
|
||||||
|
<target name="savedoc" depends="javadoc">
|
||||||
|
<delete dir="${savedoc.dir}/api"/>
|
||||||
|
<copy todir="${savedoc.dir}/api">
|
||||||
|
<fileset dir="${javadoc.home}" includes="**/*"/>
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- builds the various tests -->
|
||||||
|
<target name="tests">
|
||||||
|
<ant dir="tests" target="compile"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- a target for rebuilding everything -->
|
||||||
|
<target name="all" depends="clean,prepare,compile,javadoc,tests,dist"/>
|
||||||
|
|
||||||
|
<!-- builds our distribution files (war and jar) -->
|
||||||
|
<target name="dist" depends="prepare,compile,tests">
|
||||||
|
<!-- build our various jar files -->
|
||||||
|
<jar destfile="${deploy.dir}/${app.name}-parlor.jar">
|
||||||
|
<fileset dir="${classes.dir}" includes="com/threerings/parlor/**"/>
|
||||||
|
</jar>
|
||||||
|
<jar destfile="${deploy.dir}/${app.name}-puzzle.jar">
|
||||||
|
<fileset dir="${classes.dir}" includes="com/threerings/puzzle/**"/>
|
||||||
|
</jar>
|
||||||
|
<jar destfile="${deploy.dir}/${app.name}-micasa.jar">
|
||||||
|
<fileset dir="${classes.dir}" includes="com/threerings/micasa/**"/>
|
||||||
|
<fileset dir="${classes.dir}" includes="rsrc/config/micasa/**"/>
|
||||||
|
</jar>
|
||||||
|
<jar destfile="${deploy.dir}/${app.name}-whirled.jar">
|
||||||
|
<fileset dir="${classes.dir}" includes="com/threerings/whirled/**"/>
|
||||||
|
<fileset dir="${classes.dir}" includes="rsrc/config/whirled/**"/>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- various bits used by the retroweaver tasks -->
|
||||||
|
<taskdef name="weave" classpathref="classpath"
|
||||||
|
classname="com.rc.retroweaver.ant.RetroWeaverTask"/>
|
||||||
|
<property name="inpre" value="${deploy.dir}/${app.name}"/>
|
||||||
|
<property name="outpre" value="${deploy.dir}/retro/${app.name}"/>
|
||||||
|
|
||||||
|
<!-- a helper task for 'retro' -->
|
||||||
|
<target name="vweave">
|
||||||
|
<path id="retrocp">
|
||||||
|
<pathelement location="/usr/local/jdk1.4/jre/lib/rt.jar"/>
|
||||||
|
<fileset dir="lib" includes="**/*.jar"/>
|
||||||
|
<fileset dir="${deploy.dir}/retro" includes="*.jar"/>
|
||||||
|
</path>
|
||||||
|
<weave inputjar="${inpre}-${which}.jar" outputjar="${outpre}-${which}.jar"
|
||||||
|
failonerror="true">
|
||||||
|
<classpath refid="retrocp"/>
|
||||||
|
</weave>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- converts our 1.5 code to a 1.4 compatible format -->
|
||||||
|
<target name="retro" depends="dist">
|
||||||
|
<mkdir dir="${deploy.dir}/retro"/>
|
||||||
|
|
||||||
|
<!-- we weave everything a first time without verification so that -->
|
||||||
|
<!-- interdependencies will resolve the second time -->
|
||||||
|
<weave inputjar="${inpre}-micasa.jar" outputjar="${outpre}-micasa.jar"/>
|
||||||
|
<weave inputjar="${inpre}-parlor.jar" outputjar="${outpre}-parlor.jar"/>
|
||||||
|
<weave inputjar="${inpre}-puzzle.jar" outputjar="${outpre}-puzzle.jar"/>
|
||||||
|
<weave inputjar="${inpre}-stage.jar" outputjar="${outpre}-stage.jar"/>
|
||||||
|
<weave inputjar="${inpre}-whirled.jar" outputjar="${outpre}-whirled.jar"/>
|
||||||
|
|
||||||
|
<!-- now weave again with the verifier to check for unweavable 1.5isms -->
|
||||||
|
<antcall target="vweave"><param name="which" value="micasa"/></antcall>
|
||||||
|
<antcall target="vweave"><param name="which" value="parlor"/></antcall>
|
||||||
|
<antcall target="vweave"><param name="which" value="puzzle"/></antcall>
|
||||||
|
<antcall target="vweave"><param name="which" value="stage"/></antcall>
|
||||||
|
<antcall target="vweave"><param name="which" value="whirled"/></antcall>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- generate a class hierarchy diagram -->
|
||||||
|
<target name="hierviz" depends="prepare,compile">
|
||||||
|
<taskdef name="viztool" classname="com.samskivert.viztool.DriverTask"/>
|
||||||
|
<viztool visualizer="com.samskivert.viztool.hierarchy.HierarchyVisualizer"
|
||||||
|
pkgroot="com.threerings.miso" classes="com.threerings.miso.*"
|
||||||
|
output="hierviz.ps">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
</viztool>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- generate a class hierarchy diagram -->
|
||||||
|
<target name="sumgen" depends="prepare,compile">
|
||||||
|
<taskdef name="viztool" classname="com.samskivert.viztool.DriverTask"/>
|
||||||
|
<viztool visualizer="com.samskivert.viztool.summary.SummaryVisualizer"
|
||||||
|
pkgroot="com.threerings.miso"
|
||||||
|
classes="com.threerings.miso.*Scene.*"
|
||||||
|
output="summary.ps">
|
||||||
|
<classpath refid="base.classpath"/>
|
||||||
|
</viztool>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- creates a tarball and zipfile for source distribution -->
|
||||||
|
<target name="distrib">
|
||||||
|
<echo message="You may want to stop and run 'ant savedoc' first."/>
|
||||||
|
<echo message="Building ${lib.version} tar.gz distribution..."/>
|
||||||
|
<tar destfile="narya-${lib.version}.tar.gz" compression="gzip">
|
||||||
|
<tarfileset dir=".." mode="0775" dirmode="0775">
|
||||||
|
<include name="narya/bin/**"/>
|
||||||
|
<include name="narya/tests/bin/**"/>
|
||||||
|
<exclude name="**/CVS"/>
|
||||||
|
</tarfileset>
|
||||||
|
<tarfileset dir=".." mode="0664" dirmode="0775">
|
||||||
|
<include name="narya/**"/>
|
||||||
|
<exclude name="**/CVS"/>
|
||||||
|
<exclude name="narya/bin/**"/>
|
||||||
|
<exclude name="narya/tests/bin/**"/>
|
||||||
|
<exclude name="narya/tests/dist/**"/>
|
||||||
|
<exclude name="narya/dist/**"/>
|
||||||
|
<exclude name="narya/code/**"/>
|
||||||
|
<exclude name="narya/narya-*.*"/>
|
||||||
|
</tarfileset>
|
||||||
|
</tar>
|
||||||
|
<echo message="Building ${lib.version} zip distribution..."/>
|
||||||
|
<zip destfile="narya-${lib.version}.zip">
|
||||||
|
<fileset dir="..">
|
||||||
|
<include name="narya/**"/>
|
||||||
|
<exclude name="**/CVS"/>
|
||||||
|
<exclude name="narya/dist/**"/>
|
||||||
|
<exclude name="narya/code/**"/>
|
||||||
|
<exclude name="narya/narya-*.*"/>
|
||||||
|
</fileset>
|
||||||
|
</zip>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* Javadoc style sheet */
|
||||||
|
|
||||||
|
/* Page background color */
|
||||||
|
body {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: Courier New, monospace
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: Courier New, monospace
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings */
|
||||||
|
h1 { font-size: 145% }
|
||||||
|
|
||||||
|
/* Table colors */
|
||||||
|
.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
|
||||||
|
.TableSubHeadingColor { background: #EEEEFF } /* Light mauve */
|
||||||
|
.TableRowColor { background: #FFFFFF } /* White */
|
||||||
|
|
||||||
|
/* Font used in left-hand frame lists */
|
||||||
|
.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif }
|
||||||
|
.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif }
|
||||||
|
.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif }
|
||||||
|
|
||||||
|
/* Navigation bar fonts and colors */
|
||||||
|
.NavBarCell1 { background-color:#EEEEFF;} /* Light mauve */
|
||||||
|
.NavBarCell1Rev { background-color:#00008B;} /* Dark Blue */
|
||||||
|
.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}
|
||||||
|
.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}
|
||||||
|
|
||||||
|
.NavBarCell2 {
|
||||||
|
font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;
|
||||||
|
}
|
||||||
|
.NavBarCell3 {
|
||||||
|
font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example {
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
border: 1px solid black;
|
||||||
|
background-color: #FFFF99
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
ant.jar
|
||||||
|
commons-beanutils.jar
|
||||||
|
commons-collections.jar
|
||||||
|
commons-digester.jar
|
||||||
|
commons-io.jar
|
||||||
|
commons-lang.jar
|
||||||
|
commons-logging.jar
|
||||||
|
jme-awt.jar
|
||||||
|
jme-bui.jar
|
||||||
|
jme-effects.jar
|
||||||
|
jme.jar
|
||||||
|
jme-model.jar
|
||||||
|
jme-sound.jar
|
||||||
|
junit-3.7.jar
|
||||||
|
lwjgl.jar
|
||||||
|
lwjgl_util.jar
|
||||||
|
narya-base.jar
|
||||||
|
narya-distrib.jar
|
||||||
|
narya-tests.jar
|
||||||
|
nenya-cast.jar
|
||||||
|
nenya-media.jar
|
||||||
|
nenya-miso.jar
|
||||||
|
nenya-rsrc.jar
|
||||||
|
retroweaver-all-1.2.2.jar
|
||||||
|
samskivert.jar
|
||||||
|
velocity-1.5-dev.jar
|
||||||
|
xml-writer.jar
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
Required external libraries
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The Narya code requires the following external Java libraries (JAR files)
|
||||||
|
to be placed (or symlinked) here in the lib/ directory or in the shared
|
||||||
|
library directory specified in the build.xml file (java.libraries).
|
||||||
|
|
||||||
|
* The samskivert library:
|
||||||
|
http://samskivert.com/code/samskivert/
|
||||||
|
|
||||||
|
* Apache Commons libraries: collections, digester, io, and lang
|
||||||
|
http://jakarta.apache.org/commons/
|
||||||
|
|
||||||
|
* Megginson Technologies' XMLWriter 0.2 library:
|
||||||
|
http://www.megginson.com/Software/xml-writer-0.2.zip
|
||||||
|
|
||||||
|
Once the jar files are in place (regardless of what they are named), the
|
||||||
|
build system will automatically include them in the compile-time
|
||||||
|
classpath.
|
||||||
|
|
||||||
|
--
|
||||||
|
$Id: README 3105 2004-08-27 18:38:55Z mdb $
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Vilya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/vilya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// $Id: Log.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A placeholder class that contains a reference to the log object used by
|
||||||
|
* the MiCasa package. This is a useful pattern to use when using the
|
||||||
|
* samskivert logging facilities. One creates a top-level class like this
|
||||||
|
* one that instantiates a log object with an name that identifies log
|
||||||
|
* messages from that package and then provides static methods that
|
||||||
|
* generate log messages using that instance. Then, classes in that
|
||||||
|
* package need only import the log wrapper class and can easily use it to
|
||||||
|
* generate log messages. For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* import com.threerings.micasa.Log;
|
||||||
|
* // ...
|
||||||
|
* Log.warning("All hell is breaking loose!");
|
||||||
|
* // ...
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see com.samskivert.util.Log
|
||||||
|
*/
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
/** The static log instance configured for use by this package. */
|
||||||
|
public static com.samskivert.util.Log log =
|
||||||
|
new com.samskivert.util.Log("micasa");
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void debug (String message)
|
||||||
|
{
|
||||||
|
log.debug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void info (String message)
|
||||||
|
{
|
||||||
|
log.info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void warning (String message)
|
||||||
|
{
|
||||||
|
log.warning(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void logStackTrace (Throwable t)
|
||||||
|
{
|
||||||
|
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,336 @@
|
|||||||
|
//
|
||||||
|
// $Id: ChatPanel.java 3741 2005-10-25 11:13:51Z elizabeth $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
|
|
||||||
|
import javax.swing.event.AncestorEvent;
|
||||||
|
import javax.swing.event.AncestorListener;
|
||||||
|
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.Style;
|
||||||
|
import javax.swing.text.StyleConstants;
|
||||||
|
import javax.swing.text.StyleContext;
|
||||||
|
|
||||||
|
import com.samskivert.swing.GroupLayout;
|
||||||
|
import com.samskivert.swing.HGroupLayout;
|
||||||
|
import com.samskivert.swing.VGroupLayout;
|
||||||
|
import com.samskivert.swing.event.AncestorAdapter;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.crowd.chat.client.ChatDirector;
|
||||||
|
import com.threerings.crowd.chat.client.ChatDisplay;
|
||||||
|
import com.threerings.crowd.chat.data.ChatCodes;
|
||||||
|
import com.threerings.crowd.chat.data.ChatMessage;
|
||||||
|
import com.threerings.crowd.chat.data.SystemMessage;
|
||||||
|
import com.threerings.crowd.chat.data.UserMessage;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.OccupantObserver;
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
import com.threerings.crowd.data.OccupantInfo;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.crowd.util.CrowdContext;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
public class ChatPanel
|
||||||
|
extends JPanel
|
||||||
|
implements ActionListener, ChatDisplay, OccupantObserver, PlaceView
|
||||||
|
{
|
||||||
|
public ChatPanel (CrowdContext ctx)
|
||||||
|
{
|
||||||
|
// keep this around for later
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// create our chat director and register ourselves with it
|
||||||
|
_chatdtr = new ChatDirector(_ctx, null, null);
|
||||||
|
// XXX - the line above royally borks things because it sends
|
||||||
|
// null, null downstream.
|
||||||
|
_chatdtr.addChatDisplay(this);
|
||||||
|
|
||||||
|
// register as an occupant observer
|
||||||
|
_ctx.getOccupantDirector().addOccupantObserver(this);
|
||||||
|
|
||||||
|
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||||
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
|
setLayout(gl);
|
||||||
|
|
||||||
|
// create our scrolling chat text display
|
||||||
|
_text = new JTextPane();
|
||||||
|
_text.setEditable(false);
|
||||||
|
add(new JScrollPane(_text));
|
||||||
|
|
||||||
|
// create our styles and add those to the text pane
|
||||||
|
createStyles(_text);
|
||||||
|
|
||||||
|
// add a label for the text entry stuff
|
||||||
|
add(new JLabel("Type here to chat:"), GroupLayout.FIXED);
|
||||||
|
|
||||||
|
// create a horizontal group for the text entry bar
|
||||||
|
gl = new HGroupLayout(GroupLayout.STRETCH);
|
||||||
|
JPanel epanel = new JPanel(gl);
|
||||||
|
epanel.add(_entry = new JTextField());
|
||||||
|
_entry.setActionCommand("send");
|
||||||
|
_entry.addActionListener(this);
|
||||||
|
_entry.setEnabled(false);
|
||||||
|
|
||||||
|
_send = new JButton("Send");
|
||||||
|
_send.setEnabled(false);
|
||||||
|
_send.addActionListener(this);
|
||||||
|
_send.setActionCommand("send");
|
||||||
|
epanel.add(_send, GroupLayout.FIXED);
|
||||||
|
add(epanel, GroupLayout.FIXED);
|
||||||
|
|
||||||
|
// listen to ancestor events to request focus when added
|
||||||
|
addAncestorListener(new AncestorAdapter() {
|
||||||
|
public void ancestorAdded (AncestorEvent e) {
|
||||||
|
if (_focus) {
|
||||||
|
_entry.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For applications where the chat box has extremely limited space,
|
||||||
|
* the send button can be removed to leave more space for the text
|
||||||
|
* input box.
|
||||||
|
*/
|
||||||
|
public void removeSendButton ()
|
||||||
|
{
|
||||||
|
if (_send.isVisible()) {
|
||||||
|
// _send.getParent().remove(_send);
|
||||||
|
_send.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the chat box text entry field requests the keyboard
|
||||||
|
* focus when the panel receives {@link
|
||||||
|
* AncestorListener#ancestorAdded} or {@link PlaceView#willEnterPlace}
|
||||||
|
* events.
|
||||||
|
*/
|
||||||
|
public void setRequestFocus (boolean focus)
|
||||||
|
{
|
||||||
|
_focus = focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createStyles (JTextPane text)
|
||||||
|
{
|
||||||
|
StyleContext sctx = StyleContext.getDefaultStyleContext();
|
||||||
|
Style defstyle = sctx.getStyle(StyleContext.DEFAULT_STYLE);
|
||||||
|
|
||||||
|
_nameStyle = text.addStyle("name", defstyle);
|
||||||
|
StyleConstants.setForeground(_nameStyle, Color.blue);
|
||||||
|
|
||||||
|
_msgStyle = text.addStyle("msg", defstyle);
|
||||||
|
StyleConstants.setForeground(_msgStyle, Color.black);
|
||||||
|
|
||||||
|
_errStyle = text.addStyle("err", defstyle);
|
||||||
|
StyleConstants.setForeground(_errStyle, Color.red);
|
||||||
|
|
||||||
|
_noticeStyle = text.addStyle("notice", defstyle);
|
||||||
|
StyleConstants.setForeground(_noticeStyle, Color.magenta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void actionPerformed (ActionEvent e)
|
||||||
|
{
|
||||||
|
String cmd = e.getActionCommand();
|
||||||
|
if (cmd.equals("send")) {
|
||||||
|
sendText();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
System.out.println("Unknown action event: " + cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantEntered (OccupantInfo info)
|
||||||
|
{
|
||||||
|
displayOccupantMessage("*** " + info.username + " entered.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantLeft (OccupantInfo info)
|
||||||
|
{
|
||||||
|
displayOccupantMessage("*** " + info.username + " left.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantUpdated (OccupantInfo oinfo, OccupantInfo info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void displayOccupantMessage (String message)
|
||||||
|
{
|
||||||
|
append(message + "\n", _noticeStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendText ()
|
||||||
|
{
|
||||||
|
String text = _entry.getText();
|
||||||
|
|
||||||
|
// if the message to send begins with /tell then parse it and
|
||||||
|
// generate a tell request rather than a speak request
|
||||||
|
if (text.startsWith("/tell")) {
|
||||||
|
StringTokenizer tok = new StringTokenizer(text);
|
||||||
|
// there should be at least three tokens: '/tell target word'
|
||||||
|
if (tok.countTokens() < 3) {
|
||||||
|
displayError("Usage: /tell username message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip the /tell and grab the username
|
||||||
|
tok.nextToken();
|
||||||
|
String username = tok.nextToken();
|
||||||
|
|
||||||
|
// now strip off everything up to the username to get the
|
||||||
|
// message
|
||||||
|
int uidx = text.indexOf(username);
|
||||||
|
String message = text.substring(uidx + username.length()).trim();
|
||||||
|
|
||||||
|
// request to send this text as a tell message
|
||||||
|
_chatdtr.requestTell(new Name(username), message, null);
|
||||||
|
|
||||||
|
} else if (text.startsWith("/clear")) {
|
||||||
|
// clear the chat box
|
||||||
|
_chatdtr.clearDisplays();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// request to send this text as a chat message
|
||||||
|
_chatdtr.requestSpeak(null, text, ChatCodes.DEFAULT_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out the input because we sent a request
|
||||||
|
_entry.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface ChatDisplay
|
||||||
|
public void clear ()
|
||||||
|
{
|
||||||
|
_text.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface ChatDisplay
|
||||||
|
public void displayMessage (ChatMessage message)
|
||||||
|
{
|
||||||
|
if (message instanceof UserMessage) {
|
||||||
|
UserMessage msg = (UserMessage) message;
|
||||||
|
if (msg.localtype == ChatCodes.USER_CHAT_TYPE) {
|
||||||
|
append("[" + msg.speaker + " whispers] ", _nameStyle);
|
||||||
|
append(msg.message + "\n", _msgStyle);
|
||||||
|
} else {
|
||||||
|
append("<" + msg.speaker + "> ", _nameStyle);
|
||||||
|
append(msg.message + "\n", _msgStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (message instanceof SystemMessage) {
|
||||||
|
append(message.message + "\n", _noticeStyle);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.warning("Received unknown message type [message=" +
|
||||||
|
message + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void displayError (String message)
|
||||||
|
{
|
||||||
|
append(message + "\n", _errStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the specified text in the specified style.
|
||||||
|
*/
|
||||||
|
protected void append (String text, Style style)
|
||||||
|
{
|
||||||
|
Document doc = _text.getDocument();
|
||||||
|
try {
|
||||||
|
doc.insertString(doc.getLength(), text, style);
|
||||||
|
} catch (BadLocationException ble) {
|
||||||
|
Log.warning("Unable to insert text!? [error=" + ble + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void willEnterPlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// enable our chat input elements since we're now somewhere that
|
||||||
|
// we can chat
|
||||||
|
_entry.setEnabled(true);
|
||||||
|
_send.setEnabled(true);
|
||||||
|
if (_focus) {
|
||||||
|
_entry.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void didLeavePlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// nothing doing
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Dimension getPreferredSize ()
|
||||||
|
{
|
||||||
|
Dimension size = super.getPreferredSize();
|
||||||
|
// always prefer a sensible but not overly large width. this also
|
||||||
|
// prevents us from inheriting a foolishly large preferred width
|
||||||
|
// from the JTextPane which sometimes decides it wants to be as
|
||||||
|
// wide as its widest line of text rather than wrap that line of
|
||||||
|
// text.
|
||||||
|
size.width = PREFERRED_WIDTH;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CrowdContext _ctx;
|
||||||
|
protected ChatDirector _chatdtr;
|
||||||
|
|
||||||
|
protected boolean _focus = true;
|
||||||
|
|
||||||
|
protected JComboBox _roombox;
|
||||||
|
protected JTextPane _text;
|
||||||
|
protected JButton _send;
|
||||||
|
protected JTextField _entry;
|
||||||
|
|
||||||
|
protected Style _nameStyle;
|
||||||
|
protected Style _msgStyle;
|
||||||
|
protected Style _errStyle;
|
||||||
|
protected Style _noticeStyle;
|
||||||
|
|
||||||
|
/** A width that isn't so skinny that the text is teeny. */
|
||||||
|
protected static final int PREFERRED_WIDTH = 200;
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
//
|
||||||
|
// $Id: ClientController.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.SessionObserver;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.data.MiCasaBootstrapData;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for top-level control of the client user interface.
|
||||||
|
*/
|
||||||
|
public class ClientController extends Controller
|
||||||
|
implements SessionObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new client controller. The controller will set everything
|
||||||
|
* up in preparation for logging on.
|
||||||
|
*/
|
||||||
|
public ClientController (MiCasaContext ctx, MiCasaFrame frame)
|
||||||
|
{
|
||||||
|
// we'll want to keep these around
|
||||||
|
_ctx = ctx;
|
||||||
|
_frame = frame;
|
||||||
|
|
||||||
|
// we want to know about logon/logoff
|
||||||
|
_ctx.getClient().addClientObserver(this);
|
||||||
|
|
||||||
|
// create the logon panel and display it
|
||||||
|
_logonPanel = new LogonPanel(_ctx);
|
||||||
|
_frame.setPanel(_logonPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean handleAction (ActionEvent action)
|
||||||
|
{
|
||||||
|
String cmd = action.getActionCommand();
|
||||||
|
|
||||||
|
if (cmd.equals("logoff")) {
|
||||||
|
// request that we logoff
|
||||||
|
_ctx.getClient().logoff(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info("Unhandled action: " + action);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogon (Client client)
|
||||||
|
{
|
||||||
|
Log.info("Client did logon [client=" + client + "].");
|
||||||
|
|
||||||
|
// keep the body object around for stuff
|
||||||
|
_body = (BodyObject)client.getClientObject();
|
||||||
|
|
||||||
|
// figure out where to go
|
||||||
|
int moveOid = -1;
|
||||||
|
|
||||||
|
// hacky hack
|
||||||
|
String jumpOidStr = null;
|
||||||
|
try {
|
||||||
|
jumpOidStr = System.getProperty("jumpoid");
|
||||||
|
} catch (SecurityException se) {
|
||||||
|
Log.info("Not checking for jumpOid as we're in an applet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jumpOidStr != null) {
|
||||||
|
try {
|
||||||
|
moveOid = Integer.parseInt(jumpOidStr);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
Log.warning("Invalid jump oid [oid=" + jumpOidStr +
|
||||||
|
", err=" + nfe + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (_body.location != -1) {
|
||||||
|
// if we were already in a location, go there
|
||||||
|
moveOid = _body.location;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise head to the default lobby to start things off
|
||||||
|
MiCasaBootstrapData data = (MiCasaBootstrapData)
|
||||||
|
client.getBootstrapData();
|
||||||
|
moveOid = data.defLobbyOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moveOid > 0) {
|
||||||
|
_ctx.getLocationDirector().moveTo(moveOid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientObjectDidChange (Client client)
|
||||||
|
{
|
||||||
|
// regrab our body object
|
||||||
|
_body = (BodyObject)client.getClientObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogoff (Client client)
|
||||||
|
{
|
||||||
|
Log.info("Client did logoff [client=" + client + "].");
|
||||||
|
|
||||||
|
// reinstate the logon panel
|
||||||
|
_frame.setPanel(_logonPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected MiCasaFrame _frame;
|
||||||
|
protected BodyObject _body;
|
||||||
|
|
||||||
|
// our panels
|
||||||
|
protected LogonPanel _logonPanel;
|
||||||
|
}
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
//
|
||||||
|
// $Id: LogonPanel.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPasswordField;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
|
||||||
|
import com.samskivert.swing.GroupLayout;
|
||||||
|
import com.samskivert.swing.HGroupLayout;
|
||||||
|
import com.samskivert.swing.VGroupLayout;
|
||||||
|
|
||||||
|
import com.threerings.util.MessageBundle;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.ClientObserver;
|
||||||
|
import com.threerings.presents.client.LogonException;
|
||||||
|
import com.threerings.presents.net.Credentials;
|
||||||
|
import com.threerings.presents.net.UsernamePasswordCreds;
|
||||||
|
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
public class LogonPanel extends JPanel
|
||||||
|
implements ActionListener, ClientObserver
|
||||||
|
{
|
||||||
|
public LogonPanel (MiCasaContext ctx)
|
||||||
|
{
|
||||||
|
// keep these around for later
|
||||||
|
_ctx = ctx;
|
||||||
|
_msgs = _ctx.getMessageManager().getBundle("micasa");
|
||||||
|
|
||||||
|
setLayout(new VGroupLayout());
|
||||||
|
|
||||||
|
// stick the logon components into a panel that will stretch them
|
||||||
|
// to a sensible width
|
||||||
|
JPanel box = new JPanel(
|
||||||
|
new VGroupLayout(VGroupLayout.NONE, VGroupLayout.STRETCH,
|
||||||
|
5, VGroupLayout.CENTER)) {
|
||||||
|
public Dimension getPreferredSize () {
|
||||||
|
Dimension psize = super.getPreferredSize();
|
||||||
|
psize.width = Math.max(psize.width, 300);
|
||||||
|
return psize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
add(box);
|
||||||
|
|
||||||
|
// try obtaining our title text from a system property
|
||||||
|
String tstr = null;
|
||||||
|
try {
|
||||||
|
tstr = System.getProperty("logon.title");
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
if (tstr == null) {
|
||||||
|
tstr = "Mi Casa!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a big fat label
|
||||||
|
JLabel title = new JLabel(tstr, JLabel.CENTER);
|
||||||
|
title.setFont(new Font("Helvetica", Font.BOLD, 24));
|
||||||
|
box.add(title);
|
||||||
|
|
||||||
|
// create the username bar
|
||||||
|
JPanel bar = new JPanel(new HGroupLayout(GroupLayout.STRETCH));
|
||||||
|
bar.add(new JLabel(_msgs.get("m.username")), GroupLayout.FIXED);
|
||||||
|
_username = new JTextField();
|
||||||
|
_username.setActionCommand("skipToPassword");
|
||||||
|
_username.addActionListener(this);
|
||||||
|
bar.add(_username);
|
||||||
|
box.add(bar);
|
||||||
|
|
||||||
|
// create the password bar
|
||||||
|
bar = new JPanel(new HGroupLayout(GroupLayout.STRETCH));
|
||||||
|
bar.add(new JLabel(_msgs.get("m.password")), GroupLayout.FIXED);
|
||||||
|
_password = new JPasswordField();
|
||||||
|
_password.setActionCommand("logon");
|
||||||
|
_password.addActionListener(this);
|
||||||
|
bar.add(_password);
|
||||||
|
box.add(bar);
|
||||||
|
|
||||||
|
// create the logon button bar
|
||||||
|
HGroupLayout gl = new HGroupLayout(GroupLayout.NONE);
|
||||||
|
gl.setJustification(GroupLayout.RIGHT);
|
||||||
|
bar = new JPanel(gl);
|
||||||
|
_logon = new JButton(_msgs.get("m.logon"));
|
||||||
|
_logon.setActionCommand("logon");
|
||||||
|
_logon.addActionListener(this);
|
||||||
|
bar.add(_logon);
|
||||||
|
box.add(bar);
|
||||||
|
|
||||||
|
box.add(new JLabel(_msgs.get("m.status")));
|
||||||
|
_status = new JTextArea() {
|
||||||
|
public Dimension getPreferredScrollableViewportSize ()
|
||||||
|
{
|
||||||
|
return new Dimension(10, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_status.setEditable(false);
|
||||||
|
JScrollPane scroller = new JScrollPane(_status);
|
||||||
|
box.add(scroller);
|
||||||
|
|
||||||
|
// we'll want to listen for logon failure
|
||||||
|
_ctx.getClient().addClientObserver(this);
|
||||||
|
|
||||||
|
// start with focus in the username field
|
||||||
|
_username.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed (ActionEvent e)
|
||||||
|
{
|
||||||
|
String cmd = e.getActionCommand();
|
||||||
|
if (cmd.equals("skipToPassword")) {
|
||||||
|
_password.requestFocusInWindow();
|
||||||
|
|
||||||
|
} else if (cmd.equals("logon")) {
|
||||||
|
logon();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
System.out.println("Unknown action event: " + cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void clientDidLogon (Client client)
|
||||||
|
{
|
||||||
|
_status.append(_msgs.get("m.logon_success") + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void clientDidLogoff (Client client)
|
||||||
|
{
|
||||||
|
_status.append(_msgs.get("m.logged_off") + "\n");
|
||||||
|
setLogonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void clientFailedToLogon (Client client, Exception cause)
|
||||||
|
{
|
||||||
|
String msg;
|
||||||
|
if (cause instanceof LogonException) {
|
||||||
|
msg = MessageBundle.compose("m.logon_failed", cause.getMessage());
|
||||||
|
} else {
|
||||||
|
msg = MessageBundle.tcompose("m.logon_failed", cause.getMessage());
|
||||||
|
}
|
||||||
|
_status.append(_msgs.xlate(msg) + "\n");
|
||||||
|
setLogonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void clientObjectDidChange (Client client)
|
||||||
|
{
|
||||||
|
// nothing we can do here...
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void clientConnectionFailed (Client client, Exception cause)
|
||||||
|
{
|
||||||
|
String msg = MessageBundle.tcompose("m.connection_failed",
|
||||||
|
cause.getMessage());
|
||||||
|
_status.append(_msgs.xlate(msg) + "\n");
|
||||||
|
setLogonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public boolean clientWillLogoff (Client client)
|
||||||
|
{
|
||||||
|
// no vetoing here
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logon ()
|
||||||
|
{
|
||||||
|
// disable further logon attempts until we hear back
|
||||||
|
setLogonEnabled(false);
|
||||||
|
|
||||||
|
Name username = new Name(_username.getText().trim());
|
||||||
|
String password = new String(_password.getPassword()).trim();
|
||||||
|
|
||||||
|
String server = _ctx.getClient().getHostname();
|
||||||
|
int port = _ctx.getClient().getPorts()[0];
|
||||||
|
String msg = MessageBundle.tcompose("m.logging_on",
|
||||||
|
server, String.valueOf(port));
|
||||||
|
_status.append(_msgs.xlate(msg) + "\n");
|
||||||
|
|
||||||
|
// configure the client with some credentials and logon
|
||||||
|
Credentials creds = new UsernamePasswordCreds(username, password);
|
||||||
|
Client client = _ctx.getClient();
|
||||||
|
client.setCredentials(creds);
|
||||||
|
client.logon();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setLogonEnabled (boolean enabled)
|
||||||
|
{
|
||||||
|
_username.setEnabled(enabled);
|
||||||
|
_password.setEnabled(enabled);
|
||||||
|
_logon.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected MessageBundle _msgs;
|
||||||
|
|
||||||
|
protected JTextField _username;
|
||||||
|
protected JPasswordField _password;
|
||||||
|
protected JButton _logon;
|
||||||
|
protected JTextArea _status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaApp.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.net.UsernamePasswordCreds;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The micasa app is the main point of entry for the MiCasa client
|
||||||
|
* application. It creates and initializes the myriad components of the
|
||||||
|
* client and sets all the proper wheels in motion.
|
||||||
|
*/
|
||||||
|
public class MiCasaApp
|
||||||
|
{
|
||||||
|
public void init ()
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// create a frame
|
||||||
|
_frame = new MiCasaFrame();
|
||||||
|
|
||||||
|
// create our client instance
|
||||||
|
String cclass = null;
|
||||||
|
try {
|
||||||
|
cclass = System.getProperty("client");
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// security manager in effect, no problem
|
||||||
|
}
|
||||||
|
if (cclass == null) {
|
||||||
|
cclass = MiCasaClient.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_client = (MiCasaClient)Class.forName(cclass).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to instantiate client class " +
|
||||||
|
"[cclass=" + cclass + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize our client instance
|
||||||
|
_client.init(_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run (String server, String username, String password)
|
||||||
|
{
|
||||||
|
// position everything and show the frame
|
||||||
|
_frame.setSize(800, 600);
|
||||||
|
SwingUtil.centerWindow(_frame);
|
||||||
|
_frame.setVisible(true);
|
||||||
|
|
||||||
|
Client client = _client.getContext().getClient();
|
||||||
|
|
||||||
|
Log.info("Using [server=" + server + ".");
|
||||||
|
client.setServer(server, Client.DEFAULT_SERVER_PORTS);
|
||||||
|
|
||||||
|
// configure the client with some credentials and logon
|
||||||
|
if (username != null && password != null) {
|
||||||
|
// create and set our credentials
|
||||||
|
client.setCredentials(
|
||||||
|
new UsernamePasswordCreds(new Name(username), password));
|
||||||
|
client.logon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
String server = "localhost";
|
||||||
|
if (args.length > 0) {
|
||||||
|
server = args[0];
|
||||||
|
}
|
||||||
|
String username = (args.length > 1) ? args[1] : null;
|
||||||
|
String password = (args.length > 2) ? args[2] : null;
|
||||||
|
|
||||||
|
MiCasaApp app = new MiCasaApp();
|
||||||
|
try {
|
||||||
|
// initialize the app
|
||||||
|
app.init();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Error initializing application.");
|
||||||
|
Log.logStackTrace(ioe);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and run it
|
||||||
|
app.run(server, username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaClient _client;
|
||||||
|
protected MiCasaFrame _frame;
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaApplet.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.applet.Applet;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.ClientAdapter;
|
||||||
|
import com.threerings.presents.net.UsernamePasswordCreds;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MiCasa applet is used to make MiCasa games available via the web
|
||||||
|
* browser.
|
||||||
|
*/
|
||||||
|
public class MiCasaApplet extends Applet
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the client instance and set things up.
|
||||||
|
*/
|
||||||
|
public void init ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// create a frame
|
||||||
|
_frame = new MiCasaFrame();
|
||||||
|
|
||||||
|
// create our client instance
|
||||||
|
_client = new MiCasaClient();
|
||||||
|
_client.init(_frame);
|
||||||
|
|
||||||
|
Name username = new Name(requireParameter("username"));
|
||||||
|
String authkey = requireParameter("authkey");
|
||||||
|
String server = getCodeBase().getHost();
|
||||||
|
|
||||||
|
Client client = _client.getContext().getClient();
|
||||||
|
|
||||||
|
// indicate which server to which we should connect
|
||||||
|
client.setServer(server, Client.DEFAULT_SERVER_PORTS);
|
||||||
|
|
||||||
|
// create and set our credentials
|
||||||
|
client.setCredentials(
|
||||||
|
new UsernamePasswordCreds(username, authkey));
|
||||||
|
|
||||||
|
// we want to hide the client frame when we logoff
|
||||||
|
client.addClientObserver(new ClientAdapter() {
|
||||||
|
public void clientDidLogoff (Client c)
|
||||||
|
{
|
||||||
|
_frame.setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Unable to create client.");
|
||||||
|
Log.logStackTrace(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String requireParameter (String name)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
String value = getParameter(name);
|
||||||
|
if (value == null) {
|
||||||
|
throw new IOException("Applet missing '" + name + "' parameter.");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the client frame and really get things going.
|
||||||
|
*/
|
||||||
|
public void start ()
|
||||||
|
{
|
||||||
|
if (_client != null) {
|
||||||
|
// show the frame
|
||||||
|
_frame.setSize(800, 600);
|
||||||
|
SwingUtil.centerWindow(_frame);
|
||||||
|
_frame.setVisible(true);
|
||||||
|
// and log on
|
||||||
|
_client.getContext().getClient().logon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log off and shut on down.
|
||||||
|
*/
|
||||||
|
public void stop ()
|
||||||
|
{
|
||||||
|
if (_client != null) {
|
||||||
|
// hide the frame and log off
|
||||||
|
_frame.setVisible(false);
|
||||||
|
Client client = _client.getContext().getClient();
|
||||||
|
if (client.isLoggedOn()) {
|
||||||
|
client.logoff(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaClient _client;
|
||||||
|
protected MiCasaFrame _frame;
|
||||||
|
}
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaClient.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.samskivert.util.Config;
|
||||||
|
import com.samskivert.util.RunQueue;
|
||||||
|
import com.threerings.util.MessageManager;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.dobj.DObjectManager;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.LocationDirector;
|
||||||
|
import com.threerings.crowd.client.OccupantDirector;
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
|
||||||
|
import com.threerings.crowd.chat.client.ChatDirector;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.ParlorDirector;
|
||||||
|
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MiCasa client takes care of instantiating all of the proper
|
||||||
|
* managers and loading up all of the necessary configuration and getting
|
||||||
|
* the client bootstrapped. It can be extended by games that require an
|
||||||
|
* extended context implementation.
|
||||||
|
*/
|
||||||
|
public class MiCasaClient
|
||||||
|
implements RunQueue
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes a new client and provides it with a frame in which to
|
||||||
|
* display everything.
|
||||||
|
*/
|
||||||
|
public void init (MiCasaFrame frame)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// create our context
|
||||||
|
_ctx = createContextImpl();
|
||||||
|
|
||||||
|
// create the directors/managers/etc. provided by the context
|
||||||
|
createContextServices();
|
||||||
|
|
||||||
|
// for test purposes, hardcode the server info
|
||||||
|
_client.setServer("localhost", Client.DEFAULT_SERVER_PORTS);
|
||||||
|
|
||||||
|
// keep this for later
|
||||||
|
_frame = frame;
|
||||||
|
|
||||||
|
// log off when they close the window
|
||||||
|
_frame.addWindowListener(new WindowAdapter() {
|
||||||
|
public void windowClosing (WindowEvent evt) {
|
||||||
|
// if we're logged on, log off
|
||||||
|
if (_client.isLoggedOn()) {
|
||||||
|
_client.logoff(true);
|
||||||
|
} else {
|
||||||
|
// otherwise get the heck out
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// create our client controller and stick it in the frame
|
||||||
|
_frame.setController(new ClientController(_ctx, _frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the context in effect for this client. This
|
||||||
|
* reference is valid for the lifetime of the application.
|
||||||
|
*/
|
||||||
|
public MiCasaContext getContext ()
|
||||||
|
{
|
||||||
|
return _ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link MiCasaContext} implementation that will be
|
||||||
|
* passed around to all of the client code. Derived classes may wish
|
||||||
|
* to override this and create some extended context implementation.
|
||||||
|
*/
|
||||||
|
protected MiCasaContext createContextImpl ()
|
||||||
|
{
|
||||||
|
return new MiCasaContextImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes the various services that are provided by
|
||||||
|
* the context. Derived classes that provide an extended context
|
||||||
|
* should override this method and create their own extended
|
||||||
|
* services. They should be sure to call
|
||||||
|
* <code>super.createContextServices</code>.
|
||||||
|
*/
|
||||||
|
protected void createContextServices ()
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// create the handles on our various services
|
||||||
|
_client = new Client(null, this);
|
||||||
|
|
||||||
|
// create our managers and directors
|
||||||
|
_locdir = new LocationDirector(_ctx);
|
||||||
|
_occdir = new OccupantDirector(_ctx);
|
||||||
|
_pardtr = new ParlorDirector(_ctx);
|
||||||
|
_msgmgr = new MessageManager(MESSAGE_MANAGER_PREFIX);
|
||||||
|
_chatdir = new ChatDirector(_ctx, _msgmgr, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface RunQueue
|
||||||
|
public void postRunnable (Runnable run)
|
||||||
|
{
|
||||||
|
// queue it on up on the awt thread
|
||||||
|
EventQueue.invokeLater(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface RunQueue
|
||||||
|
public boolean isDispatchThread ()
|
||||||
|
{
|
||||||
|
return EventQueue.isDispatchThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context implementation. This provides access to all of the
|
||||||
|
* objects and services that are needed by the operating client.
|
||||||
|
*/
|
||||||
|
protected class MiCasaContextImpl implements MiCasaContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Apparently the default constructor has default access, rather
|
||||||
|
* than protected access, even though this class is declared to be
|
||||||
|
* protected. Why, I don't know, but we need to be able to extend
|
||||||
|
* this class elsewhere, so we need this.
|
||||||
|
*/
|
||||||
|
protected MiCasaContextImpl ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client getClient ()
|
||||||
|
{
|
||||||
|
return _client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DObjectManager getDObjectManager ()
|
||||||
|
{
|
||||||
|
return _client.getDObjectManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config getConfig ()
|
||||||
|
{
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationDirector getLocationDirector ()
|
||||||
|
{
|
||||||
|
return _locdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OccupantDirector getOccupantDirector ()
|
||||||
|
{
|
||||||
|
return _occdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatDirector getChatDirector ()
|
||||||
|
{
|
||||||
|
return _chatdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParlorDirector getParlorDirector ()
|
||||||
|
{
|
||||||
|
return _pardtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceView (PlaceView view)
|
||||||
|
{
|
||||||
|
// stick the place view into our frame
|
||||||
|
_frame.setPanel((JPanel)view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPlaceView (PlaceView view)
|
||||||
|
{
|
||||||
|
// we'll just let the next place view replace our old one
|
||||||
|
}
|
||||||
|
|
||||||
|
public MiCasaFrame getFrame ()
|
||||||
|
{
|
||||||
|
return _frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageManager getMessageManager ()
|
||||||
|
{
|
||||||
|
return _msgmgr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected MiCasaFrame _frame;
|
||||||
|
protected Config _config = new Config("micasa");
|
||||||
|
|
||||||
|
protected Client _client;
|
||||||
|
protected LocationDirector _locdir;
|
||||||
|
protected OccupantDirector _occdir;
|
||||||
|
protected ChatDirector _chatdir;
|
||||||
|
protected ParlorDirector _pardtr;
|
||||||
|
protected MessageManager _msgmgr;
|
||||||
|
|
||||||
|
/** The prefix prepended to localization bundle names before looking
|
||||||
|
* them up in the classpath. */
|
||||||
|
protected static final String MESSAGE_MANAGER_PREFIX = "rsrc.i18n";
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaFrame.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
import com.samskivert.swing.ControllerProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the user interface for the MiCasa client application.
|
||||||
|
*/
|
||||||
|
public class MiCasaFrame
|
||||||
|
extends JFrame implements ControllerProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs the top-level MiCasa client frame.
|
||||||
|
*/
|
||||||
|
public MiCasaFrame ()
|
||||||
|
{
|
||||||
|
this("MiCasa Client");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the top-level MiCasa client frame with the specified
|
||||||
|
* window title.
|
||||||
|
*/
|
||||||
|
public MiCasaFrame (String title)
|
||||||
|
{
|
||||||
|
super(title);
|
||||||
|
|
||||||
|
// we'll handle shutting things down ourselves
|
||||||
|
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the panel that makes up the entire client display.
|
||||||
|
*/
|
||||||
|
public void setPanel (JPanel panel)
|
||||||
|
{
|
||||||
|
// remove the old panel
|
||||||
|
getContentPane().removeAll();
|
||||||
|
// add the new one
|
||||||
|
getContentPane().add(panel, BorderLayout.CENTER);
|
||||||
|
// swing doesn't properly repaint after adding/removing children
|
||||||
|
panel.revalidate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the controller for the outermost scope. This controller will
|
||||||
|
* handle all actions that aren't handled by controllers of tigher
|
||||||
|
* scope.
|
||||||
|
*/
|
||||||
|
public void setController (Controller controller)
|
||||||
|
{
|
||||||
|
_controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Controller getController ()
|
||||||
|
{
|
||||||
|
return _controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Controller _controller;
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// $Id: OccupantList.java 3406 2005-03-15 02:12:03Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.client;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.JList;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.OccupantObserver;
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
import com.threerings.crowd.data.OccupantInfo;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.crowd.util.CrowdContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The occupant list displays the list of users that are in a particular
|
||||||
|
* place.
|
||||||
|
*/
|
||||||
|
public class OccupantList
|
||||||
|
extends JList implements PlaceView, OccupantObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs an occupant list with the supplied context which it will
|
||||||
|
* use to register itself with the necessary managers.
|
||||||
|
*/
|
||||||
|
public OccupantList (CrowdContext ctx)
|
||||||
|
{
|
||||||
|
// set up our list model
|
||||||
|
_model = new DefaultListModel();
|
||||||
|
setModel(_model);
|
||||||
|
|
||||||
|
// keep our context around for later
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// register ourselves as an occupant observer
|
||||||
|
_ctx.getOccupantDirector().addOccupantObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
// add all of the occupants of the place to our list
|
||||||
|
Iterator users = plobj.occupantInfo.iterator();
|
||||||
|
while (users.hasNext()) {
|
||||||
|
OccupantInfo info = (OccupantInfo)users.next();
|
||||||
|
_model.addElement(info.username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void didLeavePlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
// clear out our occupant entries
|
||||||
|
_model.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantEntered (OccupantInfo info)
|
||||||
|
{
|
||||||
|
// simply add this user to our list
|
||||||
|
_model.addElement(info.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantLeft (OccupantInfo info)
|
||||||
|
{
|
||||||
|
// remove this occupant from our list
|
||||||
|
_model.removeElement(info.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void occupantUpdated (OccupantInfo oinfo, OccupantInfo info)
|
||||||
|
{
|
||||||
|
// nothing doing
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Our client context. */
|
||||||
|
protected CrowdContext _ctx;
|
||||||
|
|
||||||
|
/** A list model that provides a vector interface. */
|
||||||
|
protected DefaultListModel _model;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaBootstrapData.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.data;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.BootstrapData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the basic Presents bootstrap data and provides some bootstrap
|
||||||
|
* information specific to the MiCasa services.
|
||||||
|
*/
|
||||||
|
public class MiCasaBootstrapData extends BootstrapData
|
||||||
|
{
|
||||||
|
/** The oid of the default lobby. */
|
||||||
|
public int defLobbyOid;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// $Id: Lobby.java 3726 2005-10-11 19:17:43Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.io.SimpleStreamableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class for keeping track of information for each lobby in
|
||||||
|
* operation on the server.
|
||||||
|
*/
|
||||||
|
public class Lobby extends SimpleStreamableObject
|
||||||
|
{
|
||||||
|
/** The object id of the lobby place object. */
|
||||||
|
public int placeOid;
|
||||||
|
|
||||||
|
/** The universal game identifier string for the game matchmade by
|
||||||
|
* this lobby. */
|
||||||
|
public String gameIdent;
|
||||||
|
|
||||||
|
/** The human readable name of the lobby. */
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a lobby record and initializes it with the specified
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
public Lobby (int placeOid, String gameIdent, String name)
|
||||||
|
{
|
||||||
|
this.placeOid = placeOid;
|
||||||
|
this.gameIdent = gameIdent;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a blank lobby record suitable for unserialization.
|
||||||
|
*/
|
||||||
|
public Lobby ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyConfig.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.PlaceController;
|
||||||
|
import com.threerings.crowd.data.PlaceConfig;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
public class LobbyConfig extends PlaceConfig
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public PlaceController createController ()
|
||||||
|
{
|
||||||
|
return new LobbyController();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public String getManagerClassName ()
|
||||||
|
{
|
||||||
|
return "com.threerings.micasa.lobby.LobbyManager";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes override this function and create the appropriate
|
||||||
|
* matchmaking user interface component.
|
||||||
|
*/
|
||||||
|
public JComponent createMatchMakingView (MiCasaContext ctx)
|
||||||
|
{
|
||||||
|
return new JLabel("Match-making view goes here.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates and returns a game config instance using the game
|
||||||
|
* config classname provided by the lobby configuration parameters.
|
||||||
|
*
|
||||||
|
* @exception Exception thrown if a problem occurs loading or
|
||||||
|
* instantiating the class.
|
||||||
|
*/
|
||||||
|
public GameConfig getGameConfig ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
return (GameConfig)Class.forName(_gameConfigClass).newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this lobby config object with the properties that are
|
||||||
|
* used to configure the lobby. This is called on the server when the
|
||||||
|
* lobby is loaded.
|
||||||
|
*/
|
||||||
|
public void init (Properties config)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
_gameConfigClass = getConfigValue(config, "game_config");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void toString (StringBuilder buf)
|
||||||
|
{
|
||||||
|
super.toString(buf);
|
||||||
|
if (buf.length() > 1) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
buf.append("game_config=").append(_gameConfigClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Looks up a configuration property in the supplied properties
|
||||||
|
* object and throws an exception if it's not found. */
|
||||||
|
protected String getConfigValue (Properties config, String key)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
String value = config.getProperty(key);
|
||||||
|
if (StringUtil.isBlank(value)) {
|
||||||
|
throw new Exception("Missing '" + key + "' definition in " +
|
||||||
|
"lobby configuration.");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The name of the game config class that represents the type of game
|
||||||
|
* we are matchmaking for in this lobby. */
|
||||||
|
protected String _gameConfigClass;
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyController.java 3440 2005-03-30 01:09:30Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.PlaceConfig;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.crowd.client.PlaceController;
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
import com.threerings.crowd.util.CrowdContext;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.*;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
public class LobbyController extends PlaceController
|
||||||
|
implements InvitationHandler, InvitationResponseObserver
|
||||||
|
{
|
||||||
|
public void init (CrowdContext ctx, PlaceConfig config)
|
||||||
|
{
|
||||||
|
// cast our context reference
|
||||||
|
_ctx = (MiCasaContext)ctx;
|
||||||
|
_config = (LobbyConfig)config;
|
||||||
|
|
||||||
|
super.init(ctx, config);
|
||||||
|
|
||||||
|
// register ourselves as the invitation handler
|
||||||
|
_ctx.getParlorDirector().setInvitationHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PlaceView createPlaceView (CrowdContext ctx)
|
||||||
|
{
|
||||||
|
return new LobbyPanel(_ctx, _config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.willEnterPlace(plobj);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// if a system property has been specified requesting that we
|
||||||
|
// invite another player, do so now
|
||||||
|
String invitee = System.getProperty("invitee");
|
||||||
|
if (invitee != null) {
|
||||||
|
// create a game config object
|
||||||
|
try {
|
||||||
|
GameConfig config = _config.getGameConfig();
|
||||||
|
_ctx.getParlorDirector().invite(
|
||||||
|
new Name(invitee), config, this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Error instantiating game config.");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SecurityException se) {
|
||||||
|
// nothing to see here, move it along...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invitationReceived (Invitation invite)
|
||||||
|
{
|
||||||
|
Log.info("Invitation received [invite=" + invite + "].");
|
||||||
|
|
||||||
|
// accept the invitation. we're game...
|
||||||
|
invite.accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invitationCancelled (Invitation invite)
|
||||||
|
{
|
||||||
|
Log.info("Invitation cancelled " + invite + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invitationAccepted (Invitation invite)
|
||||||
|
{
|
||||||
|
Log.info("Invitation accepted " + invite + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invitationRefused (Invitation invite, String message)
|
||||||
|
{
|
||||||
|
Log.info("Invitation refused [invite=" + invite +
|
||||||
|
", message=" + message + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invitationCountered (Invitation invite, GameConfig config)
|
||||||
|
{
|
||||||
|
Log.info("Invitation countered [invite=" + invite +
|
||||||
|
", config=" + config + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected LobbyConfig _config;
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.micasa.lobby.LobbyMarshaller;
|
||||||
|
import com.threerings.micasa.lobby.LobbyService;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.server.InvocationDispatcher;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches requests to the {@link LobbyProvider}.
|
||||||
|
*/
|
||||||
|
public class LobbyDispatcher extends InvocationDispatcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a dispatcher that may be registered to dispatch invocation
|
||||||
|
* service requests for the specified provider.
|
||||||
|
*/
|
||||||
|
public LobbyDispatcher (LobbyProvider provider)
|
||||||
|
{
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public InvocationMarshaller createMarshaller ()
|
||||||
|
{
|
||||||
|
return new LobbyMarshaller();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchRequest (
|
||||||
|
ClientObject source, int methodId, Object[] args)
|
||||||
|
throws InvocationException
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case LobbyMarshaller.GET_CATEGORIES:
|
||||||
|
((LobbyProvider)provider).getCategories(
|
||||||
|
source,
|
||||||
|
(LobbyService.CategoriesListener)args[0]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case LobbyMarshaller.GET_LOBBIES:
|
||||||
|
((LobbyProvider)provider).getLobbies(
|
||||||
|
source,
|
||||||
|
(String)args[0], (LobbyService.LobbiesListener)args[1]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchRequest(source, methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyManager.java 3749 2005-11-09 04:00:16Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.crowd.server.PlaceManager;
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes care of the server side of a particular lobby.
|
||||||
|
*/
|
||||||
|
public class LobbyManager extends PlaceManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes this lobby manager with its configuration properties.
|
||||||
|
*
|
||||||
|
* @exception Exception thrown if a configuration error is detected.
|
||||||
|
*/
|
||||||
|
public void init (LobbyRegistry lobreg, Properties config)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
// look up some configuration parameters
|
||||||
|
_gameIdent = getConfigValue(config, "ugi");
|
||||||
|
_name = getConfigValue(config, "name");
|
||||||
|
|
||||||
|
// keep this for later
|
||||||
|
_lobreg = lobreg;
|
||||||
|
|
||||||
|
Log.info("Lobby manager initialized [ident=" + _gameIdent +
|
||||||
|
", name=" + _name + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Looks up a configuration property in the supplied properties
|
||||||
|
* object and throws an exception if it's not found. */
|
||||||
|
protected String getConfigValue (Properties config, String key)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
String value = config.getProperty(key);
|
||||||
|
if (StringUtil.isBlank(value)) {
|
||||||
|
throw new Exception("Missing '" + key + "' definition in " +
|
||||||
|
"lobby configuration.");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected Class getPlaceObjectClass ()
|
||||||
|
{
|
||||||
|
return LobbyObject.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void didStartup ()
|
||||||
|
{
|
||||||
|
super.didStartup();
|
||||||
|
|
||||||
|
// let the lobby registry know that we're up and running
|
||||||
|
_lobreg.lobbyReady(_plobj.getOid(), _gameIdent, _name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The universal game identifier for the game matchmade by this
|
||||||
|
* lobby. */
|
||||||
|
protected String _gameIdent;
|
||||||
|
|
||||||
|
/** The human readable name of this lobby. */
|
||||||
|
protected String _name;
|
||||||
|
|
||||||
|
/** A reference to the lobby registry. */
|
||||||
|
protected LobbyRegistry _lobreg;
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.micasa.lobby.LobbyService;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the implementation of the {@link LobbyService} interface
|
||||||
|
* that marshalls the arguments and delivers the request to the provider
|
||||||
|
* on the server. Also provides an implementation of the response listener
|
||||||
|
* interfaces that marshall the response arguments and deliver them back
|
||||||
|
* to the requesting client.
|
||||||
|
*/
|
||||||
|
public class LobbyMarshaller extends InvocationMarshaller
|
||||||
|
implements LobbyService
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public static class CategoriesMarshaller extends ListenerMarshaller
|
||||||
|
implements CategoriesListener
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #gotCategories}
|
||||||
|
* responses. */
|
||||||
|
public static final int GOT_CATEGORIES = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void gotCategories (String[] arg1)
|
||||||
|
{
|
||||||
|
_invId = null;
|
||||||
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
|
callerOid, requestId, GOT_CATEGORIES,
|
||||||
|
new Object[] { arg1 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchResponse (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case GOT_CATEGORIES:
|
||||||
|
((CategoriesListener)listener).gotCategories(
|
||||||
|
(String[])args[0]);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchResponse(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public static class LobbiesMarshaller extends ListenerMarshaller
|
||||||
|
implements LobbiesListener
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #gotLobbies}
|
||||||
|
* responses. */
|
||||||
|
public static final int GOT_LOBBIES = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void gotLobbies (List arg1)
|
||||||
|
{
|
||||||
|
_invId = null;
|
||||||
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
|
callerOid, requestId, GOT_LOBBIES,
|
||||||
|
new Object[] { arg1 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchResponse (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case GOT_LOBBIES:
|
||||||
|
((LobbiesListener)listener).gotLobbies(
|
||||||
|
(List)args[0]);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchResponse(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #getCategories} requests. */
|
||||||
|
public static final int GET_CATEGORIES = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void getCategories (Client arg1, LobbyService.CategoriesListener arg2)
|
||||||
|
{
|
||||||
|
LobbyMarshaller.CategoriesMarshaller listener2 = new LobbyMarshaller.CategoriesMarshaller();
|
||||||
|
listener2.listener = arg2;
|
||||||
|
sendRequest(arg1, GET_CATEGORIES, new Object[] {
|
||||||
|
listener2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #getLobbies} requests. */
|
||||||
|
public static final int GET_LOBBIES = 2;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void getLobbies (Client arg1, String arg2, LobbyService.LobbiesListener arg3)
|
||||||
|
{
|
||||||
|
LobbyMarshaller.LobbiesMarshaller listener3 = new LobbyMarshaller.LobbiesMarshaller();
|
||||||
|
listener3.listener = arg3;
|
||||||
|
sendRequest(arg1, GET_LOBBIES, new Object[] {
|
||||||
|
arg2, listener3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyObject.java 3218 2004-11-17 23:16:56Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Presently the lobby object contains nothing specific, but the class
|
||||||
|
* acts as a placeholder in case lobby-wide fields are needed in the
|
||||||
|
* future.
|
||||||
|
*/
|
||||||
|
public class LobbyObject extends PlaceObject
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyPanel.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import com.samskivert.swing.*;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
import com.threerings.micasa.client.*;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to display the interface for the lobbies. It contains a lobby
|
||||||
|
* selection mechanism, a chat interface and a user interface for whatever
|
||||||
|
* match-making mechanism is appropriate for this particular lobby.
|
||||||
|
*/
|
||||||
|
public class LobbyPanel
|
||||||
|
extends JPanel implements PlaceView
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new lobby panel and the associated user interface
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
public LobbyPanel (MiCasaContext ctx, LobbyConfig config)
|
||||||
|
{
|
||||||
|
// we want a five pixel border around everything
|
||||||
|
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
|
||||||
|
// create our primary layout which divides the display in two
|
||||||
|
// horizontally
|
||||||
|
GroupLayout gl = new HGroupLayout(GroupLayout.STRETCH);
|
||||||
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
|
gl.setJustification(GroupLayout.RIGHT);
|
||||||
|
setLayout(gl);
|
||||||
|
|
||||||
|
// create our main panel
|
||||||
|
gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||||
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
|
_main = new JPanel(gl);
|
||||||
|
|
||||||
|
// create our match-making view
|
||||||
|
_main.add(config.createMatchMakingView(ctx));
|
||||||
|
|
||||||
|
// create a chat box and stick that in as well
|
||||||
|
_main.add(new ChatPanel(ctx));
|
||||||
|
|
||||||
|
// now add the main panel into the mix
|
||||||
|
add(_main);
|
||||||
|
|
||||||
|
// create our sidebar panel
|
||||||
|
gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||||
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
|
JPanel sidePanel = new JPanel(gl);
|
||||||
|
|
||||||
|
// the sidebar contains a lobby info display...
|
||||||
|
|
||||||
|
// ...a lobby selector...
|
||||||
|
JLabel label = new JLabel("Select a lobby...");
|
||||||
|
sidePanel.add(label, GroupLayout.FIXED);
|
||||||
|
LobbySelector selector = new LobbySelector(ctx);
|
||||||
|
sidePanel.add(selector);
|
||||||
|
|
||||||
|
// and an occupants list
|
||||||
|
label = new JLabel("People in lobby");
|
||||||
|
sidePanel.add(label, GroupLayout.FIXED);
|
||||||
|
_occupants = new OccupantList(ctx);
|
||||||
|
sidePanel.add(_occupants);
|
||||||
|
|
||||||
|
JButton logoff = new JButton("Logoff");
|
||||||
|
logoff.addActionListener(Controller.DISPATCHER);
|
||||||
|
logoff.setActionCommand("logoff");
|
||||||
|
sidePanel.add(logoff, GroupLayout.FIXED);
|
||||||
|
|
||||||
|
// add our sidebar panel into the mix
|
||||||
|
add(sidePanel, GroupLayout.FIXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void didLeavePlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Contains the match-making view and the chatbox. */
|
||||||
|
protected JPanel _main;
|
||||||
|
|
||||||
|
/** Our occupant list display. */
|
||||||
|
protected OccupantList _occupants;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyProvider.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import com.threerings.micasa.lobby.LobbyService;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
import com.threerings.presents.server.InvocationProvider;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the server-side of the {@link LobbyService}.
|
||||||
|
*/
|
||||||
|
public interface LobbyProvider extends InvocationProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles a {@link LobbyService#getCategories} request.
|
||||||
|
*/
|
||||||
|
public void getCategories (ClientObject caller, LobbyService.CategoriesListener arg1)
|
||||||
|
throws InvocationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a {@link LobbyService#getLobbies} request.
|
||||||
|
*/
|
||||||
|
public void getLobbies (ClientObject caller, String arg1, LobbyService.LobbiesListener arg2)
|
||||||
|
throws InvocationException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyRegistry.java 3749 2005-11-09 04:00:16Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import com.samskivert.util.*;
|
||||||
|
import com.threerings.util.StreamableArrayList;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.server.InvocationManager;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.lobby.LobbyService.CategoriesListener;
|
||||||
|
import com.threerings.micasa.lobby.LobbyService.LobbiesListener;
|
||||||
|
import com.threerings.micasa.server.MiCasaConfig;
|
||||||
|
import com.threerings.micasa.server.MiCasaServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lobby registry is the primary class that coordinates the lobby
|
||||||
|
* services on the client. It sets up the necessary invocation services
|
||||||
|
* and keeps track of the lobbies in operation on the server. Only one
|
||||||
|
* lobby registry should be created on a server.
|
||||||
|
*
|
||||||
|
* <p> Presently, the lobby registry is configured with lobbies via the
|
||||||
|
* server configuration. An example configuration follows:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* lobby_ids = foolobby, barlobby, bazlobby
|
||||||
|
*
|
||||||
|
* foolobby.mgrclass = com.threerings.micasa.lobby.LobbyManager
|
||||||
|
* foolobby.ugi = <universal game identifier>
|
||||||
|
* foolobby.name = <human readable lobby name>
|
||||||
|
* foolobby.config1 = some config value
|
||||||
|
* foolobby.config2 = some other config value
|
||||||
|
*
|
||||||
|
* barlobby.mgrclass = com.threerings.micasa.lobby.LobbyManager
|
||||||
|
* barlobby.ugi = <universal game identifier>
|
||||||
|
* barlobby.name = <human readable lobby name>
|
||||||
|
* ...
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* This information will be loaded from the MiCasa server configuration
|
||||||
|
* which means that it should live in
|
||||||
|
* <code>rsrc/config/micasa/server.properties</code> somwhere in the
|
||||||
|
* classpath where it will override the default MiCasa server properties
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* <p> The <code>UGI</code> or universal game identifier is a string that
|
||||||
|
* is used to uniquely identify every type of game and also to classify it
|
||||||
|
* according to meaningful keywords. It is best described with a few
|
||||||
|
* examples:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* backgammon,board,strategy
|
||||||
|
* spades,card,partner
|
||||||
|
* yahtzee,dice
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* As you can see, a UGI should start with an identifier uniquely
|
||||||
|
* identifying the type of game and can be followed by a list of keywords
|
||||||
|
* that classify it as a member of a particular category of games
|
||||||
|
* (eg. board, card, dice, partner game, strategy game). A game can belong
|
||||||
|
* to multiple categories.
|
||||||
|
*
|
||||||
|
* <p> As long as the UGIs in use by a particular server make some kind of
|
||||||
|
* sense, the client will be able to use them to search for lobbies
|
||||||
|
* containing games of similar types using the provided facilities.
|
||||||
|
*/
|
||||||
|
public class LobbyRegistry
|
||||||
|
implements LobbyProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the registry. It will use the supplied configuration
|
||||||
|
* instance to determine which lobbies to load, etc.
|
||||||
|
*
|
||||||
|
* @param invmgr a reference to the server's invocation manager.
|
||||||
|
*/
|
||||||
|
public void init (InvocationManager invmgr)
|
||||||
|
{
|
||||||
|
// register ourselves as an invocation service handler
|
||||||
|
invmgr.registerDispatcher(new LobbyDispatcher(this), true);
|
||||||
|
|
||||||
|
// create our lobby managers
|
||||||
|
String[] lmgrs = null;
|
||||||
|
lmgrs = MiCasaConfig.config.getValue(LOBIDS_KEY, lmgrs);
|
||||||
|
if (lmgrs == null || lmgrs.length == 0) {
|
||||||
|
Log.warning("No lobbies specified in config file (via '" +
|
||||||
|
LOBIDS_KEY + "' parameter).");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < lmgrs.length; i++) {
|
||||||
|
loadLobby(lmgrs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the oid of the default lobby.
|
||||||
|
*/
|
||||||
|
public int getDefaultLobbyOid ()
|
||||||
|
{
|
||||||
|
return _defLobbyOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the properties for a lobby from the server config and
|
||||||
|
* creates and initializes the lobby manager.
|
||||||
|
*/
|
||||||
|
protected void loadLobby (String lobbyId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// extract the properties for this lobby
|
||||||
|
Properties props = MiCasaConfig.config.getSubProperties(lobbyId);
|
||||||
|
|
||||||
|
// get the lobby manager class and UGI
|
||||||
|
String cfgClass = props.getProperty("config");
|
||||||
|
if (StringUtil.isBlank(cfgClass)) {
|
||||||
|
throw new Exception("Missing 'config' definition in " +
|
||||||
|
"lobby configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and initialize the lobby config object
|
||||||
|
LobbyConfig config = (LobbyConfig)
|
||||||
|
Class.forName(cfgClass).newInstance();
|
||||||
|
config.init(props);
|
||||||
|
|
||||||
|
// create and initialize the lobby manager. it will call
|
||||||
|
// lobbyReady() when it has obtained a reference to its lobby
|
||||||
|
// object and is ready to roll
|
||||||
|
LobbyManager lobmgr = (LobbyManager)
|
||||||
|
MiCasaServer.plreg.createPlace(config, null);
|
||||||
|
lobmgr.init(this, props);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to create lobby manager " +
|
||||||
|
"[lobbyId=" + lobbyId + ", error=" + e + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns information about all lobbies hosting games in the
|
||||||
|
* specified category.
|
||||||
|
*
|
||||||
|
* @param requester the body object of the client requesting the lobby
|
||||||
|
* list (which can be used to filter the list based on their
|
||||||
|
* capabilities).
|
||||||
|
* @param category the category of game for which the lobbies are
|
||||||
|
* desired.
|
||||||
|
* @param target the list into which the matching lobbies will be
|
||||||
|
* deposited.
|
||||||
|
*/
|
||||||
|
public void getLobbies (BodyObject requester, String category,
|
||||||
|
List target)
|
||||||
|
{
|
||||||
|
ArrayList list = (ArrayList)_lobbies.get(category);
|
||||||
|
if (list != null) {
|
||||||
|
target.addAll(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing the category identifiers of all the
|
||||||
|
* categories in which lobbies have been registered with the registry.
|
||||||
|
*
|
||||||
|
* @param requester the body object of the client requesting the
|
||||||
|
* cateogory list (which can be used to filter the list based on their
|
||||||
|
* capabilities).
|
||||||
|
*/
|
||||||
|
public String[] getCategories (BodyObject requester)
|
||||||
|
{
|
||||||
|
// might want to cache this some day so that we don't recreate it
|
||||||
|
// every time someone wants it. we can cache the array until the
|
||||||
|
// category count changes
|
||||||
|
String[] cats = new String[_lobbies.size()];
|
||||||
|
Iterator iter = _lobbies.keySet().iterator();
|
||||||
|
for (int i = 0; iter.hasNext(); i++) {
|
||||||
|
cats[i] = (String)iter.next();
|
||||||
|
}
|
||||||
|
return cats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a request by the client to obtain a list of the lobby
|
||||||
|
* categories available on this server.
|
||||||
|
*/
|
||||||
|
public void getCategories (ClientObject caller, CategoriesListener listener)
|
||||||
|
{
|
||||||
|
listener.gotCategories(getCategories((BodyObject)caller));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a request by the client to obtain a list of lobbies
|
||||||
|
* matching the supplied category string.
|
||||||
|
*/
|
||||||
|
public void getLobbies (ClientObject caller, String category,
|
||||||
|
LobbiesListener listener)
|
||||||
|
{
|
||||||
|
StreamableArrayList target = new StreamableArrayList();
|
||||||
|
ArrayList list = (ArrayList)_lobbies.get(category);
|
||||||
|
if (list != null) {
|
||||||
|
target.addAll(list);
|
||||||
|
}
|
||||||
|
listener.gotLobbies(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by our lobby managers once they have started up and are
|
||||||
|
* ready to do their lobby duties.
|
||||||
|
*/
|
||||||
|
protected void lobbyReady (int placeOid, String gameIdent, String name)
|
||||||
|
{
|
||||||
|
// create a lobby record
|
||||||
|
Lobby record = new Lobby(placeOid, gameIdent, name);
|
||||||
|
|
||||||
|
// if we don't already have a default lobby, this one is the big
|
||||||
|
// winner
|
||||||
|
if (_defLobbyOid == -1) {
|
||||||
|
_defLobbyOid = placeOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and register it in all the right lobby tables
|
||||||
|
StringTokenizer tok = new StringTokenizer(gameIdent, ",");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String category = tok.nextToken();
|
||||||
|
registerLobby(category, record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registers the supplied lobby in the specified category table. */
|
||||||
|
protected void registerLobby (String category, Lobby record)
|
||||||
|
{
|
||||||
|
ArrayList catlist = (ArrayList)_lobbies.get(category);
|
||||||
|
if (catlist == null) {
|
||||||
|
catlist = new ArrayList();
|
||||||
|
_lobbies.put(category, catlist);
|
||||||
|
}
|
||||||
|
catlist.add(record);
|
||||||
|
Log.info("Registered lobby [cat=" + category +
|
||||||
|
", record=" + record + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A table containing references to all of our lobby records (in the
|
||||||
|
* form of category lists. */
|
||||||
|
protected HashMap _lobbies = new HashMap();
|
||||||
|
|
||||||
|
/** The oid of the default lobby. */
|
||||||
|
protected int _defLobbyOid = -1;
|
||||||
|
|
||||||
|
/** The configuration key for the lobby managers list. */
|
||||||
|
protected static final String LOBIDS_KEY = "lobby_ids";
|
||||||
|
}
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbySelector.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lobby selector displays a drop-down box listing the categories of
|
||||||
|
* lobbies available on this server and when a category is selected, it
|
||||||
|
* displays a list of the lobbies that are available in that category. If
|
||||||
|
* a lobby is double-clicked, it moves the client into that lobby room.
|
||||||
|
*/
|
||||||
|
public class LobbySelector extends JPanel
|
||||||
|
implements ActionListener, LobbyService.CategoriesListener,
|
||||||
|
LobbyService.LobbiesListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new lobby selector component. It will wait until it is
|
||||||
|
* visible before issuing a get categories request to download a list
|
||||||
|
* of categories.
|
||||||
|
*/
|
||||||
|
public LobbySelector (MiCasaContext ctx)
|
||||||
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
// keep this around for later
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// create our drop-down box with a bogus entry at the moment
|
||||||
|
String[] options = new String[] { CAT_FIRST_ITEM };
|
||||||
|
_combo = new JComboBox(options);
|
||||||
|
_combo.addActionListener(this);
|
||||||
|
add(_combo, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
// and create our empty lobby list
|
||||||
|
_loblist = new JList();
|
||||||
|
_loblist.setCellRenderer(new LobbyCellRenderer());
|
||||||
|
// add a mouse listener that tells us about double clicks
|
||||||
|
MouseListener ml = new MouseAdapter() {
|
||||||
|
public void mouseClicked (MouseEvent e) {
|
||||||
|
if (e.getClickCount() == 2) {
|
||||||
|
int index = _loblist.locationToIndex(e.getPoint());
|
||||||
|
Object item = _loblist.getSelectedValue();
|
||||||
|
enterLobby((Lobby)item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_loblist.addMouseListener(ml);
|
||||||
|
add(_loblist, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void addNotify ()
|
||||||
|
{
|
||||||
|
super.addNotify();
|
||||||
|
|
||||||
|
// get a handle on our lobby service instance
|
||||||
|
_lservice = (LobbyService)
|
||||||
|
_ctx.getClient().requireService(LobbyService.class);
|
||||||
|
// and use them to look up the lobby categories
|
||||||
|
_lservice.getCategories(_ctx.getClient(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user selects a category or double-clicks on a
|
||||||
|
* lobby.
|
||||||
|
*/
|
||||||
|
public void actionPerformed (ActionEvent evt)
|
||||||
|
{
|
||||||
|
if (evt.getSource() == _combo) {
|
||||||
|
String selcat = (String)_combo.getSelectedItem();
|
||||||
|
if (!selcat.equals(CAT_FIRST_ITEM)) {
|
||||||
|
selectCategory(selcat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void gotCategories (String[] categories)
|
||||||
|
{
|
||||||
|
// append these to our "unselected" item
|
||||||
|
for (int i = 0; i < categories.length; i++) {
|
||||||
|
_combo.addItem(categories[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void gotLobbies (List lobbies)
|
||||||
|
{
|
||||||
|
// create a list model for this category
|
||||||
|
DefaultListModel model = new DefaultListModel();
|
||||||
|
|
||||||
|
// populate it with the lobby info
|
||||||
|
Iterator iter = lobbies.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
model.addElement(iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
// stick it in the table
|
||||||
|
_catlists.put(_pendingCategory, model);
|
||||||
|
|
||||||
|
// finally tell the lobby list to update the display (which we do
|
||||||
|
// by setting the combo box to this category in case the luser
|
||||||
|
// decided to try to select some new category while we weren't
|
||||||
|
// looking)
|
||||||
|
_combo.setSelectedItem(_pendingCategory);
|
||||||
|
|
||||||
|
// clear out our pending category indicator
|
||||||
|
_pendingCategory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void requestFailed (String reason)
|
||||||
|
{
|
||||||
|
Log.info("Request failed [reason=" + reason + "].");
|
||||||
|
|
||||||
|
// clear out our pending category indicator in case this was a
|
||||||
|
// failed getLobbies() request
|
||||||
|
_pendingCategory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the list of lobbies available in a particular category (if
|
||||||
|
* they haven't already been fetched) and displays them in the lobby
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
protected void selectCategory (String category)
|
||||||
|
{
|
||||||
|
DefaultListModel model = (DefaultListModel)_catlists.get(category);
|
||||||
|
if (model != null) {
|
||||||
|
_loblist.setModel(model);
|
||||||
|
|
||||||
|
} else if (_pendingCategory == null) {
|
||||||
|
// make a note that we're loading up this category
|
||||||
|
_pendingCategory = category;
|
||||||
|
// issue a request to load up the lobbies in this category
|
||||||
|
_lservice.getLobbies(_ctx.getClient(), category, this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.info("Ignoring category select request because " +
|
||||||
|
"one is outstanding [pcat=" + _pendingCategory +
|
||||||
|
", newcat=" + category + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when the user selects a lobby from the lobby list. */
|
||||||
|
protected void enterLobby (Lobby lobby)
|
||||||
|
{
|
||||||
|
// make sure we're not already in this lobby
|
||||||
|
PlaceObject plobj = _ctx.getLocationDirector().getPlaceObject();
|
||||||
|
if (plobj != null && plobj.getOid() == lobby.placeOid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise request that we go there
|
||||||
|
_ctx.getLocationDirector().moveTo(lobby.placeOid);
|
||||||
|
|
||||||
|
Log.info("Entering lobby " + lobby + ".");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Used to render Lobby instances in our lobby list. */
|
||||||
|
protected static class LobbyCellRenderer
|
||||||
|
extends DefaultListCellRenderer
|
||||||
|
{
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list,
|
||||||
|
Object value,
|
||||||
|
int index,
|
||||||
|
boolean isSelected,
|
||||||
|
boolean cellHasFocus) {
|
||||||
|
// use the lobby's name rather than the value of toString()
|
||||||
|
value = ((Lobby)value).name;
|
||||||
|
return super.getListCellRendererComponent(
|
||||||
|
list, value, index, isSelected, cellHasFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected LobbyService _lservice;
|
||||||
|
|
||||||
|
protected JComboBox _combo;
|
||||||
|
protected JList _loblist;
|
||||||
|
|
||||||
|
protected HashMap _catlists = new HashMap();
|
||||||
|
protected String _pendingCategory;
|
||||||
|
|
||||||
|
protected static final String CAT_FIRST_ITEM = "<categories...>";
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// $Id: LobbyService.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an interface to the various parlor services that are directly
|
||||||
|
* invokable by the client (by means of the invocation services).
|
||||||
|
*/
|
||||||
|
public interface LobbyService extends InvocationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used to communicate the results of a {@link #getCategories}
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
public static interface CategoriesListener extends InvocationListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Supplies the listener with the results of a {@link
|
||||||
|
* #getCategories} request.
|
||||||
|
*/
|
||||||
|
public void gotCategories (String[] categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to communicate the results of a {@link #getLobbies}
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
public static interface LobbiesListener extends InvocationListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Supplies the listener with the results of a {@link
|
||||||
|
* #getLobbies} request.
|
||||||
|
*/
|
||||||
|
public void gotLobbies (List lobbies);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the list of lobby cateogories that are available on this
|
||||||
|
* server.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param listener the listener that will receive and process the
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
public void getCategories (Client client, CategoriesListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests information on all active lobbies that match the specified
|
||||||
|
* category.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param category the category of game for which a list of lobbies is
|
||||||
|
* desired.
|
||||||
|
* @param listener the listener that will receive and process the
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
public void getLobbies (Client client, String category,
|
||||||
|
LobbiesListener listener);
|
||||||
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableItem.java 3758 2005-11-10 23:18:58Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby.table;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.Insets;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.TableDirector;
|
||||||
|
import com.threerings.parlor.client.SeatednessObserver;
|
||||||
|
import com.threerings.parlor.data.Table;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A table item displays the user interface for a single table (whether it
|
||||||
|
* be in-play or still being matchmade).
|
||||||
|
*/
|
||||||
|
public class TableItem
|
||||||
|
extends JPanel
|
||||||
|
implements ActionListener, SeatednessObserver
|
||||||
|
{
|
||||||
|
/** A reference to the table we are displaying. */
|
||||||
|
public Table table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new table item to display and interact with the supplied
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
public TableItem (MiCasaContext ctx, TableDirector tdtr, Table table)
|
||||||
|
{
|
||||||
|
// keep track of these
|
||||||
|
_tdtr = tdtr;
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// add ourselves as a seatedness observer
|
||||||
|
_tdtr.addSeatednessObserver(this);
|
||||||
|
|
||||||
|
// figure out who we are
|
||||||
|
_self = ((BodyObject)ctx.getClient().getClientObject()).getVisibleName();
|
||||||
|
|
||||||
|
// now create our user interface
|
||||||
|
setBorder(BorderFactory.createLineBorder(Color.black));
|
||||||
|
setLayout(new GridBagLayout());
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
|
||||||
|
// create a label for the table
|
||||||
|
JLabel tlabel = new JLabel("Table " + table.tableId);
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.insets = new Insets(2, 0, 0, 0);
|
||||||
|
add(tlabel, gbc);
|
||||||
|
|
||||||
|
// we have one button for every "seat" at the table
|
||||||
|
int bcount = table.occupants.length;
|
||||||
|
|
||||||
|
// create blank buttons for now and then we'll update everything
|
||||||
|
// with the current state when we're done
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
gbc.insets = new Insets(2, 0, 2, 0);
|
||||||
|
_seats = new JButton[bcount];
|
||||||
|
for (int i = 0; i < bcount; i++) {
|
||||||
|
// create the button
|
||||||
|
_seats[i] = new JButton(JOIN_LABEL);
|
||||||
|
_seats[i].addActionListener(this);
|
||||||
|
|
||||||
|
// if we're on the left
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
// if we're the last seat, then we've got an odd number
|
||||||
|
// and need to center this final seat
|
||||||
|
if (i == bcount-1) {
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
} else {
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust the insets of our last element
|
||||||
|
if (i == bcount-1) {
|
||||||
|
gbc.insets = new Insets(2, 0, 4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and add the button with the configured constraints
|
||||||
|
add(_seats[i], gbc);
|
||||||
|
|
||||||
|
// if we just added the first button, add the "go" button
|
||||||
|
// right after it
|
||||||
|
if (i == 0) {
|
||||||
|
_goButton = new JButton("Go");
|
||||||
|
_goButton.setActionCommand("go");
|
||||||
|
_goButton.addActionListener(this);
|
||||||
|
add(_goButton, gbc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// and update ourselves based on the contents of the occupants
|
||||||
|
// list
|
||||||
|
tableUpdated(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when our table has been updated and we need to update the UI
|
||||||
|
* to reflect the new information.
|
||||||
|
*/
|
||||||
|
public void tableUpdated (Table table)
|
||||||
|
{
|
||||||
|
// grab this new table reference
|
||||||
|
this.table = table;
|
||||||
|
|
||||||
|
// first look to see if we're already sitting at a table
|
||||||
|
boolean isSeated = _tdtr.isSeated();
|
||||||
|
|
||||||
|
// now enable and label the buttons accordingly
|
||||||
|
int slength = _seats.length;
|
||||||
|
for (int i = 0; i < slength; i++) {
|
||||||
|
if (table.occupants[i] == null) {
|
||||||
|
_seats[i].setText(JOIN_LABEL);
|
||||||
|
_seats[i].setEnabled(!isSeated);
|
||||||
|
_seats[i].setActionCommand("join");
|
||||||
|
|
||||||
|
} else if (table.occupants[i].equals(_self) &&
|
||||||
|
!table.inPlay()) {
|
||||||
|
_seats[i].setText(LEAVE_LABEL);
|
||||||
|
_seats[i].setEnabled(true);
|
||||||
|
_seats[i].setActionCommand("leave");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_seats[i].setText(table.occupants[i].toString());
|
||||||
|
_seats[i].setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show or hide our "go" button appropriately
|
||||||
|
_goButton.setVisible(table.gameOid != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the table list view prior to removing us. Here we clean
|
||||||
|
* up.
|
||||||
|
*/
|
||||||
|
public void tableRemoved ()
|
||||||
|
{
|
||||||
|
// no more observy
|
||||||
|
_tdtr.removeSeatednessObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void actionPerformed (ActionEvent event)
|
||||||
|
{
|
||||||
|
String cmd = event.getActionCommand();
|
||||||
|
if (cmd.equals("join")) {
|
||||||
|
// figure out what position this button is in
|
||||||
|
int position = -1;
|
||||||
|
for (int i = 0; i < _seats.length; i++) {
|
||||||
|
if (_seats[i] == event.getSource()) {
|
||||||
|
position = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (position == -1) {
|
||||||
|
Log.warning("Unable to figure out what position a <join> " +
|
||||||
|
"click came from [event=" + event + "].");
|
||||||
|
} else {
|
||||||
|
// otherwise, request to join the table at this position
|
||||||
|
_tdtr.joinTable(table.getTableId(), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (cmd.equals("leave")) {
|
||||||
|
// if we're not joining, we're leaving
|
||||||
|
_tdtr.leaveTable(table.getTableId());
|
||||||
|
|
||||||
|
} else if (cmd.equals("go")) {
|
||||||
|
// they want to see the game... so go there
|
||||||
|
_ctx.getLocationDirector().moveTo(table.gameOid);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.warning("Received unknown action [event=" + event + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void seatednessDidChange (boolean isSeated)
|
||||||
|
{
|
||||||
|
// just update ourselves
|
||||||
|
tableUpdated(table);
|
||||||
|
|
||||||
|
// enable or disable the go button based on our seatedness
|
||||||
|
if (_goButton.isVisible()) {
|
||||||
|
_goButton.setEnabled(!isSeated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A reference to our context. */
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
|
||||||
|
/** Our username. */
|
||||||
|
protected Name _self;
|
||||||
|
|
||||||
|
/** A reference to our table director. */
|
||||||
|
protected TableDirector _tdtr;
|
||||||
|
|
||||||
|
/** We have a button for each "seat" at the table. */
|
||||||
|
protected JButton[] _seats;
|
||||||
|
|
||||||
|
/** We have a button for going to games that are already in
|
||||||
|
* progress. */
|
||||||
|
protected JButton _goButton;
|
||||||
|
|
||||||
|
/** The text shown for seats at which the user can join. */
|
||||||
|
protected static final String JOIN_LABEL = "<join>";
|
||||||
|
|
||||||
|
/** The text shown for the seat in which this user occupies and which
|
||||||
|
* lets her/him know that they can leave that seat by clicking. */
|
||||||
|
protected static final String LEAVE_LABEL = "<leave>";
|
||||||
|
}
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableListView.java 3593 2005-06-10 18:10:49Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby.table;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
|
||||||
|
import com.samskivert.swing.HGroupLayout;
|
||||||
|
import com.samskivert.swing.VGroupLayout;
|
||||||
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.lobby.LobbyConfig;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.SeatednessObserver;
|
||||||
|
import com.threerings.parlor.client.TableConfigurator;
|
||||||
|
import com.threerings.parlor.client.TableDirector;
|
||||||
|
import com.threerings.parlor.client.TableObserver;
|
||||||
|
import com.threerings.parlor.data.Table;
|
||||||
|
import com.threerings.parlor.game.client.GameConfigurator;
|
||||||
|
import com.threerings.parlor.game.client.SwingGameConfigurator;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A view that displays the tables in a table lobby. It displays two
|
||||||
|
* separate lists, one of tables being matchmade and another of games in
|
||||||
|
* progress. These tables are updated dynamically as they proceed through
|
||||||
|
* the matchmaking process. UI mechanisms for creating and joining tables
|
||||||
|
* are also provided.
|
||||||
|
*/
|
||||||
|
public class TableListView extends JPanel
|
||||||
|
implements PlaceView, TableObserver, ActionListener, SeatednessObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new table list view, suitable for providing the user
|
||||||
|
* interface for table-style matchmaking in a table lobby.
|
||||||
|
*/
|
||||||
|
public TableListView (MiCasaContext ctx, LobbyConfig config)
|
||||||
|
{
|
||||||
|
// keep track of these
|
||||||
|
_config = config;
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// create our table director
|
||||||
|
_tdtr = new TableDirector(ctx, TableLobbyObject.TABLE_SET, this);
|
||||||
|
|
||||||
|
// add ourselves as a seatedness observer
|
||||||
|
_tdtr.addSeatednessObserver(this);
|
||||||
|
|
||||||
|
// set up a layout manager
|
||||||
|
HGroupLayout gl = new HGroupLayout(HGroupLayout.STRETCH);
|
||||||
|
gl.setOffAxisPolicy(HGroupLayout.STRETCH);
|
||||||
|
setLayout(gl);
|
||||||
|
|
||||||
|
// we have two lists of tables, one of tables being matchmade...
|
||||||
|
VGroupLayout pgl = new VGroupLayout(VGroupLayout.STRETCH);
|
||||||
|
pgl.setOffAxisPolicy(VGroupLayout.STRETCH);
|
||||||
|
JPanel panel = new JPanel(pgl);
|
||||||
|
panel.add(new JLabel("Pending tables"), VGroupLayout.FIXED);
|
||||||
|
|
||||||
|
VGroupLayout mgl = new VGroupLayout(VGroupLayout.NONE);
|
||||||
|
mgl.setOffAxisPolicy(VGroupLayout.STRETCH);
|
||||||
|
mgl.setJustification(VGroupLayout.TOP);
|
||||||
|
_matchList = new JPanel(mgl);
|
||||||
|
_matchList.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
panel.add(new JScrollPane(_matchList));
|
||||||
|
|
||||||
|
// create and initialize the configurator interface
|
||||||
|
GameConfig gconfig = null;
|
||||||
|
try {
|
||||||
|
gconfig = config.getGameConfig();
|
||||||
|
|
||||||
|
_tableFigger = gconfig.createTableConfigurator();
|
||||||
|
if (_tableFigger == null) {
|
||||||
|
Log.warning("Game config has not been set up to work with " +
|
||||||
|
"tables: it needs to return non-null from " +
|
||||||
|
"createTableConfigurator().");
|
||||||
|
// let's just wait until we throw an NPE below
|
||||||
|
}
|
||||||
|
|
||||||
|
_figger = gconfig.createConfigurator();
|
||||||
|
_tableFigger.init(_ctx, _figger);
|
||||||
|
if (_figger != null) {
|
||||||
|
_figger.init(_ctx);
|
||||||
|
_figger.setGameConfig(gconfig);
|
||||||
|
panel.add(((SwingGameConfigurator) _figger).getPanel(),
|
||||||
|
VGroupLayout.FIXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
_create = new JButton("Create table");
|
||||||
|
_create.addActionListener(this);
|
||||||
|
panel.add(_create, VGroupLayout.FIXED);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to create configurator interface " +
|
||||||
|
"[config=" + gconfig + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
|
||||||
|
// stick something in the UI to let them know we're hosed
|
||||||
|
panel.add(new JLabel("Aiya! Can't create tables. " +
|
||||||
|
"Configuration borked."), VGroupLayout.FIXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
add(panel);
|
||||||
|
|
||||||
|
// ...and one of games in progress
|
||||||
|
panel = new JPanel(pgl);
|
||||||
|
panel.add(new JLabel("Games in progress"), VGroupLayout.FIXED);
|
||||||
|
|
||||||
|
_playList = new JPanel(mgl);
|
||||||
|
_playList.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
panel.add(new JScrollPane(_playList));
|
||||||
|
|
||||||
|
add(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void willEnterPlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// pass the good word on to our table director
|
||||||
|
_tdtr.willEnterPlace(place);
|
||||||
|
|
||||||
|
// iterate over the tables already active in this lobby and put
|
||||||
|
// them in their respective lists
|
||||||
|
TableLobbyObject tlobj = (TableLobbyObject)place;
|
||||||
|
Iterator iter = tlobj.tableSet.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
tableAdded((Table)iter.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void didLeavePlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// pass the good word on to our table director
|
||||||
|
_tdtr.didLeavePlace(place);
|
||||||
|
|
||||||
|
// clear out our table lists
|
||||||
|
_matchList.removeAll();
|
||||||
|
_playList.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void tableAdded (Table table)
|
||||||
|
{
|
||||||
|
Log.info("Table added [table=" + table + "].");
|
||||||
|
|
||||||
|
// create a table item for this table and insert it into the
|
||||||
|
// appropriate list
|
||||||
|
JPanel panel = table.inPlay() ? _playList : _matchList;
|
||||||
|
panel.add(new TableItem(_ctx, _tdtr, table));
|
||||||
|
SwingUtil.refresh(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void tableUpdated (Table table)
|
||||||
|
{
|
||||||
|
Log.info("Table updated [table=" + table + "].");
|
||||||
|
|
||||||
|
// locate the table item associated with this table
|
||||||
|
TableItem item = getTableItem(table.getTableId());
|
||||||
|
if (item == null) {
|
||||||
|
Log.warning("Received table updated notification for " +
|
||||||
|
"unknown table [table=" + table + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let the item perform any updates it finds necessary
|
||||||
|
item.tableUpdated(table);
|
||||||
|
|
||||||
|
// and we may need to move the item from the match to the in-play
|
||||||
|
// list if it just transitioned
|
||||||
|
if (table.gameOid != -1 && item.getParent() == _matchList) {
|
||||||
|
_matchList.remove(item);
|
||||||
|
SwingUtil.refresh(_matchList);
|
||||||
|
_playList.add(item);
|
||||||
|
SwingUtil.refresh(_playList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void tableRemoved (int tableId)
|
||||||
|
{
|
||||||
|
Log.info("Table removed [tableId=" + tableId + "].");
|
||||||
|
|
||||||
|
// locate the table item associated with this table
|
||||||
|
TableItem item = getTableItem(tableId);
|
||||||
|
if (item == null) {
|
||||||
|
Log.warning("Received table removed notification for " +
|
||||||
|
"unknown table [tableId=" + tableId + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove this item from the user interface
|
||||||
|
JPanel panel = (JPanel)item.getParent();
|
||||||
|
panel.remove(item);
|
||||||
|
SwingUtil.refresh(panel);
|
||||||
|
|
||||||
|
// let the little fellow know that we gave him the boot
|
||||||
|
item.tableRemoved();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void actionPerformed (ActionEvent event)
|
||||||
|
{
|
||||||
|
// the create table button was clicked. use the game config as
|
||||||
|
// configured by the configurator to create a table
|
||||||
|
_tdtr.createTable(_tableFigger.getTableConfig(),
|
||||||
|
_figger.getGameConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void seatednessDidChange (boolean isSeated)
|
||||||
|
{
|
||||||
|
// update the create table button
|
||||||
|
_create.setEnabled(!isSeated);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the table item component associated with the specified
|
||||||
|
* table id.
|
||||||
|
*/
|
||||||
|
protected TableItem getTableItem (int tableId)
|
||||||
|
{
|
||||||
|
// first check the match list
|
||||||
|
int ccount = _matchList.getComponentCount();
|
||||||
|
for (int i = 0; i < ccount; i++) {
|
||||||
|
TableItem child = (TableItem)_matchList.getComponent(i);
|
||||||
|
if (child.table.getTableId() == tableId) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then the inplay list
|
||||||
|
ccount = _playList.getComponentCount();
|
||||||
|
for (int i = 0; i < ccount; i++) {
|
||||||
|
TableItem child = (TableItem)_playList.getComponent(i);
|
||||||
|
if (child.table.getTableId() == tableId) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sorry charlie
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A reference to the client context. */
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
|
||||||
|
/** A reference to the lobby config for the lobby in which we are
|
||||||
|
* doing table-style matchmaking. */
|
||||||
|
protected LobbyConfig _config;
|
||||||
|
|
||||||
|
/** A reference to our table director. */
|
||||||
|
protected TableDirector _tdtr;
|
||||||
|
|
||||||
|
/** The list of tables currently being matchmade. */
|
||||||
|
protected JPanel _matchList;
|
||||||
|
|
||||||
|
/** The list of tables that are in play. */
|
||||||
|
protected JPanel _playList;
|
||||||
|
|
||||||
|
/** The interface used to configure the table for a game. */
|
||||||
|
protected TableConfigurator _tableFigger;
|
||||||
|
|
||||||
|
/** The interface used to configure a game before creating it. */
|
||||||
|
protected GameConfigurator _figger;
|
||||||
|
|
||||||
|
/** Our create table button. */
|
||||||
|
protected JButton _create;
|
||||||
|
|
||||||
|
/** Our number of players indicator. */
|
||||||
|
protected JLabel _pcount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableLobbyConfig.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby.table;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import com.threerings.micasa.lobby.LobbyConfig;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructs the lobby services to use a {@link TableListView} as the
|
||||||
|
* matchmaking component.
|
||||||
|
*/
|
||||||
|
public class TableLobbyConfig extends LobbyConfig
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public String getManagerClassName ()
|
||||||
|
{
|
||||||
|
return "com.threerings.micasa.lobby.table.TableLobbyManager";
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public JComponent createMatchMakingView (MiCasaContext ctx)
|
||||||
|
{
|
||||||
|
return new TableListView(ctx, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableLobbyManager.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby.table;
|
||||||
|
|
||||||
|
import com.threerings.parlor.server.TableManager;
|
||||||
|
import com.threerings.parlor.server.TableManagerProvider;
|
||||||
|
import com.threerings.micasa.lobby.LobbyManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends lobby manager only to ensure that a table lobby object is used
|
||||||
|
* for table lobbies.
|
||||||
|
*/
|
||||||
|
public class TableLobbyManager
|
||||||
|
extends LobbyManager implements TableManagerProvider
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
protected void didStartup ()
|
||||||
|
{
|
||||||
|
super.didStartup();
|
||||||
|
|
||||||
|
// now that we have our place object, we can create our table
|
||||||
|
// manager
|
||||||
|
_tmgr = new TableManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected Class getPlaceObjectClass ()
|
||||||
|
{
|
||||||
|
return TableLobbyObject.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public TableManager getTableManager ()
|
||||||
|
{
|
||||||
|
return _tmgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A reference to our table manager. */
|
||||||
|
protected TableManager _tmgr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableLobbyObject.java 4166 2006-05-31 04:16:57Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.lobby.table;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
import com.threerings.parlor.data.Table;
|
||||||
|
import com.threerings.micasa.lobby.LobbyObject;
|
||||||
|
|
||||||
|
public class TableLobbyObject
|
||||||
|
extends LobbyObject
|
||||||
|
implements com.threerings.parlor.data.TableLobbyObject
|
||||||
|
{
|
||||||
|
// AUTO-GENERATED: FIELDS START
|
||||||
|
/** The field name of the <code>tableSet</code> field. */
|
||||||
|
public static final String TABLE_SET = "tableSet";
|
||||||
|
// AUTO-GENERATED: FIELDS END
|
||||||
|
|
||||||
|
/** A set containing all of the tables being managed by this lobby. */
|
||||||
|
public DSet tableSet = new DSet();
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public DSet getTables ()
|
||||||
|
{
|
||||||
|
return tableSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void addToTables (Table table)
|
||||||
|
{
|
||||||
|
addToTableSet(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void updateTables (Table table)
|
||||||
|
{
|
||||||
|
updateTableSet(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void removeFromTables (Comparable key)
|
||||||
|
{
|
||||||
|
removeFromTableSet(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AUTO-GENERATED: METHODS START
|
||||||
|
/**
|
||||||
|
* Requests that the specified entry be added to the
|
||||||
|
* <code>tableSet</code> set. The set will not change until the event is
|
||||||
|
* actually propagated through the system.
|
||||||
|
*/
|
||||||
|
public void addToTableSet (DSet.Entry elem)
|
||||||
|
{
|
||||||
|
requestEntryAdd(TABLE_SET, tableSet, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the entry matching the supplied key be removed from
|
||||||
|
* the <code>tableSet</code> set. The set will not change until the
|
||||||
|
* event is actually propagated through the system.
|
||||||
|
*/
|
||||||
|
public void removeFromTableSet (Comparable key)
|
||||||
|
{
|
||||||
|
requestEntryRemove(TABLE_SET, tableSet, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified entry be updated in the
|
||||||
|
* <code>tableSet</code> set. The set will not change until the event is
|
||||||
|
* actually propagated through the system.
|
||||||
|
*/
|
||||||
|
public void updateTableSet (DSet.Entry elem)
|
||||||
|
{
|
||||||
|
requestEntryUpdate(TABLE_SET, tableSet, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the <code>tableSet</code> field be set to the
|
||||||
|
* specified value. Generally one only adds, updates and removes
|
||||||
|
* entries of a distributed set, but certain situations call for a
|
||||||
|
* complete replacement of the set value. The local value will be
|
||||||
|
* updated immediately and an event will be propagated through the
|
||||||
|
* system to notify all listeners that the attribute did
|
||||||
|
* change. Proxied copies of this object (on clients) will apply the
|
||||||
|
* value change when they received the attribute changed notification.
|
||||||
|
*/
|
||||||
|
public void setTableSet (DSet value)
|
||||||
|
{
|
||||||
|
requestAttributeChange(TABLE_SET, value, this.tableSet);
|
||||||
|
this.tableSet = (value == null) ? null : value.typedClone();
|
||||||
|
}
|
||||||
|
// AUTO-GENERATED: METHODS END
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaClient.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.server;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.BootstrapData;
|
||||||
|
import com.threerings.crowd.server.CrowdClient;
|
||||||
|
|
||||||
|
import com.threerings.micasa.data.MiCasaBootstrapData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the Crowd client and provides bootstrap data specific to the
|
||||||
|
* MiCasa services.
|
||||||
|
*/
|
||||||
|
public class MiCasaClient extends CrowdClient
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
protected BootstrapData createBootstrapData ()
|
||||||
|
{
|
||||||
|
return new MiCasaBootstrapData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void populateBootstrapData (BootstrapData data)
|
||||||
|
{
|
||||||
|
super.populateBootstrapData(data);
|
||||||
|
|
||||||
|
// let the client know their default lobby oid
|
||||||
|
((MiCasaBootstrapData)data).defLobbyOid =
|
||||||
|
MiCasaServer.lobreg.getDefaultLobbyOid();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaConfig.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.server;
|
||||||
|
|
||||||
|
import com.samskivert.util.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the MiCasa server configuration.
|
||||||
|
*/
|
||||||
|
public class MiCasaConfig
|
||||||
|
{
|
||||||
|
/** Provides access to configuration data for this package. */
|
||||||
|
public static Config config = new Config("rsrc/config/micasa/server");
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaServer.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.server;
|
||||||
|
|
||||||
|
import com.threerings.crowd.server.CrowdServer;
|
||||||
|
import com.threerings.parlor.server.ParlorManager;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.lobby.LobbyRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the main entry point and general organizer of everything
|
||||||
|
* that goes on in the MiCasa game server process.
|
||||||
|
*/
|
||||||
|
public class MiCasaServer extends CrowdServer
|
||||||
|
{
|
||||||
|
/** The parlor manager in operation on this server. */
|
||||||
|
public static ParlorManager parmgr = new ParlorManager();
|
||||||
|
|
||||||
|
/** The lobby registry operating on this server. */
|
||||||
|
public static LobbyRegistry lobreg = new LobbyRegistry();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes all of the server services and prepares for operation.
|
||||||
|
*/
|
||||||
|
public void init ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
// do the base server initialization
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
// configure the client manager to use our client class
|
||||||
|
clmgr.setClientClass(MiCasaClient.class);
|
||||||
|
|
||||||
|
// initialize our parlor manager
|
||||||
|
parmgr.init(invmgr, plreg);
|
||||||
|
|
||||||
|
// initialize the lobby registry
|
||||||
|
lobreg.init(invmgr);
|
||||||
|
|
||||||
|
Log.info("MiCasa server initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
MiCasaServer server = new MiCasaServer();
|
||||||
|
try {
|
||||||
|
server.init();
|
||||||
|
server.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to initialize server.");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimpleClient.java 3283 2004-12-22 19:23:00Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.samskivert.util.Config;
|
||||||
|
import com.samskivert.util.RunQueue;
|
||||||
|
import com.threerings.util.MessageManager;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.dobj.DObjectManager;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.LocationDirector;
|
||||||
|
import com.threerings.crowd.client.OccupantDirector;
|
||||||
|
import com.threerings.crowd.client.PlaceView;
|
||||||
|
|
||||||
|
import com.threerings.crowd.chat.client.ChatDirector;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.ParlorDirector;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
import com.threerings.micasa.client.MiCasaFrame;
|
||||||
|
import com.threerings.micasa.util.MiCasaContext;
|
||||||
|
|
||||||
|
public class SimpleClient
|
||||||
|
implements RunQueue, SimulatorClient
|
||||||
|
{
|
||||||
|
public SimpleClient (SimulatorFrame frame)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// create our context
|
||||||
|
_ctx = createContext();
|
||||||
|
|
||||||
|
// create the handles on our various services
|
||||||
|
_client = new Client(null, this);
|
||||||
|
|
||||||
|
// create our managers and directors
|
||||||
|
_msgmgr = new MessageManager(getMessageManagerPrefix());
|
||||||
|
_locdir = new LocationDirector(_ctx);
|
||||||
|
_occdir = new OccupantDirector(_ctx);
|
||||||
|
_pardtr = new ParlorDirector(_ctx);
|
||||||
|
_chatdir = new ChatDirector(_ctx, _msgmgr, null);
|
||||||
|
|
||||||
|
// keep this for later
|
||||||
|
_frame = frame;
|
||||||
|
|
||||||
|
// log off when they close the window
|
||||||
|
_frame.getFrame().addWindowListener(new WindowAdapter() {
|
||||||
|
public void windowClosing (WindowEvent evt) {
|
||||||
|
// if we're logged on, log off
|
||||||
|
if (_client.isLoggedOn()) {
|
||||||
|
_client.logoff(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates our context reference.
|
||||||
|
*/
|
||||||
|
protected MiCasaContext createContext ()
|
||||||
|
{
|
||||||
|
return new MiCasaContextImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the prefix used by the message manager when looking for
|
||||||
|
* translation properties files.
|
||||||
|
*/
|
||||||
|
protected String getMessageManagerPrefix ()
|
||||||
|
{
|
||||||
|
return "rsrc";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the context in effect for this client. This
|
||||||
|
* reference is valid for the lifetime of the application.
|
||||||
|
*/
|
||||||
|
public ParlorContext getParlorContext ()
|
||||||
|
{
|
||||||
|
return _ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface RunQueue
|
||||||
|
public void postRunnable (Runnable run)
|
||||||
|
{
|
||||||
|
// queue it on up on the awt thread
|
||||||
|
EventQueue.invokeLater(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface RunQueue
|
||||||
|
public boolean isDispatchThread ()
|
||||||
|
{
|
||||||
|
return EventQueue.isDispatchThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context implementation. This provides access to all of the
|
||||||
|
* objects and services that are needed by the operating client.
|
||||||
|
*/
|
||||||
|
protected class MiCasaContextImpl implements MiCasaContext
|
||||||
|
{
|
||||||
|
public Config getConfig ()
|
||||||
|
{
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Client getClient ()
|
||||||
|
{
|
||||||
|
return _client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DObjectManager getDObjectManager ()
|
||||||
|
{
|
||||||
|
return _client.getDObjectManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationDirector getLocationDirector ()
|
||||||
|
{
|
||||||
|
return _locdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OccupantDirector getOccupantDirector ()
|
||||||
|
{
|
||||||
|
return _occdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParlorDirector getParlorDirector ()
|
||||||
|
{
|
||||||
|
return _pardtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatDirector getChatDirector ()
|
||||||
|
{
|
||||||
|
return _chatdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceView (PlaceView view)
|
||||||
|
{
|
||||||
|
// stick the place view into our frame
|
||||||
|
_frame.setPanel((JPanel)view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPlaceView (PlaceView view)
|
||||||
|
{
|
||||||
|
// we'll just let the next view replace the old one
|
||||||
|
}
|
||||||
|
|
||||||
|
public MiCasaFrame getFrame ()
|
||||||
|
{
|
||||||
|
return (MiCasaFrame)_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageManager getMessageManager ()
|
||||||
|
{
|
||||||
|
return _msgmgr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MiCasaContext _ctx;
|
||||||
|
protected SimulatorFrame _frame;
|
||||||
|
protected MessageManager _msgmgr;
|
||||||
|
|
||||||
|
protected Config _config = new Config("micasa");
|
||||||
|
protected Client _client;
|
||||||
|
protected LocationDirector _locdir;
|
||||||
|
protected OccupantDirector _occdir;
|
||||||
|
protected ParlorDirector _pardtr;
|
||||||
|
protected ChatDirector _chatdir;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimpleFrame.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
|
||||||
|
import com.threerings.micasa.client.MiCasaFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the user interface for the Simulator client application.
|
||||||
|
*/
|
||||||
|
public class SimpleFrame extends MiCasaFrame
|
||||||
|
implements SimulatorFrame
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs the top-level Simulator client frame.
|
||||||
|
*/
|
||||||
|
public SimpleFrame ()
|
||||||
|
{
|
||||||
|
super("Simulator");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public JFrame getFrame ()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Controller _controller;
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorApp.java 4158 2006-05-30 22:12:15Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
import com.samskivert.util.Interval;
|
||||||
|
import com.samskivert.util.ResultListener;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.ClientAdapter;
|
||||||
|
import com.threerings.presents.net.UsernamePasswordCreds;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.simulator.data.SimulatorInfo;
|
||||||
|
import com.threerings.micasa.simulator.server.SimpleServer;
|
||||||
|
import com.threerings.micasa.simulator.server.SimulatorServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The simulator application is a test harness to facilitate development
|
||||||
|
* and debugging of games.
|
||||||
|
*/
|
||||||
|
public class SimulatorApp
|
||||||
|
{
|
||||||
|
public void start (final String[] args) throws Exception
|
||||||
|
{
|
||||||
|
// create a frame
|
||||||
|
_frame = createSimulatorFrame();
|
||||||
|
|
||||||
|
// create the simulator info object
|
||||||
|
SimulatorInfo siminfo = new SimulatorInfo();
|
||||||
|
siminfo.gameConfigClass = args[0];
|
||||||
|
siminfo.simClass = args[1];
|
||||||
|
siminfo.playerCount = getInt(
|
||||||
|
System.getProperty("playercount"), DEFAULT_PLAYER_COUNT);
|
||||||
|
|
||||||
|
// create our client instance
|
||||||
|
_client = createSimulatorClient(_frame);
|
||||||
|
|
||||||
|
// set up the top-level client controller
|
||||||
|
Controller ctrl = createController(siminfo);
|
||||||
|
_frame.setController(ctrl);
|
||||||
|
|
||||||
|
// create the server
|
||||||
|
SimulatorServer server = createSimulatorServer();
|
||||||
|
server.init(new ResultListener() {
|
||||||
|
public void requestCompleted (Object result) {
|
||||||
|
try {
|
||||||
|
run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Simulator initialization failed " +
|
||||||
|
"[e=" + e + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void requestFailed (Exception e) {
|
||||||
|
Log.warning("Simulator initialization failed [e=" + e + "].");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// run the server on a separate thread
|
||||||
|
_serverThread = new ServerThread(server);
|
||||||
|
// start up the server so that we can be notified when
|
||||||
|
// initialization is complete
|
||||||
|
_serverThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorServer createSimulatorServer ()
|
||||||
|
{
|
||||||
|
return new SimpleServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorFrame createSimulatorFrame ()
|
||||||
|
{
|
||||||
|
return new SimpleFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorClient createSimulatorClient (SimulatorFrame frame)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
return new SimpleClient(_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorController createController (SimulatorInfo siminfo)
|
||||||
|
{
|
||||||
|
return new SimulatorController(
|
||||||
|
_client.getParlorContext(), _frame, siminfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
// configure and display the main frame
|
||||||
|
JFrame frame = _frame.getFrame();
|
||||||
|
frame.setSize(800, 600);
|
||||||
|
SwingUtil.centerWindow(frame);
|
||||||
|
frame.setVisible(true);
|
||||||
|
|
||||||
|
// start up the client
|
||||||
|
Client client = _client.getParlorContext().getClient();
|
||||||
|
Log.info("Connecting to localhost.");
|
||||||
|
client.setServer("localhost", Client.DEFAULT_SERVER_PORTS);
|
||||||
|
|
||||||
|
// we want to exit when we logged off or failed to log on
|
||||||
|
client.addClientObserver(new ClientAdapter() {
|
||||||
|
public void clientFailedToLogon (Client c, Exception cause) {
|
||||||
|
Log.info("Client failed to logon: " + cause);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
public void clientDidLogoff (Client c) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// configure the client with some credentials and logon
|
||||||
|
String username = System.getProperty("username");
|
||||||
|
if (username == null) {
|
||||||
|
username =
|
||||||
|
"bob" + ((int)(Math.random() * Integer.MAX_VALUE) % 500);
|
||||||
|
}
|
||||||
|
String password = System.getProperty("password");
|
||||||
|
if (password == null) {
|
||||||
|
password = "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and set our credentials
|
||||||
|
client.setCredentials(
|
||||||
|
new UsernamePasswordCreds(new Name(username), password));
|
||||||
|
|
||||||
|
// this is a bit of a hack, but we need to give the server long
|
||||||
|
// enough to fully initialize and start listening on its socket
|
||||||
|
// before we try to logon; there's no good way for this otherwise
|
||||||
|
// wholly independent thread to wait for the server to be ready as
|
||||||
|
// in normal circumstances they are entirely different processes;
|
||||||
|
// so we just wait half a second which does the job
|
||||||
|
new Interval() {
|
||||||
|
public void expired () {
|
||||||
|
_client.getParlorContext().getClient().logon();
|
||||||
|
}
|
||||||
|
}.schedule(500L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
if (!checkArgs(args)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimulatorApp app = new SimulatorApp();
|
||||||
|
try {
|
||||||
|
app.start(args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Error starting up application.");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean checkArgs (String[] args)
|
||||||
|
{
|
||||||
|
if (args.length < 2) {
|
||||||
|
String msg = "Usage:\n" +
|
||||||
|
" java com.threerings.simulator.SimulatorApp " +
|
||||||
|
"<game config class name> <simulant class name>\n" +
|
||||||
|
"Optional properties:\n" +
|
||||||
|
" -Dusername=<user>\n" +
|
||||||
|
" -Dplayercount=<number>\n" +
|
||||||
|
" -Dwidth=<width>\n" +
|
||||||
|
" -Dheight=<height>";
|
||||||
|
System.out.println(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getInt (String value, int defval)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
return defval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class ServerThread extends Thread
|
||||||
|
{
|
||||||
|
public ServerThread (SimulatorServer server)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
_server.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorServer _server;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimulatorClient _client;
|
||||||
|
protected SimulatorFrame _frame;
|
||||||
|
protected ServerThread _serverThread;
|
||||||
|
|
||||||
|
/** The default number of players in the game. */
|
||||||
|
protected static final int DEFAULT_PLAYER_COUNT = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorClient.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
public interface SimulatorClient
|
||||||
|
{
|
||||||
|
public ParlorContext getParlorContext ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorController.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.SessionObserver;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
import com.threerings.micasa.simulator.data.SimulatorInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for top-level control of the simulator client user interface.
|
||||||
|
*/
|
||||||
|
public class SimulatorController extends Controller
|
||||||
|
implements SessionObserver
|
||||||
|
{
|
||||||
|
/** Command constant used to logoff the client. */
|
||||||
|
public static final String LOGOFF = "logoff";
|
||||||
|
|
||||||
|
// 577-2028
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new simulator controller. The controller will set
|
||||||
|
* everything up in preparation for logging on.
|
||||||
|
*/
|
||||||
|
public SimulatorController (ParlorContext ctx, SimulatorFrame frame,
|
||||||
|
SimulatorInfo info)
|
||||||
|
{
|
||||||
|
// we'll want to keep these around
|
||||||
|
_ctx = ctx;
|
||||||
|
_frame = frame;
|
||||||
|
_info = info;
|
||||||
|
|
||||||
|
// we want to know about logon/logoff
|
||||||
|
_ctx.getClient().addClientObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean handleAction (ActionEvent action)
|
||||||
|
{
|
||||||
|
String cmd = action.getActionCommand();
|
||||||
|
|
||||||
|
if (cmd.equals(LOGOFF)) {
|
||||||
|
// request that we logoff
|
||||||
|
_ctx.getClient().logoff(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info("Unhandled action: " + action);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogon (Client client)
|
||||||
|
{
|
||||||
|
Log.info("Client did logon [client=" + client + "].");
|
||||||
|
|
||||||
|
// keep the body object around for stuff
|
||||||
|
_body = (BodyObject)client.getClientObject();
|
||||||
|
|
||||||
|
// have at it
|
||||||
|
createGame(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createGame (Client client)
|
||||||
|
{
|
||||||
|
GameConfig config = null;
|
||||||
|
try {
|
||||||
|
// create the game config object
|
||||||
|
config = (GameConfig)
|
||||||
|
Class.forName(_info.gameConfigClass).newInstance();
|
||||||
|
|
||||||
|
// get the simulator service and use it to request that our
|
||||||
|
// game be created
|
||||||
|
SimulatorService sservice = (SimulatorService)
|
||||||
|
client.requireService(SimulatorService.class);
|
||||||
|
sservice.createGame(
|
||||||
|
client, config, _info.simClass, _info.playerCount);
|
||||||
|
|
||||||
|
// our work here is done, as the location manager will move us
|
||||||
|
// into the game room straightaway
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Failed to instantiate game config " +
|
||||||
|
"[class=" + _info.gameConfigClass +
|
||||||
|
", error=" + e + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientObjectDidChange (Client client)
|
||||||
|
{
|
||||||
|
// regrab our body object
|
||||||
|
_body = (BodyObject)client.getClientObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogoff (Client client)
|
||||||
|
{
|
||||||
|
Log.info("Client did logoff [client=" + client + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
protected SimulatorFrame _frame;
|
||||||
|
protected SimulatorInfo _info;
|
||||||
|
protected BodyObject _body;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorFrame.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.samskivert.swing.Controller;
|
||||||
|
import com.samskivert.swing.ControllerProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the user interface for the Simulator client application.
|
||||||
|
*/
|
||||||
|
public interface SimulatorFrame extends ControllerProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a reference to the top-level frame that the simulator will
|
||||||
|
* use to display everything.
|
||||||
|
*/
|
||||||
|
public JFrame getFrame ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the panel that makes up the entire client display.
|
||||||
|
*/
|
||||||
|
public void setPanel (JPanel panel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the controller for the outermost scope. This controller will
|
||||||
|
* handle all actions that aren't handled by controllers of higher
|
||||||
|
* scope.
|
||||||
|
*/
|
||||||
|
public void setController (Controller controller);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorService.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.client;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to simulator invocation services.
|
||||||
|
*/
|
||||||
|
public interface SimulatorService extends InvocationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Requests that a new game be created.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param config the game config for the game to be created.
|
||||||
|
* @param simClass the class name of the simulant to create.
|
||||||
|
* @param playerCount the number of players in the game.
|
||||||
|
*/
|
||||||
|
public void createGame (Client client, GameConfig config,
|
||||||
|
String simClass, int playerCount);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorInfo.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.data;
|
||||||
|
|
||||||
|
public class SimulatorInfo
|
||||||
|
{
|
||||||
|
/** The game config classname. */
|
||||||
|
public String gameConfigClass;
|
||||||
|
|
||||||
|
/** The simulant classname. */
|
||||||
|
public String simClass;
|
||||||
|
|
||||||
|
/** The number of players in the game. */
|
||||||
|
public int playerCount;
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[gameConfigClass=" + gameConfigClass +
|
||||||
|
", simClass=" + simClass + ", playerCount=" + playerCount + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.data;
|
||||||
|
|
||||||
|
import com.threerings.micasa.simulator.client.SimulatorService;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the implementation of the {@link SimulatorService} interface
|
||||||
|
* that marshalls the arguments and delivers the request to the provider
|
||||||
|
* on the server. Also provides an implementation of the response listener
|
||||||
|
* interfaces that marshall the response arguments and deliver them back
|
||||||
|
* to the requesting client.
|
||||||
|
*/
|
||||||
|
public class SimulatorMarshaller extends InvocationMarshaller
|
||||||
|
implements SimulatorService
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #createGame} requests. */
|
||||||
|
public static final int CREATE_GAME = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void createGame (Client arg1, GameConfig arg2, String arg3, int arg4)
|
||||||
|
{
|
||||||
|
sendRequest(arg1, CREATE_GAME, new Object[] {
|
||||||
|
arg2, arg3, Integer.valueOf(arg4)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimpleServer.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import com.samskivert.util.ResultListener;
|
||||||
|
|
||||||
|
import com.threerings.micasa.server.MiCasaServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple simulator server implementation that extends the MiCasa server
|
||||||
|
* and provides no special functionality.
|
||||||
|
*/
|
||||||
|
public class SimpleServer extends MiCasaServer
|
||||||
|
implements SimulatorServer
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public void init (ResultListener obs)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
// create the simulator manager
|
||||||
|
SimulatorManager simmgr = new SimulatorManager();
|
||||||
|
simmgr.init(invmgr, plreg, clmgr, omgr, this);
|
||||||
|
|
||||||
|
if (obs != null) {
|
||||||
|
// let the initialization observer know that we've started up
|
||||||
|
obs.requestCompleted(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// $Id: Simulant.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DObjectManager;
|
||||||
|
import com.threerings.presents.dobj.MessageEvent;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.game.server.GameManager;
|
||||||
|
|
||||||
|
public abstract class Simulant
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the simulant with a body object and the game config for
|
||||||
|
* the game they'll be engaged in.
|
||||||
|
*/
|
||||||
|
public void init (BodyObject self, GameConfig config,
|
||||||
|
GameManager gmgr, DObjectManager omgr)
|
||||||
|
{
|
||||||
|
_self = self;
|
||||||
|
_config = config;
|
||||||
|
_gmgr = gmgr;
|
||||||
|
_omgr = omgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the simulant is about to enter the room in which it
|
||||||
|
* will be doing all of its business. Default implementation
|
||||||
|
* immediately notifies the game manager that the simulant is ready to
|
||||||
|
* play. Sub-classes may wish to override this to do things like
|
||||||
|
* subscribe to the game object, but should be sure to call this
|
||||||
|
* method when they're finished to give the game manager the go-ahead
|
||||||
|
* to proceed.
|
||||||
|
*/
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
// let the game manager know that the simulant's ready
|
||||||
|
_gmgr.playerReady(_self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts the given message event to the server. Since the simulant
|
||||||
|
* resides within the server itself, it has no available client
|
||||||
|
* distributed object manager and so we must set up the source oid
|
||||||
|
* ourselves before sending it on its merry way. Sub-classes should
|
||||||
|
* accordingly be sure to make use of this method to send any
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
protected void postEvent (MessageEvent mevt)
|
||||||
|
{
|
||||||
|
mevt.setSourceOid(_self.getOid());
|
||||||
|
_omgr.postEvent(mevt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The game config object. */
|
||||||
|
protected GameConfig _config;
|
||||||
|
|
||||||
|
/** The game manager for the game we're playing. */
|
||||||
|
protected GameManager _gmgr;
|
||||||
|
|
||||||
|
/** Our body object. */
|
||||||
|
protected BodyObject _self;
|
||||||
|
|
||||||
|
/** The object manager with which we're interacting. */
|
||||||
|
protected DObjectManager _omgr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import com.threerings.micasa.simulator.client.SimulatorService;
|
||||||
|
import com.threerings.micasa.simulator.data.SimulatorMarshaller;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.server.InvocationDispatcher;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches requests to the {@link SimulatorProvider}.
|
||||||
|
*/
|
||||||
|
public class SimulatorDispatcher extends InvocationDispatcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a dispatcher that may be registered to dispatch invocation
|
||||||
|
* service requests for the specified provider.
|
||||||
|
*/
|
||||||
|
public SimulatorDispatcher (SimulatorProvider provider)
|
||||||
|
{
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public InvocationMarshaller createMarshaller ()
|
||||||
|
{
|
||||||
|
return new SimulatorMarshaller();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchRequest (
|
||||||
|
ClientObject source, int methodId, Object[] args)
|
||||||
|
throws InvocationException
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case SimulatorMarshaller.CREATE_GAME:
|
||||||
|
((SimulatorProvider)provider).createGame(
|
||||||
|
source,
|
||||||
|
(GameConfig)args[0], (String)args[1], ((Integer)args[2]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchRequest(source, methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorManager.java 3758 2005-11-10 23:18:58Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.dobj.RootDObjectManager;
|
||||||
|
import com.threerings.presents.server.ClientManager;
|
||||||
|
import com.threerings.presents.server.ClientResolutionListener;
|
||||||
|
import com.threerings.presents.server.InvocationManager;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.crowd.server.PlaceManager;
|
||||||
|
import com.threerings.crowd.server.PlaceRegistry.CreationObserver;
|
||||||
|
import com.threerings.crowd.server.PlaceRegistry;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameAI;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.game.data.GameObject;
|
||||||
|
import com.threerings.parlor.game.server.GameManager;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The simulator manager is responsible for handling the simulator
|
||||||
|
* services on the server side.
|
||||||
|
*/
|
||||||
|
public class SimulatorManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the simulator manager manager. This should be called by
|
||||||
|
* the server that is making use of the simulator services on the
|
||||||
|
* single instance of simulator manager that it has created.
|
||||||
|
*
|
||||||
|
* @param invmgr a reference to the invocation manager in use by this
|
||||||
|
* server.
|
||||||
|
*/
|
||||||
|
public void init (InvocationManager invmgr, PlaceRegistry plreg,
|
||||||
|
ClientManager clmgr, RootDObjectManager omgr,
|
||||||
|
SimulatorServer simserv)
|
||||||
|
{
|
||||||
|
// register our simulator provider
|
||||||
|
SimulatorProvider sprov = new SimulatorProvider(this);
|
||||||
|
invmgr.registerDispatcher(new SimulatorDispatcher(sprov), true);
|
||||||
|
|
||||||
|
// keep these for later
|
||||||
|
_plreg = plreg;
|
||||||
|
_clmgr = clmgr;
|
||||||
|
_omgr = omgr;
|
||||||
|
_simserv = simserv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a game along with the specified number of simulant players
|
||||||
|
* and forcibly moves all players into the game room.
|
||||||
|
*/
|
||||||
|
public void createGame (
|
||||||
|
BodyObject source, GameConfig config, String simClass, int playerCount)
|
||||||
|
{
|
||||||
|
new CreateGameTask(source, config, simClass, playerCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateGameTask implements CreationObserver
|
||||||
|
{
|
||||||
|
public CreateGameTask (
|
||||||
|
BodyObject source, GameConfig config, String simClass,
|
||||||
|
int playerCount)
|
||||||
|
{
|
||||||
|
// save off game request info
|
||||||
|
_source = source;
|
||||||
|
_config = config;
|
||||||
|
_simClass = simClass;
|
||||||
|
_playerCount = playerCount;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// create the game manager and begin its initialization
|
||||||
|
// process. the game manager will take care of notifying
|
||||||
|
// the players that the game has been created once it has
|
||||||
|
// been started up (which is done by the place registry
|
||||||
|
// once the game object creation has completed)
|
||||||
|
|
||||||
|
// configure the game config with the player names
|
||||||
|
config.players = new Name[_playerCount];
|
||||||
|
config.players[0] = _source.getVisibleName();
|
||||||
|
for (int ii = 1; ii < _playerCount; ii++) {
|
||||||
|
config.players[ii] = new Name("simulant" + ii);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we needn't hang around and wait for game object
|
||||||
|
// creation if it's just us
|
||||||
|
CreationObserver obs = (_playerCount == 1) ? null : this;
|
||||||
|
_gmgr = (GameManager)_plreg.createPlace(config, obs);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to create game manager [e=" + e + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void placeCreated (PlaceObject place, PlaceManager pmgr)
|
||||||
|
{
|
||||||
|
// cast the place to the game object for the game we're creating
|
||||||
|
_gobj = (GameObject)place;
|
||||||
|
|
||||||
|
// determine the AI player skill level
|
||||||
|
byte skill;
|
||||||
|
try {
|
||||||
|
skill = Byte.parseByte(System.getProperty("skill"));
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
skill = DEFAULT_SKILL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int ii = 1; ii < _playerCount; ii++) {
|
||||||
|
// mark all simulants as AI players
|
||||||
|
_gmgr.setAI(ii, new GameAI(0, skill));
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve the simulant body objects
|
||||||
|
ClientResolutionListener listener = new ClientResolutionListener()
|
||||||
|
{
|
||||||
|
public void clientResolved (Name username, ClientObject clobj)
|
||||||
|
{
|
||||||
|
// hold onto the body object for later game creation
|
||||||
|
_sims.add(clobj);
|
||||||
|
|
||||||
|
// create the game if we've received all body objects
|
||||||
|
if (_sims.size() == (_playerCount - 1)) {
|
||||||
|
createSimulants();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resolutionFailed (Name username, Exception cause)
|
||||||
|
{
|
||||||
|
Log.warning("Unable to create simulant body object " +
|
||||||
|
"[error=" + cause + "].");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// resolve client objects for all of our simulants
|
||||||
|
for (int ii = 1; ii < _playerCount; ii++) {
|
||||||
|
Name username = new Name("simulant" + ii);
|
||||||
|
_clmgr.resolveClientObject(username, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when all simulant body objects are present and the
|
||||||
|
* simulants are ready to be created.
|
||||||
|
*/
|
||||||
|
protected void createSimulants ()
|
||||||
|
{
|
||||||
|
// finish setting up the simulants
|
||||||
|
for (int ii = 1; ii < _playerCount; ii++) {
|
||||||
|
// create the simulant object
|
||||||
|
Simulant sim;
|
||||||
|
try {
|
||||||
|
sim = (Simulant)Class.forName(_simClass).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to create simulant " +
|
||||||
|
"[class=" + _simClass + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// give the simulant its body
|
||||||
|
BodyObject bobj = (BodyObject)_sims.get(ii - 1);
|
||||||
|
sim.init(bobj, _config, _gmgr, _omgr);
|
||||||
|
|
||||||
|
// give the simulant a chance to engage in place antics
|
||||||
|
sim.willEnterPlace(_gobj);
|
||||||
|
|
||||||
|
// move the simulant into the game room since they have no
|
||||||
|
// location director to move them automagically
|
||||||
|
try {
|
||||||
|
_plreg.locprov.moveTo(bobj, _gobj.getOid());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Failed to move simulant into room " +
|
||||||
|
"[e=" + e + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The simulant body objects. */
|
||||||
|
protected ArrayList _sims = new ArrayList();
|
||||||
|
|
||||||
|
/** The game object for the game being created. */
|
||||||
|
protected GameObject _gobj;
|
||||||
|
|
||||||
|
/** The game manager for the game being created. */
|
||||||
|
protected GameManager _gmgr;
|
||||||
|
|
||||||
|
/** The number of players in the game. */
|
||||||
|
protected int _playerCount;
|
||||||
|
|
||||||
|
/** The simulant class instantiated on game creation. */
|
||||||
|
protected String _simClass;
|
||||||
|
|
||||||
|
/** The game config object. */
|
||||||
|
protected GameConfig _config;
|
||||||
|
|
||||||
|
/** The body object of the player requesting the game creation. */
|
||||||
|
protected BodyObject _source;
|
||||||
|
}
|
||||||
|
|
||||||
|
// needed for general operation
|
||||||
|
protected PlaceRegistry _plreg;
|
||||||
|
protected ClientManager _clmgr;
|
||||||
|
protected RootDObjectManager _omgr;
|
||||||
|
protected SimulatorServer _simserv;
|
||||||
|
|
||||||
|
/** The default skill level for AI players. */
|
||||||
|
protected static final byte DEFAULT_SKILL = 50;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorProvider.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.server.InvocationProvider;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
import com.threerings.micasa.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The simulator provider handles game creation requests on the server
|
||||||
|
* side, passing them off to the {@link SimulatorManager}.
|
||||||
|
*/
|
||||||
|
public class SimulatorProvider
|
||||||
|
implements InvocationProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a simulator provider.
|
||||||
|
*/
|
||||||
|
public SimulatorProvider (SimulatorManager simmgr)
|
||||||
|
{
|
||||||
|
_simmgr = simmgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a request from the client to create a new game.
|
||||||
|
*/
|
||||||
|
public void createGame (ClientObject caller, GameConfig config,
|
||||||
|
String simClass, int playerCount)
|
||||||
|
{
|
||||||
|
Log.info("handleCreateGameRequest [caller=" + caller.who() +
|
||||||
|
", config=" + config + ", simClass=" + simClass +
|
||||||
|
", playerCount=" + playerCount + "].");
|
||||||
|
|
||||||
|
_simmgr.createGame((BodyObject)caller, config, simClass, playerCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The simulator manager. */
|
||||||
|
protected SimulatorManager _simmgr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorServer.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.server;
|
||||||
|
|
||||||
|
import com.samskivert.util.ResultListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The simulator manager needs a mechanism for faking body object
|
||||||
|
* registrations, which is provided by implementations of this interface.
|
||||||
|
*/
|
||||||
|
public interface SimulatorServer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called to initialize this server instance.
|
||||||
|
*
|
||||||
|
* @param obs the observer to notify when the server has finished
|
||||||
|
* starting up, or <code>null</code> if no notification is desired.
|
||||||
|
*
|
||||||
|
* @exception Exception thrown if anything goes wrong initializing the
|
||||||
|
* server.
|
||||||
|
*/
|
||||||
|
public void init (ResultListener obs) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to perform the main body of server processing. This is
|
||||||
|
* called from the server thread and should do the simulator server's
|
||||||
|
* primary business.
|
||||||
|
*/
|
||||||
|
public void run ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// $Id: SimulatorContext.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.simulator.util;
|
||||||
|
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
import com.threerings.micasa.simulator.client.SimulatorFrame;
|
||||||
|
import com.threerings.micasa.simulator.data.SimulatorInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The simulator context encapsulates the contexts of all of the services
|
||||||
|
* that are used by the simulator client so that we can pass around one
|
||||||
|
* single context implementation that provides all of the necessary
|
||||||
|
* components to all of the services in use.
|
||||||
|
*/
|
||||||
|
public interface SimulatorContext
|
||||||
|
extends ParlorContext
|
||||||
|
{
|
||||||
|
/** Returns a reference to the primary user interface frame. */
|
||||||
|
public SimulatorFrame getFrame ();
|
||||||
|
|
||||||
|
/** Returns a reference to the simulator info describing the game and
|
||||||
|
* other details of the simulation. */
|
||||||
|
public SimulatorInfo getSimulatorInfo ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// $Id: MiCasaContext.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.micasa.util;
|
||||||
|
|
||||||
|
import com.threerings.util.MessageManager;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
import com.threerings.micasa.client.MiCasaFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The micasa context encapsulates the contexts of all of the services
|
||||||
|
* that are used by the micasa client so that we can pass around one
|
||||||
|
* single context implementation that provides all of the necessary
|
||||||
|
* components to all of the services in use.
|
||||||
|
*/
|
||||||
|
public interface MiCasaContext
|
||||||
|
extends ParlorContext
|
||||||
|
{
|
||||||
|
/** Returns a reference to the primary user interface frame. This can
|
||||||
|
* be used to set the top-level panel when we enter a game, etc. */
|
||||||
|
public MiCasaFrame getFrame ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the message manager used by the client to
|
||||||
|
* generate localized messages.
|
||||||
|
*/
|
||||||
|
public MessageManager getMessageManager ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// $Id: Log.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A placeholder class that contains a reference to the log object used by
|
||||||
|
* the Parlor services.
|
||||||
|
*/
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
public static com.samskivert.util.Log log =
|
||||||
|
new com.samskivert.util.Log("parlor");
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void debug (String message)
|
||||||
|
{
|
||||||
|
log.debug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void info (String message)
|
||||||
|
{
|
||||||
|
log.info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void warning (String message)
|
||||||
|
{
|
||||||
|
log.warning(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void logStackTrace (Throwable t)
|
||||||
|
{
|
||||||
|
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// $Id: Log.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A placeholder class that contains a reference to the log object used by
|
||||||
|
* the Card services.
|
||||||
|
*/
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
public static com.samskivert.util.Log log =
|
||||||
|
new com.samskivert.util.Log("card");
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void debug (String message)
|
||||||
|
{
|
||||||
|
log.debug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void info (String message)
|
||||||
|
{
|
||||||
|
log.info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void warning (String message)
|
||||||
|
{
|
||||||
|
log.warning(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convenience function. */
|
||||||
|
public static void logStackTrace (Throwable t)
|
||||||
|
{
|
||||||
|
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardGameController.java 4053 2006-04-25 00:49:58Z mthomas $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.Log;
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.CardCodes;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.parlor.game.client.GameController;
|
||||||
|
import com.threerings.parlor.turn.client.TurnGameController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A controller class for card games. Handles common functions like
|
||||||
|
* accepting dealt hands.
|
||||||
|
*/
|
||||||
|
public abstract class CardGameController extends GameController
|
||||||
|
implements TurnGameController, CardCodes, CardGameReceiver
|
||||||
|
{
|
||||||
|
// Documentation inherited.
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.willEnterPlace(plobj);
|
||||||
|
|
||||||
|
if (_ctx.getClient().getClientObject().receivers.containsKey(
|
||||||
|
CardGameDecoder.RECEIVER_CODE)) {
|
||||||
|
Log.warning("Yuh oh, we already have a card game receiver " +
|
||||||
|
"registered and are trying for another...!");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctx.getClient().getInvocationDirector().registerReceiver(
|
||||||
|
new CardGameDecoder(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void didLeavePlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.didLeavePlace(plobj);
|
||||||
|
|
||||||
|
_ctx.getClient().getInvocationDirector().unregisterReceiver(
|
||||||
|
CardGameDecoder.RECEIVER_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void turnDidChange (Name turnHolder)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by our sender to notify us of a received hand.
|
||||||
|
*/
|
||||||
|
public final void receivedHand (int oid, Hand hand)
|
||||||
|
{
|
||||||
|
if (oid == _gobj.getOid()) {
|
||||||
|
receivedHand(hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the server deals the client a new hand of cards. Default
|
||||||
|
* implementation does nothing.
|
||||||
|
*
|
||||||
|
* @param hand the hand dealt to the user
|
||||||
|
*/
|
||||||
|
public void receivedHand (Hand hand)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when it has received a set of cards
|
||||||
|
* from another player. Default implementation does nothing.
|
||||||
|
*
|
||||||
|
* @param plidx the index of the player providing the cards
|
||||||
|
* @param cards the cards received
|
||||||
|
*/
|
||||||
|
public void receivedCardsFromPlayer (int plidx, Card[] cards)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when the server has forced it to send
|
||||||
|
* a set of cards to another player. Default implementation does
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
|
* @param plidx the index of the player to which the cards were sent
|
||||||
|
* @param cards the cards sent
|
||||||
|
*/
|
||||||
|
public void sentCardsToPlayer (int plidx, Card[] cards)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when a set of cards is transferred between
|
||||||
|
* two other players in the game. Default implementation does nothing.
|
||||||
|
*
|
||||||
|
* @param fromidx the index of the player sending the cards
|
||||||
|
* @param toidx the index of the player receiving the cards
|
||||||
|
* @param cards the number of cards transferred
|
||||||
|
*/
|
||||||
|
public void cardsTransferredBetweenPlayers (int fromidx, int toidx,
|
||||||
|
int cards)
|
||||||
|
{}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.client.CardGameReceiver;
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.presents.client.InvocationDecoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches calls to a {@link CardGameReceiver} instance.
|
||||||
|
*/
|
||||||
|
public class CardGameDecoder extends InvocationDecoder
|
||||||
|
{
|
||||||
|
/** The generated hash code used to identify this receiver class. */
|
||||||
|
public static final String RECEIVER_CODE = "0718199d459e31d8d673744c71b0e788";
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link CardGameReceiver#cardsTransferredBetweenPlayers}
|
||||||
|
* notifications. */
|
||||||
|
public static final int CARDS_TRANSFERRED_BETWEEN_PLAYERS = 1;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link CardGameReceiver#receivedCardsFromPlayer}
|
||||||
|
* notifications. */
|
||||||
|
public static final int RECEIVED_CARDS_FROM_PLAYER = 2;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link CardGameReceiver#receivedHand}
|
||||||
|
* notifications. */
|
||||||
|
public static final int RECEIVED_HAND = 3;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link CardGameReceiver#sentCardsToPlayer}
|
||||||
|
* notifications. */
|
||||||
|
public static final int SENT_CARDS_TO_PLAYER = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a decoder that may be registered to dispatch invocation
|
||||||
|
* service notifications to the specified receiver.
|
||||||
|
*/
|
||||||
|
public CardGameDecoder (CardGameReceiver receiver)
|
||||||
|
{
|
||||||
|
this.receiver = receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public String getReceiverCode ()
|
||||||
|
{
|
||||||
|
return RECEIVER_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchNotification (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case CARDS_TRANSFERRED_BETWEEN_PLAYERS:
|
||||||
|
((CardGameReceiver)receiver).cardsTransferredBetweenPlayers(
|
||||||
|
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RECEIVED_CARDS_FROM_PLAYER:
|
||||||
|
((CardGameReceiver)receiver).receivedCardsFromPlayer(
|
||||||
|
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RECEIVED_HAND:
|
||||||
|
((CardGameReceiver)receiver).receivedHand(
|
||||||
|
((Integer)args[0]).intValue(), (Hand)args[1]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SENT_CARDS_TO_PLAYER:
|
||||||
|
((CardGameReceiver)receiver).sentCardsToPlayer(
|
||||||
|
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchNotification(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorReceiver.java 3099 2004-08-27 02:21:06Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.InvocationReceiver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines, for the card game services, a set of notifications delivered
|
||||||
|
* asynchronously by the server to the client.
|
||||||
|
*/
|
||||||
|
public interface CardGameReceiver extends InvocationReceiver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when it has received a hand of cards.
|
||||||
|
*
|
||||||
|
* @param oid the oid of the game for which this hand applies
|
||||||
|
* @param hand the received hand
|
||||||
|
*/
|
||||||
|
public void receivedHand (int oid, Hand hand);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when it has received a set of cards
|
||||||
|
* from another player.
|
||||||
|
*
|
||||||
|
* @param plidx the index of the player providing the cards
|
||||||
|
* @param cards the cards received
|
||||||
|
*/
|
||||||
|
public void receivedCardsFromPlayer (int plidx, Card[] cards);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when the server has forced it to send
|
||||||
|
* a set of cards to another player.
|
||||||
|
*
|
||||||
|
* @param plidx the index of the player to which the cards were sent
|
||||||
|
* @param cards the cards sent
|
||||||
|
*/
|
||||||
|
public void sentCardsToPlayer (int plidx, Card[] cards);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when a set of cards is transferred between
|
||||||
|
* two other players in the game.
|
||||||
|
*
|
||||||
|
* @param fromidx the index of the player sending the cards
|
||||||
|
* @param toidx the index of the player receiving the cards
|
||||||
|
* @param cards the number of cards transferred
|
||||||
|
*/
|
||||||
|
public void cardsTransferredBetweenPlayers (int fromidx, int toidx,
|
||||||
|
int cards);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,252 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardSprite.java 3819 2006-01-24 19:46:34Z mthomas $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
|
||||||
|
import com.threerings.media.image.Mirage;
|
||||||
|
import com.threerings.media.sprite.FadableImageSprite;
|
||||||
|
import com.threerings.media.util.Path;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sprite representing a playing card.
|
||||||
|
*/
|
||||||
|
public class CardSprite extends FadableImageSprite
|
||||||
|
implements Comparable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new upward-facing card sprite.
|
||||||
|
*
|
||||||
|
* @param panel the panel responsible for the sprite
|
||||||
|
* @param card the card to depict (can be null, in which case the
|
||||||
|
* card back will be shown)
|
||||||
|
*/
|
||||||
|
public CardSprite (CardPanel panel, Card card)
|
||||||
|
{
|
||||||
|
_panel = panel;
|
||||||
|
_card = card;
|
||||||
|
_facingUp = true;
|
||||||
|
|
||||||
|
updateMirage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new card sprite.
|
||||||
|
*
|
||||||
|
* @param panel the panel responsible for the sprite
|
||||||
|
* @param card the card to depict
|
||||||
|
* @param facingUp whether or not the card should be facing up
|
||||||
|
*/
|
||||||
|
public CardSprite (CardPanel panel, Card card, boolean facingUp)
|
||||||
|
{
|
||||||
|
_panel = panel;
|
||||||
|
_card = card;
|
||||||
|
_facingUp = facingUp;
|
||||||
|
|
||||||
|
updateMirage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the card to depict.
|
||||||
|
*
|
||||||
|
* @param card the new card
|
||||||
|
*/
|
||||||
|
public void setCard (Card card)
|
||||||
|
{
|
||||||
|
_card = card;
|
||||||
|
|
||||||
|
updateMirage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the card being depicted.
|
||||||
|
*
|
||||||
|
* @return the current card
|
||||||
|
*/
|
||||||
|
public Card getCard ()
|
||||||
|
{
|
||||||
|
return _card;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns this card up or down.
|
||||||
|
*
|
||||||
|
* @param facingUp whether or not the card should be facing up
|
||||||
|
*/
|
||||||
|
public void setFacingUp (boolean facingUp)
|
||||||
|
{
|
||||||
|
_facingUp = facingUp;
|
||||||
|
|
||||||
|
updateMirage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this card is facing up or down.
|
||||||
|
*
|
||||||
|
* @return true if the card is facing up, false if facing down
|
||||||
|
*/
|
||||||
|
public boolean isFacingUp ()
|
||||||
|
{
|
||||||
|
return _facingUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether or not the user can drag this card around the board.
|
||||||
|
*
|
||||||
|
* @param draggable whether or not the user can drag the card
|
||||||
|
*/
|
||||||
|
public void setDraggable (boolean draggable)
|
||||||
|
{
|
||||||
|
_draggable = draggable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether or not the user can drag this card.
|
||||||
|
*
|
||||||
|
* @return true if the user can drag the card, false if not
|
||||||
|
*/
|
||||||
|
public boolean isDraggable ()
|
||||||
|
{
|
||||||
|
return _draggable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flip the card from its current displayed card to the specified card.
|
||||||
|
*/
|
||||||
|
public void flip (Card newCard, long duration)
|
||||||
|
{
|
||||||
|
_flipStamp = 0;
|
||||||
|
_flipDuration = duration;
|
||||||
|
_flipCard = newCard;
|
||||||
|
|
||||||
|
_scaleFactor = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void tick (long tickStamp)
|
||||||
|
{
|
||||||
|
super.tick(tickStamp);
|
||||||
|
|
||||||
|
// Take care of any flipping we might be doing.
|
||||||
|
if (_flipDuration != -1) {
|
||||||
|
if (_flipStamp == 0) {
|
||||||
|
_flipStamp = tickStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
long diff = tickStamp - _flipStamp;
|
||||||
|
|
||||||
|
// Set the new scale while we're flipping
|
||||||
|
if (diff < _flipDuration/2) {
|
||||||
|
_scaleFactor = 1.0 - ((float)diff*2)/_flipDuration;
|
||||||
|
} else {
|
||||||
|
// Switch the image to the card we're flipping to.
|
||||||
|
if (_flipCard != null) {
|
||||||
|
setCard(_flipCard);
|
||||||
|
_flipCard = null;
|
||||||
|
}
|
||||||
|
_scaleFactor = ((float)diff*2)/_flipDuration - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're done, stop flipping.
|
||||||
|
if (_scaleFactor > 1.0) {
|
||||||
|
_scaleFactor = 1.0;
|
||||||
|
_flipDuration = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we flag our location as needing redrawing
|
||||||
|
if (_mgr != null) {
|
||||||
|
_mgr.getRegionManager().invalidateRegion(_bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void paint (Graphics2D gfx)
|
||||||
|
{
|
||||||
|
if (_scaleFactor <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we are flipping the card, scale it horizontally.
|
||||||
|
AffineTransform otrans = gfx.getTransform();
|
||||||
|
if (_scaleFactor < 1.0) {
|
||||||
|
int xtrans = getX() + getWidth()/2;
|
||||||
|
gfx.translate(xtrans, 0);
|
||||||
|
gfx.scale(_scaleFactor, 1.0);
|
||||||
|
gfx.translate(-xtrans, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paint(gfx);
|
||||||
|
|
||||||
|
gfx.setTransform(otrans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this to another card sprite based on their cards.
|
||||||
|
*/
|
||||||
|
public int compareTo (Object other)
|
||||||
|
{
|
||||||
|
CardSprite cs = (CardSprite)other;
|
||||||
|
if (_card == null || cs._card == null) {
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return _card.compareTo(cs._card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the mirage according to the current state.
|
||||||
|
*/
|
||||||
|
protected void updateMirage ()
|
||||||
|
{
|
||||||
|
setMirage((_card != null && _facingUp ) ?
|
||||||
|
_panel.getCardImage(_card) : _panel.getCardBackImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The panel responsible for the sprite. */
|
||||||
|
protected CardPanel _panel;
|
||||||
|
|
||||||
|
/** The depicted card. */
|
||||||
|
protected Card _card;
|
||||||
|
|
||||||
|
/** Whether or not the card is facing up. */
|
||||||
|
protected boolean _facingUp;
|
||||||
|
|
||||||
|
/** Whether or not the user can drag the card around the board. */
|
||||||
|
protected boolean _draggable;
|
||||||
|
|
||||||
|
/** The horizontal scale factor used while flipping the card. */
|
||||||
|
protected double _scaleFactor = 1.0;
|
||||||
|
|
||||||
|
/** If flipping, how long the current flip should take (otherwise -1). */
|
||||||
|
protected long _flipDuration;
|
||||||
|
|
||||||
|
/** The timestamp for when we started flipping the card. */
|
||||||
|
protected long _flipStamp;
|
||||||
|
|
||||||
|
/** The card which will be revealed when we're done flipping. */
|
||||||
|
protected Card _flipCard;
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardSpriteObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observer interface for (draggable) card sprites.
|
||||||
|
*/
|
||||||
|
public interface CardSpriteObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Notifies the observer that the user clicked a card sprite.
|
||||||
|
*
|
||||||
|
* @param sprite the dragged sprite
|
||||||
|
* @param me the mouse event associated with the drag
|
||||||
|
*/
|
||||||
|
public void cardSpriteClicked (CardSprite sprite, MouseEvent me);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the observer that the user moved the mouse pointer onto
|
||||||
|
* a card sprite.
|
||||||
|
*
|
||||||
|
* @param sprite the entered sprite
|
||||||
|
* @param me the mouse event associated with the entrance
|
||||||
|
*/
|
||||||
|
public void cardSpriteEntered (CardSprite sprite, MouseEvent me);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the observer that the user moved the mouse pointer off of
|
||||||
|
* a card sprite.
|
||||||
|
*
|
||||||
|
* @param sprite the exited the sprite
|
||||||
|
* @param me the mouse event associated with the exit
|
||||||
|
*/
|
||||||
|
public void cardSpriteExited (CardSprite sprite, MouseEvent me);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the observer that the user dragged a card sprite to a new
|
||||||
|
* location.
|
||||||
|
*
|
||||||
|
* @param sprite the dragged sprite
|
||||||
|
* @param me the mouse event associated with the drag
|
||||||
|
*/
|
||||||
|
public void cardSpriteDragged (CardSprite sprite, MouseEvent me);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
|
||||||
|
public class MicroCardSprite extends CardSprite
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new upward-facing micro-card sprite.
|
||||||
|
*
|
||||||
|
* @param panel the panel responsible for the sprite
|
||||||
|
* @param card the card to depict (can be null, in which case the
|
||||||
|
* card back will be shown)
|
||||||
|
*/
|
||||||
|
public MicroCardSprite (CardPanel panel, Card card)
|
||||||
|
{
|
||||||
|
super(panel, card);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new micro-card sprite.
|
||||||
|
*
|
||||||
|
* @param panel the panel responsible for the sprite
|
||||||
|
* @param card the card to depict
|
||||||
|
* @param facingUp whether or not the card should be facing up
|
||||||
|
*/
|
||||||
|
public MicroCardSprite (CardPanel panel, Card card, boolean facingUp)
|
||||||
|
{
|
||||||
|
super(panel, card, facingUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the mirage according to the current state.
|
||||||
|
*/
|
||||||
|
protected void updateMirage ()
|
||||||
|
{
|
||||||
|
setMirage((_card != null && _facingUp ) ?
|
||||||
|
_panel.getMicroCardImage(_card) : _panel.getMicroCardBackImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
//
|
||||||
|
// $Id: Card.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.threerings.io.ObjectInputStream;
|
||||||
|
import com.threerings.io.ObjectOutputStream;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instances of this class represent individual playing cards.
|
||||||
|
*/
|
||||||
|
public class Card implements DSet.Entry, Comparable, CardCodes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* No-arg constructor for deserialization.
|
||||||
|
*/
|
||||||
|
public Card ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new card.
|
||||||
|
*
|
||||||
|
* @param number the number of the card
|
||||||
|
* @param suit the suit of the card
|
||||||
|
*/
|
||||||
|
public Card (int number, int suit)
|
||||||
|
{
|
||||||
|
_value = (byte)((suit << 5) | number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the card, either from 2 to 11 or
|
||||||
|
* KING, QUEEN, JACK, ACE, RED_JOKER, or BLACK_JOKER.
|
||||||
|
*
|
||||||
|
* @return the value of the card
|
||||||
|
*/
|
||||||
|
public int getNumber ()
|
||||||
|
{
|
||||||
|
return (_value & 0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the suit of the card: SPADES, HEARTS, DIAMONDS, or
|
||||||
|
* CLUBS. If the card is the joker, the suit is undefined.
|
||||||
|
*
|
||||||
|
* @return the suit of the card
|
||||||
|
*/
|
||||||
|
public int getSuit ()
|
||||||
|
{
|
||||||
|
return (_value >> 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the card is a number card (2 to 10).
|
||||||
|
*
|
||||||
|
* @return true if the card is a number card, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isNumber ()
|
||||||
|
{
|
||||||
|
int number = getNumber();
|
||||||
|
|
||||||
|
return number >= 2 && number <= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the card is a face card (KING, QUEEN, or JACK).
|
||||||
|
*
|
||||||
|
* @return true if the card is a face card, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isFace ()
|
||||||
|
{
|
||||||
|
int number = getNumber();
|
||||||
|
|
||||||
|
return number == KING || number == QUEEN || number == JACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the card is an ace.
|
||||||
|
*
|
||||||
|
* @return true if the card is an ace, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isAce ()
|
||||||
|
{
|
||||||
|
return getNumber() == ACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the card is a joker.
|
||||||
|
*
|
||||||
|
* @return true if the card is a joker, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isJoker ()
|
||||||
|
{
|
||||||
|
int number = getNumber();
|
||||||
|
|
||||||
|
return number == RED_JOKER || number == BLACK_JOKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether or not this card is valid. The no-arg public
|
||||||
|
* constructor for deserialization creates an invalid card.
|
||||||
|
*
|
||||||
|
* @return true if this card is valid, false if not
|
||||||
|
*/
|
||||||
|
public boolean isValid ()
|
||||||
|
{
|
||||||
|
int number = getNumber(), suit = getSuit();
|
||||||
|
|
||||||
|
return number == RED_JOKER || number == BLACK_JOKER ||
|
||||||
|
(number >= 2 && number <= ACE &&
|
||||||
|
suit >= SPADES && suit <= DIAMONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public Comparable getKey ()
|
||||||
|
{
|
||||||
|
if (_key == null) {
|
||||||
|
_key = Byte.valueOf(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code for this card.
|
||||||
|
*
|
||||||
|
* @return this card's hash code
|
||||||
|
*/
|
||||||
|
public int hashCode ()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks this card for equality with another.
|
||||||
|
*
|
||||||
|
* @param other the other card to compare
|
||||||
|
* @return true if the cards are equal, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
if (other instanceof Card) {
|
||||||
|
return _value == ((Card)other)._value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this card to another. The card order is the same as the
|
||||||
|
* initial deck ordering: two through ten, jack, queen, king, ace for
|
||||||
|
* spades, hearts, clubs, and diamonds, then the red joker and the
|
||||||
|
* black joker.
|
||||||
|
*
|
||||||
|
* @param other the other card to compare this to
|
||||||
|
* @return -1, 0, or +1, depending on whether this card is less than,
|
||||||
|
* equal to, or greater than the other card
|
||||||
|
*/
|
||||||
|
public int compareTo (Object other)
|
||||||
|
{
|
||||||
|
int otherValue = ((Card)other)._value;
|
||||||
|
|
||||||
|
if (_value > otherValue) {
|
||||||
|
return +1;
|
||||||
|
} else if(_value < otherValue) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this card.
|
||||||
|
*
|
||||||
|
* @return a description of this card
|
||||||
|
*/
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
int number = getNumber();
|
||||||
|
|
||||||
|
if (number == RED_JOKER) {
|
||||||
|
return "RJ";
|
||||||
|
}
|
||||||
|
else if (number == BLACK_JOKER) {
|
||||||
|
return "BJ";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (number >= 2 && number <= 9) {
|
||||||
|
sb.append(Integer.toString(number));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (number) {
|
||||||
|
case 10: sb.append('T'); break;
|
||||||
|
case JACK: sb.append('J'); break;
|
||||||
|
case QUEEN: sb.append('Q'); break;
|
||||||
|
case KING: sb.append('K'); break;
|
||||||
|
case ACE: sb.append('A'); break;
|
||||||
|
default: sb.append('?'); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (getSuit()) {
|
||||||
|
case SPADES: sb.append('s'); break;
|
||||||
|
case HEARTS: sb.append('h'); break;
|
||||||
|
case CLUBS: sb.append('c'); break;
|
||||||
|
case DIAMONDS: sb.append('d'); break;
|
||||||
|
default: sb.append('?'); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The number of the card. */
|
||||||
|
protected byte _value;
|
||||||
|
|
||||||
|
/** The comparison key. */
|
||||||
|
protected transient Byte _key;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardCodes.java 3224 2004-11-19 19:04:56Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.InvocationCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants relating to the card services.
|
||||||
|
*/
|
||||||
|
public interface CardCodes extends InvocationCodes
|
||||||
|
{
|
||||||
|
/** The suit of spades. */
|
||||||
|
public static final int SPADES = 0;
|
||||||
|
|
||||||
|
/** The suit of hearts. */
|
||||||
|
public static final int HEARTS = 1;
|
||||||
|
|
||||||
|
/** The suit of clubs. */
|
||||||
|
public static final int CLUBS = 2;
|
||||||
|
|
||||||
|
/** The suit of diamonds. */
|
||||||
|
public static final int DIAMONDS = 3;
|
||||||
|
|
||||||
|
/** The number of the jack. */
|
||||||
|
public static final int JACK = 11;
|
||||||
|
|
||||||
|
/** The number of the queen. */
|
||||||
|
public static final int QUEEN = 12;
|
||||||
|
|
||||||
|
/** The number of the king. */
|
||||||
|
public static final int KING = 13;
|
||||||
|
|
||||||
|
/** The number of the ace. */
|
||||||
|
public static final int ACE = 14;
|
||||||
|
|
||||||
|
/** The number of the red joker. */
|
||||||
|
public static final int RED_JOKER = 15;
|
||||||
|
|
||||||
|
/** The number of the black joker. */
|
||||||
|
public static final int BLACK_JOKER = 16;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// $Id: TurnGameObject.java 3099 2004-08-27 02:21:06Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game object class for card games.
|
||||||
|
*/
|
||||||
|
public class CardGameObject extends GameObject
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// $Id: Deck.java 3713 2005-09-27 21:58:10Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.threerings.util.StreamableArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instances of this class represent decks of cards.
|
||||||
|
*/
|
||||||
|
public class Deck extends StreamableArrayList
|
||||||
|
implements CardCodes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Default constructor creates an unshuffled deck of cards without
|
||||||
|
* jokers.
|
||||||
|
*/
|
||||||
|
public Deck ()
|
||||||
|
{
|
||||||
|
reset(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param includeJokers whether or not to include the two jokers
|
||||||
|
* in the deck
|
||||||
|
*/
|
||||||
|
public Deck (boolean includeJokers)
|
||||||
|
{
|
||||||
|
reset(includeJokers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the deck to its initial state: an unshuffled deck of
|
||||||
|
* 52 or 54 cards, depending on whether the jokers are included.
|
||||||
|
*
|
||||||
|
* @param includeJokers whether or not to include the two jokers
|
||||||
|
* in the deck
|
||||||
|
*/
|
||||||
|
public void reset (boolean includeJokers)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for (int i = SPADES; i <= DIAMONDS; i++) {
|
||||||
|
for (int j = 2; j <= ACE; j++) {
|
||||||
|
add(new Card(j, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeJokers) {
|
||||||
|
add(new Card(RED_JOKER, 3));
|
||||||
|
add(new Card(BLACK_JOKER, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffles the deck.
|
||||||
|
*/
|
||||||
|
public void shuffle ()
|
||||||
|
{
|
||||||
|
Collections.shuffle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals a hand of cards from the deck.
|
||||||
|
*
|
||||||
|
* @param size the size of the hand to deal
|
||||||
|
* @return the newly created and populated hand, or null
|
||||||
|
* if there are not enough cards in the deck to deal the hand
|
||||||
|
*/
|
||||||
|
public Hand dealHand (int size)
|
||||||
|
{
|
||||||
|
int dsize = size();
|
||||||
|
if (dsize < size) {
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Hand hand = new Hand();
|
||||||
|
|
||||||
|
// use a sublist view to manipulate the top of the deck
|
||||||
|
List sublist = subList(dsize - size, dsize);
|
||||||
|
hand.addAll(sublist);
|
||||||
|
sublist.clear();
|
||||||
|
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hand of cards to the deck.
|
||||||
|
*
|
||||||
|
* @param hand the hand of cards to return
|
||||||
|
*/
|
||||||
|
public void returnHand (Hand hand)
|
||||||
|
{
|
||||||
|
addAll(hand);
|
||||||
|
hand.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// $Id: Hand.java 3813 2006-01-19 21:50:53Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import com.threerings.util.StreamableArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instances of this class represent hands of cards.
|
||||||
|
*/
|
||||||
|
public class Hand extends StreamableArrayList
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Adds all of the specified cards to this hand.
|
||||||
|
*/
|
||||||
|
public void addAll (Card[] cards)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards.length; i++) {
|
||||||
|
add(cards[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all of the specified cards from this hand.
|
||||||
|
*/
|
||||||
|
public void removeAll (Card[] cards)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards.length; i++) {
|
||||||
|
remove(cards[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this hand contains all of the specified cards.
|
||||||
|
*/
|
||||||
|
public boolean containsAll (Card[] cards)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards.length; i++) {
|
||||||
|
if (!contains(cards[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the members of a particular suit within this hand.
|
||||||
|
*
|
||||||
|
* @param suit the suit of interest
|
||||||
|
* @return the number of cards in the specified suit
|
||||||
|
*/
|
||||||
|
public int getSuitMemberCount (int suit)
|
||||||
|
{
|
||||||
|
int len = size(), members = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (((Card)get(i)).getSuit() == suit) {
|
||||||
|
members++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of the cards in this hand.
|
||||||
|
*/
|
||||||
|
public Card[] getCards ()
|
||||||
|
{
|
||||||
|
Card[] cards = new Card[size()];
|
||||||
|
toArray(cards);
|
||||||
|
return cards;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// $Id: TrickCardGameObject.java 3382 2005-03-03 19:55:35Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.data;
|
||||||
|
|
||||||
|
import com.threerings.io.Streamable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pairs a player index with the card that the player played in the trick.
|
||||||
|
*/
|
||||||
|
public class PlayerCard implements Streamable
|
||||||
|
{
|
||||||
|
/** The index of the player. */
|
||||||
|
public int pidx;
|
||||||
|
|
||||||
|
/** The card that the player played. */
|
||||||
|
public Card card;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-argument constructor for deserialization.
|
||||||
|
*/
|
||||||
|
public PlayerCard ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new player card.
|
||||||
|
*
|
||||||
|
* @param pidx the index of the player
|
||||||
|
* @param card the card played
|
||||||
|
*/
|
||||||
|
public PlayerCard (int pidx, Card card)
|
||||||
|
{
|
||||||
|
this.pidx = pidx;
|
||||||
|
this.card = card;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardGameManager.java 3829 2006-02-03 19:11:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.server;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.OccupantInfo;
|
||||||
|
import com.threerings.crowd.server.OccupantOp;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.Log;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.CardCodes;
|
||||||
|
import com.threerings.parlor.card.data.CardGameObject;
|
||||||
|
import com.threerings.parlor.card.data.Deck;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.parlor.game.server.GameManager;
|
||||||
|
import com.threerings.parlor.turn.server.TurnGameManager;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.InvocationService.ConfirmListener;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.dobj.MessageEvent;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
import com.threerings.presents.server.PresentsServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager class for card games. Handles common functions like dealing
|
||||||
|
* hands of cards to all players.
|
||||||
|
*/
|
||||||
|
public class CardGameManager extends GameManager
|
||||||
|
implements TurnGameManager, CardCodes
|
||||||
|
{
|
||||||
|
// Documentation inherited.
|
||||||
|
protected void didStartup ()
|
||||||
|
{
|
||||||
|
super.didStartup();
|
||||||
|
_cardgameobj = (CardGameObject)_gameobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void turnWillStart ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void turnDidStart ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void turnDidEnd ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be called to start a rematched game. It just starts the
|
||||||
|
* current game anew, but provides a mechanism for derived classes to
|
||||||
|
* do special things when there is a rematch.
|
||||||
|
*/
|
||||||
|
public void rematchGame ()
|
||||||
|
{
|
||||||
|
if (gameWillRematch()) {
|
||||||
|
startGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes can override this method and take any action needed
|
||||||
|
* prior to a game rematch. If the rematch needs to be vetoed for any
|
||||||
|
* reason, they can return false from this method and the rematch will
|
||||||
|
* be aborted.
|
||||||
|
*/
|
||||||
|
protected boolean gameWillRematch ()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals a hand of cards to the player at the specified index from
|
||||||
|
* the given Deck.
|
||||||
|
*
|
||||||
|
* @param deck the deck from which to deal
|
||||||
|
* @param size the size of the hand to deal
|
||||||
|
* @param playerIndex the index of the target player
|
||||||
|
* @return the hand dealt to the player, or null if the deal
|
||||||
|
* was canceled because the deck did not contain enough cards
|
||||||
|
*/
|
||||||
|
public Hand dealHand (Deck deck, int size, int playerIndex)
|
||||||
|
{
|
||||||
|
if (deck.size() < size) {
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Hand hand = deck.dealHand(size);
|
||||||
|
if (!isAI(playerIndex)) {
|
||||||
|
ClientObject clobj = (ClientObject)
|
||||||
|
PresentsServer.omgr.getObject(_playerOids[playerIndex]);
|
||||||
|
if (clobj != null) {
|
||||||
|
CardGameSender.sendHand(clobj, _cardgameobj.getOid(), hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals a hand of cards to each player from the specified
|
||||||
|
* Deck.
|
||||||
|
*
|
||||||
|
* @param deck the deck from which to deal
|
||||||
|
* @param size the size of the hands to deal
|
||||||
|
* @return the array of hands dealt to each player, or null if
|
||||||
|
* the deal was canceled because the deck did not contain enough
|
||||||
|
* cards
|
||||||
|
*/
|
||||||
|
public Hand[] dealHands (Deck deck, int size)
|
||||||
|
{
|
||||||
|
if (deck.size() < size * _playerCount) {
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Hand[] hands = new Hand[_playerCount];
|
||||||
|
|
||||||
|
for (int i=0;i<_playerCount;i++) {
|
||||||
|
hands[i] = dealHand(deck, size, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the player index of the specified client object, or -1
|
||||||
|
* if the client object does not represent a player.
|
||||||
|
*/
|
||||||
|
public int getPlayerIndex (ClientObject client)
|
||||||
|
{
|
||||||
|
int oid = client.getOid();
|
||||||
|
for (int i=0;i<_playerOids.length;i++) {
|
||||||
|
if (_playerOids[i] == oid) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the client object corresponding to the specified player index,
|
||||||
|
* or null if the position is not occupied by a player.
|
||||||
|
*/
|
||||||
|
public ClientObject getClientObject (int pidx)
|
||||||
|
{
|
||||||
|
if (_playerOids[pidx] != 0) {
|
||||||
|
return (ClientObject)PresentsServer.omgr.getObject(
|
||||||
|
_playerOids[pidx]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a set of cards from one player to another.
|
||||||
|
*
|
||||||
|
* @param fromPlayerIdx the index of the player sending the cards
|
||||||
|
* @param toPlayerIdx the index of the player receiving the cards
|
||||||
|
* @param cards the cards to be exchanged
|
||||||
|
*/
|
||||||
|
public void transferCardsBetweenPlayers (int fromPlayerIdx,
|
||||||
|
int toPlayerIdx, Card[] cards)
|
||||||
|
{
|
||||||
|
// Notify the sender that the cards have been taken
|
||||||
|
ClientObject fromClient = getClientObject(fromPlayerIdx);
|
||||||
|
if (fromClient != null) {
|
||||||
|
CardGameSender.sentCardsToPlayer(fromClient, toPlayerIdx, cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify the receiver with the cards
|
||||||
|
ClientObject toClient = getClientObject(toPlayerIdx);
|
||||||
|
if (toClient != null) {
|
||||||
|
CardGameSender.sendCardsFromPlayer(toClient, fromPlayerIdx,
|
||||||
|
cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and everybody else in the room other than the sender and the
|
||||||
|
// receiver with the number of cards sent
|
||||||
|
notifyCardsTransferred(fromPlayerIdx, toPlayerIdx, cards.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends sets of cards between players simultaneously. Each player is
|
||||||
|
* guaranteed to receive the notification of cards received after the
|
||||||
|
* notification of cards sent. The length of the arrays passed must
|
||||||
|
* be equal to the player count.
|
||||||
|
*
|
||||||
|
* @param toPlayerIndices for each player, the index of the player to
|
||||||
|
* transfer cards to
|
||||||
|
* @param cards for each player, the cards to transfer
|
||||||
|
*/
|
||||||
|
public void transferCardsBetweenPlayers (int[] toPlayerIndices,
|
||||||
|
Card[][] cards)
|
||||||
|
{
|
||||||
|
// Send all removal notices
|
||||||
|
for (int i = 0; i < _playerCount; i++) {
|
||||||
|
ClientObject fromClient = getClientObject(i);
|
||||||
|
if (fromClient != null) {
|
||||||
|
CardGameSender.sentCardsToPlayer(fromClient,
|
||||||
|
toPlayerIndices[i], cards[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all addition notices and notify everyone else
|
||||||
|
for (int i = 0; i < _playerCount; i++) {
|
||||||
|
ClientObject toClient = getClientObject(toPlayerIndices[i]);
|
||||||
|
if (toClient != null) {
|
||||||
|
CardGameSender.sendCardsFromPlayer(toClient, i, cards[i]);
|
||||||
|
}
|
||||||
|
notifyCardsTransferred(i, toPlayerIndices[i], cards[i].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies everyone in the room (other than the sender and the receiver)
|
||||||
|
* that a set of cards have been transferred.
|
||||||
|
*
|
||||||
|
* @param fromPlayerIdx the index of the player sending the cards
|
||||||
|
* @param toPlayerIdx the index of the player receiving the cards
|
||||||
|
* @param cards the number of cards sent
|
||||||
|
*/
|
||||||
|
protected void notifyCardsTransferred (final int fromPlayerIdx,
|
||||||
|
final int toPlayerIdx, final int cards)
|
||||||
|
{
|
||||||
|
final int senderOid = _playerOids[fromPlayerIdx],
|
||||||
|
receiverOid = _playerOids[toPlayerIdx];
|
||||||
|
OccupantOp op = new OccupantOp() {
|
||||||
|
public void apply (OccupantInfo info) {
|
||||||
|
int oid = info.getBodyOid();
|
||||||
|
if (oid != senderOid && oid != receiverOid) {
|
||||||
|
ClientObject client =
|
||||||
|
(ClientObject)PresentsServer.omgr.getObject(oid);
|
||||||
|
if (client != null) {
|
||||||
|
CardGameSender.cardsTransferredBetweenPlayers(client,
|
||||||
|
fromPlayerIdx, toPlayerIdx, cards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
applyToOccupants(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The card game object. */
|
||||||
|
protected CardGameObject _cardgameobj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.server;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.client.CardGameDecoder;
|
||||||
|
import com.threerings.parlor.card.client.CardGameReceiver;
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.server.InvocationSender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to issue notifications to a {@link CardGameReceiver} instance on a
|
||||||
|
* client.
|
||||||
|
*/
|
||||||
|
public class CardGameSender extends InvocationSender
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Issues a notification that will result in a call to {@link
|
||||||
|
* CardGameReceiver#cardsTransferredBetweenPlayers} on a client.
|
||||||
|
*/
|
||||||
|
public static void cardsTransferredBetweenPlayers (
|
||||||
|
ClientObject target, int arg1, int arg2, int arg3)
|
||||||
|
{
|
||||||
|
sendNotification(
|
||||||
|
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.CARDS_TRANSFERRED_BETWEEN_PLAYERS,
|
||||||
|
new Object[] { Integer.valueOf(arg1), Integer.valueOf(arg2), Integer.valueOf(arg3) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issues a notification that will result in a call to {@link
|
||||||
|
* CardGameReceiver#receivedCardsFromPlayer} on a client.
|
||||||
|
*/
|
||||||
|
public static void sendCardsFromPlayer (
|
||||||
|
ClientObject target, int arg1, Card[] arg2)
|
||||||
|
{
|
||||||
|
sendNotification(
|
||||||
|
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.RECEIVED_CARDS_FROM_PLAYER,
|
||||||
|
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issues a notification that will result in a call to {@link
|
||||||
|
* CardGameReceiver#receivedHand} on a client.
|
||||||
|
*/
|
||||||
|
public static void sendHand (
|
||||||
|
ClientObject target, int arg1, Hand arg2)
|
||||||
|
{
|
||||||
|
sendNotification(
|
||||||
|
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.RECEIVED_HAND,
|
||||||
|
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issues a notification that will result in a call to {@link
|
||||||
|
* CardGameReceiver#sentCardsToPlayer} on a client.
|
||||||
|
*/
|
||||||
|
public static void sentCardsToPlayer (
|
||||||
|
ClientObject target, int arg1, Card[] arg2)
|
||||||
|
{
|
||||||
|
sendNotification(
|
||||||
|
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.SENT_CARDS_TO_PLAYER,
|
||||||
|
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// $Id: TrickCardGameControllerDelegate.java 3465 2005-04-12 02:50:17Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.turn.client.TurnGameControllerDelegate;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.client.CardGameController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A card game controller delegate for trick-based card games, such as
|
||||||
|
* Spades and Hearts.
|
||||||
|
*/
|
||||||
|
public class TrickCardGameControllerDelegate
|
||||||
|
extends TurnGameControllerDelegate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param controller the game controller
|
||||||
|
*/
|
||||||
|
public TrickCardGameControllerDelegate (CardGameController
|
||||||
|
controller)
|
||||||
|
{
|
||||||
|
super(controller);
|
||||||
|
_cgctrl = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The card game controller. */
|
||||||
|
protected CardGameController _cgctrl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// $Id: RoisterService.java 17829 2004-11-12 20:24:43Z mdb $
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service calls related to trick card games.
|
||||||
|
*/
|
||||||
|
public interface TrickCardGameService extends InvocationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sends a group of cards to the player at the specified index.
|
||||||
|
*
|
||||||
|
* @param client the client object
|
||||||
|
* @param toidx the index of the player to send the cards to
|
||||||
|
* @param cards the cards to send
|
||||||
|
*/
|
||||||
|
public void sendCardsToPlayer (Client client, int toidx, Card[] cards);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays a card in the trick.
|
||||||
|
*
|
||||||
|
* @param client the client object
|
||||||
|
* @param card the card to play
|
||||||
|
* @param handSize the size of the player's hand, which is used to verify
|
||||||
|
* that the request is for the current trick
|
||||||
|
*/
|
||||||
|
public void playCard (Client client, Card card, int handSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A request for a rematch.
|
||||||
|
*
|
||||||
|
* @param client the client object
|
||||||
|
*/
|
||||||
|
public void requestRematch (Client client);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// $Id: CardCodes.java 3224 2004-11-19 19:04:56Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.data;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.CardCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants relating to trick-based card games.
|
||||||
|
*/
|
||||||
|
public interface TrickCardCodes extends CardCodes
|
||||||
|
{
|
||||||
|
/** For four-player games, the bottom (own) player. */
|
||||||
|
public static final int BOTTOM = 0;
|
||||||
|
|
||||||
|
/** For four-player games, the player on the left. */
|
||||||
|
public static final int LEFT = 1;
|
||||||
|
|
||||||
|
/** For four-player games, the top (opposite) player. */
|
||||||
|
public static final int TOP = 2;
|
||||||
|
|
||||||
|
/** For four-player games, the player on the right. */
|
||||||
|
public static final int RIGHT = 3;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.data;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the implementation of the {@link TrickCardGameService} interface
|
||||||
|
* that marshalls the arguments and delivers the request to the provider
|
||||||
|
* on the server. Also provides an implementation of the response listener
|
||||||
|
* interfaces that marshall the response arguments and deliver them back
|
||||||
|
* to the requesting client.
|
||||||
|
*/
|
||||||
|
public class TrickCardGameMarshaller extends InvocationMarshaller
|
||||||
|
implements TrickCardGameService
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #playCard} requests. */
|
||||||
|
public static final int PLAY_CARD = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void playCard (Client arg1, Card arg2, int arg3)
|
||||||
|
{
|
||||||
|
sendRequest(arg1, PLAY_CARD, new Object[] {
|
||||||
|
arg2, Integer.valueOf(arg3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #requestRematch} requests. */
|
||||||
|
public static final int REQUEST_REMATCH = 2;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void requestRematch (Client arg1)
|
||||||
|
{
|
||||||
|
sendRequest(arg1, REQUEST_REMATCH, new Object[] {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #sendCardsToPlayer} requests. */
|
||||||
|
public static final int SEND_CARDS_TO_PLAYER = 3;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void sendCardsToPlayer (Client arg1, int arg2, Card[] arg3)
|
||||||
|
{
|
||||||
|
sendRequest(arg1, SEND_CARDS_TO_PLAYER, new Object[] {
|
||||||
|
Integer.valueOf(arg2), arg3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
//
|
||||||
|
// $Id: TrickCardGameObject.java 3516 2005-04-21 00:47:17Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.data;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.parlor.card.data.PlayerCard;
|
||||||
|
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game objects for trick-based card games must implement this interface.
|
||||||
|
*/
|
||||||
|
public interface TrickCardGameObject extends TurnGameObject
|
||||||
|
{
|
||||||
|
/** The state that indicates the game is currently between hands. */
|
||||||
|
public static final int BETWEEN_HANDS = 0;
|
||||||
|
|
||||||
|
/** The state that indicates the game is currently playing a hand. */
|
||||||
|
public static final int PLAYING_HAND = 1;
|
||||||
|
|
||||||
|
/** The state that indicates the game is currently playing a trick. */
|
||||||
|
public static final int PLAYING_TRICK = 2;
|
||||||
|
|
||||||
|
/** The number of states defined for the base trick card game object. */
|
||||||
|
public static final int TRICK_STATE_COUNT = 3;
|
||||||
|
|
||||||
|
/** Indicates that the player has not requested or accepted a rematch. */
|
||||||
|
public static final int NO_REQUEST = 0;
|
||||||
|
|
||||||
|
/** Indicates that the player has requested a rematch. */
|
||||||
|
public static final int REQUESTS_REMATCH = 1;
|
||||||
|
|
||||||
|
/** Indicates that the player has accepted the rematch request. */
|
||||||
|
public static final int ACCEPTS_REMATCH = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the trick card game service used to make
|
||||||
|
* requests to the server.
|
||||||
|
*
|
||||||
|
* @return a reference to the trick card game service
|
||||||
|
*/
|
||||||
|
public TrickCardGameMarshaller getTrickCardGameService ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the reference to the trick card game service.
|
||||||
|
*
|
||||||
|
* @param trickCardGameService the trick card game service
|
||||||
|
*/
|
||||||
|
public void setTrickCardGameService (TrickCardGameMarshaller
|
||||||
|
trickCardGameService);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the field that contains the trick state: between
|
||||||
|
* hands, playing a hand, or playing a trick.
|
||||||
|
*
|
||||||
|
* @return the name of the trickState field
|
||||||
|
*/
|
||||||
|
public String getTrickStateFieldName ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the trick state: between hands, playing a hand, or playing a
|
||||||
|
* trick.
|
||||||
|
*
|
||||||
|
* @return the trick state
|
||||||
|
*/
|
||||||
|
public int getTrickState ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the trick state.
|
||||||
|
*
|
||||||
|
* @param trickState the trick state
|
||||||
|
*/
|
||||||
|
public void setTrickState (int trickState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing the turn duration scales for each player.
|
||||||
|
* Turn duration scales decrease each time players time out.
|
||||||
|
*
|
||||||
|
* @return the array of turn duration scales
|
||||||
|
*/
|
||||||
|
public float[] getTurnDurationScales ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the array of turn duration scales.
|
||||||
|
*
|
||||||
|
* @param turnDurationScales the array of turn duration scales
|
||||||
|
*/
|
||||||
|
public void setTurnDurationScales (float[] turnDurationScales);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an element of the array of turn duration scales.
|
||||||
|
*
|
||||||
|
* @param turnDurationScale the turn duration scale
|
||||||
|
* @param index the index of the turn duration scale
|
||||||
|
*/
|
||||||
|
public void setTurnDurationScalesAt (float turnDurationScale, int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the duration of the current turn, which may depend on the state
|
||||||
|
* of the game as well as the duration scale of the active player.
|
||||||
|
*/
|
||||||
|
public long getTurnDuration ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the field that contains the history of the trick
|
||||||
|
* in terms of the cards played by each player.
|
||||||
|
*
|
||||||
|
* @return the name of the cardsPlayed field
|
||||||
|
*/
|
||||||
|
public String getCardsPlayedFieldName ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing the history of the trick in terms of the
|
||||||
|
* cards played by each player.
|
||||||
|
*
|
||||||
|
* @return the cards played so far in the trick
|
||||||
|
*/
|
||||||
|
public PlayerCard[] getCardsPlayed ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the array of cards played by each player.
|
||||||
|
*
|
||||||
|
* @param cardsPlayed the array of cards played
|
||||||
|
*/
|
||||||
|
public void setCardsPlayed (PlayerCard[] cardsPlayed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the field that contains the history of the last
|
||||||
|
* trick in terms of the cards played by each player.
|
||||||
|
*
|
||||||
|
* @return the name of the lastCardsPlayed field
|
||||||
|
*/
|
||||||
|
public String getLastCardsPlayedFieldName ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing the history of the last trick in terms of
|
||||||
|
* the cards played by each player.
|
||||||
|
*
|
||||||
|
* @return the cards played in the last trick
|
||||||
|
*/
|
||||||
|
public PlayerCard[] getLastCardsPlayed ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the last array of cards played by each player.
|
||||||
|
*
|
||||||
|
* @param lastCardsPlayed the last array of cards played
|
||||||
|
*/
|
||||||
|
public void setLastCardsPlayed (PlayerCard[] lastCardsPlayed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the field that contains the rematch requests.
|
||||||
|
*
|
||||||
|
* @return the name of the rematchRequests field
|
||||||
|
*/
|
||||||
|
public String getRematchRequestsFieldName ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the array of rematch requests.
|
||||||
|
*
|
||||||
|
* @return the array of rematch requests
|
||||||
|
*/
|
||||||
|
public int[] getRematchRequests ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the array of rematch requests.
|
||||||
|
*
|
||||||
|
* @param rematchRequests the array of rematch requests
|
||||||
|
*/
|
||||||
|
public void setRematchRequests (int[] rematchRequests);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an element of the rematch request array.
|
||||||
|
*
|
||||||
|
* @param rematchRequest the rematch request value
|
||||||
|
* @param index the index at which to set the value
|
||||||
|
*/
|
||||||
|
public void setRematchRequestsAt (int rematchRequest, int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user can play the specified card at this time.
|
||||||
|
*
|
||||||
|
* @param hand the player's hand
|
||||||
|
* @param card the card that the user would like to play
|
||||||
|
*/
|
||||||
|
public boolean isCardPlayable (Hand hand, Card card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the card of the player who took the current trick.
|
||||||
|
*/
|
||||||
|
public PlayerCard getTrickTaker ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.server;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||||
|
import com.threerings.parlor.card.trick.data.TrickCardGameMarshaller;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.server.InvocationDispatcher;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches requests to the {@link TrickCardGameProvider}.
|
||||||
|
*/
|
||||||
|
public class TrickCardGameDispatcher extends InvocationDispatcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a dispatcher that may be registered to dispatch invocation
|
||||||
|
* service requests for the specified provider.
|
||||||
|
*/
|
||||||
|
public TrickCardGameDispatcher (TrickCardGameProvider provider)
|
||||||
|
{
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public InvocationMarshaller createMarshaller ()
|
||||||
|
{
|
||||||
|
return new TrickCardGameMarshaller();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchRequest (
|
||||||
|
ClientObject source, int methodId, Object[] args)
|
||||||
|
throws InvocationException
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case TrickCardGameMarshaller.PLAY_CARD:
|
||||||
|
((TrickCardGameProvider)provider).playCard(
|
||||||
|
source,
|
||||||
|
(Card)args[0], ((Integer)args[1]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case TrickCardGameMarshaller.REQUEST_REMATCH:
|
||||||
|
((TrickCardGameProvider)provider).requestRematch(
|
||||||
|
source
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case TrickCardGameMarshaller.SEND_CARDS_TO_PLAYER:
|
||||||
|
((TrickCardGameProvider)provider).sendCardsToPlayer(
|
||||||
|
source,
|
||||||
|
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchRequest(source, methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,643 @@
|
|||||||
|
//
|
||||||
|
// $Id: TrickCardGameManagerDelegate.java 4188 2006-06-13 18:03:48Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.samskivert.util.ArrayUtil;
|
||||||
|
import com.samskivert.util.Interval;
|
||||||
|
import com.samskivert.util.RandomUtil;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.dobj.DObject;
|
||||||
|
import com.threerings.presents.server.PresentsServer;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.parlor.game.server.GameManager;
|
||||||
|
import com.threerings.parlor.turn.server.TurnGameManagerDelegate;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.Log;
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.CardGameObject;
|
||||||
|
import com.threerings.parlor.card.data.Deck;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.parlor.card.data.PlayerCard;
|
||||||
|
import com.threerings.parlor.card.server.CardGameManager;
|
||||||
|
import com.threerings.parlor.card.trick.data.TrickCardGameMarshaller;
|
||||||
|
import com.threerings.parlor.card.trick.data.TrickCardGameObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A card game manager delegate for trick-based card games, such as
|
||||||
|
* Spades and Hearts.
|
||||||
|
*/
|
||||||
|
public class TrickCardGameManagerDelegate extends TurnGameManagerDelegate
|
||||||
|
implements TrickCardGameProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param manager the game manager
|
||||||
|
*/
|
||||||
|
public TrickCardGameManagerDelegate (CardGameManager manager)
|
||||||
|
{
|
||||||
|
super(manager);
|
||||||
|
|
||||||
|
_cgmgr = manager;
|
||||||
|
_deck = new Deck();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void didStartup (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.didStartup(plobj);
|
||||||
|
|
||||||
|
_trickCardGame = (TrickCardGameObject)plobj;
|
||||||
|
|
||||||
|
_cardGame = (CardGameObject)plobj;
|
||||||
|
|
||||||
|
_trickCardGame.setTrickCardGameService(
|
||||||
|
(TrickCardGameMarshaller)PresentsServer.invmgr.registerDispatcher(
|
||||||
|
new TrickCardGameDispatcher(this), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void didShutdown ()
|
||||||
|
{
|
||||||
|
super.didShutdown();
|
||||||
|
|
||||||
|
PresentsServer.invmgr.clearDispatcher(
|
||||||
|
_trickCardGame.getTrickCardGameService());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void gameWillStart ()
|
||||||
|
{
|
||||||
|
super.gameWillStart();
|
||||||
|
|
||||||
|
// clear out the last cards played
|
||||||
|
_trickCardGame.setLastCardsPlayed(null);
|
||||||
|
|
||||||
|
// initialize the turn duration scales
|
||||||
|
float[] scales = new float[_cardGame.getPlayerCount()];
|
||||||
|
Arrays.fill(scales, 1.0f);
|
||||||
|
_trickCardGame.setTurnDurationScales(scales);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the game has started. Default implementation starts the
|
||||||
|
* first hand.
|
||||||
|
*/
|
||||||
|
public void gameDidStart ()
|
||||||
|
{
|
||||||
|
super.gameDidStart();
|
||||||
|
|
||||||
|
// start the first hand
|
||||||
|
startHand();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void gameDidEnd ()
|
||||||
|
{
|
||||||
|
super.gameDidEnd();
|
||||||
|
|
||||||
|
// make sure all intervals are cancelled
|
||||||
|
_turnTimeoutInterval.cancel();
|
||||||
|
_endTrickInterval.cancel();
|
||||||
|
|
||||||
|
// make sure trick state is back to between hands
|
||||||
|
if (_trickCardGame.getTrickState() !=
|
||||||
|
TrickCardGameObject.BETWEEN_HANDS) {
|
||||||
|
_trickCardGame.setTrickState(TrickCardGameObject.BETWEEN_HANDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the array of rematch requests
|
||||||
|
_trickCardGame.setRematchRequests(
|
||||||
|
new int[_cardGame.getPlayerCount()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void startTurn ()
|
||||||
|
{
|
||||||
|
super.startTurn();
|
||||||
|
|
||||||
|
// initialize the timeout flag and schedule the timeout interval
|
||||||
|
_turnTimedOut = false;
|
||||||
|
_turnTimeoutInterval.schedule(_trickCardGame.getTurnDuration());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void endTurn ()
|
||||||
|
{
|
||||||
|
// cancel the timeout interval
|
||||||
|
_turnTimeoutInterval.cancel();
|
||||||
|
|
||||||
|
// reduce or increase the turn duration scale
|
||||||
|
if (_turnTimedOut) {
|
||||||
|
reduceTurnDurationScale(_turnIdx);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
increaseTurnDurationScale(_turnIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.endTurn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a hand of cards. Calls {@link #handWillStart}, sets the trick
|
||||||
|
* state to PLAYING_HAND, and calls {@link #handDidStart}.
|
||||||
|
*/
|
||||||
|
public void startHand ()
|
||||||
|
{
|
||||||
|
handWillStart();
|
||||||
|
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_HAND);
|
||||||
|
handDidStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the hand of cards. Calls {@link #handWillEnd}, sets the trick
|
||||||
|
* state to BETWEEN_HANDS, and calls {@link #handDidEnd}.
|
||||||
|
*/
|
||||||
|
public void endHand ()
|
||||||
|
{
|
||||||
|
handWillEnd();
|
||||||
|
_trickCardGame.setTrickState(TrickCardGameObject.BETWEEN_HANDS);
|
||||||
|
handDidEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a trick. Calls {@link #trickWillStart}, sets the trick
|
||||||
|
* state to PLAYING_TRICK, and calls {@link #trickDidStart}.
|
||||||
|
*/
|
||||||
|
public void startTrick ()
|
||||||
|
{
|
||||||
|
trickWillStart();
|
||||||
|
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_TRICK);
|
||||||
|
trickDidStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the trick. Calls {@link #trickWillEnd}, sets the trick
|
||||||
|
* state to PLAYING_HAND, and calls {@link #trickDidEnd}.
|
||||||
|
*/
|
||||||
|
public void endTrick ()
|
||||||
|
{
|
||||||
|
trickWillEnd();
|
||||||
|
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_HAND);
|
||||||
|
trickDidEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a request to transfer a group of cards between players.
|
||||||
|
* Default implementation verifies that the user's hand contains the
|
||||||
|
* specified cards, then calls {@link #sendCardsToPlayer(int, int,
|
||||||
|
* Card[])}.
|
||||||
|
*/
|
||||||
|
public void sendCardsToPlayer (ClientObject client, int toidx,
|
||||||
|
Card[] cards)
|
||||||
|
{
|
||||||
|
// make sure they're actually a player
|
||||||
|
int fromidx = _cgmgr.getPlayerIndex(client);
|
||||||
|
if (fromidx == -1) {
|
||||||
|
Log.warning("Send request from non-player [username=" +
|
||||||
|
((BodyObject)client).who() + ", cards=" +
|
||||||
|
StringUtil.toString(cards) + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure they have the cards
|
||||||
|
if (!_hands[fromidx].containsAll(cards)) {
|
||||||
|
Log.warning("Tried to send cards not held [username=" +
|
||||||
|
((BodyObject)client).who() + ", cards=" +
|
||||||
|
StringUtil.toString(cards) + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the cards
|
||||||
|
sendCardsToPlayer(fromidx, toidx, cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends cards between players without error checking. Default
|
||||||
|
* implementation transfers the cards between hands and notifies
|
||||||
|
* everyone of the transfer using {@link
|
||||||
|
* CardGameManager#transferCardsBetweenPlayers(int, int, Card[])}.
|
||||||
|
*/
|
||||||
|
protected void sendCardsToPlayer (int fromidx, int toidx, Card[] cards)
|
||||||
|
{
|
||||||
|
// remove from sending player's hand
|
||||||
|
_hands[fromidx].removeAll(cards);
|
||||||
|
|
||||||
|
// add to receiving player's hand
|
||||||
|
_hands[toidx].addAll(cards);
|
||||||
|
|
||||||
|
// notify everyone of the transfer
|
||||||
|
_cgmgr.transferCardsBetweenPlayers(fromidx, toidx, cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void playCard (ClientObject client, Card card, int handSize)
|
||||||
|
{
|
||||||
|
// make sure we're playing a trick
|
||||||
|
if (_trickCardGame.getTrickState() !=
|
||||||
|
TrickCardGameObject.PLAYING_TRICK) {
|
||||||
|
return; // silently ignore play attempts after timeouts
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure it's their turn
|
||||||
|
Name username = ((BodyObject)client).getVisibleName();
|
||||||
|
if (!username.equals(_trickCardGame.getTurnHolder())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure they're on the right trick
|
||||||
|
int pidx = _cardGame.getPlayerIndex(username);
|
||||||
|
if (_hands[pidx].size() != handSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure their hand contains the specified card
|
||||||
|
if (!_hands[pidx].contains(card)) {
|
||||||
|
Log.warning("Tried to play card not held [username=" + username +
|
||||||
|
", card=" + card + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the card is legal to play
|
||||||
|
if (!_trickCardGame.isCardPlayable(_hands[pidx], card)) {
|
||||||
|
Log.warning("Tried to play illegal card [username=" + username +
|
||||||
|
", card=" + card + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// play the card
|
||||||
|
playCard(pidx, card);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays a card for a player without error checking.
|
||||||
|
*/
|
||||||
|
protected void playCard (int pidx, Card card)
|
||||||
|
{
|
||||||
|
((DObject) _trickCardGame).startTransaction();
|
||||||
|
try {
|
||||||
|
// play the card by removing it from the hand and adding it
|
||||||
|
// to the end of the cards played array
|
||||||
|
_hands[pidx].remove(card);
|
||||||
|
PlayerCard[] cards = (PlayerCard[])ArrayUtil.append(
|
||||||
|
_trickCardGame.getCardsPlayed(), new PlayerCard(pidx, card));
|
||||||
|
_trickCardGame.setCardsPlayed(cards);
|
||||||
|
|
||||||
|
// end the user's turn
|
||||||
|
endTurn();
|
||||||
|
|
||||||
|
// end the trick if everyone has played a card
|
||||||
|
if (_turnIdx == -1) {
|
||||||
|
if (_endTrickDelay == 0) {
|
||||||
|
endTrick();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_endTrickInterval.schedule(_endTrickDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
((DObject) _trickCardGame).commitTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
public void requestRematch (ClientObject client)
|
||||||
|
{
|
||||||
|
// make sure the game is over
|
||||||
|
if (_cardGame.state != CardGameObject.GAME_OVER) {
|
||||||
|
Log.warning("Tried to request rematch when game wasn't over " +
|
||||||
|
"[username=" + ((BodyObject)client).who() + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the requester is one of the players
|
||||||
|
int pidx = _cgmgr.getPlayerIndex(client);
|
||||||
|
if (pidx == -1) {
|
||||||
|
Log.warning("Rematch request from non-player [username=" +
|
||||||
|
((BodyObject)client).who() + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the player hasn't already requested
|
||||||
|
if (_trickCardGame.getRematchRequests()[pidx] !=
|
||||||
|
TrickCardGameObject.NO_REQUEST) {
|
||||||
|
Log.warning("Repeated rematch request [username=" +
|
||||||
|
((BodyObject)client).who() + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if player is first requesting, set to request; else set
|
||||||
|
// to accept
|
||||||
|
int req = (getRematchRequestCount() == 0 ?
|
||||||
|
TrickCardGameObject.REQUESTS_REMATCH :
|
||||||
|
TrickCardGameObject.ACCEPTS_REMATCH);
|
||||||
|
_trickCardGame.setRematchRequestsAt(req, pidx);
|
||||||
|
|
||||||
|
// if all players accept the rematch, restart the game
|
||||||
|
if (getRematchRequestCount() == _cardGame.getPlayerCount()) {
|
||||||
|
_cgmgr.rematchGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of players currently requesting or accepting
|
||||||
|
* a rematch.
|
||||||
|
*/
|
||||||
|
protected int getRematchRequestCount ()
|
||||||
|
{
|
||||||
|
int[] rematchRequests = _trickCardGame.getRematchRequests();
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < rematchRequests.length; i++) {
|
||||||
|
if (rematchRequests[i] != TrickCardGameObject.NO_REQUEST) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the trick is complete--that is, whether each player has
|
||||||
|
* played a card.
|
||||||
|
*/
|
||||||
|
protected boolean isTrickComplete ()
|
||||||
|
{
|
||||||
|
return _trickCardGame.getCardsPlayed().length ==
|
||||||
|
_cardGame.getPlayerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
protected void setFirstTurnHolder ()
|
||||||
|
{
|
||||||
|
if (_trickCardGame.getTrickState() ==
|
||||||
|
TrickCardGameObject.PLAYING_TRICK) {
|
||||||
|
super.setFirstTurnHolder();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_turnIdx = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation inherited.
|
||||||
|
protected void setNextTurnHolder ()
|
||||||
|
{
|
||||||
|
if (_trickCardGame.getTrickState() ==
|
||||||
|
TrickCardGameObject.PLAYING_TRICK &&
|
||||||
|
!isTrickComplete()) {
|
||||||
|
super.setNextTurnHolder();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_turnIdx = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the current turn times out. Default implementation
|
||||||
|
* plays a random playable card if in the trick-playing state.
|
||||||
|
*/
|
||||||
|
protected void turnTimedOut ()
|
||||||
|
{
|
||||||
|
if (_trickCardGame.getTrickState() ==
|
||||||
|
TrickCardGameObject.PLAYING_TRICK) {
|
||||||
|
playCard(_turnIdx, pickRandomPlayableCard(_hands[_turnIdx]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the specified player's turn duration due to a time-out.
|
||||||
|
*/
|
||||||
|
protected void reduceTurnDurationScale (int pidx)
|
||||||
|
{
|
||||||
|
float oldScale = _trickCardGame.getTurnDurationScales()[pidx],
|
||||||
|
newScale = Math.max(oldScale - TURN_DURATION_SCALE_REDUCTION,
|
||||||
|
MINIMUM_TURN_DURATION_SCALE);
|
||||||
|
if (newScale != oldScale) {
|
||||||
|
_trickCardGame.setTurnDurationScalesAt(newScale, pidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases the specified player's turn duration due to avoiding a
|
||||||
|
* time-out.
|
||||||
|
*/
|
||||||
|
protected void increaseTurnDurationScale (int pidx)
|
||||||
|
{
|
||||||
|
float oldScale = _trickCardGame.getTurnDurationScales()[pidx],
|
||||||
|
newScale = Math.min(oldScale + TURN_DURATION_SCALE_INCREASE,
|
||||||
|
1.0f);
|
||||||
|
if (newScale != oldScale) {
|
||||||
|
_trickCardGame.setTurnDurationScalesAt(newScale, pidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random playable card from the specified hand.
|
||||||
|
*/
|
||||||
|
protected Card pickRandomPlayableCard (Hand hand)
|
||||||
|
{
|
||||||
|
ArrayList playableCards = new ArrayList();
|
||||||
|
for (int i = 0; i < hand.size(); i++) {
|
||||||
|
Card card = (Card)hand.get(i);
|
||||||
|
if (_trickCardGame.isCardPlayable(hand, card)) {
|
||||||
|
playableCards.add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (Card)RandomUtil.pickRandom(playableCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that a new hand is about to start.
|
||||||
|
*/
|
||||||
|
protected void handWillStart ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that a new hand has just started. Default
|
||||||
|
* implementation prepares the deck, deals the hands, and starts the
|
||||||
|
* first trick.
|
||||||
|
*/
|
||||||
|
protected void handDidStart ()
|
||||||
|
{
|
||||||
|
// prepare the deck
|
||||||
|
prepareDeck();
|
||||||
|
|
||||||
|
// deal cards to players
|
||||||
|
dealHands();
|
||||||
|
|
||||||
|
// start the first trick
|
||||||
|
startTrick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the deck for a new hand of cards. Default implementation
|
||||||
|
* resets to a full deck without jokers and shuffles.
|
||||||
|
*/
|
||||||
|
protected void prepareDeck ()
|
||||||
|
{
|
||||||
|
_deck.reset(false);
|
||||||
|
_deck.shuffle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deals hands to the players. Default implementation deals the entire
|
||||||
|
* deck to the players in equal-sized hands.
|
||||||
|
*/
|
||||||
|
protected void dealHands ()
|
||||||
|
{
|
||||||
|
_hands = _cgmgr.dealHands(_deck, _deck.size() /
|
||||||
|
_cardGame.getPlayerCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that the hand is about to end.
|
||||||
|
*/
|
||||||
|
protected void handWillEnd ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that the hand has ended. Default implementation
|
||||||
|
* starts the next hand.
|
||||||
|
*/
|
||||||
|
protected void handDidEnd ()
|
||||||
|
{
|
||||||
|
startHand();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that a new trick is about to start. Default
|
||||||
|
* implementation resets the array of cards played.
|
||||||
|
*/
|
||||||
|
protected void trickWillStart ()
|
||||||
|
{
|
||||||
|
_trickCardGame.setCardsPlayed(new PlayerCard[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that a new trick has started. Default
|
||||||
|
* implementation sets the first turn holder and starts the
|
||||||
|
* turn.
|
||||||
|
*/
|
||||||
|
protected void trickDidStart ()
|
||||||
|
{
|
||||||
|
setFirstTurnHolder();
|
||||||
|
startTurn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that the trick is about to end.
|
||||||
|
*/
|
||||||
|
protected void trickWillEnd ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the object that the trick has ended. Default implementation
|
||||||
|
* records the last cards played and starts the next trick, unless a
|
||||||
|
* player has run out of cards, in which case it ends the hand.
|
||||||
|
*/
|
||||||
|
protected void trickDidEnd ()
|
||||||
|
{
|
||||||
|
// store the trick results for late-joiners
|
||||||
|
_trickCardGame.setLastCardsPlayed(_trickCardGame.getCardsPlayed());
|
||||||
|
|
||||||
|
// clear out the cards played in the trick
|
||||||
|
_trickCardGame.setCardsPlayed(null);
|
||||||
|
|
||||||
|
// verify that each player has at least one card
|
||||||
|
if (anyHandsEmpty()) {
|
||||||
|
endHand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// everyone has cards; let's play another trick
|
||||||
|
startTrick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether any hands are empty.
|
||||||
|
*/
|
||||||
|
protected boolean anyHandsEmpty ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _hands.length; i++) {
|
||||||
|
if (_hands[i].isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The card game manager. */
|
||||||
|
protected CardGameManager _cgmgr;
|
||||||
|
|
||||||
|
/** The game object as trick card game. */
|
||||||
|
protected TrickCardGameObject _trickCardGame;
|
||||||
|
|
||||||
|
/** The game object as card game. */
|
||||||
|
protected CardGameObject _cardGame;
|
||||||
|
|
||||||
|
/** The amount of time to wait before ending the trick. */
|
||||||
|
protected long _endTrickDelay;
|
||||||
|
|
||||||
|
/** The deck from which cards are dealt. */
|
||||||
|
protected Deck _deck;
|
||||||
|
|
||||||
|
/** The hands of each player. */
|
||||||
|
protected Hand[] _hands;
|
||||||
|
|
||||||
|
/** Whether or not the turn timed out. */
|
||||||
|
protected boolean _turnTimedOut;
|
||||||
|
|
||||||
|
/** The all-purpose turn timeout interval. */
|
||||||
|
protected Interval _turnTimeoutInterval =
|
||||||
|
new Interval(PresentsServer.omgr) {
|
||||||
|
public void expired () {
|
||||||
|
_turnTimedOut = true;
|
||||||
|
turnTimedOut();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Calls {@link #endTrick} upon expiration. */
|
||||||
|
protected Interval _endTrickInterval = new Interval(PresentsServer.omgr) {
|
||||||
|
public void expired () {
|
||||||
|
endTrick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Reduce turn duration scales by this amount each time the player times
|
||||||
|
* out. */
|
||||||
|
protected static final float TURN_DURATION_SCALE_REDUCTION = 0.25f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase turn duration scales by this amount each time the player
|
||||||
|
* manages not to time out. */
|
||||||
|
protected static final float TURN_DURATION_SCALE_INCREASE = 0.5f;
|
||||||
|
|
||||||
|
/** Don't let turn duration scales get below this level. */
|
||||||
|
protected static final float MINIMUM_TURN_DURATION_SCALE = 0.1f;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.server;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.server.InvocationException;
|
||||||
|
import com.threerings.presents.server.InvocationProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the server-side of the {@link TrickCardGameService}.
|
||||||
|
*/
|
||||||
|
public interface TrickCardGameProvider extends InvocationProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles a {@link TrickCardGameService#playCard} request.
|
||||||
|
*/
|
||||||
|
public void playCard (ClientObject caller, Card arg1, int arg2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a {@link TrickCardGameService#requestRematch} request.
|
||||||
|
*/
|
||||||
|
public void requestRematch (ClientObject caller);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a {@link TrickCardGameService#sendCardsToPlayer} request.
|
||||||
|
*/
|
||||||
|
public void sendCardsToPlayer (ClientObject caller, int arg1, Card[] arg2);
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
//
|
||||||
|
// $Id: TrickCardGameObject.java 3382 2005-03-03 19:55:35Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.card.trick.util;
|
||||||
|
|
||||||
|
import com.threerings.parlor.card.data.Card;
|
||||||
|
import com.threerings.parlor.card.data.Hand;
|
||||||
|
import com.threerings.parlor.card.data.PlayerCard;
|
||||||
|
import com.threerings.parlor.card.trick.data.TrickCardCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methods of general utility to trick-taking card games.
|
||||||
|
*/
|
||||||
|
public class TrickCardGameUtil
|
||||||
|
implements TrickCardCodes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* For four-player games with fixed partnerships, this returns the index
|
||||||
|
* of the player's team.
|
||||||
|
*
|
||||||
|
* @param pidx the player index
|
||||||
|
*/
|
||||||
|
public static int getTeamIndex (int pidx)
|
||||||
|
{
|
||||||
|
return pidx & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games with fixed partnerships, this returns the index
|
||||||
|
* of the other team.
|
||||||
|
*
|
||||||
|
* @param tidx the index of the team
|
||||||
|
*/
|
||||||
|
public static int getOtherTeamIndex (int tidx)
|
||||||
|
{
|
||||||
|
return tidx ^ 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games with fixed partnerships, this returns the index
|
||||||
|
* of the player's partner.
|
||||||
|
*/
|
||||||
|
public static int getPartnerIndex (int pidx)
|
||||||
|
{
|
||||||
|
return pidx ^ 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games with fixed partnerships, this returns the index
|
||||||
|
* of one of the members of a team.
|
||||||
|
*
|
||||||
|
* @param tidx the index of the team
|
||||||
|
* @param midx the index of the player within the team
|
||||||
|
*/
|
||||||
|
public static int getTeamMemberIndex (int tidx, int midx)
|
||||||
|
{
|
||||||
|
return (midx << 1) | tidx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games, this returns the index of the player after the
|
||||||
|
* specified player going clockwise around the table.
|
||||||
|
*/
|
||||||
|
public static int getNextInClockwiseSequence (int pidx)
|
||||||
|
{
|
||||||
|
// 2
|
||||||
|
// 1 3
|
||||||
|
// 0
|
||||||
|
return (pidx + 1) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games with fixed partnerships, this returns the
|
||||||
|
* relative location of one player from the point of view of another.
|
||||||
|
*
|
||||||
|
* @param pidx1 the index of the player to whom the location is relative
|
||||||
|
* @param pidx2 the index of the player whose location is desired
|
||||||
|
* @return the relative location (TOP, BOTTOM, LEFT, or RIGHT)
|
||||||
|
*/
|
||||||
|
public static int getRelativeLocation (int pidx1, int pidx2)
|
||||||
|
{
|
||||||
|
return (pidx2 - pidx1) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games, returns the index of the player to the left of
|
||||||
|
* the specified player.
|
||||||
|
*/
|
||||||
|
public static int getLeftIndex (int pidx)
|
||||||
|
{
|
||||||
|
return (pidx + 1) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games, returns the index of the player to the right of
|
||||||
|
* the specified player.
|
||||||
|
*/
|
||||||
|
public static int getRightIndex (int pidx)
|
||||||
|
{
|
||||||
|
return (pidx + 3) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For four-player games, returns the index of the player across from the
|
||||||
|
* specified player.
|
||||||
|
*/
|
||||||
|
public static int getOppositeIndex (int pidx)
|
||||||
|
{
|
||||||
|
return pidx ^ 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the player can follow the suit lead with the hand given.
|
||||||
|
*/
|
||||||
|
public static boolean canFollowSuit (PlayerCard[] cardsPlayed, Hand hand)
|
||||||
|
{
|
||||||
|
return hand.getSuitMemberCount(cardsPlayed[0].card.getSuit()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the specified array contains the given card.
|
||||||
|
*/
|
||||||
|
public static boolean containsCard (PlayerCard[] cards, Card card)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards.length; i++) {
|
||||||
|
if (cards[i].card.equals(card)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the number of cards that belong to the specified suit within
|
||||||
|
* the array given.
|
||||||
|
*/
|
||||||
|
public static int countSuitMembers (PlayerCard[] cards, int suit)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < cards.length; i++) {
|
||||||
|
if (cards[i].card.getSuit() == suit) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the proposed card follows the suit lead.
|
||||||
|
*/
|
||||||
|
public static boolean followsSuit (PlayerCard[] cardsPlayed, Card card)
|
||||||
|
{
|
||||||
|
return cardsPlayed[0].card.getSuit() == card.getSuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highest card (according to the standard A,K,...,2 ordering)
|
||||||
|
* in the suit lead, with an optional trump suit.
|
||||||
|
*
|
||||||
|
* @param trumpSuit the trump suit, or -1 for none
|
||||||
|
*/
|
||||||
|
public static PlayerCard getHighestInLeadSuit (PlayerCard[] cardsPlayed,
|
||||||
|
int trumpSuit)
|
||||||
|
{
|
||||||
|
PlayerCard highest = cardsPlayed[0];
|
||||||
|
for (int i = 1; i < cardsPlayed.length; i++) {
|
||||||
|
PlayerCard other = cardsPlayed[i];
|
||||||
|
if ((other.card.getSuit() == highest.card.getSuit() &&
|
||||||
|
other.card.compareTo(highest.card) > 0) ||
|
||||||
|
(other.card.getSuit() == trumpSuit &&
|
||||||
|
highest.card.getSuit() != trumpSuit)) {
|
||||||
|
highest = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return highest;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.samskivert.swing.SimpleSlider;
|
||||||
|
import com.samskivert.swing.VGroupLayout;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.TableConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.client.SwingGameConfigurator;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a default implementation of a TableConfigurator for
|
||||||
|
* a Swing interface.
|
||||||
|
*/
|
||||||
|
public class DefaultSwingTableConfigurator extends TableConfigurator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a TableConfigurator that allows only the specified number
|
||||||
|
* of players and lets the configuring user enable private games
|
||||||
|
* only if the number of players is greater than 2.
|
||||||
|
*/
|
||||||
|
public DefaultSwingTableConfigurator (int players)
|
||||||
|
{
|
||||||
|
this(players, (players > 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TableConfigurator that allows only the specified number
|
||||||
|
* of players and lets the user configure a private table, or not.
|
||||||
|
*/
|
||||||
|
public DefaultSwingTableConfigurator (int players, boolean allowPrivate)
|
||||||
|
{
|
||||||
|
this(players, players, players, allowPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TableConfigurator that allows for the specified configuration
|
||||||
|
* parameters.
|
||||||
|
*/
|
||||||
|
public DefaultSwingTableConfigurator (int minPlayers,
|
||||||
|
int desiredPlayers, int maxPlayers, boolean allowPrivate)
|
||||||
|
{
|
||||||
|
_config.minimumPlayerCount = minPlayers;
|
||||||
|
|
||||||
|
// create a slider for players, if applicable
|
||||||
|
if (minPlayers != maxPlayers) {
|
||||||
|
_playerSlider = new SimpleSlider(
|
||||||
|
"", minPlayers, maxPlayers, desiredPlayers);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_config.desiredPlayerCount = desiredPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create up the checkbox for private games, if applicable
|
||||||
|
if (allowPrivate) {
|
||||||
|
_privateCheck = new JCheckBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void createConfigInterface ()
|
||||||
|
{
|
||||||
|
super.createConfigInterface();
|
||||||
|
|
||||||
|
SwingGameConfigurator gconf = (SwingGameConfigurator) _gameConfigurator;
|
||||||
|
|
||||||
|
if (_playerSlider != null) {
|
||||||
|
// TODO: proper translation
|
||||||
|
gconf.addControl(new JLabel("Players:"), _playerSlider);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_privateCheck != null) {
|
||||||
|
// TODO: proper translation
|
||||||
|
gconf.addControl(new JLabel("Private:"), _privateCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean isEmpty ()
|
||||||
|
{
|
||||||
|
return (_playerSlider == null) && (_privateCheck == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void flushTableConfig()
|
||||||
|
{
|
||||||
|
super.flushTableConfig();
|
||||||
|
|
||||||
|
if (_playerSlider != null) {
|
||||||
|
_config.desiredPlayerCount = _playerSlider.getValue();
|
||||||
|
}
|
||||||
|
if (_privateCheck != null) {
|
||||||
|
_config.privateTable = _privateCheck.isSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A slider for configuring the number of players at the table. */
|
||||||
|
protected SimpleSlider _playerSlider;
|
||||||
|
|
||||||
|
/** A checkbox to allow the table creator to specify if the table is
|
||||||
|
* private. */
|
||||||
|
protected JCheckBox _privateCheck;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// $Id: GameReadyObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to inform interested parties when the {@link ParlorDirector}
|
||||||
|
* receives a game ready notification. The observers can ratify the
|
||||||
|
* decision to head directly into the game or can take responsibility
|
||||||
|
* themselves for doing so.
|
||||||
|
*/
|
||||||
|
public interface GameReadyObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when a game ready notification is received.
|
||||||
|
*
|
||||||
|
* @param gameOid the place oid of the ready game.
|
||||||
|
*
|
||||||
|
* @return if the observer returns true from this method, the parlor
|
||||||
|
* director assumes they will take care of entering the game room
|
||||||
|
* after performing processing of their own. If all observers return
|
||||||
|
* false, the director will enter the game room automatically.
|
||||||
|
*/
|
||||||
|
public boolean receivedGameReady (int gameOid);
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
//
|
||||||
|
// $Id: Invitation.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.parlor.Log;
|
||||||
|
import com.threerings.parlor.data.ParlorCodes;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The invitation class is used to track information related to
|
||||||
|
* outstanding invitations generated by or targeted to this client.
|
||||||
|
*/
|
||||||
|
public class Invitation
|
||||||
|
implements ParlorCodes, ParlorService.InviteListener
|
||||||
|
{
|
||||||
|
/** The unique id for this invitation (as assigned by the
|
||||||
|
* server). This is -1 until we receive an acknowledgement from
|
||||||
|
* the server that our invitation was delivered. */
|
||||||
|
public int inviteId = -1;
|
||||||
|
|
||||||
|
/** The name of the other user involved in this invitation. */
|
||||||
|
public Name opponent;
|
||||||
|
|
||||||
|
/** The configuration of the game to be created. */
|
||||||
|
public GameConfig config;
|
||||||
|
|
||||||
|
/** Constructs a new invitation record. */
|
||||||
|
public Invitation (ParlorContext ctx, ParlorService pservice,
|
||||||
|
Name opponent, GameConfig config,
|
||||||
|
InvitationResponseObserver observer)
|
||||||
|
{
|
||||||
|
_ctx = ctx;
|
||||||
|
_pservice = pservice;
|
||||||
|
_observer = observer;
|
||||||
|
this.opponent = opponent;
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts this invitation.
|
||||||
|
*/
|
||||||
|
public void accept ()
|
||||||
|
{
|
||||||
|
// generate the invocation service request
|
||||||
|
_pservice.respond(_ctx.getClient(), inviteId,
|
||||||
|
INVITATION_ACCEPTED, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refuses this invitation.
|
||||||
|
*
|
||||||
|
* @param message the message to deliver to the inviting user
|
||||||
|
* explaining the reason for the refusal or null if no message is to
|
||||||
|
* be provided.
|
||||||
|
*/
|
||||||
|
public void refuse (String message)
|
||||||
|
{
|
||||||
|
// generate the invocation service request
|
||||||
|
_pservice.respond(_ctx.getClient(), inviteId,
|
||||||
|
INVITATION_REFUSED, message, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels this invitation.
|
||||||
|
*/
|
||||||
|
public void cancel ()
|
||||||
|
{
|
||||||
|
// if the invitation has not yet been acknowleged by the
|
||||||
|
// server, we make a note that it should be cancelled when we
|
||||||
|
// do receive the acknowlegement
|
||||||
|
if (inviteId == -1) {
|
||||||
|
_cancelled = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise, generate the invocation service request
|
||||||
|
_pservice.cancel(_ctx.getClient(), inviteId, this);
|
||||||
|
// and remove it from the pending table
|
||||||
|
_ctx.getParlorDirector().clearInvitation(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counters this invitation with an invitation with different game
|
||||||
|
* configuration parameters.
|
||||||
|
*
|
||||||
|
* @param config the updated game configuration.
|
||||||
|
* @param observer the entity that will be notified if this
|
||||||
|
* counter-invitation is accepted, refused or countered.
|
||||||
|
*/
|
||||||
|
public void counter (GameConfig config, InvitationResponseObserver observer)
|
||||||
|
{
|
||||||
|
// update our observer (who will eventually be hearing back from
|
||||||
|
// the other client about their counter-invitation)
|
||||||
|
_observer = observer;
|
||||||
|
|
||||||
|
// generate the invocation service request
|
||||||
|
_pservice.respond(_ctx.getClient(), inviteId,
|
||||||
|
INVITATION_COUNTERED, config, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void inviteReceived (int inviteId)
|
||||||
|
{
|
||||||
|
// fill in our invitation id
|
||||||
|
this.inviteId = inviteId;
|
||||||
|
|
||||||
|
// if the invitation was cancelled before we heard back about
|
||||||
|
// it, we need to send off a cancellation request now
|
||||||
|
if (_cancelled) {
|
||||||
|
_pservice.cancel(_ctx.getClient(), inviteId, this);
|
||||||
|
} else {
|
||||||
|
// otherwise, put it in the pending invites table
|
||||||
|
_ctx.getParlorDirector().registerInvitation(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void requestFailed (String reason)
|
||||||
|
{
|
||||||
|
// let the observer know what's up
|
||||||
|
_observer.invitationRefused(this, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the parlor director when we receive a response to an
|
||||||
|
* invitation initiated by this client.
|
||||||
|
*/
|
||||||
|
protected void receivedResponse (int code, Object arg)
|
||||||
|
{
|
||||||
|
// make sure we have an observer to notify
|
||||||
|
if (_observer == null) {
|
||||||
|
Log.warning("No observer registered for invitation " +
|
||||||
|
this + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify the observer
|
||||||
|
try {
|
||||||
|
switch (code) {
|
||||||
|
case INVITATION_ACCEPTED:
|
||||||
|
_observer.invitationAccepted(this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INVITATION_REFUSED:
|
||||||
|
_observer.invitationRefused(this, (String)arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INVITATION_COUNTERED:
|
||||||
|
_observer.invitationCountered(this, (GameConfig)arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Invitation response observer choked on response " +
|
||||||
|
"[code=" + code + ", arg=" + arg +
|
||||||
|
", invite=" + this + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unless the invitation was countered, we can remove it from the
|
||||||
|
// pending table because it's resolved
|
||||||
|
if (code != INVITATION_COUNTERED) {
|
||||||
|
_ctx.getParlorDirector().clearInvitation(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a string representation of this invitation record. */
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[inviteId=" + inviteId + ", opponent=" + opponent +
|
||||||
|
", config=" + config + ", observer=" + _observer +
|
||||||
|
", cancelled=" + _cancelled + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides access to client services. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** Provides access to parlor services. */
|
||||||
|
protected ParlorService _pservice;
|
||||||
|
|
||||||
|
/** The entity to notify when we receive a response for this
|
||||||
|
* invitation. */
|
||||||
|
protected InvitationResponseObserver _observer;
|
||||||
|
|
||||||
|
/** A flag indicating that we were requested to cancel this
|
||||||
|
* invitation before we even heard back with an acknowledgement
|
||||||
|
* that it was received by the server. */
|
||||||
|
protected boolean _cancelled = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// $Id: InvitationHandler.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A client entity that wishes to handle invitations received by other
|
||||||
|
* clients should implement this interface and register itself with the
|
||||||
|
* parlor director. It will subsequently be notified of any incoming
|
||||||
|
* invitations. It is also responsible for handling cancelled invitations.
|
||||||
|
*/
|
||||||
|
public interface InvitationHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when an invitation is received from another player.
|
||||||
|
*
|
||||||
|
* @param invite the received invitation.
|
||||||
|
*/
|
||||||
|
public void invitationReceived (Invitation invite);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an invitation is cancelled by the inviting player.
|
||||||
|
*
|
||||||
|
* @param invite the cancelled invitation.
|
||||||
|
*/
|
||||||
|
public void invitationCancelled (Invitation invite);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// $Id: InvitationResponseObserver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A client entity that wishes to generate invitations for games must
|
||||||
|
* implement this interface. An invitation can be accepted, refused or
|
||||||
|
* countered. A countered invitation is one where the game configuration
|
||||||
|
* is adjusted by the invited player and proposed back to the inviting
|
||||||
|
* player.
|
||||||
|
*/
|
||||||
|
public interface InvitationResponseObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called if the invitation was accepted.
|
||||||
|
*
|
||||||
|
* @param invite the invitation for which we received a response.
|
||||||
|
*/
|
||||||
|
public void invitationAccepted (Invitation invite);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if the invitation was refused.
|
||||||
|
*
|
||||||
|
* @param invite the invitation for which we received a response.
|
||||||
|
* @param message a message provided by the invited user explaining
|
||||||
|
* the reason for their refusal, or the empty string if no message was
|
||||||
|
* provided.
|
||||||
|
*/
|
||||||
|
public void invitationRefused (Invitation invite, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if the invitation was countered with an alternate game
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @param invite the invitation for which we received a response.
|
||||||
|
* @param config the game configuration proposed by the invited
|
||||||
|
* player.
|
||||||
|
*/
|
||||||
|
public void invitationCountered (Invitation invite, GameConfig config);
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorDecoder.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.ParlorReceiver;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.presents.client.InvocationDecoder;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches calls to a {@link ParlorReceiver} instance.
|
||||||
|
*/
|
||||||
|
public class ParlorDecoder extends InvocationDecoder
|
||||||
|
{
|
||||||
|
/** The generated hash code used to identify this receiver class. */
|
||||||
|
public static final String RECEIVER_CODE = "5ef9ee0d359c42a9024498ee9aad119a";
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link ParlorReceiver#gameIsReady}
|
||||||
|
* notifications. */
|
||||||
|
public static final int GAME_IS_READY = 1;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link ParlorReceiver#receivedInvite}
|
||||||
|
* notifications. */
|
||||||
|
public static final int RECEIVED_INVITE = 2;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteCancellation}
|
||||||
|
* notifications. */
|
||||||
|
public static final int RECEIVED_INVITE_CANCELLATION = 3;
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteResponse}
|
||||||
|
* notifications. */
|
||||||
|
public static final int RECEIVED_INVITE_RESPONSE = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a decoder that may be registered to dispatch invocation
|
||||||
|
* service notifications to the specified receiver.
|
||||||
|
*/
|
||||||
|
public ParlorDecoder (ParlorReceiver receiver)
|
||||||
|
{
|
||||||
|
this.receiver = receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public String getReceiverCode ()
|
||||||
|
{
|
||||||
|
return RECEIVER_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchNotification (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case GAME_IS_READY:
|
||||||
|
((ParlorReceiver)receiver).gameIsReady(
|
||||||
|
((Integer)args[0]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RECEIVED_INVITE:
|
||||||
|
((ParlorReceiver)receiver).receivedInvite(
|
||||||
|
((Integer)args[0]).intValue(), (Name)args[1], (GameConfig)args[2]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RECEIVED_INVITE_CANCELLATION:
|
||||||
|
((ParlorReceiver)receiver).receivedInviteCancellation(
|
||||||
|
((Integer)args[0]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RECEIVED_INVITE_RESPONSE:
|
||||||
|
((ParlorReceiver)receiver).receivedInviteResponse(
|
||||||
|
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (Object)args[2]
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchNotification(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorDirector.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.samskivert.util.HashIntMap;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.BasicDirector;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
|
||||||
|
import com.threerings.parlor.Log;
|
||||||
|
import com.threerings.parlor.data.ParlorCodes;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parlor director manages the client side of the game configuration
|
||||||
|
* and matchmaking processes. It is also the entity that is listening for
|
||||||
|
* game start notifications which it then dispatches the client entity
|
||||||
|
* that will actually create and display the user interface for the game
|
||||||
|
* that started.
|
||||||
|
*/
|
||||||
|
public class ParlorDirector extends BasicDirector
|
||||||
|
implements ParlorCodes, ParlorReceiver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a parlor director and provides it with the parlor
|
||||||
|
* context that it can use to access the client services that it needs
|
||||||
|
* to provide its own services. Only one parlor director should be
|
||||||
|
* active in the client at one time and it should be made available
|
||||||
|
* via the parlor context.
|
||||||
|
*
|
||||||
|
* @param ctx the parlor context in use by the client.
|
||||||
|
*/
|
||||||
|
public ParlorDirector (ParlorContext ctx)
|
||||||
|
{
|
||||||
|
super(ctx);
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// register ourselves with the invocation director as a parlor
|
||||||
|
// notification receiver
|
||||||
|
_ctx.getClient().getInvocationDirector().registerReceiver(
|
||||||
|
new ParlorDecoder(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the invitation handler, which is the entity that will be
|
||||||
|
* notified when we receive incoming invitation notifications and when
|
||||||
|
* invitations have been cancelled.
|
||||||
|
*
|
||||||
|
* @param handler our new invitation handler.
|
||||||
|
*/
|
||||||
|
public void setInvitationHandler (InvitationHandler handler)
|
||||||
|
{
|
||||||
|
_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified observer to the list of entities that are
|
||||||
|
* notified when we receive a game ready notification.
|
||||||
|
*/
|
||||||
|
public void addGameReadyObserver (GameReadyObserver observer)
|
||||||
|
{
|
||||||
|
_grobs.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified observer from the list of entities that are
|
||||||
|
* notified when we receive a game ready notification.
|
||||||
|
*/
|
||||||
|
public void removeGameReadyObserver (GameReadyObserver observer)
|
||||||
|
{
|
||||||
|
_grobs.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the named user be invited to a game described by the
|
||||||
|
* supplied game config.
|
||||||
|
*
|
||||||
|
* @param invitee the user to invite.
|
||||||
|
* @param config the configuration of the game to which the user is
|
||||||
|
* being invited.
|
||||||
|
* @param observer the entity that will be notified if this invitation
|
||||||
|
* is accepted, refused or countered.
|
||||||
|
*
|
||||||
|
* @return an invitation object that can be used to manage the
|
||||||
|
* outstanding invitation.
|
||||||
|
*/
|
||||||
|
public Invitation invite (Name invitee, GameConfig config,
|
||||||
|
InvitationResponseObserver observer)
|
||||||
|
{
|
||||||
|
// create the invitation record
|
||||||
|
Invitation invite = new Invitation(
|
||||||
|
_ctx, _pservice, invitee, config, observer);
|
||||||
|
// submit the invitation request to the server
|
||||||
|
_pservice.invite(_ctx.getClient(), invitee, config, invite);
|
||||||
|
// and return the invitation to the caller
|
||||||
|
return invite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified single player game be started.
|
||||||
|
*
|
||||||
|
* @param config the configuration of the single player game to be
|
||||||
|
* started.
|
||||||
|
* @param listener a listener to be informed of failure if the game
|
||||||
|
* cannot be started.
|
||||||
|
*/
|
||||||
|
public void startSolitaire (
|
||||||
|
GameConfig config, InvocationService.ConfirmListener listener)
|
||||||
|
{
|
||||||
|
_pservice.startSolitaire(_ctx.getClient(), config, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogoff (Client client)
|
||||||
|
{
|
||||||
|
super.clientDidLogoff(client);
|
||||||
|
_pservice = null;
|
||||||
|
_pendingInvites.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void fetchServices (Client client)
|
||||||
|
{
|
||||||
|
// get a handle on our parlor services
|
||||||
|
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void gameIsReady (int gameOid)
|
||||||
|
{
|
||||||
|
Log.info("Handling game ready [goid=" + gameOid + "].");
|
||||||
|
|
||||||
|
// see what our observers have to say about it
|
||||||
|
boolean handled = false;
|
||||||
|
for (int i = 0; i < _grobs.size(); i++) {
|
||||||
|
GameReadyObserver grob = (GameReadyObserver)_grobs.get(i);
|
||||||
|
handled = grob.receivedGameReady(gameOid) || handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if none of the observers took matters into their own hands,
|
||||||
|
// then we'll head on over to the game room ourselves
|
||||||
|
if (!handled) {
|
||||||
|
_ctx.getLocationDirector().moveTo(gameOid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void receivedInvite (int remoteId, Name inviter, GameConfig config)
|
||||||
|
{
|
||||||
|
// create an invitation record for this invitation
|
||||||
|
Invitation invite = new Invitation(
|
||||||
|
_ctx, _pservice, inviter, config, null);
|
||||||
|
invite.inviteId = remoteId;
|
||||||
|
|
||||||
|
// put it in the pending invitations table
|
||||||
|
_pendingInvites.put(remoteId, invite);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// notify the invitation handler of the incoming invitation
|
||||||
|
_handler.invitationReceived(invite);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Invitation handler choked on invite " +
|
||||||
|
"notification " + invite + ".");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void receivedInviteResponse (
|
||||||
|
int remoteId, int code, Object arg)
|
||||||
|
{
|
||||||
|
// look up the invitation record for this invitation
|
||||||
|
Invitation invite = (Invitation)_pendingInvites.get(remoteId);
|
||||||
|
if (invite == null) {
|
||||||
|
Log.warning("Have no record of invitation for which we " +
|
||||||
|
"received a response?! [remoteId=" + remoteId +
|
||||||
|
", code=" + code + ", arg=" + arg + "].");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
invite.receivedResponse(code, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void receivedInviteCancellation (int remoteId)
|
||||||
|
{
|
||||||
|
// TBD
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new invitation in our pending invitations table. The
|
||||||
|
* invitation will call this when it knows its invitation id.
|
||||||
|
*/
|
||||||
|
protected void registerInvitation (Invitation invite)
|
||||||
|
{
|
||||||
|
_pendingInvites.put(invite.inviteId, invite);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by an invitation when it knows it is no longer and can be
|
||||||
|
* cleared from the pending invitations table.
|
||||||
|
*/
|
||||||
|
protected void clearInvitation (Invitation invite)
|
||||||
|
{
|
||||||
|
_pendingInvites.remove(invite.inviteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An active parlor context. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** Provides access to parlor server side services. */
|
||||||
|
protected ParlorService _pservice;
|
||||||
|
|
||||||
|
/** The entity that has registered itself to handle incoming
|
||||||
|
* invitation notifications. */
|
||||||
|
protected InvitationHandler _handler;
|
||||||
|
|
||||||
|
/** A table of acknowledged (but not yet accepted or refused)
|
||||||
|
* invitation requests, keyed on invitation id. */
|
||||||
|
protected HashIntMap _pendingInvites = new HashIntMap();
|
||||||
|
|
||||||
|
/** We notify the entities on this list when we get a game ready
|
||||||
|
* notification. */
|
||||||
|
protected ArrayList _grobs = new ArrayList();
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorReceiver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.InvocationReceiver;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.ParlorCodes;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines, for the parlor services, a set of notifications delivered
|
||||||
|
* asynchronously by the server to the client. These are handled by the
|
||||||
|
* {@link ParlorDirector}.
|
||||||
|
*/
|
||||||
|
public interface ParlorReceiver extends InvocationReceiver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Dispatched to the client when a game in which they are a
|
||||||
|
* participant is ready for play. The client will then enter the game
|
||||||
|
* room which will trigger the loading of the appropriate game UI code
|
||||||
|
* and generally get things started.
|
||||||
|
*
|
||||||
|
* @param gameOid the object id of the game object.
|
||||||
|
*/
|
||||||
|
public void gameIsReady (int gameOid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the invocation services when another user has invited us
|
||||||
|
* to play a game.
|
||||||
|
*
|
||||||
|
* @param remoteId the unique indentifier for this invitation (used
|
||||||
|
* when countering or responding).
|
||||||
|
* @param inviter the username of the inviting user.
|
||||||
|
* @param config the configuration information for the game to which
|
||||||
|
* we've been invited.
|
||||||
|
*/
|
||||||
|
public void receivedInvite (int remoteId, Name inviter, GameConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the invocation services when another user has responded
|
||||||
|
* to our invitation by either accepting, refusing or countering it.
|
||||||
|
*
|
||||||
|
* @param remoteId the indentifier for the invitation on question.
|
||||||
|
* @param code the response code, either {@link
|
||||||
|
* ParlorCodes#INVITATION_ACCEPTED} or {@link
|
||||||
|
* ParlorCodes#INVITATION_REFUSED} or {@link
|
||||||
|
* ParlorCodes#INVITATION_COUNTERED}.
|
||||||
|
* @param arg in the case of a refused invitation, a string
|
||||||
|
* containing a message provided by the invited user explaining the
|
||||||
|
* reason for refusal (the empty string if no explanation was
|
||||||
|
* provided). In the case of a countered invitation, a new game config
|
||||||
|
* object with the modified game configuration.
|
||||||
|
*/
|
||||||
|
public void receivedInviteResponse (int remoteId, int code, Object arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the invocation services when an outstanding invitation
|
||||||
|
* has been cancelled by the inviting user.
|
||||||
|
*
|
||||||
|
* @param remoteId the indentifier of the cancelled invitation.
|
||||||
|
*/
|
||||||
|
public void receivedInviteCancellation (int remoteId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorService.java 3525 2005-04-26 02:38:42Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.TableConfig;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an interface to the various parlor invocation services.
|
||||||
|
* Presently these services are limited to the various matchmaking
|
||||||
|
* mechanisms. It is unlikely that client code will want to make direct
|
||||||
|
* use of this class, instead they would make use of the programmatic
|
||||||
|
* interface provided by the {@link ParlorDirector}.
|
||||||
|
*/
|
||||||
|
public interface ParlorService extends InvocationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used to communicate responses to {@link #invite} requests.
|
||||||
|
*/
|
||||||
|
public static interface InviteListener extends InvocationListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called in response to a successful {@link #invite} request.
|
||||||
|
*/
|
||||||
|
public void inviteReceived (int inviteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to generate
|
||||||
|
* your invitation request via {@link ParlorDirector#invite}. Requests
|
||||||
|
* that an invitation be delivered to the named user, requesting that
|
||||||
|
* they join the inviting user in a game, the details of which are
|
||||||
|
* specified in the supplied game config object.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param invitee the username of the user to be invited.
|
||||||
|
* @param config a game config object detailing the type and
|
||||||
|
* configuration of the game to be created.
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void invite (Client client, Name invitee, GameConfig config,
|
||||||
|
InviteListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to call one
|
||||||
|
* of {@link Invitation#accept}, {@link Invitation#refuse}, or {@link
|
||||||
|
* Invitation#counter}. Requests that an invitation response be
|
||||||
|
* delivered with the specified parameters.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param inviteId the unique id previously assigned by the server to
|
||||||
|
* this invitation.
|
||||||
|
* @param code the response code to use in responding to the
|
||||||
|
* invitation.
|
||||||
|
* @param arg the argument associated with the response (a string
|
||||||
|
* message from the player explaining why the response was refused in
|
||||||
|
* the case of an invitation refusal or an updated game configuration
|
||||||
|
* object in the case of a counter-invitation, or null in the case of
|
||||||
|
* an accepted invitation).
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void respond (Client client, int inviteId, int code, Object arg,
|
||||||
|
InvocationListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to call
|
||||||
|
* {@link Invitation#cancel}. Requests that an outstanding
|
||||||
|
* invitation be cancelled.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param inviteId the unique id previously assigned by the server to
|
||||||
|
* this invitation.
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void cancel (Client client, int inviteId,
|
||||||
|
InvocationListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to communicate responses to {@link #createTable}, {@link
|
||||||
|
* #joinTable}, and {@link #leaveTable} requests.
|
||||||
|
*/
|
||||||
|
public static interface TableListener extends InvocationListener
|
||||||
|
{
|
||||||
|
public void tableCreated (int tableId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to call
|
||||||
|
* {@link TableDirector#createTable}. Requests that a new table be
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param lobbyOid the oid of the lobby that will contain the newly
|
||||||
|
* created table.
|
||||||
|
* @param tableConfig the table configuration parameters.
|
||||||
|
* @param config the game config for the game to be matchmade by the
|
||||||
|
* table.
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void createTable (Client client, int lobbyOid,
|
||||||
|
TableConfig tableConfig, GameConfig config, TableListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to call
|
||||||
|
* {@link TableDirector#joinTable}. Requests that the current user
|
||||||
|
* be added to the specified table at the specified position.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param lobbyOid the oid of the lobby that contains the table.
|
||||||
|
* @param tableId the unique id of the table to which this user wishes
|
||||||
|
* to be added.
|
||||||
|
* @param position the position at the table to which this user desires
|
||||||
|
* to be added.
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void joinTable (Client client, int lobbyOid, int tableId,
|
||||||
|
int position, InvocationListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You probably don't want to call this directly, but want to call
|
||||||
|
* {@link TableDirector#leaveTable}. Requests that the current user be
|
||||||
|
* removed from the specified table.
|
||||||
|
*
|
||||||
|
* @param client a connected, operational client instance.
|
||||||
|
* @param lobbyOid the oid of the lobby that contains the table.
|
||||||
|
* @param tableId the unique id of the table from which this user
|
||||||
|
* wishes to be removed.
|
||||||
|
* @param listener will receive and process the response.
|
||||||
|
*/
|
||||||
|
public void leaveTable (Client client, int lobbyOid, int tableId,
|
||||||
|
InvocationListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to start a single player game with the specified game
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
public void startSolitaire (Client client, GameConfig config,
|
||||||
|
ConfirmListener listener);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// $Id: SeatednessObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entites that wish to hear about when we sit down at a table or stand up
|
||||||
|
* from a table can implement this interface and register themselves with
|
||||||
|
* the {@link TableDirector}.
|
||||||
|
*/
|
||||||
|
public interface SeatednessObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when this client sits down at or stands up from a table.
|
||||||
|
*
|
||||||
|
* @param isSeated true if the client is now seated at a table, false
|
||||||
|
* if they are now no longer seated at a table.
|
||||||
|
*/
|
||||||
|
public void seatednessDidChange (boolean isSeated);
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.TableConfig;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.client.GameConfigurator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be implemented some user-interface element that allows
|
||||||
|
* the user to configure whichever TableConfig options are relevant.
|
||||||
|
*/
|
||||||
|
public abstract class TableConfigurator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a TableConfigurator.
|
||||||
|
*/
|
||||||
|
public TableConfigurator ()
|
||||||
|
{
|
||||||
|
_config = createTableConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionally, you can set a pre-configured TableConfig
|
||||||
|
* that will be used to initialize the display parameters (if possible).
|
||||||
|
* This should be called prior to init().
|
||||||
|
*/
|
||||||
|
public void setTableConfig (TableConfig config)
|
||||||
|
{
|
||||||
|
if (config != null) {
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the TableConfigurator.
|
||||||
|
*
|
||||||
|
* At the time this is called, the GameConfigurator should have
|
||||||
|
* already been initialized.
|
||||||
|
*/
|
||||||
|
public void init (ParlorContext ctx, GameConfigurator gameConfigurator)
|
||||||
|
{
|
||||||
|
_ctx = ctx;
|
||||||
|
_gameConfigurator = gameConfigurator;
|
||||||
|
createConfigInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the table config object that will be used.
|
||||||
|
*/
|
||||||
|
protected TableConfig createTableConfig ()
|
||||||
|
{
|
||||||
|
return new TableConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the config interface.
|
||||||
|
*/
|
||||||
|
protected void createConfigInterface ()
|
||||||
|
{
|
||||||
|
// nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, the TableConfigurator is empty, which doesn't mean that
|
||||||
|
* it will not return a TableConfig object (for it must), but rather
|
||||||
|
* that there are no user-editable options being presented in the
|
||||||
|
* config interface.
|
||||||
|
*/
|
||||||
|
public abstract boolean isEmpty ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the fully configured table config according to the currently
|
||||||
|
* configured user interface elements.
|
||||||
|
*/
|
||||||
|
public TableConfig getTableConfig ()
|
||||||
|
{
|
||||||
|
flushTableConfig();
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes will want to override this method, flushing
|
||||||
|
* values from the user interface to the table config object.
|
||||||
|
*/
|
||||||
|
protected void flushTableConfig ()
|
||||||
|
{
|
||||||
|
// nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides access to client services. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** The config we're configurating. */
|
||||||
|
protected TableConfig _config;
|
||||||
|
|
||||||
|
/** The game configurator, which we may wish to reference. */
|
||||||
|
protected GameConfigurator _gameConfigurator;
|
||||||
|
}
|
||||||
@@ -0,0 +1,363 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableDirector.java 3758 2005-11-10 23:18:58Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.threerings.presents.client.BasicDirector;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.EntryAddedEvent;
|
||||||
|
import com.threerings.presents.dobj.EntryRemovedEvent;
|
||||||
|
import com.threerings.presents.dobj.EntryUpdatedEvent;
|
||||||
|
import com.threerings.presents.dobj.SetListener;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.Log;
|
||||||
|
import com.threerings.parlor.data.Table;
|
||||||
|
import com.threerings.parlor.data.TableConfig;
|
||||||
|
import com.threerings.parlor.data.TableLobbyObject;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As tables are created and managed within the scope of a place (a
|
||||||
|
* lobby), we want to fold the table management functionality into the
|
||||||
|
* standard hierarchy of place controllers that deal with place-related
|
||||||
|
* functionality on the client. Thus, instead of forcing places that
|
||||||
|
* expect to have tables to extend a <code>TableLobbyController</code> or
|
||||||
|
* something similar, we instead provide the table director which can be
|
||||||
|
* instantiated by the place controller (or specific table related views)
|
||||||
|
* to handle the table matchmaking services.
|
||||||
|
*
|
||||||
|
* <p> Entites that do so, will need to implement the {@link
|
||||||
|
* TableObserver} interface so that the table director can notify them
|
||||||
|
* when table related things happen.
|
||||||
|
*
|
||||||
|
* <p> The table services expect that the place object being used as a
|
||||||
|
* lobby in which the table matchmaking takes place implements the {@link
|
||||||
|
* TableLobbyObject} interface.
|
||||||
|
*/
|
||||||
|
public class TableDirector extends BasicDirector
|
||||||
|
implements SetListener, ParlorService.TableListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new table director to manage tables with the specified
|
||||||
|
* observer which will receive callbacks when interesting table
|
||||||
|
* related things happen.
|
||||||
|
*
|
||||||
|
* @param ctx the parlor context in use by the client.
|
||||||
|
* @param tableField the field name of the distributed set that
|
||||||
|
* contains the tables we will be managing.
|
||||||
|
* @param observer the entity that will receive callbacks when things
|
||||||
|
* happen to the tables.
|
||||||
|
*/
|
||||||
|
public TableDirector (
|
||||||
|
ParlorContext ctx, String tableField, TableObserver observer)
|
||||||
|
{
|
||||||
|
super(ctx);
|
||||||
|
|
||||||
|
// keep track of this stuff
|
||||||
|
_ctx = ctx;
|
||||||
|
_tableField = tableField;
|
||||||
|
_observer = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This must be called by the entity that uses the table director when
|
||||||
|
* the using entity prepares to enter and display a place. It is
|
||||||
|
* assumed that the client is already subscribed to the provided place
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
public void willEnterPlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// add ourselves as a listener to the place object
|
||||||
|
place.addListener(this);
|
||||||
|
|
||||||
|
// and remember this for later
|
||||||
|
_lobby = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This must be called by the entity that uses the table director when
|
||||||
|
* the using entity has left and is done displaying a place.
|
||||||
|
*/
|
||||||
|
public void didLeavePlace (PlaceObject place)
|
||||||
|
{
|
||||||
|
// remove our listenership
|
||||||
|
place.removeListener(this);
|
||||||
|
|
||||||
|
// clear out our lobby reference
|
||||||
|
_lobby = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified observer be added to the list of
|
||||||
|
* observers that are notified when this client sits down at or stands
|
||||||
|
* up from a table.
|
||||||
|
*/
|
||||||
|
public void addSeatednessObserver (SeatednessObserver observer)
|
||||||
|
{
|
||||||
|
_seatedObservers.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified observer be removed from to the list of
|
||||||
|
* observers that are notified when this client sits down at or stands
|
||||||
|
* up from a table.
|
||||||
|
*/
|
||||||
|
public void removeSeatednessObserver (SeatednessObserver observer)
|
||||||
|
{
|
||||||
|
_seatedObservers.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this client is currently seated at a table, false
|
||||||
|
* if they are not.
|
||||||
|
*/
|
||||||
|
public boolean isSeated ()
|
||||||
|
{
|
||||||
|
return (_ourTable != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to create a table with the specified game
|
||||||
|
* configuration. This user will become the owner of this table and
|
||||||
|
* will be added to the first position in the table. The response will
|
||||||
|
* be communicated via the {@link TableObserver} interface.
|
||||||
|
*/
|
||||||
|
public void createTable (TableConfig tableConfig, GameConfig config)
|
||||||
|
{
|
||||||
|
// if we're already in a table, refuse the request
|
||||||
|
if (_ourTable != null) {
|
||||||
|
Log.warning("Ignoring request to create table as we're " +
|
||||||
|
"already in a table [table=" + _ourTable + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we're currently in a place
|
||||||
|
if (_lobby == null) {
|
||||||
|
Log.warning("Requested to create a table but we're not " +
|
||||||
|
"currently in a place [config=" + config + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// go ahead and issue the create request
|
||||||
|
_pservice.createTable(_ctx.getClient(), _lobby.getOid(), tableConfig,
|
||||||
|
config, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to join the specified table at the specified
|
||||||
|
* position. The response will be communicated via the {@link
|
||||||
|
* TableObserver} interface.
|
||||||
|
*/
|
||||||
|
public void joinTable (int tableId, int position)
|
||||||
|
{
|
||||||
|
// if we're already in a table, refuse the request
|
||||||
|
if (_ourTable != null) {
|
||||||
|
Log.warning("Ignoring request to join table as we're " +
|
||||||
|
"already in a table [table=" + _ourTable + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we're currently in a place
|
||||||
|
if (_lobby == null) {
|
||||||
|
Log.warning("Requested to join a table but we're not " +
|
||||||
|
"currently in a place [tableId=" + tableId + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// issue the join request
|
||||||
|
_pservice.joinTable(_ctx.getClient(), _lobby.getOid(), tableId,
|
||||||
|
position, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to leave the specified table at which we are
|
||||||
|
* presumably seated. The response will be communicated via the {@link
|
||||||
|
* TableObserver} interface.
|
||||||
|
*/
|
||||||
|
public void leaveTable (int tableId)
|
||||||
|
{
|
||||||
|
// make sure we're currently in a place
|
||||||
|
if (_lobby == null) {
|
||||||
|
Log.warning("Requested to leave a table but we're not " +
|
||||||
|
"currently in a place [tableId=" + tableId + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// issue the leave request
|
||||||
|
_pservice.leaveTable(_ctx.getClient(), _lobby.getOid(), tableId, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void clientDidLogoff (Client client)
|
||||||
|
{
|
||||||
|
super.clientDidLogoff(client);
|
||||||
|
_pservice = null;
|
||||||
|
_lobby = null;
|
||||||
|
_ourTable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void fetchServices (Client client)
|
||||||
|
{
|
||||||
|
// get a handle on our parlor services
|
||||||
|
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void entryAdded (EntryAddedEvent event)
|
||||||
|
{
|
||||||
|
if (event.getName().equals(_tableField)) {
|
||||||
|
Table table = (Table)event.getEntry();
|
||||||
|
|
||||||
|
// check to see if we just joined a table
|
||||||
|
checkSeatedness(table);
|
||||||
|
|
||||||
|
// now let the observer know what's up
|
||||||
|
_observer.tableAdded(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void entryUpdated (EntryUpdatedEvent event)
|
||||||
|
{
|
||||||
|
if (event.getName().equals(_tableField)) {
|
||||||
|
Table table = (Table)event.getEntry();
|
||||||
|
|
||||||
|
// check to see if we just joined or left a table
|
||||||
|
checkSeatedness(table);
|
||||||
|
|
||||||
|
// now let the observer know what's up
|
||||||
|
_observer.tableUpdated(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void entryRemoved (EntryRemovedEvent event)
|
||||||
|
{
|
||||||
|
if (event.getName().equals(_tableField)) {
|
||||||
|
Integer tableId = (Integer)event.getKey();
|
||||||
|
|
||||||
|
// check to see if our table just disappeared
|
||||||
|
if (_ourTable != null && tableId.equals(_ourTable.tableId)) {
|
||||||
|
_ourTable = null;
|
||||||
|
notifySeatedness(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now let the observer know what's up
|
||||||
|
_observer.tableRemoved(tableId.intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void tableCreated (int tableId)
|
||||||
|
{
|
||||||
|
// nothing much to do here
|
||||||
|
Log.info("Table creation succeeded [tableId=" + tableId + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void requestFailed (String reason)
|
||||||
|
{
|
||||||
|
Log.warning("Table creation failed [reason=" + reason + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if we're a member of this table and notes it as our
|
||||||
|
* table, if so.
|
||||||
|
*/
|
||||||
|
protected void checkSeatedness (Table table)
|
||||||
|
{
|
||||||
|
Table oldTable = _ourTable;
|
||||||
|
|
||||||
|
// if this is the same table as our table, clear out our table
|
||||||
|
// reference and allow it to be added back if we are still in the
|
||||||
|
// table
|
||||||
|
if (table.equals(_ourTable)) {
|
||||||
|
_ourTable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for our username in the occupants array
|
||||||
|
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
|
||||||
|
for (int i = 0; i < table.occupants.length; i++) {
|
||||||
|
if (self.getVisibleName().equals(table.occupants[i])) {
|
||||||
|
_ourTable = table;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if nothing changed, bail now
|
||||||
|
if (oldTable == _ourTable ||
|
||||||
|
(oldTable != null && oldTable.equals(_ourTable))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise notify the observers
|
||||||
|
notifySeatedness(_ourTable != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the seatedness observers of a seatedness change.
|
||||||
|
*/
|
||||||
|
protected void notifySeatedness (boolean isSeated)
|
||||||
|
{
|
||||||
|
int slength = _seatedObservers.size();
|
||||||
|
for (int i = 0; i < slength; i++) {
|
||||||
|
SeatednessObserver observer = (SeatednessObserver)
|
||||||
|
_seatedObservers.get(i);
|
||||||
|
try {
|
||||||
|
observer.seatednessDidChange(isSeated);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Observer choked in seatednessDidChange() " +
|
||||||
|
"[observer=" + observer + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A context by which we can access necessary client services. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** Parlor server-side services. */
|
||||||
|
protected ParlorService _pservice;
|
||||||
|
|
||||||
|
/** The place object in which we're currently managing tables. */
|
||||||
|
protected PlaceObject _lobby;
|
||||||
|
|
||||||
|
/** The field name of the distributed set that contains our tables. */
|
||||||
|
protected String _tableField;
|
||||||
|
|
||||||
|
/** The entity that we talk to when table stuff happens. */
|
||||||
|
protected TableObserver _observer;
|
||||||
|
|
||||||
|
/** The table of which we are a member if any. */
|
||||||
|
protected Table _ourTable;
|
||||||
|
|
||||||
|
/** An array of entities that want to hear about when we stand up or
|
||||||
|
* sit down. */
|
||||||
|
protected ArrayList _seatedObservers = new ArrayList();
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link TableDirector} converts distributed object events into
|
||||||
|
* higher level callbacks to implementers of this interface, which are
|
||||||
|
* expected to render these events sensically in a user interface.
|
||||||
|
*/
|
||||||
|
public interface TableObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when a new table is created.
|
||||||
|
*/
|
||||||
|
public void tableAdded (Table table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when something has changed about a table (occupant list
|
||||||
|
* updated, state changed from matchmaking to in-play, etc.).
|
||||||
|
*/
|
||||||
|
public void tableUpdated (Table table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a table goes away.
|
||||||
|
*/
|
||||||
|
public void tableRemoved (int tableId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorCodes.java 3359 2005-02-19 22:38:06Z mdb $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.data;
|
||||||
|
|
||||||
|
import com.threerings.presents.data.InvocationCodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains codes used by the parlor invocation services.
|
||||||
|
*/
|
||||||
|
public interface ParlorCodes extends InvocationCodes
|
||||||
|
{
|
||||||
|
/** The response code for an accepted invitation. */
|
||||||
|
public static final int INVITATION_ACCEPTED = 0;
|
||||||
|
|
||||||
|
/** The response code for a refused invitation. */
|
||||||
|
public static final int INVITATION_REFUSED = 1;
|
||||||
|
|
||||||
|
/** The response code for a countered invitation. */
|
||||||
|
public static final int INVITATION_COUNTERED = 2;
|
||||||
|
|
||||||
|
/** An error code explaining that an invitation was rejected because
|
||||||
|
* the invited user was not online at the time the invitation was
|
||||||
|
* received. */
|
||||||
|
public static final String INVITEE_NOT_ONLINE = "m.invitee_not_online";
|
||||||
|
|
||||||
|
/** An error code returned when a user requests to join a table that
|
||||||
|
* doesn't exist. */
|
||||||
|
public static final String NO_SUCH_TABLE = "m.no_such_table";
|
||||||
|
|
||||||
|
/** An error code returned when a user requests to join a table at a
|
||||||
|
* position that is not valid. */
|
||||||
|
public static final String INVALID_TABLE_POSITION =
|
||||||
|
"m.invalid_table_position";
|
||||||
|
|
||||||
|
/** An error code returned when a user requests to join a table in a
|
||||||
|
* position that is already occupied. */
|
||||||
|
public static final String TABLE_POSITION_OCCUPIED =
|
||||||
|
"m.table_position_occupied";
|
||||||
|
|
||||||
|
/** An error code returned when a user requests to leave a table that
|
||||||
|
* they were not sitting at in the first place. */
|
||||||
|
public static final String NOT_AT_TABLE = "m.not_at_table";
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// $Id: ParlorMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.data;
|
||||||
|
|
||||||
|
import com.threerings.parlor.client.ParlorService;
|
||||||
|
import com.threerings.parlor.data.TableConfig;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.presents.client.Client;
|
||||||
|
import com.threerings.presents.client.InvocationService;
|
||||||
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the implementation of the {@link ParlorService} interface
|
||||||
|
* that marshalls the arguments and delivers the request to the provider
|
||||||
|
* on the server. Also provides an implementation of the response listener
|
||||||
|
* interfaces that marshall the response arguments and deliver them back
|
||||||
|
* to the requesting client.
|
||||||
|
*/
|
||||||
|
public class ParlorMarshaller extends InvocationMarshaller
|
||||||
|
implements ParlorService
|
||||||
|
{
|
||||||
|
// documentation inherited
|
||||||
|
public static class InviteMarshaller extends ListenerMarshaller
|
||||||
|
implements InviteListener
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #inviteReceived}
|
||||||
|
* responses. */
|
||||||
|
public static final int INVITE_RECEIVED = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void inviteReceived (int arg1)
|
||||||
|
{
|
||||||
|
_invId = null;
|
||||||
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
|
callerOid, requestId, INVITE_RECEIVED,
|
||||||
|
new Object[] { Integer.valueOf(arg1) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchResponse (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case INVITE_RECEIVED:
|
||||||
|
((InviteListener)listener).inviteReceived(
|
||||||
|
((Integer)args[0]).intValue());
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchResponse(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public static class TableMarshaller extends ListenerMarshaller
|
||||||
|
implements TableListener
|
||||||
|
{
|
||||||
|
/** The method id used to dispatch {@link #tableCreated}
|
||||||
|
* responses. */
|
||||||
|
public static final int TABLE_CREATED = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void tableCreated (int arg1)
|
||||||
|
{
|
||||||
|
_invId = null;
|
||||||
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
|
callerOid, requestId, TABLE_CREATED,
|
||||||
|
new Object[] { Integer.valueOf(arg1) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void dispatchResponse (int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
switch (methodId) {
|
||||||
|
case TABLE_CREATED:
|
||||||
|
((TableListener)listener).tableCreated(
|
||||||
|
((Integer)args[0]).intValue());
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
super.dispatchResponse(methodId, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #cancel} requests. */
|
||||||
|
public static final int CANCEL = 1;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void cancel (Client arg1, int arg2, InvocationService.InvocationListener arg3)
|
||||||
|
{
|
||||||
|
ListenerMarshaller listener3 = new ListenerMarshaller();
|
||||||
|
listener3.listener = arg3;
|
||||||
|
sendRequest(arg1, CANCEL, new Object[] {
|
||||||
|
Integer.valueOf(arg2), listener3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #createTable} requests. */
|
||||||
|
public static final int CREATE_TABLE = 2;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void createTable (Client arg1, int arg2, TableConfig arg3, GameConfig arg4, ParlorService.TableListener arg5)
|
||||||
|
{
|
||||||
|
ParlorMarshaller.TableMarshaller listener5 = new ParlorMarshaller.TableMarshaller();
|
||||||
|
listener5.listener = arg5;
|
||||||
|
sendRequest(arg1, CREATE_TABLE, new Object[] {
|
||||||
|
Integer.valueOf(arg2), arg3, arg4, listener5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #invite} requests. */
|
||||||
|
public static final int INVITE = 3;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void invite (Client arg1, Name arg2, GameConfig arg3, ParlorService.InviteListener arg4)
|
||||||
|
{
|
||||||
|
ParlorMarshaller.InviteMarshaller listener4 = new ParlorMarshaller.InviteMarshaller();
|
||||||
|
listener4.listener = arg4;
|
||||||
|
sendRequest(arg1, INVITE, new Object[] {
|
||||||
|
arg2, arg3, listener4
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #joinTable} requests. */
|
||||||
|
public static final int JOIN_TABLE = 4;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void joinTable (Client arg1, int arg2, int arg3, int arg4, InvocationService.InvocationListener arg5)
|
||||||
|
{
|
||||||
|
ListenerMarshaller listener5 = new ListenerMarshaller();
|
||||||
|
listener5.listener = arg5;
|
||||||
|
sendRequest(arg1, JOIN_TABLE, new Object[] {
|
||||||
|
Integer.valueOf(arg2), Integer.valueOf(arg3), Integer.valueOf(arg4), listener5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #leaveTable} requests. */
|
||||||
|
public static final int LEAVE_TABLE = 5;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void leaveTable (Client arg1, int arg2, int arg3, InvocationService.InvocationListener arg4)
|
||||||
|
{
|
||||||
|
ListenerMarshaller listener4 = new ListenerMarshaller();
|
||||||
|
listener4.listener = arg4;
|
||||||
|
sendRequest(arg1, LEAVE_TABLE, new Object[] {
|
||||||
|
Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #respond} requests. */
|
||||||
|
public static final int RESPOND = 6;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void respond (Client arg1, int arg2, int arg3, Object arg4, InvocationService.InvocationListener arg5)
|
||||||
|
{
|
||||||
|
ListenerMarshaller listener5 = new ListenerMarshaller();
|
||||||
|
listener5.listener = arg5;
|
||||||
|
sendRequest(arg1, RESPOND, new Object[] {
|
||||||
|
Integer.valueOf(arg2), Integer.valueOf(arg3), arg4, listener5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #startSolitaire} requests. */
|
||||||
|
public static final int START_SOLITAIRE = 7;
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void startSolitaire (Client arg1, GameConfig arg2, InvocationService.ConfirmListener arg3)
|
||||||
|
{
|
||||||
|
InvocationMarshaller.ConfirmMarshaller listener3 = new InvocationMarshaller.ConfirmMarshaller();
|
||||||
|
listener3.listener = arg3;
|
||||||
|
sendRequest(arg1, START_SOLITAIRE, new Object[] {
|
||||||
|
arg2, listener3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,402 @@
|
|||||||
|
//
|
||||||
|
// $Id: Table.java 4191 2006-06-13 22:42:20Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.data;
|
||||||
|
|
||||||
|
import com.samskivert.util.ArrayIntSet;
|
||||||
|
import com.samskivert.util.ListUtil;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
|
||||||
|
import com.threerings.parlor.data.ParlorCodes;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.game.data.PartyGameConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a table that is being used to matchmake a game by
|
||||||
|
* the Parlor services.
|
||||||
|
*/
|
||||||
|
public class Table
|
||||||
|
implements DSet.Entry, ParlorCodes
|
||||||
|
{
|
||||||
|
/** The unique identifier for this table. */
|
||||||
|
public Integer tableId;
|
||||||
|
|
||||||
|
/** The object id of the lobby object with which this table is
|
||||||
|
* associated. */
|
||||||
|
public int lobbyOid;
|
||||||
|
|
||||||
|
/** The oid of the game that was created from this table or -1 if the
|
||||||
|
* table is still in matchmaking mode. */
|
||||||
|
public int gameOid = -1;
|
||||||
|
|
||||||
|
/** An array of the usernames of the occupants of this table (some
|
||||||
|
* slots may not be filled), or null if a party game. */
|
||||||
|
public Name[] occupants;
|
||||||
|
|
||||||
|
/** The body oids of the occupants of this table, or null if a party game.
|
||||||
|
* (This is not propagated to remote instances.) */
|
||||||
|
public transient int[] bodyOids;
|
||||||
|
|
||||||
|
/** The game config for the game that is being matchmade. */
|
||||||
|
public GameConfig config;
|
||||||
|
|
||||||
|
/** The table configuration object. */
|
||||||
|
public TableConfig tconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new table instance, and assigns it the next monotonically
|
||||||
|
* increasing table id.
|
||||||
|
*
|
||||||
|
* @param lobbyOid the object id of the lobby in which this table is
|
||||||
|
* to live.
|
||||||
|
* @param tconfig the table configuration for this table.
|
||||||
|
* @param config the configuration of the game being matchmade by this
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
public Table (int lobbyOid, TableConfig tconfig, GameConfig config)
|
||||||
|
{
|
||||||
|
// assign a unique table id
|
||||||
|
tableId = Integer.valueOf(++_tableIdCounter);
|
||||||
|
|
||||||
|
// keep track of our lobby oid
|
||||||
|
this.lobbyOid = lobbyOid;
|
||||||
|
|
||||||
|
// keep a casted reference around
|
||||||
|
this.tconfig = tconfig;
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
|
// make room for the maximum number of players
|
||||||
|
if (tconfig.desiredPlayerCount != -1) {
|
||||||
|
occupants = new Name[tconfig.desiredPlayerCount];
|
||||||
|
bodyOids = new int[occupants.length];
|
||||||
|
|
||||||
|
// fill in information on the AIs
|
||||||
|
int acount = (config.ais == null) ? 0 : config.ais.length;
|
||||||
|
for (int ii = 0; ii < acount; ii++) {
|
||||||
|
// TODO: handle this naming business better
|
||||||
|
occupants[ii] = new Name("AI " + (ii+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a blank table instance, suitable for unserialization.
|
||||||
|
*/
|
||||||
|
public Table ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience function for accessing the table id as an int.
|
||||||
|
*/
|
||||||
|
public int getTableId ()
|
||||||
|
{
|
||||||
|
return tableId.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there is no one sitting at this table.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bodyOids.length; i++) {
|
||||||
|
if (bodyOids[i] != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of players currently occupying this table.
|
||||||
|
*/
|
||||||
|
public int getOccupiedCount ()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (int ii = 0; ii < occupants.length; ii++) {
|
||||||
|
if (occupants[ii] != null) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Once a table is ready to play (see {@link #mayBeStarted} and {@link
|
||||||
|
* #shouldBeStarted}), the players array can be fetched using this
|
||||||
|
* method. It will return an array containing the usernames of all of
|
||||||
|
* the players in the game, sized properly and with each player in the
|
||||||
|
* appropriate position.
|
||||||
|
*/
|
||||||
|
public Name[] getPlayers ()
|
||||||
|
{
|
||||||
|
if (isPartyGame()) {
|
||||||
|
return occupants;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and populate the players array
|
||||||
|
Name[] players = new Name[getOccupiedCount()];
|
||||||
|
for (int ii = 0, dex = 0; ii < occupants.length; ii++) {
|
||||||
|
if (occupants[ii] != null) {
|
||||||
|
players[dex++] = occupants[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a team game, get the team member indices of the compressed
|
||||||
|
* players array returned by getPlayers().
|
||||||
|
*/
|
||||||
|
public int[][] getTeamMemberIndices ()
|
||||||
|
{
|
||||||
|
int[][] teams = tconfig.teamMemberIndices;
|
||||||
|
if (teams == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compress the team indexes down
|
||||||
|
ArrayIntSet set = new ArrayIntSet();
|
||||||
|
int[][] newTeams = new int[teams.length][];
|
||||||
|
Name[] players = getPlayers();
|
||||||
|
for (int ii=0; ii < teams.length; ii++) {
|
||||||
|
set.clear();
|
||||||
|
for (int jj=0; jj < teams[ii].length; jj++) {
|
||||||
|
Name occ = occupants[teams[ii][jj]];
|
||||||
|
if (occ != null) {
|
||||||
|
set.add(ListUtil.indexOf(players, occ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newTeams[ii] = set.toIntArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTeams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the game is a party game.
|
||||||
|
*/
|
||||||
|
public boolean isPartyGame ()
|
||||||
|
{
|
||||||
|
return (PartyGameConfig.NOT_PARTY_GAME != getPartyGameType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of party game being played at this table, or
|
||||||
|
* PartyGameConfig.NOT_PARTY_GAME.
|
||||||
|
*/
|
||||||
|
public byte getPartyGameType ()
|
||||||
|
{
|
||||||
|
if (config instanceof PartyGameConfig) {
|
||||||
|
return ((PartyGameConfig) config).getPartyGameType();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return PartyGameConfig.NOT_PARTY_GAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to seat the specified user at the specified position in
|
||||||
|
* this table.
|
||||||
|
*
|
||||||
|
* @param position the position in which to seat the user.
|
||||||
|
* @param occupant the occupant to set.
|
||||||
|
*
|
||||||
|
* @return null if the user was successfully seated, a string error
|
||||||
|
* code explaining the failure if the user was not able to be seated
|
||||||
|
* at that position.
|
||||||
|
*/
|
||||||
|
public String setOccupant (int position, BodyObject occupant)
|
||||||
|
{
|
||||||
|
// make sure the requested position is a valid one
|
||||||
|
if (position >= tconfig.desiredPlayerCount || position < 0) {
|
||||||
|
return INVALID_TABLE_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the requested position is not already occupied
|
||||||
|
if (occupants[position] != null) {
|
||||||
|
return TABLE_POSITION_OCCUPIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise all is well, stick 'em in
|
||||||
|
setOccupantPos(position, occupant);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used for party games, it does no bounds checking
|
||||||
|
* or verification of the player's ability to join, if you are unsure
|
||||||
|
* you should call 'setOccupant'.
|
||||||
|
*/
|
||||||
|
public void setOccupantPos (int position, BodyObject occupant)
|
||||||
|
{
|
||||||
|
occupants[position] = occupant.getVisibleName();
|
||||||
|
bodyOids[position] = occupant.getOid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified user be removed from their seat at this
|
||||||
|
* table.
|
||||||
|
*
|
||||||
|
* @return true if the user was seated at the table and has now been
|
||||||
|
* removed, false if the user was never seated at the table in the
|
||||||
|
* first place.
|
||||||
|
*/
|
||||||
|
public boolean clearOccupant (Name username)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < occupants.length; i++) {
|
||||||
|
if (username.equals(occupants[i])) {
|
||||||
|
clearOccupantPos(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the user identified by the specified body object id
|
||||||
|
* be removed from their seat at this table.
|
||||||
|
*
|
||||||
|
* @return true if the user was seated at the table and has now been
|
||||||
|
* removed, false if the user was never seated at the table in the
|
||||||
|
* first place.
|
||||||
|
*/
|
||||||
|
public boolean clearOccupant (int bodyOid)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bodyOids.length; i++) {
|
||||||
|
if (bodyOid == bodyOids[i]) {
|
||||||
|
clearOccupantPos(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to clear an occupant at the specified position.
|
||||||
|
* Only call this method if you know what you're doing.
|
||||||
|
*/
|
||||||
|
public void clearOccupantPos (int position)
|
||||||
|
{
|
||||||
|
occupants[position] = null;
|
||||||
|
bodyOids[position] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this table has a sufficient number of occupants
|
||||||
|
* that the game can be started.
|
||||||
|
*/
|
||||||
|
public boolean mayBeStarted ()
|
||||||
|
{
|
||||||
|
if (tconfig.teamMemberIndices == null) {
|
||||||
|
// for a normal game, just check to see if we're past the minimum
|
||||||
|
return tconfig.minimumPlayerCount <= getOccupiedCount();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// for a team game, make sure each team has the minimum players
|
||||||
|
int[][] teams = tconfig.teamMemberIndices;
|
||||||
|
for (int ii=0; ii < teams.length; ii++) {
|
||||||
|
int teamCount = 0;
|
||||||
|
for (int jj=0; jj < teams[ii].length; jj++) {
|
||||||
|
if (occupants[teams[ii][jj]] != null) {
|
||||||
|
teamCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (teamCount < tconfig.minimumPlayerCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if sufficient seats are occupied that the game should
|
||||||
|
* be automatically started.
|
||||||
|
*/
|
||||||
|
public boolean shouldBeStarted ()
|
||||||
|
{
|
||||||
|
return tconfig.desiredPlayerCount <= getOccupiedCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this table is in play, false if it is still being
|
||||||
|
* matchmade.
|
||||||
|
*/
|
||||||
|
public boolean inPlay ()
|
||||||
|
{
|
||||||
|
return gameOid != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Comparable getKey ()
|
||||||
|
{
|
||||||
|
return tableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
return (other instanceof Table) &&
|
||||||
|
tableId.equals(((Table) other).tableId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int hashCode ()
|
||||||
|
{
|
||||||
|
return tableId.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a string representation of this table instance.
|
||||||
|
*/
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append(StringUtil.shortClassName(this));
|
||||||
|
buf.append(" [");
|
||||||
|
toString(buf);
|
||||||
|
buf.append("]");
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for toString, ripe for overrideability.
|
||||||
|
*/
|
||||||
|
protected void toString (StringBuilder buf)
|
||||||
|
{
|
||||||
|
buf.append("tableId=").append(tableId);
|
||||||
|
buf.append(", lobbyOid=").append(lobbyOid);
|
||||||
|
buf.append(", gameOid=").append(gameOid);
|
||||||
|
buf.append(", occupants=").append(StringUtil.toString(occupants));
|
||||||
|
buf.append(", config=").append(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A counter for assigning table ids. */
|
||||||
|
protected static int _tableIdCounter = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableConfig.java 3604 2005-06-17 20:25:28Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.data;
|
||||||
|
|
||||||
|
import com.threerings.io.SimpleStreamableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table configuration parameters for a game that is to be matchmade
|
||||||
|
* using the table services.
|
||||||
|
*/
|
||||||
|
public class TableConfig extends SimpleStreamableObject
|
||||||
|
{
|
||||||
|
/** The total number of players that are desired for the table,
|
||||||
|
* or -1 for a party game. For team games, this should be set to the
|
||||||
|
* total number of players overall, as teams may be unequal. */
|
||||||
|
public int desiredPlayerCount;
|
||||||
|
|
||||||
|
/** The minimum number of players needed overall (or per-team if a
|
||||||
|
* team-based game) for the game to start at the creator's discretion. */
|
||||||
|
public int minimumPlayerCount;
|
||||||
|
|
||||||
|
/** If non-null, indicates that this is a team-based game and contains
|
||||||
|
* the team assignments for each player. For example, a game with
|
||||||
|
* three players in two teams- players 0 and 2 versus player 1- would
|
||||||
|
* have { {0, 2}, {1} }; */
|
||||||
|
public int[][] teamMemberIndices;
|
||||||
|
|
||||||
|
/** Whether the table is "private". */
|
||||||
|
public boolean privateTable;
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// $Id: TableLobbyObject.java 4145 2006-05-24 01:24:24Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.data;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface must be implemented by the place object used by a lobby
|
||||||
|
* that wishes to make use of the table services.
|
||||||
|
*/
|
||||||
|
public interface TableLobbyObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a reference to the distributed set instance that will be
|
||||||
|
* holding the tables.
|
||||||
|
*/
|
||||||
|
public DSet getTables ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the supplied table instance to the tables set (using the
|
||||||
|
* appropriate distributed object mechanisms).
|
||||||
|
*/
|
||||||
|
public void addToTables (Table table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the value of the specified table instance in the tables
|
||||||
|
* distributed set (using the appropriate distributed object
|
||||||
|
* mechanisms).
|
||||||
|
*/
|
||||||
|
public void updateTables (Table table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the table instance that matches the specified key from the
|
||||||
|
* tables set (using the appropriate distributed object mechanisms).
|
||||||
|
*/
|
||||||
|
public void removeFromTables (Comparable key);
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// $Id: GameConfigurator.java 3590 2005-06-08 23:20:18Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.game.client;
|
||||||
|
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the base from which interfaces can be built to configure games
|
||||||
|
* prior to starting them. Derived classes would extend the base
|
||||||
|
* configurator adding interface elements and wiring them up properly to
|
||||||
|
* allow the user to configure an instance of their game.
|
||||||
|
*
|
||||||
|
* <p> Clients that use the game configurator will want to instantiate one
|
||||||
|
* based on the class returned from the {@link GameConfig} and then
|
||||||
|
* initialize it with a call to {@link #init}.
|
||||||
|
*/
|
||||||
|
public abstract class GameConfigurator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes this game configurator, creates its user interface
|
||||||
|
* elements and prepares it for display.
|
||||||
|
*/
|
||||||
|
public void init (ParlorContext ctx)
|
||||||
|
{
|
||||||
|
// save this for later
|
||||||
|
_ctx = ctx;
|
||||||
|
|
||||||
|
// create our interface elements
|
||||||
|
createConfigInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default implementation creates nothing.
|
||||||
|
*/
|
||||||
|
protected void createConfigInterface ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides this configurator with its configuration. It should set up
|
||||||
|
* all of its user interface elements to reflect the configuration.
|
||||||
|
*/
|
||||||
|
public void setGameConfig (GameConfig config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
// set up the user interface
|
||||||
|
gotGameConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes will likely want to override this method and
|
||||||
|
* configure their user interface elements accordingly.
|
||||||
|
*/
|
||||||
|
protected void gotGameConfig ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a configured game configuration.
|
||||||
|
*/
|
||||||
|
public GameConfig getGameConfig ()
|
||||||
|
{
|
||||||
|
// flush our changes to the config object
|
||||||
|
flushGameConfig();
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes will want to override this method, flushing values
|
||||||
|
* from the user interface to the game config object so that it is
|
||||||
|
* properly configured prior to being returned to the {@link
|
||||||
|
* #getGameConfig} caller.
|
||||||
|
*/
|
||||||
|
protected void flushGameConfig ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides access to client services. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** Our game configuration. */
|
||||||
|
protected GameConfig _config;
|
||||||
|
}
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
//
|
||||||
|
// $Id: GameController.java 3804 2006-01-13 01:52:36Z ray $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.parlor.game.client;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||||
|
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||||
|
|
||||||
|
import com.threerings.crowd.client.PlaceController;
|
||||||
|
import com.threerings.crowd.client.PlaceControllerDelegate;
|
||||||
|
import com.threerings.crowd.data.BodyObject;
|
||||||
|
import com.threerings.crowd.data.PlaceConfig;
|
||||||
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
|
import com.threerings.crowd.util.CrowdContext;
|
||||||
|
|
||||||
|
import com.threerings.parlor.Log;
|
||||||
|
import com.threerings.parlor.game.data.GameCodes;
|
||||||
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
import com.threerings.parlor.game.data.GameObject;
|
||||||
|
import com.threerings.parlor.game.data.PartyGameConfig;
|
||||||
|
import com.threerings.parlor.util.ParlorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The game controller manages the flow and control of a game on the
|
||||||
|
* client side. This class serves as the root of a hierarchy of controller
|
||||||
|
* classes that aim to provide functionality shared between various
|
||||||
|
* similar games. The base controller provides functionality for starting
|
||||||
|
* and ending the game and for calculating ratings adjustements when a
|
||||||
|
* game ends normally. It also handles the basic house keeping like
|
||||||
|
* subscription to the game object and dispatch of commands and
|
||||||
|
* distributed object events.
|
||||||
|
*/
|
||||||
|
public abstract class GameController extends PlaceController
|
||||||
|
implements AttributeChangeListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes this game controller with the game configuration that
|
||||||
|
* was established during the match making process. Derived classes
|
||||||
|
* may want to override this method to initialize themselves with
|
||||||
|
* game-specific configuration parameters but they should be sure to
|
||||||
|
* call <code>super.init</code> in such cases.
|
||||||
|
*
|
||||||
|
* @param ctx the client context.
|
||||||
|
* @param config the configuration of the game we are intended to
|
||||||
|
* control.
|
||||||
|
*/
|
||||||
|
public void init (CrowdContext ctx, PlaceConfig config)
|
||||||
|
{
|
||||||
|
// cast our references before we call super.init() so that when
|
||||||
|
// super.init() calls createPlaceView(), we have our casted
|
||||||
|
// references already in place
|
||||||
|
_ctx = (ParlorContext)ctx;
|
||||||
|
_config = (GameConfig)config;
|
||||||
|
|
||||||
|
super.init(ctx, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this controller as a listener to the game object (thus derived
|
||||||
|
* classes need not do so) and lets the game manager know that we are
|
||||||
|
* now ready to go.
|
||||||
|
*/
|
||||||
|
public void willEnterPlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.willEnterPlace(plobj);
|
||||||
|
|
||||||
|
// obtain a casted reference
|
||||||
|
_gobj = (GameObject)plobj;
|
||||||
|
|
||||||
|
// if this place object is not our current location we'll need to
|
||||||
|
// add it as an auxiliary chat source
|
||||||
|
BodyObject bobj = (BodyObject)_ctx.getClient().getClientObject();
|
||||||
|
if (bobj.location != plobj.getOid()) {
|
||||||
|
_ctx.getChatDirector().addAuxiliarySource(
|
||||||
|
_gobj, GameCodes.GAME_CHAT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and add ourselves as a listener
|
||||||
|
_gobj.addListener(this);
|
||||||
|
|
||||||
|
// we don't want to claim to be finished until any derived classes
|
||||||
|
// that overrode this method have executed, so we'll queue up a
|
||||||
|
// runnable here that will let the game manager know that we're
|
||||||
|
// ready on the next pass through the distributed event loop
|
||||||
|
Log.info("Entering game " + _gobj.which() + ".");
|
||||||
|
if (_gobj.getPlayerIndex(bobj.getVisibleName()) != -1) {
|
||||||
|
_ctx.getClient().getRunQueue().postRunnable(new Runnable() {
|
||||||
|
public void run () {
|
||||||
|
// finally let the game manager know that we're ready
|
||||||
|
// to roll
|
||||||
|
playerReady();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes our listener registration from the game object and cleans
|
||||||
|
* house.
|
||||||
|
*/
|
||||||
|
public void didLeavePlace (PlaceObject plobj)
|
||||||
|
{
|
||||||
|
super.didLeavePlace(plobj);
|
||||||
|
|
||||||
|
_ctx.getChatDirector().removeAuxiliarySource(_gobj);
|
||||||
|
|
||||||
|
// unlisten to the game object
|
||||||
|
_gobj.removeListener(this);
|
||||||
|
_gobj = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the game is over.
|
||||||
|
*/
|
||||||
|
public boolean isGameOver ()
|
||||||
|
{
|
||||||
|
boolean gameOver =
|
||||||
|
((_gobj != null) ? (_gobj.state != GameObject.IN_PLAY) : true);
|
||||||
|
return (_gameOver || gameOver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the client game over override. This is used in situations
|
||||||
|
* where we determine that the game is over before the server has
|
||||||
|
* informed us of such.
|
||||||
|
*/
|
||||||
|
public void setGameOver (boolean gameOver)
|
||||||
|
{
|
||||||
|
_gameOver = gameOver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link #gameWillReset}, ends the current game (locally, it
|
||||||
|
* does not tell the server to end the game), and waits to receive a
|
||||||
|
* reset notification (which is simply an event setting the game state
|
||||||
|
* to <code>IN_PLAY</code> even though it's already set to
|
||||||
|
* <code>IN_PLAY</code>) from the server which will start up a new
|
||||||
|
* game. Derived classes should override {@link #gameWillReset} to
|
||||||
|
* perform any game-specific animations.
|
||||||
|
*/
|
||||||
|
public void resetGame ()
|
||||||
|
{
|
||||||
|
// let derived classes do their thing
|
||||||
|
gameWillReset();
|
||||||
|
|
||||||
|
// end the game until we receive a new board
|
||||||
|
setGameOver(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique round identifier for the current round.
|
||||||
|
*/
|
||||||
|
public int getRoundId ()
|
||||||
|
{
|
||||||
|
return (_gobj == null) ? -1 : _gobj.roundId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles basic game controller action events. Derived classes should
|
||||||
|
* be sure to call <code>super.handleAction</code> for events they
|
||||||
|
* don't specifically handle.
|
||||||
|
*/
|
||||||
|
public boolean handleAction (ActionEvent action)
|
||||||
|
{
|
||||||
|
return super.handleAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A way for controllers to display a game-related system message.
|
||||||
|
*/
|
||||||
|
public void systemMessage (String bundle, String msg)
|
||||||
|
{
|
||||||
|
_ctx.getChatDirector().displayInfo(
|
||||||
|
bundle, msg, GameCodes.GAME_CHAT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void attributeChanged (AttributeChangedEvent event)
|
||||||
|
{
|
||||||
|
// deal with game state changes
|
||||||
|
if (event.getName().equals(GameObject.STATE)) {
|
||||||
|
if (!stateDidChange(event.getIntValue())) {
|
||||||
|
Log.warning("Game transitioned to unknown state " +
|
||||||
|
"[gobj=" + _gobj +
|
||||||
|
", state=" + event.getIntValue() + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes can override this method if they add additional game
|
||||||
|
* states and should handle transitions to those states, returning true to
|
||||||
|
* indicate they were handled and calling super for the normal game states.
|
||||||
|
*/
|
||||||
|
protected boolean stateDidChange (int state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case GameObject.IN_PLAY:
|
||||||
|
gameDidStart();
|
||||||
|
return true;
|
||||||
|
case GameObject.GAME_OVER:
|
||||||
|
gameDidEnd();
|
||||||
|
return true;
|
||||||
|
case GameObject.CANCELLED:
|
||||||
|
gameWasCancelled();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after we've entered the game and everything has initialized
|
||||||
|
* to notify the server that we, as a player, are ready to play.
|
||||||
|
*/
|
||||||
|
protected void playerReady ()
|
||||||
|
{
|
||||||
|
Log.info("Reporting ready " + _gobj.which() + ".");
|
||||||
|
_gobj.gameService.playerReady(_ctx.getClient());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the game transitions to the <code>IN_PLAY</code>
|
||||||
|
* state. This happens when all of the players have arrived and the
|
||||||
|
* server starts the game.
|
||||||
|
*/
|
||||||
|
protected void gameDidStart ()
|
||||||
|
{
|
||||||
|
if (_gobj == null) {
|
||||||
|
Log.info("Received gameDidStart() after leaving game room.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out our game over flag
|
||||||
|
setGameOver(false);
|
||||||
|
|
||||||
|
// let our delegates do their business
|
||||||
|
applyToDelegates(new DelegateOp() {
|
||||||
|
public void apply (PlaceControllerDelegate delegate) {
|
||||||
|
((GameControllerDelegate)delegate).gameDidStart();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the game transitions to the <code>GAME_OVER</code>
|
||||||
|
* state. This happens when the game reaches some end condition by
|
||||||
|
* normal means (is not cancelled or aborted).
|
||||||
|
*/
|
||||||
|
protected void gameDidEnd ()
|
||||||
|
{
|
||||||
|
// let our delegates do their business
|
||||||
|
applyToDelegates(new DelegateOp() {
|
||||||
|
public void apply (PlaceControllerDelegate delegate) {
|
||||||
|
((GameControllerDelegate)delegate).gameDidEnd();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the game was cancelled for some reason.
|
||||||
|
*/
|
||||||
|
protected void gameWasCancelled ()
|
||||||
|
{
|
||||||
|
// let our delegates do their business
|
||||||
|
applyToDelegates(new DelegateOp() {
|
||||||
|
public void apply (PlaceControllerDelegate delegate) {
|
||||||
|
((GameControllerDelegate)delegate).gameWasCancelled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to give derived classes a chance to display animations, send
|
||||||
|
* a final packet, or do any other business they care to do when the
|
||||||
|
* game is about to reset.
|
||||||
|
*/
|
||||||
|
protected void gameWillReset ()
|
||||||
|
{
|
||||||
|
// let our delegates do their business
|
||||||
|
applyToDelegates(new DelegateOp() {
|
||||||
|
public void apply (PlaceControllerDelegate delegate) {
|
||||||
|
((GameControllerDelegate)delegate).gameWillReset();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to determine if this game is a party game.
|
||||||
|
*/
|
||||||
|
protected boolean isPartyGame ()
|
||||||
|
{
|
||||||
|
return (_config instanceof PartyGameConfig) &&
|
||||||
|
(((PartyGameConfig)_config).getPartyGameType() !=
|
||||||
|
PartyGameConfig.NOT_PARTY_GAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A reference to the active parlor context. */
|
||||||
|
protected ParlorContext _ctx;
|
||||||
|
|
||||||
|
/** Our game configuration information. */
|
||||||
|
protected GameConfig _config;
|
||||||
|
|
||||||
|
/** A reference to the game object for the game that we're
|
||||||
|
* controlling. */
|
||||||
|
protected GameObject _gobj;
|
||||||
|
|
||||||
|
/** A local flag overriding the game over state for situations where
|
||||||
|
* the client knows the game is over before the server has
|
||||||
|
* transitioned the game object accordingly. */
|
||||||
|
protected boolean _gameOver;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user