initial commit
This commit is contained in:
commit
a11f93df4d
99 changed files with 7493 additions and 0 deletions
311
cockatrice/Doxyfile
Normal file
311
cockatrice/Doxyfile
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
# Doxyfile 1.5.5-KDevelop
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Project related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = clienttest
|
||||||
|
PROJECT_NUMBER = 0.1
|
||||||
|
OUTPUT_DIRECTORY =
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF = "The $name class" \
|
||||||
|
"The $name widget" \
|
||||||
|
"The $name file" \
|
||||||
|
is \
|
||||||
|
provides \
|
||||||
|
specifies \
|
||||||
|
contains \
|
||||||
|
represents \
|
||||||
|
a \
|
||||||
|
an \
|
||||||
|
the
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = YES
|
||||||
|
STRIP_FROM_PATH = /home/brukie/
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
DETAILS_AT_TOP = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 8
|
||||||
|
ALIASES =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Build related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
EXTRACT_ALL = NO
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_DIRECTORIES = NO
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to warning and progress messages
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
QUIET = NO
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the input files
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
INPUT = /home/brukie/clienttest
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
FILE_PATTERNS = *.c \
|
||||||
|
*.cc \
|
||||||
|
*.cxx \
|
||||||
|
*.cpp \
|
||||||
|
*.c++ \
|
||||||
|
*.d \
|
||||||
|
*.java \
|
||||||
|
*.ii \
|
||||||
|
*.ixx \
|
||||||
|
*.ipp \
|
||||||
|
*.i++ \
|
||||||
|
*.inl \
|
||||||
|
*.h \
|
||||||
|
*.hh \
|
||||||
|
*.hxx \
|
||||||
|
*.hpp \
|
||||||
|
*.h++ \
|
||||||
|
*.idl \
|
||||||
|
*.odl \
|
||||||
|
*.cs \
|
||||||
|
*.php \
|
||||||
|
*.php3 \
|
||||||
|
*.inc \
|
||||||
|
*.m \
|
||||||
|
*.mm \
|
||||||
|
*.dox \
|
||||||
|
*.py \
|
||||||
|
*.f90 \
|
||||||
|
*.f \
|
||||||
|
*.vhd \
|
||||||
|
*.vhdl \
|
||||||
|
*.C \
|
||||||
|
*.CC \
|
||||||
|
*.C++ \
|
||||||
|
*.II \
|
||||||
|
*.I++ \
|
||||||
|
*.H \
|
||||||
|
*.HH \
|
||||||
|
*.H++ \
|
||||||
|
*.CS \
|
||||||
|
*.PHP \
|
||||||
|
*.PHP3 \
|
||||||
|
*.M \
|
||||||
|
*.MM \
|
||||||
|
*.PY \
|
||||||
|
*.F90 \
|
||||||
|
*.F \
|
||||||
|
*.VHD \
|
||||||
|
*.VHDL \
|
||||||
|
*.C \
|
||||||
|
*.H \
|
||||||
|
*.tlh \
|
||||||
|
*.diff \
|
||||||
|
*.patch \
|
||||||
|
*.moc \
|
||||||
|
*.xpm \
|
||||||
|
*.dox
|
||||||
|
RECURSIVE = yes
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS = *
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to source browsing
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SOURCE_BROWSER = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = NO
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the alphabetical class index
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
COLS_IN_ALPHA_INDEX = 5
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the HTML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_ALIGN_MEMBERS = YES
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
GENERATE_TREEVIEW = NONE
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the LaTeX output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_LATEX = YES
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4wide
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
PDF_HYPERLINKS = YES
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the RTF output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the man page output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_LINKS = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the XML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_XML = yes
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_SCHEMA =
|
||||||
|
XML_DTD =
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options for the AutoGen Definitions output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the Perl module output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the preprocessor
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::additions related to external references
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE = clienttest.tag
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
PERL_PATH = /usr/bin/perl
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the dot tool
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
CLASS_DIAGRAMS = YES
|
||||||
|
MSCGEN_PATH =
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
DOT_FONTNAME = FreeSans
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 1000
|
||||||
|
DOT_TRANSPARENT = YES
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::additions related to the search engine
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SEARCHENGINE = NO
|
15
cockatrice/clienttest.pro
Normal file
15
cockatrice/clienttest.pro
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
######################################################################
|
||||||
|
# Automatically generated by qmake (2.01a) Sa Sep 6 14:27:18 2008
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
TARGET =
|
||||||
|
DEPENDPATH += . src
|
||||||
|
INCLUDEPATH += . src
|
||||||
|
|
||||||
|
QT += network opengl
|
||||||
|
#QTPLUGIN += qjpeg
|
||||||
|
|
||||||
|
# Input
|
||||||
|
HEADERS += src/counter.h src/dlg_games.h src/dlg_creategame.h src/dlg_connect.h src/gamesmodel.h src/client.h src/window.h src/servergame.h src/servereventdata.h src/serverresponse.h src/pendingcommand.h src/zonelist.h src/counterlist.h src/playerzone.h src/player.h src/cardlist.h src/carditem.h src/tablezone.h src/handzone.h src/playerlist.h src/game.h src/carddatabase.h src/gameview.h src/decklistmodel.h src/dlg_startgame.h src/cardinfowidget.h src/messagelogwidget.h src/serverzonecard.h src/zoneviewzone.h src/zoneviewwidget.h src/libraryzone.h src/gravezone.h src/rfgzone.h src/sideboardzone.h src/carddragitem.h src/zoneclosebutton.h src/zoneviewlayout.h
|
||||||
|
SOURCES += src/counter.cpp src/dlg_games.cpp src/dlg_creategame.cpp src/dlg_connect.cpp src/client.cpp src/main.cpp src/window.cpp src/servereventdata.cpp src/gamesmodel.cpp src/player.cpp src/playerzone.cpp src/zonelist.cpp src/counterlist.cpp src/cardlist.cpp src/carditem.cpp src/tablezone.cpp src/handzone.cpp src/playerlist.cpp src/game.cpp src/carddatabase.cpp src/gameview.cpp src/decklistmodel.cpp src/dlg_startgame.cpp src/cardinfowidget.cpp src/messagelogwidget.cpp src/zoneviewzone.cpp src/zoneviewwidget.cpp src/libraryzone.cpp src/gravezone.cpp src/rfgzone.cpp src/sideboardzone.cpp src/carddragitem.cpp src/zoneclosebutton.cpp src/zoneviewlayout.cpp
|
340
cockatrice/copying
Normal file
340
cockatrice/copying
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 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.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
203
cockatrice/src/carddatabase.cpp
Normal file
203
cockatrice/src/carddatabase.cpp
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
CardInfo::CardInfo(const QString &_name, const QString &_manacost, const QString &_cardtype, const QString &_powtough, const QStringList &_text)
|
||||||
|
: name(_name), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), pixmap(NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CardInfo::CardInfo(QDataStream &stream)
|
||||||
|
: pixmap(NULL)
|
||||||
|
{
|
||||||
|
stream >> name
|
||||||
|
>> editions
|
||||||
|
>> manacost
|
||||||
|
>> cardtype
|
||||||
|
>> powtough
|
||||||
|
>> text;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardInfo::~CardInfo()
|
||||||
|
{
|
||||||
|
if (pixmap)
|
||||||
|
qDebug(QString("Deleting pixmap for %1").arg(name).toLatin1());
|
||||||
|
delete pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfo::addEdition(const QString &edition)
|
||||||
|
{
|
||||||
|
if (!editions.contains(edition))
|
||||||
|
editions << edition;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap *CardInfo::getPixmap()
|
||||||
|
{
|
||||||
|
if (pixmap)
|
||||||
|
return pixmap;
|
||||||
|
pixmap = new QPixmap();
|
||||||
|
if (getName().isEmpty()) {
|
||||||
|
pixmap->load("../pics/back.jpg");
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
qDebug(QString("CardDatabase: loading pixmap for %1").arg(getName()).toLatin1());
|
||||||
|
for (int i = 0; i < editions.size(); i++) {
|
||||||
|
/* Fire // Ice */
|
||||||
|
if (pixmap->load(QString("../pics/%1/%2.full.jpg").arg(editions.at(i)).arg(getName().replace(" // ", ""))))
|
||||||
|
return pixmap;
|
||||||
|
if (pixmap->load(QString("../pics/%1/%2%3.full.jpg").arg(editions.at(i)).arg(getName().replace(" // ", "")).arg(1)))
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
pixmap->load("../pics/none.jpg");
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfo::saveToStream(QDataStream &stream)
|
||||||
|
{
|
||||||
|
stream << name
|
||||||
|
<< editions
|
||||||
|
<< manacost
|
||||||
|
<< cardtype
|
||||||
|
<< powtough
|
||||||
|
<< text;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardDatabase::CardDatabase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CardDatabase::~CardDatabase()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDatabase::clear()
|
||||||
|
{
|
||||||
|
QHashIterator<QString, CardInfo *> i(hash);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
delete i.value();
|
||||||
|
}
|
||||||
|
hash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CardInfo *CardDatabase::getCard(const QString &cardName)
|
||||||
|
{
|
||||||
|
if (hash.contains(cardName))
|
||||||
|
return hash.value(cardName);
|
||||||
|
else {
|
||||||
|
qDebug(QString("CardDatabase: card not found: %1").arg(cardName).toLatin1());
|
||||||
|
CardInfo *newCard = new CardInfo(cardName);
|
||||||
|
newCard->addEdition("TK");
|
||||||
|
hash.insert(cardName, newCard);
|
||||||
|
return newCard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDatabase::importOracle()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
QDir dir("../db");
|
||||||
|
|
||||||
|
// XXX User soll selber auswählen können, welche Karten ihm am besten gefallen.
|
||||||
|
// XXX Muss momentan schmutzig über Zahlen vor den Dateinamen gemacht werden.
|
||||||
|
|
||||||
|
dir.setSorting(QDir::Name | QDir::IgnoreCase);
|
||||||
|
QFileInfoList files = dir.entryInfoList(QStringList() << "*.txt");
|
||||||
|
for (int k = 0; k < files.size(); k++) {
|
||||||
|
QFileInfo i = files[k];
|
||||||
|
QString edition = i.fileName().mid(i.fileName().indexOf('_') + 1);
|
||||||
|
edition = edition.left(edition.indexOf('.'));
|
||||||
|
QFile file(i.filePath());
|
||||||
|
file.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QTextStream in(&file);
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
QString cardname = in.readLine();
|
||||||
|
QString manacost = in.readLine();
|
||||||
|
QString cardtype, powtough;
|
||||||
|
QStringList text;
|
||||||
|
if (manacost.contains("Land", Qt::CaseInsensitive)) {
|
||||||
|
cardtype = manacost;
|
||||||
|
manacost.clear();
|
||||||
|
} else {
|
||||||
|
cardtype = in.readLine();
|
||||||
|
powtough = in.readLine();
|
||||||
|
// Dirty hack.
|
||||||
|
// Cards to test: Any creature, any basic land, Ancestral Vision, Fire // Ice.
|
||||||
|
if (!powtough.contains("/") || powtough.size() > 5) {
|
||||||
|
text << powtough;
|
||||||
|
powtough = QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString line = in.readLine();
|
||||||
|
while (!line.isEmpty()) {
|
||||||
|
text << line;
|
||||||
|
line = in.readLine();
|
||||||
|
}
|
||||||
|
CardInfo *card;
|
||||||
|
if (hash.contains(cardname))
|
||||||
|
card = hash.value(cardname);
|
||||||
|
else {
|
||||||
|
card = new CardInfo(cardname, manacost, cardtype, powtough, text);
|
||||||
|
hash.insert(cardname, card);
|
||||||
|
}
|
||||||
|
card->addEdition(edition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug(QString("CardDatabase: %1 cards imported").arg(hash.size()).toLatin1());
|
||||||
|
|
||||||
|
CardInfo *empty = new CardInfo();
|
||||||
|
empty->getPixmap(); // cache pixmap for card back
|
||||||
|
hash.insert("", empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CardDatabase::loadFromFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QDataStream in(&file);
|
||||||
|
in.setVersion(QDataStream::Qt_4_4);
|
||||||
|
|
||||||
|
quint32 _magicNumber, _fileVersion, cardCount;
|
||||||
|
in >> _magicNumber
|
||||||
|
>> _fileVersion
|
||||||
|
>> cardCount;
|
||||||
|
|
||||||
|
if (_magicNumber != magicNumber)
|
||||||
|
return -1;
|
||||||
|
if (_fileVersion != fileVersion)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
hash.reserve(cardCount);
|
||||||
|
for (unsigned int i = 0; i < cardCount; i++) {
|
||||||
|
CardInfo *newCard = new CardInfo(in);
|
||||||
|
hash.insert(newCard->getName(), newCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cardCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CardDatabase::saveToFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
QDataStream out(&file);
|
||||||
|
out.setVersion(QDataStream::Qt_4_4);
|
||||||
|
|
||||||
|
out << (quint32) magicNumber
|
||||||
|
<< (quint32) fileVersion
|
||||||
|
<< (quint32) hash.size();
|
||||||
|
|
||||||
|
QHashIterator<QString, CardInfo *> i(hash);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
i.value()->saveToStream(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
51
cockatrice/src/carddatabase.h
Normal file
51
cockatrice/src/carddatabase.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef CARDDATABASE_H
|
||||||
|
#define CARDDATABASE_H
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
class CardInfo {
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QStringList editions;
|
||||||
|
QString manacost;
|
||||||
|
QString cardtype;
|
||||||
|
QString powtough;
|
||||||
|
QStringList text;
|
||||||
|
QPixmap *pixmap;
|
||||||
|
public:
|
||||||
|
CardInfo(const QString &_name = QString(),
|
||||||
|
const QString &_manacost = QString(),
|
||||||
|
const QString &_cardtype = QString(),
|
||||||
|
const QString &_powtough = QString(),
|
||||||
|
const QStringList &_text = QStringList());
|
||||||
|
CardInfo(QDataStream &stream);
|
||||||
|
~CardInfo();
|
||||||
|
QString getName() const { return name; }
|
||||||
|
QStringList getEditions() const { return editions; }
|
||||||
|
QString getManacost() const { return manacost; }
|
||||||
|
QString getCardType() const { return cardtype; }
|
||||||
|
QString getPowTough() const { return powtough; }
|
||||||
|
QStringList getText() const { return text; }
|
||||||
|
void addEdition(const QString &edition);
|
||||||
|
QPixmap *getPixmap();
|
||||||
|
void saveToStream(QDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CardDatabase {
|
||||||
|
private:
|
||||||
|
QHash<QString, CardInfo *> hash;
|
||||||
|
static const unsigned int magicNumber = 0x12345678;
|
||||||
|
static const unsigned int fileVersion = 1;
|
||||||
|
public:
|
||||||
|
CardDatabase();
|
||||||
|
~CardDatabase();
|
||||||
|
void clear();
|
||||||
|
CardInfo *getCard(const QString &cardName = QString());
|
||||||
|
void importOracle();
|
||||||
|
int loadFromFile(const QString &fileName);
|
||||||
|
bool saveToFile(const QString &fileName);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
97
cockatrice/src/carddragitem.cpp
Normal file
97
cockatrice/src/carddragitem.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#include "carddragitem.h"
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
CardDragItem::CardDragItem(QGraphicsScene *scene, PlayerZone *_startZone, QPixmap *_image, int _id, const QPointF &_hotSpot, QGraphicsItem *parent)
|
||||||
|
: QGraphicsItem(parent), image(_image), id(_id), hotSpot(_hotSpot), startZone(_startZone)
|
||||||
|
{
|
||||||
|
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
|
||||||
|
qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1());
|
||||||
|
hotSpot = QPointF();
|
||||||
|
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
|
||||||
|
qDebug(QString("CardDragItem: coordinate overflow: x = %1, y = %2").arg(hotSpot.x()).arg(hotSpot.y()).toLatin1());
|
||||||
|
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
setZValue(2000000000);
|
||||||
|
setCacheMode(DeviceCoordinateCache);
|
||||||
|
|
||||||
|
scene->addItem(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardDragItem::~CardDragItem()
|
||||||
|
{
|
||||||
|
qDebug("CardDragItem destructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF CardDragItem::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
// Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
|
||||||
|
QRectF foo = option->matrix.mapRect(boundingRect());
|
||||||
|
QPixmap bar = image->scaled(foo.width(), foo.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
painter->drawPixmap(boundingRect(), bar, bar.rect());
|
||||||
|
|
||||||
|
// painter->drawPixmap(boundingRect(), *image, QRectF(0, 0, image->width(), image->height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
QPointF sp = event->scenePos();
|
||||||
|
QList<QGraphicsItem *> colliding = scene()->items(sp);
|
||||||
|
|
||||||
|
PlayerZone *cursorZone = 0;
|
||||||
|
for (int i = colliding.size() - 1; i >= 0; i--) {
|
||||||
|
if ((cursorZone = qgraphicsitem_cast<PlayerZone *>(colliding.at(i)))) {
|
||||||
|
if (cursorZone->getName() == "table") {
|
||||||
|
QPointF cp = cursorZone->scenePos();
|
||||||
|
QPointF localpos = sp - hotSpot - cp;
|
||||||
|
setPos(QPointF(round(localpos.x() / RASTER_WIDTH) * RASTER_WIDTH, round(localpos.y() / RASTER_HEIGHT) * RASTER_HEIGHT) + cp);
|
||||||
|
} else
|
||||||
|
setPos(sp - hotSpot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
QGraphicsScene *sc = scene();
|
||||||
|
QPointF sp = scenePos();
|
||||||
|
sc->removeItem(this);
|
||||||
|
QList<QGraphicsItem *> colliding = sc->items(event->scenePos());
|
||||||
|
|
||||||
|
qDebug(QString("drop: %1 collisions").arg(colliding.size()).toLatin1());
|
||||||
|
PlayerZone *dropZone = 0;
|
||||||
|
for (int i = colliding.size() - 1; i >= 0; i--) {
|
||||||
|
QRectF bbox = colliding.at(i)->boundingRect();
|
||||||
|
qDebug(QString("bbox x %1 y %2 w %3 h %4").arg(bbox.x()).arg(bbox.y()).arg(bbox.width()).arg(bbox.height()).toLatin1());
|
||||||
|
|
||||||
|
if ((dropZone = qgraphicsitem_cast<PlayerZone *>(colliding.at(i)))) {
|
||||||
|
qDebug("zone found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropZone) {
|
||||||
|
dropZone->handleDropEvent(id, startZone, (sp - dropZone->pos()).toPoint());
|
||||||
|
QList<QGraphicsItem *> childList = childItems();
|
||||||
|
for (int i = 0; i < childList.size(); i++) {
|
||||||
|
CardDragItem *c = qgraphicsitem_cast<CardDragItem *>(childList.at(i));
|
||||||
|
if (!c)
|
||||||
|
QMessageBox::critical(0, "fehler", "null");
|
||||||
|
dropZone->handleDropEvent(c->id, startZone, (sp - dropZone->pos() + c->pos()).toPoint());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
QMessageBox::critical(0, "fehler", "fehler");
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
}
|
28
cockatrice/src/carddragitem.h
Normal file
28
cockatrice/src/carddragitem.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef CARDDRAGITEM_H
|
||||||
|
#define CARDDRAGITEM_H
|
||||||
|
|
||||||
|
#include "carditem.h"
|
||||||
|
|
||||||
|
class QGraphicsScene;
|
||||||
|
class PlayerZone;
|
||||||
|
|
||||||
|
class CardDragItem : public QGraphicsItem {
|
||||||
|
private:
|
||||||
|
QPixmap *image;
|
||||||
|
int id;
|
||||||
|
QPointF hotSpot;
|
||||||
|
PlayerZone *startZone;
|
||||||
|
public:
|
||||||
|
enum { Type = typeCardDrag };
|
||||||
|
int type() const { return Type; }
|
||||||
|
CardDragItem(QGraphicsScene *scene, PlayerZone *_startZone, QPixmap *_image, int _id, const QPointF &_hotSpot, QGraphicsItem *parent = 0);
|
||||||
|
~CardDragItem();
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
QPointF getHotSpot() const { return hotSpot; }
|
||||||
|
protected:
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
61
cockatrice/src/cardinfowidget.cpp
Normal file
61
cockatrice/src/cardinfowidget.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#include "cardinfowidget.h"
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
CardInfoWidget::CardInfoWidget(CardDatabase *_db, QWidget *parent)
|
||||||
|
: QFrame(parent), db(_db), aspectratio(0)
|
||||||
|
{
|
||||||
|
cardPicture = new QLabel();
|
||||||
|
cardPicture->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
nameLabel1 = new QLabel(tr("Name:"));
|
||||||
|
nameLabel2 = new QLabel();
|
||||||
|
manacostLabel1 = new QLabel(tr("Mana cost:"));
|
||||||
|
manacostLabel2 = new QLabel();
|
||||||
|
cardtypeLabel1 = new QLabel(tr("Card type:"));
|
||||||
|
cardtypeLabel2 = new QLabel();
|
||||||
|
powtoughLabel1 = new QLabel(tr("P / T:"));
|
||||||
|
powtoughLabel2 = new QLabel();
|
||||||
|
|
||||||
|
textLabel = new QTextEdit();
|
||||||
|
textLabel->setReadOnly(true);
|
||||||
|
|
||||||
|
QGridLayout *grid = new QGridLayout(this);
|
||||||
|
grid->addWidget(cardPicture, 0, 0, 1, 2);
|
||||||
|
grid->addWidget(nameLabel1, 1, 0);
|
||||||
|
grid->addWidget(nameLabel2, 1, 1);
|
||||||
|
grid->addWidget(manacostLabel1, 2, 0);
|
||||||
|
grid->addWidget(manacostLabel2, 2, 1);
|
||||||
|
grid->addWidget(cardtypeLabel1, 3, 0);
|
||||||
|
grid->addWidget(cardtypeLabel2, 3, 1);
|
||||||
|
grid->addWidget(powtoughLabel1, 4, 0);
|
||||||
|
grid->addWidget(powtoughLabel2, 4, 1);
|
||||||
|
grid->addWidget(textLabel, 5, 0, -1, 2);
|
||||||
|
grid->setRowStretch(5, 1);
|
||||||
|
|
||||||
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoWidget::setCard(CardInfo *card)
|
||||||
|
{
|
||||||
|
if (!card)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPixmap *pixmap = card->getPixmap();
|
||||||
|
if (aspectratio == 0)
|
||||||
|
aspectratio = (double) pixmap->height() / pixmap->width();
|
||||||
|
double w = width() * 2.0 / 3.0;
|
||||||
|
cardPicture->setPixmap(pixmap->scaled((int) w, (int) (w * aspectratio), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
|
|
||||||
|
nameLabel2->setText(card->getName());
|
||||||
|
manacostLabel2->setText(card->getManacost());
|
||||||
|
cardtypeLabel2->setText(card->getCardType());
|
||||||
|
powtoughLabel2->setText(card->getPowTough());
|
||||||
|
textLabel->setText(card->getText().join("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardInfoWidget::setCard(const QString &cardName)
|
||||||
|
{
|
||||||
|
setCard(db->getCard(cardName));
|
||||||
|
}
|
29
cockatrice/src/cardinfowidget.h
Normal file
29
cockatrice/src/cardinfowidget.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef CARDINFOWIDGET_H
|
||||||
|
#define CARDINFOWIDGET_H
|
||||||
|
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QTextEdit;
|
||||||
|
|
||||||
|
class CardInfoWidget : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
CardDatabase *db;
|
||||||
|
double aspectratio;
|
||||||
|
|
||||||
|
QLabel *cardPicture;
|
||||||
|
QLabel *nameLabel1, *nameLabel2;
|
||||||
|
QLabel *manacostLabel1, *manacostLabel2;
|
||||||
|
QLabel *cardtypeLabel1, *cardtypeLabel2;
|
||||||
|
QLabel *powtoughLabel1, *powtoughLabel2;
|
||||||
|
QTextEdit *textLabel;
|
||||||
|
public:
|
||||||
|
CardInfoWidget(CardDatabase *_db, QWidget *parent = 0);
|
||||||
|
public slots:
|
||||||
|
void setCard(CardInfo *card);
|
||||||
|
void setCard(const QString &cardName);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
202
cockatrice/src/carditem.cpp
Normal file
202
cockatrice/src/carditem.cpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtGui>
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "carddragitem.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include "tablezone.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
CardItem::CardItem(CardDatabase *_db, const QString &_name, int _cardid, QGraphicsItem *parent)
|
||||||
|
: QGraphicsItem(parent), db(_db), name(_name), id(_cardid), tapped(false), attacking(false), facedown(false), counters(0), dragItem(NULL)
|
||||||
|
{
|
||||||
|
width = CARD_WIDTH;
|
||||||
|
height = CARD_HEIGHT;
|
||||||
|
image = db->getCard(name)->getPixmap();
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
setFlag(ItemIsSelectable);
|
||||||
|
setAcceptsHoverEvents(true);
|
||||||
|
setCacheMode(DeviceCoordinateCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardItem::~CardItem()
|
||||||
|
{
|
||||||
|
qDebug(QString("CardItem destructor: %1").arg(name).toLatin1());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF CardItem::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
QRectF foo = option->matrix.mapRect(boundingRect());
|
||||||
|
qDebug(QString("%1: w=%2,h=%3").arg(name).arg(foo.width()).arg(foo.height()).toLatin1());
|
||||||
|
QPixmap bar = image->scaled((int) foo.width(), (int) foo.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
// painter->drawPixmap(boundingRect(), *image, QRectF(0, 0, image->width(), image->height()));
|
||||||
|
painter->drawPixmap(boundingRect(), bar, bar.rect());
|
||||||
|
if (isSelected()) {
|
||||||
|
painter->setPen(QPen(QColor("red")));
|
||||||
|
painter->drawRect(QRectF(1, 1, width - 2, height - 2));
|
||||||
|
}
|
||||||
|
if (counters) {
|
||||||
|
painter->setFont(QFont("Times", 32, QFont::Bold));
|
||||||
|
painter->setPen(QPen(QColor("black")));
|
||||||
|
painter->setBackground(QBrush(QColor(255, 255, 255, 100)));
|
||||||
|
painter->setBackgroundMode(Qt::OpaqueMode);
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString::number(counters));
|
||||||
|
}
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setName(const QString &_name)
|
||||||
|
{
|
||||||
|
name = _name;
|
||||||
|
image = db->getCard(name)->getPixmap();
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setTapped(bool _tapped)
|
||||||
|
{
|
||||||
|
tapped = _tapped;
|
||||||
|
if (tapped)
|
||||||
|
setTransform(QTransform().translate((float) width / 2, (float) height / 2).rotate(90).translate((float) -width / 2, (float) -height / 2));
|
||||||
|
else
|
||||||
|
setTransform(QTransform());
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setAttacking(bool _attacking)
|
||||||
|
{
|
||||||
|
attacking = _attacking;
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setFacedown(bool _facedown)
|
||||||
|
{
|
||||||
|
facedown = _facedown;
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setCounters(int _counters)
|
||||||
|
{
|
||||||
|
counters = _counters;
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::setAnnotation(const QString &_annotation)
|
||||||
|
{
|
||||||
|
annotation = _annotation;
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::resetState()
|
||||||
|
{
|
||||||
|
attacking = false;
|
||||||
|
facedown = false;
|
||||||
|
counters = 0;
|
||||||
|
annotation = QString();
|
||||||
|
setTapped(false);
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
CardDragItem *CardItem::createDragItem(PlayerZone *startZone, int _id, const QPointF &_pos, const QPointF &_scenePos)
|
||||||
|
{
|
||||||
|
dragItem = new CardDragItem(scene(), startZone, image, _id, _pos);
|
||||||
|
dragItem->setPos(_scenePos - dragItem->getHotSpot());
|
||||||
|
|
||||||
|
return dragItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::deleteDragItem()
|
||||||
|
{
|
||||||
|
delete dragItem;
|
||||||
|
dragItem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (!isSelected()) {
|
||||||
|
scene()->clearSelection();
|
||||||
|
setSelected(true);
|
||||||
|
}
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
setCursor(Qt::ClosedHandCursor);
|
||||||
|
} else if (event->button() == Qt::RightButton) {
|
||||||
|
qgraphicsitem_cast<PlayerZone *>(parentItem())->getPlayer()->showCardMenu(event->screenPos());
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance())
|
||||||
|
return;
|
||||||
|
|
||||||
|
createDragItem((PlayerZone *) parentItem(), id, event->pos(), event->scenePos());
|
||||||
|
dragItem->grabMouse();
|
||||||
|
|
||||||
|
QList<QGraphicsItem *> sel = scene()->selectedItems();
|
||||||
|
for (int i = 0; i < sel.size(); i++) {
|
||||||
|
CardItem *c = (CardItem *) sel.at(i);
|
||||||
|
if (c == this)
|
||||||
|
continue;
|
||||||
|
CardDragItem *drag = new CardDragItem(scene(), (PlayerZone *) parentItem(), c->getImage(), c->getId(), QPointF(), dragItem);
|
||||||
|
drag->setPos(c->pos() - pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
if (!isSelected()) {
|
||||||
|
// Unselect all items, then select this one
|
||||||
|
scene()->setSelectionArea(QPainterPath());
|
||||||
|
setSelected(true);
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
PlayerZone *zone = (PlayerZone *) parentItem();
|
||||||
|
// Do nothing if the card belongs to another player
|
||||||
|
if (!zone->getPlayer()->getLocal())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (zone->getHasCardAttr())
|
||||||
|
((TableZone *) zone)->toggleTapped();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||||
|
{
|
||||||
|
((PlayerZone *) parentItem())->hoverCardEvent(this);
|
||||||
|
QGraphicsItem::hoverEnterEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||||
|
{
|
||||||
|
QGraphicsItem::hoverLeaveEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CardItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
|
||||||
|
{
|
||||||
|
if (change == ItemSelectedChange) {
|
||||||
|
// XXX
|
||||||
|
return value;
|
||||||
|
} else if (change == ItemSelectedHasChanged) {
|
||||||
|
update();
|
||||||
|
return value;
|
||||||
|
} else
|
||||||
|
return QGraphicsItem::itemChange(change, value);
|
||||||
|
}
|
81
cockatrice/src/carditem.h
Normal file
81
cockatrice/src/carditem.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef CARDITEM_H
|
||||||
|
#define CARDITEM_H
|
||||||
|
|
||||||
|
#include <QGraphicsItem>
|
||||||
|
|
||||||
|
class CardDatabase;
|
||||||
|
class CardDragItem;
|
||||||
|
class PlayerZone;
|
||||||
|
|
||||||
|
|
||||||
|
const int CARD_WIDTH = 72;
|
||||||
|
const int CARD_HEIGHT = 102;
|
||||||
|
const int RASTER_WIDTH = 36;
|
||||||
|
const int RASTER_HEIGHT = 34;
|
||||||
|
|
||||||
|
/*
|
||||||
|
const int CARD_WIDTH = 72;
|
||||||
|
const int CARD_HEIGHT = 108;
|
||||||
|
const int RASTER_WIDTH = 36;
|
||||||
|
const int RASTER_HEIGHT = 36;
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int MAX_COUNTERS_ON_CARD = 999;
|
||||||
|
|
||||||
|
enum CardItemType {
|
||||||
|
typeCard = QGraphicsItem::UserType + 1,
|
||||||
|
typeCardDrag = QGraphicsItem::UserType + 2,
|
||||||
|
typeZone = QGraphicsItem::UserType + 3,
|
||||||
|
typeOther = QGraphicsItem::UserType + 4
|
||||||
|
};
|
||||||
|
|
||||||
|
class CardItem : public QGraphicsItem {
|
||||||
|
private:
|
||||||
|
CardDatabase *db;
|
||||||
|
QString name;
|
||||||
|
int id;
|
||||||
|
int width, height;
|
||||||
|
QPixmap *image;
|
||||||
|
bool tapped;
|
||||||
|
bool attacking;
|
||||||
|
bool facedown;
|
||||||
|
int counters;
|
||||||
|
QString annotation;
|
||||||
|
CardDragItem *dragItem;
|
||||||
|
public:
|
||||||
|
enum { Type = typeCard };
|
||||||
|
int type() const { return Type; }
|
||||||
|
CardItem(CardDatabase *_db, const QString &_name, int _cardid, QGraphicsItem *parent = 0);
|
||||||
|
~CardItem();
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
int getId() const { return id; }
|
||||||
|
void setId(int _id) { id = _id; }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
void setName(const QString &_name = QString());
|
||||||
|
QPixmap *getImage() const { return image; }
|
||||||
|
bool getTapped() const { return tapped; }
|
||||||
|
void setTapped(bool _tapped);
|
||||||
|
bool getAttacking() const { return attacking; }
|
||||||
|
void setAttacking(bool _attacking);
|
||||||
|
bool getFacedown() const { return facedown; }
|
||||||
|
void setFacedown(bool _facedown);
|
||||||
|
int getCounters() const { return counters; }
|
||||||
|
void setCounters(int _counters);
|
||||||
|
QString getAnnotation() const { return annotation; }
|
||||||
|
void setAnnotation(const QString &_annotation);
|
||||||
|
void resetState();
|
||||||
|
|
||||||
|
CardDragItem *createDragItem(PlayerZone *startZone, int _id, const QPointF &_pos, const QPointF &_scenePos);
|
||||||
|
void deleteDragItem();
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
31
cockatrice/src/cardlist.cpp
Normal file
31
cockatrice/src/cardlist.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "cardlist.h"
|
||||||
|
|
||||||
|
CardList::CardList(bool _contentsKnown)
|
||||||
|
: QList<CardItem *>(), contentsKnown(_contentsKnown)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CardItem *CardList::findCard(const int id, const bool remove, int *position)
|
||||||
|
{
|
||||||
|
if (!contentsKnown) {
|
||||||
|
if (empty())
|
||||||
|
return 0;
|
||||||
|
CardItem *temp = at(0);
|
||||||
|
if (remove)
|
||||||
|
removeAt(0);
|
||||||
|
if (position)
|
||||||
|
*position = id;
|
||||||
|
return temp;
|
||||||
|
} else
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
CardItem *temp = at(i);
|
||||||
|
if (temp->getId() == id) {
|
||||||
|
if (remove)
|
||||||
|
removeAt(i);
|
||||||
|
if (position)
|
||||||
|
*position = i;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
16
cockatrice/src/cardlist.h
Normal file
16
cockatrice/src/cardlist.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef CARDLIST_H
|
||||||
|
#define CARDLIST_H
|
||||||
|
|
||||||
|
#include "carditem.h"
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class CardList : public QList<CardItem *> {
|
||||||
|
protected:
|
||||||
|
bool contentsKnown;
|
||||||
|
public:
|
||||||
|
CardList(bool _contentsKnown);
|
||||||
|
CardItem *findCard(const int id, const bool remove, int *position = NULL);
|
||||||
|
bool getContentsKnown() const { return contentsKnown; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
322
cockatrice/src/client.cpp
Normal file
322
cockatrice/src/client.cpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
#include <QTimer>
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
Client::Client(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
timer = new QTimer(this);
|
||||||
|
timer->setInterval(1000);
|
||||||
|
connect(timer, SIGNAL(timeout()), this, SLOT(checkTimeout()));
|
||||||
|
|
||||||
|
MsgId = 0;
|
||||||
|
status = StatusDisconnected;
|
||||||
|
socket = new QTcpSocket(this);
|
||||||
|
socket->setTextModeEnabled(true);
|
||||||
|
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
||||||
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readLine()));
|
||||||
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Client::~Client()
|
||||||
|
{
|
||||||
|
delete socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::checkTimeout()
|
||||||
|
{
|
||||||
|
QListIterator<PendingCommand *> i(PendingCommands);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
PendingCommand *c = i.next();
|
||||||
|
c->incTime();
|
||||||
|
if (c->timeout()) {
|
||||||
|
disconnectFromServer();
|
||||||
|
emit serverTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::slotSocketError(QAbstractSocket::SocketError error)
|
||||||
|
{
|
||||||
|
emit logSocketError(socket->errorString());
|
||||||
|
disconnectFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::slotConnected()
|
||||||
|
{
|
||||||
|
timer->start();
|
||||||
|
setStatus(StatusAwaitingWelcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::readLine()
|
||||||
|
{
|
||||||
|
QString line;
|
||||||
|
for (;;) {
|
||||||
|
if (!socket->canReadLine())
|
||||||
|
break;
|
||||||
|
line = QString(socket->readLine()).trimmed();
|
||||||
|
|
||||||
|
if (line.isNull())
|
||||||
|
break;
|
||||||
|
qDebug(QString("readLine: %1").arg(line).toLatin1());
|
||||||
|
QStringList values = line.split("|");
|
||||||
|
QString prefix = values.takeFirst();
|
||||||
|
// prefix is one of {welcome, private, public, resp, list_games, list_players, list_counters, list_zones, dump_zone}
|
||||||
|
if (!(prefix.compare("private") && prefix.compare("public"))) {
|
||||||
|
ServerEventData *event = new ServerEventData(line);
|
||||||
|
if (event->getEventType() == eventPlayerId) {
|
||||||
|
QStringList data = event->getEventData();
|
||||||
|
if (data.size() != 2) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
bool ok;
|
||||||
|
int id = data[0].toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
delete event;
|
||||||
|
emit playerIdReceived(id, data[1]);
|
||||||
|
} else
|
||||||
|
emit gameEvent(event);
|
||||||
|
} else if (!prefix.compare("resp")) {
|
||||||
|
bool ok;
|
||||||
|
int msgid = values.takeFirst().toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.empty()) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = !values.takeFirst().compare("ok");
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
ServerErrorMessage message = msgNone;
|
||||||
|
|
||||||
|
// Update list of pending commands
|
||||||
|
QListIterator<PendingCommand *> i(PendingCommands);
|
||||||
|
bool found = false;
|
||||||
|
PendingCommand *c;
|
||||||
|
while (i.hasNext()) {
|
||||||
|
c = i.next();
|
||||||
|
if (c->getMsgId() == msgid) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
QString cmd = c->getCmd();
|
||||||
|
if (cmd.startsWith("submit_deck"))
|
||||||
|
readyStart();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
PendingCommands.removeAt(PendingCommands.indexOf(c));
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit responseReceived(new ServerResponse(msgid, ok, message));
|
||||||
|
} else if (!(prefix.compare("list_games")
|
||||||
|
&& prefix.compare("list_players")
|
||||||
|
&& prefix.compare("list_counters")
|
||||||
|
&& prefix.compare("list_zones")
|
||||||
|
&& prefix.compare("dump_zone")
|
||||||
|
&& prefix.compare("welcome"))) {
|
||||||
|
int cmdid = values.takeFirst().toInt();
|
||||||
|
if (!values[0].compare(".")) {
|
||||||
|
QListIterator<QStringList> i(msgbuf);
|
||||||
|
QList<ServerGame *> gamelist;
|
||||||
|
QList<ServerPlayer *> playerlist;
|
||||||
|
QList<ServerZone *> zonelist;
|
||||||
|
QList<ServerZoneCard *> zonedump;
|
||||||
|
QStringList welcomemsg;
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QStringList val = i.next();
|
||||||
|
|
||||||
|
// XXX Parametergültigkeit überprüfen
|
||||||
|
if (!prefix.compare("list_games"))
|
||||||
|
gamelist << new ServerGame(val[0], val[1], val[2].toInt(), val[3].toInt(), val[4].toInt());
|
||||||
|
else if (!prefix.compare("list_players"))
|
||||||
|
playerlist << new ServerPlayer(val[0].toInt(), val[1]);
|
||||||
|
else if (!prefix.compare("list_counters"))
|
||||||
|
{ }
|
||||||
|
else if (!prefix.compare("list_zones"))
|
||||||
|
zonelist << new ServerZone(val[0], val[1] == "1", val[2] == "1", val[3].toInt());
|
||||||
|
else if (!prefix.compare("dump_zone"))
|
||||||
|
zonedump << new ServerZoneCard(val[0].toInt(), val[1], val[2].toInt(), val[3].toInt(), val[4].toInt(), val[5] == "1", val[6]);
|
||||||
|
else if (!prefix.compare("welcome"))
|
||||||
|
welcomemsg << val[0];
|
||||||
|
}
|
||||||
|
if (!prefix.compare("list_games"))
|
||||||
|
emit gameListReceived(gamelist);
|
||||||
|
else if (!prefix.compare("list_players"))
|
||||||
|
emit playerListReceived(playerlist);
|
||||||
|
else if (!prefix.compare("list_counters"))
|
||||||
|
{ }
|
||||||
|
else if (!prefix.compare("list_zones"))
|
||||||
|
emit zoneListReceived(cmdid, zonelist);
|
||||||
|
else if (!prefix.compare("dump_zone"))
|
||||||
|
emit zoneDumpReceived(cmdid, zonedump);
|
||||||
|
else if (!prefix.compare("welcome")) {
|
||||||
|
emit welcomeMsgReceived(welcomemsg);
|
||||||
|
setStatus(StatusConnected);
|
||||||
|
setName(PlayerName);
|
||||||
|
}
|
||||||
|
msgbuf.clear();
|
||||||
|
} else
|
||||||
|
msgbuf << values;
|
||||||
|
} else {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setStatus(const ProtocolStatus _status)
|
||||||
|
{
|
||||||
|
status = _status;
|
||||||
|
emit statusChanged(_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::msg(const QString &s)
|
||||||
|
{
|
||||||
|
qDebug(QString("msg gibt aus: %1").arg(s).toLatin1());
|
||||||
|
QTextStream stream(socket);
|
||||||
|
stream.setCodec("UTF-8");
|
||||||
|
stream << s << endl;
|
||||||
|
stream.flush();
|
||||||
|
socket->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::cmd(const QString &s)
|
||||||
|
{
|
||||||
|
msg(QString("%1|%2").arg(++MsgId).arg(s));
|
||||||
|
PendingCommands << new PendingCommand(s, MsgId);
|
||||||
|
return MsgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::connectToServer(const QString &hostname, unsigned int port, const QString &playername)
|
||||||
|
{
|
||||||
|
PlayerName = playername;
|
||||||
|
socket->connectToHost(hostname, port);
|
||||||
|
setStatus(StatusConnecting);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::disconnectFromServer()
|
||||||
|
{
|
||||||
|
timer->stop();
|
||||||
|
PendingCommands.clear();
|
||||||
|
setStatus(StatusDisconnected);
|
||||||
|
socket->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::listGames()
|
||||||
|
{
|
||||||
|
return cmd("list_games");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::listPlayers()
|
||||||
|
{
|
||||||
|
return cmd("list_players");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers)
|
||||||
|
{
|
||||||
|
return cmd(QString("create_game|%1|%2|%3|%4").arg(name).arg(description).arg(password).arg(maxPlayers));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::joinGame(const QString &name, const QString &password)
|
||||||
|
{
|
||||||
|
return cmd(QString("join_game|%1|%2").arg(name).arg(password));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::leaveGame()
|
||||||
|
{
|
||||||
|
return cmd("leave_game");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::setName(const QString &name)
|
||||||
|
{
|
||||||
|
return cmd(QString("set_name|%1").arg(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::say(const QString &s)
|
||||||
|
{
|
||||||
|
return cmd(QString("say|%1").arg(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::shuffle()
|
||||||
|
{
|
||||||
|
return cmd("shuffle");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::rollDice(unsigned int sides)
|
||||||
|
{
|
||||||
|
return cmd(QString("roll_dice|%1").arg(sides));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::drawCards(unsigned int number)
|
||||||
|
{
|
||||||
|
return cmd(QString("draw_cards|%1").arg(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::moveCard(int cardid, const QString &startzone, const QString &targetzone, int x, int y)
|
||||||
|
{
|
||||||
|
// if startzone is public: cardid is the card's id
|
||||||
|
// else: cardid is the position of the card in the zone (e.g. deck)
|
||||||
|
return cmd(QString("move_card|%1|%2|%3|%4|%5").arg(cardid).arg(startzone).arg(targetzone).arg(x).arg(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::createToken(const QString &zone, const QString &name, const QString &powtough, int x, int y)
|
||||||
|
{
|
||||||
|
return cmd(QString("create_token|%1|%2|%3|%4|%5").arg(zone).arg(name).arg(powtough).arg(x).arg(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::setCardAttr(const QString &zone, int cardid, const QString &aname, const QString &avalue)
|
||||||
|
{
|
||||||
|
return cmd(QString("set_card_attr|%1|%2|%3|%4").arg(zone).arg(cardid).arg(aname).arg(avalue));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::submitDeck(const QStringList &deck)
|
||||||
|
{
|
||||||
|
int retval = cmd("submit_deck");
|
||||||
|
QStringListIterator i(deck);
|
||||||
|
while (i.hasNext())
|
||||||
|
msg(i.next());
|
||||||
|
msg(".");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::readyStart()
|
||||||
|
{
|
||||||
|
return cmd("ready_start");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::incCounter(const QString &counter, int delta)
|
||||||
|
{
|
||||||
|
return cmd(QString("inc_counter|%1|%2").arg(counter).arg(delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::setCounter(const QString &counter, int value)
|
||||||
|
{
|
||||||
|
return cmd(QString("set_counter|%1|%2").arg(counter).arg(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::delCounter(const QString &counter)
|
||||||
|
{
|
||||||
|
return cmd(QString("del_counter|%1").arg(counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::setActivePlayer(int player)
|
||||||
|
{
|
||||||
|
return cmd(QString("set_active_player|%1").arg(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::setActivePhase(int phase)
|
||||||
|
{
|
||||||
|
return cmd(QString("set_active_phase|%1").arg(phase));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::dumpZone(int player, const QString &zone, int numberCards)
|
||||||
|
{
|
||||||
|
return cmd(QString("dump_zone|%1|%2|%3").arg(player).arg(zone).arg(numberCards));
|
||||||
|
}
|
86
cockatrice/src/client.h
Normal file
86
cockatrice/src/client.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#ifndef CLIENT_H
|
||||||
|
#define CLIENT_H
|
||||||
|
|
||||||
|
#include "servereventdata.h"
|
||||||
|
#include "serverresponse.h"
|
||||||
|
#include "servergame.h"
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "serverzone.h"
|
||||||
|
#include "serverzonecard.h"
|
||||||
|
#include "pendingcommand.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
// Connection state.
|
||||||
|
// The protocol handler itself is stateless once the connection
|
||||||
|
// has been established.
|
||||||
|
enum ProtocolStatus { StatusDisconnected,
|
||||||
|
StatusConnecting,
|
||||||
|
StatusAwaitingWelcome,
|
||||||
|
StatusConnected };
|
||||||
|
|
||||||
|
class Client : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void statusChanged(ProtocolStatus _status);
|
||||||
|
void welcomeMsgReceived(QStringList welcomeMsg);
|
||||||
|
void gameListReceived(QList<ServerGame *> games);
|
||||||
|
void playerListReceived(QList<ServerPlayer *> players);
|
||||||
|
void zoneListReceived(int commandId, QList<ServerZone *> zones);
|
||||||
|
void zoneDumpReceived(int commandId, QList<ServerZoneCard *> cards);
|
||||||
|
void responseReceived(ServerResponse *response);
|
||||||
|
void playerIdReceived(int id, QString name);
|
||||||
|
void gameEvent(ServerEventData *msg);
|
||||||
|
void serverTimeout();
|
||||||
|
void logSocketError(const QString &errorString);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotConnected();
|
||||||
|
void readLine();
|
||||||
|
void checkTimeout();
|
||||||
|
void slotSocketError(QAbstractSocket::SocketError error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer *timer;
|
||||||
|
QList<PendingCommand *> PendingCommands;
|
||||||
|
QTcpSocket *socket;
|
||||||
|
ProtocolStatus status;
|
||||||
|
QList<QStringList> msgbuf;
|
||||||
|
QString PlayerName;
|
||||||
|
unsigned int MsgId;
|
||||||
|
void msg(const QString &s);
|
||||||
|
int cmd(const QString &s);
|
||||||
|
void setStatus(const ProtocolStatus _status);
|
||||||
|
public:
|
||||||
|
Client(QObject *parent = 0);
|
||||||
|
~Client();
|
||||||
|
ProtocolStatus getStatus() { return status; }
|
||||||
|
QString peerName() const { return socket->peerName(); }
|
||||||
|
|
||||||
|
void connectToServer(const QString &hostname, unsigned int port, const QString &playername);
|
||||||
|
void disconnectFromServer();
|
||||||
|
int listGames();
|
||||||
|
int listPlayers();
|
||||||
|
int createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers);
|
||||||
|
int joinGame(const QString &name, const QString &password);
|
||||||
|
int leaveGame();
|
||||||
|
int setName(const QString &name);
|
||||||
|
int say(const QString &s);
|
||||||
|
int shuffle();
|
||||||
|
int rollDice(unsigned int sides);
|
||||||
|
int drawCards(unsigned int number);
|
||||||
|
int moveCard(int cardid, const QString &startzone, const QString &targetzone, int x, int y = 0);
|
||||||
|
int createToken(const QString &zone, const QString &name, const QString &powtough, int x, int y);
|
||||||
|
int setCardAttr(const QString &zone, int cardid, const QString &aname, const QString &avalue);
|
||||||
|
int submitDeck(const QStringList &deck);
|
||||||
|
int readyStart();
|
||||||
|
int incCounter(const QString &counter, int delta);
|
||||||
|
int setCounter(const QString &counter, int value);
|
||||||
|
int delCounter(const QString &counter);
|
||||||
|
int setActivePlayer(int player);
|
||||||
|
int setActivePhase(int phase);
|
||||||
|
int dumpZone(int player, const QString &zone, int numberCards);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
30
cockatrice/src/counter.cpp
Normal file
30
cockatrice/src/counter.cpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "counter.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
Counter::Counter(Player *_player, const QString &_name, QGraphicsItem *parent)
|
||||||
|
: QGraphicsItem(parent), name(_name), value(0), player(_player)
|
||||||
|
{
|
||||||
|
player->addCounter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Counter::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 50, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->save();
|
||||||
|
painter->fillRect(boundingRect(), QBrush(QColor("gray")));
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1").arg(value));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::setValue(int _value)
|
||||||
|
{
|
||||||
|
value = _value;
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
24
cockatrice/src/counter.h
Normal file
24
cockatrice/src/counter.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef COUNTER_H
|
||||||
|
#define COUNTER_H
|
||||||
|
|
||||||
|
#include <QGraphicsItem>
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class Counter : public QGraphicsItem {
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
int value;
|
||||||
|
protected:
|
||||||
|
Player *player;
|
||||||
|
public:
|
||||||
|
Counter(Player *_player, const QString &_name, QGraphicsItem *parent = 0);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
|
||||||
|
QString getName() const { return name; }
|
||||||
|
int getValue() const { return value; }
|
||||||
|
void setValue(int _value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
11
cockatrice/src/counterlist.cpp
Normal file
11
cockatrice/src/counterlist.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "counterlist.h"
|
||||||
|
|
||||||
|
Counter *CounterList::findCounter(const QString &name) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
Counter *temp = at(i);
|
||||||
|
if (!temp->getName().compare(name))
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
12
cockatrice/src/counterlist.h
Normal file
12
cockatrice/src/counterlist.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef COUNTERLIST_H
|
||||||
|
#define COUNTERLIST_H
|
||||||
|
|
||||||
|
#include "counter.h"
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class CounterList : public QList<Counter *> {
|
||||||
|
public:
|
||||||
|
Counter *findCounter(const QString &name) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
92
cockatrice/src/decklistmodel.cpp
Normal file
92
cockatrice/src/decklistmodel.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include "decklistmodel.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
DeckListModel::~DeckListModel()
|
||||||
|
{
|
||||||
|
qDebug("DeckListModel destructor");
|
||||||
|
cleanList();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeckListModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return deckList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeckListModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant DeckListModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
if ((index.row() >= deckList.size()) || (index.column() >= 2))
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
DecklistRow *r = deckList.at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0: return r->getNumber();
|
||||||
|
case 1: return r->getCard();
|
||||||
|
default: return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
if (orientation != Qt::Horizontal)
|
||||||
|
return QVariant();
|
||||||
|
switch (section) {
|
||||||
|
case 0: return QString(tr("Number"));
|
||||||
|
case 1: return QString(tr("Card"));
|
||||||
|
default: return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckListModel::cleanList()
|
||||||
|
{
|
||||||
|
QListIterator<DecklistRow *> i(deckList);
|
||||||
|
while (i.hasNext())
|
||||||
|
delete i.next();
|
||||||
|
deckList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckListModel::loadFromFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
return;
|
||||||
|
QTextStream in(&file);
|
||||||
|
cleanList();
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
QString line = in.readLine().simplified();
|
||||||
|
bool isSideboard = false;
|
||||||
|
if (line.startsWith("SB:")) {
|
||||||
|
line = line.mid(3).trimmed();
|
||||||
|
isSideboard = true;
|
||||||
|
}
|
||||||
|
int i = line.indexOf(' ');
|
||||||
|
bool ok;
|
||||||
|
int number = line.left(i).toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
continue;
|
||||||
|
DecklistRow *row = new DecklistRow(number, line.mid(i + 1), isSideboard);
|
||||||
|
deckList << row;
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
DecklistRow *DeckListModel::getRow(int row) const
|
||||||
|
{
|
||||||
|
if (row >= deckList.size())
|
||||||
|
return 0;
|
||||||
|
return deckList.at(row);
|
||||||
|
}
|
36
cockatrice/src/decklistmodel.h
Normal file
36
cockatrice/src/decklistmodel.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef DECKLISTMODEL_H
|
||||||
|
#define DECKLISTMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class DecklistRow {
|
||||||
|
private:
|
||||||
|
int number;
|
||||||
|
QString card;
|
||||||
|
bool sideboard;
|
||||||
|
public:
|
||||||
|
DecklistRow(int _number, const QString &_card, bool _sideboard) : number(_number), card(_card), sideboard(_sideboard) { }
|
||||||
|
int getNumber() const { return number; }
|
||||||
|
QString getCard() const { return card; }
|
||||||
|
bool isSideboard() const { return sideboard; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeckListModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DeckListModel(QObject *parent = 0)
|
||||||
|
: QAbstractListModel(parent) { }
|
||||||
|
~DeckListModel();
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
void loadFromFile(const QString &fileName);
|
||||||
|
DecklistRow *getRow(int row) const;
|
||||||
|
private:
|
||||||
|
QList<DecklistRow *> deckList;
|
||||||
|
void cleanList();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
61
cockatrice/src/dlg_connect.cpp
Normal file
61
cockatrice/src/dlg_connect.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "dlg_connect.h"
|
||||||
|
|
||||||
|
DlgConnect::DlgConnect(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
{
|
||||||
|
hostLabel = new QLabel(tr("&Host:"));
|
||||||
|
hostEdit = new QLineEdit("localhost");
|
||||||
|
hostLabel->setBuddy(hostEdit);
|
||||||
|
|
||||||
|
portLabel = new QLabel(tr("&Port:"));
|
||||||
|
portEdit = new QLineEdit("4747");
|
||||||
|
portLabel->setBuddy(portEdit);
|
||||||
|
|
||||||
|
playernameLabel = new QLabel(tr("Player &name:"));
|
||||||
|
playernameEdit = new QLineEdit("Player");
|
||||||
|
playernameLabel->setBuddy(playernameEdit);
|
||||||
|
|
||||||
|
okButton = new QPushButton(tr("&OK"));
|
||||||
|
okButton->setDefault(true);
|
||||||
|
cancelButton = new QPushButton(tr("&Cancel"));
|
||||||
|
|
||||||
|
QGridLayout *grid = new QGridLayout;
|
||||||
|
grid->addWidget(hostLabel, 0, 0);
|
||||||
|
grid->addWidget(hostEdit, 0, 1);
|
||||||
|
grid->addWidget(portLabel, 1, 0);
|
||||||
|
grid->addWidget(portEdit, 1, 1);
|
||||||
|
grid->addWidget(playernameLabel, 2, 0);
|
||||||
|
grid->addWidget(playernameEdit, 2, 1);
|
||||||
|
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->addWidget(okButton);
|
||||||
|
buttonLayout->addWidget(cancelButton);
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(grid);
|
||||||
|
mainLayout->addLayout(buttonLayout);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Connect to server"));
|
||||||
|
setFixedHeight(sizeHint().height());
|
||||||
|
|
||||||
|
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||||
|
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DlgConnect::getHost()
|
||||||
|
{
|
||||||
|
return hostEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DlgConnect::getPort()
|
||||||
|
{
|
||||||
|
return portEdit->text().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DlgConnect::getPlayerName()
|
||||||
|
{
|
||||||
|
return playernameEdit->text();
|
||||||
|
}
|
23
cockatrice/src/dlg_connect.h
Normal file
23
cockatrice/src/dlg_connect.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef DLG_CONNECT_H
|
||||||
|
#define DLG_CONNECT_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
|
class DlgConnect : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DlgConnect(QWidget *parent = 0);
|
||||||
|
QString getHost();
|
||||||
|
int getPort();
|
||||||
|
QString getPlayerName();
|
||||||
|
private:
|
||||||
|
QLabel *hostLabel, *portLabel, *playernameLabel;
|
||||||
|
QLineEdit *hostEdit, *portEdit, *playernameEdit;
|
||||||
|
QPushButton *okButton, *cancelButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
85
cockatrice/src/dlg_creategame.cpp
Normal file
85
cockatrice/src/dlg_creategame.cpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "dlg_creategame.h"
|
||||||
|
|
||||||
|
DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent)
|
||||||
|
: QDialog(parent), client(_client)
|
||||||
|
{
|
||||||
|
msgid = 0;
|
||||||
|
|
||||||
|
nameLabel = new QLabel(tr("&Name:"));
|
||||||
|
nameEdit = new QLineEdit;
|
||||||
|
nameLabel->setBuddy(nameEdit);
|
||||||
|
|
||||||
|
descriptionLabel = new QLabel(tr("&Description:"));
|
||||||
|
descriptionEdit = new QLineEdit;
|
||||||
|
descriptionLabel->setBuddy(descriptionEdit);
|
||||||
|
|
||||||
|
passwordLabel = new QLabel(tr("&Password:"));
|
||||||
|
passwordEdit = new QLineEdit;
|
||||||
|
passwordLabel->setBuddy(passwordEdit);
|
||||||
|
|
||||||
|
maxPlayersLabel = new QLabel(tr("&Max Players:"));
|
||||||
|
maxPlayersEdit = new QLineEdit("2");
|
||||||
|
maxPlayersLabel->setBuddy(maxPlayersEdit);
|
||||||
|
|
||||||
|
QGridLayout *grid = new QGridLayout;
|
||||||
|
grid->addWidget(nameLabel, 0, 0);
|
||||||
|
grid->addWidget(nameEdit, 0, 1);
|
||||||
|
grid->addWidget(descriptionLabel, 1, 0);
|
||||||
|
grid->addWidget(descriptionEdit, 1, 1);
|
||||||
|
grid->addWidget(passwordLabel, 2, 0);
|
||||||
|
grid->addWidget(passwordEdit, 2, 1);
|
||||||
|
grid->addWidget(maxPlayersLabel, 3, 0);
|
||||||
|
grid->addWidget(maxPlayersEdit, 3, 1);
|
||||||
|
|
||||||
|
okButton = new QPushButton(tr("&OK"));
|
||||||
|
okButton->setDefault(true);
|
||||||
|
cancelButton = new QPushButton(tr("&Cancel"));
|
||||||
|
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->addWidget(okButton);
|
||||||
|
buttonLayout->addWidget(cancelButton);
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(grid);
|
||||||
|
mainLayout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Create game"));
|
||||||
|
setFixedHeight(sizeHint().height());
|
||||||
|
|
||||||
|
connect(okButton, SIGNAL(clicked()), this, SLOT(actOK()));
|
||||||
|
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
connect(client, SIGNAL(responseReceived(ServerResponse *)), this, SLOT(checkResponse(ServerResponse *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgCreateGame::actOK()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int maxPlayers = maxPlayersEdit->text().toInt(&ok);
|
||||||
|
if (msgid)
|
||||||
|
return;
|
||||||
|
if (!ok) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Invalid number of players."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msgid = client->createGame(nameEdit->text(),
|
||||||
|
descriptionEdit->text(),
|
||||||
|
passwordEdit->text(),
|
||||||
|
maxPlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgCreateGame::checkResponse(ServerResponse *response)
|
||||||
|
{
|
||||||
|
if (response->getMsgId() != msgid)
|
||||||
|
return;
|
||||||
|
if (response->getOk())
|
||||||
|
accept();
|
||||||
|
else {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("XXX"));
|
||||||
|
msgid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
28
cockatrice/src/dlg_creategame.h
Normal file
28
cockatrice/src/dlg_creategame.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef DLG_CREATEGAME_H
|
||||||
|
#define DLG_CREATEGAME_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
|
class DlgCreateGame : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DlgCreateGame(Client *_client, QWidget *parent = 0);
|
||||||
|
private slots:
|
||||||
|
void actOK();
|
||||||
|
void checkResponse(ServerResponse *response);
|
||||||
|
private:
|
||||||
|
Client *client;
|
||||||
|
int msgid;
|
||||||
|
|
||||||
|
QLabel *nameLabel, *descriptionLabel, *passwordLabel, *maxPlayersLabel;
|
||||||
|
QLineEdit *nameEdit, *descriptionEdit, *passwordEdit, *maxPlayersEdit;
|
||||||
|
QPushButton *okButton, *cancelButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
87
cockatrice/src/dlg_games.cpp
Normal file
87
cockatrice/src/dlg_games.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "dlg_games.h"
|
||||||
|
#include "dlg_creategame.h"
|
||||||
|
|
||||||
|
DlgGames::DlgGames(Client *_client, QWidget *parent)
|
||||||
|
: QDialog(parent), client(_client)
|
||||||
|
{
|
||||||
|
msgid = 0;
|
||||||
|
|
||||||
|
tableView = new QTreeView;
|
||||||
|
tableModel = new GamesModel(this);
|
||||||
|
tableView->setModel(tableModel);
|
||||||
|
|
||||||
|
createButton = new QPushButton(tr("&Create"));
|
||||||
|
refreshButton = new QPushButton(tr("&Refresh"));
|
||||||
|
joinButton = new QPushButton(tr("&Join"));
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
|
buttonLayout->addWidget(createButton);
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->addWidget(refreshButton);
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->addWidget(joinButton);
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addWidget(tableView);
|
||||||
|
mainLayout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Games"));
|
||||||
|
setMinimumWidth(sizeHint().width());
|
||||||
|
|
||||||
|
connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate()));
|
||||||
|
connect(refreshButton, SIGNAL(clicked()), this, SLOT(actRefresh()));
|
||||||
|
connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin()));
|
||||||
|
|
||||||
|
connect(client, SIGNAL(gameListReceived(QList<ServerGame *>)), this, SLOT(gameListReceived(QList<ServerGame *>)));
|
||||||
|
client->listGames();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgGames::actCreate()
|
||||||
|
{
|
||||||
|
DlgCreateGame dlg(client, this);
|
||||||
|
if (dlg.exec())
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgGames::actRefresh()
|
||||||
|
{
|
||||||
|
client->listGames();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgGames::checkResponse(ServerResponse *response)
|
||||||
|
{
|
||||||
|
if (response->getMsgId() != msgid)
|
||||||
|
return;
|
||||||
|
if (response->getOk())
|
||||||
|
accept();
|
||||||
|
else {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("XXX"));
|
||||||
|
msgid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgGames::actJoin()
|
||||||
|
{
|
||||||
|
if (msgid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ServerGame *game = tableModel->getGame(tableView->currentIndex().row());
|
||||||
|
QString password;
|
||||||
|
if (game->getHasPassword()) {
|
||||||
|
bool ok;
|
||||||
|
password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(client, SIGNAL(responseReceived(ServerResponse *)), this, SLOT(checkResponse(ServerResponse *)));
|
||||||
|
msgid = client->joinGame(game->getName(), password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgGames::gameListReceived(QList<ServerGame *> _gameList)
|
||||||
|
{
|
||||||
|
tableModel->setGameList(_gameList);
|
||||||
|
}
|
32
cockatrice/src/dlg_games.h
Normal file
32
cockatrice/src/dlg_games.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef DLG_GAMES_H
|
||||||
|
#define DLG_GAMES_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "gamesmodel.h"
|
||||||
|
#include "servergame.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
class QTreeView;
|
||||||
|
|
||||||
|
class DlgGames : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DlgGames(Client *_client, QWidget *parent = 0);
|
||||||
|
private slots:
|
||||||
|
void actCreate();
|
||||||
|
void actRefresh();
|
||||||
|
void actJoin();
|
||||||
|
void gameListReceived(QList<ServerGame *> _gameList);
|
||||||
|
void checkResponse(ServerResponse *response);
|
||||||
|
private:
|
||||||
|
Client *client;
|
||||||
|
int msgid;
|
||||||
|
|
||||||
|
QTreeView *tableView;
|
||||||
|
GamesModel *tableModel;
|
||||||
|
QPushButton *refreshButton, *createButton, *joinButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
63
cockatrice/src/dlg_startgame.cpp
Normal file
63
cockatrice/src/dlg_startgame.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include "dlg_startgame.h"
|
||||||
|
#include "decklistmodel.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
DlgStartGame::DlgStartGame(CardDatabase *_db, QWidget *parent)
|
||||||
|
: QDialog(parent), db(_db)
|
||||||
|
{
|
||||||
|
tableView = new QTreeView;
|
||||||
|
tableModel = new DeckListModel(this);
|
||||||
|
tableView->setModel(tableModel);
|
||||||
|
|
||||||
|
loadButton = new QPushButton(tr("&Load..."));
|
||||||
|
okButton = new QPushButton(tr("&OK"));
|
||||||
|
okButton->setDefault(true);
|
||||||
|
|
||||||
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
|
buttonLayout->addWidget(loadButton);
|
||||||
|
buttonLayout->addStretch();
|
||||||
|
buttonLayout->addWidget(okButton);
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addWidget(tableView);
|
||||||
|
mainLayout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Start game"));
|
||||||
|
setMinimumWidth(sizeHint().width());
|
||||||
|
|
||||||
|
connect(loadButton, SIGNAL(clicked()), this, SLOT(actLoad()));
|
||||||
|
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DlgStartGame::actLoad()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getOpenFileName(this, tr("Load deck"), QString(), tr("Deck files (*.dec)"));
|
||||||
|
if (!fileName.isEmpty())
|
||||||
|
tableModel->loadFromFile(fileName);
|
||||||
|
|
||||||
|
// Precache card pictures
|
||||||
|
for (int i = 0; i < tableModel->rowCount(); i++) {
|
||||||
|
QString cardName = tableModel->getRow(i)->getCard();
|
||||||
|
CardInfo *card = db->getCard(cardName);
|
||||||
|
if (!card) {
|
||||||
|
qDebug(QString("Invalid card: %1").arg(cardName).toLatin1());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
card->getPixmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList DlgStartGame::getDeckList() const
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
for (int i = 0; i < tableModel->rowCount(); i++) {
|
||||||
|
DecklistRow *temp = tableModel->getRow(i);
|
||||||
|
for (int j = 0; j < temp->getNumber(); j++)
|
||||||
|
result << QString("%1%2").arg(temp->isSideboard() ? "SB:" : "").arg(temp->getCard());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
26
cockatrice/src/dlg_startgame.h
Normal file
26
cockatrice/src/dlg_startgame.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef DLG_STARTGAME_H
|
||||||
|
#define DLG_STARTGAME_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "decklistmodel.h"
|
||||||
|
|
||||||
|
class QTreeView;
|
||||||
|
class QPushButton;
|
||||||
|
class CardDatabase;
|
||||||
|
|
||||||
|
class DlgStartGame: public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DlgStartGame(CardDatabase *_db, QWidget *parent = 0);
|
||||||
|
QStringList getDeckList() const;
|
||||||
|
private slots:
|
||||||
|
void actLoad();
|
||||||
|
private:
|
||||||
|
CardDatabase *db;
|
||||||
|
QTreeView *tableView;
|
||||||
|
DeckListModel *tableModel;
|
||||||
|
|
||||||
|
QPushButton *loadButton, *okButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
371
cockatrice/src/game.cpp
Normal file
371
cockatrice/src/game.cpp
Normal file
|
@ -0,0 +1,371 @@
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "servereventdata.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "tablezone.h"
|
||||||
|
#include "handzone.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "dlg_startgame.h"
|
||||||
|
|
||||||
|
Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName)
|
||||||
|
: QObject(), actionsMenu(_actionsMenu), cardMenu(_cardMenu), db(_db), client(_client), scene(_scene), started(false)
|
||||||
|
{
|
||||||
|
QRectF sr = scene->sceneRect();
|
||||||
|
localPlayer = addPlayer(playerId, playerName, QPointF(0, sr.y() + sr.height() / 2), true);
|
||||||
|
|
||||||
|
connect(client, SIGNAL(gameEvent(ServerEventData *)), this, SLOT(gameEvent(ServerEventData *)));
|
||||||
|
connect(client, SIGNAL(playerListReceived(QList<ServerPlayer *>)), this, SLOT(playerListReceived(QList<ServerPlayer *>)));
|
||||||
|
|
||||||
|
aUntapAll = new QAction(tr("&Untap all permanents"), this);
|
||||||
|
aUntapAll->setShortcut(tr("Ctrl+U"));
|
||||||
|
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll()));
|
||||||
|
|
||||||
|
aDecLife = new QAction(tr("&Decrement life"), this);
|
||||||
|
aDecLife->setShortcut(tr("F11"));
|
||||||
|
connect(aDecLife, SIGNAL(triggered()), this, SLOT(actDecLife()));
|
||||||
|
aIncLife = new QAction(tr("&Increment life"), this);
|
||||||
|
aIncLife->setShortcut(tr("F12"));
|
||||||
|
connect(aIncLife, SIGNAL(triggered()), this, SLOT(actIncLife()));
|
||||||
|
aSetLife = new QAction(tr("&Set life"), this);
|
||||||
|
aSetLife->setShortcut(tr("Ctrl+L"));
|
||||||
|
connect(aSetLife, SIGNAL(triggered()), this, SLOT(actSetLife()));
|
||||||
|
|
||||||
|
aShuffle = new QAction(tr("&Shuffle"), this);
|
||||||
|
aShuffle->setShortcut(tr("Ctrl+S"));
|
||||||
|
connect(aShuffle, SIGNAL(triggered()), this, SLOT(actShuffle()));
|
||||||
|
aDraw = new QAction(tr("&Draw a card"), this);
|
||||||
|
aDraw->setShortcut(tr("Ctrl+D"));
|
||||||
|
connect(aDraw, SIGNAL(triggered()), this, SLOT(actDrawCard()));
|
||||||
|
aDrawCards = new QAction(tr("D&raw cards..."), this);
|
||||||
|
connect(aDrawCards, SIGNAL(triggered()), this, SLOT(actDrawCards()));
|
||||||
|
aRollDice = new QAction(tr("R&oll dice..."), this);
|
||||||
|
aRollDice->setShortcut(tr("Ctrl+I"));
|
||||||
|
connect(aRollDice, SIGNAL(triggered()), this, SLOT(actRollDice()));
|
||||||
|
|
||||||
|
aCreateToken = new QAction(tr("&Create token..."), this);
|
||||||
|
aCreateToken->setShortcut(tr("Ctrl+T"));
|
||||||
|
connect(aCreateToken, SIGNAL(triggered()), this, SLOT(actCreateToken()));
|
||||||
|
|
||||||
|
actionsMenu->addAction(aUntapAll);
|
||||||
|
actionsMenu->addSeparator();
|
||||||
|
actionsMenu->addAction(aDecLife);
|
||||||
|
actionsMenu->addAction(aIncLife);
|
||||||
|
actionsMenu->addAction(aSetLife);
|
||||||
|
actionsMenu->addSeparator();
|
||||||
|
actionsMenu->addAction(aShuffle);
|
||||||
|
actionsMenu->addAction(aDraw);
|
||||||
|
actionsMenu->addAction(aDrawCards);
|
||||||
|
actionsMenu->addAction(aRollDice);
|
||||||
|
actionsMenu->addSeparator();
|
||||||
|
actionsMenu->addAction(aCreateToken);
|
||||||
|
|
||||||
|
aTap = new QAction(tr("&Tap"), this);
|
||||||
|
connect(aTap, SIGNAL(triggered()), this, SLOT(actTap()));
|
||||||
|
aUntap = new QAction(tr("&Untap"), this);
|
||||||
|
connect(aUntap, SIGNAL(triggered()), this, SLOT(actUntap()));
|
||||||
|
aAddCounter = new QAction(tr("&Add counter"), this);
|
||||||
|
connect(aAddCounter, SIGNAL(triggered()), this, SLOT(actAddCounter()));
|
||||||
|
aRemoveCounter = new QAction(tr("&Remove counter"), this);
|
||||||
|
connect(aRemoveCounter, SIGNAL(triggered()), this, SLOT(actRemoveCounter()));
|
||||||
|
aSetCounters = new QAction(tr("&Set counters..."), this);
|
||||||
|
connect(aSetCounters, SIGNAL(triggered()), this, SLOT(actSetCounters()));
|
||||||
|
aRearrange = new QAction(tr("&Rearrange"), this);
|
||||||
|
connect(aRearrange, SIGNAL(triggered()), this, SLOT(actRearrange()));
|
||||||
|
|
||||||
|
cardMenu->addAction(aTap);
|
||||||
|
cardMenu->addAction(aUntap);
|
||||||
|
cardMenu->addAction(aAddCounter);
|
||||||
|
cardMenu->addAction(aRemoveCounter);
|
||||||
|
cardMenu->addAction(aSetCounters);
|
||||||
|
cardMenu->addSeparator();
|
||||||
|
cardMenu->addAction(aRearrange);
|
||||||
|
|
||||||
|
dlgStartGame = new DlgStartGame(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game()
|
||||||
|
{
|
||||||
|
qDebug("Game destructor");
|
||||||
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
emit playerRemoved(players.at(i));
|
||||||
|
delete players.at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player *Game::addPlayer(int playerId, const QString &playerName, QPointF base, bool local)
|
||||||
|
{
|
||||||
|
Player *newPlayer = new Player(playerName, playerId, base, local, db, client);
|
||||||
|
|
||||||
|
const ZoneList *const z = newPlayer->getZones();
|
||||||
|
for (int i = 0; i < z->size(); i++)
|
||||||
|
scene->addItem(z->at(i));
|
||||||
|
|
||||||
|
const CounterList *const c = newPlayer->getCounters();
|
||||||
|
for (int i = 0; i < c->size(); i++)
|
||||||
|
scene->addItem(c->at(i));
|
||||||
|
|
||||||
|
connect(newPlayer, SIGNAL(hoverCard(QString)), this, SIGNAL(hoverCard(QString)));
|
||||||
|
connect(newPlayer, SIGNAL(sigShowCardMenu(QPoint)), this, SLOT(showCardMenu(QPoint)));
|
||||||
|
connect(newPlayer, SIGNAL(logMoveCard(QString, QString, QString, QString)), this, SIGNAL(logMoveCard(QString, QString, QString, QString)));
|
||||||
|
connect(newPlayer, SIGNAL(logCreateToken(QString, QString)), this, SIGNAL(logCreateToken(QString, QString)));
|
||||||
|
connect(newPlayer, SIGNAL(logSetCardCounters(QString, QString, int, int)), this, SIGNAL(logSetCardCounters(QString, QString, int, int)));
|
||||||
|
connect(newPlayer, SIGNAL(logSetTapped(QString, QString, bool)), this, SIGNAL(logSetTapped(QString, QString, bool)));
|
||||||
|
connect(newPlayer, SIGNAL(logSetCounter(QString, QString, int, int)), this, SIGNAL(logSetCounter(QString, QString, int, int)));
|
||||||
|
|
||||||
|
players << newPlayer;
|
||||||
|
emit playerAdded(newPlayer);
|
||||||
|
|
||||||
|
return newPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::playerListReceived(QList<ServerPlayer *> playerList)
|
||||||
|
{
|
||||||
|
QListIterator<ServerPlayer *> i(playerList);
|
||||||
|
QStringList nameList;
|
||||||
|
while (i.hasNext()) {
|
||||||
|
ServerPlayer *temp = i.next();
|
||||||
|
nameList << temp->getName();
|
||||||
|
int id = temp->getPlayerId();
|
||||||
|
|
||||||
|
if (id != localPlayer->getId())
|
||||||
|
addPlayer(id, temp->getName(), QPointF(0, 0), false);
|
||||||
|
|
||||||
|
delete temp;
|
||||||
|
}
|
||||||
|
emit logPlayerListReceived(nameList);
|
||||||
|
restartGameDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::restartGameDialog()
|
||||||
|
{
|
||||||
|
dlgStartGame->exec();
|
||||||
|
client->submitDeck(dlgStartGame->getDeckList());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::gameEvent(ServerEventData *msg)
|
||||||
|
{
|
||||||
|
if (!msg->getPublic())
|
||||||
|
localPlayer->gameEvent(msg);
|
||||||
|
else {
|
||||||
|
Player *p = players.findPlayer(msg->getPlayerId());
|
||||||
|
if (!p) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(msg->getEventType()) {
|
||||||
|
case eventSay:
|
||||||
|
emit logSay(p->getName(), msg->getEventData()[0]);
|
||||||
|
break;
|
||||||
|
case eventJoin: {
|
||||||
|
emit logJoin(msg->getPlayerName());
|
||||||
|
addPlayer(msg->getPlayerId(), msg->getPlayerName(), QPointF(0, 0), false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventLeave:
|
||||||
|
emit logLeave(msg->getPlayerName());
|
||||||
|
// XXX Spieler natürlich noch rauswerfen
|
||||||
|
break;
|
||||||
|
case eventReadyStart:
|
||||||
|
if (started) {
|
||||||
|
started = false;
|
||||||
|
emit logReadyStart(p->getName());
|
||||||
|
if (!p->getLocal())
|
||||||
|
restartGameDialog();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case eventGameStart:
|
||||||
|
started = true;
|
||||||
|
emit logGameStart();
|
||||||
|
break;
|
||||||
|
case eventShuffle:
|
||||||
|
emit logShuffle(p->getName());
|
||||||
|
break;
|
||||||
|
case eventRollDice: {
|
||||||
|
QStringList data = msg->getEventData();
|
||||||
|
int sides = data[0].toInt();
|
||||||
|
int roll = data[1].toInt();
|
||||||
|
emit logRollDice(p->getName(), sides, roll);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventSetActivePlayer:
|
||||||
|
break;
|
||||||
|
case eventSetActivePhase:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eventName:
|
||||||
|
case eventCreateToken:
|
||||||
|
case eventSetupZones:
|
||||||
|
case eventSetCardAttr:
|
||||||
|
case eventSetCounter:
|
||||||
|
case eventDelCounter:
|
||||||
|
case eventPlayerId: {
|
||||||
|
p->gameEvent(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventDumpZone: {
|
||||||
|
QStringList data = msg->getEventData();
|
||||||
|
emit logDumpZone(p->getName(), data[1], players.findPlayer(data[0].toInt())->getName(), data[2].toInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventMoveCard: {
|
||||||
|
if (msg->getPlayerId() == localPlayer->getId())
|
||||||
|
break;
|
||||||
|
p->gameEvent(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventDraw: {
|
||||||
|
emit logDraw(p->getName(), msg->getEventData()[0].toInt());
|
||||||
|
if (msg->getPlayerId() == localPlayer->getId())
|
||||||
|
break;
|
||||||
|
p->gameEvent(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventInvalid:
|
||||||
|
qDebug("Unhandled global event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actUntapAll()
|
||||||
|
{
|
||||||
|
CardList *const cards = localPlayer->getZones()->findZone("table")->getCards();
|
||||||
|
for (int i = 0; i < cards->size(); i++)
|
||||||
|
client->setCardAttr("table", cards->at(i)->getId(), "tapped", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actIncLife()
|
||||||
|
{
|
||||||
|
client->incCounter("life", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actDecLife()
|
||||||
|
{
|
||||||
|
client->incCounter("life", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actSetLife()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int life = QInputDialog::getInteger(0, tr("Set life"), tr("New life total:"), localPlayer->getCounters()->findCounter("life")->getValue(), 0, 2000000000, 1, &ok);
|
||||||
|
client->setCounter("life", life);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actShuffle()
|
||||||
|
{
|
||||||
|
client->shuffle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actRollDice()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int sides = QInputDialog::getInteger(0, tr("Roll dice"), tr("Number of sides:"), 20, 2, 1000, 1, &ok);
|
||||||
|
if (ok)
|
||||||
|
client->rollDice(sides);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actDrawCard()
|
||||||
|
{
|
||||||
|
client->drawCards(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actDrawCards()
|
||||||
|
{
|
||||||
|
int number = QInputDialog::getInteger(0, tr("Draw cards"), tr("Number:"));
|
||||||
|
if (number)
|
||||||
|
client->drawCards(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actCreateToken()
|
||||||
|
{
|
||||||
|
QString cardname = QInputDialog::getText(0, tr("Create token"), tr("Name:"));
|
||||||
|
if (!db->getCard(cardname))
|
||||||
|
QMessageBox::critical(0, "Error", "No such card");
|
||||||
|
else
|
||||||
|
client->createToken("table", cardname, QString(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::showCardMenu(QPoint p)
|
||||||
|
{
|
||||||
|
cardMenu->exec(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actTap()
|
||||||
|
{
|
||||||
|
QListIterator<QGraphicsItem *> i(scene->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
client->setCardAttr(qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName(), temp->getId(), "tapped", "1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actUntap()
|
||||||
|
{
|
||||||
|
QListIterator<QGraphicsItem *> i(scene->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
client->setCardAttr(qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName(), temp->getId(), "tapped", "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actAddCounter()
|
||||||
|
{
|
||||||
|
QListIterator<QGraphicsItem *> i(scene->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
if (temp->getCounters() < MAX_COUNTERS_ON_CARD)
|
||||||
|
client->setCardAttr(qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(temp->getCounters() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actRemoveCounter()
|
||||||
|
{
|
||||||
|
QListIterator<QGraphicsItem *> i(scene->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
if (temp->getCounters())
|
||||||
|
client->setCardAttr(qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(temp->getCounters() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actSetCounters()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int number = QInputDialog::getInteger(0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok);
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QListIterator<QGraphicsItem *> i(scene->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
client->setCardAttr(qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName(), temp->getId(), "counters", QString::number(number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::actRearrange()
|
||||||
|
{
|
||||||
|
// nur sinnvoll bei Karten auf dem Tisch -> Einschränkung einbauen
|
||||||
|
int x, y, x_initial = 0, y_initial = 0;
|
||||||
|
QList<QGraphicsItem *> list = scene->selectedItems();
|
||||||
|
|
||||||
|
// Find coordinates of leftmost card
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
CardItem *temp = (CardItem *) list.at(i);
|
||||||
|
if ((temp->pos().x() < x_initial) || (x_initial == 0)) {
|
||||||
|
x_initial = (int) temp->pos().x();
|
||||||
|
y_initial = (int) temp->pos().y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x = x_initial;
|
||||||
|
y = y_initial;
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
CardItem *temp = (CardItem *) list.at(i);
|
||||||
|
QString zoneName = qgraphicsitem_cast<PlayerZone *>(temp->parentItem())->getName();
|
||||||
|
x = x_initial + i * RASTER_WIDTH;
|
||||||
|
y = y_initial + (i % 3) * RASTER_HEIGHT;
|
||||||
|
client->moveCard(temp->getId(), zoneName, zoneName, x, y);
|
||||||
|
}
|
||||||
|
}
|
80
cockatrice/src/game.h
Normal file
80
cockatrice/src/game.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef GAME_H
|
||||||
|
#define GAME_H
|
||||||
|
|
||||||
|
#include "playerlist.h"
|
||||||
|
|
||||||
|
class ServerPlayer;
|
||||||
|
class QGraphicsScene;
|
||||||
|
class Player;
|
||||||
|
class Client;
|
||||||
|
class ServerEventData;
|
||||||
|
class CardDatabase;
|
||||||
|
class DlgStartGame;
|
||||||
|
|
||||||
|
class Game : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QMenu *actionsMenu, *cardMenu;
|
||||||
|
QAction *aTap, *aUntap, *aAddCounter, *aRemoveCounter, *aSetCounters, *aRearrange,
|
||||||
|
*aUntapAll, *aDecLife, *aIncLife, *aSetLife, *aShuffle, *aDraw, *aDrawCards, *aRollDice, *aCreateToken;
|
||||||
|
DlgStartGame *dlgStartGame;
|
||||||
|
|
||||||
|
CardDatabase *db;
|
||||||
|
Client *client;
|
||||||
|
QGraphicsScene *scene;
|
||||||
|
PlayerList players;
|
||||||
|
Player *localPlayer;
|
||||||
|
bool started;
|
||||||
|
Player *addPlayer(int playerId, const QString &playerName, QPointF base, bool local);
|
||||||
|
private slots:
|
||||||
|
void actUntapAll();
|
||||||
|
void actIncLife();
|
||||||
|
void actDecLife();
|
||||||
|
void actSetLife();
|
||||||
|
void actShuffle();
|
||||||
|
void actDrawCard();
|
||||||
|
void actDrawCards();
|
||||||
|
void actRollDice();
|
||||||
|
void actCreateToken();
|
||||||
|
|
||||||
|
void showCardMenu(QPoint p);
|
||||||
|
void actTap();
|
||||||
|
void actUntap();
|
||||||
|
void actAddCounter();
|
||||||
|
void actRemoveCounter();
|
||||||
|
void actSetCounters();
|
||||||
|
void actRearrange();
|
||||||
|
|
||||||
|
void gameEvent(ServerEventData *msg);
|
||||||
|
void playerListReceived(QList<ServerPlayer *> playerList);
|
||||||
|
signals:
|
||||||
|
void submitDecklist();
|
||||||
|
void hoverCard(QString name);
|
||||||
|
void playerAdded(Player *player);
|
||||||
|
void playerRemoved(Player *player);
|
||||||
|
|
||||||
|
// Log events
|
||||||
|
void logPlayerListReceived(QStringList players);
|
||||||
|
void logJoin(QString playerName);
|
||||||
|
void logLeave(QString playerName);
|
||||||
|
void logReadyStart(QString playerName);
|
||||||
|
void logGameStart();
|
||||||
|
void logSay(QString playerName, QString text);
|
||||||
|
void logShuffle(QString playerName);
|
||||||
|
void logRollDice(QString playerName, int sides, int roll);
|
||||||
|
void logDraw(QString playerName, int number);
|
||||||
|
void logMoveCard(QString playerName, QString cardName, QString startZone, QString targetZone);
|
||||||
|
void logCreateToken(QString playerName, QString cardName);
|
||||||
|
void logSetCardCounters(QString playerName, QString cardName, int value, int oldValue);
|
||||||
|
void logSetTapped(QString playerName, QString cardName, bool tapped);
|
||||||
|
void logSetCounter(QString playerName, QString counterName, int value, int oldValue);
|
||||||
|
void logDumpZone(QString playerName, QString zoneName, QString zoneOwner, int numberCards);
|
||||||
|
public slots:
|
||||||
|
void restartGameDialog();
|
||||||
|
public:
|
||||||
|
Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_actionsMenu, QMenu *_cardMenu, int playerId, const QString &playerName);
|
||||||
|
~Game();
|
||||||
|
Player *getLocalPlayer() const { return localPlayer; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
74
cockatrice/src/gamesmodel.cpp
Normal file
74
cockatrice/src/gamesmodel.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#include "gamesmodel.h"
|
||||||
|
#include "servergame.h"
|
||||||
|
|
||||||
|
GamesModel::~GamesModel()
|
||||||
|
{
|
||||||
|
cleanList();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GamesModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return gameList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GamesModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GamesModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
if ((index.row() >= gameList.size()) || (index.column() >= 4))
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
ServerGame *g = gameList.at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0: return g->getName();
|
||||||
|
case 1: return g->getDescription();
|
||||||
|
case 2: return QString(g->getHasPassword() ? "yes" : "no");
|
||||||
|
case 3: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers());
|
||||||
|
default: return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
if (orientation != Qt::Horizontal)
|
||||||
|
return QVariant();
|
||||||
|
switch (section) {
|
||||||
|
case 0: return QString("Name");
|
||||||
|
case 1: return QString("Description");
|
||||||
|
case 2: return QString("Password");
|
||||||
|
case 3: return QString("Players");
|
||||||
|
default: return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerGame *GamesModel::getGame(int row)
|
||||||
|
{
|
||||||
|
if (row >= gameList.size())
|
||||||
|
return 0;
|
||||||
|
return gameList[row];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamesModel::setGameList(const QList<ServerGame *> &_gameList)
|
||||||
|
{
|
||||||
|
cleanList();
|
||||||
|
gameList = _gameList;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamesModel::cleanList()
|
||||||
|
{
|
||||||
|
QListIterator<ServerGame *> i(gameList);
|
||||||
|
while (i.hasNext())
|
||||||
|
delete i.next();
|
||||||
|
gameList.clear();
|
||||||
|
}
|
26
cockatrice/src/gamesmodel.h
Normal file
26
cockatrice/src/gamesmodel.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef GAMESMODEL_H
|
||||||
|
#define GAMESMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QList>
|
||||||
|
#include "servergame.h"
|
||||||
|
|
||||||
|
class GamesModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GamesModel(QObject *parent = 0)
|
||||||
|
: QAbstractListModel(parent) { }
|
||||||
|
~GamesModel();
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
void setGameList(const QList<ServerGame *> &_gameList);
|
||||||
|
ServerGame *getGame(int row);
|
||||||
|
private:
|
||||||
|
QList<ServerGame *> gameList;
|
||||||
|
void cleanList();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
33
cockatrice/src/gameview.cpp
Normal file
33
cockatrice/src/gameview.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include "gameview.h"
|
||||||
|
|
||||||
|
GameView::GameView(QGraphicsScene *scene, QWidget *parent)
|
||||||
|
: QGraphicsView(scene, parent)
|
||||||
|
{
|
||||||
|
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
|
||||||
|
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||||
|
setOptimizationFlags(/*DontClipPainter | */DontSavePainterState);
|
||||||
|
setDragMode(RubberBandDrag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::scaleToScene()
|
||||||
|
{
|
||||||
|
// This function ensures that the bounding rectangles of card pictures
|
||||||
|
// have integer sizes. This is achieved by using a scale factor of n / 6.
|
||||||
|
QRectF sr = scene()->sceneRect();
|
||||||
|
QRectF vr = QRectF(viewport()->rect().adjusted(2, 2, -2, -2));
|
||||||
|
qreal scale_h = vr.width() / sr.width();
|
||||||
|
qreal scale_v = vr.height() / sr.height();
|
||||||
|
qreal scale_total = qMin(scale_h, scale_v);
|
||||||
|
|
||||||
|
qreal scale_corr = (qreal) ((int) (scale_total * 6)) / 6;
|
||||||
|
|
||||||
|
qDebug(QString("scale_corr = %1 / 6").arg(scale_corr * 6).toLatin1());
|
||||||
|
setTransform(QTransform().scale(scale_corr, scale_corr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameView::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
qDebug("GameView: resizeEvent");
|
||||||
|
QGraphicsView::resizeEvent(event);
|
||||||
|
scaleToScene();
|
||||||
|
}
|
14
cockatrice/src/gameview.h
Normal file
14
cockatrice/src/gameview.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef GAMEVIEW_H
|
||||||
|
#define GAMEVIEW_H
|
||||||
|
|
||||||
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
class GameView : public QGraphicsView {
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
public:
|
||||||
|
void scaleToScene();
|
||||||
|
GameView(QGraphicsScene *scene, QWidget *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
53
cockatrice/src/gravezone.cpp
Normal file
53
cockatrice/src/gravezone.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "gravezone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
|
GraveZone::GraveZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "grave")
|
||||||
|
{
|
||||||
|
cards = new CardList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraveZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraveZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->save();
|
||||||
|
painter->fillRect(boundingRect(), QColor("yellow"));
|
||||||
|
painter->setFont(QFont("Times", 20, QFont::Bold));
|
||||||
|
painter->setPen(QPen(QColor("black")));
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString::number(cards->size()));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraveZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < views.size(); i++)
|
||||||
|
views[i]->addCard(new CardItem(player->getDb(), card->getName(), card->getId()), reorganize, x, y);
|
||||||
|
|
||||||
|
cards->insert(x, card);
|
||||||
|
card->setPos(0, 0);
|
||||||
|
card->setVisible(false);
|
||||||
|
card->resetState();
|
||||||
|
card->setParentItem(this);
|
||||||
|
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraveZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraveZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
17
cockatrice/src/gravezone.h
Normal file
17
cockatrice/src/gravezone.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef GRAVEZONE_H
|
||||||
|
#define GRAVEZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
class GraveZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
GraveZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = 0, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
73
cockatrice/src/handzone.cpp
Normal file
73
cockatrice/src/handzone.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "handzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
HandZone::HandZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "hand")
|
||||||
|
{
|
||||||
|
cards = new CardList(player->getLocal());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF HandZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 100, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->fillRect(boundingRect(), QColor("green"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
if (cards->isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int cardCount = cards->size();
|
||||||
|
qreal totalWidth = boundingRect().width();
|
||||||
|
qreal totalHeight = boundingRect().height();
|
||||||
|
qreal cardWidth = cards->at(0)->boundingRect().width();
|
||||||
|
qreal cardHeight = cards->at(0)->boundingRect().height();
|
||||||
|
qreal x = (totalWidth - cardWidth) / 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < cardCount; i++) {
|
||||||
|
CardItem *c = cards->at(i);
|
||||||
|
// If the total height of the cards is smaller than the available height,
|
||||||
|
// the cards do not need to overlap and are displayed in the center of the area.
|
||||||
|
if (cardHeight * cardCount > totalHeight)
|
||||||
|
c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1));
|
||||||
|
else
|
||||||
|
c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2);
|
||||||
|
c->setZValue(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
Q_UNUSED(y);
|
||||||
|
|
||||||
|
if (x == -1)
|
||||||
|
x = cards->size();
|
||||||
|
cards->insert(x, card);
|
||||||
|
|
||||||
|
if (!cards->getContentsKnown()) {
|
||||||
|
card->setId(-1);
|
||||||
|
card->setName();
|
||||||
|
}
|
||||||
|
card->setParentItem(this);
|
||||||
|
card->resetState();
|
||||||
|
card->setVisible(true);
|
||||||
|
card->update(card->boundingRect());
|
||||||
|
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
Q_UNUSED(dropPoint);
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), cards->size(), 0);
|
||||||
|
}
|
17
cockatrice/src/handzone.h
Normal file
17
cockatrice/src/handzone.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef HANDZONE_H
|
||||||
|
#define HANDZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
class HandZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
HandZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = -1, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
88
cockatrice/src/libraryzone.cpp
Normal file
88
cockatrice/src/libraryzone.cpp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "libraryzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "carddragitem.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
|
LibraryZone::LibraryZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "deck")
|
||||||
|
{
|
||||||
|
cards = new CardList(false);
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF LibraryZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->save();
|
||||||
|
painter->fillRect(boundingRect(), QColor("red"));
|
||||||
|
painter->setFont(QFont("Times", 20, QFont::Bold));
|
||||||
|
painter->setPen(QPen(QColor("black")));
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString::number(cards->size()));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < views.size(); i++)
|
||||||
|
views[i]->addCard(new CardItem(player->getDb(), card->getName(), card->getId()), reorganize, x, y);
|
||||||
|
|
||||||
|
cards->insert(x, card);
|
||||||
|
card->setId(-1);
|
||||||
|
card->setName(QString());
|
||||||
|
card->setPos(0, 0);
|
||||||
|
card->setVisible(false);
|
||||||
|
card->resetState();
|
||||||
|
card->setParentItem(this);
|
||||||
|
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
PlayerZone::mousePressEvent(event);
|
||||||
|
if (event->isAccepted())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
setCursor(Qt::ClosedHandCursor);
|
||||||
|
event->accept();
|
||||||
|
} else
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CardItem *card = cards->at(0);
|
||||||
|
CardDragItem *drag = card->createDragItem(this, 0, event->pos(), event->scenePos());
|
||||||
|
drag->grabMouse();
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryZone::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
21
cockatrice/src/libraryzone.h
Normal file
21
cockatrice/src/libraryzone.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef LIBRARYZONE_H
|
||||||
|
#define LIBRARYZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
class LibraryZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
LibraryZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = 0, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
51
cockatrice/src/main.cpp
Normal file
51
cockatrice/src/main.cpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@gmx.net *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QtPlugin>
|
||||||
|
#include "window.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//Q_IMPORT_PLUGIN(qjpeg)
|
||||||
|
|
||||||
|
void myMessageOutput(QtMsgType type, const char *msg)
|
||||||
|
{
|
||||||
|
static FILE *f = NULL;
|
||||||
|
if (!f)
|
||||||
|
f = fopen("qdebug.txt", "w");
|
||||||
|
fprintf(f, "%s\n", msg);
|
||||||
|
fflush(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
qInstallMsgHandler(myMessageOutput);
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
app.addLibraryPath("plugins");
|
||||||
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
|
MainWindow *ui = new MainWindow;
|
||||||
|
ui->show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
147
cockatrice/src/messagelogwidget.cpp
Normal file
147
cockatrice/src/messagelogwidget.cpp
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
#include "messagelogwidget.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
void MessageLogWidget::appendAndScroll(const QString &s)
|
||||||
|
{
|
||||||
|
append(s);
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logConnecting(QString hostname)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("Connecting to %1...").arg(hostname));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logConnected(const QStringList WelcomeMsg)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("Connected."));
|
||||||
|
|
||||||
|
QStringListIterator i(WelcomeMsg);
|
||||||
|
while (i.hasNext())
|
||||||
|
appendAndScroll(i.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logDisconnected()
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("Disconnected from server."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logSocketError(const QString &errorString)
|
||||||
|
{
|
||||||
|
appendAndScroll(errorString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logPlayerListReceived(QStringList players)
|
||||||
|
{
|
||||||
|
append("---");
|
||||||
|
append(tr("You have joined the game. Player list:"));
|
||||||
|
for (int i = 0; i < players.size(); i++)
|
||||||
|
append(players.at(i));
|
||||||
|
appendAndScroll("---");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logJoin(QString playerName)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 has joined the game").arg(playerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logLeave(QString playerName)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 has left the game").arg(playerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logReadyStart(QString playerName)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 is ready to start a new game.").arg(playerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logGameStart()
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("Game has started."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logSay(QString playerName, QString message)
|
||||||
|
{
|
||||||
|
appendAndScroll(QString("<font color=\"red\">%1:</font> %2").arg(playerName).arg(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logShuffle(QString playerName)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 shuffles his/her library").arg(playerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logRollDice(QString playerName, int sides, int roll)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 rolled a %2 with a %3-sided dice").arg(playerName).arg(roll).arg(sides));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logDraw(QString playerName, int number)
|
||||||
|
{
|
||||||
|
if (number == 1)
|
||||||
|
appendAndScroll(tr("%1 draws a card").arg(playerName));
|
||||||
|
else
|
||||||
|
appendAndScroll(tr("%1 draws %2 cards").arg(playerName).arg(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logMoveCard(QString playerName, QString cardName, QString startZone, QString targetZone)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 moves %2 from %3 to %4").arg(playerName).arg(cardName).arg(startZone).arg(targetZone));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logCreateToken(QString playerName, QString cardName)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 creates token: %2").arg(playerName).arg(cardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logSetCardCounters(QString playerName, QString cardName, int value, int oldValue)
|
||||||
|
{
|
||||||
|
if (value > oldValue)
|
||||||
|
appendAndScroll(tr("%1 places %2 counters on %3 (now %4)").arg(playerName).arg(value - oldValue).arg(cardName).arg(value));
|
||||||
|
else
|
||||||
|
appendAndScroll(tr("%1 removes %2 counters from %3 (now %4)").arg(playerName).arg(oldValue - value).arg(cardName).arg(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logSetTapped(QString playerName, QString cardName, bool tapped)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 %2 %3").arg(playerName).arg(tapped ? "taps" : "untaps").arg(cardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logSetCounter(QString playerName, QString counterName, int value, int oldValue)
|
||||||
|
{
|
||||||
|
appendAndScroll(tr("%1 sets counter \"%2\" to %3 (%4%5)").arg(playerName).arg(counterName).arg(value).arg(value > oldValue ? "+" : "").arg(value - oldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logDumpZone(QString playerName, QString zoneName, QString zoneOwner, int numberCards)
|
||||||
|
{
|
||||||
|
if (numberCards)
|
||||||
|
appendAndScroll(tr("%1 is looking at the top %2 cards of %3's %4").arg(playerName).arg(numberCards).arg(zoneOwner).arg(zoneName));
|
||||||
|
else
|
||||||
|
appendAndScroll(tr("%1 is looking at %2's %3").arg(playerName).arg(zoneOwner).arg(zoneName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MessageLogWidget::connectToGame(Game *game)
|
||||||
|
{
|
||||||
|
connect(game, SIGNAL(logPlayerListReceived(QStringList)), this, SLOT(logPlayerListReceived(QStringList)));
|
||||||
|
connect(game, SIGNAL(logJoin(QString)), this, SLOT(logJoin(QString)));
|
||||||
|
connect(game, SIGNAL(logLeave(QString)), this, SLOT(logLeave(QString)));
|
||||||
|
connect(game, SIGNAL(logReadyStart(QString)), this, SLOT(logReadyStart(QString)));
|
||||||
|
connect(game, SIGNAL(logGameStart()), this, SLOT(logGameStart()));
|
||||||
|
connect(game, SIGNAL(logSay(QString, QString)), this, SLOT(logSay(QString, QString)));
|
||||||
|
connect(game, SIGNAL(logShuffle(QString)), this, SLOT(logShuffle(QString)));
|
||||||
|
connect(game, SIGNAL(logRollDice(QString, int, int)), this, SLOT(logRollDice(QString, int, int)));
|
||||||
|
connect(game, SIGNAL(logDraw(QString, int)), this, SLOT(logDraw(QString, int)));
|
||||||
|
connect(game, SIGNAL(logMoveCard(QString, QString, QString, QString)), this, SLOT(logMoveCard(QString, QString, QString, QString)));
|
||||||
|
connect(game, SIGNAL(logCreateToken(QString, QString)), this, SLOT(logCreateToken(QString, QString)));
|
||||||
|
connect(game, SIGNAL(logSetCardCounters(QString, QString, int, int)), this, SLOT(logSetCardCounters(QString, QString, int, int)));
|
||||||
|
connect(game, SIGNAL(logSetTapped(QString, QString, bool)), this, SLOT(logSetTapped(QString, QString, bool)));
|
||||||
|
connect(game, SIGNAL(logSetCounter(QString, QString, int, int)), this, SLOT(logSetCounter(QString, QString, int, int)));
|
||||||
|
connect(game, SIGNAL(logDumpZone(QString, QString, QString, int)), this, SLOT(logDumpZone(QString, QString, QString, int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLogWidget::MessageLogWidget(QWidget *parent)
|
||||||
|
: QTextEdit(parent)
|
||||||
|
{
|
||||||
|
setReadOnly(true);
|
||||||
|
}
|
39
cockatrice/src/messagelogwidget.h
Normal file
39
cockatrice/src/messagelogwidget.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef MESSAGELOGWIDGET_H
|
||||||
|
#define MESSAGELOGWIDGET_H
|
||||||
|
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
|
||||||
|
class MessageLogWidget : public QTextEdit {
|
||||||
|
Q_OBJECT
|
||||||
|
public slots:
|
||||||
|
void logConnecting(QString hostname);
|
||||||
|
void logConnected(const QStringList WelcomeMsg);
|
||||||
|
void logDisconnected();
|
||||||
|
void logSocketError(const QString &errorString);
|
||||||
|
private slots:
|
||||||
|
void logPlayerListReceived(QStringList players);
|
||||||
|
void logJoin(QString playerName);
|
||||||
|
void logLeave(QString playerName);
|
||||||
|
void logReadyStart(QString playerName);
|
||||||
|
void logGameStart();
|
||||||
|
void logSay(QString playerName, QString message);
|
||||||
|
void logShuffle(QString playerName);
|
||||||
|
void logRollDice(QString playerName, int sides, int roll);
|
||||||
|
void logDraw(QString playerName, int number);
|
||||||
|
void logMoveCard(QString playerName, QString cardName, QString startZone, QString targetZone);
|
||||||
|
void logCreateToken(QString playerName, QString cardName);
|
||||||
|
void logSetCardCounters(QString playerName, QString cardName, int value, int oldValue);
|
||||||
|
void logSetTapped(QString playerName, QString cardName, bool tapped);
|
||||||
|
void logSetCounter(QString playerName, QString counterName, int value, int oldValue);
|
||||||
|
void logDumpZone(QString playerName, QString zoneName, QString zoneOwner, int numberCards);
|
||||||
|
private:
|
||||||
|
void appendAndScroll(const QString &s);
|
||||||
|
public:
|
||||||
|
void connectToGame(Game *game);
|
||||||
|
MessageLogWidget(QWidget *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
19
cockatrice/src/pendingcommand.h
Normal file
19
cockatrice/src/pendingcommand.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef PENDINGCOMMAND_H
|
||||||
|
#define PENDINGCOMMAND_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class PendingCommand {
|
||||||
|
private:
|
||||||
|
QString cmd;
|
||||||
|
int msgid;
|
||||||
|
int time;
|
||||||
|
public:
|
||||||
|
int getMsgId() const { return msgid; }
|
||||||
|
QString getCmd() const { return cmd; }
|
||||||
|
bool timeout() const { return time > 5; }
|
||||||
|
void incTime() { ++time; }
|
||||||
|
PendingCommand(const QString &_cmd, int _msgid) : cmd(_cmd), msgid(_msgid), time(0) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
296
cockatrice/src/player.cpp
Normal file
296
cockatrice/src/player.cpp
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "handzone.h"
|
||||||
|
#include "tablezone.h"
|
||||||
|
#include "libraryzone.h"
|
||||||
|
#include "gravezone.h"
|
||||||
|
#include "rfgzone.h"
|
||||||
|
#include "sideboardzone.h"
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
Player::Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client)
|
||||||
|
: QObject(), defaultNumberTopCards(3), name(_name), id(_id), base(_base), local(_local), db(_db), client(_client)
|
||||||
|
{
|
||||||
|
LibraryZone *deck = new LibraryZone(this);
|
||||||
|
deck->setPos(_base);
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
qreal foo = deck->boundingRect().height();
|
||||||
|
|
||||||
|
GraveZone *grave = new GraveZone(this);
|
||||||
|
grave->setPos(_base + QPointF(0, foo));
|
||||||
|
|
||||||
|
RfgZone *rfg = new RfgZone(this);
|
||||||
|
rfg->setPos(_base + QPointF(0, 2 * foo));
|
||||||
|
|
||||||
|
SideboardZone *sb = new SideboardZone(this);
|
||||||
|
sb->setPos(_base + QPointF(0, 3 * foo));
|
||||||
|
|
||||||
|
Counter *life = new Counter(this, "life");
|
||||||
|
life->setPos(_base + QPointF(-50, 5 * foo));
|
||||||
|
|
||||||
|
_base += QPointF(deck->boundingRect().width(), 0);
|
||||||
|
|
||||||
|
PlayerZone *hand = new HandZone(this);
|
||||||
|
hand->setPos(_base);
|
||||||
|
_base += QPointF(hand->boundingRect().width(), 0);
|
||||||
|
|
||||||
|
PlayerZone *table = new TableZone(this);
|
||||||
|
table->setPos(_base);
|
||||||
|
|
||||||
|
aMoveHandToTopLibrary = new QAction(tr("Move to &top of library"), this);
|
||||||
|
connect(aMoveHandToTopLibrary, SIGNAL(triggered()), this, SLOT(actMoveHandToTopLibrary()));
|
||||||
|
aMoveHandToBottomLibrary = new QAction(tr("Move to &bottom of library"), this);
|
||||||
|
connect(aMoveHandToBottomLibrary, SIGNAL(triggered()), this, SLOT(actMoveHandToBottomLibrary()));
|
||||||
|
|
||||||
|
aViewLibrary = new QAction(tr("&View library"), this);
|
||||||
|
if (local)
|
||||||
|
aViewLibrary->setShortcut(tr("F5"));
|
||||||
|
connect(aViewLibrary, SIGNAL(triggered()), this, SLOT(actViewLibrary()));
|
||||||
|
aViewTopCards = new QAction(tr("View &top cards of library..."), this);
|
||||||
|
connect(aViewTopCards, SIGNAL(triggered()), this, SLOT(actViewTopCards()));
|
||||||
|
|
||||||
|
aViewGraveyard = new QAction(tr("&View graveyard"), this);
|
||||||
|
if (local)
|
||||||
|
aViewGraveyard->setShortcut(tr("F6"));
|
||||||
|
connect(aViewGraveyard, SIGNAL(triggered()), this, SLOT(actViewGraveyard()));
|
||||||
|
|
||||||
|
aViewRfg = new QAction(tr("&View removed cards"), this);
|
||||||
|
connect(aViewRfg, SIGNAL(triggered()), this, SLOT(actViewRfg()));
|
||||||
|
|
||||||
|
aViewSideboard = new QAction(tr("&View sideboard"), this);
|
||||||
|
connect(aViewSideboard, SIGNAL(triggered()), this, SLOT(actViewSideboard()));
|
||||||
|
|
||||||
|
playerMenu = new QMenu(tr("Player \"%1\"").arg(name));
|
||||||
|
|
||||||
|
QMenu *handMenu = playerMenu->addMenu(tr("&Hand"));
|
||||||
|
handMenu->addAction(aMoveHandToTopLibrary);
|
||||||
|
handMenu->addAction(aMoveHandToBottomLibrary);
|
||||||
|
hand->setMenu(handMenu);
|
||||||
|
|
||||||
|
QMenu *libraryMenu = playerMenu->addMenu(tr("&Library"));
|
||||||
|
libraryMenu->addAction(aViewLibrary);
|
||||||
|
libraryMenu->addAction(aViewTopCards);
|
||||||
|
deck->setMenu(libraryMenu);
|
||||||
|
|
||||||
|
QMenu *graveMenu = playerMenu->addMenu(tr("&Graveyard"));
|
||||||
|
graveMenu->addAction(aViewGraveyard);
|
||||||
|
grave->setMenu(graveMenu);
|
||||||
|
|
||||||
|
QMenu *rfgMenu = playerMenu->addMenu(tr("&Removed cards"));
|
||||||
|
rfgMenu->addAction(aViewRfg);
|
||||||
|
rfg->setMenu(rfgMenu);
|
||||||
|
|
||||||
|
QMenu *sbMenu = playerMenu->addMenu(tr("&Sideboard"));
|
||||||
|
sbMenu->addAction(aViewSideboard);
|
||||||
|
sb->setMenu(sbMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
Player::~Player()
|
||||||
|
{
|
||||||
|
qDebug("Player destructor");
|
||||||
|
|
||||||
|
for (int i = 0; i < zones.size(); i++)
|
||||||
|
delete zones.at(i);
|
||||||
|
|
||||||
|
for (int i = 0; i < counters.size(); i++)
|
||||||
|
delete counters.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actMoveHandToTopLibrary()
|
||||||
|
{
|
||||||
|
PlayerZone *library = zones.findZone("deck");
|
||||||
|
zones.findZone("hand")->moveAllToZone(library->getName(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actMoveHandToBottomLibrary()
|
||||||
|
{
|
||||||
|
PlayerZone *library = zones.findZone("deck");
|
||||||
|
zones.findZone("hand")->moveAllToZone(library->getName(), library->getCards()->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actViewLibrary()
|
||||||
|
{
|
||||||
|
emit addZoneView(this, "deck", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actViewTopCards()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int number = QInputDialog::getInteger(0, tr("View top cards of library"), tr("Number of cards:"), defaultNumberTopCards, 1, 2000000000, 1, &ok);
|
||||||
|
if (ok) {
|
||||||
|
defaultNumberTopCards = number;
|
||||||
|
emit addZoneView(this, "deck", number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actViewGraveyard()
|
||||||
|
{
|
||||||
|
emit addZoneView(this, "grave", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actViewRfg()
|
||||||
|
{
|
||||||
|
emit addZoneView(this, "rfg", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::actViewSideboard()
|
||||||
|
{
|
||||||
|
emit addZoneView(this, "sb", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::addZone(PlayerZone *z)
|
||||||
|
{
|
||||||
|
zones << z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::addCounter(Counter *c)
|
||||||
|
{
|
||||||
|
counters << c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::gameEvent(ServerEventData *event)
|
||||||
|
{
|
||||||
|
QStringList data = event->getEventData();
|
||||||
|
switch (event->getEventType()) {
|
||||||
|
case eventSetupZones: {
|
||||||
|
// XXX Life counter
|
||||||
|
int life = data[0].toInt();
|
||||||
|
int deck_cards = data[1].toInt();
|
||||||
|
int sb_cards = data[2].toInt();
|
||||||
|
// XXX Fehlerbehandlung
|
||||||
|
|
||||||
|
// Clean up existing zones first
|
||||||
|
for (int i = 0; i < zones.size(); i++)
|
||||||
|
zones.at(i)->clearContents();
|
||||||
|
|
||||||
|
Counter *lifeCounter = counters.findCounter("life");
|
||||||
|
lifeCounter->setValue(life);
|
||||||
|
|
||||||
|
PlayerZone *deck = zones.findZone("deck");
|
||||||
|
for (; deck_cards; deck_cards--)
|
||||||
|
deck->addCard(new CardItem(db, QString(), -1));
|
||||||
|
deck->reorganizeCards();
|
||||||
|
|
||||||
|
PlayerZone *sb = zones.findZone("sb");
|
||||||
|
for (; sb_cards; sb_cards--)
|
||||||
|
sb->addCard(new CardItem(db, QString(), -1));
|
||||||
|
sb->reorganizeCards();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventDraw: {
|
||||||
|
PlayerZone *deck = zones.findZone("deck");
|
||||||
|
PlayerZone *hand = zones.findZone("hand");
|
||||||
|
if (!event->getPublic()) {
|
||||||
|
hand->addCard(deck->takeCard(0, data[0].toInt(), data[1]));
|
||||||
|
} else {
|
||||||
|
int number = data[0].toInt();
|
||||||
|
for (; number; number--)
|
||||||
|
hand->addCard(deck->takeCard(0, -1, QString()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventMoveCard: {
|
||||||
|
if (data.size() != 7) {
|
||||||
|
qDebug("error");
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
int cardId = data[0].toInt();
|
||||||
|
QString cardName = data[1];
|
||||||
|
PlayerZone *startZone = zones.findZone(data[2]);
|
||||||
|
if (!startZone)
|
||||||
|
qDebug(QString("start zone invalid: %1").arg(data[2]).toLatin1());
|
||||||
|
int position = data[3].toInt();
|
||||||
|
PlayerZone *targetZone = zones.findZone(data[4]);
|
||||||
|
if (!targetZone)
|
||||||
|
qDebug(QString("target zone invalid: %1").arg(data[4]).toLatin1());
|
||||||
|
int x = data[5].toInt();
|
||||||
|
int y = data[6].toInt();
|
||||||
|
// XXX Mehr Fehlerbehandlung
|
||||||
|
|
||||||
|
CardItem *card = startZone->takeCard(position, cardId, cardName);
|
||||||
|
if (!card) // XXX
|
||||||
|
qDebug("null");
|
||||||
|
|
||||||
|
card->deleteDragItem();
|
||||||
|
|
||||||
|
// The log event has to be sent before the card is added to the target zone
|
||||||
|
// because the addCard function can modify the card object.
|
||||||
|
emit logMoveCard(name, card->getName(), startZone->getName(), targetZone->getName());
|
||||||
|
|
||||||
|
targetZone->addCard(card, true, x, y);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventCreateToken: {
|
||||||
|
// zone, cardid, cardname, powtough, x, y
|
||||||
|
if (data.size() != 6) {
|
||||||
|
qDebug("error");
|
||||||
|
}
|
||||||
|
PlayerZone *zone = zones.findZone(data[0]);
|
||||||
|
int cardid = data[1].toInt();
|
||||||
|
QString cardname = data[2];
|
||||||
|
QString powtough = data[3];
|
||||||
|
int x = data[4].toInt();
|
||||||
|
int y = data[5].toInt();
|
||||||
|
|
||||||
|
CardItem *card = new CardItem(db, cardname, cardid);
|
||||||
|
|
||||||
|
emit logCreateToken(name, card->getName());
|
||||||
|
zone->addCard(card, true, x, y);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventSetCardAttr: {
|
||||||
|
if (data.size() != 4) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
PlayerZone *zone = zones.findZone(data[0]);
|
||||||
|
int cardId = data[1].toInt();
|
||||||
|
CardItem *card = zone->getCard(cardId, "");
|
||||||
|
QString aname = data[2];
|
||||||
|
QString avalue = data[3];
|
||||||
|
// XXX Fehlerbehandlung
|
||||||
|
|
||||||
|
if (aname == "tapped") {
|
||||||
|
bool tapped = avalue == "1";
|
||||||
|
emit logSetTapped(name, card->getName(), tapped);
|
||||||
|
card->setTapped(tapped);
|
||||||
|
} else if (aname == "attacking")
|
||||||
|
card->setAttacking(avalue == "1");
|
||||||
|
else if (aname == "facedown")
|
||||||
|
card->setFacedown(avalue == "1");
|
||||||
|
else if (aname == "counters") {
|
||||||
|
int value = avalue.toInt();
|
||||||
|
emit logSetCardCounters(name, card->getName(), value, card->getCounters());
|
||||||
|
card->setCounters(value);
|
||||||
|
} else if (aname == "annotation")
|
||||||
|
card->setAnnotation(avalue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eventSetCounter: {
|
||||||
|
if (data.size() != 2) {
|
||||||
|
// XXX
|
||||||
|
}
|
||||||
|
int value = data[1].toInt();
|
||||||
|
Counter *c = counters.findCounter(data[0]);
|
||||||
|
int oldValue = c->getValue();
|
||||||
|
c->setValue(value);
|
||||||
|
emit logSetCounter(name, c->getName(), value, oldValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qDebug("unhandled player event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::hoverCardEvent(CardItem *card)
|
||||||
|
{
|
||||||
|
emit hoverCard(card->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::showCardMenu(const QPoint &p)
|
||||||
|
{
|
||||||
|
emit sigShowCardMenu(p);
|
||||||
|
}
|
71
cockatrice/src/player.h
Normal file
71
cockatrice/src/player.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef PLAYER_H
|
||||||
|
#define PLAYER_H
|
||||||
|
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QPoint>
|
||||||
|
#include "zonelist.h"
|
||||||
|
#include "counterlist.h"
|
||||||
|
#include "servereventdata.h"
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
class CardDatabase;
|
||||||
|
class QMenu;
|
||||||
|
class QAction;
|
||||||
|
|
||||||
|
class Player : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void moveCard(int cardId, QString startZone, QString targetZone, int x, int y);
|
||||||
|
void hoverCard(QString name);
|
||||||
|
void addZoneView(Player *player, QString zoneName, int number);
|
||||||
|
void sigShowCardMenu(QPoint p);
|
||||||
|
// Log events
|
||||||
|
void logMoveCard(QString playerName, QString cardName, QString startZone, QString targetZone);
|
||||||
|
void logCreateToken(QString playerName, QString cardName);
|
||||||
|
void logSetCardCounters(QString playerName, QString cardName, int value, int oldValue);
|
||||||
|
void logSetTapped(QString playerName, QString cardName, bool tapped);
|
||||||
|
void logSetCounter(QString playerName, QString counterName, int value, int oldValue);
|
||||||
|
private slots:
|
||||||
|
void actMoveHandToTopLibrary();
|
||||||
|
void actMoveHandToBottomLibrary();
|
||||||
|
|
||||||
|
void actViewLibrary();
|
||||||
|
void actViewTopCards();
|
||||||
|
|
||||||
|
void actViewGraveyard();
|
||||||
|
|
||||||
|
void actViewRfg();
|
||||||
|
|
||||||
|
void actViewSideboard();
|
||||||
|
private:
|
||||||
|
QMenu *playerMenu;
|
||||||
|
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary,
|
||||||
|
*aViewLibrary, *aViewTopCards, *aViewGraveyard, *aViewRfg, *aViewSideboard;
|
||||||
|
|
||||||
|
int defaultNumberTopCards;
|
||||||
|
QString name;
|
||||||
|
int id;
|
||||||
|
QPointF base;
|
||||||
|
bool local;
|
||||||
|
ZoneList zones;
|
||||||
|
CounterList counters;
|
||||||
|
CardDatabase *db;
|
||||||
|
public:
|
||||||
|
Client *client;
|
||||||
|
void addZone(PlayerZone *z);
|
||||||
|
void addCounter(Counter *c);
|
||||||
|
Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client);
|
||||||
|
~Player();
|
||||||
|
QMenu *getPlayerMenu() const { return playerMenu; }
|
||||||
|
int getId() const { return id; }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
bool getLocal() const { return local; }
|
||||||
|
const ZoneList *const getZones() const { return &zones; }
|
||||||
|
const CounterList *const getCounters() const { return &counters; }
|
||||||
|
void gameEvent(ServerEventData *event);
|
||||||
|
void hoverCardEvent(CardItem *card);
|
||||||
|
CardDatabase *getDb() const { return db; }
|
||||||
|
void showCardMenu(const QPoint &p);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
11
cockatrice/src/playerlist.cpp
Normal file
11
cockatrice/src/playerlist.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "playerlist.h"
|
||||||
|
|
||||||
|
Player *PlayerList::findPlayer(int id) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
Player *temp = at(i);
|
||||||
|
if (temp->getId() == id)
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
12
cockatrice/src/playerlist.h
Normal file
12
cockatrice/src/playerlist.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef PLAYERLIST_H
|
||||||
|
#define PLAYERLIST_H
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class PlayerList : public QList<Player *> {
|
||||||
|
public:
|
||||||
|
Player *findPlayer(int id) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
98
cockatrice/src/playerzone.cpp
Normal file
98
cockatrice/src/playerzone.cpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
|
PlayerZone::PlayerZone(Player *_p, const QString &_name, QGraphicsItem *parent, bool isView)
|
||||||
|
: QGraphicsItem(parent), player(_p), name(_name), cards(NULL), menu(NULL), hasCardAttr(false)
|
||||||
|
{
|
||||||
|
if (!isView)
|
||||||
|
player->addZone(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerZone::~PlayerZone()
|
||||||
|
{
|
||||||
|
qDebug(QString("PlayerZone destructor: %1").arg(name).toLatin1());
|
||||||
|
while (!views.empty())
|
||||||
|
delete views.at(0);
|
||||||
|
|
||||||
|
clearContents();
|
||||||
|
delete cards;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::clearContents()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards->size(); i++)
|
||||||
|
delete cards->at(i);
|
||||||
|
cards->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::RightButton) {
|
||||||
|
if (menu) {
|
||||||
|
menu->exec(event->screenPos());
|
||||||
|
event->accept();
|
||||||
|
} else
|
||||||
|
event->ignore();
|
||||||
|
} else
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
CardItem *PlayerZone::getCard(int cardId, const QString &cardName)
|
||||||
|
{
|
||||||
|
CardItem *c = cards->findCard(cardId, false);
|
||||||
|
// If the card's id is -1, this zone is invisible,
|
||||||
|
// so we need to give the card an id and a name as it comes out.
|
||||||
|
// It can be assumed that in an invisible zone, all cards are equal.
|
||||||
|
if ((c->getId() == -1) || (c->getName().isEmpty())) {
|
||||||
|
c->setId(cardId);
|
||||||
|
c->setName(cardName);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardItem *PlayerZone::takeCard(int position, int cardId, const QString &cardName)
|
||||||
|
{
|
||||||
|
CardItem *c = cards->takeAt(position);
|
||||||
|
for (int i = 0; i < views.size(); i++)
|
||||||
|
views[i]->removeCard(position);
|
||||||
|
|
||||||
|
if (c->getId() == -1) {
|
||||||
|
c->setId(cardId);
|
||||||
|
c->setName(cardName);
|
||||||
|
}
|
||||||
|
reorganizeCards();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::setCardAttr(int cardId, const QString &aname, const QString &avalue)
|
||||||
|
{
|
||||||
|
if (hasCardAttr)
|
||||||
|
player->client->setCardAttr(name, cardId, aname, avalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::hoverCardEvent(CardItem *card)
|
||||||
|
{
|
||||||
|
player->hoverCardEvent(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::addView(ZoneViewZone *view)
|
||||||
|
{
|
||||||
|
views.append(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::removeView(ZoneViewZone *view)
|
||||||
|
{
|
||||||
|
views.removeAt(views.indexOf(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::moveAllToZone(const QString &targetZone, int targetX)
|
||||||
|
{
|
||||||
|
// Cards need to be moved in reverse order so that the other
|
||||||
|
// cards' list index doesn't change
|
||||||
|
for (int i = cards->size() - 1; i >= 0; i--)
|
||||||
|
player->client->moveCard(cards->at(i)->getId(), getName(), targetZone, targetX);
|
||||||
|
}
|
47
cockatrice/src/playerzone.h
Normal file
47
cockatrice/src/playerzone.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef PLAYERZONE_H
|
||||||
|
#define PLAYERZONE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include "cardlist.h"
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
class ZoneViewZone;
|
||||||
|
class QMenu;
|
||||||
|
|
||||||
|
class PlayerZone : public QGraphicsItem {
|
||||||
|
protected:
|
||||||
|
Player *player;
|
||||||
|
QString name;
|
||||||
|
CardList *cards;
|
||||||
|
QList<ZoneViewZone *> views;
|
||||||
|
QMenu *menu;
|
||||||
|
bool hasCardAttr;
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
public:
|
||||||
|
enum { Type = typeZone };
|
||||||
|
int type() const { return Type; }
|
||||||
|
virtual void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint) = 0;
|
||||||
|
PlayerZone(Player *_player, const QString &_name, QGraphicsItem *parent = 0, bool isView = false);
|
||||||
|
~PlayerZone();
|
||||||
|
void clearContents();
|
||||||
|
bool getHasCardAttr() const { return hasCardAttr; }
|
||||||
|
QMenu *getMenu() const { return menu; }
|
||||||
|
void setMenu(QMenu *_menu) { menu = _menu; }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
Player *getPlayer() const { return player; }
|
||||||
|
bool contentsKnown() const { return cards->getContentsKnown(); }
|
||||||
|
CardList *const getCards() const { return cards; }
|
||||||
|
virtual void addCard(CardItem *card, bool reorganize = true, int x = -1, int y = -1) = 0;
|
||||||
|
// getCard() finds a card by id.
|
||||||
|
CardItem *getCard(int cardId, const QString &cardName);
|
||||||
|
// takeCard() finds a card by position and removes it from the zone and from all of its views.
|
||||||
|
CardItem *takeCard(int position, int cardId, const QString &cardName);
|
||||||
|
void setCardAttr(int cardId, const QString &aname, const QString &avalue);
|
||||||
|
void hoverCardEvent(CardItem *card);
|
||||||
|
void addView(ZoneViewZone *view);
|
||||||
|
void removeView(ZoneViewZone *view);
|
||||||
|
virtual void reorganizeCards() = 0;
|
||||||
|
void moveAllToZone(const QString &targetZone, int targetX);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
53
cockatrice/src/rfgzone.cpp
Normal file
53
cockatrice/src/rfgzone.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "rfgzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
|
RfgZone::RfgZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "rfg")
|
||||||
|
{
|
||||||
|
cards = new CardList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF RfgZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfgZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->save();
|
||||||
|
painter->fillRect(boundingRect(), QColor("white"));
|
||||||
|
painter->setFont(QFont("Times", 20, QFont::Bold));
|
||||||
|
painter->setPen(QPen(QColor("black")));
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString::number(cards->size()));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfgZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < views.size(); i++)
|
||||||
|
views[i]->addCard(new CardItem(player->getDb(), card->getName(), card->getId()), reorganize, x, y);
|
||||||
|
|
||||||
|
cards->insert(x, card);
|
||||||
|
card->setPos(0, 0);
|
||||||
|
card->setVisible(false);
|
||||||
|
card->resetState();
|
||||||
|
card->setParentItem(this);
|
||||||
|
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfgZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfgZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
17
cockatrice/src/rfgzone.h
Normal file
17
cockatrice/src/rfgzone.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef RFGZONE_H
|
||||||
|
#define RFGZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
class RfgZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
RfgZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = 0, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
49
cockatrice/src/servereventdata.cpp
Normal file
49
cockatrice/src/servereventdata.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include "servereventdata.h"
|
||||||
|
|
||||||
|
// Message structure for server events:
|
||||||
|
// {"private","public"}|PlayerId|PlayerName|EventType|EventData
|
||||||
|
|
||||||
|
const int event_count = 19;
|
||||||
|
const event_string event_strings[event_count] = {
|
||||||
|
{eventPlayerId, "player_id"},
|
||||||
|
{eventSay, "say"},
|
||||||
|
{eventName, "name"},
|
||||||
|
{eventJoin, "join"},
|
||||||
|
{eventLeave, "leave"},
|
||||||
|
{eventReadyStart, "ready_start"},
|
||||||
|
{eventSetupZones, "setup_zones"},
|
||||||
|
{eventGameStart, "game_start"},
|
||||||
|
{eventShuffle, "shuffle"},
|
||||||
|
{eventRollDice, "roll_dice"},
|
||||||
|
{eventDraw, "draw"},
|
||||||
|
{eventMoveCard, "move_card"},
|
||||||
|
{eventCreateToken, "create_token"},
|
||||||
|
{eventSetCardAttr, "set_card_attr"},
|
||||||
|
{eventSetCounter, "set_counter"},
|
||||||
|
{eventDelCounter, "del_counter"},
|
||||||
|
{eventSetActivePlayer, "set_active_player"},
|
||||||
|
{eventSetActivePhase, "set_active_phase"},
|
||||||
|
{eventDumpZone, "dump_zone"}
|
||||||
|
};
|
||||||
|
|
||||||
|
ServerEventData::ServerEventData(const QString &line)
|
||||||
|
{
|
||||||
|
QStringList values = line.split("|");
|
||||||
|
|
||||||
|
IsPublic = !values.takeFirst().compare("public");
|
||||||
|
PlayerId = values.takeFirst().toInt();
|
||||||
|
PlayerName = values.takeFirst();
|
||||||
|
|
||||||
|
QString type = values.takeFirst();
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < event_count; i++)
|
||||||
|
if (!type.compare(event_strings[i].str)) {
|
||||||
|
EventType = event_strings[i].type;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
EventType = eventInvalid;
|
||||||
|
|
||||||
|
EventData = values;
|
||||||
|
}
|
54
cockatrice/src/servereventdata.h
Normal file
54
cockatrice/src/servereventdata.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef SERVEREVENTDATA_H
|
||||||
|
#define SERVEREVENTDATA_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
|
||||||
|
enum ServerEventType {
|
||||||
|
eventInvalid,
|
||||||
|
eventPlayerId,
|
||||||
|
eventSay,
|
||||||
|
eventName,
|
||||||
|
eventJoin,
|
||||||
|
eventLeave,
|
||||||
|
eventReadyStart,
|
||||||
|
eventSetupZones,
|
||||||
|
eventGameStart,
|
||||||
|
eventShuffle,
|
||||||
|
eventRollDice,
|
||||||
|
eventDraw,
|
||||||
|
eventMoveCard,
|
||||||
|
eventCreateToken,
|
||||||
|
eventSetCardAttr,
|
||||||
|
eventSetCounter,
|
||||||
|
eventDelCounter,
|
||||||
|
eventSetActivePlayer,
|
||||||
|
eventSetActivePhase,
|
||||||
|
eventDumpZone
|
||||||
|
};
|
||||||
|
|
||||||
|
struct event_string {
|
||||||
|
ServerEventType type;
|
||||||
|
char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const int event_count;
|
||||||
|
extern const event_string event_strings[];
|
||||||
|
|
||||||
|
class ServerEventData {
|
||||||
|
private:
|
||||||
|
bool IsPublic;
|
||||||
|
int PlayerId;
|
||||||
|
QString PlayerName;
|
||||||
|
ServerEventType EventType;
|
||||||
|
QStringList EventData;
|
||||||
|
public:
|
||||||
|
ServerEventData(const QString &line);
|
||||||
|
bool getPublic() { return IsPublic; }
|
||||||
|
int getPlayerId() { return PlayerId; }
|
||||||
|
QString getPlayerName() { return PlayerName; }
|
||||||
|
ServerEventType getEventType() { return EventType; }
|
||||||
|
QStringList getEventData() { return EventData; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
21
cockatrice/src/servergame.h
Normal file
21
cockatrice/src/servergame.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef SERVERGAME_H
|
||||||
|
#define SERVERGAME_H
|
||||||
|
|
||||||
|
class ServerGame {
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
bool hasPassword;
|
||||||
|
unsigned char playerCount;
|
||||||
|
unsigned char maxPlayers;
|
||||||
|
public:
|
||||||
|
ServerGame(const QString &_name, const QString &_description, bool _hasPassword, unsigned char _playerCount, unsigned char _maxPlayers)
|
||||||
|
: name(_name), description(_description), hasPassword(_hasPassword), playerCount(_playerCount), maxPlayers(_maxPlayers) { }
|
||||||
|
QString getName() { return name; }
|
||||||
|
QString getDescription() { return description; }
|
||||||
|
bool getHasPassword() { return hasPassword; }
|
||||||
|
unsigned char getPlayerCount() { return playerCount; }
|
||||||
|
unsigned char getMaxPlayers() { return maxPlayers; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
17
cockatrice/src/serverplayer.h
Normal file
17
cockatrice/src/serverplayer.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef SERVERPLAYER_H
|
||||||
|
#define SERVERPLAYER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class ServerPlayer {
|
||||||
|
private:
|
||||||
|
int PlayerId;
|
||||||
|
QString name;
|
||||||
|
public:
|
||||||
|
ServerPlayer(int _PlayerId, const QString &_name)
|
||||||
|
: PlayerId(_PlayerId), name(_name) { }
|
||||||
|
int getPlayerId() { return PlayerId; }
|
||||||
|
QString getName() { return name; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
22
cockatrice/src/serverresponse.h
Normal file
22
cockatrice/src/serverresponse.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef SERVERRESPONSE_H
|
||||||
|
#define SERVERRESPONSE_H
|
||||||
|
|
||||||
|
enum ServerErrorMessage {
|
||||||
|
msgNone,
|
||||||
|
msgSyntaxError
|
||||||
|
};
|
||||||
|
|
||||||
|
class ServerResponse {
|
||||||
|
private:
|
||||||
|
int msgId;
|
||||||
|
bool ok;
|
||||||
|
ServerErrorMessage message;
|
||||||
|
public:
|
||||||
|
ServerResponse(int _msgId, bool _ok, ServerErrorMessage _message)
|
||||||
|
: msgId(_msgId), ok(_ok), message(_message) { }
|
||||||
|
int getMsgId() { return msgId; }
|
||||||
|
bool getOk() { return ok; }
|
||||||
|
ServerErrorMessage getMessage() { return message; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
21
cockatrice/src/serverzone.h
Normal file
21
cockatrice/src/serverzone.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef SERVERZONE_H
|
||||||
|
#define SERVERZONE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class ServerZone {
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
bool isPublic;
|
||||||
|
bool hasCoords;
|
||||||
|
int cardCount;
|
||||||
|
public:
|
||||||
|
ServerZone(const QString &_name, bool _isPublic, bool _hasCoords, int _cardCount)
|
||||||
|
: name(_name), isPublic(_isPublic), hasCoords(_hasCoords), cardCount(_cardCount) { }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
bool getPublic() const { return isPublic; }
|
||||||
|
bool getHasCoords() const { return hasCoords; }
|
||||||
|
int getCardCount() const { return cardCount; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
28
cockatrice/src/serverzonecard.h
Normal file
28
cockatrice/src/serverzonecard.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef SERVERZONECARD_H
|
||||||
|
#define SERVERZONECARD_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class ServerZoneCard {
|
||||||
|
private:
|
||||||
|
int id;
|
||||||
|
QString name;
|
||||||
|
int x, y;
|
||||||
|
int counters;
|
||||||
|
bool tapped;
|
||||||
|
bool attacking;
|
||||||
|
QString annotation;
|
||||||
|
public:
|
||||||
|
ServerZoneCard(int _id, const QString &_name, int _x, int _y, int _counters, bool _attacking, const QString &_annotation)
|
||||||
|
: id(_id), name(_name), x(_x), y(_y), counters(_counters), attacking(_attacking), annotation(_annotation) { }
|
||||||
|
int getId() const { return id; }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
int getX() const { return x; }
|
||||||
|
int getY() const { return y; }
|
||||||
|
int getCounters() const { return counters; }
|
||||||
|
bool getTapped() const { return tapped; }
|
||||||
|
bool getAttacking() const { return attacking; }
|
||||||
|
QString getAnnotation() const { return annotation; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
54
cockatrice/src/sideboardzone.cpp
Normal file
54
cockatrice/src/sideboardzone.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "sideboardzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
|
SideboardZone::SideboardZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "sb")
|
||||||
|
{
|
||||||
|
cards = new CardList(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF SideboardZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, 50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideboardZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->save();
|
||||||
|
painter->fillRect(boundingRect(), QColor("blue"));
|
||||||
|
painter->setFont(QFont("Times", 20, QFont::Bold));
|
||||||
|
painter->setPen(QPen(QColor("black")));
|
||||||
|
painter->drawText(boundingRect(), Qt::AlignCenter, QString::number(cards->size()));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideboardZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < views.size(); i++)
|
||||||
|
views[i]->addCard(new CardItem(player->getDb(), card->getName(), card->getId()), reorganize, x, y);
|
||||||
|
|
||||||
|
cards->insert(x, card);
|
||||||
|
card->setPos(0, 0);
|
||||||
|
card->setVisible(false);
|
||||||
|
card->resetState();
|
||||||
|
card->setParentItem(this);
|
||||||
|
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideboardZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideboardZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
update(boundingRect());
|
||||||
|
}
|
||||||
|
|
17
cockatrice/src/sideboardzone.h
Normal file
17
cockatrice/src/sideboardzone.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef SIDEBOARDZONE_H
|
||||||
|
#define SIDEBOARDZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
class SideboardZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
SideboardZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = 0, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
56
cockatrice/src/tablezone.cpp
Normal file
56
cockatrice/src/tablezone.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "tablezone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
TableZone::TableZone(Player *_p)
|
||||||
|
: PlayerZone(_p, "table"), width(700), height(500)
|
||||||
|
{
|
||||||
|
cards = new CardList(true);
|
||||||
|
hasCardAttr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF TableZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
painter->fillRect(boundingRect(), QColor("blue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
Q_UNUSED(reorganize);
|
||||||
|
cards->append(card);
|
||||||
|
if ((x != -1) && (y != -1)) {
|
||||||
|
if (!player->getLocal())
|
||||||
|
y = height - CARD_HEIGHT - y;
|
||||||
|
card->setPos(x, y);
|
||||||
|
}
|
||||||
|
card->setZValue((y + CARD_HEIGHT) * width + x + 1000);
|
||||||
|
card->setParentItem(this);
|
||||||
|
card->setVisible(true);
|
||||||
|
card->update(card->boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), dropPoint.x(), dropPoint.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableZone::toggleTapped()
|
||||||
|
{
|
||||||
|
QListIterator<QGraphicsItem *> i(scene()->selectedItems());
|
||||||
|
while (i.hasNext()) {
|
||||||
|
CardItem *temp = (CardItem *) i.next();
|
||||||
|
setCardAttr(temp->getId(), "tapped", temp->getTapped() ? "0" : "1");
|
||||||
|
}
|
||||||
|
}
|
22
cockatrice/src/tablezone.h
Normal file
22
cockatrice/src/tablezone.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef TABLEZONE_H
|
||||||
|
#define TABLEZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
const int GRID_WIDTH = 30;
|
||||||
|
const int GRID_HEIGHT = 30;
|
||||||
|
|
||||||
|
class TableZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
int width, height;
|
||||||
|
public:
|
||||||
|
TableZone(Player *_p);
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = -1, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
void toggleTapped();
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
258
cockatrice/src/window.cpp
Normal file
258
cockatrice/src/window.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@gmx.net *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtOpenGL>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
#include "dlg_connect.h"
|
||||||
|
#include "dlg_games.h"
|
||||||
|
#include "cardinfowidget.h"
|
||||||
|
#include "messagelogwidget.h"
|
||||||
|
|
||||||
|
#include "gameview.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
#include "zoneviewwidget.h"
|
||||||
|
#include "zoneviewlayout.h"
|
||||||
|
|
||||||
|
void MainWindow::hoverCard(QString name)
|
||||||
|
{
|
||||||
|
cardInfo->setCard(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::playerAdded(Player *player)
|
||||||
|
{
|
||||||
|
menuBar()->addMenu(player->getPlayerMenu());
|
||||||
|
connect(player, SIGNAL(addZoneView(Player *, QString, int)), zoneLayout, SLOT(addItem(Player *, QString, int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::playerRemoved(Player *player)
|
||||||
|
{
|
||||||
|
menuBar()->removeAction(player->getPlayerMenu()->menuAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::statusChanged(ProtocolStatus _status)
|
||||||
|
{
|
||||||
|
switch (_status) {
|
||||||
|
case StatusConnecting:
|
||||||
|
emit logConnecting(client->peerName());
|
||||||
|
break;
|
||||||
|
case StatusDisconnected:
|
||||||
|
if (game) {
|
||||||
|
delete game;
|
||||||
|
game = 0;
|
||||||
|
}
|
||||||
|
aDisconnect->setEnabled(false);
|
||||||
|
aGames->setEnabled(false);
|
||||||
|
aRestartGame->setEnabled(false);
|
||||||
|
aLeaveGame->setEnabled(false);
|
||||||
|
emit logDisconnected();
|
||||||
|
break;
|
||||||
|
case StatusConnected:
|
||||||
|
aDisconnect->setEnabled(true);
|
||||||
|
aGames->setEnabled(true);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
void MainWindow::actConnect()
|
||||||
|
{
|
||||||
|
DlgConnect dlg(this);
|
||||||
|
if (dlg.exec())
|
||||||
|
client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::actDisconnect()
|
||||||
|
{
|
||||||
|
client->disconnectFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::actGames()
|
||||||
|
{
|
||||||
|
DlgGames dlg(client, this);
|
||||||
|
dlg.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::actLeaveGame()
|
||||||
|
{
|
||||||
|
client->leaveGame();
|
||||||
|
delete game;
|
||||||
|
game = 0;
|
||||||
|
aRestartGame->setEnabled(false);
|
||||||
|
aLeaveGame->setEnabled(false);
|
||||||
|
aGames->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::actExit()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateSceneSize()
|
||||||
|
{
|
||||||
|
QRectF sr = scene->sceneRect();
|
||||||
|
QSizeF zoneSize = zoneLayout->size();
|
||||||
|
qDebug(QString("updateSceneSize: width=%1").arg(850 + zoneSize.width()).toLatin1());
|
||||||
|
scene->setSceneRect(sr.x(), sr.y(), 850 + zoneSize.width(), sr.height());
|
||||||
|
view->scaleToScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Knöpfe
|
||||||
|
|
||||||
|
void MainWindow::buttonSay()
|
||||||
|
{
|
||||||
|
client->say(sayEdit->text());
|
||||||
|
sayEdit->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::playerIdReceived(int id, QString name)
|
||||||
|
{
|
||||||
|
game = new Game(db, client, scene, actionsMenu, cardMenu, id, name);
|
||||||
|
connect(game, SIGNAL(submitDecklist()), this, SLOT(decklistDialog()));
|
||||||
|
connect(game, SIGNAL(hoverCard(QString)), this, SLOT(hoverCard(QString)));
|
||||||
|
connect(game, SIGNAL(playerAdded(Player *)), this, SLOT(playerAdded(Player *)));
|
||||||
|
connect(game, SIGNAL(playerRemoved(Player *)), this, SLOT(playerRemoved(Player *)));
|
||||||
|
connect(aRestartGame, SIGNAL(triggered()), game, SLOT(restartGameDialog()));
|
||||||
|
playerAdded(game->getLocalPlayer());
|
||||||
|
|
||||||
|
messageLog->connectToGame(game);
|
||||||
|
aGames->setEnabled(false);
|
||||||
|
aRestartGame->setEnabled(true);
|
||||||
|
aLeaveGame->setEnabled(true);
|
||||||
|
|
||||||
|
client->listPlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::serverTimeout()
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Server timeout"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::createActions()
|
||||||
|
{
|
||||||
|
aConnect = new QAction(tr("&Connect..."), this);
|
||||||
|
connect(aConnect, SIGNAL(triggered()), this, SLOT(actConnect()));
|
||||||
|
aDisconnect = new QAction(tr("&Disconnect"), this);
|
||||||
|
aDisconnect->setEnabled(false);
|
||||||
|
connect(aDisconnect, SIGNAL(triggered()), this, SLOT(actDisconnect()));
|
||||||
|
aGames = new QAction(tr("&Games..."), this);
|
||||||
|
aGames->setEnabled(false);
|
||||||
|
connect(aGames, SIGNAL(triggered()), this, SLOT(actGames()));
|
||||||
|
aRestartGame = new QAction(tr("&Restart game..."), this);
|
||||||
|
aRestartGame->setShortcut(tr("F2"));
|
||||||
|
aRestartGame->setEnabled(false);
|
||||||
|
aLeaveGame = new QAction(tr("&Leave game"), this);
|
||||||
|
aLeaveGame->setEnabled(false);
|
||||||
|
connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
|
||||||
|
aExit = new QAction(tr("&Exit"), this);
|
||||||
|
connect(aExit, SIGNAL(triggered()), this, SLOT(actExit()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::createMenus()
|
||||||
|
{
|
||||||
|
gameMenu = menuBar()->addMenu(tr("&Game"));
|
||||||
|
gameMenu->addAction(aConnect);
|
||||||
|
gameMenu->addAction(aDisconnect);
|
||||||
|
gameMenu->addSeparator();
|
||||||
|
gameMenu->addAction(aGames);
|
||||||
|
gameMenu->addAction(aRestartGame);
|
||||||
|
gameMenu->addAction(aLeaveGame);
|
||||||
|
gameMenu->addSeparator();
|
||||||
|
gameMenu->addAction(aExit);
|
||||||
|
|
||||||
|
actionsMenu = menuBar()->addMenu(tr("&Actions"));
|
||||||
|
|
||||||
|
cardMenu = menuBar()->addMenu(tr("&Card"));
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
|
: QMainWindow(parent), game(NULL)
|
||||||
|
{
|
||||||
|
// setWindowState(windowState() | Qt::WindowFullScreen);
|
||||||
|
|
||||||
|
QPixmapCache::setCacheLimit(200000);
|
||||||
|
createActions();
|
||||||
|
createMenus();
|
||||||
|
|
||||||
|
db = new CardDatabase;
|
||||||
|
int cardCount = db->loadFromFile("../cards.dat");
|
||||||
|
qDebug(QString("%1 cards loaded").arg(cardCount).toLatin1());
|
||||||
|
|
||||||
|
scene = new QGraphicsScene(0, 0, 850, 1000, this);
|
||||||
|
view = new GameView(scene);
|
||||||
|
|
||||||
|
// view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
|
||||||
|
// view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
|
|
||||||
|
zoneLayout = new ZoneViewLayout(db);
|
||||||
|
zoneLayout->setPos(850, 0);
|
||||||
|
scene->addItem(zoneLayout);
|
||||||
|
connect(zoneLayout, SIGNAL(sizeChanged()), this, SLOT(updateSceneSize()));
|
||||||
|
|
||||||
|
cardInfo = new CardInfoWidget(db);
|
||||||
|
messageLog = new MessageLogWidget;
|
||||||
|
sayEdit = new QLineEdit;
|
||||||
|
sayButton = new QPushButton(tr("&Say"));
|
||||||
|
|
||||||
|
QHBoxLayout *hLayout = new QHBoxLayout;
|
||||||
|
hLayout->addWidget(sayEdit);
|
||||||
|
hLayout->addWidget(sayButton);
|
||||||
|
|
||||||
|
QVBoxLayout *verticalLayout = new QVBoxLayout;
|
||||||
|
verticalLayout->addWidget(cardInfo);
|
||||||
|
verticalLayout->addWidget(messageLog);
|
||||||
|
verticalLayout->addLayout(hLayout);
|
||||||
|
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
mainLayout->addWidget(view);
|
||||||
|
mainLayout->setStretchFactor(view, 10);
|
||||||
|
mainLayout->addLayout(verticalLayout);
|
||||||
|
|
||||||
|
QWidget *centralWidget = new QWidget;
|
||||||
|
centralWidget->setLayout(mainLayout);
|
||||||
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
|
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(buttonSay()));
|
||||||
|
connect(sayButton, SIGNAL(clicked()), this, SLOT(buttonSay()));
|
||||||
|
|
||||||
|
client = new Client(this);
|
||||||
|
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));
|
||||||
|
connect(client, SIGNAL(statusChanged(ProtocolStatus)), this, SLOT(statusChanged(ProtocolStatus)));
|
||||||
|
connect(client, SIGNAL(playerIdReceived(int, QString)), this, SLOT(playerIdReceived(int, QString)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(logConnecting(QString)), messageLog, SLOT(logConnecting(QString)));
|
||||||
|
connect(client, SIGNAL(welcomeMsgReceived(const QStringList)), messageLog, SLOT(logConnected(const QStringList)));
|
||||||
|
connect(this, SIGNAL(logDisconnected()), messageLog, SLOT(logDisconnected()));
|
||||||
|
connect(client, SIGNAL(logSocketError(const QString &)), messageLog, SLOT(logSocketError(const QString &)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
delete game;
|
||||||
|
|
||||||
|
// db->importOracle();
|
||||||
|
// db->saveToFile("../cards.dat");
|
||||||
|
delete db;
|
||||||
|
}
|
85
cockatrice/src/window.h
Normal file
85
cockatrice/src/window.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@gmx.net *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef WINDOW_H
|
||||||
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
class QGraphicsScene;
|
||||||
|
class GameView;
|
||||||
|
class Game;
|
||||||
|
class CardDatabase;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class CardInfoWidget;
|
||||||
|
class MessageLogWidget;
|
||||||
|
class QLineEdit;
|
||||||
|
class QPushButton;
|
||||||
|
class ServerZoneCard;
|
||||||
|
class ZoneViewLayout;
|
||||||
|
class ZoneViewWidget;
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
private slots:
|
||||||
|
void hoverCard(QString name);
|
||||||
|
void playerAdded(Player *player);
|
||||||
|
void playerRemoved(Player *player);
|
||||||
|
void statusChanged(ProtocolStatus _status);
|
||||||
|
void playerIdReceived(int id, QString name);
|
||||||
|
void serverTimeout();
|
||||||
|
|
||||||
|
void buttonSay();
|
||||||
|
|
||||||
|
void actConnect();
|
||||||
|
void actDisconnect();
|
||||||
|
void actGames();
|
||||||
|
void actLeaveGame();
|
||||||
|
void actExit();
|
||||||
|
|
||||||
|
void updateSceneSize();
|
||||||
|
signals:
|
||||||
|
void logConnecting(QString hostname);
|
||||||
|
void logDisconnected();
|
||||||
|
private:
|
||||||
|
void createActions();
|
||||||
|
void createMenus();
|
||||||
|
QMenu *gameMenu, *actionsMenu, *cardMenu;
|
||||||
|
QAction *aConnect, *aDisconnect, *aGames, *aRestartGame, *aLeaveGame, *aExit;
|
||||||
|
|
||||||
|
CardInfoWidget *cardInfo;
|
||||||
|
MessageLogWidget *messageLog;
|
||||||
|
QLineEdit *sayEdit;
|
||||||
|
QPushButton *sayButton;
|
||||||
|
|
||||||
|
Client *client;
|
||||||
|
QGraphicsScene *scene;
|
||||||
|
GameView *view;
|
||||||
|
Game *game;
|
||||||
|
CardDatabase *db;
|
||||||
|
ZoneViewLayout *zoneLayout;
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget *parent = 0);
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
18
cockatrice/src/zoneclosebutton.cpp
Normal file
18
cockatrice/src/zoneclosebutton.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "zoneclosebutton.h"
|
||||||
|
|
||||||
|
void ZoneCloseButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
emit triggered();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneCloseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
painter->fillRect(rect(), QColor("red"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZoneCloseButton::ZoneCloseButton(QGraphicsItem *parent)
|
||||||
|
: QGraphicsWidget(parent)
|
||||||
|
{
|
||||||
|
resize(20, 20);
|
||||||
|
}
|
17
cockatrice/src/zoneclosebutton.h
Normal file
17
cockatrice/src/zoneclosebutton.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef ZONECLOSEBUTTON_H
|
||||||
|
#define ZONECLOSEBUTTON_H
|
||||||
|
|
||||||
|
#include <QGraphicsWidget>
|
||||||
|
|
||||||
|
class ZoneCloseButton : public QGraphicsWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void triggered();
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
public:
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
ZoneCloseButton(QGraphicsItem *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
11
cockatrice/src/zonelist.cpp
Normal file
11
cockatrice/src/zonelist.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "zonelist.h"
|
||||||
|
|
||||||
|
PlayerZone *ZoneList::findZone(const QString &name) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
PlayerZone *temp = at(i);
|
||||||
|
if (!temp->getName().compare(name))
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
12
cockatrice/src/zonelist.h
Normal file
12
cockatrice/src/zonelist.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef ZONELIST_H
|
||||||
|
#define ZONELIST_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class ZoneList : public QList<PlayerZone *> {
|
||||||
|
public:
|
||||||
|
PlayerZone *findZone(const QString &name) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
36
cockatrice/src/zoneviewlayout.cpp
Normal file
36
cockatrice/src/zoneviewlayout.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include "zoneviewlayout.h"
|
||||||
|
#include "zoneviewwidget.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
ZoneViewLayout::ZoneViewLayout(CardDatabase *_db, QGraphicsItem *parent)
|
||||||
|
: QGraphicsWidget(parent), db(_db)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewLayout::reorganize()
|
||||||
|
{
|
||||||
|
qDebug(QString("ZoneViewLayout: activate: count=%1").arg(views.size()).toLatin1());
|
||||||
|
resize(views.size() * 150, 1000);
|
||||||
|
for (int i = 0; i < views.size(); i++) {
|
||||||
|
views.at(i)->setPos(i * 150, 0);
|
||||||
|
}
|
||||||
|
emit sizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewLayout::addItem(Player *player, const QString &zoneName, int numberCards)
|
||||||
|
{
|
||||||
|
ZoneViewWidget *item = new ZoneViewWidget(db, player, player->getZones()->findZone(zoneName), numberCards, this);
|
||||||
|
views.append(item);
|
||||||
|
connect(item, SIGNAL(closePressed(ZoneViewWidget *)), this, SLOT(removeItem(ZoneViewWidget *)));
|
||||||
|
reorganize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewLayout::removeItem(ZoneViewWidget *item)
|
||||||
|
{
|
||||||
|
qDebug("ZoneViewLayout::removeItem");
|
||||||
|
views.removeAt(views.indexOf(item));
|
||||||
|
scene()->removeItem(item);
|
||||||
|
delete item;
|
||||||
|
reorganize();
|
||||||
|
}
|
25
cockatrice/src/zoneviewlayout.h
Normal file
25
cockatrice/src/zoneviewlayout.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef ZONEVIEWLAYOUT_H
|
||||||
|
#define ZONEVIEWLAYOUT_H
|
||||||
|
|
||||||
|
#include <QGraphicsWidget>
|
||||||
|
|
||||||
|
class CardDatabase;
|
||||||
|
class ZoneViewWidget;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class ZoneViewLayout : public QGraphicsWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void sizeChanged();
|
||||||
|
private:
|
||||||
|
QList<ZoneViewWidget *> views;
|
||||||
|
CardDatabase *db;
|
||||||
|
public:
|
||||||
|
ZoneViewLayout(CardDatabase *_db, QGraphicsItem *parent = 0);
|
||||||
|
void reorganize();
|
||||||
|
public slots:
|
||||||
|
void addItem(Player *player, const QString &zoneName, int numberCards = 0);
|
||||||
|
void removeItem(ZoneViewWidget *item);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
45
cockatrice/src/zoneviewwidget.cpp
Normal file
45
cockatrice/src/zoneviewwidget.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
#include "zoneviewwidget.h"
|
||||||
|
#include "carditem.h"
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "zoneclosebutton.h"
|
||||||
|
|
||||||
|
ZoneViewWidget::ZoneViewWidget(CardDatabase *_db, Player *_player, PlayerZone *_origZone, int numberCards, QGraphicsItem *parent)
|
||||||
|
: QGraphicsWidget(parent), db(_db), player(_player)
|
||||||
|
{
|
||||||
|
ZoneCloseButton *closeButton = new ZoneCloseButton(this);
|
||||||
|
connect(closeButton, SIGNAL(triggered()), this, SLOT(slotClosePressed()));
|
||||||
|
|
||||||
|
resize(150, 1000);
|
||||||
|
|
||||||
|
zone = new ZoneViewZone(player, _origZone, numberCards, this);
|
||||||
|
zone->setPos(0, 30);
|
||||||
|
if (!zone->initializeCards()) {
|
||||||
|
connect(player->client, SIGNAL(zoneDumpReceived(int, QList<ServerZoneCard *>)), this, SLOT(zoneDumpReceived(int, QList<ServerZoneCard *>)));
|
||||||
|
cmdId = player->client->dumpZone(player->getId(), _origZone->getName(), numberCards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewWidget::zoneDumpReceived(int commandId, QList<ServerZoneCard *> cards)
|
||||||
|
{
|
||||||
|
if (commandId != cmdId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < cards.size(); i++) {
|
||||||
|
ServerZoneCard *temp = cards[i];
|
||||||
|
|
||||||
|
CardItem *card = new CardItem(db, temp->getName(), i, zone);
|
||||||
|
zone->addCard(card, false, i);
|
||||||
|
|
||||||
|
delete temp;
|
||||||
|
}
|
||||||
|
zone->reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewWidget::slotClosePressed()
|
||||||
|
{
|
||||||
|
emit closePressed(this);
|
||||||
|
}
|
31
cockatrice/src/zoneviewwidget.h
Normal file
31
cockatrice/src/zoneviewwidget.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef ZONEVIEWWIDGET_H
|
||||||
|
#define ZONEVIEWWIDGET_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsWidget>
|
||||||
|
#include "serverzonecard.h"
|
||||||
|
|
||||||
|
class PlayerZone;
|
||||||
|
class ZoneViewZone;
|
||||||
|
class Player;
|
||||||
|
class CardDatabase;
|
||||||
|
|
||||||
|
class ZoneViewWidget : public QGraphicsWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
ZoneViewZone *zone;
|
||||||
|
int cmdId;
|
||||||
|
|
||||||
|
CardDatabase *db;
|
||||||
|
Player *player;
|
||||||
|
signals:
|
||||||
|
void closePressed(ZoneViewWidget *zv);
|
||||||
|
private slots:
|
||||||
|
void zoneDumpReceived(int commandId, QList<ServerZoneCard *> cards);
|
||||||
|
void slotClosePressed();
|
||||||
|
public:
|
||||||
|
ZoneViewWidget(CardDatabase *_db, Player *_player, PlayerZone *_origZone, int numberCards = 0, QGraphicsItem *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
104
cockatrice/src/zoneviewzone.cpp
Normal file
104
cockatrice/src/zoneviewzone.cpp
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include "zoneviewzone.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
ZoneViewZone::ZoneViewZone(Player *_p, PlayerZone *_origZone, int _numberCards, QGraphicsItem *parent)
|
||||||
|
: PlayerZone(_p, _origZone->getName(), parent, true), numberCards(_numberCards), origZone(_origZone)
|
||||||
|
{
|
||||||
|
cards = new CardList(true);
|
||||||
|
origZone->addView(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZoneViewZone::~ZoneViewZone()
|
||||||
|
{
|
||||||
|
qDebug("ZoneViewZone destructor");
|
||||||
|
origZone->removeView(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF ZoneViewZone::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(0, 0, CARD_WIDTH * 1.75, scene()->sceneRect().height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(painter);
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZoneViewZone::initializeCards()
|
||||||
|
{
|
||||||
|
if (!origZone->contentsKnown())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CardList *const c = origZone->getCards();
|
||||||
|
int number = numberCards == 0 ? c->size() : (numberCards < c->size() ? numberCards : c->size());
|
||||||
|
for (int i = 0; i < number; i++) {
|
||||||
|
CardItem *card = c->at(i);
|
||||||
|
addCard(new CardItem(player->getDb(), card->getName(), card->getId(), this), false, i);
|
||||||
|
}
|
||||||
|
reorganizeCards();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because of boundingRect(), this function must not be called before the zone was added to a scene.
|
||||||
|
void ZoneViewZone::reorganizeCards()
|
||||||
|
{
|
||||||
|
qDebug("reorganizeCards");
|
||||||
|
|
||||||
|
if (cards->isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int cardCount = cards->size();
|
||||||
|
qreal totalWidth = boundingRect().width();
|
||||||
|
qreal totalHeight = boundingRect().height();
|
||||||
|
qreal cardWidth = cards->at(0)->boundingRect().width();
|
||||||
|
qreal cardHeight = cards->at(0)->boundingRect().height();
|
||||||
|
qreal x1 = 0;
|
||||||
|
qreal x2 = (totalWidth - cardWidth);
|
||||||
|
|
||||||
|
for (int i = 0; i < cardCount; i++) {
|
||||||
|
CardItem *c = cards->at(i);
|
||||||
|
qreal x = i % 2 ? x2 : x1;
|
||||||
|
// If the total height of the cards is smaller than the available height,
|
||||||
|
// the cards do not need to overlap and are displayed in the center of the area.
|
||||||
|
if (cardHeight * cardCount > totalHeight)
|
||||||
|
c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1));
|
||||||
|
else
|
||||||
|
c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2);
|
||||||
|
if (!origZone->contentsKnown())
|
||||||
|
c->setId(i);
|
||||||
|
c->setZValue(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
|
{
|
||||||
|
Q_UNUSED(y);
|
||||||
|
qDebug(QString("ZoneViewZone: inserting '%1' at x=%2").arg(card->getName()).arg(x).toLatin1());
|
||||||
|
cards->insert(x, card);
|
||||||
|
card->setParentItem(this);
|
||||||
|
card->update(card->boundingRect());
|
||||||
|
if (reorganize)
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewZone::handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint)
|
||||||
|
{
|
||||||
|
Q_UNUSED(dropPoint);
|
||||||
|
qDebug(QString("handleDropEvent id=%1").arg(cardId).toLatin1());
|
||||||
|
player->client->moveCard(cardId, startZone->getName(), getName(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneViewZone::removeCard(int position)
|
||||||
|
{
|
||||||
|
if (position >= cards->size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CardItem *card = cards->at(position);
|
||||||
|
cards->removeAt(position);
|
||||||
|
delete card;
|
||||||
|
reorganizeCards();
|
||||||
|
}
|
27
cockatrice/src/zoneviewzone.h
Normal file
27
cockatrice/src/zoneviewzone.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef ZONEVIEWERZONE_H
|
||||||
|
#define ZONEVIEWERZONE_H
|
||||||
|
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include "serverzonecard.h"
|
||||||
|
|
||||||
|
class ZoneViewWidget;
|
||||||
|
|
||||||
|
class ZoneViewZone : public PlayerZone {
|
||||||
|
private:
|
||||||
|
int numberCards;
|
||||||
|
void handleDropEvent(int cardId, PlayerZone *startZone, const QPoint &dropPoint);
|
||||||
|
PlayerZone *origZone;
|
||||||
|
signals:
|
||||||
|
void removeZoneViewWidget(ZoneViewWidget *zv);
|
||||||
|
public:
|
||||||
|
ZoneViewZone(Player *_p, PlayerZone *_origZone, int _numberCards = 0, QGraphicsItem *parent = 0);
|
||||||
|
~ZoneViewZone();
|
||||||
|
QRectF boundingRect() const;
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
|
void addCard(CardItem *card, bool reorganize = true, int x = 0, int y = -1);
|
||||||
|
void reorganizeCards();
|
||||||
|
bool initializeCards();
|
||||||
|
void removeCard(int position);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
311
servatrice/Doxyfile
Executable file
311
servatrice/Doxyfile
Executable file
|
@ -0,0 +1,311 @@
|
||||||
|
# Doxyfile 1.5.5-KDevelop
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Project related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = servertest
|
||||||
|
PROJECT_NUMBER = 0.1
|
||||||
|
OUTPUT_DIRECTORY =
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF = "The $name class" \
|
||||||
|
"The $name widget" \
|
||||||
|
"The $name file" \
|
||||||
|
is \
|
||||||
|
provides \
|
||||||
|
specifies \
|
||||||
|
contains \
|
||||||
|
represents \
|
||||||
|
a \
|
||||||
|
an \
|
||||||
|
the
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = YES
|
||||||
|
STRIP_FROM_PATH = /home/brukie/
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
DETAILS_AT_TOP = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 8
|
||||||
|
ALIASES =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Build related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
EXTRACT_ALL = NO
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_DIRECTORIES = NO
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to warning and progress messages
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
QUIET = NO
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the input files
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
INPUT = /home/brukie/servertest
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
FILE_PATTERNS = *.c \
|
||||||
|
*.cc \
|
||||||
|
*.cxx \
|
||||||
|
*.cpp \
|
||||||
|
*.c++ \
|
||||||
|
*.d \
|
||||||
|
*.java \
|
||||||
|
*.ii \
|
||||||
|
*.ixx \
|
||||||
|
*.ipp \
|
||||||
|
*.i++ \
|
||||||
|
*.inl \
|
||||||
|
*.h \
|
||||||
|
*.hh \
|
||||||
|
*.hxx \
|
||||||
|
*.hpp \
|
||||||
|
*.h++ \
|
||||||
|
*.idl \
|
||||||
|
*.odl \
|
||||||
|
*.cs \
|
||||||
|
*.php \
|
||||||
|
*.php3 \
|
||||||
|
*.inc \
|
||||||
|
*.m \
|
||||||
|
*.mm \
|
||||||
|
*.dox \
|
||||||
|
*.py \
|
||||||
|
*.f90 \
|
||||||
|
*.f \
|
||||||
|
*.vhd \
|
||||||
|
*.vhdl \
|
||||||
|
*.C \
|
||||||
|
*.CC \
|
||||||
|
*.C++ \
|
||||||
|
*.II \
|
||||||
|
*.I++ \
|
||||||
|
*.H \
|
||||||
|
*.HH \
|
||||||
|
*.H++ \
|
||||||
|
*.CS \
|
||||||
|
*.PHP \
|
||||||
|
*.PHP3 \
|
||||||
|
*.M \
|
||||||
|
*.MM \
|
||||||
|
*.PY \
|
||||||
|
*.F90 \
|
||||||
|
*.F \
|
||||||
|
*.VHD \
|
||||||
|
*.VHDL \
|
||||||
|
*.C \
|
||||||
|
*.H \
|
||||||
|
*.tlh \
|
||||||
|
*.diff \
|
||||||
|
*.patch \
|
||||||
|
*.moc \
|
||||||
|
*.xpm \
|
||||||
|
*.dox
|
||||||
|
RECURSIVE = yes
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS = *
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to source browsing
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SOURCE_BROWSER = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = NO
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the alphabetical class index
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
COLS_IN_ALPHA_INDEX = 5
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the HTML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_ALIGN_MEMBERS = YES
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
GENERATE_TREEVIEW = NONE
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the LaTeX output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_LATEX = YES
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4wide
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
PDF_HYPERLINKS = YES
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the RTF output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the man page output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_LINKS = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the XML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_XML = yes
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_SCHEMA =
|
||||||
|
XML_DTD =
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options for the AutoGen Definitions output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the Perl module output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the preprocessor
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::additions related to external references
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE = servertest.tag
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
PERL_PATH = /usr/bin/perl
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the dot tool
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
CLASS_DIAGRAMS = YES
|
||||||
|
MSCGEN_PATH =
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
DOT_FONTNAME = FreeSans
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 1000
|
||||||
|
DOT_TRANSPARENT = YES
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::additions related to the search engine
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SEARCHENGINE = NO
|
340
servatrice/copying
Executable file
340
servatrice/copying
Executable file
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 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.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
32
servatrice/servertest.pro
Executable file
32
servatrice/servertest.pro
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
######################################################################
|
||||||
|
# Automatically generated by qmake (2.01a) Fr Sep 5 18:02:29 2008
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
TARGET =
|
||||||
|
DEPENDPATH += . src
|
||||||
|
INCLUDEPATH += . src
|
||||||
|
|
||||||
|
CONFIG += qt thread
|
||||||
|
QT += network
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
# Input
|
||||||
|
HEADERS += src/testserver.h src/testservergame.h src/testserversocket.h \
|
||||||
|
src/playerzone.h \
|
||||||
|
src/testcard.h \
|
||||||
|
src/version.h \
|
||||||
|
src/counter.h \
|
||||||
|
src/testrandom.h \
|
||||||
|
src/testservergamethread.h \
|
||||||
|
src/returnmessage.h
|
||||||
|
SOURCES += src/main.cpp \
|
||||||
|
src/testserver.cpp \
|
||||||
|
src/testservergame.cpp \
|
||||||
|
src/testserversocket.cpp \
|
||||||
|
src/playerzone.cpp \
|
||||||
|
src/testcard.cpp \
|
||||||
|
src/counter.cpp \
|
||||||
|
src/testrandom.cpp \
|
||||||
|
src/testservergamethread.cpp \
|
||||||
|
src/returnmessage.cpp
|
21
servatrice/src/counter.cpp
Normal file
21
servatrice/src/counter.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "counter.h"
|
||||||
|
|
37
servatrice/src/counter.h
Normal file
37
servatrice/src/counter.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef COUNTER_H
|
||||||
|
#define COUNTER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class Counter {
|
||||||
|
protected:
|
||||||
|
QString name;
|
||||||
|
int count;
|
||||||
|
public:
|
||||||
|
Counter(QString _name, int _count = 0) : name(_name), count(_count) { }
|
||||||
|
~Counter() { }
|
||||||
|
int getCount() { return count; }
|
||||||
|
void setCount(int _count) { count = _count; }
|
||||||
|
QString getName() const { return name; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
33
servatrice/src/main.cpp
Normal file
33
servatrice/src/main.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include "testserver.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
|
TestServer server;
|
||||||
|
server.listen(QHostAddress::Any, 4747);
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
86
servatrice/src/playerzone.cpp
Normal file
86
servatrice/src/playerzone.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "playerzone.h"
|
||||||
|
|
||||||
|
PlayerZone::PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _id_access)
|
||||||
|
: name(_name), has_coords(_has_coords), is_public(_is_public), id_access(_id_access)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerZone::~PlayerZone()
|
||||||
|
{
|
||||||
|
qDebug(QString("PlayerZone destructor: %1").arg(name).toLatin1());
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::shuffle(TestRandom *rnd)
|
||||||
|
{
|
||||||
|
QList<TestCard *> temp;
|
||||||
|
for (int i = cards.size(); i; i--)
|
||||||
|
temp.append(cards.takeAt(rnd->getNumber(0, i - 1)));
|
||||||
|
cards = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCard *PlayerZone::getCard(int id, bool remove, int *position)
|
||||||
|
{
|
||||||
|
if (hasIdAccess()) {
|
||||||
|
QListIterator<TestCard *> CardIterator(cards);
|
||||||
|
int i = 0;
|
||||||
|
while (CardIterator.hasNext()) {
|
||||||
|
TestCard *tmp = CardIterator.next();
|
||||||
|
if (tmp->getId() == id) {
|
||||||
|
if (remove)
|
||||||
|
cards.removeAt(i);
|
||||||
|
if (position)
|
||||||
|
*position = i;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
if (id >= cards.size())
|
||||||
|
return NULL;
|
||||||
|
TestCard *tmp = cards[id];
|
||||||
|
if (remove)
|
||||||
|
cards.removeAt(id);
|
||||||
|
if (position)
|
||||||
|
*position = id;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::insertCard(TestCard *card, int x, int y)
|
||||||
|
{
|
||||||
|
if (hasCoords()) {
|
||||||
|
card->setCoords(x, y);
|
||||||
|
cards.append(card);
|
||||||
|
} else {
|
||||||
|
card->setCoords(0, 0);
|
||||||
|
cards.insert(x, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerZone::clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cards.size(); i++)
|
||||||
|
delete cards.at(i);
|
||||||
|
cards.clear();
|
||||||
|
}
|
55
servatrice/src/playerzone.h
Normal file
55
servatrice/src/playerzone.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef PLAYERZONE_H
|
||||||
|
#define PLAYERZONE_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include "testcard.h"
|
||||||
|
#include "testrandom.h"
|
||||||
|
|
||||||
|
class PlayerZone {
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
bool has_coords;
|
||||||
|
bool is_public; // Contents of the zone are visible for anyone
|
||||||
|
bool id_access; // getCard() finds by id, not by list index
|
||||||
|
// Example: When moving a card from the library to the table,
|
||||||
|
// the card has to be found by list index because the client
|
||||||
|
// does not know the id. But when moving a card from the hand
|
||||||
|
// to the table, the card can be found by id because the client
|
||||||
|
// knows the id and the hand does not need to have a specific order.
|
||||||
|
public:
|
||||||
|
PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _id_access);
|
||||||
|
~PlayerZone();
|
||||||
|
|
||||||
|
TestCard *getCard(int id, bool remove, int *position = NULL);
|
||||||
|
|
||||||
|
bool isPublic() { return is_public; }
|
||||||
|
bool hasCoords() { return has_coords; }
|
||||||
|
bool hasIdAccess() { return id_access; }
|
||||||
|
QString getName() { return name; }
|
||||||
|
|
||||||
|
QList<TestCard *> cards;
|
||||||
|
void insertCard(TestCard *card, int x, int y);
|
||||||
|
void shuffle(TestRandom *rnd);
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
33
servatrice/src/returnmessage.cpp
Normal file
33
servatrice/src/returnmessage.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include "returnmessage.h"
|
||||||
|
#include "testserversocket.h"
|
||||||
|
|
||||||
|
void ReturnMessage::setMsgId(unsigned int _msg_id)
|
||||||
|
{
|
||||||
|
msg_id = _msg_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReturnMessage::send(const QString &args, bool success)
|
||||||
|
{
|
||||||
|
TestServerSocket *s = qobject_cast<TestServerSocket *>(parent());
|
||||||
|
if (!s)
|
||||||
|
return false;
|
||||||
|
s->msg(QString("resp|%1|%2|%3").arg(msg_id)
|
||||||
|
.arg(success ? "ok" : "err")
|
||||||
|
.arg(args));
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReturnMessage::sendList(const QStringList &args)
|
||||||
|
{
|
||||||
|
TestServerSocket *s = qobject_cast<TestServerSocket *>(parent());
|
||||||
|
if (!s)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < args.size(); i++)
|
||||||
|
s->msg(QString("%1|%2|%3").arg(cmd)
|
||||||
|
.arg(msg_id)
|
||||||
|
.arg(args[i]));
|
||||||
|
s->msg(QString("%1|%2|.").arg(cmd).arg(msg_id));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
21
servatrice/src/returnmessage.h
Normal file
21
servatrice/src/returnmessage.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef RETURNMESSAGE_H
|
||||||
|
#define RETURNMESSAGE_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ReturnMessage : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
unsigned int msg_id;
|
||||||
|
QString cmd;
|
||||||
|
public:
|
||||||
|
ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { }
|
||||||
|
unsigned int getMsgId() const { return msg_id; }
|
||||||
|
void setMsgId(unsigned int _msg_id);
|
||||||
|
void setCmd(const QString &_cmd) { cmd = _cmd; }
|
||||||
|
bool send(const QString &args = QString(), bool success = true);
|
||||||
|
bool sendList(const QStringList &args);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
62
servatrice/src/testcard.cpp
Normal file
62
servatrice/src/testcard.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "testcard.h"
|
||||||
|
|
||||||
|
TestCard::TestCard(QString _name, int _id, int _coord_x, int _coord_y)
|
||||||
|
: id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), counters(0), tapped(false), attacking(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TestCard::~TestCard()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCard::resetState()
|
||||||
|
{
|
||||||
|
setCoords(0, 0);
|
||||||
|
setCounters(0);
|
||||||
|
setTapped(false);
|
||||||
|
setAttacking(false);
|
||||||
|
setFaceDown(false);
|
||||||
|
setAnnotation("");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestCard::setAttribute(const QString &aname, const QString &avalue)
|
||||||
|
{
|
||||||
|
if (!aname.compare("counters")) {
|
||||||
|
bool ok;
|
||||||
|
int tmp_int = avalue.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return false;
|
||||||
|
setCounters(tmp_int);
|
||||||
|
} else if (!aname.compare("tapped")) {
|
||||||
|
setTapped(!avalue.compare("1"));
|
||||||
|
} else if (!aname.compare("attacking")) {
|
||||||
|
setAttacking(!avalue.compare("1"));
|
||||||
|
} else if (!aname.compare("facedown")) {
|
||||||
|
setFaceDown(!avalue.compare("1"));
|
||||||
|
} else if (!aname.compare("annotation")) {
|
||||||
|
setAnnotation(avalue);
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
63
servatrice/src/testcard.h
Normal file
63
servatrice/src/testcard.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TESTCARD_H
|
||||||
|
#define TESTCARD_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
/**
|
||||||
|
@author Max-Wilhelm Bruker <brukie@laptop>
|
||||||
|
*/
|
||||||
|
class TestCard {
|
||||||
|
private:
|
||||||
|
int id;
|
||||||
|
int coord_x, coord_y;
|
||||||
|
QString name;
|
||||||
|
int counters;
|
||||||
|
bool tapped;
|
||||||
|
bool attacking;
|
||||||
|
bool facedown;
|
||||||
|
QString annotation;
|
||||||
|
public:
|
||||||
|
TestCard(QString _name, int _id, int _coord_x, int _coord_y);
|
||||||
|
~TestCard();
|
||||||
|
|
||||||
|
int getId() { return id; }
|
||||||
|
int getX() { return coord_x; }
|
||||||
|
int getY() { return coord_y; }
|
||||||
|
QString getName() { return name; }
|
||||||
|
int getCounters() { return counters; }
|
||||||
|
bool getTapped() { return tapped; }
|
||||||
|
bool getAttacking() { return attacking; }
|
||||||
|
bool getFaceDown() { return facedown; }
|
||||||
|
QString getAnnotation() { return annotation; }
|
||||||
|
|
||||||
|
void setCoords(int x, int y) { coord_x = x; coord_y = y; }
|
||||||
|
void setName(const QString &_name) { name = _name; }
|
||||||
|
void setCounters(int _counters) { counters = _counters; }
|
||||||
|
void setTapped(bool _tapped) { tapped = _tapped; }
|
||||||
|
void setAttacking(bool _attacking) { attacking = _attacking; }
|
||||||
|
void setFaceDown(bool _facedown) { facedown = _facedown; }
|
||||||
|
void setAnnotation(const QString &_annotation) { annotation = _annotation; }
|
||||||
|
|
||||||
|
void resetState();
|
||||||
|
bool setAttribute(const QString &aname, const QString &avalue);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
18
servatrice/src/testrandom.cpp
Normal file
18
servatrice/src/testrandom.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "testrandom.h"
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
void TestRandom::init()
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
int seed = QDateTime::currentDateTime().toTime_t();
|
||||||
|
qDebug(QString("%1: qsrand(%2)").arg(thread()->metaObject()->className()).arg(seed).toLatin1());
|
||||||
|
qsrand(seed);
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int TestRandom::getNumber(unsigned int min, unsigned int max)
|
||||||
|
{
|
||||||
|
int r = qrand();
|
||||||
|
return min + (unsigned int) (((double) (max + 1 - min)) * r / (RAND_MAX + 1.0));
|
||||||
|
}
|
18
servatrice/src/testrandom.h
Normal file
18
servatrice/src/testrandom.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef TESTRANDOM_H
|
||||||
|
#define TESTRANDOM_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
class TestRandom : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
bool initialized;
|
||||||
|
public:
|
||||||
|
TestRandom(QObject *parent) : QObject(parent), initialized(false) { }
|
||||||
|
void init();
|
||||||
|
unsigned int getNumber(unsigned int min, unsigned int max);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
107
servatrice/src/testserver.cpp
Normal file
107
servatrice/src/testserver.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "testserver.h"
|
||||||
|
|
||||||
|
TestServer::TestServer(QObject *parent)
|
||||||
|
: QTcpServer(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServer::~TestServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServer::gameCreated(TestServerGame *_game, TestServerSocket *_creator)
|
||||||
|
{
|
||||||
|
games << _game;
|
||||||
|
_creator->moveToThread(_game->thread());
|
||||||
|
_game->addPlayer(_creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServer::addGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator)
|
||||||
|
{
|
||||||
|
TestServerGameThread *newThread = new TestServerGameThread(name, description, password, maxPlayers, creator);
|
||||||
|
connect(newThread, SIGNAL(gameCreated(TestServerGame *, TestServerSocket *)), this, SLOT(gameCreated(TestServerGame *, TestServerSocket *)));
|
||||||
|
connect(newThread, SIGNAL(finished()), this, SLOT(gameClosed()));
|
||||||
|
newThread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServer::incomingConnection(int socketId)
|
||||||
|
{
|
||||||
|
TestServerSocket *socket = new TestServerSocket(this);
|
||||||
|
socket->setSocketDescriptor(socketId);
|
||||||
|
connect(socket, SIGNAL(createGame(const QString, const QString, const QString, const int, TestServerSocket *)), this, SLOT(addGame(const QString, const QString, const QString, const int, TestServerSocket *)));
|
||||||
|
connect(socket, SIGNAL(joinGame(const QString, TestServerSocket *)), this, SLOT(addClientToGame(const QString, TestServerSocket *)));
|
||||||
|
socket->initConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServerGame *TestServer::getGame(const QString &name)
|
||||||
|
{
|
||||||
|
QListIterator<TestServerGame *> i(games);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
TestServerGame *tmp = i.next();
|
||||||
|
if ((!tmp->name.compare(name, Qt::CaseSensitive)) && !tmp->getGameStarted())
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<TestServerGame *> TestServer::listOpenGames()
|
||||||
|
{
|
||||||
|
QList<TestServerGame *> result;
|
||||||
|
QListIterator<TestServerGame *> i(games);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
TestServerGame *tmp = i.next();
|
||||||
|
tmp->mutex->lock();
|
||||||
|
if ((!tmp->getGameStarted())
|
||||||
|
&& (tmp->getPlayerCount() < tmp->maxPlayers))
|
||||||
|
result.append(tmp);
|
||||||
|
tmp->mutex->unlock();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestServer::checkGamePassword(const QString &name, const QString &password)
|
||||||
|
{
|
||||||
|
TestServerGame *tmp;
|
||||||
|
if ((tmp = getGame(name))) {
|
||||||
|
QMutexLocker locker(tmp->mutex);
|
||||||
|
if ((!tmp->getGameStarted())
|
||||||
|
&& (!tmp->password.compare(password, Qt::CaseSensitive))
|
||||||
|
&& (tmp->getPlayerCount() < tmp->maxPlayers))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServer::addClientToGame(const QString name, TestServerSocket *client)
|
||||||
|
{
|
||||||
|
TestServerGame *tmp = getGame(name);
|
||||||
|
client->moveToThread(tmp->thread());
|
||||||
|
tmp->addPlayer(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServer::gameClosed()
|
||||||
|
{
|
||||||
|
qDebug("TestServer::gameClosed");
|
||||||
|
TestServerGameThread *t = qobject_cast<TestServerGameThread *>(sender());
|
||||||
|
games.removeAt(games.indexOf(t->getGame()));
|
||||||
|
delete t;
|
||||||
|
}
|
49
servatrice/src/testserver.h
Normal file
49
servatrice/src/testserver.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TESTSERVER_H
|
||||||
|
#define TESTSERVER_H
|
||||||
|
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include "testservergamethread.h"
|
||||||
|
#include "testservergame.h"
|
||||||
|
|
||||||
|
class TestServerGame;
|
||||||
|
class TestServerSocket;
|
||||||
|
|
||||||
|
class TestServer : public QTcpServer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private slots:
|
||||||
|
void addGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator);
|
||||||
|
void addClientToGame(const QString name, TestServerSocket *client);
|
||||||
|
void gameCreated(TestServerGame *_game, TestServerSocket *_creator);
|
||||||
|
void gameClosed();
|
||||||
|
public:
|
||||||
|
TestServer(QObject *parent = 0);
|
||||||
|
~TestServer();
|
||||||
|
bool checkGamePassword(const QString &name, const QString &password);
|
||||||
|
QList<TestServerGame *> listOpenGames();
|
||||||
|
TestServerGame *getGame(const QString &name);
|
||||||
|
private:
|
||||||
|
void incomingConnection(int SocketId);
|
||||||
|
QList<TestServerGame *> games;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
155
servatrice/src/testservergame.cpp
Normal file
155
servatrice/src/testservergame.cpp
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "testservergame.h"
|
||||||
|
|
||||||
|
TestServerGame::TestServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent)
|
||||||
|
: QObject(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers)
|
||||||
|
{
|
||||||
|
gameStarted = false;
|
||||||
|
mutex = new QMutex(QMutex::Recursive);
|
||||||
|
rnd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServerGame::~TestServerGame()
|
||||||
|
{
|
||||||
|
if (rnd)
|
||||||
|
delete rnd;
|
||||||
|
delete mutex;
|
||||||
|
qDebug("TestServerGame destructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestServerGame::getGameStarted()
|
||||||
|
{
|
||||||
|
return gameStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestServerGame::getPlayerCount()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
return players.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList TestServerGame::getPlayerNames()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
QStringList result;
|
||||||
|
QListIterator<TestServerSocket *> i(players);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
TestServerSocket *tmp = i.next();
|
||||||
|
result << QString("%1|%2").arg(tmp->getPlayerId()).arg(tmp->PlayerName);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServerSocket *TestServerGame::getPlayer(int player_id)
|
||||||
|
{
|
||||||
|
QListIterator<TestServerSocket *> i(players);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
TestServerSocket *tmp = i.next();
|
||||||
|
if (tmp->getPlayerId() == player_id)
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::msg(const QString &s)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
QListIterator<TestServerSocket *> i(players);
|
||||||
|
while (i.hasNext())
|
||||||
|
i.next()->msg(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::broadcastEvent(const QString &cmd, TestServerSocket *player)
|
||||||
|
{
|
||||||
|
if (player)
|
||||||
|
msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->PlayerName).arg(cmd));
|
||||||
|
else
|
||||||
|
msg(QString("public|||%1").arg(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::startGameIfReady()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
if (players.size() < maxPlayers)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < players.size(); i++)
|
||||||
|
if (players.at(i)->getStatus() != StatusReadyStart)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rnd = new TestRandom(this);
|
||||||
|
rnd->init();
|
||||||
|
|
||||||
|
for (int i = 0; i < players.size(); i++)
|
||||||
|
players.at(i)->setupZones();
|
||||||
|
|
||||||
|
activePlayer = 0;
|
||||||
|
activePhase = 0;
|
||||||
|
gameStarted = true;
|
||||||
|
broadcastEvent("game_start", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::addPlayer(TestServerSocket *player)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
int max = -1;
|
||||||
|
QListIterator<TestServerSocket *> i(players);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
int tmp = i.next()->getPlayerId();
|
||||||
|
if (tmp > max)
|
||||||
|
max = tmp;
|
||||||
|
}
|
||||||
|
player->setPlayerId(max + 1);
|
||||||
|
|
||||||
|
player->setGame(this);
|
||||||
|
player->msg(QString("private|||player_id|%1|%2").arg(max + 1).arg(player->PlayerName));
|
||||||
|
broadcastEvent("join", player);
|
||||||
|
|
||||||
|
players << player;
|
||||||
|
|
||||||
|
connect(player, SIGNAL(broadcastEvent(const QString &, TestServerSocket *)), this, SLOT(broadcastEvent(const QString &, TestServerSocket *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::removePlayer(TestServerSocket *player)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
|
||||||
|
players.removeAt(players.indexOf(player));
|
||||||
|
broadcastEvent("leave", player);
|
||||||
|
if (!players.size())
|
||||||
|
thread()->quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::setActivePlayer(int _activePlayer)
|
||||||
|
{
|
||||||
|
activePlayer = _activePlayer;
|
||||||
|
broadcastEvent(QString("set_active_player|%1").arg(_activePlayer), NULL);
|
||||||
|
setActivePhase(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGame::setActivePhase(int _activePhase)
|
||||||
|
{
|
||||||
|
activePhase = _activePhase;
|
||||||
|
broadcastEvent(QString("set_active_phase|%1").arg(_activePhase), NULL);
|
||||||
|
}
|
64
servatrice/src/testservergame.h
Normal file
64
servatrice/src/testservergame.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TESTSERVERGAME_H
|
||||||
|
#define TESTSERVERGAME_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QStringList>
|
||||||
|
#include "testserversocket.h"
|
||||||
|
#include "testrandom.h"
|
||||||
|
|
||||||
|
class TestServerSocket;
|
||||||
|
|
||||||
|
class TestServerGame : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QList<TestServerSocket *> players;
|
||||||
|
bool gameStarted;
|
||||||
|
int activePlayer;
|
||||||
|
int activePhase;
|
||||||
|
public slots:
|
||||||
|
void broadcastEvent(const QString &event, TestServerSocket *player);
|
||||||
|
public:
|
||||||
|
QMutex *mutex;
|
||||||
|
TestRandom *rnd;
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
QString password;
|
||||||
|
int maxPlayers;
|
||||||
|
TestServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent = 0);
|
||||||
|
~TestServerGame();
|
||||||
|
bool getGameStarted();
|
||||||
|
int getPlayerCount();
|
||||||
|
QStringList getPlayerNames();
|
||||||
|
TestServerSocket *getPlayer(int player_id);
|
||||||
|
void addPlayer(TestServerSocket *player);
|
||||||
|
void removePlayer(TestServerSocket *player);
|
||||||
|
void startGameIfReady();
|
||||||
|
void msg(const QString &s);
|
||||||
|
int getActivePlayer() { return activePlayer; }
|
||||||
|
int getActivePhase() { return activePhase; }
|
||||||
|
void setActivePlayer(int _activePlayer);
|
||||||
|
void setActivePhase(int _activePhase);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
20
servatrice/src/testservergamethread.cpp
Normal file
20
servatrice/src/testservergamethread.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "testservergamethread.h"
|
||||||
|
|
||||||
|
TestServerGameThread::TestServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, TestServerSocket *_creator, QObject *parent)
|
||||||
|
: QThread(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers), creator(_creator), game(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServerGameThread::~TestServerGameThread()
|
||||||
|
{
|
||||||
|
if (game)
|
||||||
|
delete game;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerGameThread::run()
|
||||||
|
{
|
||||||
|
game = new TestServerGame(name, description, password, maxPlayers);
|
||||||
|
emit gameCreated(game, creator);
|
||||||
|
exec();
|
||||||
|
}
|
30
servatrice/src/testservergamethread.h
Normal file
30
servatrice/src/testservergamethread.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef TESTSERVERGAMETHREAD_H
|
||||||
|
#define TESTSERVERGAMETHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include "testservergame.h"
|
||||||
|
#include "testserversocket.h"
|
||||||
|
|
||||||
|
class TestServerGame;
|
||||||
|
class TestServerSocket;
|
||||||
|
|
||||||
|
class TestServerGameThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void gameCreated(TestServerGame *_game, TestServerSocket *creator);
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
QString password;
|
||||||
|
int maxPlayers;
|
||||||
|
TestServerSocket *creator;
|
||||||
|
TestServerGame *game;
|
||||||
|
public:
|
||||||
|
TestServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, TestServerSocket *_creator, QObject *parent = 0);
|
||||||
|
~TestServerGameThread();
|
||||||
|
TestServerGame *getGame() { return game; }
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
595
servatrice/src/testserversocket.cpp
Normal file
595
servatrice/src/testserversocket.cpp
Normal file
|
@ -0,0 +1,595 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include "testserver.h"
|
||||||
|
#include "testserversocket.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
TestServerSocket::TestServerSocket(TestServer *_server, QObject *parent)
|
||||||
|
: QTcpSocket(parent), server(_server)
|
||||||
|
{
|
||||||
|
remsg = new ReturnMessage(this);
|
||||||
|
connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
|
||||||
|
connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
|
||||||
|
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError)));
|
||||||
|
setTextModeEnabled(true);
|
||||||
|
PlayerStatus = StatusNormal;
|
||||||
|
game = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestServerSocket::~TestServerSocket()
|
||||||
|
{
|
||||||
|
qDebug("TestServerSocket destructor");
|
||||||
|
if (game)
|
||||||
|
game->removePlayer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::setName(const QString &name)
|
||||||
|
{
|
||||||
|
emit broadcastEvent(QString("name|%1|%2").arg(PlayerName).arg(name), this);
|
||||||
|
PlayerName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerZone *TestServerSocket::getZone(const QString &name)
|
||||||
|
{
|
||||||
|
QListIterator<PlayerZone *> ZoneIterator(zones);
|
||||||
|
while (ZoneIterator.hasNext()) {
|
||||||
|
PlayerZone *temp = ZoneIterator.next();
|
||||||
|
if (!temp->getName().compare(name))
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Counter *TestServerSocket::getCounter(const QString &name)
|
||||||
|
{
|
||||||
|
QListIterator<Counter *> CounterIterator(counters);
|
||||||
|
while (CounterIterator.hasNext()) {
|
||||||
|
Counter *temp = CounterIterator.next();
|
||||||
|
if (!temp->getName().compare(name))
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::setupZones()
|
||||||
|
{
|
||||||
|
// Delete existing zones and counters
|
||||||
|
clearZones();
|
||||||
|
|
||||||
|
// This may need to be customized according to the game rules.
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create zones
|
||||||
|
PlayerZone *deck = new PlayerZone("deck", false, false, false);
|
||||||
|
zones << deck;
|
||||||
|
PlayerZone *sb = new PlayerZone("sb", false, false, false);
|
||||||
|
zones << sb;
|
||||||
|
zones << new PlayerZone("table", true, true, true);
|
||||||
|
zones << new PlayerZone("hand", false, false, true);
|
||||||
|
zones << new PlayerZone("grave", false, true, true);
|
||||||
|
zones << new PlayerZone("rfg", false, true, true);
|
||||||
|
|
||||||
|
// Create life counter
|
||||||
|
Counter *life = new Counter("life", 20);
|
||||||
|
counters << life;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Assign card ids and create deck from decklist
|
||||||
|
QListIterator<QString> DeckIterator(DeckList);
|
||||||
|
int i = 0;
|
||||||
|
while (DeckIterator.hasNext())
|
||||||
|
deck->cards.append(new TestCard(DeckIterator.next(), i++, 0, 0));
|
||||||
|
deck->shuffle(game->rnd);
|
||||||
|
|
||||||
|
QListIterator<QString> SBIterator(SideboardList);
|
||||||
|
while (SBIterator.hasNext())
|
||||||
|
sb->cards.append(new TestCard(SBIterator.next(), i++, 0, 0));
|
||||||
|
|
||||||
|
nextCardId = i;
|
||||||
|
|
||||||
|
PlayerStatus = StatusPlaying;
|
||||||
|
broadcastEvent(QString("setup_zones|%1|%2|%3").arg(getCounter("life")->getCount())
|
||||||
|
.arg(deck->cards.size())
|
||||||
|
.arg(getZone("sb")->cards.size()), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::clearZones()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < zones.size(); i++)
|
||||||
|
delete zones.at(i);
|
||||||
|
zones.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < counters.size(); i++)
|
||||||
|
delete counters.at(i);
|
||||||
|
counters.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::leaveGame()
|
||||||
|
{
|
||||||
|
if (!game)
|
||||||
|
return;
|
||||||
|
game->removePlayer(this);
|
||||||
|
game = 0;
|
||||||
|
PlayerStatus = StatusNormal;
|
||||||
|
clearZones();
|
||||||
|
moveToThread(server->thread());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::readClient()
|
||||||
|
{
|
||||||
|
QTextStream *stream = new QTextStream(this);
|
||||||
|
stream->setCodec("UTF-8");
|
||||||
|
QStringList lines;
|
||||||
|
|
||||||
|
// Before parsing, everything has to be buffered so that the stream
|
||||||
|
// can be deleted in order to avoid problems when moving the object
|
||||||
|
// to another thread while this function is still running.
|
||||||
|
for (;;) {
|
||||||
|
QString line = stream->readLine();
|
||||||
|
if (line.isNull())
|
||||||
|
break;
|
||||||
|
lines << line;
|
||||||
|
}
|
||||||
|
delete stream;
|
||||||
|
|
||||||
|
QStringListIterator i(lines);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QString line = i.next();
|
||||||
|
|
||||||
|
qDebug(QString("<<< %1").arg(line).toLatin1());
|
||||||
|
switch (PlayerStatus) {
|
||||||
|
case StatusNormal:
|
||||||
|
case StatusReadyStart:
|
||||||
|
case StatusPlaying:
|
||||||
|
parseCommand(line);
|
||||||
|
break;
|
||||||
|
case StatusSubmitDeck:
|
||||||
|
QString card = line;
|
||||||
|
if (!card.compare(".")) {
|
||||||
|
PlayerStatus = StatusNormal;
|
||||||
|
remsg->send();
|
||||||
|
} else if (card.startsWith("SB:"))
|
||||||
|
SideboardList << card.mid(3);
|
||||||
|
else
|
||||||
|
DeckList << card;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestServerSocket::parseCommand(QString line)
|
||||||
|
{
|
||||||
|
QStringList params = line.split("|");
|
||||||
|
|
||||||
|
// Extract message id
|
||||||
|
bool conv_ok;
|
||||||
|
int msgId = params.takeFirst().toInt(&conv_ok);
|
||||||
|
if (!conv_ok) {
|
||||||
|
remsg->setMsgId(0);
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
}
|
||||||
|
remsg->setMsgId(msgId);
|
||||||
|
|
||||||
|
if (params.empty()) {
|
||||||
|
remsg->setMsgId(0);
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract command
|
||||||
|
QString cmd = params.takeFirst();
|
||||||
|
remsg->setCmd(cmd);
|
||||||
|
|
||||||
|
// parse command
|
||||||
|
|
||||||
|
if (!cmd.compare("list_games", Qt::CaseInsensitive)) {
|
||||||
|
remsg->send();
|
||||||
|
QList<TestServerGame *> gameList = server->listOpenGames();
|
||||||
|
QListIterator<TestServerGame *> gameListIterator(gameList);
|
||||||
|
QStringList result;
|
||||||
|
while (gameListIterator.hasNext()) {
|
||||||
|
TestServerGame *tmp = gameListIterator.next();
|
||||||
|
tmp->mutex->lock();
|
||||||
|
result << QString("%1|%2|%3|%4|%5").arg(tmp->name)
|
||||||
|
.arg(tmp->description)
|
||||||
|
.arg(tmp->password == "" ? 0 : 1)
|
||||||
|
.arg(tmp->getPlayerCount())
|
||||||
|
.arg(tmp->maxPlayers);
|
||||||
|
tmp->mutex->unlock();
|
||||||
|
}
|
||||||
|
remsg->sendList(result);
|
||||||
|
} else if (!cmd.compare("create_game", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 4)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
QString name = params[0];
|
||||||
|
QString description = params[1];
|
||||||
|
QString password = params[2];
|
||||||
|
int maxPlayers = params[3].toInt();
|
||||||
|
if (server->getGame(name))
|
||||||
|
return remsg->send("name_not_found", false);
|
||||||
|
remsg->send();
|
||||||
|
leaveGame();
|
||||||
|
|
||||||
|
emit createGame(name, description, password, maxPlayers, this);
|
||||||
|
} else if (!cmd.compare("join_game", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 2)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
QString name = params[0];
|
||||||
|
QString password = params[1];
|
||||||
|
if (!server->checkGamePassword(name, password))
|
||||||
|
return remsg->send("wrong_password", false);
|
||||||
|
remsg->send();
|
||||||
|
leaveGame();
|
||||||
|
|
||||||
|
emit joinGame(name, this);
|
||||||
|
} else if (!cmd.compare("leave_game", Qt::CaseInsensitive)) {
|
||||||
|
remsg->send();
|
||||||
|
leaveGame();
|
||||||
|
} else if (!cmd.compare("set_name", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
remsg->send();
|
||||||
|
setName(params[0]);
|
||||||
|
} else if (!cmd.compare("list_players", Qt::CaseInsensitive)) {
|
||||||
|
if (!game)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
|
||||||
|
remsg->send();
|
||||||
|
remsg->sendList(game->getPlayerNames());
|
||||||
|
} else if (!cmd.compare("say", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent(QString("say|%1").arg(params[0]), this);
|
||||||
|
} else if (!cmd.compare("submit_deck", Qt::CaseInsensitive)) {
|
||||||
|
PlayerStatus = StatusSubmitDeck;
|
||||||
|
DeckList.clear();
|
||||||
|
SideboardList.clear();
|
||||||
|
} else if (!cmd.compare("shuffle", Qt::CaseInsensitive)) {
|
||||||
|
if (!game)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
if (!game->getGameStarted())
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
getZone("deck")->shuffle(game->rnd);
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent("shuffle", this);
|
||||||
|
} else if (!cmd.compare("ready_start", Qt::CaseInsensitive)) {
|
||||||
|
if (!game)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
PlayerStatus = StatusReadyStart;
|
||||||
|
emit broadcastEvent(QString("ready_start"), this);
|
||||||
|
game->startGameIfReady();
|
||||||
|
} else if (!cmd.compare("draw_cards", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int number = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
PlayerZone *deck = getZone("deck");
|
||||||
|
PlayerZone *hand = getZone("hand");
|
||||||
|
|
||||||
|
if (deck->cards.size() < number)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
|
||||||
|
for (int i = 0; i < number; ++i) {
|
||||||
|
TestCard *card = deck->cards.first();
|
||||||
|
deck->cards.removeFirst();
|
||||||
|
hand->cards.append(card);
|
||||||
|
msg(QString("private|||draw|%1|%2").arg(card->getId()).arg(card->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
emit broadcastEvent(QString("draw|%1").arg(number), this);
|
||||||
|
} else if (!cmd.compare("move_card", Qt::CaseInsensitive)) {
|
||||||
|
// ID Karte, Startzone, Zielzone, Koordinaten X, Y
|
||||||
|
if (params.size() != 5)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int cardid = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
PlayerZone *startzone = getZone(params[1]);
|
||||||
|
PlayerZone *targetzone = getZone(params[2]);
|
||||||
|
if ((!startzone) || (!targetzone))
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
|
||||||
|
int position = -1;
|
||||||
|
TestCard *card = startzone->getCard(cardid, true, &position);
|
||||||
|
if (!card)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
int x = params[3].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
int y = 0;
|
||||||
|
if (targetzone->hasCoords()) {
|
||||||
|
y = params[4].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
}
|
||||||
|
targetzone->insertCard(card, x, y);
|
||||||
|
remsg->send();
|
||||||
|
msg(QString("private|||move_card|%1|%2|%3|%4|%5|%6|%7").arg(card->getId())
|
||||||
|
.arg(card->getName())
|
||||||
|
.arg(startzone->getName())
|
||||||
|
.arg(position)
|
||||||
|
.arg(targetzone->getName())
|
||||||
|
.arg(x)
|
||||||
|
.arg(y));
|
||||||
|
// Was ist mit Facedown-Karten?
|
||||||
|
if ((startzone->isPublic()) || (targetzone->isPublic()))
|
||||||
|
emit broadcastEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7").arg(card->getId())
|
||||||
|
.arg(card->getName())
|
||||||
|
.arg(startzone->getName())
|
||||||
|
.arg(position)
|
||||||
|
.arg(targetzone->getName())
|
||||||
|
.arg(x)
|
||||||
|
.arg(y), this);
|
||||||
|
else
|
||||||
|
emit broadcastEvent(QString("move_card|||%1|%2|%3|%4|%5").arg(startzone->getName())
|
||||||
|
.arg(position)
|
||||||
|
.arg(targetzone->getName())
|
||||||
|
.arg(x)
|
||||||
|
.arg(y), this);
|
||||||
|
} else if (!cmd.compare("create_token", Qt::CaseInsensitive)) {
|
||||||
|
// zone, cardname, powtough, x, y
|
||||||
|
// powtough wird erst mal ignoriert
|
||||||
|
if (params.size() != 5)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
PlayerZone *zone = getZone(params[0]);
|
||||||
|
if (!zone)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
QString cardname = params[1];
|
||||||
|
int x = params[3].toInt();
|
||||||
|
int y = params[4].toInt();
|
||||||
|
int cardid = nextCardId++;
|
||||||
|
QString powtough = params[2];
|
||||||
|
|
||||||
|
remsg->send();
|
||||||
|
TestCard *card = new TestCard(cardname, cardid, x, y);
|
||||||
|
zone->insertCard(card, x, y);
|
||||||
|
emit broadcastEvent(QString("create_token|%1|%2|%3|%4|%5|%6").arg(zone->getName())
|
||||||
|
.arg(cardid)
|
||||||
|
.arg(cardname)
|
||||||
|
.arg(powtough)
|
||||||
|
.arg(x)
|
||||||
|
.arg(y), this);
|
||||||
|
} else if (!cmd.compare("set_card_attr", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 4)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
// zone, card id, attr name, attr value
|
||||||
|
// card id = -1 => affects all cards in the specified zone
|
||||||
|
PlayerZone *zone = getZone(params[0]);
|
||||||
|
if (!zone)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
bool ok;
|
||||||
|
int cardid = params[1].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
|
||||||
|
if (cardid == -1) {
|
||||||
|
QListIterator<TestCard *> CardIterator(zone->cards);
|
||||||
|
while (CardIterator.hasNext())
|
||||||
|
if (!CardIterator.next()->setAttribute(params[2], params[3]))
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
} else {
|
||||||
|
TestCard *card = zone->getCard(cardid, false);
|
||||||
|
if (!card)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
if (!card->setAttribute(params[2], params[3]))
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
}
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent(QString("set_card_attr|%1|%2|%3|%4").arg(zone->getName()).arg(cardid).arg(params[2]).arg(params[3]), this);
|
||||||
|
} else if (!cmd.compare("inc_counter", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 2)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
Counter *c = getCounter(params[0]);
|
||||||
|
if (!c)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
bool ok;
|
||||||
|
int delta = params[1].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
remsg->send();
|
||||||
|
c->setCount(c->getCount() + delta);
|
||||||
|
emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(c->getCount()), this);
|
||||||
|
} else if (!cmd.compare("set_counter", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 2)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
Counter *c = getCounter(params[0]);
|
||||||
|
bool ok;
|
||||||
|
int count = params[1].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
if (!c) {
|
||||||
|
c = new Counter(params[0], count);
|
||||||
|
counters << c;
|
||||||
|
} else
|
||||||
|
c->setCount(count);
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(count), this);
|
||||||
|
} else if (!cmd.compare("del_counter", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
Counter *c = getCounter(params[0]);
|
||||||
|
if (!c)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
delete c;
|
||||||
|
counters.removeAt(counters.indexOf(c));
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent(QString("del_counter|%1").arg(params[0]), this);
|
||||||
|
} else if (!cmd.compare("list_counters", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int player_id = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
TestServerSocket *player = game->getPlayer(player_id);
|
||||||
|
if (!player)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
remsg->sendList(player->listCounters());
|
||||||
|
} else if (!cmd.compare("list_zones", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int player_id = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
TestServerSocket *player = game->getPlayer(player_id);
|
||||||
|
if (!player)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
remsg->sendList(player->listZones());
|
||||||
|
} else if (!cmd.compare("dump_zone", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 3)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int player_id = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
int number_cards = params[2].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
TestServerSocket *player = game->getPlayer(player_id);
|
||||||
|
if (!player)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
PlayerZone *zone = player->getZone(params[1]);
|
||||||
|
if (!zone)
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
if (!(zone->isPublic() || (player_id == PlayerId)))
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
QListIterator<TestCard *> card_iterator(zone->cards);
|
||||||
|
QStringList result;
|
||||||
|
for (int i = 0; card_iterator.hasNext() && (i < number_cards || number_cards == 0); i++) {
|
||||||
|
TestCard *tmp = card_iterator.next();
|
||||||
|
// XXX Face down cards
|
||||||
|
if (zone->hasIdAccess())
|
||||||
|
result << QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(tmp->getId())
|
||||||
|
.arg(tmp->getName())
|
||||||
|
.arg(tmp->getX())
|
||||||
|
.arg(tmp->getY())
|
||||||
|
.arg(tmp->getCounters())
|
||||||
|
.arg(tmp->getTapped())
|
||||||
|
.arg(tmp->getAttacking())
|
||||||
|
.arg(tmp->getAnnotation());
|
||||||
|
else
|
||||||
|
result << QString("%1|%2||||||").arg(i).arg(tmp->getName());
|
||||||
|
}
|
||||||
|
remsg->sendList(result);
|
||||||
|
emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this);
|
||||||
|
} else if (!cmd.compare("roll_dice", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int sides = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
remsg->send();
|
||||||
|
emit broadcastEvent(QString("roll_dice|%1|%2").arg(sides).arg(game->rnd->getNumber(1, sides)), this);
|
||||||
|
} else if (!cmd.compare("set_active_player", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int active_player = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
if (!game->getPlayer(active_player))
|
||||||
|
return remsg->send("game_state", false);
|
||||||
|
remsg->send();
|
||||||
|
game->setActivePlayer(active_player);
|
||||||
|
} else if (!cmd.compare("set_active_phase", Qt::CaseInsensitive)) {
|
||||||
|
if (params.size() != 1)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
bool ok;
|
||||||
|
int active_phase = params[0].toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
// XXX Überprüfung, ob die Phase existiert...
|
||||||
|
remsg->send();
|
||||||
|
game->setActivePhase(active_phase);
|
||||||
|
} else
|
||||||
|
return remsg->send("syntax", false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerStatusEnum TestServerSocket::getStatus()
|
||||||
|
{
|
||||||
|
return PlayerStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::setStatus(PlayerStatusEnum status)
|
||||||
|
{
|
||||||
|
PlayerStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::setGame(TestServerGame *g)
|
||||||
|
{
|
||||||
|
game = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList TestServerSocket::listCounters()
|
||||||
|
{
|
||||||
|
QStringList counter_list;
|
||||||
|
QListIterator<Counter *> i(counters);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
Counter *tmp = i.next();
|
||||||
|
counter_list << QString("%1|%2").arg(tmp->getName()).arg(tmp->getCount());
|
||||||
|
}
|
||||||
|
return counter_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList TestServerSocket::listZones()
|
||||||
|
{
|
||||||
|
QStringList zone_list;
|
||||||
|
QListIterator<PlayerZone *> i(zones);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
PlayerZone *tmp = i.next();
|
||||||
|
zone_list << QString("%1|%2|%3|%4").arg(tmp->getName()).arg(tmp->isPublic()).arg(tmp->hasCoords()).arg(tmp->cards.size());
|
||||||
|
}
|
||||||
|
return zone_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::msg(const QString &s)
|
||||||
|
{
|
||||||
|
qDebug(QString(">>> %1").arg(s).toLatin1());
|
||||||
|
QTextStream stream(this);
|
||||||
|
stream.setCodec("UTF-8");
|
||||||
|
stream << s << endl;
|
||||||
|
stream.flush();
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::initConnection()
|
||||||
|
{
|
||||||
|
msg(QString("welcome||%1").arg(VERSION_STRING));
|
||||||
|
msg("welcome||.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestServerSocket::catchSocketError(QAbstractSocket::SocketError socketError)
|
||||||
|
{
|
||||||
|
qDebug(QString("socket error: %1").arg(socketError).toLatin1());
|
||||||
|
deleteLater();
|
||||||
|
}
|
81
servatrice/src/testserversocket.h
Normal file
81
servatrice/src/testserversocket.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TESTSERVERSOCKET_H
|
||||||
|
#define TESTSERVERSOCKET_H
|
||||||
|
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include "testserver.h"
|
||||||
|
#include "testservergame.h"
|
||||||
|
#include "playerzone.h"
|
||||||
|
#include "returnmessage.h"
|
||||||
|
#include "counter.h"
|
||||||
|
|
||||||
|
class TestServer;
|
||||||
|
class TestServerGame;
|
||||||
|
class PlayerZone;
|
||||||
|
|
||||||
|
enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying };
|
||||||
|
|
||||||
|
class TestServerSocket : public QTcpSocket
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private slots:
|
||||||
|
void readClient();
|
||||||
|
void catchSocketError(QAbstractSocket::SocketError socketError);
|
||||||
|
signals:
|
||||||
|
void createGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator);
|
||||||
|
void joinGame(const QString name, TestServerSocket *player);
|
||||||
|
void commandReceived(QString cmd, TestServerSocket *player);
|
||||||
|
void broadcastEvent(const QString &event, TestServerSocket *player);
|
||||||
|
void startGameIfReady();
|
||||||
|
private:
|
||||||
|
TestServer *server;
|
||||||
|
TestServerGame *game;
|
||||||
|
QList<QString> DeckList;
|
||||||
|
QList<QString> SideboardList;
|
||||||
|
QList<PlayerZone *> zones;
|
||||||
|
QList<Counter *> counters;
|
||||||
|
int PlayerId;
|
||||||
|
int nextCardId;
|
||||||
|
PlayerZone *getZone(const QString &name);
|
||||||
|
Counter *getCounter(const QString &name);
|
||||||
|
void setName(const QString &name);
|
||||||
|
void clearZones();
|
||||||
|
void leaveGame();
|
||||||
|
bool parseCommand(QString line);
|
||||||
|
PlayerStatusEnum PlayerStatus;
|
||||||
|
ReturnMessage *remsg;
|
||||||
|
public:
|
||||||
|
QString PlayerName;
|
||||||
|
TestServerSocket(TestServer *_server, QObject *parent = 0);
|
||||||
|
~TestServerSocket();
|
||||||
|
void msg(const QString &s);
|
||||||
|
void setGame(TestServerGame *g);
|
||||||
|
PlayerStatusEnum getStatus();
|
||||||
|
void setStatus(PlayerStatusEnum status);
|
||||||
|
void initConnection();
|
||||||
|
int getPlayerId() { return PlayerId; }
|
||||||
|
void setPlayerId(int _id) { PlayerId = _id; }
|
||||||
|
QStringList listCounters();
|
||||||
|
QStringList listZones();
|
||||||
|
void setupZones();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
21
servatrice/src/version.h
Normal file
21
servatrice/src/version.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Max-Wilhelm Bruker *
|
||||||
|
* brukie@laptop *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
const char *VERSION_STRING = "Testserver 0.20090304";
|
Loading…
Reference in a new issue