Merge remote-tracking branch 'upstream/master' into better-picurl-error-handling

This commit is contained in:
Fabio Bas 2014-08-07 21:38:57 +02:00
commit 9383961140
119 changed files with 6467 additions and 4856 deletions

View file

@ -7,13 +7,21 @@
cmake_minimum_required(VERSION 2.6)
set(PROJECT_NAME "Cockatrice")
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 1)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} )
if(POLICY CMP0020)
cmake_policy(SET CMP0020 OLD)
endif()
# Defualt to "Release" build type
if(POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif()
if(POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
set(PROJECT_NAME "Cockatrice")
# Default to "Release" build type
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
@ -24,9 +32,19 @@ ENDIF()
# A project name is needed for CPack
PROJECT("${PROJECT_NAME}")
# Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# Search path for cmake modules
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# Retrieve git version hash
include(getversion)
# Create a header and a cpp file containing the version hash
include(createversionfile)
# Define a proper install path
if(UNIX)
if(APPLE)
@ -58,8 +76,19 @@ IF(MSVC)
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations")
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror")
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations)
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
IF(CXX_HAS_WARNING_${FLAG})
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
ENDIF()
ENDFOREACH()
ELSE()
# other: osx/llvm, bsd/llvm
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
@ -71,8 +100,33 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF()
#Find Qt4 and enable the needed features
FIND_PACKAGE(Qt4 REQUIRED)
# Find Qt and enable the needed features
# Default is Qt5 unless WITH_QT4 option is enabled
option(WITH_QT4 "Force thr use of Qt4 libraries" OFF)
IF(NOT WITH_QT4)
FIND_PACKAGE(Qt5Widgets)
ENDIF()
IF(Qt5Widgets_FOUND)
MESSAGE(STATUS "Found Qt ${Qt5Widgets_VERSION_STRING}")
if(UNIX AND NOT APPLE AND "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
# FIX: Qt was built with -reduce-relocations
add_definitions(-fPIC)
endif()
ELSE()
FIND_PACKAGE(Qt4 4.8.0 REQUIRED)
IF(QT4_FOUND)
# Old FindQt4.cmake modules used the same flag with different case
SET(Qt4_FOUND TRUE)
ENDIF()
IF(Qt4_FOUND)
MESSAGE(STATUS "Found Qt ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}")
ELSE()
MESSAGE(FATAL_ERROR "No Qt4 or Qt5 found!")
ENDIF()
ENDIF()
set(CMAKE_AUTOMOC TRUE)
@ -83,8 +137,8 @@ FIND_PACKAGE(Protobuf REQUIRED)
set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
@ -96,7 +150,7 @@ if(UNIX)
set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-osx_git-${PROJECT_VERSION}")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
else()
# linux
@ -107,13 +161,13 @@ if(UNIX)
endif()
elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}\\\\${PROJECT_VERSION}")
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\${PROJECT_NAME}.exe")
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}")
set(CPACK_NSIS_HELP_LINK "https://github.com/Daenyth/Cockatrice")
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/Daenyth/Cockatrice")
set(CPACK_NSIS_CONTACT "Daenyth+github@gmail.com")
set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_win32_git-${PROJECT_VERSION}")
# Configure file with custom definitions for NSIS.
configure_file(
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
)
endif()
include(CPack)

105
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,105 @@
# Style Guide #
### Compatibility ###
Cockatrice is written in C++-03, so do not use C++11 constructs such as `auto`.
Cockatrice support both Qt 4 and Qt 5, so make sure that your code compiles
with both. If there have been breaking changes between Qt 4 and 5, use a
statement such as
#if QT_VERSION >= 0x500000
doSomethingWithQt5();
#else
doSomethingWithQt4();
#endif
For consistency, use Qt data structures where possible, such as `QString` over
`std::string` or `QList` over `std::vector`.
### Header files ###
Use header files with the extension `.h` and source files with the extension
`.cpp`.
Use header guards in the form of `FILE_NAME_H`.
Simple functions, such as getters, may be written inline in the header file,
but other functions should be written in the source file.
Keep library includes and project includes grouped together. So this is okay:
// Good:
#include <QList>
#include <QString>
#include "card.h"
#include "deck.h"
// Good:
#include "card.h"
#include "deck.h"
#include <QList>
#include <QString>
// Bad:
#include <QList>
#include "card.h"
#include <QString>
#include "deck.h"
### Naming ###
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
function and variable names.
Member variables aren't decorated in any way. Don't prefix or suffix with
underscores, etc.
For arguments to constructors which have the same names as member variables,
prefix those arguments with underscores:
MyClass::MyClass(int _myData)
: myData(_myData)
{}
Pointers and references should be denoted with the `*` or `&` going with the
variable name:
// Good:
Foo *foo1 = new Foo;
Foo &foo2 = *foo1;
// Bad:
Bar* bar1 = new Bar;
Bar& bar2 = *bar1;
Use `0` instead of `NULL` (or `nullptr`) for null pointers.
### Braces ###
Use K&R-style braces. Braces for function implementations go on their own
lines, but they go on the same line everywhere else:
int main()
{
if (someCondition) {
doSomething();
} else {
while (someOtherCondition) {
doSomethingElse();
}
}
}
Braces can be omitted for single-statement if's and the like, as long as it is
still legible.
### Tabs ###
Use only spaces. Four spaces per tab.
### Lines ###
Do not have trailing whitespace in your lines.
Lines should be 80 characters or less, as a soft limit.

View file

@ -33,8 +33,11 @@ To compile:
The following flags can be passed to `cmake`:
- `-DWITH_SERVER=1` build the server
- `-DWITHOUT_CLIENT=1` do not build the client
- `-DWITH_SERVER=1` Build the server
- `-DWITH_CLIENT=0` Do not build the client
- `-DWITH_ORACLE=0` Do not build Oracle
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5.
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings.
# Running

View file

@ -0,0 +1 @@
!define NSIS_SOURCE_PATH "@PROJECT_SOURCE_DIR@"

View file

@ -1,30 +1,26 @@
!include ..\..\..\NSIS.definitions.nsh
!include "MUI2.nsh"
!include "FileFunc.nsh"
!define /date TIMESTAMP "%Y%m%d"
!searchparse /file ../build/cockatrice/version_string.cpp '= "' VERSION '";'
Name "Cockatrice"
OutFile "cockatrice_win32_${TIMESTAMP}_git-${VERSION}.exe"
Name "@CPACK_PACKAGE_NAME@"
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
SetCompressor /SOLID lzma
InstallDir "$PROGRAMFILES\Cockatrice"
; set the Qt install dir here (and make sure you use the latest 4.8 version for packaging)
!define QTDIR "C:\Qt\4.8.6"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
!define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftimage.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "headerimage.bmp"
!define MUI_HEADERIMAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue."
!define MUI_FINISHPAGE_RUN "$INSTDIR/oracle.exe"
!define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now"
!define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\COPYING"
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\COPYING"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
@ -39,37 +35,9 @@ InstallDir "$PROGRAMFILES\Cockatrice"
Section "Application" SecApplication
SetShellVarContext all
SetOutPath "$INSTDIR"
File ..\build\cockatrice\Release\cockatrice.exe
File ..\build\oracle\Release\oracle.exe
File ..\doc\usermanual\Usermanual.pdf
File ..\build\protobuf-2.5.0\protobuf-2.5.0\vsprojects\Release\libprotobuf.lib
File "${QTDIR}\bin\QtCore4.dll"
File "${QTDIR}\bin\QtGui4.dll"
File "${QTDIR}\bin\QtNetwork4.dll"
File "${QTDIR}\bin\QtSvg4.dll"
File "${QTDIR}\bin\QtXml4.dll"
File "${QTDIR}\bin\QtMultimedia4.dll"
SetOutPath "$INSTDIR\zonebg"
File /r ..\zonebg\*.*
SetOutPath "$INSTDIR\plugins"
SetOutPath "$INSTDIR\plugins\codecs"
File "${QTDIR}\plugins\codecs\qcncodecs4.dll"
File "${QTDIR}\plugins\codecs\qjpcodecs4.dll"
File "${QTDIR}\plugins\codecs\qkrcodecs4.dll"
File "${QTDIR}\plugins\codecs\qtwcodecs4.dll"
SetOutPath "$INSTDIR\plugins\iconengines"
File "${QTDIR}\plugins\iconengines\qsvgicon4.dll"
SetOutPath "$INSTDIR\plugins\imageformats"
File "${QTDIR}\plugins\imageformats\qjpeg4.dll"
File "${QTDIR}\plugins\imageformats\qsvg4.dll"
SetOutPath "$INSTDIR\sounds"
File /r ..\sounds\*.*
SetOutPath "$INSTDIR\translations"
File /r ..\build\cockatrice\*.qm
@CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
@CPACK_NSIS_FULL_INSTALL@
WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
@ -107,12 +75,10 @@ SetShellVarContext all
Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\Usermanual.pdf"
Delete "$INSTDIR\libprotobuf.lib"
Delete "$INSTDIR\QtCore4.dll"
Delete "$INSTDIR\QtGui4.dll"
Delete "$INSTDIR\QtNetwork4.dll"
Delete "$INSTDIR\QtSvg4.dll"
Delete "$INSTDIR\QtXml4.dll"
Delete "$INSTDIR\QtMultimedia4.dll"
Delete "$INSTDIR\Qt*.dll"
Delete "$INSTDIR\icu*.dll"
Delete "$INSTDIR\qt.conf"
Delete "$INSTDIR\qdebug.txt"
RMDir "$INSTDIR"
RMDir "$SMPROGRAMS\Cockatrice"

View file

@ -0,0 +1,17 @@
set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
set( hstring "extern const char *VERSION_STRING\;\n" )
set( cppstring "const char * VERSION_STRING = \"${PROJECT_VERSION}\"\;\n")
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
)

View file

@ -2,6 +2,7 @@ find_package(Git)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --long --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID
)
@ -15,15 +16,5 @@ else()
message( WARNING "Git not found. Build will not contain git revision info." )
endif()
set( hstring "extern const char *VERSION_STRING\;\n" )
set( cppstring "const char * VERSION_STRING = \"${GIT_COMMIT_ID}\"\;\n")
file(WRITE version_string.cpp.txt ${cppstring} )
file(WRITE version_string.h.txt ${hstring} )
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different version_string.h.txt ${CMAKE_CURRENT_BINARY_DIR}/version_string.h
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different version_string.cpp.txt ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp
)
set(PROJECT_VERSION_MAJOR ${GIT_COMMIT_ID})
set(PROJECT_VERSION ${GIT_COMMIT_ID} )

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Before After
Before After

View file

@ -90,7 +90,7 @@ SET(cockatrice_SOURCES
src/qt-json/json.cpp
src/soundengine.cpp
src/pending_command.cpp
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp
${VERSION_STRING_CPP}
)
if (UNIX AND NOT APPLE)
@ -125,41 +125,119 @@ if(APPLE)
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE)
if (NOT QT_QTMULTIMEDIA_FOUND)
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(QtMobility REQUIRED)
endif (NOT QT_QTMULTIMEDIA_FOUND)
set(COCKATRICE_LIBS)
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTMULTIMEDIA TRUE)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE)
# Qt4 stuff
if(Qt4_FOUND)
if (NOT QT_QTMULTIMEDIA_FOUND)
FIND_PACKAGE(QtMobility REQUIRED)
endif()
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTMULTIMEDIA TRUE)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE)
# Include directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(${QT_INCLUDES})
INCLUDE_DIRECTORIES(${QT_MOBILITY_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR})
LIST(APPEND COCKATRICE_LIBS ${QT_LIBRARIES})
LIST(APPEND COCKATRICE_LIBS ${QT_QTMAIN_LIBRARY})
LIST(APPEND COCKATRICE_LIBS ${QT_MOBILITY_MULTIMEDIAKIT_LIBRARY})
# Let cmake chew Qt4's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT4_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
QT4_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Widgets)
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Network)
endif()
# QtMultimedia
find_package(Qt5Multimedia)
if(Qt5Multimedia_FOUND)
include_directories(${Qt5Multimedia_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Multimedia)
endif()
# QtPrinter
find_package(Qt5PrintSupport)
if(Qt5PrintSupport_FOUND)
include_directories(${Qt5PrintSupport_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS PrintSupport)
endif()
# QtXml
find_package(Qt5Xml)
if(Qt5Xml_FOUND)
include_directories(${Qt5Xml_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Xml)
endif()
# QtSvg
find_package(Qt5Svg)
if(Qt5Svg_FOUND)
include_directories(${Qt5Svg_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Svg)
endif()
# Qt5LinguistTools
find_package(Qt5LinguistTools)
if(Qt5LinguistTools_FOUND)
include_directories(${Qt5LinguistTools_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS LinguistTools)
endif()
# Let cmake chew Qt5's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
QT5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
# guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
endif()
# Declare path variables
set(ICONDIR share/icons CACHE STRING "icon dir")
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination")
# Let cmake chew Qt4's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT4_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
QT4_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
# Include directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(../common)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR})
# Build cockatrice binary and link it
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES} ${QT_MOBILITY_MULTIMEDIAKIT_LIBRARY})
if(MSVC)
set_target_properties(cockatrice PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
endif(MSVC)
if(Qt4_FOUND)
if(MSVC)
set(QT_USE_QTMAIN true)
endif()
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${COCKATRICE_LIBS})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common Qt5::WinMain)
else()
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common)
endif()
qt5_use_modules(cockatrice ${COCKATRICE_LIBS})
endif()
if(UNIX)
if(APPLE)
@ -178,11 +256,6 @@ elseif(WIN32)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${CMAKE_CURRENT_BINARY_DIR}/version_string.h
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/../common/getversion.cmake
)
if(APPLE)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
@ -215,3 +288,36 @@ Data = Resources\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()
if(WIN32)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
# note: no codecs in qt5
# note: phonon_backend => mediaservice
# note: needs platform on osx
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*d\\.dll")
else()
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*[^d]\\.dll")
endif()
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations
Data = Resources\")
" COMPONENT Runtime)
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -11,8 +11,12 @@
AbstractCounter::AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent)
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), hovered(false), aDec(0), aInc(0), dialogSemaphore(false), deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
{
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
if (player->getLocal()) {
menu = new QMenu(name);
aSet = new QAction(this);
@ -129,7 +133,13 @@ void AbstractCounter::setCounter()
{
bool ok;
dialogSemaphore = true;
int newValue = QInputDialog::getInteger(0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok);
int newValue =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok);
if (deleteAfterDialog) {
deleteLater();
return;

View file

@ -13,6 +13,7 @@
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QDebug>
#include <QImageReader>
const int CardDatabase::versionNeeded = 3;
@ -124,28 +125,38 @@ void PictureLoader::processLoadQueue()
}
PictureToLoad ptl = loadQueue.takeFirst();
mutex.unlock();
QString correctedName = ptl.getCard()->getCorrectedName();
QString picsPath = _picsPath;
QString setName = ptl.getSetName();
//The list of paths to the folders in which to search for images
QList<QString> picsPaths = QList<QString>() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName() + ".full"
<< _picsPath + "/" + ptl.getSetName() + "/" + ptl.getCard()->getCorrectedName() + ".full"
<< _picsPath + "/downloadedPics/" + ptl.getSetName() + "/" + ptl.getCard()->getCorrectedName() + ".full";
QImage image;
if (!image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(setName).arg(correctedName)))
if (!image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(setName).arg(correctedName).arg(1)))
if (!image.load(QString("%1/%2/%3/%4.full.jpg").arg(picsPath).arg("downloadedPics").arg(setName).arg(correctedName))) {
if (picDownload) {
cardsToDownload.append(ptl);
if (!downloadRunning)
startNextPicDownload();
} else {
if (ptl.nextSet())
loadQueue.prepend(ptl);
else
emit imageLoaded(ptl.getCard(), QImage());
}
continue;
}
QImageReader imgReader;
imgReader.setDecideFormatFromContent(true);
bool found = false;
emit imageLoaded(ptl.getCard(), image);
//Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension
for (int i = 0; i < picsPaths.length() && !found; i ++) {
imgReader.setFileName(picsPaths.at(i));
if (imgReader.read(&image)) {
emit imageLoaded(ptl.getCard(), image);
found = true;
}
}
if (!found) {
if (picDownload) {
cardsToDownload.append(ptl);
if (!downloadRunning)
startNextPicDownload();
} else {
if (ptl.nextSet())
loadQueue.prepend(ptl);
else
emit imageLoaded(ptl.getCard(), QImage());
}
}
}
}
@ -153,11 +164,25 @@ QString PictureLoader::getPicUrl(CardInfo *card)
{
if (!picDownload) return QString("");
QString picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
CardSet *set = card->getPreferredSet();
QString picUrl = QString("");
// first check if Hq is enabled and a custom Hq card url exists in cards.xml
if(picDownloadHq)
{
picUrl = card->getCustomPicURLHq(set->getShortName());
if (!picUrl.isEmpty())
return picUrl;
}
// then, test for a custom, non-Hq card url in cards.xml
picUrl = card->getCustomPicURL(set->getShortName());
if (!picUrl.isEmpty())
return picUrl;
// otherwise, fallback to the default url
picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
CardSet *set = card->getPreferredSet();
if (set) {
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
@ -211,25 +236,27 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
qDebug() << "Download failed:" << reply->errorString();
}
const QByteArray &picData = reply->readAll();
const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
QImage testImage;
if (testImage.loadFromData(picData)) {
if (!QDir(QString(picsPath + "/downloadedPics/")).exists()) {
QDir dir(picsPath);
if (!dir.exists())
return;
dir.mkdir("downloadedPics");
}
if (!QDir(QString(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName())).exists()) {
QDir dir(QString(picsPath + "/downloadedPics"));
dir.mkdir(cardBeingDownloaded.getSetName());
QImageReader imgReader;
imgReader.setDecideFormatFromContent(true);
imgReader.setDevice(reply);
QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer
if (extension == ".jpeg")
extension = ".jpg";
if (imgReader.read(&testImage)) {
if (!QDir().mkpath(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName())) {
qDebug() << picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + " could not be created.";
return;
}
QString suffix;
if (!cardBeingDownloaded.getStripped())
suffix = ".full";
QFile newPic(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + ".jpg");
QFile newPic(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + extension);
if (!newPic.open(QIODevice::WriteOnly))
return;
newPic.write(picData);
@ -294,6 +321,8 @@ CardInfo::CardInfo(CardDatabase *_db,
bool _cipt,
int _tableRow,
const SetList &_sets,
const QStringMap &_customPicURLs,
const QStringMap &_customPicURLsHq,
MuidMap _muIds)
: db(_db),
name(_name),
@ -305,6 +334,8 @@ CardInfo::CardInfo(CardDatabase *_db,
text(_text),
colors(_colors),
loyalty(_loyalty),
customPicURLs(_customPicURLs),
customPicURLsHq(_customPicURLsHq),
muIds(_muIds),
cipt(_cipt),
tableRow(_tableRow),
@ -453,6 +484,26 @@ int CardInfo::getPreferredMuId()
return muIds[getPreferredSet()->getShortName()];
}
QString CardInfo::simplifyName(const QString &name) {
QString simpleName(name);
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
// with nothing.
simpleName.replace("æ", "ae");
simpleName.replace("Æ", "AE");
// Replace Jötun Grunt with Jotun Grunt.
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
// Replace dashes with spaces so that we can say "garruk the veil cursed"
// instead of the unintuitive "garruk the veilcursed".
simpleName = simpleName.replace("-", " ");
simpleName.remove(QRegExp("[^a-zA-Z0-9 ]"));
simpleName = simpleName.toLower();
return simpleName;
}
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
{
xml.writeStartElement("card");
@ -467,6 +518,14 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
tmpSet=sets[i]->getShortName();
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
tmpString = info->getCustomPicURL(tmpSet);
if(!tmpString.isEmpty())
xml.writeAttribute("picURL", tmpString);
tmpString = info->getCustomPicURLHq(tmpSet);
if(!tmpString.isEmpty())
xml.writeAttribute("picURLHq", tmpString);
xml.writeCharacters(tmpSet);
xml.writeEndElement();
}
@ -526,55 +585,55 @@ CardDatabase::~CardDatabase()
void CardDatabase::clear()
{
QHashIterator<QString, CardSet *> setIt(setHash);
QHashIterator<QString, CardSet *> setIt(sets);
while (setIt.hasNext()) {
setIt.next();
delete setIt.value();
}
setHash.clear();
sets.clear();
QHashIterator<QString, CardInfo *> i(cardHash);
QHashIterator<QString, CardInfo *> i(cards);
while (i.hasNext()) {
i.next();
delete i.value();
}
cardHash.clear();
cards.clear();
// The pointers themselves were already deleted, so we don't delete them
// again.
simpleNameCards.clear();
}
void CardDatabase::addCard(CardInfo *card)
{
cardHash.insert(card->getName(), card);
cards.insert(card->getName(), card);
simpleNameCards.insert(CardInfo::simplifyName(card->getName()), card);
emit cardAdded(card);
}
void CardDatabase::removeCard(CardInfo *card)
{
cardHash.remove(card->getName());
cards.remove(card->getName());
simpleNameCards.remove(CardInfo::simplifyName(card->getName()));
emit cardRemoved(card);
}
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound)
{
if (cardName.isEmpty())
return noCard;
else if (cardHash.contains(cardName))
return cardHash.value(cardName);
else if (createIfNotFound) {
CardInfo *newCard = new CardInfo(this, cardName, true);
newCard->addToSet(getSet("TK"));
cardHash.insert(cardName, newCard);
return newCard;
} else
return 0;
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) {
return getCardFromMap(cards, cardName, createIfNotFound);
}
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
QString simpleName = CardInfo::simplifyName(cardName);
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
}
CardSet *CardDatabase::getSet(const QString &setName)
{
if (setHash.contains(setName))
return setHash.value(setName);
if (sets.contains(setName))
return sets.value(setName);
else {
CardSet *newSet = new CardSet(setName);
setHash.insert(setName, newSet);
sets.insert(setName, newSet);
return newSet;
}
}
@ -582,7 +641,7 @@ CardSet *CardDatabase::getSet(const QString &setName)
SetList CardDatabase::getSetList() const
{
SetList result;
QHashIterator<QString, CardSet *> i(setHash);
QHashIterator<QString, CardSet *> i(sets);
while (i.hasNext()) {
i.next();
result << i.value();
@ -592,7 +651,9 @@ SetList CardDatabase::getSetList() const
void CardDatabase::clearPixmapCache()
{
QHashIterator<QString, CardInfo *> i(cardHash);
// This also clears the cards in simpleNameCards since they point to the
// same object.
QHashIterator<QString, CardInfo *> i(cards);
while (i.hasNext()) {
i.next();
i.value()->clearPixmapCache();
@ -616,7 +677,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "longname")
longName = xml.readElementText();
}
setHash.insert(shortName, new CardSet(shortName, longName));
sets.insert(shortName, new CardSet(shortName, longName));
}
}
}
@ -629,6 +690,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
if (xml.name() == "card") {
QString name, manacost, type, pt, text;
QStringList colors;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muids;
SetList sets;
int tableRow = 0;
@ -655,6 +717,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
if (attrs.hasAttribute("muId")) {
muids[setName] = attrs.value("muId").toString().toInt();
}
if (attrs.hasAttribute("picURL")) {
customPicURLs[setName] = attrs.value("picURL").toString();
}
if (attrs.hasAttribute("picURLHq")) {
customPicURLsHq[setName] = attrs.value("picURLHq").toString();
}
} else if (xml.name() == "color")
colors << xml.readElementText();
else if (xml.name() == "tablerow")
@ -666,46 +734,32 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "token")
isToken = xml.readElementText().toInt();
}
cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, muids));
addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids));
}
}
}
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
if (cardName.isEmpty())
return noCard;
else if (cardMap.contains(cardName))
return cardMap.value(cardName);
else if (createIfNotFound) {
CardInfo *newCard = new CardInfo(this, cardName, true);
newCard->addToSet(getSet("TK"));
cardMap.insert(cardName, newCard);
return newCard;
} else
return 0;
}
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
{
QFile file(fileName);
file.open(QIODevice::ReadOnly);
if (!file.isOpen())
return FileError;
if (tokens) {
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
if (i.value()->getIsToken()) {
delete i.value();
i.remove();
}
}
} else {
QHashIterator<QString, CardSet *> setIt(setHash);
while (setIt.hasNext()) {
setIt.next();
delete setIt.value();
}
setHash.clear();
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
if (!i.value()->getIsToken()) {
delete i.value();
i.remove();
}
}
cardHash.clear();
}
QXmlStreamReader xml(&file);
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::StartElement) {
@ -726,9 +780,9 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
}
}
}
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded";
qDebug() << cards.size() << "cards in" << sets.size() << "sets loaded";
if (cardHash.isEmpty()) return NoCards;
if (cards.isEmpty()) return NoCards;
return Ok;
}
@ -747,18 +801,17 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
if (!tokens) {
xml.writeStartElement("sets");
QHashIterator<QString, CardSet *> setIterator(setHash);
QHashIterator<QString, CardSet *> setIterator(sets);
while (setIterator.hasNext())
xml << setIterator.next().value();
xml.writeEndElement(); // sets
}
xml.writeStartElement("cards");
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) {
CardInfo *card = cardIterator.next().value();
if (card->getIsToken() == tokens)
xml << card;
xml << card;
}
xml.writeEndElement(); // cards
@ -772,7 +825,7 @@ void CardDatabase::picDownloadChanged()
{
pictureLoader->setPicDownload(settingsCache->getPicDownload());
if (settingsCache->getPicDownload()) {
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext())
cardIterator.next().value()->clearPixmapCacheMiss();
}
@ -782,7 +835,7 @@ void CardDatabase::picDownloadHqChanged()
{
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
if (settingsCache->getPicDownloadHq()) {
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext())
cardIterator.next().value()->clearPixmapCacheMiss();
}
@ -792,11 +845,11 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
{
LoadStatus tempLoadStatus = NotLoaded;
if (!path.isEmpty())
tempLoadStatus = loadFromFile(path, tokens);
tempLoadStatus = loadFromFile(path);
if (tempLoadStatus == Ok) {
SetList allSets;
QHashIterator<QString, CardSet *> setsIterator(setHash);
QHashIterator<QString, CardSet *> setsIterator(sets);
while (setsIterator.hasNext())
allSets.append(setsIterator.next().value());
allSets.sortByKey();
@ -828,7 +881,7 @@ void CardDatabase::loadTokenDatabase()
QStringList CardDatabase::getAllColors() const
{
QSet<QString> colors;
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) {
const QStringList &cardColors = cardIterator.next().value()->getColors();
if (cardColors.isEmpty())
@ -843,7 +896,7 @@ QStringList CardDatabase::getAllColors() const
QStringList CardDatabase::getAllMainCardTypes() const
{
QSet<QString> types;
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext())
types.insert(cardIterator.next().value()->getMainCardType());
return types.toList();

View file

@ -95,6 +95,13 @@ private:
CardDatabase *db;
QString name;
/*
* The name without punctuation or capitalization, for better card tag name
* recognition.
*/
QString simpleName;
bool isToken;
SetList sets;
QString manacost;
@ -103,6 +110,7 @@ private:
QString text;
QStringList colors;
int loyalty;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muIds;
bool cipt;
int tableRow;
@ -121,6 +129,8 @@ public:
bool _cipt = false,
int _tableRow = 0,
const SetList &_sets = SetList(),
const QStringMap &_customPicURLs = QStringMap(),
const QStringMap &_customPicURLsHq = QStringMap(),
MuidMap muids = MuidMap());
~CardInfo();
const QString &getName() const { return name; }
@ -138,12 +148,16 @@ public:
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
const QStringList &getColors() const { return colors; }
QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
QString getCustomPicURLHq(const QString &set) const { return customPicURLsHq.value(set); }
int getMuId(const QString &set) const { return muIds.value(set); }
QString getMainCardType() const;
QString getCorrectedName() const;
int getTableRow() const { return tableRow; }
void setTableRow(int _tableRow) { tableRow = _tableRow; }
void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); }
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
void addToSet(CardSet *set);
QPixmap *loadPixmap();
@ -153,6 +167,12 @@ public:
void imageLoaded(const QImage &image);
CardSet *getPreferredSet();
int getPreferredMuId();
/**
* Simplify a name to have no punctuation and lowercase all letters, for
* less strict name-matching.
*/
static QString simplifyName(const QString &name);
public slots:
void updatePixmapCache();
signals:
@ -162,11 +182,27 @@ signals:
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
typedef QHash<QString, CardInfo *> CardNameMap;
typedef QHash<QString, CardSet *> SetNameMap;
class CardDatabase : public QObject {
Q_OBJECT
protected:
QHash<QString, CardInfo *> cardHash;
QHash<QString, CardSet *> setHash;
/*
* The cards, indexed by name.
*/
CardNameMap cards;
/**
* The cards, indexed by their simple name.
*/
CardNameMap simpleNameCards;
/*
* The sets, indexed by short name.
*/
SetNameMap sets;
CardInfo *noCard;
QThread *pictureLoaderThread;
@ -176,6 +212,8 @@ private:
static const int versionNeeded;
void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml);
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
public:
CardDatabase(QObject *parent = 0);
~CardDatabase();
@ -183,10 +221,17 @@ public:
void addCard(CardInfo *card);
void removeCard(CardInfo *card);
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
/*
* Get a card by its simple name. The name will be simplified in this
* function, so you don't need to simplify it beforehand.
*/
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
CardSet *getSet(const QString &setName);
QList<CardInfo *> getCardList() const { return cardHash.values(); }
QList<CardInfo *> getCardList() const { return cards.values(); }
SetList getSetList() const;
LoadStatus loadFromFile(const QString &fileName, bool tokens = false);
LoadStatus loadFromFile(const QString &fileName);
bool saveToFile(const QString &fileName, bool tokens = false);
QStringList getAllColors() const;
QStringList getAllMainCardTypes() const;

