mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-14 20:01:06 -08:00
Compare commits
54 commits
1db8dba9cf
...
cba909241b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cba909241b | ||
|
|
1f8d252c68 | ||
|
|
28a5bd44e7 | ||
|
|
255c713ce4 | ||
|
|
af05b85f29 | ||
|
|
8ed6354595 | ||
|
|
25c85cf0bb | ||
|
|
cce606764c | ||
|
|
24874b10cf | ||
|
|
a712553c81 | ||
|
|
bac2d285e3 | ||
|
|
96b819d7c8 | ||
|
|
8968709642 | ||
|
|
1a4d89ff8f | ||
|
|
4feb31bd1a | ||
|
|
4c5a5e3e55 | ||
|
|
5d06bb903d | ||
|
|
57a6a0d9cb | ||
|
|
f83a61979f | ||
|
|
07eb9f0103 | ||
|
|
38acddeede | ||
|
|
74a6acde91 | ||
|
|
4a010bd17f | ||
|
|
315cbae345 | ||
|
|
bdda3dedfa | ||
|
|
8822ade49d | ||
|
|
7fa6234eee | ||
|
|
efc7e7a079 | ||
|
|
be2c16eca5 | ||
|
|
b8e8f2c738 | ||
|
|
1e1f79db0d | ||
|
|
bb61617d42 | ||
|
|
a44757bd11 | ||
|
|
6bed5d6f67 | ||
|
|
205e1ecebf | ||
|
|
aaafa72c0e | ||
|
|
56c456414b | ||
|
|
95f02ac0a1 | ||
|
|
d0fc27e3a8 | ||
|
|
514014dc00 | ||
|
|
870ab23608 | ||
|
|
d603a2bb6a | ||
|
|
b1f4d1e99d | ||
|
|
d0991b68f6 | ||
|
|
08a608992d | ||
|
|
b545efb929 | ||
|
|
a02523ee9e | ||
|
|
a8e9eb3c1b | ||
|
|
327a6bfd8a | ||
|
|
86039d7eb6 | ||
|
|
0a9d6b2226 | ||
|
|
885b50de00 | ||
|
|
76bcc4842b | ||
|
|
b858d684cb |
1218 changed files with 23280 additions and 5331 deletions
|
|
@ -4,7 +4,6 @@ RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
ccache \
|
ccache \
|
||||||
clang-format \
|
|
||||||
cmake \
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ RUN apt-get update && \
|
||||||
build-essential \
|
build-essential \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
ccache \
|
ccache \
|
||||||
clang-format \
|
|
||||||
cmake \
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
ccache \
|
ccache \
|
||||||
clang-format \
|
|
||||||
cmake \
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
ccache \
|
ccache \
|
||||||
clang-format \
|
|
||||||
cmake \
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ RUN apt-get update && \
|
||||||
build-essential \
|
build-essential \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
ccache \
|
ccache \
|
||||||
clang-format \
|
|
||||||
cmake \
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
|
gcovr \
|
||||||
git \
|
git \
|
||||||
libgl-dev \
|
libgl-dev \
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
|
|
|
||||||
272
.ci/compile.sh
272
.ci/compile.sh
|
|
@ -8,14 +8,19 @@
|
||||||
# --suffix <suffix> renames package with this suffix, requires arg
|
# --suffix <suffix> renames package with this suffix, requires arg
|
||||||
# --server compiles servatrice
|
# --server compiles servatrice
|
||||||
# --test runs tests
|
# --test runs tests
|
||||||
|
# --sanitize builds with AddressSanitizer and UndefinedBehaviorSanitizer, gcc/clang only
|
||||||
|
# --coverage instruments the test run for line coverage and prints a gcovr summary, gcc only
|
||||||
|
|
||||||
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||||
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||||
# --evict-ccache <age> runs ccache eviction based on given age after build
|
# --evict-ccache <age> runs ccache eviction based on given age after build
|
||||||
|
# --sccache uses sccache instead, needs a generator that runs the compiler itself
|
||||||
# --dir <dir> sets the name of the build dir, default is "build"
|
# --dir <dir> sets the name of the build dir, default is "build"
|
||||||
# --cmake-generator <generator> sets CMAKE_GENERATOR as used by cmake
|
# --cmake-generator <generator> sets CMAKE_GENERATOR as used by cmake
|
||||||
# --target-macos-version <version> sets the min os version - only used for macOS builds
|
# --target-macos-version <version> sets the min os version - only used for macOS builds
|
||||||
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE CCACHE_EVICTION_AGE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION
|
# --profile writes an MSBuild performance summary and binary log, Windows only
|
||||||
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir>)
|
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE CCACHE_EVICTION_AGE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION MAKE_SANITIZE MAKE_COVERAGE VCPKG_TARGET_MACOS_VERSION BUILD_PARALLEL_LEVEL BUILD_PROFILE USE_SCCACHE
|
||||||
|
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --sanitize --coverage --ccache <ccache_size> --dir <dir> --profile --sccache)
|
||||||
# exitcode: 1 for failure, 3 for invalid arguments
|
# exitcode: 1 for failure, 3 for invalid arguments
|
||||||
|
|
||||||
# Read arguments
|
# Read arguments
|
||||||
|
|
@ -57,6 +62,14 @@ while [[ $# != 0 ]]; do
|
||||||
MAKE_TEST=1
|
MAKE_TEST=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
'--sanitize')
|
||||||
|
MAKE_SANITIZE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--coverage')
|
||||||
|
MAKE_COVERAGE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
'--debug')
|
'--debug')
|
||||||
BUILDTYPE="Debug"
|
BUILDTYPE="Debug"
|
||||||
shift
|
shift
|
||||||
|
|
@ -82,6 +95,10 @@ while [[ $# != 0 ]]; do
|
||||||
CCACHE_EVICTION_AGE=$1
|
CCACHE_EVICTION_AGE=$1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
'--sccache')
|
||||||
|
USE_SCCACHE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
'--vcpkg')
|
'--vcpkg')
|
||||||
USE_VCPKG=1
|
USE_VCPKG=1
|
||||||
shift
|
shift
|
||||||
|
|
@ -104,6 +121,10 @@ while [[ $# != 0 ]]; do
|
||||||
export CMAKE_GENERATOR=$1
|
export CMAKE_GENERATOR=$1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
'--profile')
|
||||||
|
BUILD_PROFILE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
'--target-macos-version')
|
'--target-macos-version')
|
||||||
shift
|
shift
|
||||||
if [[ $# == 0 ]]; then
|
if [[ $# == 0 ]]; then
|
||||||
|
|
@ -122,6 +143,12 @@ done
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# cmake reads the generator platform from the environment, so a leftover platform
|
||||||
|
# follows the generator around; Ninja has no platform to select.
|
||||||
|
if [[ $CMAKE_GENERATOR != "Visual Studio"* ]]; then
|
||||||
|
unset CMAKE_GENERATOR_PLATFORM
|
||||||
|
fi
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
./servatrice/check_schema_version.sh
|
./servatrice/check_schema_version.sh
|
||||||
if [[ ! $BUILDTYPE ]]; then
|
if [[ ! $BUILDTYPE ]]; then
|
||||||
|
|
@ -131,6 +158,15 @@ if [[ ! $BUILD_DIR ]]; then
|
||||||
BUILD_DIR="build"
|
BUILD_DIR="build"
|
||||||
fi
|
fi
|
||||||
mkdir -p "$BUILD_DIR"
|
mkdir -p "$BUILD_DIR"
|
||||||
|
|
||||||
|
if [[ $MAKE_COVERAGE ]]; then
|
||||||
|
# Resolved while the working directory is still the source root. $0 is relative to the
|
||||||
|
# directory the script was invoked from, so after the cd below it no longer resolves, and
|
||||||
|
# under `set -e` the failed subshell would abort the build rather than just yielding an empty
|
||||||
|
# variable. Only the coverage report needs this, so only coverage pays for it.
|
||||||
|
SRC_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
fi
|
||||||
|
|
||||||
cd "$BUILD_DIR"
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
# Set minimum CMake Version
|
# Set minimum CMake Version
|
||||||
|
|
@ -138,6 +174,16 @@ export CMAKE_POLICY_VERSION_MINIMUM=3.10
|
||||||
|
|
||||||
# Add cmake flags
|
# Add cmake flags
|
||||||
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||||
|
if [[ $USE_CCACHE && $USE_SCCACHE ]]; then
|
||||||
|
echo "::error file=$0::ccache and sccache at the same time is not a supported combination"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ $USE_SCCACHE && $CMAKE_GENERATOR != "Ninja"* ]]; then
|
||||||
|
# A compiler cache wraps the compiler, and only generators that run the compiler
|
||||||
|
# themselves are given a launcher to wrap: cmake does not pass one to MSBuild.
|
||||||
|
echo "::error file=$0::sccache needs a Ninja generator, not '$CMAKE_GENERATOR', which would ignore it"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if [[ $MAKE_SERVER ]]; then
|
if [[ $MAKE_SERVER ]]; then
|
||||||
flags+=("-DWITH_SERVER=1")
|
flags+=("-DWITH_SERVER=1")
|
||||||
fi
|
fi
|
||||||
|
|
@ -147,6 +193,17 @@ fi
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
flags+=("-DTEST=1")
|
flags+=("-DTEST=1")
|
||||||
fi
|
fi
|
||||||
|
if [[ $MAKE_SANITIZE ]]; then
|
||||||
|
flags+=("-DENABLE_SANITIZERS=ON")
|
||||||
|
else
|
||||||
|
# The release-package step re-runs cmake in the same build dir, so an
|
||||||
|
# ENABLE_SANITIZERS=ON left over from the debug step would otherwise leak
|
||||||
|
# into the shipped binaries (libasan/libubsan Depends in the DEB).
|
||||||
|
flags+=("-DENABLE_SANITIZERS=OFF")
|
||||||
|
fi
|
||||||
|
if [[ $MAKE_COVERAGE ]]; then
|
||||||
|
flags+=("-DENABLE_COVERAGE=ON")
|
||||||
|
fi
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
flags+=("-DUSE_CCACHE=1")
|
flags+=("-DUSE_CCACHE=1")
|
||||||
# PCH-aware caching is required or ccache refuses to cache any TU that
|
# PCH-aware caching is required or ccache refuses to cache any TU that
|
||||||
|
|
@ -157,6 +214,10 @@ if [[ $USE_CCACHE ]]; then
|
||||||
ccache --max-size "$CCACHE_SIZE"
|
ccache --max-size "$CCACHE_SIZE"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [[ $USE_SCCACHE ]]; then
|
||||||
|
flags+=("-DUSE_SCCACHE=1")
|
||||||
|
flags+=("-DCMAKE_C_COMPILER_LAUNCHER=sccache" "-DCMAKE_CXX_COMPILER_LAUNCHER=sccache")
|
||||||
|
fi
|
||||||
if [[ $PACKAGE_TYPE ]]; then
|
if [[ $PACKAGE_TYPE ]]; then
|
||||||
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||||
fi
|
fi
|
||||||
|
|
@ -178,6 +239,22 @@ function ccachestatsverbose() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cpuinfo() {
|
||||||
|
# The number of cores decides how much build parallelism is useful; the hosted
|
||||||
|
# runners are not all sized alike, so read it off the machine instead of assuming.
|
||||||
|
case "$RUNNER_OS" in
|
||||||
|
Windows)
|
||||||
|
echo "cores: ${NUMBER_OF_PROCESSORS:-unknown}"
|
||||||
|
;;
|
||||||
|
macOS)
|
||||||
|
echo "cores: $(sysctl -n hw.ncpu)"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "cores: $(nproc 2>/dev/null || echo unknown)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
# Compile
|
# Compile
|
||||||
if [[ $RUNNER_OS == macOS ]]; then
|
if [[ $RUNNER_OS == macOS ]]; then
|
||||||
# QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action,
|
# QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action,
|
||||||
|
|
@ -212,8 +289,14 @@ if [[ $RUNNER_OS == macOS ]]; then
|
||||||
triplet_source="../vcpkg/triplets/community/$arch-osx.cmake"
|
triplet_source="../vcpkg/triplets/community/$arch-osx.cmake"
|
||||||
fi
|
fi
|
||||||
cp "$triplet_source" "$triplet_file"
|
cp "$triplet_source" "$triplet_file"
|
||||||
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file"
|
# The triplet is what vcpkg hashes into the ABI hash of every port, so two legs that
|
||||||
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file"
|
# agree here reuse each other's binary cache. Targets 14, 15 and 26 on the same Xcode
|
||||||
|
# produce identical binaries when they share the lowest deployment target, so they all
|
||||||
|
# build against 14 to keep one vcpkg cache scope instead of three.
|
||||||
|
# Keep in sync with "vcpkg_scope" and "vcpkg_deployment_target" in desktop-build.yml.
|
||||||
|
vcpkg_target="${VCPKG_TARGET_MACOS_VERSION:-$TARGET_MACOS_VERSION}"
|
||||||
|
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $vcpkg_target)" >>"$triplet_file"
|
||||||
|
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $vcpkg_target)" >>"$triplet_file"
|
||||||
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
|
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
|
||||||
flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version")
|
flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version")
|
||||||
flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version")
|
flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version")
|
||||||
|
|
@ -256,9 +339,33 @@ if [[ $RUNNER_OS == macOS ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [[ $RUNNER_OS == Windows ]]; then
|
elif [[ $RUNNER_OS == Windows ]]; then
|
||||||
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
if [[ $CMAKE_GENERATOR == "Visual Studio"* ]]; then
|
||||||
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
# cmake only hands MSBuild a job count when it is asked for, and without it
|
||||||
buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true)
|
# MSBuild builds a single node: one project at a time, whatever MTT does inside
|
||||||
|
# it. Ask for a node per core.
|
||||||
|
if [[ ! $BUILD_PARALLEL_LEVEL ]]; then
|
||||||
|
BUILD_PARALLEL_LEVEL="${NUMBER_OF_PROCESSORS:-1}"
|
||||||
|
fi
|
||||||
|
buildflags+=(--parallel "$BUILD_PARALLEL_LEVEL")
|
||||||
|
|
||||||
|
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||||
|
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
||||||
|
# EnforceProcessCountAcrossBuilds makes the CL_MPCount ceiling apply across all
|
||||||
|
# the projects the nodes are building, instead of each node running its own
|
||||||
|
# cl.exe processes and /m and MTT multiplying into an oversubscribed machine.
|
||||||
|
buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true -p:EnforceProcessCountAcrossBuilds=true -p:CL_MPCount="$BUILD_PARALLEL_LEVEL")
|
||||||
|
if [[ $BUILD_PROFILE ]]; then
|
||||||
|
# A performance summary says which projects and tasks cost what, the binary log
|
||||||
|
# keeps the full timeline; both are far too noisy to always produce. The files
|
||||||
|
# land next to the solution, i.e. in the build dir the workflow uploads. These
|
||||||
|
# join the MTT options above, which already carried the "--" separator.
|
||||||
|
buildflags+=("-flp:PerformanceSummary;v=q;LogFile=msbuild-perf.log" -bl:msbuild.binlog)
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Ninja runs the compiler itself, so it neither needs the MSVC switches nor
|
||||||
|
# wants a job count: it sizes its own pool for the cores it finds.
|
||||||
|
echo "ninja $(ninja --version)"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
|
|
@ -274,10 +381,19 @@ cmake .. "${flags[@]}"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Build project"
|
echo "::group::Build project"
|
||||||
|
cpuinfo
|
||||||
echo "Running cmake --build with flags: ${buildflags[*]}"
|
echo "Running cmake --build with flags: ${buildflags[*]}"
|
||||||
cmake --build . "${buildflags[@]}"
|
cmake --build . "${buildflags[@]}"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ $BUILD_PROFILE && $RUNNER_OS == Windows && -f msbuild-perf.log ]]; then
|
||||||
|
# Repeat the summary in the job log so the numbers are readable without
|
||||||
|
# downloading the binary log, which is hundreds of megabytes.
|
||||||
|
echo "::group::MSBuild performance summary"
|
||||||
|
cat msbuild-perf.log
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
if [[ $CCACHE_EVICTION_AGE ]]; then
|
if [[ $CCACHE_EVICTION_AGE ]]; then
|
||||||
echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE"
|
echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE"
|
||||||
|
|
@ -287,6 +403,10 @@ if [[ $USE_CCACHE ]]; then
|
||||||
echo "::group::Show ccache stats again"
|
echo "::group::Show ccache stats again"
|
||||||
ccachestatsverbose
|
ccachestatsverbose
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
elif [[ $USE_SCCACHE ]]; then
|
||||||
|
echo "::group::Show sccache stats"
|
||||||
|
sccache --show-stats
|
||||||
|
echo "::endgroup::"
|
||||||
elif [[ $CCACHE_EVICTION_AGE ]]; then
|
elif [[ $CCACHE_EVICTION_AGE ]]; then
|
||||||
echo "::error file=$0::ccache eviction is enabled while ccache is disabled!"
|
echo "::error file=$0::ccache eviction is enabled while ccache is disabled!"
|
||||||
fi
|
fi
|
||||||
|
|
@ -306,7 +426,50 @@ fi
|
||||||
|
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
echo "::group::Run tests"
|
echo "::group::Run tests"
|
||||||
ctest -C "$BUILDTYPE" --output-on-failure
|
if [[ $MAKE_SANITIZE ]]; then
|
||||||
|
# detect_leaks=0: Qt and the sanitizers' own runtimes both leak at exit by design, and
|
||||||
|
# LeakSanitizer's default is aggressive enough to bury our real findings under hundreds
|
||||||
|
# of process-teardown reports. Malloc/free misuse and use-after-free are what ASan is for
|
||||||
|
# and they stay fully on.
|
||||||
|
# abort_on_error=1: a bad access leaves the process in an unusable state, so continuing
|
||||||
|
# only produces a second, more confusing report from the wreckage.
|
||||||
|
# UBSAN halt_on_error=1: without it UBSan prints "runtime error: ..." but the
|
||||||
|
# process exits 0 (recover mode), so gtest/ctest report a pass and the job
|
||||||
|
# stays green. Combined with -fno-sanitize-recover=undefined at compile time,
|
||||||
|
# the first finding aborts the test process with a non-zero exit.
|
||||||
|
export ASAN_OPTIONS="detect_leaks=0:abort_on_error=1:print_stacktrace=1:symbolize=1"
|
||||||
|
export UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1:symbolize=1"
|
||||||
|
fi
|
||||||
|
# Every TEST() is its own CTest entry, so the suite is process-spawn bound rather than CPU
|
||||||
|
# bound and -j recovers nearly all of the per-process overhead. The test binaries are safe to
|
||||||
|
# run concurrently: the only one that claims a fixed resource is single_instance_manager_test,
|
||||||
|
# which already scopes its local socket name to its own pid so parallel copies cannot collide.
|
||||||
|
ctest -C "$BUILDTYPE" --output-on-failure -j "${CTEST_JOBS:-4}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAKE_COVERAGE ]]; then
|
||||||
|
# gcovr is not a build dependency and is not available everywhere, so a missing one is reported
|
||||||
|
# and skipped rather than failing an otherwise green build.
|
||||||
|
echo "::group::Coverage report"
|
||||||
|
GCOVR="$(command -v gcovr || true)"
|
||||||
|
if [[ -z $GCOVR ]]; then
|
||||||
|
echo "gcovr not found; install it to produce a coverage report"
|
||||||
|
else
|
||||||
|
"$GCOVR" --version
|
||||||
|
# This script configures with `cmake ..`, so the build dir it was started from is the object
|
||||||
|
# directory and the source root is one level up. Both are passed explicitly: gcovr otherwise
|
||||||
|
# walks the current directory and trips over in-tree build directories left by other tooling,
|
||||||
|
# whose stale .gcno files cannot be resolved. --config is named too, so the filters apply no
|
||||||
|
# matter what directory gcovr happens to start from.
|
||||||
|
GCOVR_ARGS=("." --root "$SRC_ROOT" --object-directory "." --config "$SRC_ROOT/gcovr.cfg")
|
||||||
|
"$GCOVR" "${GCOVR_ARGS[@]}" --txt --decisions
|
||||||
|
"$GCOVR" "${GCOVR_ARGS[@]}" --html-details coverage-details.html --html-title "Cockatrice line coverage"
|
||||||
|
"$GCOVR" "${GCOVR_ARGS[@]}" --lcov -o coverage.lcov
|
||||||
|
"$GCOVR" "${GCOVR_ARGS[@]}" --cobertura-pretty -o coverage.xml
|
||||||
|
"$GCOVR" "${GCOVR_ARGS[@]}" --json-summary-pretty -o coverage-summary.json
|
||||||
|
echo "Coverage artifacts written to coverage-details.html, coverage.lcov, coverage.xml and coverage-summary.json"
|
||||||
|
fi
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -353,15 +516,21 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
fi
|
fi
|
||||||
echo "Installer content is clean"
|
echo "Installer content is clean"
|
||||||
|
|
||||||
# Fail the build if the installer is missing a Qt runtime the applications
|
# Fail the build if the installer does not carry the runtime the
|
||||||
# link against. The DLLs reach the package by globbing every *.dll out of
|
# applications link against - a file that must be there, or a DLL that must
|
||||||
# the build output directories, so a module the client links statically
|
# not be. The runtime DLLs reach the package by globbing every *.dll out of
|
||||||
# (Qt6Multimedia.dll, Qt6QuickWidgets.dll) can be left out without anything
|
# the build output directories, so anything that build produced can ride
|
||||||
# else noticing, and the only symptom is a client that refuses to start
|
# along and nothing else in the build objects to it: a Qt module the client
|
||||||
# after an update. required-qt-runtime.txt is written by the top level
|
# links statically (Qt6Multimedia.dll, Qt6QuickWidgets.dll) can be left out,
|
||||||
# CMakeLists.txt from the same module list the targets are built against.
|
# and the test framework's gtest.dll can be shipped. Either only surfaces on
|
||||||
if [[ ! -f required-qt-runtime.txt ]]; then
|
# a user's machine after an update has already replaced their install, as
|
||||||
echo "::error file=$0::required-qt-runtime.txt not found in the build dir, cannot verify the Qt runtime"
|
# "The code execution cannot proceed because Qt6Multimedia.dll was not
|
||||||
|
# found" or "abseil_dll.dll is either not designed to run on Windows or it
|
||||||
|
# contains an error". required-runtime.txt is written by the top level
|
||||||
|
# CMakeLists.txt from the same module lists the targets are built against
|
||||||
|
# plus the vcpkg bin directory the app-local copies come from.
|
||||||
|
if [[ ! -f required-runtime.txt ]]; then
|
||||||
|
echo "::error file=$0::required-runtime.txt not found in the build dir, cannot verify the runtime"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# 7-Zip writes CRLF on Windows, so the \r has to come off before any
|
# 7-Zip writes CRLF on Windows, so the \r has to come off before any
|
||||||
|
|
@ -371,7 +540,7 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
# being a wildcard; -i because that is how the installed tree behaves -
|
# being a wildcard; -i because that is how the installed tree behaves -
|
||||||
# the uninstaller clears both $INSTDIR\plugins and $INSTDIR\Plugins.
|
# the uninstaller clears both $INSTDIR\plugins and $INSTDIR\Plugins.
|
||||||
# The archive side and the manifest side have to agree on line endings.
|
# The archive side and the manifest side have to agree on line endings.
|
||||||
# CMake writes required-qt-runtime.txt with the platform's line ending and
|
# CMake writes required-runtime.txt with the platform's line ending and
|
||||||
# 7-Zip writes CRLF on Windows, so a trailing \r survives on $entry and
|
# 7-Zip writes CRLF on Windows, so a trailing \r survives on $entry and
|
||||||
# defeats the whole-line match - every entry then reads as missing even
|
# defeats the whole-line match - every entry then reads as missing even
|
||||||
# though the listing holds it verbatim.
|
# though the listing holds it verbatim.
|
||||||
|
|
@ -380,7 +549,7 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
installer_paths="$("$seven_zip" l -slt "$package" | tr -d '\r' |
|
installer_paths="$("$seven_zip" l -slt "$package" | tr -d '\r' |
|
||||||
sed -n 's/^Path = //p' |
|
sed -n 's/^Path = //p' |
|
||||||
sed -e 's|\\|/|g' -e 's|^[$]INSTDIR/||' -e 's|^[$]OUTDIR/||' -e 's|^[$]PLUGINSDIR/||' -e 's|^\./||' -e 's|^/||')"
|
sed -e 's|\\|/|g' -e 's|^[$]INSTDIR/||' -e 's|^[$]OUTDIR/||' -e 's|^[$]PLUGINSDIR/||' -e 's|^\./||' -e 's|^/||')"
|
||||||
manifest="$(tr -d '\r' <required-qt-runtime.txt)"
|
manifest="$(tr -d '\r' <required-runtime.txt)"
|
||||||
missing=""
|
missing=""
|
||||||
checked=0
|
checked=0
|
||||||
while IFS= read -r entry; do
|
while IFS= read -r entry; do
|
||||||
|
|
@ -393,11 +562,11 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
fi
|
fi
|
||||||
done <<<"$manifest"
|
done <<<"$manifest"
|
||||||
if [[ -n $missing ]]; then
|
if [[ -n $missing ]]; then
|
||||||
echo "::error file=$0::Installer is missing required Qt runtime files:$missing"
|
echo "::error file=$0::Installer is missing required runtime files:$missing"
|
||||||
# Print both sides of the comparison. A mismatch here has twice been
|
# Print both sides of the comparison. A mismatch here has twice been
|
||||||
# caused by the shape of 7-Zip's output rather than by a missing file,
|
# caused by the shape of 7-Zip's output rather than by a missing file,
|
||||||
# and a bare "missing" line cannot tell those apart.
|
# and a bare "missing" line cannot tell those apart.
|
||||||
echo "required-qt-runtime.txt asked for $checked path(s); 7-Zip listed $(grep -c '' <<<"$installer_paths") path(s)"
|
echo "required-runtime.txt asked for $checked path(s); 7-Zip listed $(grep -c '' <<<"$installer_paths") path(s)"
|
||||||
# Indent with parameter expansion rather than sed 's/^/ /', which the
|
# Indent with parameter expansion rather than sed 's/^/ /', which the
|
||||||
# linter reports as SC2001.
|
# linter reports as SC2001.
|
||||||
echo "--- required ---"
|
echo "--- required ---"
|
||||||
|
|
@ -407,7 +576,66 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
echo "${listed_head//$'\n'/$'\n '}"
|
echo "${listed_head//$'\n'/$'\n '}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Installer contains the full Qt runtime ($checked files)"
|
echo "Installer carries the Qt runtime of every module the three applications link ($checked files)"
|
||||||
|
|
||||||
|
# Now the other direction: a top level DLL in the package that the manifest
|
||||||
|
# does not name. The missing check above cannot see a runtime that was
|
||||||
|
# never expected.
|
||||||
|
#
|
||||||
|
# Two things are reported here and neither may fail the build.
|
||||||
|
#
|
||||||
|
# The test framework is a fact rather than a guess - no shipped executable
|
||||||
|
# links gtest or gmock, and the build output directories the "*.dll" glob
|
||||||
|
# reads are shared with the test targets, so gtest.dll and gmock.dll are
|
||||||
|
# one filter away from shipping in every release. Even so it is reported
|
||||||
|
# instead of enforced: a check that has never passed on a real package has
|
||||||
|
# not earned the right to block a release, and the first Windows run of an
|
||||||
|
# enforcing version is exactly when its own wrong assumptions show up.
|
||||||
|
#
|
||||||
|
# Everything else is expected to be there. required-runtime.txt names the
|
||||||
|
# Qt modules the three applications link, and the protobuf, Abseil,
|
||||||
|
# OpenSSL, liblzma, ffmpeg and Qt debug DLLs in the package come in on the
|
||||||
|
# build output glob instead, because nothing in the build declares them by
|
||||||
|
# name. So this list is a report of what the package carries, not a verdict.
|
||||||
|
# Read it when a dependency is added; do not fail on it.
|
||||||
|
forbidden=""
|
||||||
|
unexpected=""
|
||||||
|
while IFS= read -r entry; do
|
||||||
|
[[ -z $entry ]] && continue
|
||||||
|
# Top level only. A DLL under Plugins/ or a nested image format plugin is
|
||||||
|
# a plugin the platform loads by name, not a runtime the executable
|
||||||
|
# imports, and requiring one here would list all of them every run.
|
||||||
|
[[ $entry == */* ]] && continue
|
||||||
|
if grep -qxiF "$entry" <<<"$manifest"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# NSIS extracts its plugins to $PLUGINSDIR, which the path normalization
|
||||||
|
# above strips, so they arrive here looking like payload files. They are
|
||||||
|
# part of the installer, not of the installed tree.
|
||||||
|
if [[ $entry == [Nn][Ss][Dd][Ii][Aa][Ll][Oo][Gg][Ss].dll ||
|
||||||
|
$entry == [Nn][Ss][Ee][Xx][Ee][Cc].dll ||
|
||||||
|
$entry == [Ss][Yy][Ss][Tt][Ee][Mm].dll ||
|
||||||
|
$entry == [Uu][Ss][Ee][Rr][Ii][Nn][Ff][Oo].dll ||
|
||||||
|
$entry == [Ii][Nn][Ee][Tt].dll ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $entry == [Gg][Tt][Ee][Ss][Tt]* || $entry == [Gg][Mm][Oo][Cc][Kk]* ]]; then
|
||||||
|
forbidden+=" $entry"
|
||||||
|
else
|
||||||
|
unexpected+=" $entry"
|
||||||
|
fi
|
||||||
|
done < <(grep -i '\.dll$' <<<"$installer_paths")
|
||||||
|
if [[ -n $forbidden ]]; then
|
||||||
|
echo "::warning file=$0::Installer contains test framework DLLs that no shipped executable links:$forbidden"
|
||||||
|
echo "A build output directory shared with the test targets has leaked into the package."
|
||||||
|
fi
|
||||||
|
if [[ -n $unexpected ]]; then
|
||||||
|
echo "Top level DLLs in the package beyond the linked Qt modules:$unexpected"
|
||||||
|
echo "These arrive on the build output glob, not from required-runtime.txt, so they are reported and not required."
|
||||||
|
fi
|
||||||
|
if [[ -z $forbidden && -z $unexpected ]]; then
|
||||||
|
echo "Installer carries no runtime files beyond the linked Qt modules"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,17 @@
|
||||||
# --set-cache <location> sets the location to cache the image or for ccache
|
# --set-cache <location> sets the location to cache the image or for ccache
|
||||||
#
|
#
|
||||||
# requires: docker
|
# requires: docker
|
||||||
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE
|
# uses env: NAME IMAGE_SUFFIX CACHE BUILD GET SAVE INTERACTIVE
|
||||||
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||||
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
||||||
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||||
#
|
#
|
||||||
|
# IMAGE_SUFFIX is optional and only appended to the image name, never to NAME, so that a matrix
|
||||||
|
# leg can have its own image and image cache without needing its own directory under .ci. Two legs
|
||||||
|
# building and tagging the same image concurrently would race on `docker build --tag`.
|
||||||
|
# It is deliberately not called SUFFIX: compile.sh already uses SUFFIX for output file names, and
|
||||||
|
# a job-level SUFFIX would be silently overridden by those per-step env blocks.
|
||||||
|
#
|
||||||
# exported RUN function will run the BUILD_SCRIPT inside of the docker container.
|
# exported RUN function will run the BUILD_SCRIPT inside of the docker container.
|
||||||
# note that the docker container will not inherit any environment variables!
|
# note that the docker container will not inherit any environment variables!
|
||||||
#
|
#
|
||||||
|
|
@ -81,7 +87,7 @@ if ! [[ $NAME ]]; then
|
||||||
return 3
|
return 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export IMAGE_NAME="${project_name,,}_${NAME,,}" # lower case
|
export IMAGE_NAME="${project_name,,}_${NAME,,}${IMAGE_SUFFIX:+_${IMAGE_SUFFIX,,}}" # lower case
|
||||||
|
|
||||||
docker_dir=".ci/$NAME"
|
docker_dir=".ci/$NAME"
|
||||||
if ! [[ -r $docker_dir/Dockerfile ]]; then
|
if ! [[ -r $docker_dir/Dockerfile ]]; then
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
.git/
|
|
||||||
build/
|
build/
|
||||||
.github/
|
.github/
|
||||||
.tx/
|
.tx/
|
||||||
|
|
|
||||||
299
.github/workflows/desktop-build.yml
vendored
299
.github/workflows/desktop-build.yml
vendored
|
|
@ -144,17 +144,36 @@ jobs:
|
||||||
|
|
||||||
package: DEB
|
package: DEB
|
||||||
|
|
||||||
name: ${{ matrix.distro }} ${{ matrix.version }}
|
# The one leg that runs the suite under AddressSanitizer and
|
||||||
|
# UndefinedBehaviorSanitizer. Debian 13 and Fedora 44 keep covering the
|
||||||
|
# uninstrumented suite, so nothing is lost by instrumenting this one.
|
||||||
|
sanitize: yes
|
||||||
|
|
||||||
|
- distro: Ubuntu
|
||||||
|
version: 26.04
|
||||||
|
variant: cover # separate image and ccache, same distro
|
||||||
|
|
||||||
|
# The one leg that runs instrumented for line coverage and publishes the report as
|
||||||
|
# a workflow artifact. It is a separate leg rather than a second flag on the
|
||||||
|
# sanitizer leg because the two instruments answer different questions: the
|
||||||
|
# sanitizer leg reports what the run did wrong, the coverage leg reports what the
|
||||||
|
# run never touched at all. Combining them would also slow both down. Packaging is
|
||||||
|
# skipped because the leg above already publishes the DEB for this distro.
|
||||||
|
coverage: yes
|
||||||
|
package: skip
|
||||||
|
|
||||||
|
name: ${{ matrix.distro }} ${{ matrix.version }}${{ matrix.variant && format(' {0}', matrix.variant) || '' }}
|
||||||
needs: configure
|
needs: configure
|
||||||
runs-on: ubuntu-latest # https://github.com/actions/runner-images
|
runs-on: ubuntu-latest # https://github.com/actions/runner-images
|
||||||
continue-on-error: ${{ matrix.allow-failure == 'yes' }}
|
continue-on-error: ${{ matrix.allow-failure == 'yes' }}
|
||||||
timeout-minutes: 70
|
timeout-minutes: 70
|
||||||
env:
|
env:
|
||||||
CACHE: ${{ github.workspace }}/.cache/${{ matrix.distro }}${{ matrix.version }} # directory for caching docker image and ccache
|
CACHE: ${{ github.workspace }}/.cache/${{ matrix.distro }}${{ matrix.version }}${{ matrix.variant }} # directory for caching docker image and ccache
|
||||||
CCACHE_EVICTION_AGE: 7d
|
CCACHE_EVICTION_AGE: 7d
|
||||||
CCACHE_SIZE: 600M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
CCACHE_SIZE: 600M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||||
CMAKE_GENERATOR: 'Ninja'
|
CMAKE_GENERATOR: 'Ninja'
|
||||||
NAME: ${{ matrix.distro }}${{ matrix.version }}
|
NAME: ${{ matrix.distro }}${{ matrix.version }}
|
||||||
|
IMAGE_SUFFIX: ${{ matrix.variant }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
|
|
@ -164,8 +183,8 @@ jobs:
|
||||||
id: restore_ccache
|
id: restore_ccache
|
||||||
uses: actions/cache/restore@v6
|
uses: actions/cache/restore@v6
|
||||||
with:
|
with:
|
||||||
key: ccache-${{ matrix.distro }}${{ matrix.version }}
|
key: ccache-${{ matrix.distro }}${{ matrix.version }}${{ matrix.variant }}
|
||||||
path: ${{ env.CACHE }}
|
path: ${{ env.CACHE }}/.ccache
|
||||||
|
|
||||||
- name: "Build ${{ matrix.distro }} ${{ matrix.version }} Docker image"
|
- name: "Build ${{ matrix.distro }} ${{ matrix.version }} Docker image"
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -174,6 +193,9 @@ jobs:
|
||||||
- name: "Build debug and test"
|
- name: "Build debug and test"
|
||||||
if: matrix.test != 'skip'
|
if: matrix.test != 'skip'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
env:
|
||||||
|
sanitize: '${{ matrix.sanitize }}'
|
||||||
|
coverage: '${{ matrix.coverage }}'
|
||||||
run: |
|
run: |
|
||||||
source .ci/docker.sh
|
source .ci/docker.sh
|
||||||
args=()
|
args=()
|
||||||
|
|
@ -181,7 +203,33 @@ jobs:
|
||||||
args+=(--ccache "$CCACHE_SIZE")
|
args+=(--ccache "$CCACHE_SIZE")
|
||||||
args+=(--cmake-generator "$CMAKE_GENERATOR")
|
args+=(--cmake-generator "$CMAKE_GENERATOR")
|
||||||
|
|
||||||
RUN --server --debug --test "${args[@]}"
|
extra=()
|
||||||
|
[[ $sanitize == yes ]] && extra+=(--sanitize)
|
||||||
|
[[ $coverage == yes ]] && extra+=(--coverage)
|
||||||
|
|
||||||
|
RUN --server --debug --test "${extra[@]}" "${args[@]}"
|
||||||
|
|
||||||
|
# RUN bind-mounts the workspace into the container, so the report the build wrote into
|
||||||
|
# build/ is already on the host and no second container is needed to collect it.
|
||||||
|
- name: "Collect coverage report"
|
||||||
|
if: matrix.coverage == 'yes'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p coverage
|
||||||
|
# --html-details writes one page per source file plus a stylesheet and script, and the
|
||||||
|
# index links to all of them by relative name. Copying the index alone would publish a
|
||||||
|
# report where every link 404s, so the whole family has to travel together.
|
||||||
|
cp build/coverage-details* coverage/
|
||||||
|
cp build/coverage.lcov build/coverage.xml build/coverage-summary.json coverage/
|
||||||
|
ls -la coverage/
|
||||||
|
|
||||||
|
- name: "Upload coverage artifact"
|
||||||
|
if: matrix.coverage == 'yes'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
path: coverage/
|
||||||
|
if-no-files-found: warn
|
||||||
|
|
||||||
- name: "Build release package"
|
- name: "Build release package"
|
||||||
id: build
|
id: build
|
||||||
|
|
@ -219,7 +267,7 @@ jobs:
|
||||||
uses: actions/cache/save@v6
|
uses: actions/cache/save@v6
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.restore_ccache.outputs.cache-primary-key }}
|
key: ${{ steps.restore_ccache.outputs.cache-primary-key }}
|
||||||
path: ${{ env.CACHE }}
|
path: ${{ env.CACHE }}/.ccache
|
||||||
|
|
||||||
- name: "Upload artifact"
|
- name: "Upload artifact"
|
||||||
id: upload_artifact
|
id: upload_artifact
|
||||||
|
|
@ -277,6 +325,8 @@ jobs:
|
||||||
soc: Intel
|
soc: Intel
|
||||||
type: Release
|
type: Release
|
||||||
use_ccache: 1
|
use_ccache: 1
|
||||||
|
vcpkg_scope: 'vcpkg/macos13-x64-xcode26.3/'
|
||||||
|
vcpkg_upload: 1 # only one leg per vcpkg_scope hands its archives over
|
||||||
xcode: "26.3"
|
xcode: "26.3"
|
||||||
|
|
||||||
- os: macOS
|
- os: macOS
|
||||||
|
|
@ -293,6 +343,9 @@ jobs:
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Release
|
type: Release
|
||||||
use_ccache: 1
|
use_ccache: 1
|
||||||
|
vcpkg_deployment_target: 14
|
||||||
|
vcpkg_scope: 'vcpkg/macos14-arm64-xcode26.6/'
|
||||||
|
vcpkg_upload: 1 # only one leg per vcpkg_scope hands its archives over
|
||||||
xcode: "26.6"
|
xcode: "26.6"
|
||||||
|
|
||||||
- os: macOS
|
- os: macOS
|
||||||
|
|
@ -309,6 +362,8 @@ jobs:
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Release
|
type: Release
|
||||||
use_ccache: 1
|
use_ccache: 1
|
||||||
|
vcpkg_deployment_target: 14
|
||||||
|
vcpkg_scope: 'vcpkg/macos14-arm64-xcode26.6/'
|
||||||
xcode: "26.6"
|
xcode: "26.6"
|
||||||
|
|
||||||
- os: macOS
|
- os: macOS
|
||||||
|
|
@ -322,12 +377,20 @@ jobs:
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Debug
|
type: Debug
|
||||||
use_ccache: 1
|
use_ccache: 1
|
||||||
|
vcpkg_deployment_target: 14
|
||||||
|
vcpkg_scope: 'vcpkg/macos14-arm64-xcode26.6/'
|
||||||
xcode: "26.6"
|
xcode: "26.6"
|
||||||
|
|
||||||
- os: Windows
|
- os: Windows
|
||||||
target: 10
|
target: 10
|
||||||
runner: windows-2025 # https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-VS2026-Readme.md
|
runner: windows-2025 # https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-VS2026-Readme.md
|
||||||
|
|
||||||
|
# Set build_profile: 1 to have the build write an MSBuild performance
|
||||||
|
# summary and a binary log; empty on every entry that runs by default.
|
||||||
|
# Enabled here on purpose: this pull request measures MSBuild
|
||||||
|
# parallelism, so its run is the one worth profiling.
|
||||||
|
build_profile: 1
|
||||||
|
|
||||||
cmake_generator: "Visual Studio 18 2026"
|
cmake_generator: "Visual Studio 18 2026"
|
||||||
cmake_generator_platform: x64
|
cmake_generator_platform: x64
|
||||||
make_package: 1
|
make_package: 1
|
||||||
|
|
@ -335,12 +398,40 @@ jobs:
|
||||||
qt_version: 6.11.*
|
qt_version: 6.11.*
|
||||||
qt_modules: qtimageformats qtmultimedia qtshadertools qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtshadertools qtwebsockets
|
||||||
type: Release
|
type: Release
|
||||||
|
vcpkg_scope: 'vcpkg/windows10-x64-vs2026/'
|
||||||
|
vcpkg_upload: 1 # only one leg per vcpkg_scope hands its archives over
|
||||||
|
|
||||||
name: ${{ matrix.os }} ${{ matrix.target }}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
# A/B run: is Ninja faster than the Visual Studio generator on this runner?
|
||||||
|
# It is allowed to fail and is never published, see the steps that build
|
||||||
|
# a release below. Delete this entry once the answer is known.
|
||||||
|
- os: Windows
|
||||||
|
target: 10
|
||||||
|
runner: windows-2025
|
||||||
|
|
||||||
|
cmake_generator: Ninja
|
||||||
|
experiment: yes
|
||||||
|
make_package: 1
|
||||||
|
package_suffix: "-Win10-ninja"
|
||||||
|
qt_version: 6.11.*
|
||||||
|
qt_modules: qtimageformats qtmultimedia qtshadertools qtwebsockets
|
||||||
|
type: Release
|
||||||
|
use_sccache: 1
|
||||||
|
variant: ' (Ninja)'
|
||||||
|
# The same scope as the Visual Studio leg, so both halves of the A/B
|
||||||
|
# start from the same vcpkg cache and the comparison is about the
|
||||||
|
# generator alone. Without it this leg's prefix is empty, which makes
|
||||||
|
# the cache action restore the whole vcpkg/ namespace and write entries
|
||||||
|
# that no scope claims. vcpkg_upload is deliberately left unset, so only
|
||||||
|
# the Visual Studio leg hands its archives over.
|
||||||
|
vcpkg_scope: 'vcpkg/windows10-x64-vs2026/'
|
||||||
|
|
||||||
|
name: ${{ matrix.os }} ${{ matrix.target }}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}${{ matrix.variant }}
|
||||||
needs: configure
|
needs: configure
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
|
continue-on-error: ${{ matrix.experiment == 'yes' }}
|
||||||
timeout-minutes: 100
|
timeout-minutes: 100
|
||||||
env:
|
env:
|
||||||
|
BUILD_PROFILE: '${{ matrix.build_profile }}'
|
||||||
CCACHE_DIR: ${{ github.workspace }}/.cache/
|
CCACHE_DIR: ${{ github.workspace }}/.cache/
|
||||||
CCACHE_SIZE: 600M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
CCACHE_SIZE: 600M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||||
|
|
||||||
|
|
@ -423,6 +514,28 @@ jobs:
|
||||||
modules: ${{ matrix.qt_modules }}
|
modules: ${{ matrix.qt_modules }}
|
||||||
version: ${{ matrix.qt_version }}
|
version: ${{ matrix.qt_version }}
|
||||||
|
|
||||||
|
# Ninja invokes cl.exe directly and needs the MSVC environment on PATH; the
|
||||||
|
# Visual Studio generator locates the compiler on its own and skips this.
|
||||||
|
- name: "[Windows/Ninja] Set up MSVC environment"
|
||||||
|
if: matrix.os == 'Windows' && matrix.cmake_generator == 'Ninja'
|
||||||
|
uses: TheMrMilchmann/setup-msvc-dev@v4.1.0
|
||||||
|
with:
|
||||||
|
arch: x64
|
||||||
|
|
||||||
|
# sccache is only useful for the Ninja job: a compiler cache has to wrap the
|
||||||
|
# compiler, and MSBuild is driven by cmake instead of running it, so a
|
||||||
|
# launcher handed to MSBuild is ignored without a word.
|
||||||
|
- name: "[Windows/Ninja] Set up sccache"
|
||||||
|
if: matrix.os == 'Windows' && matrix.cmake_generator == 'Ninja'
|
||||||
|
uses: mozilla-actions/sccache-action@v0.0.11
|
||||||
|
env:
|
||||||
|
SCCACHE_GHA_ENABLED: "true"
|
||||||
|
# A fork pull request can read the cache, but the token it runs with
|
||||||
|
# cannot write to the base branch's scope.
|
||||||
|
SCCACHE_GHA_RW_MODE: ${{ github.event.pull_request.head.repo.fork && 'READ_ONLY' || 'READ_WRITE' }}
|
||||||
|
# A cache that cannot be reached must not fail the build.
|
||||||
|
SCCACHE_IGNORE_SERVER_IO_ERROR: "1"
|
||||||
|
|
||||||
- name: "[Windows] Install NSIS"
|
- name: "[Windows] Install NSIS"
|
||||||
if: matrix.os == 'Windows'
|
if: matrix.os == 'Windows'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -432,8 +545,28 @@ jobs:
|
||||||
id: vcpkg-cache
|
id: vcpkg-cache
|
||||||
uses: TAServers/vcpkg-cache@v3
|
uses: TAServers/vcpkg-cache@v3
|
||||||
with:
|
with:
|
||||||
|
# Every entry is keyed by vcpkg ABI hash, and one hash set exists per platform,
|
||||||
|
# target and toolchain. The action restores every entry it finds under the
|
||||||
|
# prefix, not just the hashes vcpkg asks for, so with one shared vcpkg/
|
||||||
|
# namespace every leg downloads all 66 archives of all 5 legs on every run.
|
||||||
|
# Each of those restores also refreshes the entry's last access date, which
|
||||||
|
# is why a dead ABI generation is never evicted by age. Naming the scope is
|
||||||
|
# what makes those generations identifiable, and prune-caches below able to
|
||||||
|
# delete them.
|
||||||
|
prefix: ${{ matrix.vcpkg_scope }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# The action only creates its directory when the prefix matched at least one
|
||||||
|
# entry, and it reads that directory unguarded when it saves at the end of the
|
||||||
|
# job. A scope nobody has written to yet therefore leaves the directory missing
|
||||||
|
# and fails the job, which is exactly the state every scope starts in. Make the
|
||||||
|
# directory up front so an empty scope is a cache miss instead of an error.
|
||||||
|
- name: "Create vcpkg cache directory"
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
CACHE_DIR: '${{ steps.vcpkg-cache.outputs.path }}'
|
||||||
|
run: mkdir -p "$CACHE_DIR"
|
||||||
|
|
||||||
# Uses environment variables, see compile.sh for more details
|
# Uses environment variables, see compile.sh for more details
|
||||||
- name: "Build Cockatrice"
|
- name: "Build Cockatrice"
|
||||||
id: build
|
id: build
|
||||||
|
|
@ -451,11 +584,22 @@ jobs:
|
||||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||||
MAKE_PACKAGE: '${{ matrix.make_package }}'
|
MAKE_PACKAGE: '${{ matrix.make_package }}'
|
||||||
PACKAGE_SUFFIX: '${{ matrix.package_suffix }}'
|
PACKAGE_SUFFIX: '${{ matrix.package_suffix }}'
|
||||||
TARGET_MACOS_VERSION: ${{ matrix.override_target }}
|
TARGET_MACOS_VERSION: '${{ matrix.override_target }}'
|
||||||
USE_CCACHE: ${{ matrix.use_ccache }}
|
USE_CCACHE: ${{ matrix.use_ccache }}
|
||||||
|
USE_SCCACHE: ${{ matrix.use_sccache }}
|
||||||
|
# Only pushes to the default branch may write the shared binary cache: the
|
||||||
|
# archives a run compiles are only as trustworthy as the code they were
|
||||||
|
# built from, and only merged code may populate the scope that master and
|
||||||
|
# release builds restore and link. Pull requests (same-repository ones
|
||||||
|
# included) restore the shared cache but never write it; with the source
|
||||||
|
# left at read the collect step below finds nothing on PRs, so no
|
||||||
|
# pull-request-scoped entry is ever saved that no later run could restore.
|
||||||
|
# Forks pushing to their own default branch resolve github.ref against
|
||||||
|
# their own repository, so they keep a working cache of their own there.
|
||||||
VCPKG_BINARY_SOURCES: "clear;files,${{ steps.vcpkg-cache.outputs.path }},${{ case(github.ref == 'refs/heads/master', 'readwrite', 'read') }}"
|
VCPKG_BINARY_SOURCES: "clear;files,${{ steps.vcpkg-cache.outputs.path }},${{ case(github.ref == 'refs/heads/master', 'readwrite', 'read') }}"
|
||||||
VCPKG_DISABLE_METRICS: 1
|
VCPKG_DISABLE_METRICS: 1
|
||||||
VCPKG_FEATURE_FLAGS: dependencygraph
|
VCPKG_FEATURE_FLAGS: dependencygraph
|
||||||
|
VCPKG_TARGET_MACOS_VERSION: ${{ matrix.vcpkg_deployment_target }}
|
||||||
run: .ci/compile.sh --server --test --vcpkg
|
run: .ci/compile.sh --server --test --vcpkg
|
||||||
|
|
||||||
# CPack reports a failed makensis run as "Problem running NSIS command"
|
# CPack reports a failed makensis run as "Problem running NSIS command"
|
||||||
|
|
@ -469,6 +613,63 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
run: find . -name NSISOutput.log -exec cat {} +
|
run: find . -name NSISOutput.log -exec cat {} +
|
||||||
|
|
||||||
|
# A master run hands over the archives it had to build itself so that
|
||||||
|
# vcpkg-cache-import.yml, which runs in the default branch scope, can save them
|
||||||
|
# where later runs can restore them. Pull requests hand over nothing: their cache
|
||||||
|
# entries would be scoped to refs/pull/<n>/merge and stay unreadable for every
|
||||||
|
# other run, so writing them only burns the repository's quota.
|
||||||
|
# vcpkg_upload keeps this to one leg per scope: macOS 14, 15 and 26 share a scope
|
||||||
|
# by design, and all three rebuild the same archives, so uploading from each of them
|
||||||
|
# would publish three identical 269 MB artifacts under one artifact name and make
|
||||||
|
# the importer spawn a save job per copy.
|
||||||
|
- name: "Collect new vcpkg entries"
|
||||||
|
id: vcpkg_new
|
||||||
|
if: github.ref == 'refs/heads/master' && matrix.vcpkg_upload == 1
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
CACHE_DIR: '${{ steps.vcpkg-cache.outputs.path }}'
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
VCPKG_SCOPE: '${{ matrix.vcpkg_scope }}'
|
||||||
|
run: |
|
||||||
|
# The archive name is the ABI hash, so a missing key is exactly what vcpkg had
|
||||||
|
# to compile from source in this job.
|
||||||
|
gh api --paginate \
|
||||||
|
"repos/$GITHUB_REPOSITORY/actions/caches?ref=refs/heads/master&key=$VCPKG_SCOPE&per_page=100" \
|
||||||
|
--jq '.actions_caches[].key' | sort -u >"$RUNNER_TEMP/master-keys.txt"
|
||||||
|
find "$CACHE_DIR" -type f -name '*.zip' -exec basename {} .zip \; |
|
||||||
|
sed "s|^|$VCPKG_SCOPE|" | sort -u >"$RUNNER_TEMP/local-keys.txt"
|
||||||
|
comm -23 "$RUNNER_TEMP/local-keys.txt" "$RUNNER_TEMP/master-keys.txt" >"$RUNNER_TEMP/new-keys.txt"
|
||||||
|
|
||||||
|
mkdir -p "$RUNNER_TEMP/vcpkg-new"
|
||||||
|
: >"$RUNNER_TEMP/vcpkg-new/keys.txt"
|
||||||
|
while read -r key; do
|
||||||
|
hash="${key##*/}"
|
||||||
|
archive="$(find "$CACHE_DIR" -type f -name "$hash.zip" -print -quit)"
|
||||||
|
dir="$RUNNER_TEMP/vcpkg-new/${hash:0:2}" # vcpkg's own two character fanout
|
||||||
|
mkdir -p "$dir"
|
||||||
|
cp "$archive" "$dir/"
|
||||||
|
echo "$key ${hash:0:2}/$hash.zip" >>"$RUNNER_TEMP/vcpkg-new/keys.txt"
|
||||||
|
done <"$RUNNER_TEMP/new-keys.txt"
|
||||||
|
|
||||||
|
count="$(wc -l <"$RUNNER_TEMP/new-keys.txt")"
|
||||||
|
echo "vcpkg scope $VCPKG_SCOPE: $count entries to import"
|
||||||
|
echo "count=$count" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "slug=$(sed -e 's|^vcpkg/||' -e 's|/$||' -e 's|/|-|g' <<<"$VCPKG_SCOPE")" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# archive: false accepts a single file and nothing else, and a scope hands over one
|
||||||
|
# archive per ABI hash vcpkg had to rebuild, which is 23 files on a cold runner.
|
||||||
|
# Zipping the directory keeps the fanout at the artifact root, which is where
|
||||||
|
# vcpkg-cache-import.yml looks for keys.txt once download-artifact unpacks it.
|
||||||
|
- name: "Upload new vcpkg entries"
|
||||||
|
# An empty count means the step above did not run at all, on master and on forks
|
||||||
|
if: steps.vcpkg_new.outputs.count != '' && steps.vcpkg_new.outputs.count != '0'
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
if-no-files-found: error # a count above zero with nothing staged is a bug
|
||||||
|
name: vcpkg-new-${{ steps.vcpkg_new.outputs.slug }}
|
||||||
|
path: ${{ runner.temp }}/vcpkg-new
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
# Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342
|
# Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342
|
||||||
- name: "[macOS] Delete remote compiler cache (ccache)"
|
- name: "[macOS] Delete remote compiler cache (ccache)"
|
||||||
if: matrix.os == 'macOS' && matrix.use_ccache == 1 && github.ref == 'refs/heads/master' && steps.restore_ccache.outputs.cache-hit
|
if: matrix.os == 'macOS' && matrix.use_ccache == 1 && github.ref == 'refs/heads/master' && steps.restore_ccache.outputs.cache-hit
|
||||||
|
|
@ -544,8 +745,11 @@ jobs:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
path: ${{ steps.build.outputs.path }}
|
path: ${{ steps.build.outputs.path }}
|
||||||
|
|
||||||
|
# Ninja writes its PDBs next to the binaries instead of into a Release
|
||||||
|
# subdirectory, and the experimental job is not a source of release debug
|
||||||
|
# symbols, so it keeps out of both.
|
||||||
- name: "[Windows] Upload PDBs (Program Databases)"
|
- name: "[Windows] Upload PDBs (Program Databases)"
|
||||||
if: matrix.os == 'Windows' && github.ref_type != 'tag'
|
if: matrix.os == 'Windows' && matrix.experiment != 'yes' && github.ref_type != 'tag'
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
@ -555,8 +759,19 @@ jobs:
|
||||||
build/oracle/Release/*.pdb
|
build/oracle/Release/*.pdb
|
||||||
build/servatrice/Release/*.pdb
|
build/servatrice/Release/*.pdb
|
||||||
|
|
||||||
|
# Written only when the matrix entry sets build_profile, so the artifact
|
||||||
|
# exists exactly on the runs that were asked to produce one.
|
||||||
|
- name: "[Windows] Upload MSBuild binary log"
|
||||||
|
if: always() && matrix.os == 'Windows' && env.BUILD_PROFILE == '1'
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
if-no-files-found: error
|
||||||
|
name: ${{ steps.build.outputs.name }}-msbuild
|
||||||
|
path: build/msbuild.binlog
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
- name: "Upload to release"
|
- name: "Upload to release"
|
||||||
if: needs.configure.outputs.tag != null && matrix.make_package == '1'
|
if: needs.configure.outputs.tag != null && matrix.make_package == '1' && matrix.experiment != 'yes'
|
||||||
id: upload_release
|
id: upload_release
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
|
|
@ -581,3 +796,67 @@ jobs:
|
||||||
BUILD_PATH: ${{ steps.build.outputs.path }}
|
BUILD_PATH: ${{ steps.build.outputs.path }}
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice
|
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice
|
||||||
|
|
||||||
|
prune-caches:
|
||||||
|
name: Prune caches
|
||||||
|
# Only master writes caches at all, so only master may clean them up too
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
||||||
|
continue-on-error: true # freeing space must never fail a build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# The repository holds 10Gi of cache against entries that want more, and GitHub
|
||||||
|
# evicts the least recently used entry whenever that is exceeded. The vcpkg
|
||||||
|
# entries are the reason that never happens: the restore above touches every
|
||||||
|
# entry under the prefix on every run, so a dead ABI generation keeps its access
|
||||||
|
# date fresh forever and age based eviction can never reach it. Deleting by age
|
||||||
|
# alone cannot fix that, only knowing which scope an entry belongs to can.
|
||||||
|
- name: "Delete unusable cache entries"
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
# Must list every vcpkg_scope of the build-vcpkg matrix above, or the entries of
|
||||||
|
# a scope that is still in use get deleted on the next run.
|
||||||
|
LIVE_VCPKG_SCOPES: 'vcpkg/macos13-x64-xcode26.3/ vcpkg/macos14-arm64-xcode26.6/ vcpkg/windows10-x64-vs2026/'
|
||||||
|
run: |
|
||||||
|
gh api --paginate "repos/$GITHUB_REPOSITORY/actions/caches?per_page=100" \
|
||||||
|
--jq '.actions_caches[] | [.id, .ref, .key, .last_accessed_at] | @tsv' >"$RUNNER_TEMP/caches.tsv"
|
||||||
|
|
||||||
|
cutoff="$(( $(date -u +%s) - 7 * 24 * 3600 ))"
|
||||||
|
live=" ${LIVE_VCPKG_SCOPES} "
|
||||||
|
deleted=0
|
||||||
|
while IFS=$'\t' read -r id ref key accessed; do
|
||||||
|
[[ -n $id ]] || continue
|
||||||
|
# Only ever touch the key shapes this workflow creates, so that an entry of
|
||||||
|
# some other workflow can never be deleted by accident
|
||||||
|
case "$key" in
|
||||||
|
vcpkg/* | ccache-* | Qt*) ;;
|
||||||
|
*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
reason=""
|
||||||
|
if [[ $ref != refs/heads/master ]]; then
|
||||||
|
reason="scoped to $ref"
|
||||||
|
elif [[ $key == vcpkg/* ]]; then
|
||||||
|
# "<scope>/<abi hash>", cut the hash off the end to get the scope
|
||||||
|
scope="vcpkg/${key#vcpkg/}"
|
||||||
|
scope="${scope%/*}/"
|
||||||
|
if [[ $live != *" $scope "* ]]; then
|
||||||
|
reason="no matrix leg uses $scope"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -z $reason ]]; then
|
||||||
|
stamp="$(date -u -d "$accessed" +%s 2>/dev/null || echo 0)"
|
||||||
|
if [[ $stamp -ne 0 && $stamp -lt $cutoff ]]; then
|
||||||
|
reason="unused since $accessed"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $reason ]]; then
|
||||||
|
echo "::notice::deleting $key, $reason"
|
||||||
|
gh api -X DELETE "repos/$GITHUB_REPOSITORY/actions/caches/$id"
|
||||||
|
deleted=$((deleted + 1))
|
||||||
|
fi
|
||||||
|
done <"$RUNNER_TEMP/caches.tsv"
|
||||||
|
|
||||||
|
echo "::notice::deleted $deleted of $(wc -l <"$RUNNER_TEMP/caches.tsv") cache entries"
|
||||||
|
|
|
||||||
33
.github/workflows/docker-release.yml
vendored
33
.github/workflows/docker-release.yml
vendored
|
|
@ -20,11 +20,22 @@ on:
|
||||||
release:
|
release:
|
||||||
types:
|
types:
|
||||||
- released # publishing of stable releases
|
- released # publishing of stable releases
|
||||||
|
workflow_dispatch: # (re)publish the image for an existing stable release
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Existing release tag to build and publish (e.g. 2026-10-03-Release-3.1.0)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
latest:
|
||||||
|
description: 'Also update the "latest" tag'
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
|
||||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
|
# Cancel earlier, unfinished runs of this workflow on the same branch (unless publishing)
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
|
group: "${{ github.workflow }} @ ${{ inputs.tag || github.ref_name }}"
|
||||||
cancel-in-progress: ${{ github.event_name != 'release' }}
|
cancel-in-progress: ${{ github.event_name != 'release' && github.event_name != 'workflow_dispatch' }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GHCR_IMAGE: ghcr.io/cockatrice/servatrice
|
GHCR_IMAGE: ghcr.io/cockatrice/servatrice
|
||||||
|
|
@ -57,12 +68,14 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v7
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
ref: ${{ case(github.event_name == 'workflow_dispatch', format('refs/tags/{0}', inputs.tag), '') }}
|
||||||
|
|
||||||
- name: "Set up Docker buildx"
|
- name: "Set up Docker buildx"
|
||||||
uses: docker/setup-buildx-action@v4
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: "Login to GitHub Container Registry (GHCR)"
|
- name: "Login to GitHub Container Registry (GHCR)"
|
||||||
if: github.event_name == 'release' && github.event.release.prerelease == false
|
if: (github.event_name == 'release' && github.event.release.prerelease == false) || github.event_name == 'workflow_dispatch'
|
||||||
id: login
|
id: login
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -70,7 +83,7 @@ jobs:
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ github.token }}
|
password: ${{ github.token }}
|
||||||
|
|
||||||
# Don't push for non-release triggers
|
# Don't push for non-publishing triggers
|
||||||
- name: "Build image"
|
- name: "Build image"
|
||||||
if: steps.login.outcome != 'success'
|
if: steps.login.outcome != 'success'
|
||||||
uses: docker/build-push-action@v7
|
uses: docker/build-push-action@v7
|
||||||
|
|
@ -111,7 +124,6 @@ jobs:
|
||||||
if: steps.login.outcome == 'success'
|
if: steps.login.outcome == 'success'
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
archive: false
|
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: digest-${{ matrix.label }}
|
name: digest-${{ matrix.label }}
|
||||||
path: ${{ runner.temp }}/digests/*
|
path: ${{ runner.temp }}/digests/*
|
||||||
|
|
@ -121,7 +133,7 @@ jobs:
|
||||||
# Create an OCI image index from the platform-specific image manifests
|
# Create an OCI image index from the platform-specific image manifests
|
||||||
index:
|
index:
|
||||||
name: "Publish multi-platform Servatrice image"
|
name: "Publish multi-platform Servatrice image"
|
||||||
if: github.repository_owner == 'Cockatrice' && github.event_name == 'release' && github.event.release.prerelease == false
|
if: github.repository_owner == 'Cockatrice' && ((github.event_name == 'release' && github.event.release.prerelease == false) || github.event_name == 'workflow_dispatch')
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
||||||
|
|
||||||
|
|
@ -147,8 +159,11 @@ jobs:
|
||||||
images: ${{ env.GHCR_IMAGE }}
|
images: ${{ env.GHCR_IMAGE }}
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=auto
|
latest=auto
|
||||||
|
# if semver, also: type=semver,pattern={{version}} / {{major}}.{{minor}}
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=tag # if semver, also: type=semver,pattern={{version}} / {{major}}.{{minor}}
|
type=ref,event=tag
|
||||||
|
type=raw,value=${{ inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' && inputs.latest }}
|
||||||
|
|
||||||
# Add OCI annotations to image index and publish tags
|
# Add OCI annotations to image index and publish tags
|
||||||
- name: "Create image index"
|
- name: "Create image index"
|
||||||
|
|
@ -176,7 +191,7 @@ jobs:
|
||||||
|
|
||||||
- name: "Inspect images"
|
- name: "Inspect images"
|
||||||
env:
|
env:
|
||||||
GITHUB_TAG: ${{ github.ref_name }}
|
GITHUB_TAG: ${{ inputs.tag || github.ref_name }}
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect "$GHCR_IMAGE:latest"
|
docker buildx imagetools inspect "$GHCR_IMAGE:latest"
|
||||||
docker buildx imagetools inspect "$GHCR_IMAGE:$GITHUB_TAG"
|
docker buildx imagetools inspect "$GHCR_IMAGE:$GITHUB_TAG"
|
||||||
|
|
|
||||||
12
.github/workflows/documentation-build.yml
vendored
12
.github/workflows/documentation-build.yml
vendored
|
|
@ -28,12 +28,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v7
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: "Install Graphviz"
|
- name: "Install Graphviz"
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y graphviz
|
sudo apt-get install -y graphviz
|
||||||
dot -V
|
dot -V
|
||||||
|
|
@ -44,6 +45,7 @@ jobs:
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
|
|
||||||
- name: "Update Doxygen Configuration"
|
- name: "Update Doxygen Configuration"
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
git diff Doxyfile
|
git diff Doxyfile
|
||||||
doxygen -u Doxyfile
|
doxygen -u Doxyfile
|
||||||
|
|
@ -58,9 +60,10 @@ jobs:
|
||||||
|
|
||||||
- name: "Generate Documentation"
|
- name: "Generate Documentation"
|
||||||
if: always()
|
if: always()
|
||||||
|
shell: bash
|
||||||
run: doxygen Doxyfile
|
run: doxygen Doxyfile
|
||||||
|
|
||||||
- name: "Deploy to cockatrice.github.io"
|
- name: "Deploy to cockatrice.github.io/docs"
|
||||||
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -69,3 +72,8 @@ jobs:
|
||||||
external_repository: Cockatrice/cockatrice.github.io
|
external_repository: Cockatrice/cockatrice.github.io
|
||||||
publish_branch: master
|
publish_branch: master
|
||||||
publish_dir: ./docs/html
|
publish_dir: ./docs/html
|
||||||
|
|
||||||
|
- name: Link to Documentation Page
|
||||||
|
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
|
||||||
|
shell: bash
|
||||||
|
run: echo "::notice title=New documentation published::Shortly available at https://cockatrice.github.io/docs/"
|
||||||
|
|
|
||||||
2
.github/workflows/translations-pull.yml
vendored
2
.github/workflows/translations-pull.yml
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
name: Update Translations
|
name: Update Translations
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
|
||||||
2
.github/workflows/translations-push.yml
vendored
2
.github/workflows/translations-push.yml
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
name: Update Translation Source
|
name: Update Translation Source
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
|
||||||
121
.github/workflows/vcpkg-cache-import.yml
vendored
Normal file
121
.github/workflows/vcpkg-cache-import.yml
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
name: Import vcpkg cache
|
||||||
|
|
||||||
|
# After a runner image update changes every port's ABI hash, the first master run
|
||||||
|
# rebuilds protobuf, openssl and abseil from source and saves them into the shared
|
||||||
|
# cache, where every later run can restore them.
|
||||||
|
#
|
||||||
|
# Only master pushes are imported here: the collect step, keys.txt and the zip
|
||||||
|
# contents all come from the workflow run being imported, so importing from an
|
||||||
|
# unmerged pull request would let anyone who can push a branch — or a bot actor
|
||||||
|
# such as Dependabot, whose PRs are same-repo — promote arbitrary binaries into
|
||||||
|
# the scope that master and tag builds restore and link into signed releases.
|
||||||
|
# Forks build untrusted code and must never reach that scope either.
|
||||||
|
#
|
||||||
|
# repository_dispatch is not used on purpose: it would also resolve to the default branch,
|
||||||
|
# but it counts as a low-trust trigger and may only write there when it declares a
|
||||||
|
# write-capable cache-mode, which puts it in the same position as workflow_run.
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
actions: write # needed to save entries into the default branch's cache scope
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Build Desktop"]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
# Every import writes the same scopes, so let them queue instead of racing each other
|
||||||
|
concurrency:
|
||||||
|
group: vcpkg-cache-import
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
list:
|
||||||
|
name: List new vcpkg entries
|
||||||
|
# Only a successful push to the default branch has archives worth importing.
|
||||||
|
# Only code that landed on master may populate the scope master runs restore.
|
||||||
|
# Bot actors are excluded on top: their runs must never promote binaries into
|
||||||
|
# the shared scope even if they somehow target the default branch.
|
||||||
|
if: >-
|
||||||
|
github.event.workflow_run.conclusion == 'success' &&
|
||||||
|
github.event.workflow_run.event == 'push' &&
|
||||||
|
github.event.workflow_run.head_branch == 'master' &&
|
||||||
|
github.event.workflow_run.head_repository.full_name == github.repository &&
|
||||||
|
!endsWith(github.event.workflow_run.actor.login, '[bot]') &&
|
||||||
|
!endsWith(github.event.workflow_run.triggering_actor.login, '[bot]')
|
||||||
|
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
||||||
|
# workflow_run is a low-trust trigger, so cache access is read-only by default even
|
||||||
|
# though this run resolves to the default branch. Assert below that this took effect,
|
||||||
|
# because a save under read-only access only warns and would import nothing silently.
|
||||||
|
cache-mode: write
|
||||||
|
outputs:
|
||||||
|
entries: ${{ steps.scan.outputs.entries }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Download new vcpkg entries"
|
||||||
|
uses: actions/download-artifact@v8
|
||||||
|
with:
|
||||||
|
pattern: vcpkg-new-*
|
||||||
|
path: incoming
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: "Assert write access"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ $ACTIONS_CACHE_MODE != *write* ]]; then
|
||||||
|
echo "::error::expected a write-capable cache, got '$ACTIONS_CACHE_MODE'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: "List cache entries"
|
||||||
|
id: scan
|
||||||
|
shell: bash
|
||||||
|
working-directory: incoming
|
||||||
|
run: |
|
||||||
|
entries="$(find . -name keys.txt -type f -exec sh -c '
|
||||||
|
for manifest; do
|
||||||
|
artifact="$(basename "$(dirname "$manifest")")"
|
||||||
|
while read -r key path; do
|
||||||
|
printf "{\"artifact\": \"%s\", \"key\": \"%s\", \"path\": \"%s\"}\n" \
|
||||||
|
"$artifact" "$key" "$path"
|
||||||
|
done <"$manifest"
|
||||||
|
done
|
||||||
|
' _ {} +)"
|
||||||
|
[[ -n $entries ]] || exit 0
|
||||||
|
# Compact, because a multi line value cannot be written to GITHUB_OUTPUT
|
||||||
|
entries="$(jq -cs '.' <<<"$entries")"
|
||||||
|
echo "entries=$entries" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "::notice::importing $(jq length <<<"$entries") vcpkg entries"
|
||||||
|
|
||||||
|
save:
|
||||||
|
name: "Save ${{ matrix.entry.key }}"
|
||||||
|
needs: list
|
||||||
|
if: needs.list.outputs.entries
|
||||||
|
runs-on: ubuntu-slim
|
||||||
|
cache-mode: write
|
||||||
|
strategy:
|
||||||
|
# One job per archive, they run in parallel and each only uploads a single file
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 20
|
||||||
|
matrix:
|
||||||
|
entry: ${{ fromJSON(needs.list.outputs.entries) }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Download new vcpkg entries"
|
||||||
|
uses: actions/download-artifact@v8
|
||||||
|
with:
|
||||||
|
pattern: ${{ matrix.entry.artifact }}
|
||||||
|
path: incoming
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: "Save vcpkg entry"
|
||||||
|
uses: actions/cache/save@v6
|
||||||
|
with:
|
||||||
|
# The payload is a Windows or macOS archive while the upload runs on Linux, and
|
||||||
|
# without this the entry would be stamped as a Linux cache that neither of them
|
||||||
|
# is allowed to restore.
|
||||||
|
enableCrossOsArchive: true
|
||||||
|
key: ${{ matrix.entry.key }}
|
||||||
|
path: incoming/${{ matrix.entry.path }}
|
||||||
|
|
@ -8,8 +8,19 @@
|
||||||
# 3.16 required for Qt6 and target_precompile_headers()
|
# 3.16 required for Qt6 and target_precompile_headers()
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
# Let CMake pick the MSVC debug information format through
|
||||||
|
# CMAKE_MSVC_DEBUG_INFORMATION_FORMAT instead of writing it into the
|
||||||
|
# CMAKE_<LANG>_FLAGS_<CONFIG> defaults. The policy has to be settled before the
|
||||||
|
# first project() enables a language, and it does not exist before CMake 3.25,
|
||||||
|
# where the old defaults are the only thing available.
|
||||||
|
if(POLICY CMP0141)
|
||||||
|
cmake_policy(SET CMP0141 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Use compiler cache (ccache)
|
# Use compiler cache (ccache)
|
||||||
option(USE_CCACHE "Cache the build results with ccache" ON)
|
option(USE_CCACHE "Cache the build results with ccache" ON)
|
||||||
|
# Use compiler cache (sccache), for generators that invoke the compiler themselves
|
||||||
|
option(USE_SCCACHE "Cache the build results with sccache" OFF)
|
||||||
# Treat warnings as errors (Debug builds only)
|
# Treat warnings as errors (Debug builds only)
|
||||||
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||||
# Check for translation updates
|
# Check for translation updates
|
||||||
|
|
@ -22,6 +33,10 @@ option(WITH_ORACLE "Build Cockatrice card database tool (Oracle)" ON)
|
||||||
option(WITH_SERVER "Build Cockatrice server (Servatrice)" OFF)
|
option(WITH_SERVER "Build Cockatrice server (Servatrice)" OFF)
|
||||||
# Compile tests
|
# Compile tests
|
||||||
option(TEST "Build tests" OFF)
|
option(TEST "Build tests" OFF)
|
||||||
|
# Build with AddressSanitizer and UndefinedBehaviorSanitizer
|
||||||
|
option(ENABLE_SANITIZERS "Build with AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
|
||||||
|
# Build instrumented for GCC line coverage, reported with gcovr
|
||||||
|
option(ENABLE_COVERAGE "Build instrumented for GCC line coverage" OFF)
|
||||||
# Use vcpkg regardless of OS
|
# Use vcpkg regardless of OS
|
||||||
option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
|
option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
|
||||||
|
|
||||||
|
|
@ -86,11 +101,11 @@ endif()
|
||||||
|
|
||||||
# A project name is needed for CPack
|
# A project name is needed for CPack
|
||||||
# Version can be overriden by git tags, see cmake/getversion.cmake
|
# Version can be overriden by git tags, see cmake/getversion.cmake
|
||||||
project("Cockatrice" VERSION 3.1.0)
|
project("Cockatrice" VERSION 3.1.2)
|
||||||
|
|
||||||
# Set release name if not provided via env/cmake var
|
# Set release name if not provided via env/cmake var
|
||||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||||
set(GIT_TAG_RELEASENAME "Graduation Day")
|
set(GIT_TAG_RELEASENAME "Reality Check")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Use c++20 for all targets
|
# Use c++20 for all targets
|
||||||
|
|
@ -152,8 +167,17 @@ endif()
|
||||||
|
|
||||||
# Define proper compilation flags
|
# Define proper compilation flags
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics, Debug Symbols
|
# Debug information: a cache can only store and restore objects that carry it
|
||||||
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc /Zi")
|
# inside, so a cached build asks for /Z7 (Embedded); otherwise /Zi (ProgramDatabase).
|
||||||
|
# Either way the linker is told to write the PDB, in every configuration.
|
||||||
|
if(USE_SCCACHE)
|
||||||
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||||
|
else()
|
||||||
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT ProgramDatabase)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
|
||||||
|
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc")
|
||||||
# Visual Studio: Maximum Optimization, Multi-threaded DLL
|
# Visual Studio: Maximum Optimization, Multi-threaded DLL
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
||||||
# Visual Studio: No Optimization, Multi-threaded Debug DLL
|
# Visual Studio: No Optimization, Multi-threaded Debug DLL
|
||||||
|
|
@ -211,6 +235,12 @@ else()
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Always included, because they define cockatrice_disable_sanitizers_for() and
|
||||||
|
# cockatrice_disable_coverage_for() for the vendored trees. They only touch the global flags
|
||||||
|
# when ENABLE_SANITIZERS or ENABLE_COVERAGE is on.
|
||||||
|
include(Sanitizers)
|
||||||
|
include(Coverage)
|
||||||
|
|
||||||
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
|
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
add_definitions("-DSFMT_MEXP=19937")
|
add_definitions("-DSFMT_MEXP=19937")
|
||||||
|
|
@ -326,38 +356,54 @@ elseif(WIN32)
|
||||||
# Configure file with custom definitions for NSIS.
|
# Configure file with custom definitions for NSIS.
|
||||||
configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh")
|
configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh")
|
||||||
|
|
||||||
# Every Qt module the client links against, as the DLL names a Windows install
|
# Every runtime DLL a Windows install has to contain, as paths relative to the
|
||||||
# has to contain, plus the platform plugin without which the client cannot
|
# install root. .ci/compile.sh reads this and fails the build when the packaged
|
||||||
# start. .ci/compile.sh reads this and fails the build when the packaged
|
# installer is missing one of them, or carries a runtime it does not know about.
|
||||||
# installer is missing one of them.
|
|
||||||
#
|
#
|
||||||
# Only the client is packaged on Windows, so this is the client's module list
|
# All three applications are packaged into the same directory on Windows, so
|
||||||
# rather than the union across server, client and Oracle: demanding Oracle's or
|
# this is the union of their Qt module lists, not just the client's: Servatrice
|
||||||
# Servatrice's modules of the client installer checks nothing about the client.
|
# contributes Qt6Sql.dll and Oracle contributes nothing the client lacks, and a
|
||||||
|
# client-only manifest leaves Qt6Sql.dll unasserted even though servatrice.exe
|
||||||
|
# is installed next to cockatrice.exe and cannot start without it.
|
||||||
#
|
#
|
||||||
# A statically linked Qt module ships no runtime DLL, so requiring one would
|
# A statically linked Qt module ships no runtime DLL, so requiring one would
|
||||||
# fail the package check on a static build for no reason. cockatrice/CMakeLists.txt
|
# fail the package check on a static build for no reason. cockatrice/CMakeLists.txt
|
||||||
# installs the runtime of every module listed here, and skips static ones the
|
# installs the runtime of every module listed here, and skips static ones the
|
||||||
# same way, so the two can never disagree.
|
# same way, so the two can never disagree.
|
||||||
#
|
#
|
||||||
# A DLL missing from the package only surfaces on a user's machine, after an
|
# Only the Qt modules, and that is deliberate. protobuf, Abseil, liblzma, zlib
|
||||||
# update has already replaced their install, as "The code execution cannot
|
# and OpenSSL also ride in on the "*.dll" glob, and a client whose runtime is
|
||||||
# proceed because Qt6Multimedia.dll was not found" or as a missing procedure
|
# absent, stale or of the wrong architecture fails to start with "abseil_dll.dll
|
||||||
# entry point in a Qt6QuickWidgets.dll left over from the previous version.
|
# is either not designed to run on Windows or it contains an error", so they
|
||||||
# Assert it while the installer is still being built instead.
|
# are exactly the files worth asserting.
|
||||||
set(_required_qt_runtime "")
|
#
|
||||||
foreach(_qt_module IN LISTS COCKATRICE_QT_MODULES)
|
# Their names cannot be derived from the vcpkg bin directory, which is what a
|
||||||
|
# first attempt did and what a Windows build immediately refuted: bin holds
|
||||||
|
# everything vcpkg installed, not everything the applications import. It also
|
||||||
|
# contains gmock.dll, libprotobuf-lite.dll, libprotoc.dll, legacy.dll and three
|
||||||
|
# pthreadVC*.dll FindThreads probes, none of which any shipped executable
|
||||||
|
# links, so requiring them failed a build over a package that was correct.
|
||||||
|
#
|
||||||
|
# Deriving them from the executables' own import tables is the real answer,
|
||||||
|
# and fixup_bundle already walks it to decide what to copy. Until that result
|
||||||
|
# is available to CMake, requiring the vcpkg half would mean guessing names
|
||||||
|
# again, which is what produced this bug report in the first place. So assert
|
||||||
|
# what is derived from the build's own link lists and leave the rest to the
|
||||||
|
# purge in cmake/NSIS.template.in, which removes every DLL regardless of name.
|
||||||
|
set(_required_runtime "")
|
||||||
|
foreach(_qt_module IN LISTS COCKATRICE_QT_MODULES SERVATRICE_QT_MODULES ORACLE_QT_MODULES)
|
||||||
get_target_property(_qt_module_type ${_qt_module} TYPE)
|
get_target_property(_qt_module_type ${_qt_module} TYPE)
|
||||||
if(_qt_module_type STREQUAL "SHARED_LIBRARY")
|
if(_qt_module_type STREQUAL "SHARED_LIBRARY")
|
||||||
string(REGEX REPLACE "^Qt6::" "" _qt_component "${_qt_module}")
|
string(REGEX REPLACE "^Qt6::" "" _qt_component "${_qt_module}")
|
||||||
list(APPEND _required_qt_runtime "Qt6${_qt_component}.dll")
|
list(APPEND _required_runtime "Qt6${_qt_component}.dll")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
list(APPEND _required_qt_runtime "Plugins/platforms/qwindows.dll")
|
list(APPEND _required_runtime "Plugins/platforms/qwindows.dll")
|
||||||
list(REMOVE_DUPLICATES _required_qt_runtime)
|
|
||||||
list(SORT _required_qt_runtime)
|
list(REMOVE_DUPLICATES _required_runtime)
|
||||||
string(REPLACE ";" "\n" _required_qt_runtime "${_required_qt_runtime}")
|
list(SORT _required_runtime)
|
||||||
file(WRITE "${PROJECT_BINARY_DIR}/required-qt-runtime.txt" "${_required_qt_runtime}\n")
|
string(REPLACE ";" "\n" _required_runtime "${_required_runtime}")
|
||||||
|
file(WRITE "${PROJECT_BINARY_DIR}/required-runtime.txt" "${_required_runtime}\n")
|
||||||
|
|
||||||
# include vcredist into the package; NSIS will take care of running it
|
# include vcredist into the package; NSIS will take care of running it
|
||||||
if(VCREDISTRUNTIME_FOUND)
|
if(VCREDISTRUNTIME_FOUND)
|
||||||
|
|
|
||||||
18
Doxyfile
18
Doxyfile
|
|
@ -1066,25 +1066,11 @@ INPUT_FILE_ENCODING =
|
||||||
# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||||
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||||
|
|
||||||
FILE_PATTERNS = *.cc \
|
FILE_PATTERNS = *.cpp \
|
||||||
*.cxx \
|
|
||||||
*.cxxm \
|
|
||||||
*.cpp \
|
|
||||||
*.cppm \
|
*.cppm \
|
||||||
*.ccm \
|
|
||||||
*.c++ \
|
|
||||||
*.c++m \
|
|
||||||
*.ii \
|
|
||||||
*.ixx \
|
|
||||||
*.ipp \
|
*.ipp \
|
||||||
*.i++ \
|
|
||||||
*.inl \
|
*.inl \
|
||||||
*.h \
|
*.h \
|
||||||
*.hh \
|
|
||||||
*.hxx \
|
|
||||||
*.hpp \
|
|
||||||
*.h++ \
|
|
||||||
*.markdown \
|
|
||||||
*.md \
|
*.md \
|
||||||
*.dox \
|
*.dox \
|
||||||
*.proto
|
*.proto
|
||||||
|
|
@ -2667,7 +2653,7 @@ DOT_NUM_THREADS = 0
|
||||||
# Minimum value: 1, maximum value: 1000, default value: 50.
|
# Minimum value: 1, maximum value: 1000, default value: 50.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
DOT_BATCH_SIZE = 500
|
DOT_BATCH_SIZE = 50
|
||||||
|
|
||||||
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
|
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
|
||||||
# subgraphs. When you want a differently looking font in the dot files that
|
# subgraphs. When you want a differently looking font in the dot files that
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ There are various places where useful information for different needs are mainta
|
||||||
- [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) `Community supported`
|
- [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) `Community supported`
|
||||||
- [Official Webpage](https://cockatrice.github.io/)
|
- [Official Webpage](https://cockatrice.github.io/)
|
||||||
- [Official README](https://github.com/Cockatrice/Cockatrice/blob/master/README.md) `This file`
|
- [Official README](https://github.com/Cockatrice/Cockatrice/blob/master/README.md) `This file`
|
||||||
|
- [Official CONTRIBUTING](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md)
|
||||||
|
|
||||||
Cockatrice tries to use the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
Cockatrice tries to use the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
||||||
|
|
||||||
|
|
@ -159,6 +160,12 @@ The following flags (with their non-default values) can be passed to `cmake`:
|
||||||
| `-DUPDATE_TRANSLATIONS=1` | Configure `make` to update the translation .ts files for new strings in the source code<br> **Note:** `make clean` will remove the .ts files |
|
| `-DUPDATE_TRANSLATIONS=1` | Configure `make` to update the translation .ts files for new strings in the source code<br> **Note:** `make clean` will remove the .ts files |
|
||||||
| `-DTEST=1` | Enable regression tests<br> **Note:** `make test` to run tests, *googletest* will be downloaded if not available |
|
| `-DTEST=1` | Enable regression tests<br> **Note:** `make test` to run tests, *googletest* will be downloaded if not available |
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Build code documentation ([Doxygen](https://www.doxygen.nl)) according to our [configuration](https://github.com/Cockatrice/Cockatrice/blob/master/Doxyfile) into `/docs`:
|
||||||
|
> ```bash
|
||||||
|
> doxygen Doxyfile
|
||||||
|
> ```
|
||||||
|
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
|
|
||||||
|
|
|
||||||
75
cmake/Coverage.cmake
Normal file
75
cmake/Coverage.cmake
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Line-coverage instrumentation opt-in, plus per-source opt-out
|
||||||
|
# Input: ENABLE_COVERAGE
|
||||||
|
# Defines: cockatrice_disable_coverage_for
|
||||||
|
#
|
||||||
|
# Included once from the root CMakeLists.txt, immediately after the per-compiler flag
|
||||||
|
# block, so add_compile_options() reaches every library and executable defined below.
|
||||||
|
#
|
||||||
|
# Note the name deliberately shadows CMake's own built-in Modules/Coverage.cmake. It resolves
|
||||||
|
# to this file only because the root CMakeLists.txt puts cmake/ at the front of
|
||||||
|
# CMAKE_MODULE_PATH; if that ever moves, include(Coverage) would silently pick up the built-in
|
||||||
|
# module, which only defines a `COVERAGE` custom target and touches no global flags, so
|
||||||
|
# instrumentation would quietly stop happening rather than erroring.
|
||||||
|
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
# Opt a set of vendored sources out of instrumentation.
|
||||||
|
#
|
||||||
|
# cockatrice_disable_coverage_for(<source> ...)
|
||||||
|
#
|
||||||
|
# Third-party code drags the total down with lines no test can ever reach, and a total that
|
||||||
|
# cannot move is not a useful signal. This is the same carve-out the sanitizer build uses.
|
||||||
|
#
|
||||||
|
# The sources must be named relative to the directory that compiles them. CMake resolves a
|
||||||
|
# source-file property against the directory scope the target was declared in, so calling
|
||||||
|
# this from the root with absolute paths silently does nothing. That is why the call sites
|
||||||
|
# live next to the add_library/add_executable that pull the vendored code in.
|
||||||
|
#
|
||||||
|
# SKIP_PRECOMPILE_HEADERS mirrors the sanitizer helper. The precompiled header carries the
|
||||||
|
# instrumentation flags, and mixing an instrumented PCH with an uninstrumented translation
|
||||||
|
# unit makes GCC reject it.
|
||||||
|
function(cockatrice_disable_coverage_for)
|
||||||
|
if(NOT ENABLE_COVERAGE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
# There is no -fno-coverage: --coverage is shorthand for -fprofile-arcs -ftest-coverage, so both
|
||||||
|
# halves have to be negated. CC rejects "-fno-coverage" outright, which is how the vendored C
|
||||||
|
# files below hit it first.
|
||||||
|
set_source_files_properties(
|
||||||
|
${ARGN} PROPERTIES COMPILE_OPTIONS "-fno-profile-arcs;-fno-test-coverage" SKIP_PRECOMPILE_HEADERS ON
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
if(ENABLE_COVERAGE)
|
||||||
|
# Line coverage needs the compiler's own toolchain, so only GCC is supported. Clang's
|
||||||
|
# equivalent is llvm-cov, which reads a different intermediate format and would need a
|
||||||
|
# separate report path; rejecting it is better than emitting .gcno files that gcovr cannot
|
||||||
|
# read.
|
||||||
|
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
message(FATAL_ERROR "ENABLE_COVERAGE requires GCC, but the compiler is ${CMAKE_CXX_COMPILER_ID}. "
|
||||||
|
"Clang coverage needs llvm-cov and is not wired up."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Probe the way the flag will actually be used: compile AND link. A .gcno file comes from the
|
||||||
|
# compile step, but the runtime that writes .gcda files comes from the link step, so probing
|
||||||
|
# only the compile step would pass on a toolchain that cannot actually produce coverage.
|
||||||
|
set(_cockatrice_saved_required_flags "${CMAKE_REQUIRED_FLAGS}")
|
||||||
|
set(_cockatrice_saved_required_link_options "${CMAKE_REQUIRED_LINK_OPTIONS}")
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-O0 -g")
|
||||||
|
set(CMAKE_REQUIRED_LINK_OPTIONS -fprofile-arcs -ftest-coverage)
|
||||||
|
check_cxx_source_compiles("int main() { return 0; }" COCKATRICE_HAVE_COVERAGE_FLAGS)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${_cockatrice_saved_required_flags}")
|
||||||
|
set(CMAKE_REQUIRED_LINK_OPTIONS "${_cockatrice_saved_required_link_options}")
|
||||||
|
|
||||||
|
if(NOT COCKATRICE_HAVE_COVERAGE_FLAGS)
|
||||||
|
message(FATAL_ERROR "ENABLE_COVERAGE is on, but this toolchain rejected the coverage flags.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# -O0 keeps the line mapping honest: at higher optimisation levels the compiler merges and
|
||||||
|
# relocates lines, and the report describes code that no longer exists in that form.
|
||||||
|
add_compile_options(--coverage -O0 -g)
|
||||||
|
add_link_options(--coverage)
|
||||||
|
|
||||||
|
message(STATUS "Coverage instrumentation enabled (--coverage). Report with gcovr over the build dir.")
|
||||||
|
endif()
|
||||||
|
|
@ -7,6 +7,12 @@
|
||||||
# Output: ORACLE_QT_MODULES
|
# Output: ORACLE_QT_MODULES
|
||||||
# Output: TEST_QT_MODULES
|
# Output: TEST_QT_MODULES
|
||||||
|
|
||||||
|
# Every Qt module an application links against, as the DLL names a Windows
|
||||||
|
# install has to contain. Core is listed explicitly rather than left to arrive
|
||||||
|
# transitively: it is the one module nothing can do without, and required-runtime.txt
|
||||||
|
# is built from these lists, so a module missing here is a runtime the package
|
||||||
|
# check never asserts. That is how Qt6Core.dll went unasserted while every other
|
||||||
|
# Qt module was checked.
|
||||||
set(REQUIRED_QT_COMPONENTS Core)
|
set(REQUIRED_QT_COMPONENTS Core)
|
||||||
if(WITH_SERVER)
|
if(WITH_SERVER)
|
||||||
set(_SERVATRICE_NEEDED Network Sql WebSockets)
|
set(_SERVATRICE_NEEDED Network Sql WebSockets)
|
||||||
|
|
@ -14,6 +20,7 @@ endif()
|
||||||
if(WITH_CLIENT)
|
if(WITH_CLIENT)
|
||||||
set(_COCKATRICE_NEEDED
|
set(_COCKATRICE_NEEDED
|
||||||
Concurrent
|
Concurrent
|
||||||
|
Core
|
||||||
Gui
|
Gui
|
||||||
Multimedia
|
Multimedia
|
||||||
Network
|
Network
|
||||||
|
|
@ -33,7 +40,9 @@ endif()
|
||||||
if(TEST)
|
if(TEST)
|
||||||
# Union of Qt modules required across all test targets (independent of application targets).
|
# Union of Qt modules required across all test targets (independent of application targets).
|
||||||
# When adding a new test that needs additional Qt modules, add them here rather than in the test's CMakeLists.txt.
|
# When adding a new test that needs additional Qt modules, add them here rather than in the test's CMakeLists.txt.
|
||||||
set(_TEST_NEEDED Concurrent Network Svg Widgets)
|
# Test is QtTest: it brings QAbstractItemModelTester and QSignalSpy, which are how the Qt model
|
||||||
|
# and signal contracts get verified without standing up a GUI.
|
||||||
|
set(_TEST_NEEDED Concurrent Network Svg Widgets Test)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED}
|
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,13 @@ Var IsUpgrade
|
||||||
Var AbortReason
|
Var AbortReason
|
||||||
Var WaitPid
|
Var WaitPid
|
||||||
Var LauncherExited
|
Var LauncherExited
|
||||||
|
Var InstallLogPath
|
||||||
|
Var LogHandle
|
||||||
|
Var LogMessage
|
||||||
|
Var LogFindHandle
|
||||||
|
Var LogFindName
|
||||||
|
Var LogMatchLabel
|
||||||
|
Var LogMatchPattern
|
||||||
|
|
||||||
!include LogicLib.nsh
|
!include LogicLib.nsh
|
||||||
!include FileFunc.nsh
|
!include FileFunc.nsh
|
||||||
|
|
@ -64,8 +71,67 @@ Page Custom PortableModePageCreate PortableModePageLeave
|
||||||
|
|
||||||
!insertmacro MUI_LANGUAGE English
|
!insertmacro MUI_LANGUAGE English
|
||||||
|
|
||||||
|
; Installer log
|
||||||
|
; Every run appends a step-by-step trace to a file so a failed upgrade on a
|
||||||
|
; user's machine can be diagnosed after the fact. Kept in $TEMP rather than in
|
||||||
|
; $INSTDIR because the previous version's uninstaller removes the whole install
|
||||||
|
; directory part-way through an upgrade. Read it back with:
|
||||||
|
; notepad %TEMP%\Cockatrice-installer.log
|
||||||
|
!macro CockLog text
|
||||||
|
Push "${text}"
|
||||||
|
Call CockLogWrite
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function CockLogWrite
|
||||||
|
Pop $LogMessage
|
||||||
|
FileOpen $LogHandle "$InstallLogPath" a
|
||||||
|
${If} $LogHandle == ""
|
||||||
|
Return
|
||||||
|
${EndIf}
|
||||||
|
; FileOpen places the pointer at the start of the file in every mode, so
|
||||||
|
; 'a' alone would overwrite the log from the beginning on each line. Seek
|
||||||
|
; past the existing content first to actually append.
|
||||||
|
FileSeek $LogHandle 0 END
|
||||||
|
FileWrite $LogHandle "$LogMessage$\r$\n"
|
||||||
|
FileClose $LogHandle
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
; Logs every file matching $INSTDIR\<mask>. Used to record the DLL inventory
|
||||||
|
; before and after the upgrade purge, which is what shows whether Qt6Gui.dll was
|
||||||
|
; on disk and what (if anything) survived the deletes.
|
||||||
|
!macro CockLogListing label mask
|
||||||
|
Push "${label}"
|
||||||
|
Push "$INSTDIR\${mask}"
|
||||||
|
Call CockLogListing
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function CockLogListing
|
||||||
|
Pop $LogMatchPattern
|
||||||
|
Pop $LogMatchLabel
|
||||||
|
!insertmacro CockLog "listing [$LogMatchLabel] pattern=$LogMatchPattern"
|
||||||
|
FindFirst $LogFindHandle $LogFindName "$LogMatchPattern"
|
||||||
|
${If} $LogFindHandle == ""
|
||||||
|
!insertmacro CockLog "listing [$LogMatchLabel] (no matches)"
|
||||||
|
Return
|
||||||
|
${EndIf}
|
||||||
|
log_listing_loop:
|
||||||
|
!insertmacro CockLog "listing [$LogMatchLabel] $LogFindName"
|
||||||
|
ClearErrors
|
||||||
|
FindNext $LogFindHandle $LogFindName
|
||||||
|
IfErrors 0 log_listing_loop
|
||||||
|
FindClose $LogFindHandle
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
Function .onInit
|
Function .onInit
|
||||||
|
|
||||||
|
StrCpy $InstallLogPath "$TEMP\Cockatrice-installer.log"
|
||||||
|
; Start each run from a clean file so the log that gets sent back is the last
|
||||||
|
; run, not every past run glued together.
|
||||||
|
FileOpen $LogHandle "$InstallLogPath" w
|
||||||
|
FileClose $LogHandle
|
||||||
|
!insertmacro CockLog "=================================================================="
|
||||||
|
!insertmacro CockLog "installer start: @CPACK_PACKAGE_NAME@ @CPACK_PACKAGE_VERSION@"
|
||||||
|
|
||||||
${If} ${NSIS_IS_64_BIT} == 1 #NSIS 64bit
|
${If} ${NSIS_IS_64_BIT} == 1 #NSIS 64bit
|
||||||
${IfNot} ${RunningX64}
|
${IfNot} ${RunningX64}
|
||||||
MessageBox MB_OK|MB_ICONSTOP "This version of Cockatrice requires a 64-bit Windows system."
|
MessageBox MB_OK|MB_ICONSTOP "This version of Cockatrice requires a 64-bit Windows system."
|
||||||
|
|
@ -158,6 +224,13 @@ ${EndIf}
|
||||||
; Now that $PortableMode reflects reality, commit InstDir into the correct slot
|
; Now that $PortableMode reflects reality, commit InstDir into the correct slot
|
||||||
Call SetModeDestinationFromInstdir
|
Call SetModeDestinationFromInstdir
|
||||||
|
|
||||||
|
!insertmacro CockLog "options: InstDir=$InstDir PortableMode=$PortableMode ReinstallMode=$ReinstallMode WaitPid=$WaitPid"
|
||||||
|
${If} ${Silent}
|
||||||
|
!insertmacro CockLog "options: running silently"
|
||||||
|
${Else}
|
||||||
|
!insertmacro CockLog "options: interactive"
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
; Wait for the process that launched this installer to exit before anything is
|
; Wait for the process that launched this installer to exit before anything is
|
||||||
; replaced or deleted. It goes first because it is the one check here that needs
|
; replaced or deleted. It goes first because it is the one check here that needs
|
||||||
; no powershell.exe: on a machine where the process lookup cannot run at all, the
|
; no powershell.exe: on a machine where the process lookup cannot run at all, the
|
||||||
|
|
@ -175,12 +248,14 @@ Call SetModeDestinationFromInstdir
|
||||||
; interactive installs the section re-checks after the directory page, when
|
; interactive installs the section re-checks after the directory page, when
|
||||||
; $INSTDIR is the directory the user actually picked.
|
; $INSTDIR is the directory the user actually picked.
|
||||||
${If} $ReinstallMode = 1
|
${If} $ReinstallMode = 1
|
||||||
|
!insertmacro CockLog "reinstall: waiting for launcher and other instances"
|
||||||
Call WaitForLauncherToExit
|
Call WaitForLauncherToExit
|
||||||
Call EnsureAppsNotRunning
|
Call EnsureAppsNotRunning
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} $ReinstallMode = 1
|
${If} $ReinstallMode = 1
|
||||||
${AndIf} $PortableMode = 0
|
${AndIf} $PortableMode = 0
|
||||||
|
!insertmacro CockLog "reinstall: auto-uninstalling previous version"
|
||||||
Call AutoUninstallIfNeeded
|
Call AutoUninstallIfNeeded
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
|
|
@ -226,13 +301,23 @@ Function AutoUninstallIfNeeded
|
||||||
|
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
|
|
||||||
|
; _?=$INSTDIR keeps the old uninstaller running in place. An NSIS uninstaller
|
||||||
|
; normally copies itself to %TEMP% and runs from there so that it can delete its
|
||||||
|
; own directory, and the process we started exits at once. ExecWait then returns
|
||||||
|
; before the uninstall has run, and the temp copy keeps deleting files - from
|
||||||
|
; 3.1.0 and 3.1.1 on disk a blanket "RMDir /r $INSTDIR" - while the section
|
||||||
|
; below is still writing the new payload. _?= disables the copy and makes
|
||||||
|
; ExecWait block until the uninstall finishes. It must be the last argument
|
||||||
|
; and must not be quoted, even when the path contains spaces.
|
||||||
|
;
|
||||||
; --- 32-bit uninstall ---
|
; --- 32-bit uninstall ---
|
||||||
SetRegView 32
|
SetRegView 32
|
||||||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
||||||
|
|
||||||
|
!insertmacro CockLog "uninstall (32-bit): '$R0 _?=$INSTDIR'"
|
||||||
StrCmp $R0 "" done32
|
StrCmp $R0 "" done32
|
||||||
DetailPrint "Removing previous version (32-bit)..."
|
DetailPrint "Removing previous version (32-bit)..."
|
||||||
ExecWait '$R0'
|
ExecWait '$R0 _?=$INSTDIR'
|
||||||
|
|
||||||
done32:
|
done32:
|
||||||
|
|
||||||
|
|
@ -241,9 +326,10 @@ ${If} ${RunningX64}
|
||||||
SetRegView 64
|
SetRegView 64
|
||||||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
||||||
|
|
||||||
|
!insertmacro CockLog "uninstall (64-bit): '$R0 _?=$INSTDIR'"
|
||||||
StrCmp $R0 "" done64
|
StrCmp $R0 "" done64
|
||||||
DetailPrint "Removing previous version (64-bit)..."
|
DetailPrint "Removing previous version (64-bit)..."
|
||||||
ExecWait '$R0'
|
ExecWait '$R0 _?=$INSTDIR'
|
||||||
|
|
||||||
done64:
|
done64:
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
@ -360,6 +446,7 @@ Function WaitForAppToClose
|
||||||
; usage: set $R1 to the display name (e.g. "cockatrice.exe") and $R2 to the
|
; usage: set $R1 to the display name (e.g. "cockatrice.exe") and $R2 to the
|
||||||
; base image name (e.g. "cockatrice")
|
; base image name (e.g. "cockatrice")
|
||||||
Call IsAppRunning
|
Call IsAppRunning
|
||||||
|
!insertmacro CockLog "guard $R1: state=$R0 (dir=$GuardDir)"
|
||||||
; Only a definite "running" is worth waiting for. "Not running" is done, and
|
; Only a definite "running" is worth waiting for. "Not running" is done, and
|
||||||
; "could not determine" must not keep the installer waiting on an answer it
|
; "could not determine" must not keep the installer waiting on an answer it
|
||||||
; will never get - but it cannot simply be waved through either, see
|
; will never get - but it cannot simply be waved through either, see
|
||||||
|
|
@ -384,6 +471,7 @@ Function WaitForAppToClose
|
||||||
Sleep 500
|
Sleep 500
|
||||||
Call IsAppRunning
|
Call IsAppRunning
|
||||||
${If} $R0 = 0
|
${If} $R0 = 0
|
||||||
|
!insertmacro CockLog "guard $R1: closed gracefully"
|
||||||
DetailPrint "$R1 closed."
|
DetailPrint "$R1 closed."
|
||||||
Return
|
Return
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
@ -402,6 +490,7 @@ Function WaitForAppToClose
|
||||||
; deck, and nothing has been replaced yet, so aborting just defers the
|
; deck, and nothing has been replaced yet, so aborting just defers the
|
||||||
; update and preserves the user's data.
|
; update and preserves the user's data.
|
||||||
${If} $AllowForceClose = 0
|
${If} $AllowForceClose = 0
|
||||||
|
!insertmacro CockLog "guard $R1: still running after 60s, aborting (no force close)"
|
||||||
DetailPrint "$R1 is still running after 60 s; aborting the update so that no data is lost."
|
DetailPrint "$R1 is still running after 60 s; aborting the update so that no data is lost."
|
||||||
StrCpy $AbortReason \
|
StrCpy $AbortReason \
|
||||||
"$R1 did not close within 60 seconds, so the installation was aborted to avoid losing unsaved data.$\r$\n$\r$\nPlease close $R1 and run the installer again."
|
"$R1 did not close within 60 seconds, so the installation was aborted to avoid losing unsaved data.$\r$\n$\r$\nPlease close $R1 and run the installer again."
|
||||||
|
|
@ -410,11 +499,13 @@ Function WaitForAppToClose
|
||||||
; Oracle and Servatrice are console applications: CloseMainWindow()
|
; Oracle and Servatrice are console applications: CloseMainWindow()
|
||||||
; returned false for them and waiting longer cannot help. They hold no
|
; returned false for them and waiting longer cannot help. They hold no
|
||||||
; unsaved user data, so stop them by PID.
|
; unsaved user data, so stop them by PID.
|
||||||
|
!insertmacro CockLog "guard $R1: still running after 60s, force-stopping"
|
||||||
DetailPrint "Force-stopping $R1 ..."
|
DetailPrint "Force-stopping $R1 ..."
|
||||||
Call ForceCloseApps
|
Call ForceCloseApps
|
||||||
Sleep 2000
|
Sleep 2000
|
||||||
Call IsAppRunning
|
Call IsAppRunning
|
||||||
${If} $R0 = 0
|
${If} $R0 = 0
|
||||||
|
!insertmacro CockLog "guard $R1: force-stopped"
|
||||||
DetailPrint "$R1 closed."
|
DetailPrint "$R1 closed."
|
||||||
Return
|
Return
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
@ -422,6 +513,7 @@ Function WaitForAppToClose
|
||||||
Call HandleUnknownAppState
|
Call HandleUnknownAppState
|
||||||
Return
|
Return
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
!insertmacro CockLog "guard $R1: could not be stopped, aborting"
|
||||||
DetailPrint "$R1 is still running after 60 s; aborting the update."
|
DetailPrint "$R1 is still running after 60 s; aborting the update."
|
||||||
StrCpy $AbortReason \
|
StrCpy $AbortReason \
|
||||||
"$R1 could not be stopped, so the installation was aborted.$\r$\n$\r$\nPlease close $R1 and run the installer again."
|
"$R1 could not be stopped, so the installation was aborted.$\r$\n$\r$\nPlease close $R1 and run the installer again."
|
||||||
|
|
@ -486,8 +578,16 @@ FunctionEnd
|
||||||
; Only the first of those two gets a dialog; the second reports through the log
|
; Only the first of those two gets a dialog; the second reports through the log
|
||||||
; and the exit code.
|
; and the exit code.
|
||||||
Function AbortInstall
|
Function AbortInstall
|
||||||
${IfNot} ${Silent}
|
!insertmacro CockLog "ABORT: $AbortReason"
|
||||||
MessageBox MB_OK|MB_ICONEXCLAMATION "$AbortReason"
|
!insertmacro CockLog "full installer log: $InstallLogPath"
|
||||||
|
; Show a dialog whenever someone is at the keyboard to see it: an interactive
|
||||||
|
; install, or the in-app updater's /R upgrade. The /R upgrade is silent, but
|
||||||
|
; the client that launched the installer has already quit, so the user is
|
||||||
|
; still there. Only a /S install without /R is attended by a package manager
|
||||||
|
; and must go straight to the exit code.
|
||||||
|
${If} $ReinstallMode = 1
|
||||||
|
${OrIfNot} ${Silent}
|
||||||
|
MessageBox MB_OK|MB_ICONEXCLAMATION "$AbortReason$\r$\n$\r$\nA detailed installer log was written to:$\r$\n$InstallLogPath"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
SetErrorLevel 1
|
SetErrorLevel 1
|
||||||
Abort
|
Abort
|
||||||
|
|
@ -510,17 +610,33 @@ FunctionEnd
|
||||||
; falls back to the name based guard.
|
; falls back to the name based guard.
|
||||||
Function WaitForLauncherToExit
|
Function WaitForLauncherToExit
|
||||||
StrCpy $LauncherExited 0
|
StrCpy $LauncherExited 0
|
||||||
|
!insertmacro CockLog "wait-launcher: pid='$WaitPid'"
|
||||||
${If} $WaitPid == ""
|
${If} $WaitPid == ""
|
||||||
|
!insertmacro CockLog "wait-launcher: no pid given, falling back to name check"
|
||||||
Return
|
Return
|
||||||
${EndIf}
|
${EndIf}
|
||||||
; PROCESS_SYNCHRONIZE is the only access this needs - enough to wait on the
|
; PROCESS_SYNCHRONIZE is the only access this needs - enough to wait on the
|
||||||
; handle, and the least likely to be refused for a reason that has nothing to
|
; handle, and the least likely to be refused for a reason that has nothing to
|
||||||
; do with the upgrade.
|
; do with the upgrade.
|
||||||
|
;
|
||||||
|
; System.dll maps its output registers so that .rN writes $N and .RN writes
|
||||||
|
; $RN. The caller reads $R0/$R1, so the uppercase .RN form is required; the
|
||||||
|
; original .r0/.r1 wrote $0/$1 and left $R1 empty, which made the "did not
|
||||||
|
; exit" test below compare "" against "0" and abort on every /PID= upgrade.
|
||||||
ClearErrors
|
ClearErrors
|
||||||
System::Call 'kernel32::OpenProcess(i 0x00100000, i 0, i $WaitPid) p.r0'
|
System::Call 'kernel32::OpenProcess(i 0x00100000, i 0, i $WaitPid) p.R0'
|
||||||
|
; OpenProcess returns a null handle for a process that is already gone. The
|
||||||
|
; System plugin does not raise the NSIS error flag from a called function's
|
||||||
|
; return value, so ${Errors} alone never saw that case and the null handle was
|
||||||
|
; passed straight to WaitForSingleObject. Fold a plugin failure into the same
|
||||||
|
; null-handle case instead of reading a handle that was never written.
|
||||||
${If} ${Errors}
|
${If} ${Errors}
|
||||||
|
StrCpy $R0 0
|
||||||
|
${EndIf}
|
||||||
|
${If} $R0 == 0
|
||||||
; The launcher is gone - OpenProcess cannot open a dead process - which is
|
; The launcher is gone - OpenProcess cannot open a dead process - which is
|
||||||
; exactly the state the wait was for.
|
; exactly the state the wait was for.
|
||||||
|
!insertmacro CockLog "wait-launcher: already exited"
|
||||||
DetailPrint "The application that started this installer has already exited."
|
DetailPrint "The application that started this installer has already exited."
|
||||||
StrCpy $LauncherExited 1
|
StrCpy $LauncherExited 1
|
||||||
Return
|
Return
|
||||||
|
|
@ -529,14 +645,16 @@ Function WaitForLauncherToExit
|
||||||
; Same 60 s grace period the name based check uses, so a client that is slow
|
; Same 60 s grace period the name based check uses, so a client that is slow
|
||||||
; to flush its card database does not get less room than it used to.
|
; to flush its card database does not get less room than it used to.
|
||||||
; WAIT_OBJECT_0 is 0; WAIT_TIMEOUT is 258 and a failed wait reports 0xFFFFFFFF.
|
; WAIT_OBJECT_0 is 0; WAIT_TIMEOUT is 258 and a failed wait reports 0xFFFFFFFF.
|
||||||
System::Call 'kernel32::WaitForSingleObject(p r0, i 60000) i.r1'
|
System::Call 'kernel32::WaitForSingleObject(p R0, i 60000) i.R1'
|
||||||
System::Call 'kernel32::CloseHandle(p r0)'
|
System::Call 'kernel32::CloseHandle(p R0)'
|
||||||
${If} $R1 != 0
|
${If} $R1 != 0
|
||||||
|
!insertmacro CockLog "wait-launcher: did not exit within 60s (wait=$R1)"
|
||||||
DetailPrint "The application that started this installer did not exit within 60 s."
|
DetailPrint "The application that started this installer did not exit within 60 s."
|
||||||
StrCpy $AbortReason \
|
StrCpy $AbortReason \
|
||||||
"The application that started this update has not exited yet, so the installation was cancelled rather than replace files it is still using.$\r$\n$\r$\nPlease close Cockatrice and run the installer again."
|
"The application that started this update has not exited yet, so the installation was cancelled rather than replace files it is still using.$\r$\n$\r$\nPlease close Cockatrice and run the installer again."
|
||||||
Call AbortInstall
|
Call AbortInstall
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
!insertmacro CockLog "wait-launcher: launcher exited"
|
||||||
DetailPrint "The application that started this installer has exited."
|
DetailPrint "The application that started this installer has exited."
|
||||||
StrCpy $LauncherExited 1
|
StrCpy $LauncherExited 1
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
@ -562,9 +680,11 @@ FunctionEnd
|
||||||
Function GuardAppsNotRunning
|
Function GuardAppsNotRunning
|
||||||
; usage: set $GuardDir to the directory to guard, then call this
|
; usage: set $GuardDir to the directory to guard, then call this
|
||||||
Call IsProcessLookupAvailable
|
Call IsProcessLookupAvailable
|
||||||
|
!insertmacro CockLog "guard: powershell available=$R0 dir=$GuardDir launcherExited=$LauncherExited"
|
||||||
${If} $R0 = 0
|
${If} $R0 = 0
|
||||||
; Without PowerShell we cannot tell whether a running instance is
|
; Without PowerShell we cannot tell whether a running instance is
|
||||||
; holding locks on the files we are about to replace.
|
; holding locks on the files we are about to replace.
|
||||||
|
!insertmacro CockLog "guard: powershell unavailable, skipping instance check"
|
||||||
DetailPrint "Could not start powershell.exe; skipping the running instance check. Close Cockatrice, Oracle and Servatrice manually if the installation reports a problem."
|
DetailPrint "Could not start powershell.exe; skipping the running instance check. Close Cockatrice, Oracle and Servatrice manually if the installation reports a problem."
|
||||||
; On a silent upgrade that used to be a warning and nothing more, which
|
; On a silent upgrade that used to be a warning and nothing more, which
|
||||||
; left the very process that launched the installer free to go on
|
; left the very process that launched the installer free to go on
|
||||||
|
|
@ -587,7 +707,8 @@ Function GuardAppsNotRunning
|
||||||
${EndIf}
|
${EndIf}
|
||||||
; The user has to be told to close the applications by hand, but a /S
|
; The user has to be told to close the applications by hand, but a /S
|
||||||
; install without /R is unattended and would block on this forever.
|
; install without /R is unattended and would block on this forever.
|
||||||
${IfNot} ${Silent}
|
${If} $ReinstallMode = 1
|
||||||
|
${OrIfNot} ${Silent}
|
||||||
MessageBox MB_OK|MB_ICONEXCLAMATION "This installer could not check whether Cockatrice is still running, because powershell.exe could not be started.$\r$\n$\r$\nPlease close Cockatrice, Oracle and Servatrice manually before continuing."
|
MessageBox MB_OK|MB_ICONEXCLAMATION "This installer could not check whether Cockatrice is still running, because powershell.exe could not be started.$\r$\n$\r$\nPlease close Cockatrice, Oracle and Servatrice manually before continuing."
|
||||||
${EndIf}
|
${EndIf}
|
||||||
Return
|
Return
|
||||||
|
|
@ -633,7 +754,11 @@ Function IsExistingCockatriceInstall
|
||||||
; there to prove that it is one. Every Qt module Cockatrice links is part of
|
; there to prove that it is one. Every Qt module Cockatrice links is part of
|
||||||
; the payload, so match them all: probing only Qt6Core.dll would miss a
|
; the payload, so match them all: probing only Qt6Core.dll would miss a
|
||||||
; directory where that one file happened to be deletable and the others
|
; directory where that one file happened to be deletable and the others
|
||||||
; were not.
|
; were not. Qt6*.dll rather than *.dll on purpose: this function decides
|
||||||
|
; whether a directory is ours, and a folder that merely holds some DLLs of
|
||||||
|
; its own must not be purged. Qt6*.dll is enough even when only the protobuf
|
||||||
|
; runtime survived, because the whole Qt set is mapped by the same process
|
||||||
|
; that maps abseil_dll.dll and so is locked or free with it.
|
||||||
StrCpy $R3 "Qt6*.dll"
|
StrCpy $R3 "Qt6*.dll"
|
||||||
Call CheckStaleRuntimeMask
|
Call CheckStaleRuntimeMask
|
||||||
${If} ${FileExists} "$INSTDIR\qt.conf"
|
${If} ${FileExists} "$INSTDIR\qt.conf"
|
||||||
|
|
@ -645,36 +770,23 @@ FunctionEnd
|
||||||
; the purge. NSIS silently skips whatever it cannot delete, so one surviving file
|
; the purge. NSIS silently skips whatever it cannot delete, so one surviving file
|
||||||
; is enough to prove that something still holds a lock on the install directory.
|
; is enough to prove that something still holds a lock on the install directory.
|
||||||
;
|
;
|
||||||
; The masks below have to cover the purge above one for one. A check that only
|
; Any DLL at all counts, not a list of expected ones. The purge removes every
|
||||||
; probed named files could not see a locked Qt6Multimedia.dll or a Plugins
|
; top-level DLL, so after it has run the only DLL that can still be there is one
|
||||||
; directory the purge was unable to remove, so the exact files that broke the
|
; it failed to delete, whatever its name. A mask per library family (Qt, then
|
||||||
; install were also the ones this check was blind to.
|
; OpenSSL, then zlib) is what let abseil_dll.dll through: it is in neither the
|
||||||
|
; purge nor this check, so it survived a 3.0.2 to 3.1 update untouched, the new
|
||||||
|
; executables were written next to it, and the client then failed to start with
|
||||||
|
; "abseil_dll.dll is either not designed to run on Windows or it contains an
|
||||||
|
; error". Probing *.dll has no list to fall out of date when the next
|
||||||
|
; transitive dependency appears.
|
||||||
Function HasStaleRuntimeFiles
|
Function HasStaleRuntimeFiles
|
||||||
StrCpy $R0 0
|
StrCpy $R0 0
|
||||||
StrCpy $R3 "Qt*.dll"
|
StrCpy $R3 "*.dll"
|
||||||
Call CheckStaleRuntimeMask
|
Call CheckStaleRuntimeMask
|
||||||
StrCpy $R3 "libcrypto*.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
StrCpy $R3 "libssl*.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
StrCpy $R3 "zlib*.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
StrCpy $R3 "icu*.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
StrCpy $R3 "libeay32.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
StrCpy $R3 "ssleay32.dll"
|
|
||||||
Call CheckStaleRuntimeMask
|
|
||||||
${If} $R0 = 1
|
|
||||||
Return
|
|
||||||
${EndIf}
|
|
||||||
${If} ${FileExists} "$INSTDIR\libmysql.dll"
|
|
||||||
StrCpy $R0 1
|
|
||||||
Return
|
|
||||||
${EndIf}
|
|
||||||
; IfFileExists takes wildcards, so a Plugins directory the purge could not
|
; IfFileExists takes wildcards, so a Plugins directory the purge could not
|
||||||
; remove counts as a leftover too.
|
; remove counts as a leftover too.
|
||||||
${If} ${FileExists} "$INSTDIR\Plugins\*.*"
|
${If} ${FileExists} "$INSTDIR\Plugins\*.*"
|
||||||
|
!insertmacro CockLog "stale-runtime: Plugins directory survived the purge"
|
||||||
StrCpy $R0 1
|
StrCpy $R0 1
|
||||||
${EndIf}
|
${EndIf}
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
@ -687,6 +799,7 @@ Function CheckStaleRuntimeMask
|
||||||
${EndIf}
|
${EndIf}
|
||||||
FindFirst $StaleFindHandle $StaleFindName "$INSTDIR\$R3"
|
FindFirst $StaleFindHandle $StaleFindName "$INSTDIR\$R3"
|
||||||
${If} $StaleFindHandle != ""
|
${If} $StaleFindHandle != ""
|
||||||
|
!insertmacro CockLog "stale-runtime: '$StaleFindName' matched $R3 in $INSTDIR"
|
||||||
StrCpy $R0 1
|
StrCpy $R0 1
|
||||||
FindClose $StaleFindHandle
|
FindClose $StaleFindHandle
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
@ -925,9 +1038,10 @@ ${If} $PortableMode = 0
|
||||||
; directory before letting it delete anything. The uninstall string is
|
; directory before letting it delete anything. The uninstall string is
|
||||||
; stashed away first, the check works on $R0.
|
; stashed away first, the check works on $R0.
|
||||||
StrCpy $OldUninstallString $R0
|
StrCpy $OldUninstallString $R0
|
||||||
|
!insertmacro CockLog "componentsPagePre: old 32-bit uninstall '$OldUninstallString _?=$INSTDIR'"
|
||||||
Call EnsureOldInstallNotRunning
|
Call EnsureOldInstallNotRunning
|
||||||
ClearErrors
|
ClearErrors
|
||||||
ExecWait "$OldUninstallString"
|
ExecWait "$OldUninstallString _?=$INSTDIR"
|
||||||
|
|
||||||
done32:
|
done32:
|
||||||
|
|
||||||
|
|
@ -947,9 +1061,10 @@ ${If} $PortableMode = 0
|
||||||
|
|
||||||
uninst64:
|
uninst64:
|
||||||
StrCpy $OldUninstallString $R0
|
StrCpy $OldUninstallString $R0
|
||||||
|
!insertmacro CockLog "componentsPagePre: old 64-bit uninstall '$OldUninstallString _?=$INSTDIR'"
|
||||||
Call EnsureOldInstallNotRunning
|
Call EnsureOldInstallNotRunning
|
||||||
ClearErrors
|
ClearErrors
|
||||||
ExecWait "$OldUninstallString"
|
ExecWait "$OldUninstallString _?=$INSTDIR"
|
||||||
|
|
||||||
done64:
|
done64:
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
@ -964,15 +1079,19 @@ Section "Application" SecApplication
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
|
!insertmacro CockLog "section: InstDir=$INSTDIR PortableMode=$PortableMode ReinstallMode=$ReinstallMode"
|
||||||
|
|
||||||
; No application instance may be running while any file below is deleted or
|
; No application instance may be running while any file below is deleted or
|
||||||
; replaced: both upgrade blocks start by removing the old executables and
|
; replaced: both upgrade blocks start by removing the old executables and
|
||||||
; runtime DLLs, and NSIS silently skips whatever is locked, which is how an
|
; runtime DLLs, and NSIS silently skips whatever is locked, which is how an
|
||||||
; install ends up with a mix of old and new Qt DLLs next to the new executable
|
; install ends up with a mix of old and new runtimes next to the new executable.
|
||||||
; ("The procedure entry point X could not be located in the dynamic link
|
; The next start then fails with "The procedure entry point X could not be
|
||||||
; library ...Qt6Network.dll"). So the check has to come before the first
|
; located in the dynamic link library ...Qt6Network.dll" for the Qt ones, or
|
||||||
; Delete/RMDir and not after it - an interactive install into an existing
|
; "abseil_dll.dll is either not designed to run on Windows or it contains an
|
||||||
; portable directory with cockatrice.exe still running would otherwise delete
|
; error" for the protobuf ones. So the check has to come before the first
|
||||||
; the old files under its feet.
|
; Delete/RMDir and not after it: an interactive install into an existing portable
|
||||||
|
; directory with cockatrice.exe still running would otherwise delete the old
|
||||||
|
; files under its feet.
|
||||||
;
|
;
|
||||||
; It is skipped on the /R path: .onInit already ran it before
|
; It is skipped on the /R path: .onInit already ran it before
|
||||||
; AutoUninstallIfNeeded removed the previous installation, so by the time this
|
; AutoUninstallIfNeeded removed the previous installation, so by the time this
|
||||||
|
|
@ -987,32 +1106,39 @@ ${EndIf}
|
||||||
${If} $PortableMode = 1
|
${If} $PortableMode = 1
|
||||||
${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
||||||
; upgrade portable mode
|
; upgrade portable mode
|
||||||
|
!insertmacro CockLog "section: portable upgrade purge"
|
||||||
|
!insertmacro CockLogListing "before-portable-purge" "*.dll"
|
||||||
|
; plugins and translations are payload and are rewritten by the payload
|
||||||
|
; below, so removing them here is safe. sounds and themes are payload
|
||||||
|
; too - the default packs are rewritten below as well - but a portable
|
||||||
|
; user's custom sounds and themes live in exactly those folders, so a
|
||||||
|
; recursive purge here would delete user content along with the defaults.
|
||||||
|
; Stale default files from an older release are overwritten or replaced
|
||||||
|
; by the payload, never by a purge.
|
||||||
RMDir /r "$INSTDIR\plugins"
|
RMDir /r "$INSTDIR\plugins"
|
||||||
RMDir /r "$INSTDIR\sounds"
|
|
||||||
RMDir /r "$INSTDIR\themes"
|
|
||||||
RMDir /r "$INSTDIR\translations"
|
RMDir /r "$INSTDIR\translations"
|
||||||
Delete "$INSTDIR\uninstall.exe"
|
Delete "$INSTDIR\uninstall.exe"
|
||||||
Delete "$INSTDIR\cockatrice.exe"
|
Delete "$INSTDIR\cockatrice.exe"
|
||||||
Delete "$INSTDIR\oracle.exe"
|
Delete "$INSTDIR\oracle.exe"
|
||||||
Delete "$INSTDIR\servatrice.exe"
|
Delete "$INSTDIR\servatrice.exe"
|
||||||
Delete "$INSTDIR\Qt*.dll"
|
; Every top-level DLL, not a list of expected ones. The payload is written
|
||||||
Delete "$INSTDIR\libmysql.dll"
|
; after this block, so a DLL the new build still needs is put straight back;
|
||||||
Delete "$INSTDIR\icu*.dll"
|
; what this has to guarantee is that nothing from the previous build is left
|
||||||
Delete "$INSTDIR\libcrypto*.dll"
|
; to be loaded next to the new executables. Naming the families by hand is
|
||||||
Delete "$INSTDIR\libssl*.dll"
|
; what let abseil_dll.dll through; see HasStaleRuntimeFiles.
|
||||||
Delete "$INSTDIR\libeay32.dll"
|
Delete "$INSTDIR\*.dll"
|
||||||
Delete "$INSTDIR\ssleay32.dll"
|
|
||||||
Delete "$INSTDIR\qt.conf"
|
Delete "$INSTDIR\qt.conf"
|
||||||
Delete "$INSTDIR\qdebug.txt"
|
Delete "$INSTDIR\qdebug.txt"
|
||||||
Delete "$INSTDIR\servatrice.sql"
|
Delete "$INSTDIR\servatrice.sql"
|
||||||
Delete "$INSTDIR\servatrice.ini.example"
|
Delete "$INSTDIR\servatrice.ini.example"
|
||||||
Delete "$INSTDIR\zlib*.dll"
|
|
||||||
RMDir "$INSTDIR"
|
RMDir "$INSTDIR"
|
||||||
|
!insertmacro CockLogListing "after-portable-purge" "*.dll"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; Remove any runtime DLLs left over from older versions, so a mismatched
|
; Remove any runtime DLLs left over from older versions, so a mismatched
|
||||||
; Qt/OpenSSL set cannot survive next to the new executables.
|
; Qt/OpenSSL/protobuf set cannot survive next to the new executables.
|
||||||
Call IsExistingCockatriceInstall
|
Call IsExistingCockatriceInstall
|
||||||
|
!insertmacro CockLog "section: IsExistingCockatriceInstall=$R0"
|
||||||
; Remembered because the stale-runtime check below must only ever fire for a
|
; Remembered because the stale-runtime check below must only ever fire for a
|
||||||
; directory this installer recognised as a Cockatrice install. Scanning for
|
; directory this installer recognised as a Cockatrice install. Scanning for
|
||||||
; leftovers in an unrelated directory (a first-time install into a folder that
|
; leftovers in an unrelated directory (a first-time install into a folder that
|
||||||
|
|
@ -1021,48 +1147,48 @@ Call IsExistingCockatriceInstall
|
||||||
StrCpy $IsUpgrade $R0
|
StrCpy $IsUpgrade $R0
|
||||||
${If} $PortableMode = 0
|
${If} $PortableMode = 0
|
||||||
${AndIf} $R0 = 1
|
${AndIf} $R0 = 1
|
||||||
|
!insertmacro CockLog "section: non-portable upgrade purge"
|
||||||
|
!insertmacro CockLogListing "before-purge" "*.dll"
|
||||||
RMDir /r "$INSTDIR\Plugins"
|
RMDir /r "$INSTDIR\Plugins"
|
||||||
Delete "$INSTDIR\Qt*.dll"
|
Delete "$INSTDIR\*.dll"
|
||||||
Delete "$INSTDIR\libcrypto*.dll"
|
!insertmacro CockLogListing "after-purge" "*.dll"
|
||||||
Delete "$INSTDIR\libssl*.dll"
|
!insertmacro CockLogListing "after-plugins" "Plugins\*.*"
|
||||||
Delete "$INSTDIR\zlib*.dll"
|
|
||||||
Delete "$INSTDIR\libmysql.dll"
|
|
||||||
Delete "$INSTDIR\icu*.dll"
|
|
||||||
Delete "$INSTDIR\libeay32.dll"
|
|
||||||
Delete "$INSTDIR\ssleay32.dll"
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; Whatever was locked during the purge - by an instance that started while the
|
; Whatever was locked during the purge (by an instance that started while the
|
||||||
; installer was running, or because the running instance check could not be
|
; installer was running, or because the running instance check could not be
|
||||||
; performed at all - is still on disk, and the new executables are about to be
|
; performed at all) is still on disk, and the new executables are about to be
|
||||||
; written next to it. That mix is exactly what makes the next start fail with
|
; written next to it. That mix is exactly what makes the next start fail with
|
||||||
; "The procedure entry point X could not be located in the dynamic link library
|
; "The procedure entry point X could not be located in the dynamic link library
|
||||||
; ...Qt6QuickWidgets.dll" or "The code execution cannot proceed because
|
; ...Qt6QuickWidgets.dll", "The code execution cannot proceed because
|
||||||
; Qt6Multimedia.dll was not found", so stop here instead of compounding it.
|
; Qt6Multimedia.dll was not found", or "abseil_dll.dll is either not designed to
|
||||||
; Nothing of the new payload has been written at this point, so the next run -
|
; run on Windows or it contains an error", so stop here instead of compounding
|
||||||
; with the applications closed - gets a clean install.
|
; it. Nothing of the new payload has been written at this point, so the next run,
|
||||||
|
; with the applications closed, gets a clean install.
|
||||||
${If} $IsUpgrade = 1
|
${If} $IsUpgrade = 1
|
||||||
Call HasStaleRuntimeFiles
|
Call HasStaleRuntimeFiles
|
||||||
|
!insertmacro CockLog "section: HasStaleRuntimeFiles=$R0"
|
||||||
${Else}
|
${Else}
|
||||||
StrCpy $R0 0
|
StrCpy $R0 0
|
||||||
${EndIf}
|
${EndIf}
|
||||||
${If} $R0 = 1
|
${If} $R0 = 1
|
||||||
|
!insertmacro CockLog "section: aborting, files of a previous version survived the purge"
|
||||||
DetailPrint "Files of a previous version could not be removed; aborting the installation."
|
DetailPrint "Files of a previous version could not be removed; aborting the installation."
|
||||||
; The in-app updater runs this installer silent and detached and never looks
|
; The in-app updater runs this installer silent and detached and never looks
|
||||||
; at its exit code, so the user has to be told what happened. A /S install
|
; at its exit code, so the user has to be told what happened. A /S install
|
||||||
; without /R is unattended - a package manager, for instance - and a message
|
; without /R is unattended (a package manager, for instance) and a message
|
||||||
; box there would block forever, so that case only reports through the log
|
; box there would block forever, so that case only reports through the log
|
||||||
; and the exit code.
|
; and the exit code. AbortInstall owns that decision.
|
||||||
${IfNot} ${Silent}
|
StrCpy $AbortReason \
|
||||||
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
"The installation could not remove all files of a previous version of Cockatrice, most likely because it is still running or was started as administrator, and was cancelled rather than leave a mismatched install behind.$\r$\n$\r$\nPlease close Cockatrice, Oracle and Servatrice and run the installer again."
|
||||||
"The installation could not remove all files of a previous version of Cockatrice, most likely because it is still running or was started as administrator, and was cancelled rather than leave a mismatched install behind.$\r$\n$\r$\nPlease close Cockatrice, Oracle and Servatrice and run the installer again."
|
Call AbortInstall
|
||||||
${EndIf}
|
|
||||||
SetErrorLevel 1
|
|
||||||
Abort
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
@CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
|
@CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
|
||||||
|
!insertmacro CockLog "section: writing payload to $INSTDIR"
|
||||||
@CPACK_NSIS_FULL_INSTALL@
|
@CPACK_NSIS_FULL_INSTALL@
|
||||||
|
!insertmacro CockLog "section: payload written"
|
||||||
|
!insertmacro CockLogListing "final" "Qt6*.dll"
|
||||||
|
|
||||||
${If} $PortableMode = 0
|
${If} $PortableMode = 0
|
||||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||||
|
|
@ -1126,6 +1252,7 @@ ${If} $ReinstallMode = 1
|
||||||
Exec '"$INSTDIR\cockatrice.exe"'
|
Exec '"$INSTDIR\cockatrice.exe"'
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
|
!insertmacro CockLog "section: application install complete"
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
Section "Start menu item" SecStartMenu
|
Section "Start menu item" SecStartMenu
|
||||||
|
|
@ -1142,16 +1269,32 @@ Section "un.Application" UnSecApplication
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
StrCpy $R1 0
|
StrCpy $R1 0
|
||||||
|
|
||||||
; Record whether this was a portable install before the directory (and the
|
; Record whether this was a portable install before portable.dat is
|
||||||
; portable.dat marker inside it) is removed below.
|
; removed below.
|
||||||
IfFileExists "$INSTDIR\portable.dat" 0 +2
|
IfFileExists "$INSTDIR\portable.dat" 0 +2
|
||||||
StrCpy $R1 1
|
StrCpy $R1 1
|
||||||
|
|
||||||
; Remove the entire application directory so any file that is not part of
|
; Remove only what the installer wrote. The two lists below are generated
|
||||||
; the installed payload (e.g. build-tree artifacts such as *.dir folders,
|
; by CPack from the staged install tree: one Delete per installed file and
|
||||||
; *_autogen and *.tlog files from a build) cannot survive between an
|
; one non-recursive RMDir per installed directory, children first.
|
||||||
; uninstall and a fresh reinstall.
|
; Anything the user put in $INSTDIR - decks, pictures, portable data
|
||||||
RMDir /r "$INSTDIR"
|
; folders - is not on those lists and survives, and $INSTDIR itself is
|
||||||
|
; only removed when nothing else is left in it. An earlier version of this
|
||||||
|
; section ran a blanket "RMDir /r $INSTDIR" to keep build-tree artifacts
|
||||||
|
; out of a fresh reinstall; that also deleted user decks whenever a user
|
||||||
|
; had pointed their data folders into the install directory, so payload
|
||||||
|
; purity may never be bought at that price again.
|
||||||
|
@CPACK_NSIS_DELETE_FILES@
|
||||||
|
@CPACK_NSIS_DELETE_DIRECTORIES@
|
||||||
|
|
||||||
|
; Written by the installer itself, so absent from the staged payload
|
||||||
|
; above; qdebug.txt is app-generated log output next to the executables.
|
||||||
|
Delete "$INSTDIR\uninstall.exe"
|
||||||
|
Delete "$INSTDIR\portable.dat"
|
||||||
|
Delete "$INSTDIR\qdebug.txt"
|
||||||
|
|
||||||
|
; Succeeds only when no foreign files remain.
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
RMDir /r "$SMPROGRAMS\Cockatrice"
|
RMDir /r "$SMPROGRAMS\Cockatrice"
|
||||||
|
|
||||||
|
|
|
||||||
109
cmake/Sanitizers.cmake
Normal file
109
cmake/Sanitizers.cmake
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# AddressSanitizer + UndefinedBehaviorSanitizer opt-in, plus per-source opt-out
|
||||||
|
# Input: ENABLE_SANITIZERS
|
||||||
|
# Defines: cockatrice_disable_sanitizers_for
|
||||||
|
#
|
||||||
|
# Included once from the root CMakeLists.txt, immediately after the per-compiler flag
|
||||||
|
# block, so add_compile_options() reaches every library and executable defined below.
|
||||||
|
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
# Opt a set of vendored sources out of instrumentation.
|
||||||
|
#
|
||||||
|
# cockatrice_disable_sanitizers_for(<source> ...)
|
||||||
|
#
|
||||||
|
# Sanitizer findings inside vendored code are not actionable for us, and letting them
|
||||||
|
# through buries our own bugs in noise until everyone learns to skip the job.
|
||||||
|
#
|
||||||
|
# The sources must be named relative to the directory that compiles them. CMake resolves a
|
||||||
|
# source-file property against the directory scope the target was declared in, so calling
|
||||||
|
# this from the root with absolute paths silently does nothing. That is why the call sites
|
||||||
|
# live next to the add_library/add_executable that pull the vendored code in.
|
||||||
|
#
|
||||||
|
# SKIP_PRECOMPILE_HEADERS is not optional. The precompiled header is built with the
|
||||||
|
# sanitizer flags, so it defines __SANITIZE_ADDRESS__; a translation unit compiled with
|
||||||
|
# -fno-sanitize=all does not, and GCC then refuses the PCH with
|
||||||
|
# "not used because __SANITIZE_ADDRESS__ not defined", which is a fatal -Werror=invalid-pch
|
||||||
|
# in the servatrice and oracle builds.
|
||||||
|
function(cockatrice_disable_sanitizers_for)
|
||||||
|
if(NOT ENABLE_SANITIZERS)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set_source_files_properties(${ARGN} PROPERTIES COMPILE_OPTIONS "-fno-sanitize=all" SKIP_PRECOMPILE_HEADERS ON)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
if(ENABLE_SANITIZERS)
|
||||||
|
# Probe a flag the way it will actually be used: on the compile step AND the link step.
|
||||||
|
# check_cxx_compiler_flag() only probes the compile step, which makes every sanitizer
|
||||||
|
# flag look unsupported because linking an ASan object without -fsanitize=address leaves
|
||||||
|
# __asan_init undefined. That is a silent misconfiguration rather than an error, so the
|
||||||
|
# probe has to link.
|
||||||
|
function(cockatrice_probe_flag FLAG VARNAME)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
|
||||||
|
set(CMAKE_REQUIRED_LINK_OPTIONS "${FLAG}")
|
||||||
|
check_cxx_source_compiles("int main() { return 0; }" ${VARNAME})
|
||||||
|
unset(CMAKE_REQUIRED_FLAGS)
|
||||||
|
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
set(SANITIZER_FLAGS
|
||||||
|
-fsanitize=address,undefined
|
||||||
|
-fno-omit-frame-pointer
|
||||||
|
# UBSan defaults to recover mode: it prints "runtime error: ..." but the
|
||||||
|
# process exits 0, so gtest/ctest report a pass and CI stays green.
|
||||||
|
# -fno-sanitize-recover makes the first finding abort instead. This is
|
||||||
|
# probed like the other cosmetic flags, but CI also sets
|
||||||
|
# UBSAN_OPTIONS=halt_on_error=1 as the runtime-side guarantee.
|
||||||
|
-fno-sanitize-recover=undefined
|
||||||
|
# Qt builds QObject subclasses into raw storage and writes the vptr afterwards, which
|
||||||
|
# the vptr check reports on essentially every QObject instantiation. The check has no
|
||||||
|
# value for us because nothing outside moc-generated code inherits QObject, so it is
|
||||||
|
# off outright rather than suppressed piecemeal.
|
||||||
|
-fno-sanitize=vptr
|
||||||
|
)
|
||||||
|
|
||||||
|
# MSVC has no ASan/UBSan equivalent, and clang-cl would need /fsanitize=address plus a
|
||||||
|
# matching runtime link, which is a separate piece of work.
|
||||||
|
if(MSVC)
|
||||||
|
message(FATAL_ERROR "ENABLE_SANITIZERS is not supported with MSVC")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Probe rather than assume, so an older toolchain gets the sanitizers it can support
|
||||||
|
# instead of failing the build on a flag it does not recognize.
|
||||||
|
set(SANITIZER_SUPPORTED_FLAGS)
|
||||||
|
foreach(FLAG ${SANITIZER_FLAGS})
|
||||||
|
string(MAKE_C_IDENTIFIER "COCKATRICE_HAS${FLAG}" _FLAG_VAR)
|
||||||
|
cockatrice_probe_flag("${FLAG}" ${_FLAG_VAR})
|
||||||
|
if(${_FLAG_VAR})
|
||||||
|
list(APPEND SANITIZER_SUPPORTED_FLAGS ${FLAG})
|
||||||
|
else()
|
||||||
|
message(STATUS "Sanitizers: ${FLAG} unsupported by ${CMAKE_CXX_COMPILER_ID}, skipping")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# The whole point of the option is the sanitizers, so an unsupported pair is fatal even
|
||||||
|
# though the cosmetic flags above are allowed to degrade.
|
||||||
|
if(NOT "-fsanitize=address,undefined" IN_LIST SANITIZER_SUPPORTED_FLAGS)
|
||||||
|
message(FATAL_ERROR "ENABLE_SANITIZERS requires -fsanitize=address,undefined, which "
|
||||||
|
"${CMAKE_CXX_COMPILER_ID} does not accept"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_compile_options(${SANITIZER_SUPPORTED_FLAGS})
|
||||||
|
add_link_options(-fsanitize=address,undefined)
|
||||||
|
|
||||||
|
# Recorded so the test tree can label its entries and a plain `make` at the same time
|
||||||
|
# cannot quietly disagree with what CI ran.
|
||||||
|
set(COCKATRICE_SANITIZERS
|
||||||
|
ON
|
||||||
|
CACHE INTERNAL "AddressSanitizer and UBSan are enabled"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# ENABLE_SANITIZERS is OFF, but COCKATRICE_SANITIZERS is CACHE INTERNAL, so a
|
||||||
|
# reused build dir (e.g. CI's release-package step reconfiguring the same dir
|
||||||
|
# after the sanitized debug step) would otherwise keep skipping NO_SANITIZE
|
||||||
|
# tests and keep the 300s discovery timeout. Reset it explicitly.
|
||||||
|
set(COCKATRICE_SANITIZERS
|
||||||
|
OFF
|
||||||
|
CACHE INTERNAL "AddressSanitizer and UBSan are enabled" FORCE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
@ -3,22 +3,53 @@
|
||||||
*
|
*
|
||||||
* Safe for every target that links Qt Core, including the headless
|
* Safe for every target that links Qt Core, including the headless
|
||||||
* Servatrice binary. Keep this header free of any widget/gui types.
|
* Servatrice binary. Keep this header free of any widget/gui types.
|
||||||
|
*
|
||||||
|
* Candidates are chosen from IWYU include statistics: a header earns a
|
||||||
|
* spot when it is not already reachable from the rest of this list and
|
||||||
|
* enough translation units re-parse it. Qt headers are stable across
|
||||||
|
* builds, so the precompiled header rarely invalidates.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QElapsedTimer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QItemSelectionModel>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QMetaEnum>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QPropertyAnimation>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QSettings>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QUuid>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,56 @@
|
||||||
* Includes the Qt Core precompiled header plus the heavy Gui, Widgets and
|
* Includes the Qt Core precompiled header plus the heavy Gui, Widgets and
|
||||||
* Network layers that virtually every client translation unit re-parses.
|
* Network layers that virtually every client translation unit re-parses.
|
||||||
* Do not use on Servatrice (headless, QT_DONT_USE_QTGUI).
|
* Do not use on Servatrice (headless, QT_DONT_USE_QTGUI).
|
||||||
|
*
|
||||||
|
* Candidates are chosen from IWYU include statistics: a header earns a
|
||||||
|
* spot when it is not already reachable from the rest of this list and
|
||||||
|
* enough translation units re-parse it. Qt headers are stable across
|
||||||
|
* builds, so the precompiled header rarely invalidates.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qtcore_pch.h"
|
#include "qtcore_pch.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QCompleter>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
|
#include <QListWidget>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QStandardItemModel>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <QTableWidgetItem>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
#include <QToolButton>
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/dialogs/dlg_update.cpp
|
src/interface/widgets/dialogs/dlg_update.cpp
|
||||||
src/interface/widgets/dialogs/dlg_view_log.cpp
|
src/interface/widgets/dialogs/dlg_view_log.cpp
|
||||||
src/interface/widgets/dialogs/override_printing_warning.cpp
|
src/interface/widgets/dialogs/override_printing_warning.cpp
|
||||||
|
src/interface/widgets/dialogs/path_safety_warning.cpp
|
||||||
src/interface/widgets/dialogs/tip_of_the_day.cpp
|
src/interface/widgets/dialogs/tip_of_the_day.cpp
|
||||||
src/interface/widgets/deck_share/deck_share_utils.cpp
|
src/interface/widgets/deck_share/deck_share_utils.cpp
|
||||||
src/interface/widgets/deck_share/shared_deck_preview_widget.cpp
|
src/interface/widgets/deck_share/shared_deck_preview_widget.cpp
|
||||||
|
|
@ -140,6 +141,10 @@ set(cockatrice_SOURCES
|
||||||
src/game_graphics/zones/view_zone.cpp
|
src/game_graphics/zones/view_zone.cpp
|
||||||
src/game_graphics/zones/view_zone_widget.cpp
|
src/game_graphics/zones/view_zone_widget.cpp
|
||||||
src/game_graphics/board/abstract_graphics_item.cpp
|
src/game_graphics/board/abstract_graphics_item.cpp
|
||||||
|
src/interface/card_database_update/card_database_update_status_bar.cpp
|
||||||
|
src/interface/card_database_update/card_database_update_status_bar.h
|
||||||
|
src/interface/card_database_update/card_update_progress.cpp
|
||||||
|
src/interface/card_database_update/card_update_progress.h
|
||||||
src/interface/card_picture_loader/card_picture_loader.cpp
|
src/interface/card_picture_loader/card_picture_loader.cpp
|
||||||
src/interface/card_picture_loader/card_picture_loader_local.cpp
|
src/interface/card_picture_loader/card_picture_loader_local.cpp
|
||||||
src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.cpp
|
src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.cpp
|
||||||
|
|
@ -687,7 +692,7 @@ if(WIN32)
|
||||||
# import table, and the glob above only sees DLLs that were already copied next
|
# import table, and the glob above only sees DLLs that were already copied next
|
||||||
# to the executable. Qt6::Concurrent is linked but never imported - QtConcurrent::run
|
# to the executable. Qt6::Concurrent is linked but never imported - QtConcurrent::run
|
||||||
# and QFutureWatcher are header-only in Qt 6 - so neither step ships
|
# and QFutureWatcher are header-only in Qt 6 - so neither step ships
|
||||||
# Qt6Concurrent.dll, even though required-qt-runtime.txt lists it and the
|
# Qt6Concurrent.dll, even though required-runtime.txt lists it and the
|
||||||
# Windows package check then fails on a package that is fine to run.
|
# Windows package check then fails on a package that is fine to run.
|
||||||
# Qt6::ShaderTools is skipped for the same reason.
|
# Qt6::ShaderTools is skipped for the same reason.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,4 @@ Name=Cockatrice
|
||||||
Exec=cockatrice %U
|
Exec=cockatrice %U
|
||||||
Icon=cockatrice
|
Icon=cockatrice
|
||||||
Categories=Game;CardGame;
|
Categories=Game;CardGame;
|
||||||
MimeType=application/x-cockatrice;
|
MimeType=application/x-cockatrice;x-scheme-handler/cockatrice;
|
||||||
X-Scheme-Handler/cockatrice=true
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,10 @@
|
||||||
#include "lag_monitor.h"
|
#include "lag_monitor.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
|
#include <QMessageLogger>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
LagMonitor::LagMonitor(QObject *parent) : QObject(parent)
|
LagMonitor::LagMonitor(QObject *parent) : QObject(parent)
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,15 @@
|
||||||
#ifndef LAG_MONITOR_H
|
#ifndef LAG_MONITOR_H
|
||||||
#define LAG_MONITOR_H
|
#define LAG_MONITOR_H
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(LagMonitorLog, "lag_monitor");
|
inline Q_LOGGING_CATEGORY(LagMonitorLog, "lag_monitor");
|
||||||
|
|
||||||
class QEvent;
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@
|
||||||
|
|
||||||
#include "latency_graph_widget.h"
|
#include "latency_graph_widget.h"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QRectF>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <qnumeric.h>
|
||||||
|
|
||||||
LatencyGraphWidget::LatencyGraphWidget(QWidget *parent) : QWidget(parent)
|
LatencyGraphWidget::LatencyGraphWidget(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Bar graph of recent network round-trip samples.
|
* @brief Bar graph of recent network round-trip samples.
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@
|
||||||
#include "latency_status_widget.h"
|
#include "latency_status_widget.h"
|
||||||
|
|
||||||
#include "latency_graph_widget.h"
|
#include "latency_graph_widget.h"
|
||||||
|
#include "latency_tracker.h"
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPoint>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
|
||||||
LatencyStatusWidget::LatencyStatusWidget(QWidget *parent) : QWidget(parent)
|
LatencyStatusWidget::LatencyStatusWidget(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@
|
||||||
#define LATENCY_STATUS_WIDGET_H
|
#define LATENCY_STATUS_WIDGET_H
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <libcockatrice/network/client/abstract/latency_tracker.h>
|
#include <libcockatrice/network/client/abstract/latency_tracker.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class LatencyGraphWidget;
|
class LatencyGraphWidget;
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,25 @@
|
||||||
#include "../interface/widgets/dialogs/dlg_forgot_password_reset.h"
|
#include "../interface/widgets/dialogs/dlg_forgot_password_reset.h"
|
||||||
#include "../interface/widgets/dialogs/dlg_register.h"
|
#include "../interface/widgets/dialogs/dlg_register.h"
|
||||||
#include "../interface/widgets/utility/get_text_with_max.h"
|
#include "../interface/widgets/utility/get_text_with_max.h"
|
||||||
|
#include "libcockatrice/protocol/pb/event_connection_closed.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/event_server_shutdown.pb.h"
|
||||||
|
|
||||||
|
#include <QChar>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QStringLiteral>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
#include <libcockatrice/network/client/remote/remote_client.h>
|
||||||
#include <libcockatrice/protocol/pb/response.pb.h>
|
#include <libcockatrice/protocol/pb/response.pb.h>
|
||||||
#include <libcockatrice/settings/servers_settings.h>
|
#include <libcockatrice/settings/servers_settings.h>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
ConnectionController::ConnectionController(QWidget *dialogParent, QObject *parent)
|
ConnectionController::ConnectionController(QWidget *dialogParent, QObject *parent)
|
||||||
: QObject(parent), dialogParent(dialogParent)
|
: QObject(parent), dialogParent(dialogParent)
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,22 @@
|
||||||
#define COCKATRICE_REMOTE_CONNECTION_CONTROLLER_H
|
#define COCKATRICE_REMOTE_CONNECTION_CONTROLLER_H
|
||||||
|
|
||||||
#include "abstract_client.h"
|
#include "abstract_client.h"
|
||||||
|
#include "latency_tracker.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QThread>
|
#include <QtGlobal>
|
||||||
#include <libcockatrice/protocol/pb/event_connection_closed.pb.h>
|
#include <qtmetamacros.h>
|
||||||
#include <libcockatrice/protocol/pb/event_server_shutdown.pb.h>
|
|
||||||
|
|
||||||
class RemoteClient;
|
class RemoteClient;
|
||||||
class ServerInfo_User;
|
class ServerInfo_User;
|
||||||
class DlgConnect;
|
class DlgConnect;
|
||||||
|
class Event_ConnectionClosed;
|
||||||
|
class Event_ServerShutdown;
|
||||||
|
class QThread;
|
||||||
|
class QWidget;
|
||||||
|
template <typename T> class QList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owns the RemoteClient and its worker thread.
|
* Owns the RemoteClient and its worker thread.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
||||||
#include "deck_stats_interface.h"
|
#include "deck_stats_interface.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/card/card_info.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_querier.h"
|
||||||
|
#include "libcockatrice/deck_list/tree/inner_deck_list_node.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
#include <functional>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/deck_list/deck_list.h>
|
#include <libcockatrice/deck_list/deck_list.h>
|
||||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
#ifndef DECKSTATS_INTERFACE_H
|
#ifndef DECKSTATS_INTERFACE_H
|
||||||
#define DECKSTATS_INTERFACE_H
|
#define DECKSTATS_INTERFACE_H
|
||||||
|
|
||||||
#include <libcockatrice/deck_list/deck_list.h>
|
#include <QObject>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,28 @@
|
||||||
#include "tapped_out_interface.h"
|
#include "tapped_out_interface.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/card/card_info.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_querier.h"
|
||||||
|
#include "libcockatrice/deck_list/tree/inner_deck_list_node.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QRegularExpressionMatchIterator>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <functional>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/deck_list/deck_list.h>
|
#include <libcockatrice/deck_list/deck_list.h>
|
||||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(TappedOutInterfaceLog, "tapped_out_interface");
|
inline Q_LOGGING_CATEGORY(TappedOutInterfaceLog, "tapped_out_interface");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "deck_link_to_api_transformer.h"
|
#include "deck_link_to_api_transformer.h"
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
|
||||||
namespace DeckLinkToApiTransformer
|
namespace DeckLinkToApiTransformer
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,36 @@
|
||||||
#include "spoiler_background_updater.h"
|
#include "spoiler_background_updater.h"
|
||||||
|
|
||||||
#include "../../../../interface/window_main.h"
|
|
||||||
#include "../../../../main.h"
|
#include "../../../../main.h"
|
||||||
#include "../../../settings/cache_settings.h"
|
#include "../../../settings/cache_settings.h"
|
||||||
|
|
||||||
|
#include <QChar>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QList>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QTimeZone>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrentRun>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <functional>
|
||||||
#include <libcockatrice/card/database/card_database.h>
|
#include <libcockatrice/card/database/card_database.h>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/settings/download_settings.h>
|
#include <libcockatrice/settings/download_settings.h>
|
||||||
#include <libcockatrice/settings/paths_settings.h>
|
#include <libcockatrice/settings/paths_settings.h>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
#include <version_string.h>
|
#include <version_string.h>
|
||||||
|
|
||||||
#define SPOILERS_STATUS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/SpoilerSeasonEnabled"
|
#define SPOILERS_STATUS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/SpoilerSeasonEnabled"
|
||||||
|
|
@ -163,7 +178,15 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
||||||
|
|
||||||
// Data written, so reload the card database
|
// Data written, so reload the card database
|
||||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
|
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
|
||||||
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
|
// Spoilers can introduce sets the config has never seen; the loader never
|
||||||
|
// runs checkUnknownSets() itself, so run it once the finished snapshot has
|
||||||
|
// been swapped in.
|
||||||
|
auto *watcher = new QFutureWatcher<void>(this);
|
||||||
|
connect(watcher, &QFutureWatcher<void>::finished, this, [watcher] {
|
||||||
|
watcher->deleteLater();
|
||||||
|
CardDatabaseManager::getInstance()->checkUnknownSets();
|
||||||
|
});
|
||||||
|
watcher->setFuture(QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); }));
|
||||||
|
|
||||||
// If the user has notifications enabled, let them know
|
// If the user has notifications enabled, let them know
|
||||||
// when the database was last updated
|
// when the database was last updated
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,11 @@
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class QProcess;
|
||||||
|
class QUrl;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(SpoilerBackgroundUpdaterLog, "spoiler_background_updater");
|
inline Q_LOGGING_CATEGORY(SpoilerBackgroundUpdaterLog, "spoiler_background_updater");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
|
|
||||||
#ifndef CLIENT_UPDATE_CHECKER_H
|
#ifndef CLIENT_UPDATE_CHECKER_H
|
||||||
#define CLIENT_UPDATE_CHECKER_H
|
#define CLIENT_UPDATE_CHECKER_H
|
||||||
#include <QObject>
|
#include "release_channel.h"
|
||||||
|
|
||||||
class Release;
|
#include <QMetaObject>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We use a singleton instance of UpdateChannel, which can cause interference and feedback loops when multiple objects
|
* We use a singleton instance of UpdateChannel, which can cause interference and feedback loops when multiple objects
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,27 @@
|
||||||
|
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QMessageBox>
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSysInfo>
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVariantMap>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
#include <qprocessordetection.h>
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariantMap>
|
#include <QVariantList>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(ReleaseChannelLog, "release_channel");
|
inline Q_LOGGING_CATEGORY(ReleaseChannelLog, "release_channel");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
#include "update_downloader.h"
|
#include "update_downloader.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QChar>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response(nullptr)
|
UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response(nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,14 @@
|
||||||
#ifndef COCKATRICE_UPDATEDOWNLOADER_H
|
#ifndef COCKATRICE_UPDATEDOWNLOADER_H
|
||||||
#define COCKATRICE_UPDATEDOWNLOADER_H
|
#define COCKATRICE_UPDATEDOWNLOADER_H
|
||||||
|
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtNetwork>
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
class UpdateDownloader : public QObject
|
class UpdateDownloader : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,20 @@
|
||||||
|
|
||||||
#include "../network/update/client/release_channel.h"
|
#include "../network/update/client/release_channel.h"
|
||||||
#include "card_counter_settings.h"
|
#include "card_counter_settings.h"
|
||||||
|
#include "libcockatrice/interfaces/interface_card_database_path_provider.h"
|
||||||
#include "shortcuts_settings.h"
|
#include "shortcuts_settings.h"
|
||||||
#include "version_string.h"
|
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QGlobalStatic>
|
#include <QGlobalStatic>
|
||||||
|
#include <QMessageLogger>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QtGlobal>
|
||||||
#include <libcockatrice/settings/appearance_settings.h>
|
#include <libcockatrice/settings/appearance_settings.h>
|
||||||
#include <libcockatrice/settings/cache_storage_settings.h>
|
#include <libcockatrice/settings/cache_storage_settings.h>
|
||||||
#include <libcockatrice/settings/card_database_settings.h>
|
#include <libcockatrice/settings/card_database_settings.h>
|
||||||
|
|
@ -128,6 +133,10 @@ SettingsCache::SettingsCache()
|
||||||
// Migrate settings from global.ini to per-class INI files (runs at most once)
|
// Migrate settings from global.ini to per-class INI files (runs at most once)
|
||||||
SettingsMigration::migrateSettingsFromGlobalIni(settingsPath);
|
SettingsMigration::migrateSettingsFromGlobalIni(settingsPath);
|
||||||
|
|
||||||
|
// Repair gamefilters.ini keys renamed to camelCase by #7084 for profiles that migrated
|
||||||
|
// before that rename (idempotent, safe to run on every startup, portable builds included).
|
||||||
|
SettingsMigration::migrateGameFiltersToCamelCase(settingsPath);
|
||||||
|
|
||||||
shortcutsSettings = new ShortcutsSettings(settingsPath, this);
|
shortcutsSettings = new ShortcutsSettings(settingsPath, this);
|
||||||
cardDatabaseSettings = new CardDatabaseSettings(settingsPath, this);
|
cardDatabaseSettings = new CardDatabaseSettings(settingsPath, this);
|
||||||
serversSettings = new ServersSettings(settingsPath, this);
|
serversSettings = new ServersSettings(settingsPath, this);
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@
|
||||||
#ifndef SETTINGSCACHE_H
|
#ifndef SETTINGSCACHE_H
|
||||||
#define SETTINGSCACHE_H
|
#define SETTINGSCACHE_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <libcockatrice/interfaces/interface_card_database_path_provider.h>
|
#include <libcockatrice/interfaces/interface_card_database_path_provider.h>
|
||||||
#include <libcockatrice/interfaces/interface_network_settings_provider.h>
|
#include <libcockatrice/interfaces/interface_network_settings_provider.h>
|
||||||
#include <libcockatrice/utility/macros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(SettingsCacheLog, "settings_cache");
|
inline Q_LOGGING_CATEGORY(SettingsCacheLog, "settings_cache");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
#include "card_counter_settings.h"
|
#include "card_counter_settings.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/settings/settings_manager.h"
|
||||||
|
|
||||||
|
#include <QChar>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QVariant>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
class QObject;
|
||||||
|
|
||||||
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
|
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
|
||||||
: SettingsManager(settingsPath + "card_counters.ini", "cards", "counters", parent)
|
: SettingsManager(settingsPath + "card_counters.ini", "cards", "counters", parent)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@
|
||||||
#ifndef CARD_COUNTER_SETTINGS_H
|
#ifndef CARD_COUNTER_SETTINGS_H
|
||||||
#define CARD_COUNTER_SETTINGS_H
|
#define CARD_COUNTER_SETTINGS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
#include <libcockatrice/settings/settings_manager.h>
|
#include <libcockatrice/settings/settings_manager.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class QSettings;
|
|
||||||
class QColor;
|
class QColor;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
class CardCounterSettings : public SettingsManager
|
class CardCounterSettings : public SettingsManager
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,24 @@
|
||||||
#include "cache_settings.h"
|
#include "cache_settings.h"
|
||||||
#include "shortcuts_settings.h"
|
#include "shortcuts_settings.h"
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QAbstractItemView>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QHash>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
#include <QList>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QStandardItem>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
|
||||||
|
class QObject;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
ShortcutFilterProxyModel::ShortcutFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
|
ShortcutFilterProxyModel::ShortcutFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,13 @@
|
||||||
#define SHORTCUT_TREEVIEW_H
|
#define SHORTCUT_TREEVIEW_H
|
||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QStandardItemModel>
|
#include <QString>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class QObject;
|
||||||
|
class QStandardItemModel;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom implementation of QSortFilterProxyModel that appends the source and parent strings together when filtering
|
* Custom implementation of QSortFilterProxyModel that appends the source and parent strings together when filtering
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QMap>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <utility>
|
#include <QVariant>
|
||||||
|
|
||||||
ShortcutKey::ShortcutKey(const QString &_name, QList<QKeySequence> _sequence, ShortcutGroup::Groups _group)
|
ShortcutKey::ShortcutKey(const QString &_name, QList<QKeySequence> _sequence, ShortcutGroup::Groups _group)
|
||||||
: QList<QKeySequence>(_sequence), name(_name), group(_group)
|
: QList<QKeySequence>(_sequence), name(_name), group(_group)
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,18 @@
|
||||||
#define SHORTCUTSSETTINGS_H
|
#define SHORTCUTSSETTINGS_H
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QChar>
|
||||||
|
#include <QHash>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QSettings>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(ShortcutsSettingsLog, "shortcuts_settings");
|
inline Q_LOGGING_CATEGORY(ShortcutsSettingsLog, "shortcuts_settings");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,15 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QAudioOutput>
|
#include <QAudioOutput>
|
||||||
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QList>
|
||||||
#include <QMediaPlayer>
|
#include <QMediaPlayer>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QtGlobal>
|
||||||
#include <libcockatrice/settings/sound_settings.h>
|
#include <libcockatrice/settings/sound_settings.h>
|
||||||
|
|
||||||
#define DEFAULT_THEME_NAME "Default"
|
#define DEFAULT_THEME_NAME "Default"
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,17 @@
|
||||||
#ifndef SOUNDENGINE_H
|
#ifndef SOUNDENGINE_H
|
||||||
#define SOUNDENGINE_H
|
#define SOUNDENGINE_H
|
||||||
|
|
||||||
#include <QAudioOutput>
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMediaPlayer>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class QAudioOutput;
|
||||||
|
class QMediaPlayer;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(SoundEngineLog, "sound_engine");
|
inline Q_LOGGING_CATEGORY(SoundEngineLog, "sound_engine");
|
||||||
|
|
||||||
class QBuffer;
|
|
||||||
|
|
||||||
typedef QMap<QString, QString> QStringMap;
|
typedef QMap<QString, QString> QStringMap;
|
||||||
|
|
||||||
class SoundEngine : public QObject
|
class SoundEngine : public QObject
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,6 @@ public:
|
||||||
{
|
{
|
||||||
return SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName);
|
return SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool getIncludeRebalancedCards() const override
|
|
||||||
{
|
|
||||||
return SettingsCache::instance().cardsDisplay().getIncludeRebalancedCards();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H
|
#endif // COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,27 @@
|
||||||
#include "deck_filter_string.h"
|
#include "deck_filter_string.h"
|
||||||
|
|
||||||
|
#include "../interface/deck_loader/loaded_deck.h"
|
||||||
|
#include "libcockatrice/card/card_localization.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_querier.h"
|
||||||
|
#include "libcockatrice/deck_list/deck_list.h"
|
||||||
|
#include "libcockatrice/deck_list/tree/deck_list_card_node.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <any>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/filters/filter_string.h>
|
#include <libcockatrice/filters/filter_string.h>
|
||||||
#include <libcockatrice/utility/peglib.h>
|
#include <libcockatrice/utility/peglib.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
static peg::parser search(R"(
|
static peg::parser search(R"(
|
||||||
Start <- QueryPartList
|
Start <- QueryPartList
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,14 @@
|
||||||
#ifndef DECK_FILTER_STRING_H
|
#ifndef DECK_FILTER_STRING_H
|
||||||
#define DECK_FILTER_STRING_H
|
#define DECK_FILTER_STRING_H
|
||||||
|
|
||||||
#include "../interface/deck_loader/loaded_deck.h"
|
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <libcockatrice/card/card_localization.h>
|
#include <libcockatrice/card/card_localization.h>
|
||||||
|
|
||||||
|
struct CardSearchLanguage;
|
||||||
|
struct LoadedDeck;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string");
|
inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,15 @@
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QIcon>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QSizePolicy>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringLiteral>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QtGlobal>
|
||||||
#include <libcockatrice/filters/filter_card.h>
|
#include <libcockatrice/filters/filter_card.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent)
|
FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
#define FILTERBUILDER_H
|
#define FILTERBUILDER_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class QCheckBox;
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class LineEditUnfocusable;
|
class LineEditUnfocusable;
|
||||||
class CardFilter;
|
class CardFilter;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
#include "filter_tree_model.h"
|
#include "filter_tree_model.h"
|
||||||
|
|
||||||
|
#include <QFlags>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <functional>
|
||||||
#include <libcockatrice/filters/filter_card.h>
|
#include <libcockatrice/filters/filter_card.h>
|
||||||
#include <libcockatrice/filters/filter_tree.h>
|
#include <libcockatrice/filters/filter_tree.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
class QObject;
|
||||||
|
|
||||||
FilterTreeModel::FilterTreeModel(QObject *parent) : QAbstractItemModel(parent)
|
FilterTreeModel::FilterTreeModel(QObject *parent) : QAbstractItemModel(parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,15 @@
|
||||||
#define FILTERTREEMODEL_H
|
#define FILTERTREEMODEL_H
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
#include <QList>
|
||||||
|
#include <QModelIndex>
|
||||||
#include <libcockatrice/filters/filter_card.h>
|
#include <libcockatrice/filters/filter_card.h>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class FilterTree;
|
class FilterTree;
|
||||||
class CardFilter;
|
|
||||||
class FilterTreeNode;
|
class FilterTreeNode;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
class FilterTreeModel : public QAbstractItemModel
|
class FilterTreeModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,21 @@
|
||||||
#include "syntax_help.h"
|
#include "syntax_help.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFlags>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QObject>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTextBrowser>
|
||||||
|
#include <QTextDocument>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the card search syntax help window
|
* Creates the card search syntax help window
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@
|
||||||
#ifndef SEARCH_SYNTAX_HELP_H
|
#ifndef SEARCH_SYNTAX_HELP_H
|
||||||
#define SEARCH_SYNTAX_HELP_H
|
#define SEARCH_SYNTAX_HELP_H
|
||||||
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QTextBrowser>
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QTextBrowser;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(SyntaxHelpLog, "syntax_help");
|
inline Q_LOGGING_CATEGORY(SyntaxHelpLog, "syntax_help");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,18 @@
|
||||||
#include "abstract_game.h"
|
#include "abstract_game.h"
|
||||||
|
|
||||||
#include "../interface/widgets/tabs/tab_game.h"
|
#include "game_event_handler.h"
|
||||||
|
#include "game_meta_info.h"
|
||||||
|
#include "game_state.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_replay.pb.h"
|
||||||
|
#include "player/player_info.h"
|
||||||
#include "player/player_logic.h"
|
#include "player/player_logic.h"
|
||||||
|
#include "player/player_manager.h"
|
||||||
|
#include "zones/card_zone_logic.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class AbstractClient;
|
||||||
|
|
||||||
AbstractGame::AbstractGame(QObject *_parent) : QObject(_parent)
|
AbstractGame::AbstractGame(QObject *_parent) : QObject(_parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,18 @@
|
||||||
#ifndef COCKATRICE_ABSTRACT_GAME_H
|
#ifndef COCKATRICE_ABSTRACT_GAME_H
|
||||||
#define COCKATRICE_ABSTRACT_GAME_H
|
#define COCKATRICE_ABSTRACT_GAME_H
|
||||||
|
|
||||||
#include "game_event_handler.h"
|
|
||||||
#include "game_meta_info.h"
|
|
||||||
#include "game_state.h"
|
|
||||||
#include "player/player_manager.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class CardItem;
|
class CardItem;
|
||||||
|
class AbstractClient;
|
||||||
|
class GameEventHandler;
|
||||||
|
class GameMetaInfo;
|
||||||
|
class GameReplay;
|
||||||
|
class GameState;
|
||||||
|
class PlayerManager;
|
||||||
|
|
||||||
class AbstractGame : public QObject
|
class AbstractGame : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "arrow_registry.h"
|
#include "arrow_registry.h"
|
||||||
|
|
||||||
#include "../game_graphics/board/arrow_item.h"
|
#include "../game_graphics/board/arrow_item.h"
|
||||||
|
#include "board/arrow_data.h"
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
void ArrowRegistry::insert(QSharedPointer<ArrowData> data, ArrowItem *arrow)
|
void ArrowRegistry::insert(QSharedPointer<ArrowData> data, ArrowItem *arrow)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
#ifndef COCKATRICE_ARROW_REGISTRY_H
|
#ifndef COCKATRICE_ARROW_REGISTRY_H
|
||||||
#define COCKATRICE_ARROW_REGISTRY_H
|
#define COCKATRICE_ARROW_REGISTRY_H
|
||||||
|
|
||||||
#include "board/arrow_data.h"
|
#include <QList>
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QSharedPointer>
|
|
||||||
|
|
||||||
class ArrowItem;
|
class ArrowItem;
|
||||||
|
struct ArrowData;
|
||||||
|
template <class T> class QSharedPointer;
|
||||||
|
|
||||||
struct ArrowKey
|
struct ArrowKey
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#include "arrow_data.h"
|
#include "arrow_data.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_arrow.pb.h"
|
||||||
|
#include "libcockatrice/utility/color.h"
|
||||||
|
|
||||||
ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow, int creatorId, bool isLocalCreator)
|
ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow, int creatorId, bool isLocalCreator)
|
||||||
{
|
{
|
||||||
ArrowData data;
|
ArrowData data;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_arrow.pb.h>
|
|
||||||
#include <libcockatrice/utility/color.h>
|
class ServerInfo_Arrow;
|
||||||
|
|
||||||
struct ArrowData
|
struct ArrowData
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
#include "card_list.h"
|
#include "card_list.h"
|
||||||
|
|
||||||
#include "../../game_graphics/board/card_item.h"
|
#include "../../game_graphics/board/card_item.h"
|
||||||
|
#include "libcockatrice/card/printing/exact_card.h"
|
||||||
|
|
||||||
|
#include <QChar>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <compare>
|
||||||
#include <libcockatrice/card/card_info.h>
|
#include <libcockatrice/card/card_info.h>
|
||||||
|
|
||||||
CardList::CardList(bool _contentsKnown) : QList<CardItem *>(), contentsKnown(_contentsKnown)
|
CardList::CardList(bool _contentsKnown) : QList<CardItem *>(), contentsKnown(_contentsKnown)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QString>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(CardListLog, "card_list");
|
inline Q_LOGGING_CATEGORY(CardListLog, "card_list");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "card_state.h"
|
#include "card_state.h"
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
void CardState::resetState(bool keepAnnotations)
|
void CardState::resetState(bool keepAnnotations)
|
||||||
{
|
{
|
||||||
attacking = false;
|
attacking = false;
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class CardZoneLogic;
|
class CardZoneLogic;
|
||||||
class CardItem;
|
class CardItem;
|
||||||
|
|
||||||
class CardState : public QObject
|
class CardState : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "counter_state.h"
|
#include "counter_state.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_counter.pb.h"
|
||||||
|
|
||||||
#include <libcockatrice/utility/color.h>
|
#include <libcockatrice/utility/color.h>
|
||||||
|
|
||||||
CounterState::CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent)
|
CounterState::CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_counter.pb.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class ServerInfo_Counter;
|
||||||
|
|
||||||
class CounterState : public QObject
|
class CounterState : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,17 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
#include "../interface/widgets/tabs/tab_game.h"
|
#include "game_meta_info.h"
|
||||||
|
#include "game_state.h"
|
||||||
|
#include "player/player_manager.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/event_game_joined.pb.h>
|
#include <libcockatrice/protocol/pb/event_game_joined.pb.h>
|
||||||
|
|
||||||
|
class AbstractClient;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
Game::Game(QObject *_parent,
|
Game::Game(QObject *_parent,
|
||||||
bool isLocalGame,
|
bool isLocalGame,
|
||||||
QList<AbstractClient *> &_clients,
|
QList<AbstractClient *> &_clients,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,14 @@
|
||||||
|
|
||||||
#include "abstract_game.h"
|
#include "abstract_game.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class AbstractClient;
|
||||||
|
class Event_GameJoined;
|
||||||
|
class QObject;
|
||||||
|
class QString;
|
||||||
|
template <class Key, class T> class QMap;
|
||||||
|
template <typename T> class QList;
|
||||||
|
|
||||||
class Game : public AbstractGame
|
class Game : public AbstractGame
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,30 @@
|
||||||
#include "game_event_handler.h"
|
#include "game_event_handler.h"
|
||||||
|
|
||||||
#include "../game_graphics/log/message_log_widget.h"
|
|
||||||
#include "../interface/widgets/tabs/tab_game.h"
|
|
||||||
#include "abstract_game.h"
|
#include "abstract_game.h"
|
||||||
|
#include "game_meta_info.h"
|
||||||
|
#include "game_state.h"
|
||||||
|
#include "libcockatrice/protocol/pb/commands.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_commands.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_event.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_event_context.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/response.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_game.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_player.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_playerproperties.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_user.pb.h"
|
||||||
|
#include "player/player_event_handler.h"
|
||||||
|
#include "player/player_info.h"
|
||||||
|
#include "player/player_logic.h"
|
||||||
|
#include "player/player_manager.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMapIterator>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <google/protobuf/stubs/port.h>
|
||||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
||||||
#include <libcockatrice/protocol/get_pb_extension.h>
|
#include <libcockatrice/protocol/get_pb_extension.h>
|
||||||
#include <libcockatrice/protocol/pb/command_concede.pb.h>
|
#include <libcockatrice/protocol/pb/command_concede.pb.h>
|
||||||
|
|
@ -13,7 +34,6 @@
|
||||||
#include <libcockatrice/protocol/pb/command_next_turn.pb.h>
|
#include <libcockatrice/protocol/pb/command_next_turn.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/command_reverse_turn.pb.h>
|
#include <libcockatrice/protocol/pb/command_reverse_turn.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/command_set_active_phase.pb.h>
|
#include <libcockatrice/protocol/pb/command_set_active_phase.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/context_connection_state_changed.pb.h>
|
|
||||||
#include <libcockatrice/protocol/pb/context_deck_select.pb.h>
|
#include <libcockatrice/protocol/pb/context_deck_select.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/event_game_closed.pb.h>
|
#include <libcockatrice/protocol/pb/event_game_closed.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/event_game_host_changed.pb.h>
|
#include <libcockatrice/protocol/pb/event_game_host_changed.pb.h>
|
||||||
|
|
@ -28,6 +48,8 @@
|
||||||
#include <libcockatrice/protocol/pb/event_set_active_player.pb.h>
|
#include <libcockatrice/protocol/pb/event_set_active_player.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/game_event_container.pb.h>
|
#include <libcockatrice/protocol/pb/game_event_container.pb.h>
|
||||||
#include <libcockatrice/protocol/pending_command.h>
|
#include <libcockatrice/protocol/pending_command.h>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
GameEventHandler::GameEventHandler(AbstractGame *_game) : QObject(_game), game(_game)
|
GameEventHandler::GameEventHandler(AbstractGame *_game) : QObject(_game), game(_game)
|
||||||
{
|
{
|
||||||
|
|
@ -255,8 +277,6 @@ void GameEventHandler::eventSpectatorLeave(const Event_Leave &event,
|
||||||
emit spectatorLeft(eventPlayerId);
|
emit spectatorLeft(eventPlayerId);
|
||||||
|
|
||||||
game->getPlayerManager()->removeSpectator(eventPlayerId);
|
game->getPlayerManager()->removeSpectator(eventPlayerId);
|
||||||
|
|
||||||
emitUserEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event,
|
void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event,
|
||||||
|
|
@ -443,9 +463,9 @@ void GameEventHandler::eventJoin(const Event_Join &event, int /*eventPlayerId*/,
|
||||||
PlayerLogic *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info());
|
PlayerLogic *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info());
|
||||||
emit logJoinPlayer(newPlayer);
|
emit logJoinPlayer(newPlayer);
|
||||||
emit playerJoined(playerInfo);
|
emit playerJoined(playerInfo);
|
||||||
}
|
|
||||||
|
|
||||||
emitUserEvent();
|
emitUserEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GameEventHandler::getLeaveReason(Event_Leave::LeaveReason reason)
|
QString GameEventHandler::getLeaveReason(Event_Leave::LeaveReason reason)
|
||||||
|
|
|
||||||
|
|
@ -19,23 +19,29 @@
|
||||||
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
#include <libcockatrice/protocol/pb/event_leave.pb.h>
|
#include <libcockatrice/protocol/pb/event_leave.pb.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
// IWYU pragma: keep
|
||||||
|
// GameEventContext, ServerInfo_Player and ServerInfo_User are passed by value
|
||||||
|
// to signals and slots, so the moc-generated code needs the complete types.
|
||||||
|
#include <libcockatrice/protocol/pb/game_event_context.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
|
||||||
|
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||||
|
|
||||||
class AbstractClient;
|
class AbstractClient;
|
||||||
class AbstractGame;
|
class AbstractGame;
|
||||||
class CommandContainer;
|
|
||||||
class GameCommand;
|
|
||||||
class GameEventContainer;
|
class GameEventContainer;
|
||||||
class GameEventContext;
|
class GameEventContext;
|
||||||
class PendingCommand;
|
class PendingCommand;
|
||||||
class PlayerLogic;
|
class PlayerLogic;
|
||||||
class Response;
|
class Response;
|
||||||
|
|
||||||
class Event_GameStateChanged;
|
class Event_GameStateChanged;
|
||||||
class Event_PlayerPropertiesChanged;
|
class Event_PlayerPropertiesChanged;
|
||||||
class Event_Join;
|
class Event_Join;
|
||||||
class Event_Leave;
|
|
||||||
class Event_GameHostChanged;
|
class Event_GameHostChanged;
|
||||||
class Event_GameClosed;
|
class Event_GameClosed;
|
||||||
class Event_SetActivePlayer;
|
class Event_SetActivePlayer;
|
||||||
|
|
@ -44,6 +50,15 @@ class Event_GameSay;
|
||||||
class Event_Kicked;
|
class Event_Kicked;
|
||||||
class Event_ReverseTurn;
|
class Event_ReverseTurn;
|
||||||
class Event_Ping;
|
class Event_Ping;
|
||||||
|
class ServerInfo_PlayerProperties;
|
||||||
|
namespace google
|
||||||
|
{
|
||||||
|
namespace protobuf
|
||||||
|
{
|
||||||
|
class Message;
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
template <typename T> class QList;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler");
|
inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,16 @@
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_game.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_game.pb.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
// Translation layer class to expose protobuf safely and hook it up to Qt Signals.
|
// Translation layer class to expose protobuf safely and hook it up to Qt Signals.
|
||||||
// This class de-couples the domain object (i.e. the GameMetaInfo) from the network object.
|
// This class de-couples the domain object (i.e. the GameMetaInfo) from the network object.
|
||||||
// If the network object changes, only this class needs to be adjusted.
|
// If the network object changes, only this class needs to be adjusted.
|
||||||
|
|
||||||
class AbstractGame;
|
class AbstractGame;
|
||||||
|
|
||||||
class GameMetaInfo : public QObject
|
class GameMetaInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
#include "abstract_game.h"
|
#include "abstract_game.h"
|
||||||
|
|
||||||
|
#include <QChar>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
class AbstractClient;
|
||||||
|
|
||||||
GameState::GameState(AbstractGame *parent,
|
GameState::GameState(AbstractGame *parent,
|
||||||
int _secondsElapsed,
|
int _secondsElapsed,
|
||||||
int _hostId,
|
int _hostId,
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,14 @@
|
||||||
#ifndef COCKATRICE_GAME_STATE_H
|
#ifndef COCKATRICE_GAME_STATE_H
|
||||||
#define COCKATRICE_GAME_STATE_H
|
#define COCKATRICE_GAME_STATE_H
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QList>
|
||||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class AbstractGame;
|
class AbstractGame;
|
||||||
class ServerInfo_PlayerProperties;
|
class AbstractClient;
|
||||||
class ServerInfo_User;
|
class QTimer;
|
||||||
|
|
||||||
class GameState : public QObject
|
class GameState : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
#include "phase.h"
|
#include "phase.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QList>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
Phase::Phase(const QString &_name, const QString &_color, const QString &_soundFileName)
|
Phase::Phase(const QString &_name, const QString &_color, const QString &_soundFileName)
|
||||||
: name(_name), color(_color), soundFileName(_soundFileName)
|
: name(_name), color(_color), soundFileName(_soundFileName)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@
|
||||||
#ifndef PHASE_H
|
#ifndef PHASE_H
|
||||||
#define PHASE_H
|
#define PHASE_H
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QCoreApplication>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
class Phase
|
class Phase
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,54 @@
|
||||||
#include "player_actions.h"
|
#include "player_actions.h"
|
||||||
|
|
||||||
|
#include "../../client/settings/cache_settings.h"
|
||||||
|
#include "../../game_graphics/board/card_item.h"
|
||||||
|
#include "../../game_graphics/dialogs/dlg_create_token.h"
|
||||||
#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h"
|
#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h"
|
||||||
#include "../../game_graphics/dialogs/dlg_roll_dice.h"
|
|
||||||
#include "../../game_graphics/player/card_menu_action_type.h"
|
#include "../../game_graphics/player/card_menu_action_type.h"
|
||||||
#include "../../game_graphics/zones/hand_zone.h"
|
|
||||||
#include "../../game_graphics/zones/table_zone.h"
|
#include "../../game_graphics/zones/table_zone.h"
|
||||||
#include "../../interface/widgets/tabs/tab_game.h"
|
#include "../../interface/deck_loader/loaded_deck.h"
|
||||||
#include "../../interface/widgets/utility/get_text_with_max.h"
|
#include "../abstract_game.h"
|
||||||
|
#include "../board/counter_state.h"
|
||||||
|
#include "../game_event_handler.h"
|
||||||
|
#include "../zones/card_zone_logic.h"
|
||||||
|
#include "../zones/hand_zone_logic.h"
|
||||||
|
#include "../zones/pile_zone_logic.h"
|
||||||
|
#include "../zones/table_zone_logic.h"
|
||||||
#include "../zones/view_zone_logic.h"
|
#include "../zones/view_zone_logic.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_querier.h"
|
||||||
|
#include "libcockatrice/card/printing/exact_card.h"
|
||||||
|
#include "libcockatrice/card/printing/printing_info.h"
|
||||||
|
#include "libcockatrice/card/relation/card_relation_type.h"
|
||||||
|
#include "libcockatrice/deck_list/deck_list.h"
|
||||||
|
#include "libcockatrice/filters/filter_string.h"
|
||||||
|
#include "libcockatrice/protocol/pb/card_attributes.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_commands.pb.h"
|
||||||
|
#include "libcockatrice/settings/cards_display_settings.h"
|
||||||
|
#include "player_info.h"
|
||||||
|
#include "player_logic.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QChar>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QFlags>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMapIterator>
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QPointF>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVariantList>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <google/protobuf/stubs/port.h>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/card/relation/card_relation.h>
|
#include <libcockatrice/card/relation/card_relation.h>
|
||||||
#include <libcockatrice/protocol/pb/command_attach_card.pb.h>
|
#include <libcockatrice/protocol/pb/command_attach_card.pb.h>
|
||||||
|
|
@ -26,13 +66,16 @@
|
||||||
#include <libcockatrice/protocol/pb/command_set_card_counter.pb.h>
|
#include <libcockatrice/protocol/pb/command_set_card_counter.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/command_shuffle.pb.h>
|
#include <libcockatrice/protocol/pb/command_shuffle.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/command_undo_draw.pb.h>
|
#include <libcockatrice/protocol/pb/command_undo_draw.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
|
|
||||||
#include <libcockatrice/settings/card_override_settings.h>
|
#include <libcockatrice/settings/card_override_settings.h>
|
||||||
#include <libcockatrice/settings/interface_settings.h>
|
#include <libcockatrice/settings/interface_settings.h>
|
||||||
#include <libcockatrice/utility/clamped_arithmetic.h>
|
#include <libcockatrice/utility/clamped_arithmetic.h>
|
||||||
#include <libcockatrice/utility/counter_limits.h>
|
#include <libcockatrice/utility/counter_limits.h>
|
||||||
#include <libcockatrice/utility/expression.h>
|
#include <libcockatrice/utility/expression.h>
|
||||||
#include <libcockatrice/utility/zone_names.h>
|
#include <libcockatrice/utility/zone_names.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
#include <qnumeric.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// milliseconds in between triggers of the move top cards until action
|
// milliseconds in between triggers of the move top cards until action
|
||||||
static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
|
static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,25 @@
|
||||||
#ifndef COCKATRICE_PLAYER_ACTIONS_H
|
#ifndef COCKATRICE_PLAYER_ACTIONS_H
|
||||||
#define COCKATRICE_PLAYER_ACTIONS_H
|
#define COCKATRICE_PLAYER_ACTIONS_H
|
||||||
|
|
||||||
#include "../../game_graphics/board/card_item.h"
|
#include "../../game_graphics/board/card_item.h" // IWYU pragma: keep - moc instantiates the metatype for QList<CardItem *>, which Qt 6.4 needs complete
|
||||||
#include "../../game_graphics/dialogs/dlg_create_token.h"
|
#include "../../game_graphics/dialogs/dlg_create_token.h"
|
||||||
#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h"
|
#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h"
|
||||||
#include "../../game_graphics/player/card_menu_action_type.h"
|
#include "../../game_graphics/player/card_menu_action_type.h"
|
||||||
#include "event_processing_options.h"
|
#include "../board/card_list.h"
|
||||||
#include "player_logic.h"
|
#include "libcockatrice/card/card_info.h"
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
#include <libcockatrice/card/relation/card_relation_type.h>
|
#include <libcockatrice/card/relation/card_relation_type.h>
|
||||||
#include <libcockatrice/filters/filter_string.h>
|
#include <libcockatrice/filters/filter_string.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class CardItem;
|
||||||
|
class CardRelation;
|
||||||
|
class QAction;
|
||||||
|
class QTimer;
|
||||||
|
template <typename T> class QList;
|
||||||
|
|
||||||
namespace google
|
namespace google
|
||||||
{
|
{
|
||||||
|
|
@ -29,9 +37,9 @@ class Message;
|
||||||
} // namespace google
|
} // namespace google
|
||||||
|
|
||||||
class Command_MoveCard;
|
class Command_MoveCard;
|
||||||
class GameEventContext;
|
|
||||||
class PendingCommand;
|
class PendingCommand;
|
||||||
class PlayerLogic;
|
class PlayerLogic;
|
||||||
|
|
||||||
class PlayerActions : public QObject
|
class PlayerActions : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,32 @@
|
||||||
#include "player_event_handler.h"
|
#include "player_event_handler.h"
|
||||||
|
|
||||||
#include "../../game_graphics/board/arrow_item.h"
|
|
||||||
#include "../../game_graphics/board/card_item.h"
|
#include "../../game_graphics/board/card_item.h"
|
||||||
#include "../../game_graphics/zones/view_zone.h"
|
#include "../../game_graphics/zones/view_zone.h"
|
||||||
#include "../../interface/widgets/tabs/tab_game.h"
|
#include "../abstract_game.h"
|
||||||
#include "../board/arrow_data.h"
|
#include "../board/arrow_data.h"
|
||||||
#include "../board/card_list.h"
|
#include "../board/card_list.h"
|
||||||
|
#include "../board/counter_state.h"
|
||||||
|
#include "../zones/card_zone_logic.h"
|
||||||
|
#include "../zones/hand_zone_logic.h"
|
||||||
|
#include "../zones/pile_zone_logic.h"
|
||||||
|
#include "libcockatrice/card/card_info.h"
|
||||||
|
#include "libcockatrice/card/printing/exact_card.h"
|
||||||
|
#include "libcockatrice/protocol/pb/card_attributes.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_event.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/game_event_context.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_card.pb.h"
|
||||||
|
#include "libcockatrice/utility/card_ref.h"
|
||||||
#include "player_actions.h"
|
#include "player_actions.h"
|
||||||
|
#include "player_info.h"
|
||||||
#include "player_logic.h"
|
#include "player_logic.h"
|
||||||
|
#include "player_manager.h"
|
||||||
|
|
||||||
#include <libcockatrice/protocol/pb/command_set_card_attr.pb.h>
|
#include <QDebug>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <algorithm>
|
||||||
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
|
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/context_undo_draw.pb.h>
|
#include <libcockatrice/protocol/pb/context_undo_draw.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/event_attach_card.pb.h>
|
#include <libcockatrice/protocol/pb/event_attach_card.pb.h>
|
||||||
|
|
@ -32,8 +49,9 @@
|
||||||
#include <libcockatrice/protocol/pb/event_set_card_counter.pb.h>
|
#include <libcockatrice/protocol/pb/event_set_card_counter.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/event_set_counter.pb.h>
|
#include <libcockatrice/protocol/pb/event_set_counter.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/event_shuffle.pb.h>
|
#include <libcockatrice/protocol/pb/event_shuffle.pb.h>
|
||||||
#include <libcockatrice/utility/color.h>
|
|
||||||
#include <libcockatrice/utility/zone_names.h>
|
#include <libcockatrice/utility/zone_names.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player)
|
PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,14 @@
|
||||||
#include "event_processing_options.h"
|
#include "event_processing_options.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <libcockatrice/protocol/pb/card_attributes.pb.h>
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/game_event.pb.h>
|
#include <libcockatrice/protocol/pb/game_event.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/game_event_context.pb.h>
|
#include <qtmetamacros.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
class CardItem;
|
class CardItem;
|
||||||
class CardZoneLogic;
|
class CardZoneLogic;
|
||||||
class PlayerLogic;
|
class PlayerLogic;
|
||||||
|
|
||||||
class Event_AttachCard;
|
class Event_AttachCard;
|
||||||
class Event_ChangeZoneProperties;
|
class Event_ChangeZoneProperties;
|
||||||
class Event_CreateArrow;
|
class Event_CreateArrow;
|
||||||
|
|
@ -50,6 +50,9 @@ class Event_SetCardCounter;
|
||||||
class Event_SetCounter;
|
class Event_SetCounter;
|
||||||
class Event_Shuffle;
|
class Event_Shuffle;
|
||||||
class Event_GameLogNotice;
|
class Event_GameLogNotice;
|
||||||
|
class GameEventContext;
|
||||||
|
enum CardAttribute : int;
|
||||||
|
template <typename T> class QList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class PlayerEventHandler
|
* @class PlayerEventHandler
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "player_info.h"
|
#include "player_info.h"
|
||||||
|
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_user.pb.h"
|
||||||
|
|
||||||
PlayerInfo::PlayerInfo(const ServerInfo_User &info, int _id, bool _local, bool _judge)
|
PlayerInfo::PlayerInfo(const ServerInfo_User &info, int _id, bool _local, bool _judge)
|
||||||
: id(_id), local(_local), judge(_judge)
|
: id(_id), local(_local), judge(_judge)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
#ifndef COCKATRICE_PLAYER_INFO_H
|
#ifndef COCKATRICE_PLAYER_INFO_H
|
||||||
#define COCKATRICE_PLAYER_INFO_H
|
#define COCKATRICE_PLAYER_INFO_H
|
||||||
|
|
||||||
#include "../../game_graphics/player/player_target.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class PlayerInfo : public QObject
|
class PlayerInfo : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,37 @@
|
||||||
#include "player_logic.h"
|
#include "player_logic.h"
|
||||||
|
|
||||||
#include "../../game_graphics/board/arrow_item.h"
|
|
||||||
#include "../../game_graphics/board/card_item.h"
|
#include "../../game_graphics/board/card_item.h"
|
||||||
#include "../../game_graphics/board/counter_general.h"
|
#include "../abstract_game.h"
|
||||||
#include "../../game_graphics/game_scene.h"
|
#include "../board/arrow_data.h"
|
||||||
#include "../../game_graphics/player/player_target.h"
|
#include "../board/counter_state.h"
|
||||||
#include "../../game_graphics/zones/hand_zone.h"
|
#include "../game_meta_info.h"
|
||||||
#include "../../game_graphics/zones/pile_zone.h"
|
#include "../zones/hand_zone_logic.h"
|
||||||
#include "../../game_graphics/zones/stack_zone.h"
|
#include "../zones/pile_zone_logic.h"
|
||||||
#include "../../game_graphics/zones/table_zone.h"
|
#include "../zones/stack_zone_logic.h"
|
||||||
#include "../../interface/theme_manager.h"
|
#include "../zones/table_zone_logic.h"
|
||||||
#include "../../interface/widgets/tabs/tab_game.h"
|
#include "libcockatrice/protocol/pb/serverinfo_card.pb.h"
|
||||||
#include "../board/card_list.h"
|
#include "libcockatrice/protocol/pb/serverinfo_counter.pb.h"
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_playerproperties.pb.h"
|
||||||
|
#include "libcockatrice/utility/zone_names.h"
|
||||||
#include "player_actions.h"
|
#include "player_actions.h"
|
||||||
|
#include "player_event_handler.h"
|
||||||
|
#include "player_info.h"
|
||||||
|
#include "player_manager.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMenu>
|
#include <QMapIterator>
|
||||||
#include <QMetaType>
|
#include <QMessageLogger>
|
||||||
#include <QPainter>
|
#include <QMutableMapIterator>
|
||||||
#include <QtConcurrent>
|
#include <QSet>
|
||||||
#include <libcockatrice/protocol/pb/command_attach_card.pb.h>
|
#include <QSharedPointer>
|
||||||
#include <libcockatrice/protocol/pb/command_set_card_counter.pb.h>
|
#include <QtGlobal>
|
||||||
#include <libcockatrice/protocol/pb/event_create_arrow.pb.h>
|
|
||||||
#include <libcockatrice/protocol/pb/event_create_counter.pb.h>
|
|
||||||
#include <libcockatrice/protocol/pb/event_draw_cards.pb.h>
|
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_zone.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_zone.pb.h>
|
||||||
|
#include <libcockatrice/utility/card_ref.h>
|
||||||
#include <libcockatrice/utility/color.h>
|
#include <libcockatrice/utility/color.h>
|
||||||
|
#include <qalgorithms.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent)
|
PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent)
|
||||||
: QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)),
|
: QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)),
|
||||||
|
|
|
||||||
|
|
@ -7,57 +7,48 @@
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
#define PLAYER_H
|
#define PLAYER_H
|
||||||
|
|
||||||
#include "../../game_graphics/player/player_area.h"
|
#include "../zones/card_zone_logic.h"
|
||||||
#include "../../interface/widgets/menus/tearoff_menu.h"
|
|
||||||
#include "../board/arrow_data.h"
|
|
||||||
#include "../interface/deck_loader/loaded_deck.h"
|
|
||||||
#include "../zones/hand_zone_logic.h"
|
#include "../zones/hand_zone_logic.h"
|
||||||
#include "../zones/pile_zone_logic.h"
|
#include "../zones/pile_zone_logic.h"
|
||||||
#include "../zones/stack_zone_logic.h"
|
#include "../zones/stack_zone_logic.h"
|
||||||
#include "../zones/table_zone_logic.h"
|
#include "../zones/table_zone_logic.h"
|
||||||
#include "player_event_handler.h"
|
#include "libcockatrice/deck_list/deck_list.h"
|
||||||
#include "player_info.h"
|
#include "libcockatrice/utility/card_ref.h"
|
||||||
#include "player_manager.h"
|
#include "libcockatrice/utility/playmat_params.h"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QTimer>
|
#include <QObject>
|
||||||
#include <libcockatrice/filters/filter_string.h>
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/card_attributes.pb.h>
|
|
||||||
#include <libcockatrice/protocol/pb/game_event.pb.h>
|
|
||||||
#include <libcockatrice/utility/zone_names.h>
|
#include <libcockatrice/utility/zone_names.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
// IWYU pragma: keep
|
||||||
|
// ServerInfo_Card appears inside QList<...> in signal and slot
|
||||||
|
// signatures, which the moc-generated code needs to be complete.
|
||||||
|
#include <libcockatrice/protocol/pb/serverinfo_card.pb.h>
|
||||||
|
|
||||||
|
class CardItem;
|
||||||
|
class CounterState;
|
||||||
|
class QWidget;
|
||||||
|
class ServerInfo_PlayerProperties;
|
||||||
|
struct ArrowData;
|
||||||
|
struct LoadedDeck;
|
||||||
|
template <class T> class QSharedPointer;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(PlayerLog, "player");
|
inline Q_LOGGING_CATEGORY(PlayerLog, "player");
|
||||||
|
|
||||||
namespace google
|
|
||||||
{
|
|
||||||
namespace protobuf
|
|
||||||
{
|
|
||||||
class Message;
|
|
||||||
}
|
|
||||||
} // namespace google
|
|
||||||
class AbstractCardItem;
|
class AbstractCardItem;
|
||||||
class AbstractGame;
|
class AbstractGame;
|
||||||
class ArrowItem;
|
|
||||||
class ArrowTarget;
|
|
||||||
class CardDatabase;
|
|
||||||
class CardZone;
|
|
||||||
class CommandContainer;
|
|
||||||
class GameCommand;
|
|
||||||
class GameEvent;
|
|
||||||
class PlayerInfo;
|
class PlayerInfo;
|
||||||
class PlayerEventHandler;
|
class PlayerEventHandler;
|
||||||
class PlayerActions;
|
class PlayerActions;
|
||||||
class PlayerMenu;
|
|
||||||
class QAction;
|
|
||||||
class QMenu;
|
|
||||||
class ServerInfo_Arrow;
|
|
||||||
class ServerInfo_Card;
|
class ServerInfo_Card;
|
||||||
class ServerInfo_Counter;
|
class ServerInfo_Counter;
|
||||||
class ServerInfo_Player;
|
class ServerInfo_Player;
|
||||||
class ServerInfo_User;
|
class ServerInfo_User;
|
||||||
class TabGame;
|
|
||||||
|
|
||||||
const int MAX_TOKENS_PER_DIALOG = 99;
|
const int MAX_TOKENS_PER_DIALOG = 99;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
#include "player_manager.h"
|
#include "player_manager.h"
|
||||||
|
|
||||||
#include "../abstract_game.h"
|
#include "../abstract_game.h"
|
||||||
|
#include "../game_state.h"
|
||||||
|
#include "player_info.h"
|
||||||
#include "player_logic.h"
|
#include "player_logic.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QMapIterator>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
PlayerManager::PlayerManager(AbstractGame *_game,
|
PlayerManager::PlayerManager(AbstractGame *_game,
|
||||||
int _localPlayerId,
|
int _localPlayerId,
|
||||||
bool _localPlayerIsJudge,
|
bool _localPlayerIsJudge,
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,17 @@
|
||||||
#ifndef COCKATRICE_PLAYER_MANAGER_H
|
#ifndef COCKATRICE_PLAYER_MANAGER_H
|
||||||
#define COCKATRICE_PLAYER_MANAGER_H
|
#define COCKATRICE_PLAYER_MANAGER_H
|
||||||
|
|
||||||
|
#include "libcockatrice/protocol/pb/serverinfo_user.pb.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_playerproperties.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_playerproperties.pb.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
class AbstractGame;
|
class AbstractGame;
|
||||||
class PlayerLogic;
|
class PlayerLogic;
|
||||||
|
|
||||||
class PlayerManager : public QObject
|
class PlayerManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
#include "replay.h"
|
#include "replay.h"
|
||||||
|
|
||||||
#include "../interface/widgets/tabs/tab_game.h"
|
#include "game_meta_info.h"
|
||||||
|
#include "game_state.h"
|
||||||
|
#include "player/player_manager.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class GameReplay;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
Replay::Replay(QObject *_parent, const GameReplay *_replay, bool isLocalGame) : AbstractGame(_parent)
|
Replay::Replay(QObject *_parent, const GameReplay *_replay, bool isLocalGame) : AbstractGame(_parent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
#include "abstract_game.h"
|
#include "abstract_game.h"
|
||||||
|
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class GameReplay;
|
||||||
|
class QObject;
|
||||||
|
|
||||||
class Replay : public AbstractGame
|
class Replay : public AbstractGame
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,25 @@
|
||||||
#include "card_zone_logic.h"
|
#include "card_zone_logic.h"
|
||||||
|
|
||||||
|
#include "../../client/translation.h"
|
||||||
#include "../../game_graphics/board/card_item.h"
|
#include "../../game_graphics/board/card_item.h"
|
||||||
|
#include "../../game_graphics/zones/card_zone.h"
|
||||||
#include "../../game_graphics/zones/view_zone.h"
|
#include "../../game_graphics/zones/view_zone.h"
|
||||||
|
#include "../board/card_list.h"
|
||||||
#include "../player/player_actions.h"
|
#include "../player/player_actions.h"
|
||||||
|
#include "../player/player_info.h"
|
||||||
#include "../player/player_logic.h"
|
#include "../player/player_logic.h"
|
||||||
|
#include "libcockatrice/card/database/card_database.h"
|
||||||
#include "view_zone_logic.h"
|
#include "view_zone_logic.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QMessageLogger>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QVariant>
|
||||||
#include <libcockatrice/card/database/card_database_manager.h>
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
#include <libcockatrice/protocol/pb/command_move_card.pb.h>
|
#include <libcockatrice/protocol/pb/command_move_card.pb.h>
|
||||||
#include <libcockatrice/utility/zone_names.h>
|
#include <libcockatrice/utility/zone_names.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param _player the player that the zone belongs to
|
* @param _player the player that the zone belongs to
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,18 @@
|
||||||
#include "../../client/translation.h"
|
#include "../../client/translation.h"
|
||||||
#include "../board/card_list.h"
|
#include "../board/card_list.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
class CardItem;
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(CardZoneLogicLog, "card_zone_logic");
|
inline Q_LOGGING_CATEGORY(CardZoneLogicLog, "card_zone_logic");
|
||||||
|
|
||||||
class PlayerLogic;
|
class PlayerLogic;
|
||||||
class ZoneViewZone;
|
class ZoneViewZone;
|
||||||
class QMenu;
|
|
||||||
class QAction;
|
|
||||||
class QPainter;
|
|
||||||
class CardDragItem;
|
|
||||||
|
|
||||||
class CardZoneLogic : public QObject
|
class CardZoneLogic : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue