Merge remote-tracking branch 'upstream/master'

Some tabs to spaces, and maybe fixed to work with Qt 5.

Conflicts:
	cockatrice/src/deckstats_interface.cpp
	common/decklist.cpp
	common/decklist.h
	oracle/src/oracleimporter.cpp
This commit is contained in:
Waleed Khan 2014-07-20 14:40:18 -04:00
commit 359882917a
98 changed files with 5371 additions and 4720 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ tags
build* build*
*.qm *.qm
.directory .directory
mysql.cnf

View file

@ -7,13 +7,21 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
set(PROJECT_NAME "Cockatrice") if(POLICY CMP0020)
set(PROJECT_VERSION_MAJOR 0) cmake_policy(SET CMP0020 OLD)
set(PROJECT_VERSION_MINOR 0) endif()
set(PROJECT_VERSION_PATCH 1)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} )
# 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 # User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
IF(DEFINED CMAKE_BUILD_TYPE) IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build") SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
@ -24,9 +32,19 @@ ENDIF()
# A project name is needed for CPack # A project name is needed for CPack
PROJECT("${PROJECT_NAME}") PROJECT("${PROJECT_NAME}")
# Set conventional loops # Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) 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 # Define a proper install path
if(UNIX) if(UNIX)
if(APPLE) if(APPLE)
@ -71,8 +89,33 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
ADD_DEFINITIONS("-DSFMT_MEXP=19937") ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF() ENDIF()
#Find Qt4 and enable the needed features # Find Qt and enable the needed features
FIND_PACKAGE(Qt4 REQUIRED) # 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) set(CMAKE_AUTOMOC TRUE)
@ -83,8 +126,8 @@ FIND_PACKAGE(Protobuf REQUIRED)
set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com") set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team") set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
@ -96,7 +139,7 @@ if(UNIX)
set(CPACK_DMG_FORMAT "UDBZ") set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}") set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX") 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") set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
else() else()
# linux # linux
@ -107,13 +150,13 @@ if(UNIX)
endif() endif()
elseif(WIN32) elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR}) set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}\\\\${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_win32_git-${PROJECT_VERSION}")
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\${PROJECT_NAME}.exe")
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}") # Configure file with custom definitions for NSIS.
set(CPACK_NSIS_HELP_LINK "https://github.com/Daenyth/Cockatrice") configure_file(
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/Daenyth/Cockatrice") ${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
set(CPACK_NSIS_CONTACT "Daenyth+github@gmail.com") ${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
set(CPACK_NSIS_MODIFY_PATH ON) )
endif() endif()
include(CPack) include(CPack)

View file

@ -33,8 +33,9 @@ To compile:
The following flags can be passed to `cmake`: The following flags can be passed to `cmake`:
- `-DWITH_SERVER=1` build the server - `-DWITH_SERVER=1` Build the server
- `-DWITHOUT_CLIENT=1` do not build the client - `-DWITHOUT_CLIENT=1` Do not build the client
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5.
# Running # 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 "MUI2.nsh"
!include "FileFunc.nsh" !include "FileFunc.nsh"
!define /date TIMESTAMP "%Y%m%d" Name "@CPACK_PACKAGE_NAME@"
!searchparse /file ../build/cockatrice/version_string.cpp '= "' VERSION '";' OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
Name "Cockatrice"
OutFile "cockatrice_win32_${TIMESTAMP}_git-${VERSION}.exe"
SetCompressor /SOLID lzma SetCompressor /SOLID lzma
InstallDir "$PROGRAMFILES\Cockatrice" InstallDir "$PROGRAMFILES\Cockatrice"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
; 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 MUI_ABORTWARNING !define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_HEADERIMAGE !define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "headerimage.bmp" !define MUI_HEADERIMAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "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_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 "$INSTDIR/oracle.exe"
!define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now" !define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now"
!define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets" !define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets"
!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\COPYING" !insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\COPYING"
!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
@ -39,37 +35,9 @@ InstallDir "$PROGRAMFILES\Cockatrice"
Section "Application" SecApplication Section "Application" SecApplication
SetShellVarContext all SetShellVarContext all
SetOutPath "$INSTDIR" 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" @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
File /r ..\zonebg\*.* @CPACK_NSIS_FULL_INSTALL@
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
WriteUninstaller "$INSTDIR\uninstall.exe" WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
@ -107,12 +75,10 @@ SetShellVarContext all
Delete "$INSTDIR\oracle.exe" Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\Usermanual.pdf" Delete "$INSTDIR\Usermanual.pdf"
Delete "$INSTDIR\libprotobuf.lib" Delete "$INSTDIR\libprotobuf.lib"
Delete "$INSTDIR\QtCore4.dll" Delete "$INSTDIR\Qt*.dll"
Delete "$INSTDIR\QtGui4.dll" Delete "$INSTDIR\icu*.dll"
Delete "$INSTDIR\QtNetwork4.dll" Delete "$INSTDIR\qt.conf"
Delete "$INSTDIR\QtSvg4.dll" Delete "$INSTDIR\qdebug.txt"
Delete "$INSTDIR\QtXml4.dll"
Delete "$INSTDIR\QtMultimedia4.dll"
RMDir "$INSTDIR" RMDir "$INSTDIR"
RMDir "$SMPROGRAMS\Cockatrice" 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) if(GIT_FOUND)
execute_process( execute_process(
COMMAND ${GIT_EXECUTABLE} describe --long --always COMMAND ${GIT_EXECUTABLE} describe --long --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID OUTPUT_VARIABLE GIT_COM_ID
) )
@ -15,15 +16,5 @@ else()
message( WARNING "Git not found. Build will not contain git revision info." ) message( WARNING "Git not found. Build will not contain git revision info." )
endif() endif()
set( hstring "extern const char *VERSION_STRING\;\n" ) set(PROJECT_VERSION_MAJOR ${GIT_COMMIT_ID})
set( cppstring "const char * VERSION_STRING = \"${GIT_COMMIT_ID}\"\;\n") set(PROJECT_VERSION ${GIT_COMMIT_ID} )
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
)

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View file

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

View file

@ -90,7 +90,7 @@ SET(cockatrice_SOURCES
src/qt-json/json.cpp src/qt-json/json.cpp
src/soundengine.cpp src/soundengine.cpp
src/pending_command.cpp src/pending_command.cpp
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${VERSION_STRING_CPP}
) )
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@ -125,41 +125,119 @@ if(APPLE)
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns) set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE) ENDIF(APPLE)
if (NOT QT_QTMULTIMEDIA_FOUND) set(COCKATRICE_LIBS)
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(QtMobility REQUIRED)
endif (NOT QT_QTMULTIMEDIA_FOUND)
SET(QT_USE_QTNETWORK TRUE) # Qt4 stuff
SET(QT_USE_QTMULTIMEDIA TRUE) if(Qt4_FOUND)
SET(QT_USE_QTXML TRUE) if (NOT QT_QTMULTIMEDIA_FOUND)
SET(QT_USE_QTSVG TRUE) 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 # Declare path variables
set(ICONDIR share/icons CACHE STRING "icon dir") set(ICONDIR share/icons CACHE STRING "icon dir")
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination") 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 directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(../common) INCLUDE_DIRECTORIES(../common)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) 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 # Build cockatrice binary and link it
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS}) 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) if(Qt4_FOUND)
set_target_properties(cockatrice PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS") if(MSVC)
endif(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(UNIX)
if(APPLE) if(APPLE)
@ -178,11 +256,6 @@ elseif(WIN32)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations) INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
endif() 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) if(APPLE)
# these needs to be relative to CMAKE_INSTALL_PREFIX # these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins) 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}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() 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,7 +11,11 @@
AbstractCounter::AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent) 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) : 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); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
if (player->getLocal()) { if (player->getLocal()) {
menu = new QMenu(name); menu = new QMenu(name);
@ -129,7 +133,13 @@ void AbstractCounter::setCounter()
{ {
bool ok; bool ok;
dialogSemaphore = true; 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) { if (deleteAfterDialog) {
deleteLater(); deleteLater();
return; return;

View file

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

View file

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

View file

@ -30,6 +30,8 @@ DeckListModel::~DeckListModel()
void DeckListModel::rebuildTree() void DeckListModel::rebuildTree()
{ {
beginResetModel();
root->clearTree(); root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot(); InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) { for (int i = 0; i < listRoot->size(); i++) {
@ -55,7 +57,7 @@ void DeckListModel::rebuildTree()
} }
} }
reset(); endResetModel();
} }
int DeckListModel::rowCount(const QModelIndex &parent) const int DeckListModel::rowCount(const QModelIndex &parent) const

View file

@ -7,6 +7,10 @@
#include <QMessageBox> #include <QMessageBox>
#include <QDesktopServices> #include <QDesktopServices>
#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif
DeckStatsInterface::DeckStatsInterface( DeckStatsInterface::DeckStatsInterface(
CardDatabase &_cardDatabase, CardDatabase &_cardDatabase,
QObject *parent QObject *parent
@ -41,16 +45,28 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
deleteLater(); deleteLater();
} }
void DeckStatsInterface::analyzeDeck(DeckList *deck) void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
{ {
QUrl params;
DeckList deckWithoutTokens; DeckList deckWithoutTokens;
copyDeckWithoutTokens(*deck, deckWithoutTokens); copyDeckWithoutTokens(*deck, deckWithoutTokens);
#if QT_VERSION < 0x050000
QUrl params;
params.addQueryItem("deck", deckWithoutTokens.writeToString_Plain()); 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)
{
QByteArray data; QByteArray data;
data.append(params.encodedQuery()); getAnalyzeRequestData(deck, &data);
QNetworkRequest request(QUrl("http://deckstats.net/index.php")); QNetworkRequest request(QUrl("http://deckstats.net/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

View file

@ -5,6 +5,7 @@
#include "decklist.h" #include "decklist.h"
#include <QObject> #include <QObject>
class QByteArray;
class QNetworkAccessManager; class QNetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class DeckList; class DeckList;
@ -25,6 +26,7 @@ private:
private slots: private slots:
void queryFinished(QNetworkReply *reply); void queryFinished(QNetworkReply *reply);
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
public: public:
DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0); DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
void analyzeDeck(DeckList *deck); 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) DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent)
: AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0) : AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0)
{ {
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
} }
DeckViewCard::~DeckViewCard() DeckViewCard::~DeckViewCard()

View file

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

View file

@ -73,8 +73,13 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
chooseTokenView->header()->setStretchLastSection(false); chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1); chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2); chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents); chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setResizeMode(4, 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))); connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex)));
QAction *aAddToken = new QAction(tr("Add token"), this); QAction *aAddToken = new QAction(tr("Add token"), this);

View file

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

View file

@ -19,6 +19,16 @@ private:
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes; QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
QSpinBox *maxPlayersFilterMinSpinBox; QSpinBox *maxPlayersFilterMinSpinBox;
QSpinBox *maxPlayersFilterMaxSpinBox; 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: public:
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0); DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);

View file

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

View file

@ -55,6 +55,7 @@ QString translationPath = TRANSLATION_PATH;
QString translationPath = QString(); QString translationPath = QString();
#endif #endif
#if QT_VERSION < 0x050000
static void myMessageOutput(QtMsgType /*type*/, const char *msg) static void myMessageOutput(QtMsgType /*type*/, const char *msg)
{ {
QFile file("qdebug.txt"); QFile file("qdebug.txt");
@ -63,6 +64,16 @@ static void myMessageOutput(QtMsgType /*type*/, const char *msg)
out << msg << endl; out << msg << endl;
file.close(); 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() void installNewTranslator()
{ {
@ -87,11 +98,21 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
if (app.arguments().contains("--debug-output")) if (app.arguments().contains("--debug-output"))
{
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
app.addLibraryPath(app.applicationDirPath() + "/plugins"); app.addLibraryPath(app.applicationDirPath() + "/plugins");
#endif #endif
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cockatrice"); QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice.de"); QCoreApplication::setOrganizationDomain("cockatrice.de");
@ -115,7 +136,12 @@ int main(int argc, char *argv[])
qsrand(QDateTime::currentDateTime().toTime_t()); qsrand(QDateTime::currentDateTime().toTime_t());
bool startMainProgram = true;
#if QT_VERSION < 0x050000
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
const QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
if (!db->getLoadSuccess()) if (!db->getLoadSuccess())
if (db->loadCardDatabase(dataDir + "/cards.xml")) if (db->loadCardDatabase(dataDir + "/cards.xml"))
settingsCache->setCardDatabasePath(dataDir + "/cards.xml"); settingsCache->setCardDatabasePath(dataDir + "/cards.xml");

View file

@ -13,7 +13,11 @@ PileZone::PileZone(Player *_p, const QString &_name, bool _isShufflable, bool _c
: CardZone(_p, _name, false, _isShufflable, _contentsKnown, parent) : CardZone(_p, _name, false, _isShufflable, _contentsKnown, parent)
{ {
setCacheMode(DeviceCoordinateCache); // Do not move this line to the parent constructor! setCacheMode(DeviceCoordinateCache); // Do not move this line to the parent constructor!
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
setCursor(Qt::OpenHandCursor); 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)); 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() void Player::actViewTopCards()
{ {
bool ok; 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) { if (ok) {
defaultNumberTopCards = number; defaultNumberTopCards = number;
static_cast<GameScene *>(scene())->toggleZoneView(this, "deck", number); static_cast<GameScene *>(scene())->toggleZoneView(this, "deck", number);
@ -829,7 +835,13 @@ void Player::actMulligan()
void Player::actDrawCards() 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) { if (number) {
Command_DrawCards cmd; Command_DrawCards cmd;
cmd.set_number(number); cmd.set_number(number);
@ -844,8 +856,14 @@ void Player::actUndoDraw()
void Player::actMoveTopCardsToGrave() void Player::actMoveTopCardsToGrave()
{ {
int number = QInputDialog::getInteger(0, tr("Move top cards to grave"), tr("Number:")); int number =
if (!number) #if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to grave"), tr("Number:"));
if (!number)
return; return;
const int maxCards = zones.value("deck")->getCards().size(); const int maxCards = zones.value("deck")->getCards().size();
@ -867,8 +885,14 @@ void Player::actMoveTopCardsToGrave()
void Player::actMoveTopCardsToExile() void Player::actMoveTopCardsToExile()
{ {
int number = QInputDialog::getInteger(0, tr("Move top cards to exile"), tr("Number:")); int number =
if (!number) #if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to exile"), tr("Number:"));
if (!number)
return; return;
const int maxCards = zones.value("deck")->getCards().size(); const int maxCards = zones.value("deck")->getCards().size();
@ -914,7 +938,13 @@ void Player::actUntapAll()
void Player::actRollDie() void Player::actRollDie()
{ {
bool ok; 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) { if (ok) {
Command_RollDie cmd; Command_RollDie cmd;
cmd.set_sides(sides); cmd.set_sides(sides);
@ -2022,7 +2052,13 @@ void Player::actCardCounterTrigger()
case 11: { case 11: {
bool ok; bool ok;
dialogSemaphore = true; 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; dialogSemaphore = false;
if (clearCardsToDelete()) if (clearCardsToDelete())
return; return;

View file

@ -72,7 +72,11 @@ PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient
setColumnCount(6); setColumnCount(6);
setHeaderHidden(true); setHeaderHidden(true);
setRootIsDecorated(false); setRootIsDecorated(false);
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents); header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
retranslateUi(); retranslateUi();
} }

View file

@ -553,7 +553,7 @@ int Json::nextToken(const QString &json, int &index)
QChar c = json[index]; QChar c = json[index];
index++; index++;
switch(c.toAscii()) switch(c.toLatin1())
{ {
case '{': return JsonTokenCurlyOpen; case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose; 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) : AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), messageLength(0)
{ {
timer = new QTimer(this); timer = new QTimer(this);
timer->setInterval(9000); timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(ping())); connect(timer, SIGNAL(timeout()), this, SLOT(ping()));
socket = new QTcpSocket(this); 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); const Response_DeckList &resp = r.GetExtension(Response_DeckList::ext);
beginResetModel();
root->clearTree(); root->clearTree();
reset();
endResetModel();
ServerInfo_DeckStorage_TreeItem tempRoot; ServerInfo_DeckStorage_TreeItem tempRoot;
tempRoot.set_id(0); tempRoot.set_id(0);
@ -280,7 +283,11 @@ RemoteDeckList_TreeWidget::RemoteDeckList_TreeWidget(AbstractClient *_client, QW
setModel(proxyModel); setModel(proxyModel);
connect(treeModel, SIGNAL(treeRefreshed()), this, SLOT(expandAll())); connect(treeModel, SIGNAL(treeRefreshed()), this, SLOT(expandAll()));
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents); header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
setUniformRowHeights(true); setUniformRowHeights(true);
setSortingEnabled(true); setSortingEnabled(true);
proxyModel->sort(0, Qt::AscendingOrder); proxyModel->sort(0, Qt::AscendingOrder);

View file

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

View file

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

View file

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

View file

@ -134,7 +134,11 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
deckView->setUniformRowHeights(true); deckView->setUniformRowHeights(true);
deckView->setSortingEnabled(true); deckView->setSortingEnabled(true);
deckView->sortByColumn(1, Qt::AscendingOrder); deckView->sortByColumn(1, Qt::AscendingOrder);
#if QT_VERSION < 0x050000
deckView->header()->setResizeMode(QHeaderView::ResizeToContents); deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
deckView->installEventFilter(&deckViewKeySignals); deckView->installEventFilter(&deckViewKeySignals);
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement())); connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -479,6 +479,7 @@ void TabSupervisor::updateCurrent(int index)
tab->setContentsChanged(false); tab->setContentsChanged(false);
} }
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus()); emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
tab->tabActivated();
} else } else
emit setMenu(); emit setMenu();
} }

View file

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

View file

@ -216,7 +216,11 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL
userTree = new QTreeWidget; userTree = new QTreeWidget;
userTree->setColumnCount(3); userTree->setColumnCount(3);
#if QT_VERSION < 0x050000
userTree->header()->setResizeMode(QHeaderView::ResizeToContents); userTree->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
userTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
userTree->setHeaderHidden(true); userTree->setHeaderHidden(true);
userTree->setRootIsDecorated(false); userTree->setRootIsDecorated(false);
userTree->setIconSize(QSize(20, 12)); userTree->setIconSize(QSize(20, 12));

View file

@ -241,7 +241,7 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
{ {
switch (r) { switch (r) {
case Response::RespWrongPassword: case Response::RespWrongPassword:
QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); QMessageBox::critical(this, tr("Error"), tr("Incorrect username or password. Please check your authentication information and try again."));
break; break;
case Response::RespWouldOverwriteOldSession: case Response::RespWouldOverwriteOldSession:
QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login.")); QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login."));

View file

@ -28,7 +28,20 @@ SET(common_SOURCES
sfmt/SFMT.c 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(pb)
INCLUDE_DIRECTORIES(sfmt) INCLUDE_DIRECTORIES(sfmt)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -2,9 +2,9 @@
#define GET_PB_EXTENSION_H #define GET_PB_EXTENSION_H
namespace google { namespace google {
namespace protobuf { namespace protobuf {
class Message; class Message;
} }
} }
int getPbExtension(const ::google::protobuf::Message &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) QVector<int> RNG_Abstract::makeNumbersVector(int n, int min, int max)
{ {
const int bins = max - min + 1; const int bins = max - min + 1;
QVector<int> result(bins); QVector<int> result(bins);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
int number = rand(min, max); int number = rand(min, max);
if ((number < min) || (number > max)) if ((number < min) || (number > max))
qDebug() << "rand(" << min << "," << max << ") returned " << number; qDebug() << "rand(" << min << "," << max << ") returned " << number;
else else
result[number - min]++; result[number - min]++;
} }
return result; return result;
} }
double RNG_Abstract::testRandom(const QVector<int> &numbers) const double RNG_Abstract::testRandom(const QVector<int> &numbers) const
{ {
int n = 0; int n = 0;
for (int i = 0; i < numbers.size(); ++i) for (int i = 0; i < numbers.size(); ++i)
n += numbers[i]; n += numbers[i];
double expected = (double) n / (double) numbers.size(); double expected = (double) n / (double) numbers.size();
double chisq = 0; double chisq = 0;
for (int i = 0; i < numbers.size(); ++i) for (int i = 0; i < numbers.size(); ++i)
chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected; chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected;
return chisq; return chisq;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -18,31 +18,31 @@ class Server_Game;
class Server_AbstractUserInterface : public ServerInfo_User_Container { class Server_AbstractUserInterface : public ServerInfo_User_Container {
private: private:
mutable QMutex gameListMutex; mutable QMutex gameListMutex;
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId) QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
protected: protected:
Server *server; Server *server;
public: public:
Server_AbstractUserInterface(Server *_server) : server(_server) { } Server_AbstractUserInterface(Server *_server) : server(_server) { }
Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { } Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { }
virtual ~Server_AbstractUserInterface() { } virtual ~Server_AbstractUserInterface() { }
virtual int getLastCommandTime() const = 0; virtual int getLastCommandTime() const = 0;
void playerRemovedFromGame(Server_Game *game); void playerRemovedFromGame(Server_Game *game);
void playerAddedToGame(int gameId, int roomId, int playerId); void playerAddedToGame(int gameId, int roomId, int playerId);
void joinPersistentGames(ResponseContainer &rc); void joinPersistentGames(ResponseContainer &rc);
QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; } QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; }
virtual void sendProtocolItem(const Response &item) = 0; virtual void sendProtocolItem(const Response &item) = 0;
virtual void sendProtocolItem(const SessionEvent &item) = 0; virtual void sendProtocolItem(const SessionEvent &item) = 0;
virtual void sendProtocolItem(const GameEventContainer &item) = 0; virtual void sendProtocolItem(const GameEventContainer &item) = 0;
virtual void sendProtocolItem(const RoomEvent &item) = 0; virtual void sendProtocolItem(const RoomEvent &item) = 0;
void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item); void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item);
static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent); static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent);
void sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode); void sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode);
}; };
#endif #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) void Server_Arrow::getInfo(ServerInfo_Arrow *info)
{ {
info->set_id(id); info->set_id(id);
info->set_start_player_id(startCard->getZone()->getPlayer()->getPlayerId()); info->set_start_player_id(startCard->getZone()->getPlayer()->getPlayerId());
info->set_start_zone(startCard->getZone()->getName().toStdString()); info->set_start_zone(startCard->getZone()->getName().toStdString());
info->set_start_card_id(startCard->getId()); info->set_start_card_id(startCard->getId());
info->mutable_arrow_color()->CopyFrom(arrowColor); info->mutable_arrow_color()->CopyFrom(arrowColor);
Server_Card *targetCard = qobject_cast<Server_Card *>(targetItem); Server_Card *targetCard = qobject_cast<Server_Card *>(targetItem);
if (targetCard) { if (targetCard) {
info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId()); info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
info->set_target_zone(targetCard->getZone()->getName().toStdString()); info->set_target_zone(targetCard->getZone()->getName().toStdString());
info->set_target_card_id(targetCard->getId()); info->set_target_card_id(targetCard->getId());
} else } else
info->set_target_player_id(static_cast<Server_Player *>(targetItem)->getPlayerId()); info->set_target_player_id(static_cast<Server_Player *>(targetItem)->getPlayerId());
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,32 +6,32 @@
#include "server.h" #include "server.h"
class Server_DatabaseInterface : public QObject { class Server_DatabaseInterface : public QObject {
Q_OBJECT Q_OBJECT
public: public:
Server_DatabaseInterface(QObject *parent = 0) Server_DatabaseInterface(QObject *parent = 0)
: QObject(parent) { } : QObject(parent) { }
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0; 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 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> getBuddyList(const QString &name) { return QMap<QString, ServerInfo_User>(); }
virtual QMap<QString, ServerInfo_User> getIgnoreList(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 isInBuddyList(const QString &whoseList, const QString &who) { return false; }
virtual bool isInIgnoreList(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 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 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 DeckList *getDeckFromDatabase(int deckId, int userId) { return 0; }
virtual qint64 startSession(const QString &userName, const QString &address) { return 0; } virtual qint64 startSession(const QString &userName, const QString &address) { return 0; }
public slots: public slots:
virtual void endSession(qint64 sessionId) { } virtual void endSession(qint64 sessionId) { }
public: public:
virtual int getNextGameId() = 0; virtual int getNextGameId() = 0;
virtual int getNextReplayId() = 0; virtual int getNextReplayId() = 0;
virtual void clearSessionTables() { } virtual void clearSessionTables() { }
virtual void lockSessionTables() { } virtual void lockSessionTables() { }
virtual void unlockSessionTables() { } virtual void unlockSessionTables() { }
virtual bool userSessionExists(const QString &userName) { return false; } virtual bool userSessionExists(const QString &userName) { return false; }
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -21,17 +21,17 @@
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent) Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent)
: QObject(parent), : QObject(parent),
Server_AbstractUserInterface(_server), Server_AbstractUserInterface(_server),
deleted(false), deleted(false),
databaseInterface(_databaseInterface), databaseInterface(_databaseInterface),
authState(NotLoggedIn), authState(NotLoggedIn),
acceptsUserListChanges(false), acceptsUserListChanges(false),
acceptsRoomListChanges(false), acceptsRoomListChanges(false),
timeRunning(0), timeRunning(0),
lastDataReceived(0) lastDataReceived(0)
{ {
connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout()));
} }
Server_ProtocolHandler::~Server_ProtocolHandler() Server_ProtocolHandler::~Server_ProtocolHandler()
@ -42,540 +42,540 @@ Server_ProtocolHandler::~Server_ProtocolHandler()
// The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock). // The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock).
void Server_ProtocolHandler::prepareDestroy() void Server_ProtocolHandler::prepareDestroy()
{ {
if (deleted) if (deleted)
return; return;
deleted = true; deleted = true;
QMapIterator<int, Server_Room *> roomIterator(rooms); QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext()) while (roomIterator.hasNext())
roomIterator.next().value()->removeClient(this); roomIterator.next().value()->removeClient(this);
QMap<int, QPair<int, int> > tempGames(getGames()); QMap<int, QPair<int, int> > tempGames(getGames());
server->roomsLock.lockForRead(); server->roomsLock.lockForRead();
QMapIterator<int, QPair<int, int> > gameIterator(tempGames); QMapIterator<int, QPair<int, int> > gameIterator(tempGames);
while (gameIterator.hasNext()) { while (gameIterator.hasNext()) {
gameIterator.next(); gameIterator.next();
Server_Room *r = server->getRooms().value(gameIterator.value().first); Server_Room *r = server->getRooms().value(gameIterator.value().first);
if (!r) if (!r)
continue; continue;
r->gamesLock.lockForRead(); r->gamesLock.lockForRead();
Server_Game *g = r->getGames().value(gameIterator.key()); Server_Game *g = r->getGames().value(gameIterator.key());
if (!g) { if (!g) {
r->gamesLock.unlock(); r->gamesLock.unlock();
continue; continue;
} }
g->gameMutex.lock(); g->gameMutex.lock();
Server_Player *p = g->getPlayers().value(gameIterator.value().second); Server_Player *p = g->getPlayers().value(gameIterator.value().second);
if (!p) { if (!p) {
g->gameMutex.unlock(); g->gameMutex.unlock();
r->gamesLock.unlock(); r->gamesLock.unlock();
continue; continue;
} }
p->disconnectClient(); p->disconnectClient();
g->gameMutex.unlock(); g->gameMutex.unlock();
r->gamesLock.unlock(); r->gamesLock.unlock();
} }
server->roomsLock.unlock(); server->roomsLock.unlock();
server->removeClient(this); server->removeClient(this);
deleteLater(); deleteLater();
} }
void Server_ProtocolHandler::sendProtocolItem(const Response &item) void Server_ProtocolHandler::sendProtocolItem(const Response &item)
{ {
ServerMessage msg; ServerMessage msg;
msg.mutable_response()->CopyFrom(item); msg.mutable_response()->CopyFrom(item);
msg.set_message_type(ServerMessage::RESPONSE); msg.set_message_type(ServerMessage::RESPONSE);
transmitProtocolItem(msg); transmitProtocolItem(msg);
} }
void Server_ProtocolHandler::sendProtocolItem(const SessionEvent &item) void Server_ProtocolHandler::sendProtocolItem(const SessionEvent &item)
{ {
ServerMessage msg; ServerMessage msg;
msg.mutable_session_event()->CopyFrom(item); msg.mutable_session_event()->CopyFrom(item);
msg.set_message_type(ServerMessage::SESSION_EVENT); msg.set_message_type(ServerMessage::SESSION_EVENT);
transmitProtocolItem(msg); transmitProtocolItem(msg);
} }
void Server_ProtocolHandler::sendProtocolItem(const GameEventContainer &item) void Server_ProtocolHandler::sendProtocolItem(const GameEventContainer &item)
{ {
ServerMessage msg; ServerMessage msg;
msg.mutable_game_event_container()->CopyFrom(item); msg.mutable_game_event_container()->CopyFrom(item);
msg.set_message_type(ServerMessage::GAME_EVENT_CONTAINER); msg.set_message_type(ServerMessage::GAME_EVENT_CONTAINER);
transmitProtocolItem(msg); transmitProtocolItem(msg);
} }
void Server_ProtocolHandler::sendProtocolItem(const RoomEvent &item) void Server_ProtocolHandler::sendProtocolItem(const RoomEvent &item)
{ {
ServerMessage msg; ServerMessage msg;
msg.mutable_room_event()->CopyFrom(item); msg.mutable_room_event()->CopyFrom(item);
msg.set_message_type(ServerMessage::ROOM_EVENT); msg.set_message_type(ServerMessage::ROOM_EVENT);
transmitProtocolItem(msg); transmitProtocolItem(msg);
} }
Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.session_command_size() - 1; i >= 0; --i) { for (int i = cont.session_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const SessionCommand &sc = cont.session_command(i); const SessionCommand &sc = cont.session_command(i);
const int num = getPbExtension(sc); const int num = getPbExtension(sc);
if (num != SessionCommand::PING) { // don't log ping commands if (num != SessionCommand::PING) { // don't log ping commands
if (num == SessionCommand::LOGIN) { // log login commands, but hide passwords if (num == SessionCommand::LOGIN) { // log login commands, but hide passwords
SessionCommand debugSc(sc); SessionCommand debugSc(sc);
debugSc.MutableExtension(Command_Login::ext)->clear_password(); debugSc.MutableExtension(Command_Login::ext)->clear_password();
logDebugMessage(QString::fromStdString(debugSc.ShortDebugString())); logDebugMessage(QString::fromStdString(debugSc.ShortDebugString()));
} else } else
logDebugMessage(QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
} }
switch ((SessionCommand::SessionCommandType) num) { switch ((SessionCommand::SessionCommandType) num) {
case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break; case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break;
case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break; case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break;
case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc); break; case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc); break;
case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break; case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break;
case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break; case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break;
case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break; case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break;
case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc); break; case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc); break;
case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc); break; case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc); break;
default: resp = processExtendedSessionCommand(num, sc, rc); default: resp = processExtendedSessionCommand(num, sc, rc);
} }
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
} }
return finalResponseCode; return finalResponseCode;
} }
Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
QReadLocker locker(&server->roomsLock); QReadLocker locker(&server->roomsLock);
Server_Room *room = rooms.value(cont.room_id(), 0); Server_Room *room = rooms.value(cont.room_id(), 0);
if (!room) if (!room)
return Response::RespNotInRoom; return Response::RespNotInRoom;
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.room_command_size() - 1; i >= 0; --i) { for (int i = cont.room_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const RoomCommand &sc = cont.room_command(i); const RoomCommand &sc = cont.room_command(i);
const int num = getPbExtension(sc); const int num = getPbExtension(sc);
logDebugMessage(QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
switch ((RoomCommand::RoomCommandType) num) { switch ((RoomCommand::RoomCommandType) num) {
case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break; case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break;
case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc); break; case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc); break;
case RoomCommand::CREATE_GAME: resp = cmdCreateGame(sc.GetExtension(Command_CreateGame::ext), room, rc); break; case RoomCommand::CREATE_GAME: resp = cmdCreateGame(sc.GetExtension(Command_CreateGame::ext), room, rc); break;
case RoomCommand::JOIN_GAME: resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc); break; case RoomCommand::JOIN_GAME: resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc); break;
} }
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
} }
return finalResponseCode; return finalResponseCode;
} }
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
QMap<int, QPair<int, int> > gameMap = getGames(); QMap<int, QPair<int, int> > gameMap = getGames();
if (!gameMap.contains(cont.game_id())) if (!gameMap.contains(cont.game_id()))
return Response::RespNotInRoom; return Response::RespNotInRoom;
const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id()); const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());
QReadLocker roomsLocker(&server->roomsLock); QReadLocker roomsLocker(&server->roomsLock);
Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first); Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
if (!room) if (!room)
return Response::RespNotInRoom; return Response::RespNotInRoom;
QReadLocker roomGamesLocker(&room->gamesLock); QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(cont.game_id()); Server_Game *game = room->getGames().value(cont.game_id());
if (!game) { if (!game) {
if (room->getExternalGames().contains(cont.game_id())) { if (room->getExternalGames().contains(cont.game_id())) {
server->sendIsl_GameCommand(cont, server->sendIsl_GameCommand(cont,
room->getExternalGames().value(cont.game_id()).server_id(), room->getExternalGames().value(cont.game_id()).server_id(),
userInfo->session_id(), userInfo->session_id(),
roomIdAndPlayerId.first, roomIdAndPlayerId.first,
roomIdAndPlayerId.second roomIdAndPlayerId.second
); );
return Response::RespNothing; return Response::RespNothing;
} }
return Response::RespNotInRoom; return Response::RespNotInRoom;
} }
QMutexLocker gameLocker(&game->gameMutex); QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second); Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
if (!player) if (!player)
return Response::RespNotInRoom; return Response::RespNotInRoom;
GameEventStorage ges; GameEventStorage ges;
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.game_command_size() - 1; i >= 0; --i) { for (int i = cont.game_command_size() - 1; i >= 0; --i) {
const GameCommand &sc = cont.game_command(i); const GameCommand &sc = cont.game_command(i);
logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));
Response::ResponseCode resp = player->processGameCommand(sc, rc, ges); Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
} }
ges.sendToGame(game); ges.sendToGame(game);
return finalResponseCode; return finalResponseCode;
} }
Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
if (!userInfo) if (!userInfo)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) if (!(userInfo->user_level() & ServerInfo_User::IsModerator))
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.moderator_command_size() - 1; i >= 0; --i) { for (int i = cont.moderator_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const ModeratorCommand &sc = cont.moderator_command(i); const ModeratorCommand &sc = cont.moderator_command(i);
const int num = getPbExtension(sc); const int num = getPbExtension(sc);
logDebugMessage(QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
resp = processExtendedModeratorCommand(num, sc, rc); resp = processExtendedModeratorCommand(num, sc, rc);
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
} }
return finalResponseCode; return finalResponseCode;
} }
Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
if (!userInfo) if (!userInfo)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
if (!(userInfo->user_level() & ServerInfo_User::IsAdmin)) if (!(userInfo->user_level() & ServerInfo_User::IsAdmin))
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.admin_command_size() - 1; i >= 0; --i) { for (int i = cont.admin_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const AdminCommand &sc = cont.admin_command(i); const AdminCommand &sc = cont.admin_command(i);
const int num = getPbExtension(sc); const int num = getPbExtension(sc);
logDebugMessage(QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
resp = processExtendedAdminCommand(num, sc, rc); resp = processExtendedAdminCommand(num, sc, rc);
if (resp != Response::RespOk) if (resp != Response::RespOk)
finalResponseCode = resp; finalResponseCode = resp;
} }
return finalResponseCode; return finalResponseCode;
} }
void Server_ProtocolHandler::processCommandContainer(const CommandContainer &cont) void Server_ProtocolHandler::processCommandContainer(const CommandContainer &cont)
{ {
// Command processing must be disabled after prepareDestroy() has been called. // Command processing must be disabled after prepareDestroy() has been called.
if (deleted) if (deleted)
return; return;
lastDataReceived = timeRunning; lastDataReceived = timeRunning;
ResponseContainer responseContainer(cont.has_cmd_id() ? cont.cmd_id() : -1); ResponseContainer responseContainer(cont.has_cmd_id() ? cont.cmd_id() : -1);
Response::ResponseCode finalResponseCode; Response::ResponseCode finalResponseCode;
if (cont.game_command_size()) if (cont.game_command_size())
finalResponseCode = processGameCommandContainer(cont, responseContainer); finalResponseCode = processGameCommandContainer(cont, responseContainer);
else if (cont.room_command_size()) else if (cont.room_command_size())
finalResponseCode = processRoomCommandContainer(cont, responseContainer); finalResponseCode = processRoomCommandContainer(cont, responseContainer);
else if (cont.session_command_size()) else if (cont.session_command_size())
finalResponseCode = processSessionCommandContainer(cont, responseContainer); finalResponseCode = processSessionCommandContainer(cont, responseContainer);
else if (cont.moderator_command_size()) else if (cont.moderator_command_size())
finalResponseCode = processModeratorCommandContainer(cont, responseContainer); finalResponseCode = processModeratorCommandContainer(cont, responseContainer);
else if (cont.admin_command_size()) else if (cont.admin_command_size())
finalResponseCode = processAdminCommandContainer(cont, responseContainer); finalResponseCode = processAdminCommandContainer(cont, responseContainer);
else else
finalResponseCode = Response::RespInvalidCommand; finalResponseCode = Response::RespInvalidCommand;
if ((finalResponseCode != Response::RespNothing)) if ((finalResponseCode != Response::RespNothing))
sendResponseContainer(responseContainer, finalResponseCode); sendResponseContainer(responseContainer, finalResponseCode);
} }
void Server_ProtocolHandler::pingClockTimeout() void Server_ProtocolHandler::pingClockTimeout()
{ {
int interval = server->getMessageCountingInterval(); int interval = server->getMessageCountingInterval();
if (interval > 0) { if (interval > 0) {
messageSizeOverTime.prepend(0); messageSizeOverTime.prepend(0);
if (messageSizeOverTime.size() > server->getMessageCountingInterval()) if (messageSizeOverTime.size() > server->getMessageCountingInterval())
messageSizeOverTime.removeLast(); messageSizeOverTime.removeLast();
messageCountOverTime.prepend(0); messageCountOverTime.prepend(0);
if (messageCountOverTime.size() > server->getMessageCountingInterval()) if (messageCountOverTime.size() > server->getMessageCountingInterval())
messageCountOverTime.removeLast(); messageCountOverTime.removeLast();
} }
if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime())
prepareDestroy(); prepareDestroy();
++timeRunning; ++timeRunning;
} }
Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cmd*/, ResponseContainer & /*rc*/) Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cmd*/, ResponseContainer & /*rc*/)
{ {
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc)
{ {
QString userName = QString::fromStdString(cmd.user_name()).simplified(); QString userName = QString::fromStdString(cmd.user_name()).simplified();
if (userName.isEmpty() || (userInfo != 0)) if (userName.isEmpty() || (userInfo != 0))
return Response::RespContextError; return Response::RespContextError;
QString reasonStr; QString reasonStr;
int banSecondsLeft = 0; int banSecondsLeft = 0;
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft); AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft);
switch (res) { switch (res) {
case UserIsBanned: { case UserIsBanned: {
Response_Login *re = new Response_Login; Response_Login *re = new Response_Login;
re->set_denied_reason_str(reasonStr.toStdString()); re->set_denied_reason_str(reasonStr.toStdString());
if (banSecondsLeft != 0) if (banSecondsLeft != 0)
re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toTime_t()); re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toTime_t());
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespUserIsBanned; return Response::RespUserIsBanned;
} }
case NotLoggedIn: return Response::RespWrongPassword; case NotLoggedIn: return Response::RespWrongPassword;
case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession; case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession;
case UsernameInvalid: return Response::RespUsernameInvalid; case UsernameInvalid: return Response::RespUsernameInvalid;
default: authState = res; default: authState = res;
} }
userName = QString::fromStdString(userInfo->name()); userName = QString::fromStdString(userInfo->name());
Event_ServerMessage event; Event_ServerMessage event;
event.set_message(server->getLoginMessage().toStdString()); event.set_message(server->getLoginMessage().toStdString());
rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event));
Response_Login *re = new Response_Login; Response_Login *re = new Response_Login;
re->mutable_user_info()->CopyFrom(copyUserInfo(true)); re->mutable_user_info()->CopyFrom(copyUserInfo(true));
if (authState == PasswordRight) { if (authState == PasswordRight) {
QMapIterator<QString, ServerInfo_User> buddyIterator(databaseInterface->getBuddyList(userName)); QMapIterator<QString, ServerInfo_User> buddyIterator(databaseInterface->getBuddyList(userName));
while (buddyIterator.hasNext()) while (buddyIterator.hasNext())
re->add_buddy_list()->CopyFrom(buddyIterator.next().value()); re->add_buddy_list()->CopyFrom(buddyIterator.next().value());
QMapIterator<QString, ServerInfo_User> ignoreIterator(databaseInterface->getIgnoreList(userName)); QMapIterator<QString, ServerInfo_User> ignoreIterator(databaseInterface->getIgnoreList(userName));
while (ignoreIterator.hasNext()) while (ignoreIterator.hasNext())
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value()); re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
} }
joinPersistentGames(rc); joinPersistentGames(rc);
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message &cmd, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message &cmd, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
QReadLocker locker(&server->clientsLock); QReadLocker locker(&server->clientsLock);
QString receiver = QString::fromStdString(cmd.user_name()); QString receiver = QString::fromStdString(cmd.user_name());
Server_AbstractUserInterface *userInterface = server->findUser(receiver); Server_AbstractUserInterface *userInterface = server->findUser(receiver);
if (!userInterface) if (!userInterface)
return Response::RespNameNotFound; return Response::RespNameNotFound;
if (databaseInterface->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) if (databaseInterface->isInIgnoreList(receiver, QString::fromStdString(userInfo->name())))
return Response::RespInIgnoreList; return Response::RespInIgnoreList;
Event_UserMessage event; Event_UserMessage event;
event.set_sender_name(userInfo->name()); event.set_sender_name(userInfo->name());
event.set_receiver_name(cmd.user_name()); event.set_receiver_name(cmd.user_name());
event.set_message(cmd.message()); event.set_message(cmd.message());
SessionEvent *se = prepareSessionEvent(event); SessionEvent *se = prepareSessionEvent(event);
userInterface->sendProtocolItem(*se); userInterface->sendProtocolItem(*se);
rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
// We don't need to check whether the user is logged in; persistent games should also work. // We don't need to check whether the user is logged in; persistent games should also work.
// The client needs to deal with an empty result list. // The client needs to deal with an empty result list.
Response_GetGamesOfUser *re = new Response_GetGamesOfUser; Response_GetGamesOfUser *re = new Response_GetGamesOfUser;
server->roomsLock.lockForRead(); server->roomsLock.lockForRead();
QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
while (roomIterator.hasNext()) { while (roomIterator.hasNext()) {
Server_Room *room = roomIterator.next().value(); Server_Room *room = roomIterator.next().value();
room->gamesLock.lockForRead(); room->gamesLock.lockForRead();
room->getInfo(*re->add_room_list(), false, true); room->getInfo(*re->add_room_list(), false, true);
QListIterator<ServerInfo_Game> gameIterator(room->getGamesOfUser(QString::fromStdString(cmd.user_name()))); QListIterator<ServerInfo_Game> gameIterator(room->getGamesOfUser(QString::fromStdString(cmd.user_name())));
while (gameIterator.hasNext()) while (gameIterator.hasNext())
re->add_game_list()->CopyFrom(gameIterator.next()); re->add_game_list()->CopyFrom(gameIterator.next());
room->gamesLock.unlock(); room->gamesLock.unlock();
} }
server->roomsLock.unlock(); server->roomsLock.unlock();
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
QString userName = QString::fromStdString(cmd.user_name()); QString userName = QString::fromStdString(cmd.user_name());
Response_GetUserInfo *re = new Response_GetUserInfo; Response_GetUserInfo *re = new Response_GetUserInfo;
if (userName.isEmpty()) if (userName.isEmpty())
re->mutable_user_info()->CopyFrom(*userInfo); re->mutable_user_info()->CopyFrom(*userInfo);
else { else {
QReadLocker locker(&server->clientsLock); QReadLocker locker(&server->clientsLock);
ServerInfo_User_Container *infoSource = server->findUser(userName); ServerInfo_User_Container *infoSource = server->findUser(userName);
if (!infoSource) if (!infoSource)
return Response::RespNameNotFound; return Response::RespNameNotFound;
re->mutable_user_info()->CopyFrom(infoSource->copyUserInfo(true, false, userInfo->user_level() & ServerInfo_User::IsModerator)); re->mutable_user_info()->CopyFrom(infoSource->copyUserInfo(true, false, userInfo->user_level() & ServerInfo_User::IsModerator));
} }
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRooms & /*cmd*/, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRooms & /*cmd*/, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
Event_ListRooms event; Event_ListRooms event;
QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
while (roomIterator.hasNext()) while (roomIterator.hasNext())
roomIterator.next().value()->getInfo(*event.add_room_list(), false); roomIterator.next().value()->getInfo(*event.add_room_list(), false);
rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event));
acceptsRoomListChanges = true; acceptsRoomListChanges = true;
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
if (rooms.contains(cmd.room_id())) if (rooms.contains(cmd.room_id()))
return Response::RespContextError; return Response::RespContextError;
QReadLocker serverLocker(&server->roomsLock); QReadLocker serverLocker(&server->roomsLock);
Server_Room *r = server->getRooms().value(cmd.room_id(), 0); Server_Room *r = server->getRooms().value(cmd.room_id(), 0);
if (!r) if (!r)
return Response::RespNameNotFound; return Response::RespNameNotFound;
r->addClient(this); r->addClient(this);
rooms.insert(r->getId(), r); rooms.insert(r->getId(), r);
Event_RoomSay joinMessageEvent; Event_RoomSay joinMessageEvent;
joinMessageEvent.set_message(r->getJoinMessage().toStdString()); joinMessageEvent.set_message(r->getJoinMessage().toStdString());
rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent)); rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));
Response_JoinRoom *re = new Response_JoinRoom; Response_JoinRoom *re = new Response_JoinRoom;
r->getInfo(*re->mutable_room_info(), true); r->getInfo(*re->mutable_room_info(), true);
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUsers & /*cmd*/, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUsers & /*cmd*/, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
Response_ListUsers *re = new Response_ListUsers; Response_ListUsers *re = new Response_ListUsers;
server->clientsLock.lockForRead(); server->clientsLock.lockForRead();
QMapIterator<QString, Server_ProtocolHandler *> userIterator = server->getUsers(); QMapIterator<QString, Server_ProtocolHandler *> userIterator = server->getUsers();
while (userIterator.hasNext()) while (userIterator.hasNext())
re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false)); re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false));
QMapIterator<QString, Server_AbstractUserInterface *> extIterator = server->getExternalUsers(); QMapIterator<QString, Server_AbstractUserInterface *> extIterator = server->getExternalUsers();
while (extIterator.hasNext()) while (extIterator.hasNext())
re->add_user_list()->CopyFrom(extIterator.next().value()->copyUserInfo(false)); re->add_user_list()->CopyFrom(extIterator.next().value()->copyUserInfo(false));
acceptsUserListChanges = true; acceptsUserListChanges = true;
server->clientsLock.unlock(); server->clientsLock.unlock();
rc.setResponseExtension(re); rc.setResponseExtension(re);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdLeaveRoom(const Command_LeaveRoom & /*cmd*/, Server_Room *room, ResponseContainer & /*rc*/) Response::ResponseCode Server_ProtocolHandler::cmdLeaveRoom(const Command_LeaveRoom & /*cmd*/, Server_Room *room, ResponseContainer & /*rc*/)
{ {
rooms.remove(room->getId()); rooms.remove(room->getId());
room->removeClient(this); room->removeClient(this);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer & /*rc*/) Response::ResponseCode Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer & /*rc*/)
{ {
QString msg = QString::fromStdString(cmd.message()); QString msg = QString::fromStdString(cmd.message());
if (server->getMessageCountingInterval() > 0) { if (server->getMessageCountingInterval() > 0) {
int totalSize = 0, totalCount = 0; int totalSize = 0, totalCount = 0;
if (messageSizeOverTime.isEmpty()) if (messageSizeOverTime.isEmpty())
messageSizeOverTime.prepend(0); messageSizeOverTime.prepend(0);
messageSizeOverTime[0] += msg.size(); messageSizeOverTime[0] += msg.size();
for (int i = 0; i < messageSizeOverTime.size(); ++i) for (int i = 0; i < messageSizeOverTime.size(); ++i)
totalSize += messageSizeOverTime[i]; totalSize += messageSizeOverTime[i];
if (messageCountOverTime.isEmpty()) if (messageCountOverTime.isEmpty())
messageCountOverTime.prepend(0); messageCountOverTime.prepend(0);
++messageCountOverTime[0]; ++messageCountOverTime[0];
for (int i = 0; i < messageCountOverTime.size(); ++i) for (int i = 0; i < messageCountOverTime.size(); ++i)
totalCount += messageCountOverTime[i]; totalCount += messageCountOverTime[i];
if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval())) if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval()))
return Response::RespChatFlood; return Response::RespChatFlood;
} }
msg.replace(QChar('\n'), QChar(' ')); msg.replace(QChar('\n'), QChar(' '));
room->say(QString::fromStdString(userInfo->name()), msg); room->say(QString::fromStdString(userInfo->name()), msg);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
const int gameId = databaseInterface->getNextGameId(); const int gameId = databaseInterface->getNextGameId();
if (gameId == -1) if (gameId == -1)
return Response::RespInternalError; return Response::RespInternalError;
if (server->getMaxGamesPerUser() > 0) if (server->getMaxGamesPerUser() > 0)
if (room->getGamesCreatedByUser(QString::fromStdString(userInfo->name())) >= server->getMaxGamesPerUser()) if (room->getGamesCreatedByUser(QString::fromStdString(userInfo->name())) >= server->getMaxGamesPerUser())
return Response::RespContextError; return Response::RespContextError;
QList<int> gameTypes; QList<int> gameTypes;
for (int i = cmd.game_type_ids_size() - 1; i >= 0; --i) for (int i = cmd.game_type_ids_size() - 1; i >= 0; --i)
gameTypes.append(cmd.game_type_ids(i)); gameTypes.append(cmd.game_type_ids(i));
QString description = QString::fromStdString(cmd.description()); QString description = QString::fromStdString(cmd.description());
if (description.size() > 60) if (description.size() > 60)
description = description.left(60); description = description.left(60);
Server_Game *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room); Server_Game *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room);
game->addPlayer(this, rc, false, false); game->addPlayer(this, rc, false, false);
room->addGame(game); room->addGame(game);
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc) Response::ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc)
{ {
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
return room->processJoinGameCommand(cmd, rc, this); return room->processJoinGameCommand(cmd, rc, this);
} }