View file

@ -68,14 +68,16 @@ QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation,
void CardDatabaseModel::updateCardList()
{
beginResetModel();
for (int i = 0; i < cardList.size(); ++i)
disconnect(cardList[i], 0, this, 0);
cardList = db->getCardList();
for (int i = 0; i < cardList.size(); ++i)
connect(cardList[i], SIGNAL(cardInfoChanged(CardInfo *)), this, SLOT(cardInfoChanged(CardInfo *)));
reset();
endResetModel();
}
void CardDatabaseModel::cardInfoChanged(CardInfo *card)

View file

@ -81,7 +81,7 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidge
} else
setFixedWidth(250);
setCard(db->getCard(cardName));
setCard(getCard(cardName));
setMinimized(settingsCache->getCardInfoMinimized());
}
@ -166,7 +166,7 @@ void CardInfoWidget::setCard(CardInfo *card)
void CardInfoWidget::setCard(const QString &cardName)
{
setCard(db->getCard(cardName));
setCard(getCard(cardName));
}
void CardInfoWidget::setCard(AbstractCardItem *card)
@ -176,7 +176,11 @@ void CardInfoWidget::setCard(AbstractCardItem *card)
void CardInfoWidget::clear()
{
setCard(db->getCard());
setCard(getCard());
}
CardInfo *CardInfoWidget::getCard(const QString &cardName) {
return db->getCardBySimpleName(cardName);
}
void CardInfoWidget::updatePixmap()
@ -188,7 +192,7 @@ void CardInfoWidget::updatePixmap()
if (resizedPixmap)
cardPicture->setPixmap(*resizedPixmap);
else
cardPicture->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
}
void CardInfoWidget::retranslateUi()

View file

@ -42,6 +42,11 @@ private:
CardInfo *info;
void setMinimized(int _minimized);
/*
* Wrapper around db->getCardBySimpleName.
*/
CardInfo *getCard(const QString &cardName = QString());
public:
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
void retranslateUi();

View file

@ -233,7 +233,8 @@ CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPoin
void CardItem::deleteDragItem()
{
dragItem->deleteLater();
if(dragItem)
dragItem->deleteLater();
dragItem = NULL;
}

View file

@ -30,6 +30,8 @@ DeckListModel::~DeckListModel()
void DeckListModel::rebuildTree()
{
beginResetModel();
root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
@ -55,7 +57,7 @@ void DeckListModel::rebuildTree()
}
}
reset();
endResetModel();
}
int DeckListModel::rowCount(const QModelIndex &parent) const
@ -470,13 +472,7 @@ void DeckListModel::printDeckList(QPrinter *printer)
doc.print(printer);
}
void DeckListModel::pricesUpdated(InnerDecklistNode *node)
void DeckListModel::pricesUpdated()
{
if (!node)
node = root;
if (node->isEmpty())
return;
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
emit layoutChanged();
}

View file

@ -51,7 +51,7 @@ public:
void cleanList();
DeckLoader *getDeckList() const { return deckList; }
void setDeckList(DeckLoader *_deck);
void pricesUpdated(InnerDecklistNode *node = 0);
void pricesUpdated();
private:
DeckLoader *deckList;
InnerDecklistNode *root;

View file

@ -7,8 +7,14 @@
#include <QMessageBox>
#include <QDesktopServices>
DeckStatsInterface::DeckStatsInterface(QObject *parent)
: QObject(parent)
#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif
DeckStatsInterface::DeckStatsInterface(
CardDatabase &_cardDatabase,
QObject *parent
) : QObject(parent), cardDatabase(_cardDatabase)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
@ -39,15 +45,62 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
deleteLater();
}
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
{
DeckList deckWithoutTokens;
copyDeckWithoutTokens(*deck, deckWithoutTokens);
#if QT_VERSION < 0x050000
QUrl params;
params.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
data->append(params.encodedQuery());
#else
QUrl params;
QUrlQuery urlQuery;
urlQuery.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
params.setQuery(urlQuery);
data->append(params.query(QUrl::EncodeReserved));
#endif
}
void DeckStatsInterface::analyzeDeck(DeckList *deck)
{
QUrl params;
params.addQueryItem("deck", deck->writeToString_Plain());
QByteArray data;
data.append(params.encodedQuery());
getAnalyzeRequestData(deck, &data);
QNetworkRequest request(QUrl("http://deckstats.net/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
manager->post(request, data);
}
struct CopyIfNotAToken {
CardDatabase &cardDatabase;
DeckList &destination;
CopyIfNotAToken(
CardDatabase &_cardDatabase,
DeckList &_destination
) : cardDatabase(_cardDatabase), destination(_destination) {};
void operator()(
const InnerDecklistNode *node,
const DecklistCardNode *card
) const {
if (!cardDatabase.getCard(card->getName())->getIsToken()) {
DecklistCardNode *addedCard = destination.addCard(
card->getName(),
node->getName()
);
addedCard->setNumber(card->getNumber());
}
}
};
void DeckStatsInterface::copyDeckWithoutTokens(
const DeckList &source,
DeckList &destination
) {
CopyIfNotAToken copyIfNotAToken(cardDatabase, destination);
source.forEachCard(copyIfNotAToken);
}

View file

@ -1,8 +1,11 @@
#ifndef DECKSTATS_INTERFACE_H
#define DECKSTATS_INTERFACE_H
#include "carddatabase.h"
#include "decklist.h"
#include <QObject>
class QByteArray;
class QNetworkAccessManager;
class QNetworkReply;
class DeckList;
@ -11,10 +14,21 @@ class DeckStatsInterface : public QObject {
Q_OBJECT
private:
QNetworkAccessManager *manager;
CardDatabase &cardDatabase;
/**
* Deckstats doesn't recognize token cards, and instead tries to find the
* closest non-token card instead. So we construct a new deck which has no
* tokens.
*/
void copyDeckWithoutTokens(const DeckList &source, DeckList& destination);
private slots:
void queryFinished(QNetworkReply *reply);
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
public:
DeckStatsInterface(QObject *parent = 0);
DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
void analyzeDeck(DeckList *deck);
};

View file

@ -64,7 +64,11 @@ void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent)
: AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0)
{
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
}
DeckViewCard::~DeckViewCard()

View file

@ -79,8 +79,13 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents);
#else
chooseTokenView->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
#endif
connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex)));
if (predefinedTokens.isEmpty())

View file

@ -73,8 +73,13 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents);
#else
chooseTokenView->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
#endif
connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex)));
QAction *aAddToken = new QAction(tr("Add token"), this);
@ -108,7 +113,7 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
setWindowTitle(tr("Edit tokens"));
}
void DlgEditTokens::tokenSelectionChanged(const QModelIndex &current, const QModelIndex &previous)
void DlgEditTokens::tokenSelectionChanged(const QModelIndex &current, const QModelIndex & /* previous */)
{
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();

View file

@ -9,26 +9,53 @@
#include <QVBoxLayout>
#include <QGridLayout>
#include <QDialogButtonBox>
#include <QSettings>
#include <QCryptographicHash>
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent)
: QDialog(parent)
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &_allGameTypes, QWidget *parent)
: QDialog(parent),
allGameTypes(_allGameTypes)
{
QSettings settings;
settings.beginGroup("filter_games");
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games"));
unavailableGamesVisibleCheckBox->setChecked(
settings.value("unavailable_games_visible", false).toBool()
);
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games"));
passwordProtectedGamesVisibleCheckBox->setChecked(
settings.value("password_protected_games_visible", false).toBool()
);
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
gameNameFilterEdit = new QLineEdit;
gameNameFilterEdit->setText(
settings.value("game_name_filter", "").toString()
);
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
gameNameFilterLabel->setBuddy(gameNameFilterEdit);
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
creatorNameFilterEdit = new QLineEdit;
creatorNameFilterEdit->setText(
settings.value("creator_name_filter", "").toString()
);
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
while (gameTypesIterator.hasNext()) {
gameTypesIterator.next();
QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
temp->setChecked(
settings.value(
"game_type/" + hashGameType(gameTypesIterator.value()),
false
).toBool()
);
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
gameTypeFilterLayout->addWidget(temp);
}
@ -43,14 +70,18 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
maxPlayersFilterMinSpinBox = new QSpinBox;
maxPlayersFilterMinSpinBox->setMinimum(1);
maxPlayersFilterMinSpinBox->setMaximum(99);
maxPlayersFilterMinSpinBox->setValue(1);
maxPlayersFilterMinSpinBox->setValue(
settings.value("min_players", 1).toInt()
);
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
maxPlayersFilterMaxSpinBox = new QSpinBox;
maxPlayersFilterMaxSpinBox->setMinimum(1);
maxPlayersFilterMaxSpinBox->setMaximum(99);
maxPlayersFilterMaxSpinBox->setValue(99);
maxPlayersFilterMaxSpinBox->setValue(
settings.value("max_players", 99).toInt()
);
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
QGridLayout *maxPlayersFilterLayout = new QGridLayout;
@ -83,7 +114,7 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
hbox->addLayout(rightColumn);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
@ -94,6 +125,42 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
setWindowTitle(tr("Filter games"));
}
void DlgFilterGames::actOk() {
QSettings settings;
settings.beginGroup("filter_games");
settings.setValue(
"unavailable_games_visible",
unavailableGamesVisibleCheckBox->isChecked()
);
settings.setValue(
"password_protected_games_visible",
passwordProtectedGamesVisibleCheckBox->isChecked()
);
settings.setValue("game_name_filter", gameNameFilterEdit->text());
settings.setValue("creator_name_filter", creatorNameFilterEdit->text());
QMapIterator<int, QString> gameTypeIterator(allGameTypes);
QMapIterator<int, QCheckBox *> checkboxIterator(gameTypeFilterCheckBoxes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
checkboxIterator.next();
settings.setValue(
"game_type/" + hashGameType(gameTypeIterator.value()),
checkboxIterator.value()->isChecked()
);
}
settings.setValue("min_players", maxPlayersFilterMinSpinBox->value());
settings.setValue("max_players", maxPlayersFilterMaxSpinBox->value());
accept();
}
QString DlgFilterGames::hashGameType(const QString &gameType) const {
return QCryptographicHash::hash(gameType.toUtf8(), QCryptographicHash::Md5).toHex();
}
bool DlgFilterGames::getUnavailableGamesVisible() const
{
return unavailableGamesVisibleCheckBox->isChecked();

View file

@ -19,6 +19,16 @@ private:
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
QSpinBox *maxPlayersFilterMinSpinBox;
QSpinBox *maxPlayersFilterMaxSpinBox;
const QMap<int, QString> &allGameTypes;
/*
* The game type might contain special characters, so to use it in
* QSettings we just hash it.
*/
QString hashGameType(const QString &gameType) const;
private slots:
void actOk();
public:
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);

View file

@ -18,11 +18,13 @@
#include <QInputDialog>
#include <QSpinBox>
#include <QDialogButtonBox>
#include <QRadioButton>
#include <QDebug>
#include "carddatabase.h"
#include "dlg_settings.h"
#include "main.h"
#include "settingscache.h"
#include "priceupdater.h"
GeneralSettingsPage::GeneralSettingsPage()
{
@ -531,9 +533,30 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
priceTagsCheckBox = new QCheckBox;
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
priceTagSource0 = new QRadioButton;
priceTagSource1 = new QRadioButton;
switch(settingsCache->getPriceTagSource())
{
case AbstractPriceUpdater::DBPriceSource:
priceTagSource1->setChecked(true);
break;
case AbstractPriceUpdater::BLPPriceSource:
default:
priceTagSource0->setChecked(true);
break;
}
connect(priceTagSource0, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
connect(priceTagSource1, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
connect(this, SIGNAL(priceTagSourceChanged(int)), settingsCache, SLOT(setPriceTagSource(int)));
QGridLayout *generalGrid = new QGridLayout;
generalGrid->addWidget(priceTagsCheckBox, 0, 0);
generalGrid->addWidget(priceTagSource0, 1, 0);
generalGrid->addWidget(priceTagSource1, 2, 0);
generalGroupBox = new QGroupBox;
generalGroupBox->setLayout(generalGrid);
@ -546,10 +569,26 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
void DeckEditorSettingsPage::retranslateUi()
{
priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)"));
priceTagsCheckBox->setText(tr("Enable &price tag feature"));
priceTagSource0->setText(tr("using data from blacklotusproject.com"));
priceTagSource1->setText(tr("using data from deckbrew.com"));
generalGroupBox->setTitle(tr("General"));
}
void DeckEditorSettingsPage::radioPriceTagSourceClicked(bool checked)
{
if(!checked)
return;
int source=AbstractPriceUpdater::BLPPriceSource;
if(priceTagSource0->isChecked())
source=AbstractPriceUpdater::BLPPriceSource;
if(priceTagSource1->isChecked())
source=AbstractPriceUpdater::DBPriceSource;
emit priceTagSourceChanged(source);
}
MessagesSettingsPage::MessagesSettingsPage()
{
aAdd = new QAction(this);

View file

@ -15,6 +15,7 @@ class QCheckBox;
class QLabel;
class QCloseEvent;
class QSpinBox;
class QRadioButton;
class AbstractSettingsPage : public QWidget {
public:
@ -100,8 +101,13 @@ class DeckEditorSettingsPage : public AbstractSettingsPage {
public:
DeckEditorSettingsPage();
void retranslateUi();
private slots:
void radioPriceTagSourceClicked(bool checked);
signals:
void priceTagSourceChanged(int _priceTagSource);
private:
QCheckBox *priceTagsCheckBox;
QRadioButton *priceTagSource0, *priceTagSource1;
QGroupBox *generalGroupBox;
};

View file

@ -18,10 +18,10 @@ public:
virtual void enable() { enabled = true; nodeChanged(); }
virtual void disable() { enabled = false; nodeChanged(); }
virtual FilterTreeNode *parent() const { return NULL; }
virtual FilterTreeNode *nodeAt(int i) const { return NULL; }
virtual void deleteAt(int i) {}
virtual FilterTreeNode *nodeAt(int /* i */) const { return NULL; }
virtual void deleteAt(int /* i */) {}
virtual int childCount() const { return 0; }
virtual int childIndex(const FilterTreeNode *node) const { return -1; }
virtual int childIndex(const FilterTreeNode * /* node */) const { return -1; }
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
virtual QString text() const { return QString(textCStr()); }
virtual bool isLeaf() const { return false; }
@ -48,7 +48,7 @@ class FilterTreeBranch : public FilterTreeNode {
protected:
QList<T> childNodes;
public:
~FilterTreeBranch();
virtual ~FilterTreeBranch();
FilterTreeNode *nodeAt(int i) const;
void deleteAt(int i);
int childCount() const { return childNodes.size(); }
@ -102,6 +102,7 @@ public:
FilterItem(QString trm, FilterItemList *parent)
: p(parent), term(trm) {}
virtual ~FilterItem() {};
CardFilter::Attr attr() const { return p->attr(); }
CardFilter::Type type() const { return p->type; }

View file

@ -33,8 +33,11 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup
gameListView->header()->hideSection(1);
else
gameListProxyModel->setUnavailableGamesVisible(true);
#if QT_VERSION < 0x050000
gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents);
#else
gameListView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
#endif
filterButton = new QPushButton;
filterButton->setIcon(QIcon(":/resources/icon_search.svg"));
connect(filterButton, SIGNAL(clicked()), this, SLOT(actSetFilter()));
@ -81,12 +84,6 @@ void GameSelector::actSetFilter()
if (room)
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
DlgFilterGames dlg(gameTypeMap, this);
dlg.setUnavailableGamesVisible(gameListProxyModel->getUnavailableGamesVisible());
dlg.setPasswordProtectedGamesVisible(gameListProxyModel->getPasswordProtectedGamesVisible());
dlg.setGameNameFilter(gameListProxyModel->getGameNameFilter());
dlg.setCreatorNameFilter(gameListProxyModel->getCreatorNameFilter());
dlg.setGameTypeFilter(gameListProxyModel->getGameTypeFilter());
dlg.setMaxPlayersFilter(gameListProxyModel->getMaxPlayersFilterMin(), gameListProxyModel->getMaxPlayersFilterMax());
if (!dlg.exec())
return;

View file

@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name,
return result;
}
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft)
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, QString & /* reasonStr */, int & /* secondsLeft */)
{
return UnknownUser;
}

View file

@ -30,6 +30,7 @@
#include <QIcon>
#include <QDir>
#include <QDesktopServices>
#include <QDebug>
#include "main.h"
#include "window_main.h"
@ -55,6 +56,7 @@ QString translationPath = TRANSLATION_PATH;
QString translationPath = QString();
#endif
#if QT_VERSION < 0x050000
static void myMessageOutput(QtMsgType /*type*/, const char *msg)
{
QFile file("qdebug.txt");
@ -63,6 +65,16 @@ static void myMessageOutput(QtMsgType /*type*/, const char *msg)
out << msg << endl;
file.close();
}
#else
static void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
QFile file("qdebug.txt");
file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
QTextStream out(&file);
out << msg << endl;
file.close();
}
#endif
void installNewTranslator()
{
@ -87,11 +99,21 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
if (app.arguments().contains("--debug-output"))
{
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMessageOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
}
#ifdef Q_OS_WIN
app.addLibraryPath(app.applicationDirPath() + "/plugins");
#endif
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice.de");
@ -114,8 +136,12 @@ int main(int argc, char *argv[])
installNewTranslator();
qsrand(QDateTime::currentDateTime().toTime_t());
#if QT_VERSION < 0x050000
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
const QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
if (!db->getLoadSuccess())
if (db->loadCardDatabase(dataDir + "/cards.xml"))
settingsCache->setCardDatabasePath(dataDir + "/cards.xml");
@ -133,7 +159,9 @@ int main(int argc, char *argv[])
QDir().mkpath(dataDir + "/pics");
settingsCache->setPicsPath(dataDir + "/pics");
}
if (!QDir().mkpath(settingsCache->getPicsPath() + "/CUSTOM"))
qDebug() << "Could not create " + settingsCache->getPicsPath().toUtf8() + "/CUSTOM. Will fall back on default card images.";
#ifdef Q_OS_MAC
if(settingsCache->getHandBgPath().isEmpty() &&
settingsCache->getStackBgPath().isEmpty() &&

View file

@ -13,7 +13,11 @@ PileZone::PileZone(Player *_p, const QString &_name, bool _isShufflable, bool _c
: CardZone(_p, _name, false, _isShufflable, _contentsKnown, parent)
{
setCacheMode(DeviceCoordinateCache); // Do not move this line to the parent constructor!
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
setCursor(Qt::OpenHandCursor);
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));

View file

@ -774,7 +774,13 @@ void Player::actViewLibrary()
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);
int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("View top cards of library"), tr("Number of cards:"), defaultNumberTopCards, 1, 2000000000, 1, &ok);
if (ok) {
defaultNumberTopCards = number;
static_cast<GameScene *>(scene())->toggleZoneView(this, "deck", number);
@ -829,7 +835,13 @@ void Player::actMulligan()
void Player::actDrawCards()
{
int number = QInputDialog::getInteger(0, tr("Draw cards"), tr("Number:"));
int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Draw cards"), tr("Number:"));
if (number) {
Command_DrawCards cmd;
cmd.set_number(number);
@ -844,8 +856,14 @@ void Player::actUndoDraw()
void Player::actMoveTopCardsToGrave()
{
int number = QInputDialog::getInteger(0, tr("Move top cards to grave"), tr("Number:"));
if (!number)
int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to grave"), tr("Number:"));
if (!number)
return;
const int maxCards = zones.value("deck")->getCards().size();
@ -867,8 +885,14 @@ void Player::actMoveTopCardsToGrave()
void Player::actMoveTopCardsToExile()
{
int number = QInputDialog::getInteger(0, tr("Move top cards to exile"), tr("Number:"));
if (!number)
int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to exile"), tr("Number:"));
if (!number)
return;
const int maxCards = zones.value("deck")->getCards().size();
@ -914,7 +938,13 @@ void Player::actUntapAll()
void Player::actRollDie()
{
bool ok;
int sides = QInputDialog::getInteger(0, tr("Roll die"), tr("Number of sides:"), 20, 2, 1000, 1, &ok);
int sides =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Roll die"), tr("Number of sides:"), 20, 2, 1000, 1, &ok);
if (ok) {
Command_RollDie cmd;
cmd.set_sides(sides);
@ -929,6 +959,10 @@ void Player::actCreateToken()
return;
lastTokenName = dlg.getName();
if (CardInfo *correctedCard = db->getCardBySimpleName(lastTokenName, false)) {
lastTokenName = correctedCard->getName();
}
lastTokenColor = dlg.getColor();
lastTokenPT = dlg.getPT();
lastTokenAnnotation = dlg.getAnnotation();
@ -2022,7 +2056,13 @@ void Player::actCardCounterTrigger()
case 11: {
bool ok;
dialogSemaphore = true;
int number = QInputDialog::getInteger(0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok);
int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok);
dialogSemaphore = false;
if (clearCardsToDelete())
return;

View file

@ -72,7 +72,11 @@ PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient
setColumnCount(6);
setHeaderHidden(true);
setRootIsDecorated(false);
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
retranslateUi();
}
@ -174,5 +178,5 @@ void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &ind
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
userContextMenu->showContextMenu(pos, userName, userLevel, playerId);
userContextMenu->showContextMenu(pos, userName, userLevel, true, playerId);
}

View file

@ -4,25 +4,46 @@
*/
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMessageBox>
#include "qt-json/json.h"
#include "priceupdater.h"
#include "main.h"
#include "carddatabase.h"
#if QT_VERSION < 0x050000
// for Qt::escape()
#include <QtGui/qtextdocument.h>
#endif
/**
* Constructor.
*
* @param _deck deck.
*/
PriceUpdater::PriceUpdater(const DeckList *_deck)
AbstractPriceUpdater::AbstractPriceUpdater(const DeckList *_deck)
{
nam = new QNetworkAccessManager(this);
deck = _deck;
}
// blacklotusproject.com
/**
* Constructor.
*
* @param _deck deck.
*/
BLPPriceUpdater::BLPPriceUpdater(const DeckList *_deck)
: AbstractPriceUpdater(_deck)
{
}
/**
* Update the prices of the cards in deckList.
*/
void PriceUpdater::updatePrices()
void BLPPriceUpdater::updatePrices()
{
QString q = "http://blacklotusproject.com/json/?cards=";
QStringList cards = deck->getCardList();
@ -38,7 +59,7 @@ void PriceUpdater::updatePrices()
/**
* Called when the download of the json file with the prices is finished.
*/
void PriceUpdater::downloadFinished()
void BLPPriceUpdater::downloadFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
bool ok;
@ -82,3 +103,188 @@ void PriceUpdater::downloadFinished()
deleteLater();
emit finishedUpdate();
}
// deckbrew.com
/**
* Constructor.
*
* @param _deck deck.
*/
DBPriceUpdater::DBPriceUpdater(const DeckList *_deck)
: AbstractPriceUpdater(_deck)
{
}
/**
* Update the prices of the cards in deckList.
*/
void DBPriceUpdater::updatePrices()
{
QString base = "https://api.deckbrew.com/mtg/cards", q = "";
QStringList cards = deck->getCardList();
muidMap.clear();
urls.clear();
CardInfo * card;
int muid;
SetList sets;
bool bNotFirst=false;
for (int i = 0; i < cards.size(); ++i) {
card = db->getCard(cards[i], false);
sets = card->getSets();
for(int j = 0; j < sets.size(); ++j)
{
muid=card->getMuId(sets[j]->getShortName());
if (!muid) {
continue;
}
//qDebug() << "muid " << muid << " card: " << cards[i] << endl;
if(bNotFirst)
{
q += QString("&m=%1").arg(muid);
} else {
q += QString("?m=%1").arg(muid);
bNotFirst = true;
}
muidMap.insert(muid, cards[i]);
if(q.length() > 240)
{
urls.append(base + q);
bNotFirst=false;
q = "";
}
}
}
if(q.length() > 0)
urls.append(base + q);
requestNext();
}
void DBPriceUpdater::requestNext()
{
if(urls.empty())
return;
QUrl url(urls.takeFirst(), QUrl::TolerantMode);
//qDebug() << "request prices from: " << url.toString() << endl;
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
/**
* Called when the download of the json file with the prices is finished.
*/
void DBPriceUpdater::downloadFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
bool ok;
QString tmp = QString(reply->readAll());
// Errors are incapsulated in an object, check for them first
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
if (!ok) {
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
if(resultMap.contains("errors"))
{
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices:") +
"<br/>" +
#if QT_VERSION < 0x050000
Qt::escape(resultMap["errors"].toList().first().toString())
#else
resultMap["errors"].toList().first().toString().toHtmlEscaped()
#endif
);
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
// Good results are a list
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
if (!ok) {
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
QMap<QString, float> cardsPrice;
QListIterator<QVariant> it(resultList);
while (it.hasNext()) {
QVariantMap cardMap = it.next().toMap();
// get sets list
QList<QVariant> editions = cardMap.value("editions").toList();
foreach (QVariant ed, editions)
{
// retrieve card name "as we know it" from the muid
QVariantMap edition = ed.toMap();
QString set = edition.value("set_id").toString();
int muid = edition.value("multiverse_id").toString().toInt();
if(!muidMap.contains(muid))
continue;
QString name=muidMap.value(muid);
// Prices are in USD cents
float price = edition.value("price").toMap().value("median").toString().toFloat() / 100;
//qDebug() << "card " << name << " set " << set << " price " << price << endl;
/**
* Make sure Masters Edition (MED) isn't the set, as it doesn't
* physically exist. Also check the price to see that the cheapest set
* ends up as the final price.
*/
if (set != "MED" && price > 0 && (!cardsPrice.contains(name) || cardsPrice.value(name) > price))
cardsPrice.insert(name, price);
}
}
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
float price = cardsPrice[currentCard->getName()];
if(price > 0)
currentCard->setPrice(price);
}
}
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}

View file

@ -1,28 +1,57 @@
#ifndef PRICEUPDATER_H
#define PRICEUPDATER_H
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include "decklist.h"
class QNetworkAccessManager;
// If we don't typedef this, won't compile on OS X < 10.9
typedef QMap<int, QString> MuidStringMap;
/**
* Price Updater.
*
* @author Marcio Ribeiro <mmr@b1n.org>
*/
class PriceUpdater : public QObject
class AbstractPriceUpdater : public QWidget
{
Q_OBJECT
private:
public:
enum PriceSource { BLPPriceSource, DBPriceSource };
protected:
const DeckList *deck;
QNetworkAccessManager *nam;
signals:
void finishedUpdate();
private slots:
void downloadFinished();
protected slots:
virtual void downloadFinished() = 0;
public:
PriceUpdater(const DeckList *deck);
void updatePrices();
AbstractPriceUpdater(const DeckList *deck);
virtual void updatePrices() = 0;
};
class BLPPriceUpdater : public AbstractPriceUpdater
{
Q_OBJECT
protected:
virtual void downloadFinished();
public:
BLPPriceUpdater(const DeckList *deck);
virtual void updatePrices();
};
class DBPriceUpdater : public AbstractPriceUpdater
{
Q_OBJECT
protected:
MuidStringMap muidMap;
QList<QString> urls;
protected:
virtual void downloadFinished();
void requestNext();
public:
DBPriceUpdater(const DeckList *deck);
virtual void updatePrices();
};
#endif

View file

@ -553,7 +553,7 @@ int Json::nextToken(const QString &json, int &index)
QChar c = json[index];
index++;
switch(c.toAscii())
switch(c.toLatin1())
{
case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose;

View file

@ -15,7 +15,7 @@ RemoteClient::RemoteClient(QObject *parent)
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), messageLength(0)
{
timer = new QTimer(this);
timer->setInterval(9000);
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(ping()));
socket = new QTcpSocket(this);

View file

@ -258,8 +258,11 @@ void RemoteDeckList_TreeModel::deckListFinished(const Response &r)
{
const Response_DeckList &resp = r.GetExtension(Response_DeckList::ext);
beginResetModel();
root->clearTree();
reset();
endResetModel();
ServerInfo_DeckStorage_TreeItem tempRoot;
tempRoot.set_id(0);
@ -280,7 +283,11 @@ RemoteDeckList_TreeWidget::RemoteDeckList_TreeWidget(AbstractClient *_client, QW
setModel(proxyModel);
connect(treeModel, SIGNAL(treeRefreshed()), this, SLOT(expandAll()));
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
setUniformRowHeights(true);
setSortingEnabled(true);
proxyModel->sort(0, Qt::AscendingOrder);

View file

@ -278,7 +278,11 @@ RemoteReplayList_TreeWidget::RemoteReplayList_TreeWidget(AbstractClient *_client
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
setModel(proxyModel);
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
header()->setStretchLastSection(false);
setUniformRowHeights(true);
setSortingEnabled(true);

View file

@ -43,7 +43,7 @@ void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
update();
}
void ReplayTimelineWidget::paintEvent(QPaintEvent *event)
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);
painter.drawRect(0, 0, width() - 1, height() - 1);

View file

@ -45,6 +45,7 @@ SettingsCache::SettingsCache()
soundPath = settings->value("sound/path").toString();
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt();
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
}
@ -247,6 +248,12 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
emit priceTagFeatureChanged(priceTagFeature);
}
void SettingsCache::setPriceTagSource(int _priceTagSource)
{
priceTagSource = _priceTagSource;
settings->setValue("deckeditor/pricetagsource", priceTagSource);
}
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)
{
ignoreUnregisteredUsers = _ignoreUnregisteredUsers;

View file

@ -53,6 +53,7 @@ private:
bool soundEnabled;
QString soundPath;
bool priceTagFeature;
int priceTagSource;
bool ignoreUnregisteredUsers;
QString picUrl;
QString picUrlHq;
@ -87,6 +88,7 @@ public:
bool getSoundEnabled() const { return soundEnabled; }
QString getSoundPath() const { return soundPath; }
bool getPriceTagFeature() const { return priceTagFeature; }
int getPriceTagSource() const { return priceTagSource; }
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
QString getPicUrl() const { return picUrl; }
QString getPicUrlHq() const { return picUrlHq; }
@ -121,6 +123,7 @@ public slots:
void setSoundEnabled(int _soundEnabled);
void setSoundPath(const QString &_soundPath);
void setPriceTagFeature(int _priceTagFeature);
void setPriceTagSource(int _priceTagSource);
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
void setPicUrl(const QString &_picUrl);
void setPicUrlHq(const QString &_picUrlHq);

View file

@ -33,8 +33,13 @@ void SoundEngine::soundEnabledChanged()
if (settingsCache->getSoundEnabled()) {
qDebug("SoundEngine: enabling sound");
QAudioFormat format;
#if QT_VERSION < 0x050000
format.setFrequency(44100);
format.setChannels(1);
#else
format.setSampleRate(44100);
format.setChannelCount(1);
#endif
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);

View file

@ -31,6 +31,7 @@ public:
virtual QString getTabText() const = 0;
virtual void retranslateUi() = 0;
virtual void closeRequest() { }
virtual void tabActivated() { }
};
#endif

View file

@ -134,7 +134,11 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
deckView->setUniformRowHeights(true);
deckView->setSortingEnabled(true);
deckView->sortByColumn(1, Qt::AscendingOrder);
#if QT_VERSION < 0x050000
deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
deckView->installEventFilter(&deckViewKeySignals);
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
@ -508,7 +512,10 @@ void TabDeckEditor::actPrintDeck()
void TabDeckEditor::actAnalyzeDeck()
{
DeckStatsInterface *interface = new DeckStatsInterface(this); // it deletes itself when done
DeckStatsInterface *interface = new DeckStatsInterface(
*databaseModel->getDatabase(),
this
); // it deletes itself when done
interface->analyzeDeck(deckModel->getDeckList());
}
@ -639,12 +646,25 @@ void TabDeckEditor::actDecrement()
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
{
aUpdatePrices->setVisible(enabled);
deckModel->pricesUpdated();
}
void TabDeckEditor::actUpdatePrices()
{
aUpdatePrices->setDisabled(true);
PriceUpdater *up = new PriceUpdater(deckModel->getDeckList());
AbstractPriceUpdater *up;
switch(settingsCache->getPriceTagSource())
{
case AbstractPriceUpdater::DBPriceSource:
up = new DBPriceUpdater(deckModel->getDeckList());
break;
case AbstractPriceUpdater::BLPPriceSource:
default:
up = new BLPPriceUpdater(deckModel->getDeckList());
break;
}
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
up->updatePrices();
}

View file

@ -38,7 +38,11 @@ TabDeckStorage::TabDeckStorage(TabSupervisor *_tabSupervisor, AbstractClient *_c
localDirView->setColumnHidden(1, true);
localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0));
localDirView->setSortingEnabled(true);
#if QT_VERSION < 0x050000
localDirView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
localDirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
localDirView->header()->setSortIndicator(0, Qt::AscendingOrder);
leftToolBar = new QToolBar;

View file

@ -254,7 +254,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
// Create list: event number -> time [ms]
// Distribute simultaneous events evenly across 1 second.
int lastEventTimestamp = -1;
unsigned int lastEventTimestamp = 0;
const int eventCount = replay->event_list_size();
for (int i = 0; i < eventCount; ++i) {
int j = i + 1;

View file

@ -49,6 +49,12 @@ void TabMessage::retranslateUi()
aLeave->setText(tr("&Leave"));
}
void TabMessage::tabActivated()
{
if(!sayEdit->hasFocus())
sayEdit->setFocus();
}
QString TabMessage::getUserName() const
{
return QString::fromStdString(otherUserInfo->name());

View file

@ -34,6 +34,7 @@ public:
~TabMessage();
void retranslateUi();
void closeRequest();
void tabActivated();
QString getUserName() const;
QString getTabText() const;

View file

@ -36,7 +36,11 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client)
localDirView->setColumnHidden(1, true);
localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0));
localDirView->setSortingEnabled(true);
#if QT_VERSION < 0x050000
localDirView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
localDirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
localDirView->header()->setSortIndicator(0, Qt::AscendingOrder);
leftToolBar = new QToolBar;
@ -198,7 +202,7 @@ void TabReplays::actDownload()
client->sendCommand(pend);
}
void TabReplays::downloadFinished(const Response &r, const CommandContainer &commandContainer, const QVariant &extraData)
void TabReplays::downloadFinished(const Response &r, const CommandContainer & /* commandContainer */, const QVariant &extraData)
{
if (r.response_code() != Response::RespOk)
return;

View file

@ -121,6 +121,12 @@ void TabRoom::closeRequest()
actLeaveRoom();
}
void TabRoom::tabActivated()
{
if(!sayEdit->hasFocus())
sayEdit->setFocus();
}
QString TabRoom::sanitizeHtml(QString dirty) const
{
return dirty

View file

@ -64,6 +64,7 @@ public:
~TabRoom();
void retranslateUi();
void closeRequest();
void tabActivated();
void processRoomEvent(const RoomEvent &event);
int getRoomId() const { return roomId; }
const QMap<int, QString> &getGameTypes() const { return gameTypes; }

View file

@ -28,11 +28,17 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent)
roomList->setRootIsDecorated(false);
roomList->setColumnCount(4);
roomList->header()->setStretchLastSection(false);
#if QT_VERSION < 0x050000
roomList->header()->setResizeMode(0, QHeaderView::ResizeToContents);
roomList->header()->setResizeMode(1, QHeaderView::Stretch);
roomList->header()->setResizeMode(2, QHeaderView::ResizeToContents);
roomList->header()->setResizeMode(3, QHeaderView::ResizeToContents);
#else
roomList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
roomList->header()->setSectionResizeMode(1, QHeaderView::Stretch);
roomList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
#endif
joinButton = new QPushButton;
connect(joinButton, SIGNAL(clicked()), this, SLOT(joinClicked()));
QHBoxLayout *buttonLayout = new QHBoxLayout;

View file

@ -76,7 +76,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
}
TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent)
: QTabWidget(parent), userInfo(0), client(_client), tabUserLists(0), tabServer(0), tabDeckStorage(0), tabAdmin(0), tabReplays(0)
: QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0)
{
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
setElideMode(Qt::ElideRight);
@ -479,6 +479,7 @@ void TabSupervisor::updateCurrent(int index)
tab->setContentsChanged(false);
}
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
tab->tabActivated();
} else
emit setMenu();
}

View file

@ -28,7 +28,11 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent)
currentMinimumWidth = minWidth;
setCacheMode(DeviceCoordinateCache);
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
}
void TableZone::updateBgPixmap()

View file

@ -102,7 +102,7 @@ void UserContextMenu::banUser_dialogFinished()
client->sendCommand(client->prepareModeratorCommand(cmd));
}
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId)
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online, int playerId)
{
aUserName->setText(userName);
@ -132,7 +132,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName
menu->addAction(aBan);
}
bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name());
aChat->setEnabled(anotherUser);
aDetails->setEnabled(online);
aChat->setEnabled(anotherUser && online);
aShowGames->setEnabled(anotherUser);
aAddToBuddyList->setEnabled(anotherUser);
aRemoveFromBuddyList->setEnabled(anotherUser);

