net.supermathie.jao.client
. Jao
and
JaoGUI
are AWT based and form the basic original
GUI client. JaoSwing
is the most up-to-date
client. JaoCUI
was originally written as the
primary client for visually impaired users, however, the character
input required was not effective enough on the Windows platform
where it was originally targetted. It is intended to make the
Swing client accessible in this way.
JaoInterface
abstract class represents the minimum requirements
for providing an interface to play Jao. The word "interface" in this
context is more akin to "graphical user interface" than "Java interface".
A client which implements this interface has much of the low-level work,
especially messaging and protocol concerns, taken care of.
New Swing based clients should be based on JaoSwing
, and new
computer players should be based on JaoTI
, the Jao Test Interface.
net.supermathie.jao.shared.Message
. They may contain zero or more
instances of any serializable class. Zero or more integers and Strings can
also be sent with no class casting overhead. The protocol allows for
two-way communication through a firewall, as sending and receiving messages are
completely separated and can occur in any fashion. The server could, in theory,
start sending a message back to a client halfway through the client sending
a message to the server. In order to keep the connection open, the client
will send a "ping" message if no other messages have been sent in a configurable
amount of time (10 seconds). The server will ping a client every 10 seconds
and keep track of the timing. This information is sent out to all clients in
the same game or in the lobby.
start-server.bat
or start-server.sh
script. The JaoServer will load the saved rulesets and single rules (if any have been
saved). If the rules can't be loaded, it will automatically load a ruleset for
Screw Your Neighbour.
Because the rules are stored using Java serialization, recompiling the classes
can cause a failure in loading them. At some point they will have a serial
version UID set on them, or an alternate method will be used for saving them.
Each ruleset describes the rules for a particular card game. Single rules are added to
mutable games, such as those based on Mao. These can be sent to the server, and
the server will serialize them to "TheRules" file on shutdown. To look at how
to send new rulesets to a JaoServer, refer to the RuleSetGenerator
class.
A JaoServer is properly shutdown by typing "shutdown" and enter at the console.
It will let all the connected clients know it is shutting down, allow for a period
of time, and then terminate all connections. If there are no running clients, there
is no waiting time, and the server shuts down immediately. The rulesets and single
rules are then saved via serialization to "TheRules" file.
Originally it was planned that rulesets could only be changed by the IP address they
were originally sent from. However, in these days of dynamic IPs that is no longer
possible. The RuleSetWrapper
class holds an IP address (which is always
127.0.0.1) and so, effectively, any ruleset or rule can be overridden. Some sort of
security model is needed: perhaps a user ID/password combination is sufficient,
with the addition of a hash to defeat replay attacks.
The commands "decks" and "commands" can also be issued at the console. These will
display the available decks and the messaging types the JaoServer supports.
The use of the word "command" in this context refers to the "Command" design
pattern[citation needed]. The decks and commands are loaded from the
jao-conf.xml
file in the server-config
directory.
When the JaoServer recieves a message, the message type is examined and a handler,
called a "command", is selected and executed on that message. These commands are
found in net.supermathie.jao.server.command
.
The net.supermathie.jao.shared.Messenger
class provides the basics of
the Jao protocol that are used by both the client and the server. Some of this
code predates JDK 1.1 and thus there are a substantial number of synchronization
primitives that have been created. In particular, the order in which threads are
notified when sleeping on a monitor did not use to be guaranteed. As such, there is
a Hashtable so that only one thread will ever wait on a condition. However, all
known JREs wake threads up in a FIFO order and the documentation now mandates the
ordering, meaning that much of this code is now unnecessary.
The net.supermathie.jao.shared.MessengerServer
class provides the
implementation of the server side of the Jao protocol. The
net.supermathie.jao.shared.MessengerClient
class provides the
implementation of the client side of the Jao protocol.
To create new rulesets, refer to the net.supermathie.jao.server.RuleSetGenerator
class.
This class creates a few different rulesets and sends them to the server.
It was originally intended that rulesets could be added and changed while the server is running.
The initial implementation of Jao was such that the classes were "loose" on the server (not in a JAR file),
and so new classes could be created on the server and be picked up by running clients.
However, a JAR file is much more easily deployed to the server and can be compressed, reducing
the time it takes a browser to load a client for Jao. It may be that the possibility of having
dynamic code deployed during a game will no longer be possible or perhaps the creation of a
custom class loader may yet provide this functionality. At present, there are no mutable games
supported (where new rules requiring new code are created during play) and so this problem is
not an immediate concern.
Screw Your Neighbour is an instance of net.supermathie.jao.shared.TrickTakingRuleSet
.
Trick taking games taking advantage of this class have basic support for determining the
winner of a trick and also validation to ensure players follow suit.
Support for mutable games is envisioned. In the net.supermathie.jao.shared
package see
ActionRule
,
AdditionalPenaltyCardRule
,
BiddingRule
,
CardRule
,
DiscardRule
,
OrderRule
,
PenaltyCardRule
,
SuitChangeRule
and
TrickRule
.
Screw Your Neighbour uses BR1
and TrickRule
in that package. Also see
RuleSet.PropertyRuleSet
.