View file

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

View file

@ -4,20 +4,20 @@
void Server_RemoteUserInterface::sendProtocolItem(const Response &item) 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) 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) 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) 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 { class Server_RemoteUserInterface : public Server_AbstractUserInterface {
public: public:
Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { } Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { }
int getLastCommandTime() const { return 0; } int getLastCommandTime() const { return 0; }
void sendProtocolItem(const Response &item); void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item); void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item); void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item); void sendProtocolItem(const RoomEvent &item);
}; };
#endif #endif

View file

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

View file

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

View file

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

View file

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

View file

@ -5,16 +5,16 @@ class ServerInfo_User;
class ServerInfo_User_Container { class ServerInfo_User_Container {
protected: protected:
ServerInfo_User *userInfo; ServerInfo_User *userInfo;
public: public:
ServerInfo_User_Container(ServerInfo_User *_userInfo = 0); ServerInfo_User_Container(ServerInfo_User *_userInfo = 0);
ServerInfo_User_Container(const ServerInfo_User &_userInfo); ServerInfo_User_Container(const ServerInfo_User &_userInfo);
ServerInfo_User_Container(const ServerInfo_User_Container &other); ServerInfo_User_Container(const ServerInfo_User_Container &other);
virtual ~ServerInfo_User_Container(); virtual ~ServerInfo_User_Container();
ServerInfo_User *getUserInfo() const { return userInfo; } ServerInfo_User *getUserInfo() const { return userInfo; }
void setUserInfo(const ServerInfo_User &_userInfo); void setUserInfo(const ServerInfo_User &_userInfo);
ServerInfo_User &copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo = false, bool sessionInfo = false) const; ServerInfo_User &copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo = false, bool sessionInfo = false) const;
ServerInfo_User copyUserInfo(bool complete, bool internalInfo = false, bool sessionInfo = false) const; ServerInfo_User copyUserInfo(bool complete, bool internalInfo = false, bool sessionInfo = false) const;
}; };
#endif #endif

View file

@ -16,21 +16,77 @@ SET(oracle_SOURCES
../cockatrice/src/qt-json/json.cpp ../cockatrice/src/qt-json/json.cpp
) )
SET(QT_USE_QTNETWORK TRUE) set(ORACLE_LIBS)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE) # Qt4 stuff
if(Qt4_FOUND)
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE)
# Include directories
INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
LIST(APPEND ORACLE_LIBS ${QT_QTMAIN_LIBRARY})
LIST(APPEND ORACLE_LIBS ${QT_LIBRARIES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Widgets)
# QtConcurrent
find_package(Qt5Concurrent)
if(Qt5Concurrent_FOUND)
include_directories(${Qt5Concurrent_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Concurrent)
endif()
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Network)
endif()
# QtXml
find_package(Qt5Xml)
if(Qt5Xml_FOUND)
include_directories(${Qt5Xml_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Xml)
endif()
# QtSvg
find_package(Qt5Svg)
if(Qt5Svg_FOUND)
include_directories(${Qt5Svg_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Svg)
endif()
# 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()
# Include directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(../cockatrice/src) INCLUDE_DIRECTORIES(../cockatrice/src)
# Build oracle binary and link it # Build oracle binary and link it
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_MOC_SRCS}) ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_MOC_SRCS})
TARGET_LINK_LIBRARIES(oracle ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
if(MSVC) if(Qt4_FOUND)
set_target_properties(oracle PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS") if(MSVC)
endif(MSVC) set(QT_USE_QTMAIN true)
endif()
TARGET_LINK_LIBRARIES(oracle ${ORACLE_LIBS})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(oracle Qt5::WinMain)
endif()
qt5_use_modules(oracle ${ORACLE_LIBS})
endif()
if(UNIX) if(UNIX)
if(APPLE) if(APPLE)
@ -78,3 +134,35 @@ Translations = Resources/translations\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/oracle.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/oracle.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() 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\")
" 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}/oracle.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -9,7 +9,10 @@ int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cockatrice"); QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice"); QCoreApplication::setOrganizationDomain("cockatrice");

View file

@ -1,5 +1,9 @@
#include "oracleimporter.h" #include "oracleimporter.h"
#include <QtGui> #if QT_VERSION < 0x050000
#include <QtGui>
#else
#include <QtWidgets>
#endif
#include <QDebug> #include <QDebug>
#include "qt-json/json.h" #include "qt-json/json.h"
@ -199,6 +203,11 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0;
cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0;
cardIsToken = map.value("layout") == "token"; cardIsToken = map.value("layout") == "token";
// Distinguish Vanguard cards from regular cards of the same name.
if (map.value("layout") == "vanguard") {
cardName += " Avatar";
}
} }
CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n")); CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n"));