View file

@ -36,7 +36,7 @@ private slots:
public:
UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0);
void retranslateUi();
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId = -1);
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online = true, int playerId = -1);
};
#endif

View file

@ -216,7 +216,11 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL
userTree = new QTreeWidget;
userTree->setColumnCount(3);
#if QT_VERSION < 0x050000
userTree->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
userTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
userTree->setHeaderHidden(true);
userTree->setRootIsDecorated(false);
userTree->setIconSize(QSize(20, 12));
@ -307,8 +311,9 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/)
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
{
const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo();
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()));
bool online = index.sibling(index.row(), 0).data(Qt::UserRole + 1).toBool();
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), online);
}
void UserList::sortItems()

View file

@ -28,7 +28,20 @@ SET(common_SOURCES
sfmt/SFMT.c
)
INCLUDE(${QT_USE_FILE})
set(ORACLE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
# Include directories
INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
endif()
INCLUDE_DIRECTORIES(pb)
INCLUDE_DIRECTORIES(sfmt)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})

View file

@ -10,26 +10,26 @@
#ifdef QT_GUI_LIB
inline QColor convertColorToQColor(const color &c)
{
return QColor(c.r(), c.g(), c.b());
return QColor(c.r(), c.g(), c.b());
}
inline color convertQColorToColor(const QColor &c)
{
color result;
result.set_r(c.red());
result.set_g(c.green());
result.set_b(c.blue());
return result;
color result;
result.set_r(c.red());
result.set_g(c.green());
result.set_b(c.blue());
return result;
}
#endif
inline color makeColor(int r, int g, int b)
{
color result;
result.set_r(r);
result.set_g(g);
result.set_b(b);
return result;
color result;
result.set_r(r);
result.set_g(g);
result.set_b(b);
return result;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -23,152 +23,175 @@ class InnerDecklistNode;
class SideboardPlan {
private:
QString name;
QList<MoveCard_ToZone> moveList;
QString name;
QList<MoveCard_ToZone> moveList;
public:
SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
QString getName() const { return name; }
const QList<MoveCard_ToZone> &getMoveList() const { return moveList; }
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
QString getName() const { return name; }
const QList<MoveCard_ToZone> &getMoveList() const { return moveList; }
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
};
enum DeckSortMethod { ByNumber, ByName, ByPrice };
class AbstractDecklistNode {
protected:
InnerDecklistNode *parent;
DeckSortMethod sortMethod;
InnerDecklistNode *parent;
DeckSortMethod sortMethod;
public:
AbstractDecklistNode(InnerDecklistNode *_parent = 0);
virtual ~AbstractDecklistNode() { }
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
virtual QString getName() const = 0;
InnerDecklistNode *getParent() const { return parent; }
int depth() const;
virtual int height() const = 0;
virtual bool compare(AbstractDecklistNode *other) const = 0;
AbstractDecklistNode(InnerDecklistNode *_parent = 0);
virtual ~AbstractDecklistNode() { }
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
virtual QString getName() const = 0;
InnerDecklistNode *getParent() const { return parent; }
int depth() const;
virtual int height() const = 0;
virtual bool compare(AbstractDecklistNode *other) const = 0;
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
};
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *> {
private:
QString name;
class compareFunctor;
QString name;
class compareFunctor;
public:
InnerDecklistNode(const QString &_name = QString(), InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent), name(_name) { }
InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = 0);
virtual ~InnerDecklistNode();
void setSortMethod(DeckSortMethod method);
QString getName() const { return name; }
void setName(const QString &_name) { name = _name; }
static QString visibleNameFromName(const QString &_name);
virtual QString getVisibleName() const;
void clearTree();
AbstractDecklistNode *findChild(const QString &name);
int height() const;
int recursiveCount(bool countTotalCards = false) const;
InnerDecklistNode(const QString &_name = QString(), InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent), name(_name) { }
InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = 0);
virtual ~InnerDecklistNode();
void setSortMethod(DeckSortMethod method);
QString getName() const { return name; }
void setName(const QString &_name) { name = _name; }
static QString visibleNameFromName(const QString &_name);
virtual QString getVisibleName() const;
void clearTree();
AbstractDecklistNode *findChild(const QString &name);
int height() const;
int recursiveCount(bool countTotalCards = false) const;
float recursivePrice(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool comparePrice(AbstractDecklistNode *other) const;
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
bool compare(AbstractDecklistNode *other) const;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool comparePrice(AbstractDecklistNode *other) const;
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
bool readElement(QXmlStreamReader *xml);
void writeElement(QXmlStreamWriter *xml);
bool readElement(QXmlStreamReader *xml);
void writeElement(QXmlStreamWriter *xml);
};
class AbstractDecklistCardNode : public AbstractDecklistNode {
public:
AbstractDecklistCardNode(InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent) { }
virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0;
virtual QString getName() const = 0;
virtual void setName(const QString &_name) = 0;
AbstractDecklistCardNode(InnerDecklistNode *_parent = 0) : AbstractDecklistNode(_parent) { }
virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0;
virtual QString getName() const = 0;
virtual void setName(const QString &_name) = 0;
virtual float getPrice() const = 0;
virtual void setPrice(const float _price) = 0;
float getTotalPrice() const { return getNumber() * getPrice(); }
int height() const { return 0; }
bool compare(AbstractDecklistNode *other) const;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool compareTotalPrice(AbstractDecklistNode *other) const;
int height() const { return 0; }
bool compare(AbstractDecklistNode *other) const;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool compareTotalPrice(AbstractDecklistNode *other) const;
bool readElement(QXmlStreamReader *xml);
void writeElement(QXmlStreamWriter *xml);
bool readElement(QXmlStreamReader *xml);
void writeElement(QXmlStreamWriter *xml);
};
class DecklistCardNode : public AbstractDecklistCardNode {
private:
QString name;
int number;
QString name;
int number;
float price;
public:
DecklistCardNode(const QString &_name = QString(), int _number = 1, float _price = 0, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(_price) { }
DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(0) { }
DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const { return number; }
void setNumber(int _number) { number = _number; }
QString getName() const { return name; }
void setName(const QString &_name) { name = _name; }
DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const { return number; }
void setNumber(int _number) { number = _number; }
QString getName() const { return name; }
void setName(const QString &_name) { name = _name; }
float getPrice() const { return price; }
void setPrice(const float _price) { price = _price; }
};
class DeckList : public QObject {
Q_OBJECT
Q_OBJECT
private:
QString name, comments;
QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
QString name, comments;
QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
signals:
void deckHashChanged();
void deckHashChanged();
public slots:
void setName(const QString &_name = QString()) { name = _name; }
void setComments(const QString &_comments = QString()) { comments = _comments; }
void setName(const QString &_name = QString()) { name = _name; }
void setComments(const QString &_comments = QString()) { comments = _comments; }
public:
DeckList();
DeckList(const DeckList &other);
DeckList(const QString &nativeString);
~DeckList();
QString getName() const { return name; }
QString getComments() const { return comments; }
QList<MoveCard_ToZone> getCurrentSideboardPlan();
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
const QMap<QString, SideboardPlan *> &getSideboardPlans() const { return sideboardPlans; }
DeckList();
DeckList(const DeckList &other);
DeckList(const QString &nativeString);
~DeckList();
QString getName() const { return name; }
QString getComments() const { return comments; }
QList<MoveCard_ToZone> getCurrentSideboardPlan();
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
const QMap<QString, SideboardPlan *> &getSideboardPlans() const { return sideboardPlans; }
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
bool loadFromXml(QXmlStreamReader *xml);
bool loadFromString_Native(const QString &nativeString);
QString writeToString_Native();
bool loadFromFile_Native(QIODevice *device);
bool saveToFile_Native(QIODevice *device);
bool loadFromStream_Plain(QTextStream &stream);
bool loadFromFile_Plain(QIODevice *device);
bool saveToStream_Plain(QTextStream &stream);
bool saveToFile_Plain(QIODevice *device);
QString writeToString_Plain();
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
bool loadFromXml(QXmlStreamReader *xml);
bool loadFromString_Native(const QString &nativeString);
QString writeToString_Native();
bool loadFromFile_Native(QIODevice *device);
bool saveToFile_Native(QIODevice *device);
bool loadFromStream_Plain(QTextStream &stream);
bool loadFromFile_Plain(QIODevice *device);
bool saveToStream_Plain(QTextStream &stream);
bool saveToFile_Plain(QIODevice *device);
QString writeToString_Plain();
void cleanList();
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
QStringList getCardList() const;
void cleanList();
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
QStringList getCardList() const;
int getSideboardSize() const;
QString getDeckHash() const { return deckHash; }
void updateDeckHash();
QString getDeckHash() const { return deckHash; }
void updateDeckHash();
InnerDecklistNode *getRoot() const { return root; }
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
InnerDecklistNode *getRoot() const { return root; }
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
/**
* Calls a given function object for each card in the deck. It must
* take a InnerDecklistNode* as its first argument and a
* DecklistCardNode* as its second.
*/
template <typename Callback>
void forEachCard(Callback &callback) const {
// Support for this is only possible if the internal structure
// doesn't get more complicated.
for (int i = 0; i < root->size(); i++) {
const InnerDecklistNode *node =
dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
const DecklistCardNode *card =
dynamic_cast<DecklistCardNode *>(
node->at(j)
);
callback(node, card);
}
}
}
};
#endif

View file

@ -4,10 +4,10 @@
int getPbExtension(const ::google::protobuf::Message &message)
{
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList;
message.GetReflection()->ListFields(message, &fieldList);
for (unsigned int j = 0; j < fieldList.size(); ++j)
if (fieldList[j]->is_extension())
return fieldList[j]->number();
return -1;
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList;
message.GetReflection()->ListFields(message, &fieldList);
for (unsigned int j = 0; j < fieldList.size(); ++j)
if (fieldList[j]->is_extension())
return fieldList[j]->number();
return -1;
}

View file

@ -2,9 +2,9 @@
#define GET_PB_EXTENSION_H
namespace google {
namespace protobuf {
class Message;
}
namespace protobuf {
class Message;
}
}
int getPbExtension(const ::google::protobuf::Message &message);

View file

@ -4,27 +4,27 @@
QVector<int> RNG_Abstract::makeNumbersVector(int n, int min, int max)
{
const int bins = max - min + 1;
QVector<int> result(bins);
for (int i = 0; i < n; ++i) {
int number = rand(min, max);
if ((number < min) || (number > max))
qDebug() << "rand(" << min << "," << max << ") returned " << number;
else
result[number - min]++;
}
return result;
const int bins = max - min + 1;
QVector<int> result(bins);
for (int i = 0; i < n; ++i) {
int number = rand(min, max);
if ((number < min) || (number > max))
qDebug() << "rand(" << min << "," << max << ") returned " << number;
else
result[number - min]++;
}
return result;
}
double RNG_Abstract::testRandom(const QVector<int> &numbers) const
{
int n = 0;
for (int i = 0; i < numbers.size(); ++i)
n += numbers[i];
double expected = (double) n / (double) numbers.size();
double chisq = 0;
for (int i = 0; i < numbers.size(); ++i)
chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected;
return chisq;
int n = 0;
for (int i = 0; i < numbers.size(); ++i)
n += numbers[i];
double expected = (double) n / (double) numbers.size();
double chisq = 0;
for (int i = 0; i < numbers.size(); ++i)
chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected;
return chisq;
}

View file

@ -5,12 +5,12 @@
#include <QVector>
class RNG_Abstract : public QObject {
Q_OBJECT
Q_OBJECT
public:
RNG_Abstract(QObject *parent = 0) : QObject(parent) { }
virtual unsigned int rand(int min, int max) = 0;
QVector<int> makeNumbersVector(int n, int min, int max);
double testRandom(const QVector<int> &numbers) const;
RNG_Abstract(QObject *parent = 0) : QObject(parent) { }
virtual unsigned int rand(int min, int max) = 0;
QVector<int> makeNumbersVector(int n, int min, int max);
double testRandom(const QVector<int> &numbers) const;
};
extern RNG_Abstract *rng;

View file

@ -11,10 +11,10 @@
#endif
RNG_SFMT::RNG_SFMT(QObject *parent)
: RNG_Abstract(parent)
: RNG_Abstract(parent)
{
// initialize the random number generator with a 32bit integer seed (timestamp)
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toTime_t());
// initialize the random number generator with a 32bit integer seed (timestamp)
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toTime_t());
}
/**
@ -32,11 +32,11 @@ unsigned int RNG_SFMT::rand(int min, int max) {
* There has been no use for negative random numbers with rand() though, so it's treated as error.
*/
if(min < 0) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: Got min " +
QString::number(min) + " < 0!\n").toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
throw std::invalid_argument(
QString("Invalid bounds for RNG: Got min " +
QString::number(min) + " < 0!\n").toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
// For complete fairness and equal timing, this should be a roll, but let's skip it anyway
@ -99,38 +99,38 @@ unsigned int RNG_SFMT::rand(int min, int max) {
*/
unsigned int RNG_SFMT::cdf(unsigned int min, unsigned int max)
{
// This all makes no sense if min > max, which should never happen.
if(min > max) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: min > max! Values were: min = " +
QString::number(min) + ", max = " +
QString::number(max)).toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
// This all makes no sense if min > max, which should never happen.
if(min > max) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: min > max! Values were: min = " +
QString::number(min) + ", max = " +
QString::number(max)).toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
// First compute the diameter (aka size, length) of the [min, max] interval
const unsigned int diameter = max - min + 1;
// First compute the diameter (aka size, length) of the [min, max] interval
const unsigned int diameter = max - min + 1;
// Compute how many buckets (each in size of the diameter) will fit into the
// universe.
// If the division has a remainder, the result is floored automatically.
const uint64_t buckets = UINT64_MAX / diameter;
// Compute how many buckets (each in size of the diameter) will fit into the
// universe.
// If the division has a remainder, the result is floored automatically.
const uint64_t buckets = UINT64_MAX / diameter;
// Compute the last valid random number. All numbers beyond have to be ignored.
// If there was no remainder in the previous step, limit is equal to UINT64_MAX.
const uint64_t limit = diameter * buckets;
// Compute the last valid random number. All numbers beyond have to be ignored.
// If there was no remainder in the previous step, limit is equal to UINT64_MAX.
const uint64_t limit = diameter * buckets;
uint64_t rand;
// To make the random number generation thread-safe, a mutex is created around
// the generation. Outside of the loop of course, to avoid lock/unlock overhead.
mutex.lock();
do {
rand = sfmt_genrand_uint64(&sfmt);
} while (rand >= limit);
mutex.unlock();
uint64_t rand;
// To make the random number generation thread-safe, a mutex is created around
// the generation. Outside of the loop of course, to avoid lock/unlock overhead.
mutex.lock();
do {
rand = sfmt_genrand_uint64(&sfmt);
} while (rand >= limit);
mutex.unlock();
// Now determine the bucket containing the SFMT() random number and after adding
// the lower bound, a random number from [min, max] can be returned.
return (unsigned int) (rand / buckets + min);
// Now determine the bucket containing the SFMT() random number and after adding
// the lower bound, a random number from [min, max] can be returned.
return (unsigned int) (rand / buckets + min);
}

View file

@ -26,15 +26,15 @@
*/
class RNG_SFMT : public RNG_Abstract {
Q_OBJECT
Q_OBJECT
private:
QMutex mutex;
sfmt_t sfmt;
// The discrete cumulative distribution function for the RNG
unsigned int cdf(unsigned int min, unsigned int max);
QMutex mutex;
sfmt_t sfmt;
// The discrete cumulative distribution function for the RNG
unsigned int cdf(unsigned int min, unsigned int max);
public:
RNG_SFMT(QObject *parent = 0);
unsigned int rand(int min, int max);
RNG_SFMT(QObject *parent = 0);
unsigned int rand(int min, int max);
};
#endif

View file

@ -36,18 +36,18 @@
#include <QDebug>
Server::Server(bool _threaded, QObject *parent)
: QObject(parent), threaded(_threaded), nextLocalGameId(0)
: QObject(parent), threaded(_threaded), nextLocalGameId(0)
{
qRegisterMetaType<ServerInfo_Game>("ServerInfo_Game");
qRegisterMetaType<ServerInfo_Room>("ServerInfo_Room");
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
qRegisterMetaType<CommandContainer>("CommandContainer");
qRegisterMetaType<Response>("Response");
qRegisterMetaType<GameEventContainer>("GameEventContainer");
qRegisterMetaType<IslMessage>("IslMessage");
qRegisterMetaType<Command_JoinGame>("Command_JoinGame");
connect(this, SIGNAL(sigSendIslMessage(IslMessage, int)), this, SLOT(doSendIslMessage(IslMessage, int)), Qt::QueuedConnection);
qRegisterMetaType<ServerInfo_Game>("ServerInfo_Game");
qRegisterMetaType<ServerInfo_Room>("ServerInfo_Room");
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
qRegisterMetaType<CommandContainer>("CommandContainer");
qRegisterMetaType<Response>("Response");
qRegisterMetaType<GameEventContainer>("GameEventContainer");
qRegisterMetaType<IslMessage>("IslMessage");
qRegisterMetaType<Command_JoinGame>("Command_JoinGame");
connect(this, SIGNAL(sigSendIslMessage(IslMessage, int)), this, SLOT(doSendIslMessage(IslMessage, int)), Qt::QueuedConnection);
}
Server::~Server()
@ -56,532 +56,532 @@ Server::~Server()
void Server::prepareDestroy()
{
// dirty :(
if (threaded) {
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
QMetaObject::invokeMethod(clients.at(i), "prepareDestroy", Qt::QueuedConnection);
clientsLock.unlock();
bool done = false;
class SleeperThread : public QThread
{
public:
static void msleep(unsigned long msecs) { QThread::usleep(msecs); }
};
// dirty :(
if (threaded) {
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
QMetaObject::invokeMethod(clients.at(i), "prepareDestroy", Qt::QueuedConnection);
clientsLock.unlock();
bool done = false;
class SleeperThread : public QThread
{
public:
static void msleep(unsigned long msecs) { QThread::usleep(msecs); }
};
do {
SleeperThread::msleep(10);
clientsLock.lockForRead();
if (clients.isEmpty())
done = true;
clientsLock.unlock();
} while (!done);
} else {
// no locking is needed in unthreaded mode
while (!clients.isEmpty())
clients.first()->prepareDestroy();
}
roomsLock.lockForWrite();
QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext())
delete roomIterator.next().value();
rooms.clear();
roomsLock.unlock();
do {
SleeperThread::msleep(10);
clientsLock.lockForRead();
if (clients.isEmpty())
done = true;
clientsLock.unlock();
} while (!done);
} else {
// no locking is needed in unthreaded mode
while (!clients.isEmpty())
clients.first()->prepareDestroy();
}
roomsLock.lockForWrite();
QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext())
delete roomIterator.next().value();
rooms.clear();
roomsLock.unlock();
}
void Server::setDatabaseInterface(Server_DatabaseInterface *_databaseInterface)
{
connect(this, SIGNAL(endSession(qint64)), _databaseInterface, SLOT(endSession(qint64)));
databaseInterfaces.insert(QThread::currentThread(), _databaseInterface);
connect(this, SIGNAL(endSession(qint64)), _databaseInterface, SLOT(endSession(qint64)));
databaseInterfaces.insert(QThread::currentThread(), _databaseInterface);
}
Server_DatabaseInterface *Server::getDatabaseInterface() const
{
return databaseInterfaces.value(QThread::currentThread());
return databaseInterfaces.value(QThread::currentThread());
}
AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reasonStr, int &secondsLeft)
{
if (name.size() > 35)
name = name.left(35);
Server_DatabaseInterface *databaseInterface = getDatabaseInterface();
QWriteLocker locker(&clientsLock);
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, reasonStr, secondsLeft);
if ((authState == NotLoggedIn) || (authState == UserIsBanned || authState == UsernameInvalid))
return authState;
ServerInfo_User data = databaseInterface->getUserData(name, true);
data.set_address(session->getAddress().toStdString());
name = QString::fromStdString(data.name()); // Compensate for case indifference
databaseInterface->lockSessionTables();
if (authState == PasswordRight) {
if (users.contains(name) || databaseInterface->userSessionExists(name)) {
qDebug("Login denied: would overwrite old session");
databaseInterface->unlockSessionTables();
return WouldOverwriteOldSession;
}
} else if (authState == UnknownUser) {
// Change user name so that no two users have the same names,
// don't interfere with registered user names though.
QString tempName = name;
int i = 0;
while (users.contains(tempName) || databaseInterface->userExists(tempName) || databaseInterface->userSessionExists(tempName))
tempName = name + "_" + QString::number(++i);
name = tempName;
data.set_name(name.toStdString());
}
users.insert(name, session);
qDebug() << "Server::loginUser:" << session << "name=" << name;
data.set_session_id(databaseInterface->startSession(name, session->getAddress()));
databaseInterface->unlockSessionTables();
usersBySessionId.insert(data.session_id(), session);
qDebug() << "session id:" << data.session_id();
session->setUserInfo(data);
Event_UserJoined event;
event.mutable_user_info()->CopyFrom(session->copyUserInfo(false));
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
delete se;
event.mutable_user_info()->CopyFrom(session->copyUserInfo(true, true, true));
locker.unlock();
se = Server_ProtocolHandler::prepareSessionEvent(event);
sendIsl_SessionEvent(*se);
delete se;
return authState;
if (name.size() > 35)
name = name.left(35);
Server_DatabaseInterface *databaseInterface = getDatabaseInterface();
QWriteLocker locker(&clientsLock);
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, reasonStr, secondsLeft);
if ((authState == NotLoggedIn) || (authState == UserIsBanned || authState == UsernameInvalid))
return authState;
ServerInfo_User data = databaseInterface->getUserData(name, true);
data.set_address(session->getAddress().toStdString());
name = QString::fromStdString(data.name()); // Compensate for case indifference
databaseInterface->lockSessionTables();
if (authState == PasswordRight) {
if (users.contains(name) || databaseInterface->userSessionExists(name)) {
qDebug("Login denied: would overwrite old session");
databaseInterface->unlockSessionTables();
return WouldOverwriteOldSession;
}
} else if (authState == UnknownUser) {
// Change user name so that no two users have the same names,
// don't interfere with registered user names though.
QString tempName = name;
int i = 0;
while (users.contains(tempName) || databaseInterface->userExists(tempName) || databaseInterface->userSessionExists(tempName))
tempName = name + "_" + QString::number(++i);
name = tempName;
data.set_name(name.toStdString());
}
users.insert(name, session);
qDebug() << "Server::loginUser:" << session << "name=" << name;
data.set_session_id(databaseInterface->startSession(name, session->getAddress()));
databaseInterface->unlockSessionTables();
usersBySessionId.insert(data.session_id(), session);
qDebug() << "session id:" << data.session_id();
session->setUserInfo(data);
Event_UserJoined event;
event.mutable_user_info()->CopyFrom(session->copyUserInfo(false));
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
delete se;
event.mutable_user_info()->CopyFrom(session->copyUserInfo(true, true, true));
locker.unlock();
se = Server_ProtocolHandler::prepareSessionEvent(event);
sendIsl_SessionEvent(*se);
delete se;
return authState;
}
void Server::addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId)
{
QWriteLocker locker(&persistentPlayersLock);
persistentPlayers.insert(userName, PlayerReference(roomId, gameId, playerId));
QWriteLocker locker(&persistentPlayersLock);
persistentPlayers.insert(userName, PlayerReference(roomId, gameId, playerId));
}
void Server::removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId)
{
QWriteLocker locker(&persistentPlayersLock);
persistentPlayers.remove(userName, PlayerReference(roomId, gameId, playerId));
QWriteLocker locker(&persistentPlayersLock);
persistentPlayers.remove(userName, PlayerReference(roomId, gameId, playerId));
}
QList<PlayerReference> Server::getPersistentPlayerReferences(const QString &userName) const
{
QReadLocker locker(&persistentPlayersLock);
return persistentPlayers.values(userName);
QReadLocker locker(&persistentPlayersLock);
return persistentPlayers.values(userName);
}
Server_AbstractUserInterface *Server::findUser(const QString &userName) const
{
// Call this only with clientsLock set.
Server_AbstractUserInterface *userHandler = users.value(userName);
if (userHandler)
return userHandler;
else
return externalUsers.value(userName);
// Call this only with clientsLock set.
Server_AbstractUserInterface *userHandler = users.value(userName);
if (userHandler)
return userHandler;
else
return externalUsers.value(userName);
}
void Server::addClient(Server_ProtocolHandler *client)
{
QWriteLocker locker(&clientsLock);
clients << client;
QWriteLocker locker(&clientsLock);
clients << client;
}
void Server::removeClient(Server_ProtocolHandler *client)
{
QWriteLocker locker(&clientsLock);
clients.removeAt(clients.indexOf(client));
ServerInfo_User *data = client->getUserInfo();
if (data) {
Event_UserLeft event;
event.set_name(data->name());
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
sendIsl_SessionEvent(*se);
delete se;
users.remove(QString::fromStdString(data->name()));
qDebug() << "Server::removeClient: name=" << QString::fromStdString(data->name());
if (data->has_session_id()) {
const qint64 sessionId = data->session_id();
usersBySessionId.remove(sessionId);
emit endSession(sessionId);
qDebug() << "closed session id:" << sessionId;
}
}
qDebug() << "Server::removeClient: removed" << (void *) client << ";" << clients.size() << "clients; " << users.size() << "users left";
QWriteLocker locker(&clientsLock);
clients.removeAt(clients.indexOf(client));
ServerInfo_User *data = client->getUserInfo();
if (data) {
Event_UserLeft event;
event.set_name(data->name());
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
sendIsl_SessionEvent(*se);
delete se;
users.remove(QString::fromStdString(data->name()));
qDebug() << "Server::removeClient: name=" << QString::fromStdString(data->name());
if (data->has_session_id()) {
const qint64 sessionId = data->session_id();
usersBySessionId.remove(sessionId);
emit endSession(sessionId);
qDebug() << "closed session id:" << sessionId;
}
}
qDebug() << "Server::removeClient: removed" << (void *) client << ";" << clients.size() << "clients; " << users.size() << "users left";
}
void Server::externalUserJoined(const ServerInfo_User &userInfo)
{
// This function is always called from the main thread via signal/slot.
clientsLock.lockForWrite();
Server_RemoteUserInterface *newUser = new Server_RemoteUserInterface(this, ServerInfo_User_Container(userInfo));
externalUsers.insert(QString::fromStdString(userInfo.name()), newUser);
externalUsersBySessionId.insert(userInfo.session_id(), newUser);
Event_UserJoined event;
event.mutable_user_info()->CopyFrom(userInfo);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
delete se;
clientsLock.unlock();
ResponseContainer rc(-1);
newUser->joinPersistentGames(rc);
newUser->sendResponseContainer(rc, Response::RespNothing);
// This function is always called from the main thread via signal/slot.
clientsLock.lockForWrite();
Server_RemoteUserInterface *newUser = new Server_RemoteUserInterface(this, ServerInfo_User_Container(userInfo));
externalUsers.insert(QString::fromStdString(userInfo.name()), newUser);
externalUsersBySessionId.insert(userInfo.session_id(), newUser);
Event_UserJoined event;
event.mutable_user_info()->CopyFrom(userInfo);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
delete se;
clientsLock.unlock();
ResponseContainer rc(-1);
newUser->joinPersistentGames(rc);
newUser->sendResponseContainer(rc, Response::RespNothing);
}
void Server::externalUserLeft(const QString &userName)
{
// This function is always called from the main thread via signal/slot.
clientsLock.lockForWrite();
Server_AbstractUserInterface *user = externalUsers.take(userName);
externalUsersBySessionId.remove(user->getUserInfo()->session_id());
clientsLock.unlock();
QMap<int, QPair<int, int> > userGames(user->getGames());
QMapIterator<int, QPair<int, int> > userGamesIterator(userGames);
roomsLock.lockForRead();
while (userGamesIterator.hasNext()) {
userGamesIterator.next();
Server_Room *room = rooms.value(userGamesIterator.value().first);
if (!room)
continue;
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(userGamesIterator.key());
if (!game)
continue;
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(userGamesIterator.value().second);
if (!player)
continue;
player->disconnectClient();
}
roomsLock.unlock();
delete user;
Event_UserLeft event;
event.set_name(userName.toStdString());
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
clientsLock.unlock();
delete se;
// This function is always called from the main thread via signal/slot.
clientsLock.lockForWrite();
Server_AbstractUserInterface *user = externalUsers.take(userName);
externalUsersBySessionId.remove(user->getUserInfo()->session_id());
clientsLock.unlock();
QMap<int, QPair<int, int> > userGames(user->getGames());
QMapIterator<int, QPair<int, int> > userGamesIterator(userGames);
roomsLock.lockForRead();
while (userGamesIterator.hasNext()) {
userGamesIterator.next();
Server_Room *room = rooms.value(userGamesIterator.value().first);
if (!room)
continue;
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(userGamesIterator.key());
if (!game)
continue;
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(userGamesIterator.value().second);
if (!player)
continue;
player->disconnectClient();
}
roomsLock.unlock();
delete user;
Event_UserLeft event;
event.set_name(userName.toStdString());
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se);
clientsLock.unlock();
delete se;
}
void Server::externalRoomUserJoined(int roomId, const ServerInfo_User &userInfo)
{
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomUserJoined: room id=" << roomId << "not found";
return;
}
room->addExternalUser(userInfo);
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomUserJoined: room id=" << roomId << "not found";
return;
}
room->addExternalUser(userInfo);
}
void Server::externalRoomUserLeft(int roomId, const QString &userName)
{
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomUserLeft: room id=" << roomId << "not found";
return;
}
room->removeExternalUser(userName);
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomUserLeft: room id=" << roomId << "not found";
return;
}
room->removeExternalUser(userName);
}
void Server::externalRoomSay(int roomId, const QString &userName, const QString &message)
{
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomSay: room id=" << roomId << "not found";
return;
}
room->say(userName, message, false);
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomSay: room id=" << roomId << "not found";
return;
}
room->say(userName, message, false);
}
void Server::externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo)
{
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomGameListChanged: room id=" << roomId << "not found";
return;
}
room->updateExternalGameList(gameInfo);
// This function is always called from the main thread via signal/slot.
QReadLocker locker(&roomsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalRoomGameListChanged: room id=" << roomId << "not found";
return;
}
room->updateExternalGameList(gameInfo);
}
void Server::externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
try {
QReadLocker roomsLocker(&roomsLock);
QReadLocker clientsLocker(&clientsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalJoinGameCommandReceived: room id=" << roomId << "not found";
throw Response::RespNotInRoom;
}
Server_AbstractUserInterface *userInterface = externalUsersBySessionId.value(sessionId);
if (!userInterface) {
qDebug() << "externalJoinGameCommandReceived: session id=" << sessionId << "not found";
throw Response::RespNotInRoom;
}
ResponseContainer responseContainer(cmdId);
Response::ResponseCode responseCode = room->processJoinGameCommand(cmd, responseContainer, userInterface);
userInterface->sendResponseContainer(responseContainer, responseCode);
} catch (Response::ResponseCode code) {
Response response;
response.set_cmd_id(cmdId);
response.set_response_code(code);
sendIsl_Response(response, serverId, sessionId);
}
// This function is always called from the main thread via signal/slot.
try {
QReadLocker roomsLocker(&roomsLock);
QReadLocker clientsLocker(&clientsLock);
Server_Room *room = rooms.value(roomId);
if (!room) {
qDebug() << "externalJoinGameCommandReceived: room id=" << roomId << "not found";
throw Response::RespNotInRoom;
}
Server_AbstractUserInterface *userInterface = externalUsersBySessionId.value(sessionId);
if (!userInterface) {
qDebug() << "externalJoinGameCommandReceived: session id=" << sessionId << "not found";
throw Response::RespNotInRoom;
}
ResponseContainer responseContainer(cmdId);
Response::ResponseCode responseCode = room->processJoinGameCommand(cmd, responseContainer, userInterface);
userInterface->sendResponseContainer(responseContainer, responseCode);
} catch (Response::ResponseCode code) {
Response response;
response.set_cmd_id(cmdId);
response.set_response_code(code);
sendIsl_Response(response, serverId, sessionId);
}
}
void Server::externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
try {
ResponseContainer responseContainer(cont.cmd_id());
Response::ResponseCode finalResponseCode = Response::RespOk;
QReadLocker roomsLocker(&roomsLock);
Server_Room *room = rooms.value(cont.room_id());
if (!room) {
qDebug() << "externalGameCommandContainerReceived: room id=" << cont.room_id() << "not found";
throw Response::RespNotInRoom;
}
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(cont.game_id());
if (!game) {
qDebug() << "externalGameCommandContainerReceived: game id=" << cont.game_id() << "not found";
throw Response::RespNotInRoom;
}
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(playerId);
if (!player) {
qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
throw Response::RespNotInRoom;
}
GameEventStorage ges;
for (int i = cont.game_command_size() - 1; i >= 0; --i) {
const GameCommand &sc = cont.game_command(i);
qDebug() << "[ISL]" << QString::fromStdString(sc.ShortDebugString());
Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges);
if (resp != Response::RespOk)
finalResponseCode = resp;
}
ges.sendToGame(game);
if (finalResponseCode != Response::RespNothing) {
player->playerMutex.lock();
player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
player->playerMutex.unlock();
}
} catch (Response::ResponseCode code) {
Response response;
response.set_cmd_id(cont.cmd_id());
response.set_response_code(code);
sendIsl_Response(response, serverId, sessionId);
}
// This function is always called from the main thread via signal/slot.
try {
ResponseContainer responseContainer(cont.cmd_id());
Response::ResponseCode finalResponseCode = Response::RespOk;
QReadLocker roomsLocker(&roomsLock);
Server_Room *room = rooms.value(cont.room_id());
if (!room) {
qDebug() << "externalGameCommandContainerReceived: room id=" << cont.room_id() << "not found";
throw Response::RespNotInRoom;
}
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(cont.game_id());
if (!game) {
qDebug() << "externalGameCommandContainerReceived: game id=" << cont.game_id() << "not found";
throw Response::RespNotInRoom;
}
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(playerId);
if (!player) {
qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
throw Response::RespNotInRoom;
}
GameEventStorage ges;
for (int i = cont.game_command_size() - 1; i >= 0; --i) {
const GameCommand &sc = cont.game_command(i);
qDebug() << "[ISL]" << QString::fromStdString(sc.ShortDebugString());
Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges);
if (resp != Response::RespOk)
finalResponseCode = resp;
}
ges.sendToGame(game);
if (finalResponseCode != Response::RespNothing) {
player->playerMutex.lock();
player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
player->playerMutex.unlock();
}
} catch (Response::ResponseCode code) {
Response response;
response.set_cmd_id(cont.cmd_id());
response.set_response_code(code);
sendIsl_Response(response, serverId, sessionId);
}
}
void Server::externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
QReadLocker usersLocker(&clientsLock);
Server_ProtocolHandler *client = usersBySessionId.value(sessionId);
if (!client) {
qDebug() << "externalGameEventContainerReceived: session" << sessionId << "not found";
return;
}
client->sendProtocolItem(cont);
// This function is always called from the main thread via signal/slot.
QReadLocker usersLocker(&clientsLock);
Server_ProtocolHandler *client = usersBySessionId.value(sessionId);
if (!client) {
qDebug() << "externalGameEventContainerReceived: session" << sessionId << "not found";
return;
}
client->sendProtocolItem(cont);
}
void Server::externalResponseReceived(const Response &resp, qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
QReadLocker usersLocker(&clientsLock);
Server_ProtocolHandler *client = usersBySessionId.value(sessionId);
if (!client) {
qDebug() << "externalResponseReceived: session" << sessionId << "not found";
return;
}
client->sendProtocolItem(resp);
// This function is always called from the main thread via signal/slot.
QReadLocker usersLocker(&clientsLock);
Server_ProtocolHandler *client = usersBySessionId.value(sessionId);
if (!client) {
qDebug() << "externalResponseReceived: session" << sessionId << "not found";
return;
}
client->sendProtocolItem(resp);
}
void Server::broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl)
{
// This function is always called from the main thread via signal/slot.
Event_ListRooms event;
event.add_room_list()->CopyFrom(roomInfo);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
// This function is always called from the main thread via signal/slot.
Event_ListRooms event;
event.add_room_list()->CopyFrom(roomInfo);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsRoomListChanges())
clients[i]->sendProtocolItem(*se);
clientsLock.unlock();
if (sendToIsl)
sendIsl_SessionEvent(*se);
delete se;
clientsLock.lockForRead();
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsRoomListChanges())
clients[i]->sendProtocolItem(*se);
clientsLock.unlock();
if (sendToIsl)
sendIsl_SessionEvent(*se);
delete se;
}
void Server::addRoom(Server_Room *newRoom)
{
QWriteLocker locker(&roomsLock);
qDebug() << "Adding room: ID=" << newRoom->getId() << "name=" << newRoom->getName();
rooms.insert(newRoom->getId(), newRoom);
connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)), Qt::QueuedConnection);
QWriteLocker locker(&roomsLock);
qDebug() << "Adding room: ID=" << newRoom->getId() << "name=" << newRoom->getName();
rooms.insert(newRoom->getId(), newRoom);
connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)), Qt::QueuedConnection);
}
int Server::getUsersCount() const
{
QReadLocker locker(&clientsLock);
return users.size();
QReadLocker locker(&clientsLock);
return users.size();
}
int Server::getGamesCount() const
{
int result = 0;
QReadLocker locker(&roomsLock);
QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext()) {
Server_Room *room = roomIterator.next().value();
QReadLocker roomLocker(&room->gamesLock);
result += room->getGames().size();
}
return result;
int result = 0;
QReadLocker locker(&roomsLock);
QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext()) {
Server_Room *room = roomIterator.next().value();
QReadLocker roomLocker(&room->gamesLock);
result += room->getGames().size();
}
return result;
}
void Server::sendIsl_Response(const Response &item, int serverId, qint64 sessionId)
{
IslMessage msg;
msg.set_message_type(IslMessage::RESPONSE);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_response()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::RESPONSE);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_response()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
}
void Server::sendIsl_SessionEvent(const SessionEvent &item, int serverId, qint64 sessionId)
{
IslMessage msg;
msg.set_message_type(IslMessage::SESSION_EVENT);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_session_event()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::SESSION_EVENT);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_session_event()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
}
void Server::sendIsl_GameEventContainer(const GameEventContainer &item, int serverId, qint64 sessionId)
{
IslMessage msg;
msg.set_message_type(IslMessage::GAME_EVENT_CONTAINER);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_game_event_container()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::GAME_EVENT_CONTAINER);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_game_event_container()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
}
void Server::sendIsl_RoomEvent(const RoomEvent &item, int serverId, qint64 sessionId)
{
IslMessage msg;
msg.set_message_type(IslMessage::ROOM_EVENT);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_room_event()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::ROOM_EVENT);
if (sessionId != -1)
msg.set_session_id(sessionId);
msg.mutable_room_event()->CopyFrom(item);
emit sigSendIslMessage(msg, serverId);
}
void Server::sendIsl_GameCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId, int playerId)
{
IslMessage msg;
msg.set_message_type(IslMessage::GAME_COMMAND_CONTAINER);
msg.set_session_id(sessionId);
msg.set_player_id(playerId);
CommandContainer *cont = msg.mutable_game_command();
cont->CopyFrom(item);
cont->set_room_id(roomId);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::GAME_COMMAND_CONTAINER);
msg.set_session_id(sessionId);
msg.set_player_id(playerId);
CommandContainer *cont = msg.mutable_game_command();
cont->CopyFrom(item);
cont->set_room_id(roomId);
emit sigSendIslMessage(msg, serverId);
}
void Server::sendIsl_RoomCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId)
{
IslMessage msg;
msg.set_message_type(IslMessage::ROOM_COMMAND_CONTAINER);
msg.set_session_id(sessionId);
CommandContainer *cont = msg.mutable_room_command();
cont->CopyFrom(item);
cont->set_room_id(roomId);
emit sigSendIslMessage(msg, serverId);
IslMessage msg;
msg.set_message_type(IslMessage::ROOM_COMMAND_CONTAINER);
msg.set_session_id(sessionId);
CommandContainer *cont = msg.mutable_room_command();
cont->CopyFrom(item);
cont->set_room_id(roomId);
emit sigSendIslMessage(msg, serverId);
}

View file

@ -31,87 +31,87 @@ enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2,
class Server : public QObject
{
Q_OBJECT
Q_OBJECT
signals:
void pingClockTimeout();
void sigSendIslMessage(const IslMessage &message, int serverId);
void endSession(qint64 sessionId);
void pingClockTimeout();
void sigSendIslMessage(const IslMessage &message, int serverId);
void endSession(qint64 sessionId);
private slots:
void broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl = false);
void broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl = false);
public:
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
Server(bool _threaded, QObject *parent = 0);
~Server();
void setThreaded(bool _threaded) { threaded = _threaded; }
AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason, int &secondsLeft);
const QMap<int, Server_Room *> &getRooms() { return rooms; }
Server_AbstractUserInterface *findUser(const QString &userName) const;
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
void addClient(Server_ProtocolHandler *player);
void removeClient(Server_ProtocolHandler *player);
virtual QString getLoginMessage() const { return QString(); }
virtual bool getGameShouldPing() const { return false; }
virtual int getMaxGameInactivityTime() const { return 9999999; }
virtual int getMaxPlayerInactivityTime() const { return 9999999; }
virtual int getMessageCountingInterval() const { return 0; }
virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual int getMaxGamesPerUser() const { return 0; }
virtual bool getThreaded() const { return false; }
Server_DatabaseInterface *getDatabaseInterface() const;
int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; }
void sendIsl_Response(const Response &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_SessionEvent(const SessionEvent &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_GameEventContainer(const GameEventContainer &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_RoomEvent(const RoomEvent &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_GameCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId, int playerId);
void sendIsl_RoomCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &userName);
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
void addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
void removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
QList<PlayerReference> getPersistentPlayerReferences(const QString &userName) const;
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
Server(bool _threaded, QObject *parent = 0);
~Server();
void setThreaded(bool _threaded) { threaded = _threaded; }
AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason, int &secondsLeft);
const QMap<int, Server_Room *> &getRooms() { return rooms; }
Server_AbstractUserInterface *findUser(const QString &userName) const;
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
void addClient(Server_ProtocolHandler *player);
void removeClient(Server_ProtocolHandler *player);
virtual QString getLoginMessage() const { return QString(); }
virtual bool getGameShouldPing() const { return false; }
virtual int getMaxGameInactivityTime() const { return 9999999; }
virtual int getMaxPlayerInactivityTime() const { return 9999999; }
virtual int getMessageCountingInterval() const { return 0; }
virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual int getMaxGamesPerUser() const { return 0; }
virtual bool getThreaded() const { return false; }
Server_DatabaseInterface *getDatabaseInterface() const;
int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; }
void sendIsl_Response(const Response &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_SessionEvent(const SessionEvent &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_GameEventContainer(const GameEventContainer &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_RoomEvent(const RoomEvent &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_GameCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId, int playerId);
void sendIsl_RoomCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &userName);
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
void addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
void removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
QList<PlayerReference> getPersistentPlayerReferences(const QString &userName) const;
private:
bool threaded;
QMultiMap<QString, PlayerReference> persistentPlayers;
mutable QReadWriteLock persistentPlayersLock;
int nextLocalGameId;
QMutex nextLocalGameIdMutex;
protected slots:
void externalUserJoined(const ServerInfo_User &userInfo);
void externalUserLeft(const QString &userName);
void externalRoomUserJoined(int roomId, const ServerInfo_User &userInfo);
void externalRoomUserLeft(int roomId, const QString &userName);
void externalRoomSay(int roomId, const QString &userName, const QString &message);
void externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo);
void externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId);
void externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId);
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
void externalResponseReceived(const Response &resp, qint64 sessionId);
virtual void doSendIslMessage(const IslMessage &msg, int serverId) { }
bool threaded;
QMultiMap<QString, PlayerReference> persistentPlayers;
mutable QReadWriteLock persistentPlayersLock;
int nextLocalGameId;
QMutex nextLocalGameIdMutex;
protected slots:
void externalUserJoined(const ServerInfo_User &userInfo);
void externalUserLeft(const QString &userName);
void externalRoomUserJoined(int roomId, const ServerInfo_User &userInfo);
void externalRoomUserLeft(int roomId, const QString &userName);
void externalRoomSay(int roomId, const QString &userName, const QString &message);
void externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo);
void externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId);
void externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId);
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
void externalResponseReceived(const Response &resp, qint64 sessionId);
virtual void doSendIslMessage(const IslMessage & /* msg */, int /* serverId */) { }
protected:
void prepareDestroy();
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);
QList<Server_ProtocolHandler *> clients;
QMap<qint64, Server_ProtocolHandler *> usersBySessionId;
QMap<QString, Server_ProtocolHandler *> users;
QMap<qint64, Server_AbstractUserInterface *> externalUsersBySessionId;
QMap<QString, Server_AbstractUserInterface *> externalUsers;
QMap<int, Server_Room *> rooms;
QMap<QThread *, Server_DatabaseInterface *> databaseInterfaces;
int getUsersCount() const;
int getGamesCount() const;
void addRoom(Server_Room *newRoom);
void prepareDestroy();
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);
QList<Server_ProtocolHandler *> clients;
QMap<qint64, Server_ProtocolHandler *> usersBySessionId;
QMap<QString, Server_ProtocolHandler *> users;
QMap<qint64, Server_AbstractUserInterface *> externalUsersBySessionId;
QMap<QString, Server_AbstractUserInterface *> externalUsers;
QMap<int, Server_Room *> rooms;
QMap<QThread *, Server_DatabaseInterface *> databaseInterfaces;
int getUsersCount() const;
int getGamesCount() const;
void addRoom(Server_Room *newRoom);
};
#endif