View file

@ -1,8 +1,25 @@
#include <QtGui> #include <QtGui>
#if QT_VERSION < 0x050000
#include <QDesktopServices>
#else
#include <QStandardPaths>
#include <QtConcurrent>
#endif
#include <QAbstractButton>
#include <QCheckBox>
#include <QFileDialog>
#include <QGridLayout> #include <QGridLayout>
#include <QDesktopServices> #include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QTextEdit>
#include "oraclewizard.h" #include "oraclewizard.h"
#include "oracleimporter.h" #include "oracleimporter.h"
@ -13,7 +30,14 @@ OracleWizard::OracleWizard(QWidget *parent)
: QWizard(parent) : QWizard(parent)
{ {
settings = new QSettings(this); settings = new QSettings(this);
importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this);
importer = new OracleImporter(
#if QT_VERSION < 0x050000
QDesktopServices::storageLocation(QDesktopServices::DataLocation)
#else
QStandardPaths::standardLocations(QStandardPaths::DataLocation).first()
#endif
, this);
addPage(new IntroPage); addPage(new IntroPage);
addPage(new LoadSetsPage); addPage(new LoadSetsPage);
@ -372,7 +396,12 @@ void SaveSetsPage::updateTotalProgress(int cardsImported, int setIndex, const QS
bool SaveSetsPage::validatePage() bool SaveSetsPage::validatePage()
{ {
bool ok = false; bool ok = false;
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); const QString dataDir =
#if QT_VERSION < 0x050000
QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
QDir dir(dataDir); QDir dir(dataDir);
if (!dir.exists()) if (!dir.exists())
dir.mkpath(dataDir); dir.mkpath(dataDir);

View file

@ -4,8 +4,6 @@
PROJECT(servatrice) PROJECT(servatrice)
# cmake module for libgcrypt is included in current directory
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(Libgcrypt REQUIRED) FIND_PACKAGE(Libgcrypt REQUIRED)
SET(servatrice_SOURCES SET(servatrice_SOURCES
@ -17,15 +15,50 @@ SET(servatrice_SOURCES
src/server_logger.cpp src/server_logger.cpp
src/serversocketinterface.cpp src/serversocketinterface.cpp
src/isl_interface.cpp src/isl_interface.cpp
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${VERSION_STRING_CPP}
) )
SET(QT_DONTUSE_QTGUI) set(SERVATRICE_LIBS)
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTSQL TRUE) # Qt4 stuff
if(Qt4_FOUND)
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTSQL TRUE)
# Include directories
INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
LIST(APPEND SERVATRICE_LIBS ${QT_LIBRARIES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Widgets)
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Network)
endif()
# QtSql
find_package(Qt5Sql)
if(Qt5Sql_FOUND)
include_directories(${Qt5Sql_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Sql)
endif()
# 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()
SET(QT_DONT_USE_QTGUI TRUE)
# Include directories # Include directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(../common) INCLUDE_DIRECTORIES(../common)
INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
@ -34,13 +67,21 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
# Build servatrice binary and link it # Build servatrice binary and link it
ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_MOC_SRCS}) ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_MOC_SRCS})
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${QT_LIBRARIES} ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
#add_custom_target(versionheader ALL DEPENDS version_header) if(Qt4_FOUND)
add_custom_command( if(MSVC)
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_string.h ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp set(QT_USE_QTMAIN true)
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/../common/getversion.cmake endif()
) TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${SERVATRICE_LIBS} ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} Qt5::WinMain)
else()
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
endif()
qt5_use_modules(servatrice ${SERVATRICE_LIBS})
endif()
# install rules # install rules
if(UNIX) if(UNIX)
@ -85,3 +126,35 @@ Translations = Resources/translations\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() 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\")
" 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}/servatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -0,0 +1,3 @@
#!/bin/bash
# SCHEDULE WITH CRONTAB BASED ON TIME PERIOD REPLAYS SHOULD BE SAVED UNTIL (EX: SCHEDULE ONCE A WEEK TO KEEP A WEEKS WORTH OF REPLAYS IN THE DB)
mysql --defaults-file=./mysql.cnf -h localhost -e 'truncate table servatrice.cockatrice_replays;truncate table servatrice.cockatrice_replays_access'

View file

@ -0,0 +1,3 @@
#!/bin/bash
# SCHEDULE WITH CRONTAB TO RUN ONCE A MONTH
mysql --defaults-file=./mysql.cnf -h localhost -e "delete from servatrice.cockatrice_sessions where start_time < DATE_SUB(now(), INTERVAL 1 MONTH)"

View file

@ -0,0 +1,3 @@
[client]
user={db_username}
password={db_password}

View file

@ -82,6 +82,7 @@ void testHash()
std::cerr << startTime.secsTo(endTime) << "secs" << std::endl; std::cerr << startTime.secsTo(endTime) << "secs" << std::endl;
} }
#if QT_VERSION < 0x050000
void myMessageOutput(QtMsgType /*type*/, const char *msg) void myMessageOutput(QtMsgType /*type*/, const char *msg)
{ {
logger->logMessage(msg); logger->logMessage(msg);
@ -92,6 +93,18 @@ void myMessageOutput2(QtMsgType /*type*/, const char *msg)
logger->logMessage(msg); logger->logMessage(msg);
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
#else
void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
logger->logMessage(msg);
}
void myMessageOutput2(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
logger->logMessage(msg);
std::cerr << msg.toStdString() << std::endl;
}
#endif
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
void sigSegvHandler(int sig) void sigSegvHandler(int sig)
@ -122,7 +135,10 @@ int main(int argc, char *argv[])
qRegisterMetaType<QList<int> >("QList<int>"); qRegisterMetaType<QList<int> >("QList<int>");
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat);
@ -134,10 +150,18 @@ int main(int argc, char *argv[])
loggerThread->start(); loggerThread->start();
QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString())); QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString()));
#if QT_VERSION < 0x050000
if (logToConsole) if (logToConsole)
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
else else
qInstallMsgHandler(myMessageOutput2); qInstallMsgHandler(myMessageOutput2);
#else
if (logToConsole)
qInstallMessageHandler(myMessageOutput);
else
qInstallMessageHandler(myMessageOutput2);
#endif
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
struct sigaction hup; struct sigaction hup;
hup.sa_handler = ServerLogger::hupSignalHandler; hup.sa_handler = ServerLogger::hupSignalHandler;
@ -174,7 +198,11 @@ int main(int argc, char *argv[])
std::cerr << "-------------------------" << std::endl; std::cerr << "-------------------------" << std::endl;
std::cerr << "Server initialized." << std::endl; std::cerr << "Server initialized." << std::endl;
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
retval = app.exec(); retval = app.exec();
std::cerr << "Server quit." << std::endl; std::cerr << "Server quit." << std::endl;