View file

@ -15,82 +15,82 @@
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
{
switch (type) {
case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(item)); break;
}
switch (type) {
case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(item)); break;
}
}
SessionEvent *Server_AbstractUserInterface::prepareSessionEvent(const ::google::protobuf::Message &sessionEvent)
{
SessionEvent *event = new SessionEvent;
event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent);
return event;
SessionEvent *event = new SessionEvent;
event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent);
return event;
}
void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode)
{
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue();
for (int i = 0; i < preResponseQueue.size(); ++i)
sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
if (responseCode != Response::RespNothing) {
Response response;
response.set_cmd_id(responseContainer.getCmdId());
response.set_response_code(responseCode);
::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
if (responseExtension)
response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
sendProtocolItem(response);
}
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
for (int i = 0; i < postResponseQueue.size(); ++i)
sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue();
for (int i = 0; i < preResponseQueue.size(); ++i)
sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
if (responseCode != Response::RespNothing) {
Response response;
response.set_cmd_id(responseContainer.getCmdId());
response.set_response_code(responseCode);
::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
if (responseExtension)
response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
sendProtocolItem(response);
}
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
for (int i = 0; i < postResponseQueue.size(); ++i)
sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
}
void Server_AbstractUserInterface::playerRemovedFromGame(Server_Game *game)
{
qDebug() << "Server_AbstractUserInterface::playerRemovedFromGame(): gameId =" << game->getGameId();
QMutexLocker locker(&gameListMutex);
games.remove(game->getGameId());
qDebug() << "Server_AbstractUserInterface::playerRemovedFromGame(): gameId =" << game->getGameId();
QMutexLocker locker(&gameListMutex);
games.remove(game->getGameId());
}
void Server_AbstractUserInterface::playerAddedToGame(int gameId, int roomId, int playerId)
{
qDebug() << "Server_AbstractUserInterface::playerAddedToGame(): gameId =" << gameId;
QMutexLocker locker(&gameListMutex);
games.insert(gameId, QPair<int, int>(roomId, playerId));
qDebug() << "Server_AbstractUserInterface::playerAddedToGame(): gameId =" << gameId;
QMutexLocker locker(&gameListMutex);
games.insert(gameId, QPair<int, int>(roomId, playerId));
}
void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
{
QList<PlayerReference> gamesToJoin = server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
server->roomsLock.lockForRead();
for (int i = 0; i < gamesToJoin.size(); ++i) {
const PlayerReference &pr = gamesToJoin.at(i);
Server_Room *room = server->getRooms().value(pr.getRoomId());
if (!room)
continue;
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(pr.getGameId());
if (!game)
continue;
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
player->setUserInterface(this);
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
game->createGameJoinedEvent(player, rc, true);
}
server->roomsLock.unlock();
QList<PlayerReference> gamesToJoin = server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
server->roomsLock.lockForRead();
for (int i = 0; i < gamesToJoin.size(); ++i) {
const PlayerReference &pr = gamesToJoin.at(i);
Server_Room *room = server->getRooms().value(pr.getRoomId());
if (!room)
continue;
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(pr.getGameId());
if (!game)
continue;
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
player->setUserInterface(this);
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
game->createGameJoinedEvent(player, rc, true);
}
server->roomsLock.unlock();
}

View file

@ -18,31 +18,31 @@ class Server_Game;
class Server_AbstractUserInterface : public ServerInfo_User_Container {
private:
mutable QMutex gameListMutex;
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
mutable QMutex gameListMutex;
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
protected:
Server *server;
Server *server;
public:
Server_AbstractUserInterface(Server *_server) : server(_server) { }
Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { }
virtual ~Server_AbstractUserInterface() { }
virtual int getLastCommandTime() const = 0;
void playerRemovedFromGame(Server_Game *game);
void playerAddedToGame(int gameId, int roomId, int playerId);
void joinPersistentGames(ResponseContainer &rc);
QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; }
virtual void sendProtocolItem(const Response &item) = 0;
virtual void sendProtocolItem(const SessionEvent &item) = 0;
virtual void sendProtocolItem(const GameEventContainer &item) = 0;
virtual void sendProtocolItem(const RoomEvent &item) = 0;
void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item);
static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent);
void sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode);
Server_AbstractUserInterface(Server *_server) : server(_server) { }
Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { }
virtual ~Server_AbstractUserInterface() { }
virtual int getLastCommandTime() const = 0;
void playerRemovedFromGame(Server_Game *game);
void playerAddedToGame(int gameId, int roomId, int playerId);
void joinPersistentGames(ResponseContainer &rc);
QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; }
virtual void sendProtocolItem(const Response &item) = 0;
virtual void sendProtocolItem(const SessionEvent &item) = 0;
virtual void sendProtocolItem(const GameEventContainer &item) = 0;
virtual void sendProtocolItem(const RoomEvent &item) = 0;
void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item);
static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent);
void sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode);
};
#endif

View file

@ -14,17 +14,17 @@ Server_Arrow::Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget
void Server_Arrow::getInfo(ServerInfo_Arrow *info)
{
info->set_id(id);
info->set_start_player_id(startCard->getZone()->getPlayer()->getPlayerId());
info->set_start_zone(startCard->getZone()->getName().toStdString());
info->set_start_card_id(startCard->getId());
info->mutable_arrow_color()->CopyFrom(arrowColor);
info->set_id(id);
info->set_start_player_id(startCard->getZone()->getPlayer()->getPlayerId());
info->set_start_zone(startCard->getZone()->getName().toStdString());
info->set_start_card_id(startCard->getId());
info->mutable_arrow_color()->CopyFrom(arrowColor);
Server_Card *targetCard = qobject_cast<Server_Card *>(targetItem);
if (targetCard) {
info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
info->set_target_zone(targetCard->getZone()->getName().toStdString());
info->set_target_card_id(targetCard->getId());
} else
info->set_target_player_id(static_cast<Server_Player *>(targetItem)->getPlayerId());
Server_Card *targetCard = qobject_cast<Server_Card *>(targetItem);
if (targetCard) {
info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
info->set_target_zone(targetCard->getZone()->getName().toStdString());
info->set_target_card_id(targetCard->getId());
} else
info->set_target_player_id(static_cast<Server_Player *>(targetItem)->getPlayerId());
}

View file

@ -9,18 +9,18 @@ class ServerInfo_Arrow;
class Server_Arrow {
private:
int id;
Server_Card *startCard;
Server_ArrowTarget *targetItem;
color arrowColor;
int id;
Server_Card *startCard;
Server_ArrowTarget *targetItem;
color arrowColor;
public:
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor);
int getId() const { return id; }
Server_Card *getStartCard() const { return startCard; }
Server_ArrowTarget *getTargetItem() const { return targetItem; }
const color &getColor() const { return arrowColor; }
void getInfo(ServerInfo_Arrow *info);
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor);
int getId() const { return id; }
Server_Card *getStartCard() const { return startCard; }
Server_ArrowTarget *getTargetItem() const { return targetItem; }
const color &getColor() const { return arrowColor; }
void getInfo(ServerInfo_Arrow *info);
};
#endif

View file

@ -1,2 +1,2 @@
#include "server_arrowtarget.h"
#include "server_arrowtarget.h"

View file

@ -4,7 +4,7 @@
#include <QObject>
class Server_ArrowTarget : public QObject {
Q_OBJECT
Q_OBJECT
};
#endif

View file

@ -23,138 +23,138 @@
#include "pb/serverinfo_card.pb.h"
Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone)
: zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0)
: zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0)
{
}
Server_Card::~Server_Card()
{
// setParentCard(0) leads to the item being removed from our list, so we can't iterate properly
while (!attachedCards.isEmpty())
attachedCards.first()->setParentCard(0);
if (parentCard)
parentCard->removeAttachedCard(this);
// setParentCard(0) leads to the item being removed from our list, so we can't iterate properly
while (!attachedCards.isEmpty())
attachedCards.first()->setParentCard(0);
if (parentCard)
parentCard->removeAttachedCard(this);
}
void Server_Card::resetState()
{
counters.clear();
setTapped(false);
setAttacking(false);
power = -1;
toughness = -1;
setAnnotation(QString());
setDoesntUntap(false);
counters.clear();
setTapped(false);
setAttacking(false);
power = -1;
toughness = -1;
setAnnotation(QString());
setDoesntUntap(false);
}
QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue, bool allCards)
{
switch (attribute) {
case AttrTapped: {
bool value = avalue == "1";
if (!(!value && allCards && doesntUntap))
setTapped(value);
break;
}
case AttrAttacking: setAttacking(avalue == "1"); break;
case AttrFaceDown: setFaceDown(avalue == "1"); break;
case AttrColor: setColor(avalue); break;
case AttrPT: setPT(avalue); return getPT();
case AttrAnnotation: setAnnotation(avalue); break;
case AttrDoesntUntap: setDoesntUntap(avalue == "1"); break;
}
return avalue;
switch (attribute) {
case AttrTapped: {
bool value = avalue == "1";
if (!(!value && allCards && doesntUntap))
setTapped(value);
break;
}
case AttrAttacking: setAttacking(avalue == "1"); break;
case AttrFaceDown: setFaceDown(avalue == "1"); break;
case AttrColor: setColor(avalue); break;
case AttrPT: setPT(avalue); return getPT();
case AttrAnnotation: setAnnotation(avalue); break;
case AttrDoesntUntap: setDoesntUntap(avalue == "1"); break;
}
return avalue;
}
void Server_Card::setCounter(int id, int value)
{
if (value)
counters.insert(id, value);
else
counters.remove(id);
if (value)
counters.insert(id, value);
else
counters.remove(id);
}
void Server_Card::setPT(const QString &_pt)
{
if (_pt.isEmpty()) {
power = 0;
toughness = -1;
} else {
int sep = _pt.indexOf('/');
QString p1 = _pt.left(sep);
QString p2 = _pt.mid(sep + 1);
if (p1.isEmpty() || p2.isEmpty())
return;
if ((p1[0] == '+') || (p2[0] == '+')) {
if (power < 0)
power = 0;
if (toughness < 0)
toughness = 0;
}
if (p1[0] == '+')
power += p1.mid(1).toInt();
else
power = p1.toInt();
if (p2[0] == '+')
toughness += p2.mid(1).toInt();
else
toughness = p2.toInt();
}
if (_pt.isEmpty()) {
power = 0;
toughness = -1;
} else {
int sep = _pt.indexOf('/');
QString p1 = _pt.left(sep);
QString p2 = _pt.mid(sep + 1);
if (p1.isEmpty() || p2.isEmpty())
return;
if ((p1[0] == '+') || (p2[0] == '+')) {
if (power < 0)
power = 0;
if (toughness < 0)
toughness = 0;
}
if (p1[0] == '+')
power += p1.mid(1).toInt();
else
power = p1.toInt();
if (p2[0] == '+')
toughness += p2.mid(1).toInt();
else
toughness = p2.toInt();
}
}
QString Server_Card::getPT() const
{
if (toughness < 0)
return QString("");
return QString::number(power) + "/" + QString::number(toughness);
if (toughness < 0)
return QString("");
return QString::number(power) + "/" + QString::number(toughness);
}
void Server_Card::setParentCard(Server_Card *_parentCard)
{
if (parentCard)
parentCard->removeAttachedCard(this);
parentCard = _parentCard;
if (parentCard)
parentCard->addAttachedCard(this);
if (parentCard)
parentCard->removeAttachedCard(this);
parentCard = _parentCard;
if (parentCard)
parentCard->addAttachedCard(this);
}
void Server_Card::getInfo(ServerInfo_Card *info)
{
QString displayedName = facedown ? QString() : name;
info->set_id(id);
info->set_name(displayedName.toStdString());
info->set_x(coord_x);
info->set_y(coord_y);
if (facedown)
info->set_face_down(true);
info->set_tapped(tapped);
if (attacking)
info->set_attacking(true);
if (!color.isEmpty())
info->set_color(color.toStdString());
const QString ptStr = getPT();
if (!ptStr.isEmpty())
info->set_pt(ptStr.toStdString());
if (!annotation.isEmpty())
info->set_annotation(annotation.toStdString());
if (destroyOnZoneChange)
info->set_destroy_on_zone_change(true);
if (doesntUntap)
info->set_doesnt_untap(true);
QMapIterator<int, int> cardCounterIterator(counters);
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();
ServerInfo_CardCounter *counterInfo = info->add_counter_list();
counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
}
QString displayedName = facedown ? QString() : name;
info->set_id(id);
info->set_name(displayedName.toStdString());
info->set_x(coord_x);
info->set_y(coord_y);
if (facedown)
info->set_face_down(true);
info->set_tapped(tapped);
if (attacking)
info->set_attacking(true);
if (!color.isEmpty())
info->set_color(color.toStdString());
const QString ptStr = getPT();
if (!ptStr.isEmpty())
info->set_pt(ptStr.toStdString());
if (!annotation.isEmpty())
info->set_annotation(annotation.toStdString());
if (destroyOnZoneChange)
info->set_destroy_on_zone_change(true);
if (doesntUntap)
info->set_doesnt_untap(true);
QMapIterator<int, int> cardCounterIterator(counters);
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();
ServerInfo_CardCounter *counterInfo = info->add_counter_list();
counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
}
if (parentCard) {
info->set_attach_player_id(parentCard->getZone()->getPlayer()->getPlayerId());
info->set_attach_zone(parentCard->getZone()->getName().toStdString());
info->set_attach_card_id(parentCard->getId());
}
if (parentCard) {
info->set_attach_player_id(parentCard->getZone()->getPlayer()->getPlayerId());
info->set_attach_zone(parentCard->getZone()->getName().toStdString());
info->set_attach_card_id(parentCard->getId());
}
}

View file

@ -29,68 +29,68 @@ class Server_CardZone;
class ServerInfo_Card;
class Server_Card : public Server_ArrowTarget {
Q_OBJECT
Q_OBJECT
private:
Server_CardZone *zone;
int id;
int coord_x, coord_y;
QString name;
QMap<int, int> counters;
bool tapped;
bool attacking;
bool facedown;
QString color;
int power, toughness;
QString annotation;
bool destroyOnZoneChange;
bool doesntUntap;
Server_Card *parentCard;
QList<Server_Card *> attachedCards;
Server_CardZone *zone;
int id;
int coord_x, coord_y;
QString name;
QMap<int, int> counters;
bool tapped;
bool attacking;
bool facedown;
QString color;
int power, toughness;
QString annotation;
bool destroyOnZoneChange;
bool doesntUntap;
Server_Card *parentCard;
QList<Server_Card *> attachedCards;
public:
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
~Server_Card();
Server_CardZone *getZone() const { return zone; }
void setZone(Server_CardZone *_zone) { zone = _zone; }
int getId() const { return id; }
int getX() const { return coord_x; }
int getY() const { return coord_y; }
QString getName() const { return name; }
const QMap<int, int> &getCounters() const { return counters; }
int getCounter(int id) const { return counters.value(id, 0); }
bool getTapped() const { return tapped; }
bool getAttacking() const { return attacking; }
bool getFaceDown() const { return facedown; }
QString getColor() const { return color; }
QString getPT() const;
QString getAnnotation() const { return annotation; }
bool getDoesntUntap() const { return doesntUntap; }
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
Server_Card *getParentCard() const { return parentCard; }
const QList<Server_Card *> &getAttachedCards() const { return attachedCards; }
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
~Server_Card();
Server_CardZone *getZone() const { return zone; }
void setZone(Server_CardZone *_zone) { zone = _zone; }
int getId() const { return id; }
int getX() const { return coord_x; }
int getY() const { return coord_y; }
QString getName() const { return name; }
const QMap<int, int> &getCounters() const { return counters; }
int getCounter(int id) const { return counters.value(id, 0); }
bool getTapped() const { return tapped; }
bool getAttacking() const { return attacking; }
bool getFaceDown() const { return facedown; }
QString getColor() const { return color; }
QString getPT() const;
QString getAnnotation() const { return annotation; }
bool getDoesntUntap() const { return doesntUntap; }
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
Server_Card *getParentCard() const { return parentCard; }
const QList<Server_Card *> &getAttachedCards() const { return attachedCards; }
void setId(int _id) { id = _id; }
void setCoords(int x, int y) { coord_x = x; coord_y = y; }
void setName(const QString &_name) { name = _name; }
void setCounter(int id, int value);
void setTapped(bool _tapped) { tapped = _tapped; }
void setAttacking(bool _attacking) { attacking = _attacking; }
void setFaceDown(bool _facedown) { facedown = _facedown; }
void setColor(const QString &_color) { color = _color; }
void setPT(const QString &_pt);
void setAnnotation(const QString &_annotation) { annotation = _annotation; }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
void setDoesntUntap(bool _doesntUntap) { doesntUntap = _doesntUntap; }
void setParentCard(Server_Card *_parentCard);
void addAttachedCard(Server_Card *card) { attachedCards.append(card); }
void removeAttachedCard(Server_Card *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
void resetState();
QString setAttribute(CardAttribute attribute, const QString &avalue, bool allCards);
void getInfo(ServerInfo_Card *info);
void setId(int _id) { id = _id; }
void setCoords(int x, int y) { coord_x = x; coord_y = y; }
void setName(const QString &_name) { name = _name; }
void setCounter(int id, int value);
void setTapped(bool _tapped) { tapped = _tapped; }
void setAttacking(bool _attacking) { attacking = _attacking; }
void setFaceDown(bool _facedown) { facedown = _facedown; }
void setColor(const QString &_color) { color = _color; }
void setPT(const QString &_pt);
void setAnnotation(const QString &_annotation) { annotation = _annotation; }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
void setDoesntUntap(bool _doesntUntap) { doesntUntap = _doesntUntap; }
void setParentCard(Server_Card *_parentCard);
void addAttachedCard(Server_Card *card) { attachedCards.append(card); }
void removeAttachedCard(Server_Card *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
void resetState();
QString setAttribute(CardAttribute attribute, const QString &avalue, bool allCards);
void getInfo(ServerInfo_Card *info);
};
#endif

View file

@ -33,48 +33,48 @@ class GameEventStorage;
class Server_CardZone {
private:
Server_Player *player;
QString name;
bool has_coords;
ServerInfo_Zone::ZoneType type;
int cardsBeingLookedAt;
QSet<int> playersWithWritePermission;
bool alwaysRevealTopCard;
QList<Server_Card *> cards;
QMap<int, QMap<int, Server_Card *> > coordinateMap; // y -> (x -> card)
QMap<int, QMultiMap<QString, int> > freePilesMap; // y -> (cardName -> x)
QMap<int, int> freeSpaceMap; // y -> x
void removeCardFromCoordMap(Server_Card *card, int oldX, int oldY);
void insertCardIntoCoordMap(Server_Card *card, int x, int y);
Server_Player *player;
QString name;
bool has_coords;
ServerInfo_Zone::ZoneType type;
int cardsBeingLookedAt;
QSet<int> playersWithWritePermission;
bool alwaysRevealTopCard;
QList<Server_Card *> cards;
QMap<int, QMap<int, Server_Card *> > coordinateMap; // y -> (x -> card)
QMap<int, QMultiMap<QString, int> > freePilesMap; // y -> (cardName -> x)
QMap<int, int> freeSpaceMap; // y -> x
void removeCardFromCoordMap(Server_Card *card, int oldX, int oldY);
void insertCardIntoCoordMap(Server_Card *card, int x, int y);
public:
Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type);
~Server_CardZone();
const QList<Server_Card *> &getCards() const { return cards; }
int removeCard(Server_Card *card);
Server_Card *getCard(int id, int *position = NULL, bool remove = false);
Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type);
~Server_CardZone();
const QList<Server_Card *> &getCards() const { return cards; }
int removeCard(Server_Card *card);
Server_Card *getCard(int id, int *position = NULL, bool remove = false);
int getCardsBeingLookedAt() const { return cardsBeingLookedAt; }
void setCardsBeingLookedAt(int _cardsBeingLookedAt) { cardsBeingLookedAt = _cardsBeingLookedAt; }
bool hasCoords() const { return has_coords; }
ServerInfo_Zone::ZoneType getType() const { return type; }
QString getName() const { return name; }
Server_Player *getPlayer() const { return player; }
void getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient);
int getFreeGridColumn(int x, int y, const QString &cardName) const;
bool isColumnEmpty(int x, int y) const;
bool isColumnStacked(int x, int y) const;
void fixFreeSpaces(GameEventStorage &ges);
void moveCardInRow(GameEventStorage &ges, Server_Card *card, int x, int y);
void insertCard(Server_Card *card, int x, int y);
void updateCardCoordinates(Server_Card *card, int oldX, int oldY);
void shuffle();
void clear();
void addWritePermission(int playerId);
const QSet<int> &getPlayersWithWritePermission() const { return playersWithWritePermission; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
int getCardsBeingLookedAt() const { return cardsBeingLookedAt; }
void setCardsBeingLookedAt(int _cardsBeingLookedAt) { cardsBeingLookedAt = _cardsBeingLookedAt; }
bool hasCoords() const { return has_coords; }
ServerInfo_Zone::ZoneType getType() const { return type; }
QString getName() const { return name; }
Server_Player *getPlayer() const { return player; }
void getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient);
int getFreeGridColumn(int x, int y, const QString &cardName) const;
bool isColumnEmpty(int x, int y) const;
bool isColumnStacked(int x, int y) const;
void fixFreeSpaces(GameEventStorage &ges);
void moveCardInRow(GameEventStorage &ges, Server_Card *card, int x, int y);
void insertCard(Server_Card *card, int x, int y);
void updateCardCoordinates(Server_Card *card, int oldX, int oldY);
void shuffle();
void clear();
void addWritePermission(int playerId);
const QSet<int> &getPlayersWithWritePermission() const { return playersWithWritePermission; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
};
#endif

View file

@ -12,9 +12,9 @@ Server_Counter::Server_Counter(int _id, const QString &_name, const color &_coun
void Server_Counter::getInfo(ServerInfo_Counter *info)
{
info->set_id(id);
info->set_name(name.toStdString());
info->mutable_counter_color()->CopyFrom(counterColor);
info->set_radius(radius);
info->set_count(count);
info->set_id(id);
info->set_name(name.toStdString());
info->mutable_counter_color()->CopyFrom(counterColor);
info->set_radius(radius);
info->set_count(count);
}

View file

@ -27,22 +27,22 @@ class ServerInfo_Counter;
class Server_Counter {
protected:
int id;
QString name;
color counterColor;
int radius;
int count;
int id;
QString name;
color counterColor;
int radius;
int count;
public:
Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count = 0);
~Server_Counter() { }
int getId() const { return id; }
QString getName() const { return name; }
const color &getColor() const { return counterColor; }
int getRadius() const { return radius; }
int getCount() const { return count; }
void setCount(int _count) { count = _count; }
void getInfo(ServerInfo_Counter *info);
Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count = 0);
~Server_Counter() { }
int getId() const { return id; }
QString getName() const { return name; }
const color &getColor() const { return counterColor; }
int getRadius() const { return radius; }
int getCount() const { return count; }
void setCount(int _count) { count = _count; }
void getInfo(ServerInfo_Counter *info);
};
#endif

View file

@ -6,32 +6,32 @@
#include "server.h"
class Server_DatabaseInterface : public QObject {
Q_OBJECT
Q_OBJECT
public:
Server_DatabaseInterface(QObject *parent = 0)
: QObject(parent) { }
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0;
virtual bool userExists(const QString &user) { return false; }
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString &name) { return QMap<QString, ServerInfo_User>(); }
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) { return QMap<QString, ServerInfo_User>(); }
virtual bool isInBuddyList(const QString &whoseList, const QString &who) { return false; }
virtual bool isInIgnoreList(const QString &whoseList, const QString &who) { return false; }
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
virtual void storeGameInformation(const QString &roomName, const QStringList &roomGameTypes, const ServerInfo_Game &gameInfo, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replayList) { }
virtual DeckList *getDeckFromDatabase(int deckId, int userId) { return 0; }
virtual qint64 startSession(const QString &userName, const QString &address) { return 0; }
Server_DatabaseInterface(QObject *parent = 0)
: QObject(parent) { }
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0;
virtual bool userExists(const QString & /* user */) { return false; }
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual bool isInBuddyList(const QString & /* whoseList */, const QString & /* who */) { return false; }
virtual bool isInIgnoreList(const QString & /* whoseList */, const QString & /* who */) { return false; }
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
virtual void storeGameInformation(const QString & /* roomName */, const QStringList & /* roomGameTypes */, const ServerInfo_Game & /* gameInfo */, const QSet<QString> & /* allPlayersEver */, const QSet<QString> & /* allSpectatorsEver */, const QList<GameReplay *> & /* replayList */) { }
virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; }
virtual qint64 startSession(const QString & /* userName */, const QString & /* address */) { return 0; }
public slots:
virtual void endSession(qint64 sessionId) { }
virtual void endSession(qint64 /* sessionId */ ) { }
public:
virtual int getNextGameId() = 0;
virtual int getNextReplayId() = 0;
virtual void clearSessionTables() { }
virtual void lockSessionTables() { }
virtual void unlockSessionTables() { }
virtual bool userSessionExists(const QString &userName) { return false; }
virtual int getNextGameId() = 0;
virtual int getNextReplayId() = 0;
virtual void clearSessionTables() { }
virtual void lockSessionTables() { }
virtual void unlockSessionTables() { }
virtual bool userSessionExists(const QString & /* userName */) { return false; }
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -42,86 +42,86 @@ class Server_AbstractUserInterface;
class Event_GameStateChanged;
class Server_Game : public QObject {
Q_OBJECT
Q_OBJECT
private:
Server_Room *room;
int nextPlayerId;
int hostId;
ServerInfo_User *creatorInfo;
QMap<int, Server_Player *> players;
QSet<QString> allPlayersEver, allSpectatorsEver;
bool gameStarted;
bool gameClosed;
int gameId;
QString description;
QString password;
int maxPlayers;
QList<int> gameTypes;
int activePlayer, activePhase;
bool onlyBuddies, onlyRegistered;
bool spectatorsAllowed;
bool spectatorsNeedPassword;
bool spectatorsCanTalk;
bool spectatorsSeeEverything;
int inactivityCounter;
int startTimeOfThisGame, secondsElapsed;
bool firstGameStarted;
QDateTime startTime;
QTimer *pingClock;
QList<GameReplay *> replayList;
GameReplay *currentReplay;
void createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
void sendGameStateToPlayers();
void storeGameInformation();
Server_Room *room;
int nextPlayerId;
int hostId;
ServerInfo_User *creatorInfo;
QMap<int, Server_Player *> players;
QSet<QString> allPlayersEver, allSpectatorsEver;
bool gameStarted;
bool gameClosed;
int gameId;
QString description;
QString password;
int maxPlayers;
QList<int> gameTypes;
int activePlayer, activePhase;
bool onlyBuddies, onlyRegistered;
bool spectatorsAllowed;
bool spectatorsNeedPassword;
bool spectatorsCanTalk;
bool spectatorsSeeEverything;
int inactivityCounter;
int startTimeOfThisGame, secondsElapsed;
bool firstGameStarted;
QDateTime startTime;
QTimer *pingClock;
QList<GameReplay *> replayList;
GameReplay *currentReplay;
void createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
void sendGameStateToPlayers();
void storeGameInformation();
signals:
void sigStartGameIfReady();
void gameInfoChanged(ServerInfo_Game gameInfo);
void sigStartGameIfReady();
void gameInfoChanged(ServerInfo_Game gameInfo);
private slots:
void pingClockTimeout();
void doStartGameIfReady();
void pingClockTimeout();
void doStartGameIfReady();
public:
mutable QMutex gameMutex;
Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent);
~Server_Game();
Server_Room *getRoom() const { return room; }
void getInfo(ServerInfo_Game &result) const;
int getHostId() const { return hostId; }
ServerInfo_User *getCreatorInfo() const { return creatorInfo; }
bool getGameStarted() const { return gameStarted; }
int getPlayerCount() const;
int getSpectatorCount() const;
const QMap<int, Server_Player *> &getPlayers() const { return players; }
int getGameId() const { return gameId; }
QString getDescription() const { return description; }
QString getPassword() const { return password; }
int getMaxPlayers() const { return maxPlayers; }
bool getSpectatorsAllowed() const { return spectatorsAllowed; }
bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; }
bool getSpectatorsCanTalk() const { return spectatorsCanTalk; }
bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; }
Response::ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions);
bool containsUser(const QString &userName) const;
void addPlayer(Server_AbstractUserInterface *userInterface, ResponseContainer &rc, bool spectator, bool broadcastUpdate = true);
void removePlayer(Server_Player *player);
void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player);
void unattachCards(GameEventStorage &ges, Server_Player *player);
bool kickPlayer(int playerId);
void startGameIfReady();
void stopGameIfFinished();
int getActivePlayer() const { return activePlayer; }
int getActivePhase() const { return activePhase; }
void setActivePlayer(int _activePlayer);
void setActivePhase(int _activePhase);
void nextTurn();
int getSecondsElapsed() const { return secondsElapsed; }
mutable QMutex gameMutex;
Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent);
~Server_Game();
Server_Room *getRoom() const { return room; }
void getInfo(ServerInfo_Game &result) const;
int getHostId() const { return hostId; }
ServerInfo_User *getCreatorInfo() const { return creatorInfo; }
bool getGameStarted() const { return gameStarted; }
int getPlayerCount() const;
int getSpectatorCount() const;
const QMap<int, Server_Player *> &getPlayers() const { return players; }
int getGameId() const { return gameId; }
QString getDescription() const { return description; }
QString getPassword() const { return password; }
int getMaxPlayers() const { return maxPlayers; }
bool getSpectatorsAllowed() const { return spectatorsAllowed; }
bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; }
bool getSpectatorsCanTalk() const { return spectatorsCanTalk; }
bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; }
Response::ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions);
bool containsUser(const QString &userName) const;
void addPlayer(Server_AbstractUserInterface *userInterface, ResponseContainer &rc, bool spectator, bool broadcastUpdate = true);
void removePlayer(Server_Player *player);
void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player);
void unattachCards(GameEventStorage &ges, Server_Player *player);
bool kickPlayer(int playerId);
void startGameIfReady();
void stopGameIfFinished();
int getActivePlayer() const { return activePlayer; }
int getActivePhase() const { return activePhase; }
void setActivePlayer(int _activePlayer);
void setActivePhase(int _activePhase);
void nextTurn();
int getSecondsElapsed() const { return secondsElapsed; }
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming);
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext);
void sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1);
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming);
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext);
void sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -62,104 +62,104 @@ class Command_SetSideboardLock;
class Command_ChangeZoneProperties;
class Server_Player : public Server_ArrowTarget, public ServerInfo_User_Container {
Q_OBJECT
Q_OBJECT
private:
class MoveCardCompareFunctor;
Server_Game *game;
Server_AbstractUserInterface *userInterface;
DeckList *deck;
QMap<QString, Server_CardZone *> zones;
QMap<int, Server_Counter *> counters;
QMap<int, Server_Arrow *> arrows;
QList<int> lastDrawList;
int pingTime;
int playerId;
bool spectator;
int initialCards;
int nextCardId;
bool readyStart;
bool conceded;
bool sideboardLocked;
class MoveCardCompareFunctor;
Server_Game *game;
Server_AbstractUserInterface *userInterface;
DeckList *deck;
QMap<QString, Server_CardZone *> zones;
QMap<int, Server_Counter *> counters;
QMap<int, Server_Arrow *> arrows;
QList<int> lastDrawList;
int pingTime;
int playerId;
bool spectator;
int initialCards;
int nextCardId;
bool readyStart;
bool conceded;
bool sideboardLocked;
public:
mutable QMutex playerMutex;
Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_AbstractUserInterface *_handler);
~Server_Player();
void prepareDestroy();
Server_AbstractUserInterface *getUserInterface() const { return userInterface; }
void setUserInterface(Server_AbstractUserInterface *_userInterface);
void disconnectClient();
void setPlayerId(int _id) { playerId = _id; }
bool getReadyStart() const { return readyStart; }
void setReadyStart(bool _readyStart) { readyStart = _readyStart; }
int getPlayerId() const { return playerId; }
bool getSpectator() const { return spectator; }
bool getConceded() const { return conceded; }
void setConceded(bool _conceded) { conceded = _conceded; }
DeckList *getDeck() const { return deck; }
Server_Game *getGame() const { return game; }
const QMap<QString, Server_CardZone *> &getZones() const { return zones; }
const QMap<int, Server_Counter *> &getCounters() const { return counters; }
const QMap<int, Server_Arrow *> &getArrows() const { return arrows; }
int getPingTime() const { return pingTime; }
void setPingTime(int _pingTime) { pingTime = _pingTime; }
void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo);
int newCardId();
int newCounterId() const;
int newArrowId() const;
void addZone(Server_CardZone *zone);
void addArrow(Server_Arrow *arrow);
bool deleteArrow(int arrowId);
void addCounter(Server_Counter *counter);
void clearZones();
void setupZones();
mutable QMutex playerMutex;
Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_AbstractUserInterface *_handler);
~Server_Player();
void prepareDestroy();
Server_AbstractUserInterface *getUserInterface() const { return userInterface; }
void setUserInterface(Server_AbstractUserInterface *_userInterface);
void disconnectClient();
void setPlayerId(int _id) { playerId = _id; }
bool getReadyStart() const { return readyStart; }
void setReadyStart(bool _readyStart) { readyStart = _readyStart; }
int getPlayerId() const { return playerId; }
bool getSpectator() const { return spectator; }
bool getConceded() const { return conceded; }
void setConceded(bool _conceded) { conceded = _conceded; }
DeckList *getDeck() const { return deck; }
Server_Game *getGame() const { return game; }
const QMap<QString, Server_CardZone *> &getZones() const { return zones; }
const QMap<int, Server_Counter *> &getCounters() const { return counters; }
const QMap<int, Server_Arrow *> &getArrows() const { return arrows; }
int getPingTime() const { return pingTime; }
void setPingTime(int _pingTime) { pingTime = _pingTime; }
void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo);
int newCardId();
int newCounterId() const;
int newArrowId() const;
void addZone(Server_CardZone *zone);
void addArrow(Server_Arrow *arrow);
bool deleteArrow(int arrowId);
void addCounter(Server_Counter *counter);
void clearZones();
void setupZones();
Response::ResponseCode drawCards(GameEventStorage &ges, int number);
Response::ResponseCode moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces = true, bool undoingDraw = false);
void unattachCard(GameEventStorage &ges, Server_Card *card);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, const QString &zone, int cardId, CardAttribute attribute, const QString &attrValue);
Response::ResponseCode drawCards(GameEventStorage &ges, int number);
Response::ResponseCode moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces = true, bool undoingDraw = false);
void unattachCard(GameEventStorage &ges, Server_Card *card);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, const QString &zone, int cardId, CardAttribute attribute, const QString &attrValue);
Response::ResponseCode cmdLeaveGame(const Command_LeaveGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges);
void sendGameEvent(const GameEventContainer &event);
void getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
Response::ResponseCode cmdLeaveGame(const Command_LeaveGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdFlipCard(const Command_FlipCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateToken(const Command_CreateToken &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges);
void sendGameEvent(const GameEventContainer &event);
void getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
};
#endif

View file

@ -3,15 +3,15 @@
class PlayerReference {
private:
int roomId;
int gameId;
int playerId;
int roomId;
int gameId;
int playerId;
public:
PlayerReference(int _roomId, int _gameId, int _playerId) : roomId(_roomId), gameId(_gameId), playerId(_playerId) { }
int getRoomId() const { return roomId; }
int getGameId() const { return gameId; }
int getPlayerId() const { return playerId; }
bool operator==(const PlayerReference &other) { return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId)); }
PlayerReference(int _roomId, int _gameId, int _playerId) : roomId(_roomId), gameId(_gameId), playerId(_playerId) { }
int getRoomId() const { return roomId; }
int getGameId() const { return gameId; }
int getPlayerId() const { return playerId; }
bool operator==(const PlayerReference &other) { return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId)); }
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -40,64 +40,64 @@ class Command_CreateGame;
class Command_JoinGame;
class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface {
Q_OBJECT
Q_OBJECT
protected:
QMap<int, Server_Room *> rooms;
bool deleted;
Server_DatabaseInterface *databaseInterface;
AuthenticationResult authState;
bool acceptsUserListChanges;
bool acceptsRoomListChanges;
virtual void logDebugMessage(const QString &message) { }
QMap<int, Server_Room *> rooms;
bool deleted;
Server_DatabaseInterface *databaseInterface;
AuthenticationResult authState;
bool acceptsUserListChanges;
bool acceptsRoomListChanges;
virtual void logDebugMessage(const QString & /* message */) { }
private:
QList<int> messageSizeOverTime, messageCountOverTime;
int timeRunning, lastDataReceived;
QTimer *pingClock;
QList<int> messageSizeOverTime, messageCountOverTime;
int timeRunning, lastDataReceived;
QTimer *pingClock;
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
Response::ResponseCode cmdPing(const Command_Ping &cmd, ResponseContainer &rc);
Response::ResponseCode cmdLogin(const Command_Login &cmd, ResponseContainer &rc);
Response::ResponseCode cmdMessage(const Command_Message &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc);
Response::ResponseCode cmdListRooms(const Command_ListRooms &cmd, ResponseContainer &rc);
Response::ResponseCode cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc);
Response::ResponseCode cmdListUsers(const Command_ListUsers &cmd, ResponseContainer &rc);
Response::ResponseCode cmdLeaveRoom(const Command_LeaveRoom &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
Response::ResponseCode cmdPing(const Command_Ping &cmd, ResponseContainer &rc);
Response::ResponseCode cmdLogin(const Command_Login &cmd, ResponseContainer &rc);
Response::ResponseCode cmdMessage(const Command_Message &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc);
Response::ResponseCode cmdListRooms(const Command_ListRooms &cmd, ResponseContainer &rc);
Response::ResponseCode cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc);
Response::ResponseCode cmdListUsers(const Command_ListUsers &cmd, ResponseContainer &rc);
Response::ResponseCode cmdLeaveRoom(const Command_LeaveRoom &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedSessionCommand(int /* cmdType */, const SessionCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedModeratorCommand(int /* cmdType */, const ModeratorCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedAdminCommand(int /* cmdType */, const AdminCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
private slots:
void pingClockTimeout();
void pingClockTimeout();
public slots:
void prepareDestroy();
void prepareDestroy();
public:
Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~Server_ProtocolHandler();
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; }
virtual QString getAddress() const = 0;
Server_DatabaseInterface *getDatabaseInterface() const { return databaseInterface; }
Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~Server_ProtocolHandler();
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; }
virtual QString getAddress() const = 0;
Server_DatabaseInterface *getDatabaseInterface() const { return databaseInterface; }
int getLastCommandTime() const { return timeRunning - lastDataReceived; }
void processCommandContainer(const CommandContainer &cont);
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item);
int getLastCommandTime() const { return timeRunning - lastDataReceived; }
void processCommandContainer(const CommandContainer &cont);
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item);
};
#endif

View file

@ -4,20 +4,20 @@
void Server_RemoteUserInterface::sendProtocolItem(const Response &item)
{
server->sendIsl_Response(item, userInfo->server_id(), userInfo->session_id());
server->sendIsl_Response(item, userInfo->server_id(), userInfo->session_id());
}
void Server_RemoteUserInterface::sendProtocolItem(const SessionEvent &item)
{
server->sendIsl_SessionEvent(item, userInfo->server_id(), userInfo->session_id());
server->sendIsl_SessionEvent(item, userInfo->server_id(), userInfo->session_id());
}
void Server_RemoteUserInterface::sendProtocolItem(const GameEventContainer &item)
{
server->sendIsl_GameEventContainer(item, userInfo->server_id(), userInfo->session_id());
server->sendIsl_GameEventContainer(item, userInfo->server_id(), userInfo->session_id());
}
void Server_RemoteUserInterface::sendProtocolItem(const RoomEvent &item)
{
server->sendIsl_RoomEvent(item, userInfo->server_id(), userInfo->session_id());
server->sendIsl_RoomEvent(item, userInfo->server_id(), userInfo->session_id());
}

View file

@ -5,14 +5,14 @@
class Server_RemoteUserInterface : public Server_AbstractUserInterface {
public:
Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { }
int getLastCommandTime() const { return 0; }
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item);
Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { }
int getLastCommandTime() const { return 0; }
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item);
};
#endif

View file

@ -3,64 +3,64 @@
#include "server_game.h"
GameEventStorageItem::GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients)
: event(new GameEvent), recipients(_recipients)
: event(new GameEvent), recipients(_recipients)
{
event->GetReflection()->MutableMessage(event, _event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_event);
event->set_player_id(_playerId);
event->GetReflection()->MutableMessage(event, _event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_event);
event->set_player_id(_playerId);
}
GameEventStorageItem::~GameEventStorageItem()
{
delete event;
delete event;
}
GameEventStorage::GameEventStorage()
: gameEventContext(0)
: gameEventContext(0)
{
}
GameEventStorage::~GameEventStorage()
{
delete gameEventContext;
for (int i = 0; i < gameEventList.size(); ++i)
delete gameEventList[i];
delete gameEventContext;
for (int i = 0; i < gameEventList.size(); ++i)
delete gameEventList[i];
}
void GameEventStorage::setGameEventContext(const ::google::protobuf::Message &_gameEventContext)
{
delete gameEventContext;
gameEventContext = new GameEventContext;
gameEventContext->GetReflection()->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_gameEventContext);
delete gameEventContext;
gameEventContext = new GameEventContext;
gameEventContext->GetReflection()->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_gameEventContext);
}
void GameEventStorage::enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients, int _privatePlayerId)
{
gameEventList.append(new GameEventStorageItem(event, playerId, recipients));
if (_privatePlayerId != -1)
privatePlayerId = _privatePlayerId;
gameEventList.append(new GameEventStorageItem(event, playerId, recipients));
if (_privatePlayerId != -1)
privatePlayerId = _privatePlayerId;
}
void GameEventStorage::sendToGame(Server_Game *game)
{
if (gameEventList.isEmpty())
return;
GameEventContainer *contPrivate = new GameEventContainer;
GameEventContainer *contOthers = new GameEventContainer;
for (int i = 0; i < gameEventList.size(); ++i) {
const GameEvent &event = gameEventList[i]->getGameEvent();
const GameEventStorageItem::EventRecipients recipients = gameEventList[i]->getRecipients();
if (recipients.testFlag(GameEventStorageItem::SendToPrivate))
contPrivate->add_event_list()->CopyFrom(event);
if (recipients.testFlag(GameEventStorageItem::SendToOthers))
contOthers->add_event_list()->CopyFrom(event);
}
if (gameEventContext) {
contPrivate->mutable_context()->CopyFrom(*gameEventContext);
contOthers->mutable_context()->CopyFrom(*gameEventContext);
}
game->sendGameEventContainer(contPrivate, GameEventStorageItem::SendToPrivate, privatePlayerId);
game->sendGameEventContainer(contOthers, GameEventStorageItem::SendToOthers, privatePlayerId);
if (gameEventList.isEmpty())
return;
GameEventContainer *contPrivate = new GameEventContainer;
GameEventContainer *contOthers = new GameEventContainer;
for (int i = 0; i < gameEventList.size(); ++i) {
const GameEvent &event = gameEventList[i]->getGameEvent();
const GameEventStorageItem::EventRecipients recipients = gameEventList[i]->getRecipients();
if (recipients.testFlag(GameEventStorageItem::SendToPrivate))
contPrivate->add_event_list()->CopyFrom(event);
if (recipients.testFlag(GameEventStorageItem::SendToOthers))
contOthers->add_event_list()->CopyFrom(event);
}
if (gameEventContext) {
contPrivate->mutable_context()->CopyFrom(*gameEventContext);
contOthers->mutable_context()->CopyFrom(*gameEventContext);
}
game->sendGameEventContainer(contPrivate, GameEventStorageItem::SendToPrivate, privatePlayerId);
game->sendGameEventContainer(contOthers, GameEventStorageItem::SendToOthers, privatePlayerId);
}
ResponseContainer::ResponseContainer(int _cmdId)
@ -70,9 +70,9 @@ ResponseContainer::ResponseContainer(int _cmdId)
ResponseContainer::~ResponseContainer()
{
delete responseExtension;
for (int i = 0; i < preResponseQueue.size(); ++i)
delete preResponseQueue[i].second;
for (int i = 0; i < postResponseQueue.size(); ++i)
delete postResponseQueue[i].second;
delete responseExtension;
for (int i = 0; i < preResponseQueue.size(); ++i)
delete preResponseQueue[i].second;
for (int i = 0; i < postResponseQueue.size(); ++i)
delete postResponseQueue[i].second;
}

View file

@ -2,6 +2,7 @@
#define SERVER_RESPONSE_CONTAINERS_H
#include <QPair>
#include <QList>
#include "pb/server_message.pb.h"
namespace google { namespace protobuf { class Message; } }
@ -9,54 +10,54 @@ class Server_Game;
class GameEventStorageItem {
public:
enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
private:
GameEvent *event;
EventRecipients recipients;
GameEvent *event;
EventRecipients recipients;
public:
GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients);
~GameEventStorageItem();
const GameEvent &getGameEvent() const { return *event; }
EventRecipients getRecipients() const { return recipients; }
GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients);
~GameEventStorageItem();
const GameEvent &getGameEvent() const { return *event; }
EventRecipients getRecipients() const { return recipients; }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(GameEventStorageItem::EventRecipients)
class GameEventStorage {
private:
::google::protobuf::Message *gameEventContext;
QList<GameEventStorageItem *> gameEventList;
int privatePlayerId;
::google::protobuf::Message *gameEventContext;
QList<GameEventStorageItem *> gameEventList;
int privatePlayerId;
public:
GameEventStorage();
~GameEventStorage();
void setGameEventContext(const ::google::protobuf::Message &_gameEventContext);
::google::protobuf::Message *getGameEventContext() const { return gameEventContext; }
const QList<GameEventStorageItem *> &getGameEventList() const { return gameEventList; }
int getPrivatePlayerId() const { return privatePlayerId; }
void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1);
void sendToGame(Server_Game *game);
GameEventStorage();
~GameEventStorage();
void setGameEventContext(const ::google::protobuf::Message &_gameEventContext);
::google::protobuf::Message *getGameEventContext() const { return gameEventContext; }
const QList<GameEventStorageItem *> &getGameEventList() const { return gameEventList; }
int getPrivatePlayerId() const { return privatePlayerId; }
void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1);
void sendToGame(Server_Game *game);
};
class ResponseContainer {
private:
int cmdId;
::google::protobuf::Message *responseExtension;
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue;
int cmdId;
::google::protobuf::Message *responseExtension;
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue;
public:
ResponseContainer(int _cmdId);
~ResponseContainer();
int getCmdId() const { return cmdId; }
void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; }
::google::protobuf::Message *getResponseExtension() const { return responseExtension; }
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); }
void enqueuePostResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { postResponseQueue.append(qMakePair(type, item)); }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPreResponseQueue() const { return preResponseQueue; }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPostResponseQueue() const { return postResponseQueue; }
ResponseContainer(int _cmdId);
~ResponseContainer();
int getCmdId() const { return cmdId; }
void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; }
::google::protobuf::Message *getResponseExtension() const { return responseExtension; }
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); }
void enqueuePostResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { postResponseQueue.append(qMakePair(type, item)); }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPreResponseQueue() const { return preResponseQueue; }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPostResponseQueue() const { return postResponseQueue; }
};
#endif

View file

@ -13,326 +13,326 @@
#include <google/protobuf/descriptor.h>
Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent)
: QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive)
: QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive)
{
connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection);
connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection);
}
Server_Room::~Server_Room()
{
qDebug("Server_Room destructor");
gamesLock.lockForWrite();
const QList<Server_Game *> gameList = games.values();
for (int i = 0; i < gameList.size(); ++i)
delete gameList[i];
games.clear();
gamesLock.unlock();
usersLock.lockForWrite();
users.clear();
usersLock.unlock();
qDebug("Server_Room destructor");
gamesLock.lockForWrite();
const QList<Server_Game *> gameList = games.values();
for (int i = 0; i < gameList.size(); ++i)
delete gameList[i];
games.clear();
gamesLock.unlock();
usersLock.lockForWrite();
users.clear();
usersLock.unlock();
}
Server *Server_Room::getServer() const
{
return static_cast<Server *>(parent());
return static_cast<Server *>(parent());
}
const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, bool includeExternalData) const
{
result.set_room_id(id);
result.set_name(name.toStdString());
result.set_description(description.toStdString());
result.set_auto_join(autoJoin);
gamesLock.lockForRead();
result.set_game_count(games.size() + externalGames.size());
if (complete) {
QMapIterator<int, Server_Game *> gameIterator(games);
while (gameIterator.hasNext())
gameIterator.next().value()->getInfo(*result.add_game_list());
if (includeExternalData) {
QMapIterator<int, ServerInfo_Game> externalGameIterator(externalGames);
while (externalGameIterator.hasNext())
result.add_game_list()->CopyFrom(externalGameIterator.next().value());
}
}
gamesLock.unlock();
usersLock.lockForRead();
result.set_player_count(users.size() + externalUsers.size());
if (complete) {
QMapIterator<QString, Server_ProtocolHandler *> userIterator(users);
while (userIterator.hasNext())
result.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false));
if (includeExternalData) {
QMapIterator<QString, ServerInfo_User_Container> externalUserIterator(externalUsers);
while (externalUserIterator.hasNext())
result.add_user_list()->CopyFrom(externalUserIterator.next().value().copyUserInfo(false));
}
}
usersLock.unlock();
if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i) {
ServerInfo_GameType *gameTypeInfo = result.add_gametype_list();
gameTypeInfo->set_game_type_id(i);
gameTypeInfo->set_description(gameTypes[i].toStdString());
}
return result;
result.set_room_id(id);
result.set_name(name.toStdString());
result.set_description(description.toStdString());
result.set_auto_join(autoJoin);
gamesLock.lockForRead();
result.set_game_count(games.size() + externalGames.size());
if (complete) {
QMapIterator<int, Server_Game *> gameIterator(games);
while (gameIterator.hasNext())
gameIterator.next().value()->getInfo(*result.add_game_list());
if (includeExternalData) {
QMapIterator<int, ServerInfo_Game> externalGameIterator(externalGames);
while (externalGameIterator.hasNext())
result.add_game_list()->CopyFrom(externalGameIterator.next().value());
}
}
gamesLock.unlock();
usersLock.lockForRead();
result.set_player_count(users.size() + externalUsers.size());
if (complete) {
QMapIterator<QString, Server_ProtocolHandler *> userIterator(users);
while (userIterator.hasNext())
result.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false));
if (includeExternalData) {
QMapIterator<QString, ServerInfo_User_Container> externalUserIterator(externalUsers);
while (externalUserIterator.hasNext())
result.add_user_list()->CopyFrom(externalUserIterator.next().value().copyUserInfo(false));
}
}
usersLock.unlock();
if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i) {
ServerInfo_GameType *gameTypeInfo = result.add_gametype_list();
gameTypeInfo->set_game_type_id(i);
gameTypeInfo->set_description(gameTypes[i].toStdString());
}
return result;
}
RoomEvent *Server_Room::prepareRoomEvent(const ::google::protobuf::Message &roomEvent)
{
RoomEvent *event = new RoomEvent;
event->set_room_id(id);
event->GetReflection()->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(roomEvent);
return event;
RoomEvent *event = new RoomEvent;
event->set_room_id(id);
event->GetReflection()->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(roomEvent);
return event;
}
void Server_Room::addClient(Server_ProtocolHandler *client)
{
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(client->copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
users.insert(QString::fromStdString(client->getUserInfo()->name()), client);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(client->copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
users.insert(QString::fromStdString(client->getUserInfo()->name()), client);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
void Server_Room::removeClient(Server_ProtocolHandler *client)
{
usersLock.lockForWrite();
users.remove(QString::fromStdString(client->getUserInfo()->name()));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(client->getUserInfo()->name());
sendRoomEvent(prepareRoomEvent(event));
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
usersLock.lockForWrite();
users.remove(QString::fromStdString(client->getUserInfo()->name()));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(client->getUserInfo()->name());
sendRoomEvent(prepareRoomEvent(event));
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
void Server_Room::addExternalUser(const ServerInfo_User &userInfo)
{
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_User_Container userInfoContainer(userInfo);
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(userInfoContainer.copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event), false);
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_User_Container userInfoContainer(userInfo);
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(userInfoContainer.copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event), false);
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
emit roomInfoChanged(roomInfo);
usersLock.lockForWrite();
externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
emit roomInfoChanged(roomInfo);
}
void Server_Room::removeExternalUser(const QString &name)
{
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
if (externalUsers.contains(name))
externalUsers.remove(name);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(name.toStdString());
sendRoomEvent(prepareRoomEvent(event), false);
emit roomInfoChanged(roomInfo);
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
if (externalUsers.contains(name))
externalUsers.remove(name);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(name.toStdString());
sendRoomEvent(prepareRoomEvent(event), false);
emit roomInfoChanged(roomInfo);
}
void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo)
{
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
if (!gameInfo.has_player_count() && externalGames.contains(gameInfo.game_id()))
externalGames.remove(gameInfo.game_id());
else
externalGames.insert(gameInfo.game_id(), gameInfo);
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
broadcastGameListUpdate(gameInfo, false);
emit roomInfoChanged(roomInfo);
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
if (!gameInfo.has_player_count() && externalGames.contains(gameInfo.game_id()))
externalGames.remove(gameInfo.game_id());
else
externalGames.insert(gameInfo.game_id(), gameInfo);
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
broadcastGameListUpdate(gameInfo, false);
emit roomInfoChanged(roomInfo);
}
Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface)
{
// This function is called from the Server thread and from the S_PH thread.
// server->roomsMutex is always locked.
QReadLocker roomGamesLocker(&gamesLock);
Server_Game *g = games.value(cmd.game_id());
if (!g) {
if (externalGames.contains(cmd.game_id())) {
CommandContainer cont;
cont.set_cmd_id(rc.getCmdId());
RoomCommand *roomCommand = cont.add_room_command();
roomCommand->GetReflection()->MutableMessage(roomCommand, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
getServer()->sendIsl_RoomCommand(cont, externalGames.value(cmd.game_id()).server_id(), userInterface->getUserInfo()->session_id(), id);
return Response::RespNothing;
} else
return Response::RespNameNotFound;
}
QMutexLocker gameLocker(&g->gameMutex);
Response::ResponseCode result = g->checkJoin(userInterface->getUserInfo(), QString::fromStdString(cmd.password()), cmd.spectator(), cmd.override_restrictions());
if (result == Response::RespOk)
g->addPlayer(userInterface, rc, cmd.spectator());
return result;
// This function is called from the Server thread and from the S_PH thread.
// server->roomsMutex is always locked.
QReadLocker roomGamesLocker(&gamesLock);
Server_Game *g = games.value(cmd.game_id());
if (!g) {
if (externalGames.contains(cmd.game_id())) {
CommandContainer cont;
cont.set_cmd_id(rc.getCmdId());
RoomCommand *roomCommand = cont.add_room_command();
roomCommand->GetReflection()->MutableMessage(roomCommand, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
getServer()->sendIsl_RoomCommand(cont, externalGames.value(cmd.game_id()).server_id(), userInterface->getUserInfo()->session_id(), id);
return Response::RespNothing;
} else
return Response::RespNameNotFound;
}
QMutexLocker gameLocker(&g->gameMutex);
Response::ResponseCode result = g->checkJoin(userInterface->getUserInfo(), QString::fromStdString(cmd.password()), cmd.spectator(), cmd.override_restrictions());
if (result == Response::RespOk)
g->addPlayer(userInterface, rc, cmd.spectator());
return result;
}
void Server_Room::say(const QString &userName, const QString &s, bool sendToIsl)
{
Event_RoomSay event;
event.set_name(userName.toStdString());
event.set_message(s.toStdString());
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
Event_RoomSay event;
event.set_name(userName.toStdString());
event.set_message(s.toStdString());
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
}
void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl)
{
usersLock.lockForRead();
{
QMapIterator<QString, Server_ProtocolHandler *> userIterator(users);
while (userIterator.hasNext())
userIterator.next().value()->sendProtocolItem(*event);
}
usersLock.unlock();
if (sendToIsl)
static_cast<Server *>(parent())->sendIsl_RoomEvent(*event);
delete event;
usersLock.lockForRead();
{
QMapIterator<QString, Server_ProtocolHandler *> userIterator(users);
while (userIterator.hasNext())
userIterator.next().value()->sendProtocolItem(*event);
}
usersLock.unlock();
if (sendToIsl)
static_cast<Server *>(parent())->sendIsl_RoomEvent(*event);
delete event;
}
void Server_Room::broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl)
{
Event_ListGames event;
event.add_game_list()->CopyFrom(gameInfo);
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
Event_ListGames event;
event.add_game_list()->CopyFrom(gameInfo);
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
}
void Server_Room::addGame(Server_Game *game)
{
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
connect(game, SIGNAL(gameInfoChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)));
game->gameMutex.lock();
games.insert(game->getGameId(), game);
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
roomInfo.set_game_count(games.size() + externalGames.size());
game->gameMutex.unlock();
gamesLock.unlock();
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// -----------
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
connect(game, SIGNAL(gameInfoChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)));
game->gameMutex.lock();
games.insert(game->getGameId(), game);
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
roomInfo.set_game_count(games.size() + externalGames.size());
game->gameMutex.unlock();
gamesLock.unlock();
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// -----------
emit gameListChanged(gameInfo);
emit roomInfoChanged(roomInfo);
emit gameListChanged(gameInfo);
emit roomInfoChanged(roomInfo);
}
void Server_Room::removeGame(Server_Game *game)
{
// No need to lock gamesLock or gameMutex. This method is only
// called from ~Server_Game, which locks both mutexes anyway beforehand.
disconnect(game, 0, this, 0);
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
emit gameListChanged(gameInfo);
games.remove(game->getGameId());
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_game_count(games.size() + externalGames.size());
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
// No need to lock gamesLock or gameMutex. This method is only
// called from ~Server_Game, which locks both mutexes anyway beforehand.
disconnect(game, 0, this, 0);
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
emit gameListChanged(gameInfo);
games.remove(game->getGameId());
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_game_count(games.size() + externalGames.size());
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
int Server_Room::getGamesCreatedByUser(const QString &userName) const
{
QReadLocker locker(&gamesLock);
QMapIterator<int, Server_Game *> gamesIterator(games);
int result = 0;
while (gamesIterator.hasNext())
if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString())
++result;
return result;
QReadLocker locker(&gamesLock);
QMapIterator<int, Server_Game *> gamesIterator(games);
int result = 0;
while (gamesIterator.hasNext())
if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString())
++result;
return result;
}
QList<ServerInfo_Game> Server_Room::getGamesOfUser(const QString &userName) const
{
QReadLocker locker(&gamesLock);
QList<ServerInfo_Game> result;
QMapIterator<int, Server_Game *> gamesIterator(games);
while (gamesIterator.hasNext()) {
Server_Game *game = gamesIterator.next().value();
if (game->containsUser(userName)) {
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
result.append(gameInfo);
}
}
return result;
QReadLocker locker(&gamesLock);
QList<ServerInfo_Game> result;
QMapIterator<int, Server_Game *> gamesIterator(games);
while (gamesIterator.hasNext()) {
Server_Game *game = gamesIterator.next().value();
if (game->containsUser(userName)) {
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
result.append(gameInfo);
}
}
return result;
}

View file

@ -24,58 +24,58 @@ class ResponseContainer;
class Server_AbstractUserInterface;
class Server_Room : public QObject {
Q_OBJECT
Q_OBJECT
signals:
void roomInfoChanged(const ServerInfo_Room &roomInfo);
void gameListChanged(const ServerInfo_Game &gameInfo);
void roomInfoChanged(const ServerInfo_Room &roomInfo);
void gameListChanged(const ServerInfo_Game &gameInfo);
private:
int id;
QString name;
QString description;
bool autoJoin;
QString joinMessage;
QStringList gameTypes;
QMap<int, Server_Game *> games;
QMap<int, ServerInfo_Game> externalGames;
QMap<QString, Server_ProtocolHandler *> users;
QMap<QString, ServerInfo_User_Container> externalUsers;
int id;
QString name;
QString description;
bool autoJoin;
QString joinMessage;
QStringList gameTypes;
QMap<int, Server_Game *> games;
QMap<int, ServerInfo_Game> externalGames;
QMap<QString, Server_ProtocolHandler *> users;
QMap<QString, ServerInfo_User_Container> externalUsers;
private slots:
void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true);
void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true);
public:
mutable QReadWriteLock usersLock;
mutable QReadWriteLock gamesLock;
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
~Server_Room();
int getId() const { return id; }
QString getName() const { return name; }
QString getDescription() const { return description; }
bool getAutoJoin() const { return autoJoin; }
QString getJoinMessage() const { return joinMessage; }
const QStringList &getGameTypes() const { return gameTypes; }
const QMap<int, Server_Game *> &getGames() const { return games; }
const QMap<int, ServerInfo_Game> &getExternalGames() const { return externalGames; }
Server *getServer() const;
const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
int getGamesCreatedByUser(const QString &name) const;
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
void addClient(Server_ProtocolHandler *client);
void removeClient(Server_ProtocolHandler *client);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &name);
const QMap<QString, ServerInfo_User_Container> &getExternalUsers() const { return externalUsers; }
void updateExternalGameList(const ServerInfo_Game &gameInfo);
Response::ResponseCode processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface);
void say(const QString &userName, const QString &s, bool sendToIsl = true);
void addGame(Server_Game *game);
void removeGame(Server_Game *game);
void sendRoomEvent(RoomEvent *event, bool sendToIsl = true);
RoomEvent *prepareRoomEvent(const ::google::protobuf::Message &roomEvent);
mutable QReadWriteLock usersLock;
mutable QReadWriteLock gamesLock;
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
~Server_Room();
int getId() const { return id; }
QString getName() const { return name; }
QString getDescription() const { return description; }
bool getAutoJoin() const { return autoJoin; }
QString getJoinMessage() const { return joinMessage; }
const QStringList &getGameTypes() const { return gameTypes; }
const QMap<int, Server_Game *> &getGames() const { return games; }
const QMap<int, ServerInfo_Game> &getExternalGames() const { return externalGames; }
Server *getServer() const;
const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
int getGamesCreatedByUser(const QString &name) const;
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
void addClient(Server_ProtocolHandler *client);
void removeClient(Server_ProtocolHandler *client);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &name);
const QMap<QString, ServerInfo_User_Container> &getExternalUsers() const { return externalUsers; }
void updateExternalGameList(const ServerInfo_Game &gameInfo);
Response::ResponseCode processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface);
void say(const QString &userName, const QString &s, bool sendToIsl = true);
void addGame(Server_Game *game);
void removeGame(Server_Game *game);
void sendRoomEvent(RoomEvent *event, bool sendToIsl = true);
RoomEvent *prepareRoomEvent(const ::google::protobuf::Message &roomEvent);
};
#endif

View file

@ -7,46 +7,46 @@ ServerInfo_User_Container::ServerInfo_User_Container(ServerInfo_User *_userInfo)
}
ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User &_userInfo)
: userInfo(new ServerInfo_User(_userInfo))
: userInfo(new ServerInfo_User(_userInfo))
{
}
ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User_Container &other)
{
if (other.userInfo)
userInfo = new ServerInfo_User(*other.userInfo);
else
userInfo = 0;
if (other.userInfo)
userInfo = new ServerInfo_User(*other.userInfo);
else
userInfo = 0;
}
ServerInfo_User_Container::~ServerInfo_User_Container()
{
delete userInfo;
delete userInfo;
}
void ServerInfo_User_Container::setUserInfo(const ServerInfo_User &_userInfo)
{
userInfo = new ServerInfo_User(_userInfo);
userInfo = new ServerInfo_User(_userInfo);
}
ServerInfo_User &ServerInfo_User_Container::copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo, bool sessionInfo) const
{
if (userInfo) {
result.CopyFrom(*userInfo);
if (!sessionInfo) {
result.clear_session_id();
result.clear_address();
}
if (!internalInfo)
result.clear_id();
if (!complete)
result.clear_avatar_bmp();
}
return result;
if (userInfo) {
result.CopyFrom(*userInfo);
if (!sessionInfo) {
result.clear_session_id();
result.clear_address();
}
if (!internalInfo)
result.clear_id();
if (!complete)
result.clear_avatar_bmp();
}
return result;
}
ServerInfo_User ServerInfo_User_Container::copyUserInfo(bool complete, bool internalInfo, bool sessionInfo) const
{
ServerInfo_User result;
return copyUserInfo(result, complete, internalInfo, sessionInfo);
ServerInfo_User result;
return copyUserInfo(result, complete, internalInfo, sessionInfo);
}

Some files were not shown because too many files have changed in this diff Show more