View file

@ -16,7 +16,7 @@ QString PasswordHasher::computeHash(const QString &password, const QString &salt
const int algo = GCRY_MD_SHA512; const int algo = GCRY_MD_SHA512;
const int rounds = 1000; const int rounds = 1000;
QByteArray passwordBuffer = (salt + password).toAscii(); QByteArray passwordBuffer = (salt + password).toUtf8();
int hashLen = gcry_md_get_algo_dlen(algo); int hashLen = gcry_md_get_algo_dlen(algo);
char hash[hashLen], tmp[hashLen]; char hash[hashLen], tmp[hashLen];
gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size()); gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size());

View file

@ -78,7 +78,11 @@ Servatrice_GameServer::~Servatrice_GameServer()
} }
} }
#if QT_VERSION < 0x050000
void Servatrice_GameServer::incomingConnection(int socketDescriptor) void Servatrice_GameServer::incomingConnection(int socketDescriptor)
#else
void Servatrice_GameServer::incomingConnection(qintptr socketDescriptor)
#endif
{ {
// Determine connection pool with smallest client count // Determine connection pool with smallest client count
int minClientCount = -1; int minClientCount = -1;
@ -234,8 +238,16 @@ bool Servatrice::initServer()
if (!certFile.open(QIODevice::ReadOnly)) if (!certFile.open(QIODevice::ReadOnly))
throw QString("Error opening certificate file: %1").arg(certFileName); throw QString("Error opening certificate file: %1").arg(certFileName);
QSslCertificate cert(&certFile); QSslCertificate cert(&certFile);
#if QT_VERSION < 0x050000
if (!cert.isValid()) if (!cert.isValid())
throw(QString("Invalid certificate.")); throw(QString("Invalid certificate."));
#else
const QDateTime currentTime = QDateTime::currentDateTime();
if(currentTime < cert.effectiveDate() ||
currentTime > cert.expiryDate() ||
cert.isBlacklisted())
throw(QString("Invalid certificate."));
#endif
qDebug() << "Loading private key..."; qDebug() << "Loading private key...";
QFile keyFile(keyFileName); QFile keyFile(keyFileName);
if (!keyFile.open(QIODevice::ReadOnly)) if (!keyFile.open(QIODevice::ReadOnly))
@ -319,7 +331,7 @@ void Servatrice::updateServerList()
query.prepare("select id, ssl_cert, hostname, address, game_port, control_port from " + dbPrefix + "_servers order by id asc"); query.prepare("select id, ssl_cert, hostname, address, game_port, control_port from " + dbPrefix + "_servers order by id asc");
servatriceDatabaseInterface->execSqlQuery(query); servatriceDatabaseInterface->execSqlQuery(query);
while (query.next()) { while (query.next()) {
ServerProperties prop(query.value(0).toInt(), QSslCertificate(query.value(1).toString().toAscii()), query.value(2).toString(), QHostAddress(query.value(3).toString()), query.value(4).toInt(), query.value(5).toInt()); ServerProperties prop(query.value(0).toInt(), QSslCertificate(query.value(1).toString().toUtf8()), query.value(2).toString(), QHostAddress(query.value(3).toString()), query.value(4).toInt(), query.value(5).toInt());
serverList.append(prop); serverList.append(prop);
qDebug() << QString("#%1 CERT=%2 NAME=%3 IP=%4:%5 CPORT=%6").arg(prop.id).arg(QString(prop.cert.digest().toHex())).arg(prop.hostname).arg(prop.address.toString()).arg(prop.gamePort).arg(prop.controlPort); qDebug() << QString("#%1 CERT=%2 NAME=%3 IP=%4:%5 CPORT=%6").arg(prop.id).arg(QString(prop.cert.digest().toHex())).arg(prop.hostname).arg(prop.address.toString()).arg(prop.gamePort).arg(prop.controlPort);
} }

View file

@ -52,7 +52,11 @@ public:
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0); Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
~Servatrice_GameServer(); ~Servatrice_GameServer();
protected: protected:
#if QT_VERSION < 0x050000
void incomingConnection(int socketDescriptor); void incomingConnection(int socketDescriptor);
#else
void incomingConnection(qintptr socketDescriptor);
#endif
}; };
class Servatrice_IslServer : public QTcpServer { class Servatrice_IslServer : public QTcpServer {

View file

@ -2,7 +2,7 @@
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
brew update brew update
brew install qt cmake protobuf libgcrypt brew install qt protobuf libgcrypt
else else
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev